package de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.uncertain; /* This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures Copyright (C) 2015 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ import de.lmu.ifi.dbs.elki.data.Clustering; import de.lmu.ifi.dbs.elki.data.NumberVector; import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation; import de.lmu.ifi.dbs.elki.data.type.TypeUtil; import de.lmu.ifi.dbs.elki.database.ids.DBIDIter; import de.lmu.ifi.dbs.elki.database.relation.Relation; import de.lmu.ifi.dbs.elki.database.relation.RelationUtil; import de.lmu.ifi.dbs.elki.result.Result; import de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy.Hierarchy; import de.lmu.ifi.dbs.elki.utilities.exceptions.ObjectNotFoundException; import de.lmu.ifi.dbs.elki.visualization.VisualizationTask; import de.lmu.ifi.dbs.elki.visualization.VisualizationTree; import de.lmu.ifi.dbs.elki.visualization.VisualizerContext; import de.lmu.ifi.dbs.elki.visualization.gui.VisualizationPlot; import de.lmu.ifi.dbs.elki.visualization.projections.Projection; import de.lmu.ifi.dbs.elki.visualization.projector.ScatterPlotProjector; import de.lmu.ifi.dbs.elki.visualization.style.ClusterStylingPolicy; import de.lmu.ifi.dbs.elki.visualization.style.StyleLibrary; import de.lmu.ifi.dbs.elki.visualization.style.StylingPolicy; import de.lmu.ifi.dbs.elki.visualization.style.marker.MarkerLibrary; import de.lmu.ifi.dbs.elki.visualization.visualizers.AbstractVisFactory; import de.lmu.ifi.dbs.elki.visualization.visualizers.Visualization; import de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.AbstractScatterplotVisualization; /** * Visualize a single derived sample from an uncertain database. * * Note: this is currently a hack. Our projection only applies to vector field * relations currently, and this visualizer activates if such a relation (e.g. a * sample, or the center of mass) has a parent relation of type UncertainObject. * But it serves the purpose. * * @author Erich Schubert * @since 0.5.0 * * @apiviz.stereotype factory * @apiviz.uses Instance oneway - - «create» */ public class UncertainInstancesVisualization extends AbstractVisFactory { /** * A short name characterizing this Visualizer. */ private static final String NAME = "Uncertain Instance"; /** * Constructor. */ public UncertainInstancesVisualization() { super(); } @Override public Visualization makeVisualization(VisualizationTask task, VisualizationPlot plot, double width, double height, Projection proj) { return new Instance(task, plot, width, height, proj); } @Override public void processNewResult(VisualizerContext context, Object start) { Hierarchy.Iter> it = VisualizationTree.filter(context, start, ScatterPlotProjector.class); for(; it.valid(); it.advance()) { // Find a scatter plot visualizing uncertain objects: ScatterPlotProjector p = it.get(); Relation r = p.getRelation(); if(!TypeUtil.UNCERTAIN_OBJECT_FIELD.isAssignableFromType(r.getDataTypeInformation())) { continue; } final VisualizationTask task = new VisualizationTask(NAME, context, p, r, this); task.level = VisualizationTask.LEVEL_DATA; task.addUpdateFlags(VisualizationTask.ON_DATA | VisualizationTask.ON_SAMPLE | VisualizationTask.ON_STYLEPOLICY); context.addVis(p, task); continue; } } /** * Instance. * * @author Erich Schubert * * @apiviz.uses StylingPolicy */ public class Instance extends AbstractScatterplotVisualization { /** * CSS class for uncertain bounding boxes. */ public static final String CSS_CLASS = "uncertain-instances"; /** * Constructor. * * @param task Visualization task * @param plot Plot to draw to * @param width Embedding width * @param height Embedding height * @param proj Projection */ public Instance(VisualizationTask task, VisualizationPlot plot, double width, double height, Projection proj) { super(task, plot, width, height, proj); addListeners(); } @Override public void fullRedraw() { setupCanvas(); final StyleLibrary style = context.getStyleLibrary(); final StylingPolicy spol = context.getStylingPolicy(); final double size = style.getSize(StyleLibrary.MARKERPLOT); final MarkerLibrary ml = style.markers(); // Only visualize cluster-based policies if(!(spol instanceof ClusterStylingPolicy)) { return; } ClusterStylingPolicy cspol = (ClusterStylingPolicy) spol; Clustering c = cspol.getClustering(); // If this is a sample from the uncertain database, it must have a parent // relation containing vectors, which is a child to the uncertain // database. Hierarchy.Iter it = context.getHierarchy().iterAncestors(c); Relation srel = null; boolean isChild = false; for(; it.valid(); it.advance()) { Result r = it.get(); if(r == this.rel) { isChild = true; } else if(r instanceof Relation) { final SimpleTypeInformation type = ((Relation) r).getDataTypeInformation(); if(TypeUtil.NUMBER_VECTOR_FIELD.isAssignableFromType(type)) { @SuppressWarnings("unchecked") Relation vr = (Relation) r; int dim = RelationUtil.dimensionality(vr); if(dim == RelationUtil.dimensionality(this.rel)) { srel = vr; } } } if(isChild && srel != null) { break; } } // Nothing found, probably in a different subtree. if(!isChild || srel == null) { return; } for(int cnum = cspol.getMinStyle(); cnum < cspol.getMaxStyle(); cnum++) { for(DBIDIter iter = cspol.iterateClass(cnum); iter.valid(); iter.advance()) { if(!sample.getSample().contains(iter)) { continue; // TODO: can we test more efficiently than this? } try { final NumberVector vec = srel.get(iter); double[] v = proj.fastProjectDataToRenderSpace(vec); if(v[0] != v[0] || v[1] != v[1]) { continue; // NaN! } ml.useMarker(svgp, layer, v[0], v[1], cnum, size); } catch(ObjectNotFoundException e) { // ignore. } } } } } }