summaryrefslogtreecommitdiff
path: root/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/KeyVisualization.java
diff options
context:
space:
mode:
authorAndrej Shadura <andrewsh@debian.org>2019-03-09 22:30:34 +0000
committerAndrej Shadura <andrewsh@debian.org>2019-03-09 22:30:34 +0000
commitb7b404fd7a726774d442562d11659d7b5368cdb9 (patch)
tree6f510ddbf80c1a51e333f80411541565ac71c9e9 /src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/KeyVisualization.java
parentace5fa7f57d49756c0e1b111a30f3b6a9436c1cb (diff)
Import Upstream version 0.5.5
Diffstat (limited to 'src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/KeyVisualization.java')
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/KeyVisualization.java249
1 files changed, 142 insertions, 107 deletions
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/KeyVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/KeyVisualization.java
index 62a4fb5c..f21e4df6 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/KeyVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/KeyVisualization.java
@@ -52,147 +52,182 @@ import de.lmu.ifi.dbs.elki.visualization.visualizers.Visualization;
/**
* Visualizer, displaying the key for a clustering.
- *
+ *
* @author Erich Schubert
*
- * @apiviz.has Clustering oneway - - visualizes
+ * @apiviz.stereotype factory
+ * @apiviz.uses Instance oneway - - «create»
*/
-public class KeyVisualization extends AbstractVisualization {
+public class KeyVisualization extends AbstractVisFactory {
/**
* Name for this visualizer.
*/
private static final String NAME = "Cluster Key";
- /**
- * Clustering to display
- */
- private Clustering<Model> clustering;
+ @Override
+ public void processNewResult(HierarchicalResult baseResult, Result newResult) {
+ // Find clusterings we can visualize:
+ Collection<Clustering<?>> clusterings = ResultUtil.filterResults(newResult, Clustering.class);
+ for(Clustering<?> c : clusterings) {
+ final int numc = c.getAllClusters().size();
+ if(numc > 0) {
+ // FIXME: compute from labels?
+ final double maxwidth = 10.;
+ final VisualizationTask task = new VisualizationTask(NAME, c, null, this);
+ final int cols = getPreferredColumns(1.0, 1.0, numc, maxwidth);
+ final int rows = (int) Math.ceil(numc / (double) cols);
+ final double div = Math.max(2. + rows, cols * maxwidth);
+ task.width = cols * maxwidth / div;
+ task.height = (2. + rows) / div;
+ task.level = VisualizationTask.LEVEL_STATIC;
+ task.nodetail = true;
+ baseResult.getHierarchy().add(c, task);
+ }
+ }
+ }
/**
- * Constructor.
+ * Compute the preferred number of columns.
*
- * @param task Visualization task
+ * @param width Target width
+ * @param height Target height
+ * @param numc Number of clusters
+ * @param maxwidth Max width of entries
+ * @return Preferred number of columns
*/
- public KeyVisualization(VisualizationTask task) {
- super(task);
- this.clustering = task.getResult();
- context.addResultListener(this);
+ public static int getPreferredColumns(double width, double height, int numc, double maxwidth) {
+ // Maximum width (compared to height) of labels - guess.
+ // FIXME: do we really need to do this three-step computation?
+ // Number of rows we'd use in a squared layout:
+ final double rows = Math.ceil(Math.pow(numc * maxwidth, height / (width + height)));
+ // Given this number of rows (plus two for header), use this many columns:
+ return (int) Math.ceil(numc / (rows + 2));
}
@Override
- public void destroy() {
- context.removeResultListener(this);
- super.destroy();
+ public Visualization makeVisualization(VisualizationTask task) {
+ return new Instance(task);
}
@Override
- public void resultChanged(Result current) {
- super.resultChanged(current);
- if(current == context.getStyleResult()) {
- incrementalRedraw();
- }
+ public boolean allowThumbnails(VisualizationTask task) {
+ return false;
}
- @Override
- protected void redraw() {
- SVGPlot svgp = task.getPlot();
- final List<Cluster<Model>> allcs = clustering.getAllClusters();
-
- StyleLibrary style = context.getStyleLibrary();
- MarkerLibrary ml = style.markers();
- layer = svgp.svgElement(SVGConstants.SVG_G_TAG);
-
- // Add a label for the clustering.
- {
- Element label = svgp.svgText(0.1, 0.7, clustering.getLongName());
- label.setAttribute(SVGConstants.SVG_STYLE_ATTRIBUTE, "font-size: 0.4; fill: "+style.getTextColor(StyleLibrary.DEFAULT));
- layer.appendChild(label);
+ /**
+ * Instance
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has Clustering oneway - - visualizes
+ */
+ public class Instance extends AbstractVisualization {
+ /**
+ * Clustering to display
+ */
+ private Clustering<Model> clustering;
+
+ /**
+ * Constructor.
+ *
+ * @param task Visualization task
+ */
+ public Instance(VisualizationTask task) {
+ super(task);
+ this.clustering = task.getResult();
+ context.addResultListener(this);
}
- // TODO: multi-column layout!
- int i = 0;
- for(Cluster<Model> c : allcs) {
- ml.useMarker(svgp, layer, 0.3, i + 1.5, i, 0.3);
- Element label = svgp.svgText(0.7, i + 1.7, c.getNameAutomatic());
- label.setAttribute(SVGConstants.SVG_STYLE_ATTRIBUTE, "font-size: 0.6; fill: "+style.getTextColor(StyleLibrary.DEFAULT));
- layer.appendChild(label);
- i++;
+ @Override
+ public void destroy() {
+ context.removeResultListener(this);
+ super.destroy();
}
- // Add a button to set style policy
- {
- StylingPolicy sp = context.getStyleResult().getStylingPolicy();
- if(sp instanceof ClusterStylingPolicy && ((ClusterStylingPolicy) sp).getClustering() == clustering) {
- // Don't show the button when active. May confuse people more than the disappearing button
-
- // SVGButton button = new SVGButton(.1, i + 1.1, 3.8, .7, .2);
- // button.setTitle("Active style", "darkgray");
- // layer.appendChild(button.render(svgp));
- }
- else {
- SVGButton button = new SVGButton(.1, i + 1.1, 3.8, .7, .2);
- button.setTitle("Set style", "black");
- Element elem = button.render(svgp);
- // Attach listener
- EventTarget etr = (EventTarget) elem;
- etr.addEventListener(SVGConstants.SVG_CLICK_EVENT_TYPE, new EventListener() {
- @Override
- public void handleEvent(Event evt) {
- setStylePolicy();
- }
- }, false);
- layer.appendChild(elem);
+ @Override
+ public void resultChanged(Result current) {
+ super.resultChanged(current);
+ if(current == context.getStyleResult()) {
+ incrementalRedraw();
}
}
- int rows = i + 2;
- int cols = Math.max(6, (int) (rows * task.getHeight() / task.getWidth()));
- final double margin = style.getSize(StyleLibrary.MARGIN);
- final String transform = SVGUtil.makeMarginTransform(task.getWidth(), task.getHeight(), cols, rows, margin / StyleLibrary.SCALE);
- SVGUtil.setAtt(layer, SVGConstants.SVG_TRANSFORM_ATTRIBUTE, transform);
- }
+ @Override
+ protected void redraw() {
+ SVGPlot svgp = task.getPlot();
+ StyleLibrary style = context.getStyleResult().getStyleLibrary();
+ MarkerLibrary ml = style.markers();
+
+ // Maximum width (compared to height) of labels - guess.
+ // FIXME: compute from labels?
+ final double maxwidth = 10.;
+
+ final List<Cluster<Model>> allcs = clustering.getAllClusters();
+ final int numc = allcs.size();
+ final int cols = getPreferredColumns(task.getWidth(), task.getHeight(), numc, maxwidth);
+ final int rows = 2 + (int) Math.ceil(numc / (double) cols);
+ // We use a coordinate system based on rows, so columns are at c*maxwidth
+
+ layer = svgp.svgElement(SVGConstants.SVG_G_TAG);
+ // Add a label for the clustering.
+ {
+ Element label = svgp.svgText(0.1, 0.7, clustering.getLongName());
+ label.setAttribute(SVGConstants.SVG_STYLE_ATTRIBUTE, "font-size: 0.4; fill: " + style.getTextColor(StyleLibrary.DEFAULT));
+ layer.appendChild(label);
+ }
- /**
- * Trigger a style change.
- */
- protected void setStylePolicy() {
- context.getStyleResult().setStylingPolicy(new ClusterStylingPolicy(clustering, context.getStyleLibrary()));
- context.getHierarchy().resultChanged(context.getStyleResult());
- }
+ int i = 0;
+ for(Cluster<Model> c : allcs) {
+ final int col = i / rows;
+ final int row = i % rows;
+ ml.useMarker(svgp, layer, 0.3 + maxwidth * col, row + 1.5, i, 0.3);
+ Element label = svgp.svgText(0.7 + maxwidth * col, row + 1.7, c.getNameAutomatic());
+ label.setAttribute(SVGConstants.SVG_STYLE_ATTRIBUTE, "font-size: 0.6; fill: " + style.getTextColor(StyleLibrary.DEFAULT));
+ layer.appendChild(label);
+ i++;
+ }
- /**
- * Visualization factory
- *
- * @author Erich Schubert
- *
- * @apiviz.stereotype factory
- * @apiviz.uses KeyVisualization oneway - - «create»
- */
- public static class Factory extends AbstractVisFactory {
- @Override
- public void processNewResult(HierarchicalResult baseResult, Result newResult) {
- // Find clusterings we can visualize:
- Collection<Clustering<?>> clusterings = ResultUtil.filterResults(newResult, Clustering.class);
- for (Clustering<?> c : clusterings) {
- if(c.getAllClusters().size() > 0) {
- final VisualizationTask task = new VisualizationTask(NAME, c, null, this);
- task.width = 1.0;
- task.height = 1.0;
- task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_STATIC);
- task.put(VisualizationTask.META_NODETAIL, true);
- baseResult.getHierarchy().add(c, task);
+ // Add a button to set style policy
+ {
+ StylingPolicy sp = context.getStyleResult().getStylingPolicy();
+ if(sp instanceof ClusterStylingPolicy && ((ClusterStylingPolicy) sp).getClustering() == clustering) {
+ // Don't show the button when active. May confuse people more than the
+ // disappearing button?
+
+ // SVGButton button = new SVGButton(.1, rows + 1.1, 3.8, .7, .2);
+ // button.setTitle("Active style", "darkgray");
+ // layer.appendChild(button.render(svgp));
+ }
+ else {
+ SVGButton button = new SVGButton(.1, rows + 1.1, 3.8, .7, .2);
+ button.setTitle("Set style", "black");
+ Element elem = button.render(svgp);
+ // Attach listener
+ EventTarget etr = (EventTarget) elem;
+ etr.addEventListener(SVGConstants.SVG_CLICK_EVENT_TYPE, new EventListener() {
+ @Override
+ public void handleEvent(Event evt) {
+ setStylePolicy();
+ }
+ }, false);
+ layer.appendChild(elem);
}
}
- }
- @Override
- public Visualization makeVisualization(VisualizationTask task) {
- return new KeyVisualization(task);
+ // int rows = i + 2;
+ // int cols = Math.max(6, (int) (rows * task.getHeight() /
+ // task.getWidth()));
+ final double margin = style.getSize(StyleLibrary.MARGIN);
+ final String transform = SVGUtil.makeMarginTransform(task.getWidth(), task.getHeight(), cols * maxwidth, rows, margin / StyleLibrary.SCALE);
+ SVGUtil.setAtt(layer, SVGConstants.SVG_TRANSFORM_ATTRIBUTE, transform);
}
- @Override
- public boolean allowThumbnails(VisualizationTask task) {
- return false;
+ /**
+ * Trigger a style change.
+ */
+ protected void setStylePolicy() {
+ context.getStyleResult().setStylingPolicy(new ClusterStylingPolicy(clustering, context.getStyleResult().getStyleLibrary()));
+ context.getHierarchy().resultChanged(context.getStyleResult());
}
}
} \ No newline at end of file