diff options
author | Erich Schubert <erich@debian.org> | 2011-09-24 12:24:37 +0200 |
---|---|---|
committer | Andrej Shadura <andrewsh@debian.org> | 2019-03-09 22:30:30 +0000 |
commit | 3a6ca942c89382b33bbc95ad772e4def12109da1 (patch) | |
tree | 8055db779223e3cd7f4738d9ae8e1b92c04935a8 | |
parent | 31b594b746419717396c9daa8bf1863890739d82 (diff) | |
parent | 21d13de881e43d4ab86369af4c5fc744b342b3f9 (diff) |
Import Debian changes 0.4.0-1
elki (0.4.0-1) unstable; urgency=low
* New upstream release. (0.4.0 final)
* Try to make lintian happier with the DEP-5 copyright format
* Fixes a bug where various methods would require a classlabel that
previously would fall-back to any kind of label available.
133 files changed, 2153 insertions, 1313 deletions
diff --git a/debian/changelog b/debian/changelog index 77acb45e..1728b88f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,12 @@ +elki (0.4.0-1) unstable; urgency=low + + * New upstream release. (0.4.0 final) + * Try to make lintian happier with the DEP-5 copyright format + * Fixes a bug where various methods would require a classlabel that + previously would fall-back to any kind of label available. + + -- Erich Schubert <erich@debian.org> Sat, 24 Sep 2011 12:24:37 +0200 + elki (0.4.0~beta2-1) unstable; urgency=low * New upstream release. diff --git a/debian/copyright b/debian/copyright index 5002be43..2f54576f 100644 --- a/debian/copyright +++ b/debian/copyright @@ -1,16 +1,16 @@ Format: http://dep.debian.net/deps/dep5 Upstream-Name: ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Source: <http://elki.dbs.ifi.lmu.de/> +Source: http://elki.dbs.ifi.lmu.de/ Files: * Copyright: 2011 Lehr- und Forschungseinheit für Datenbanksysteme, Ludwig-Maximilians-Universität München -License: AGPL-3.0+ +License: AGPL-3+ Files: debian/* Copyright: 2011 Erich Schubert <erich@debian.org> -License: GPL-3.0+ +License: AGPL-3+ -License: AGPL-3.0+ +License: AGPL-3+ ELKI: Environment for Developing KDD-Applications Supported by Index-Structures . Copyright (C) 2011 Lehr- und Forschungseinheit für Datenbanksysteme, Ludwig-Maximilians-Universität München diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/DummyAlgorithm.java b/src/de/lmu/ifi/dbs/elki/algorithm/DummyAlgorithm.java index d864f18c..e403c623 100644 --- a/src/de/lmu/ifi/dbs/elki/algorithm/DummyAlgorithm.java +++ b/src/de/lmu/ifi/dbs/elki/algorithm/DummyAlgorithm.java @@ -41,10 +41,15 @@ import de.lmu.ifi.dbs.elki.utilities.documentation.Title; /** * Dummy Algorithm, which just iterates over all points once, doing a 10NN query * each. Useful in testing e.g. index structures and as template for custom - * algorithms. + * algorithms. If you are looking for an algorithm that does <em>nothing</em>, + * you must use {@link de.lmu.ifi.dbs.elki.algorithm.NullAlgorithm + * NullAlgorithm} instead. While this algorithm doesn't produce a result, it + * still performs rather expensive operations. * * @author Erich Schubert * @param <O> Vector type + * + * @apiviz.uses KNNQuery */ @Title("Dummy Algorithm") @Description("The algorithm executes a euclidena 10NN query on all data points, and can be used in unit testing") @@ -70,13 +75,15 @@ public class DummyAlgorithm<O extends NumberVector<?, ?>> extends AbstractAlgori * @return Null result */ public Result run(Database database, Relation<O> relation) { + // Get a distance and knn query for the Euclidean distance + // Hardcoded, only use this if you only allow the eucliden distance DistanceQuery<O, DoubleDistance> distQuery = database.getDistanceQuery(relation, EuclideanDistanceFunction.STATIC); KNNQuery<O, DoubleDistance> knnQuery = database.getKNNQuery(distQuery, 10); for(DBID id : relation.iterDBIDs()) { - // Get the actual object from the database (but discard) + // Get the actual object from the database (but discard the result) relation.get(id); - // run a 10NN query for each point (but discard) + // run a 10NN query for each point (but discard the result) knnQuery.getKNNForDBID(id, 10); } return null; diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/ClusteringAlgorithm.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/ClusteringAlgorithm.java index 2f05e44b..e28dbff3 100644 --- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/ClusteringAlgorithm.java +++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/ClusteringAlgorithm.java @@ -40,8 +40,8 @@ import de.lmu.ifi.dbs.elki.database.Database; * * @author Arthur Zimek * - * @apiviz.uses Clustering - * @apiviz.uses Model + * @apiviz.has Clustering + * @apiviz.has Model * * @param <C> Clustering type */ diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/OPTICSTypeAlgorithm.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/OPTICSTypeAlgorithm.java index e8b113d7..c233963d 100644 --- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/OPTICSTypeAlgorithm.java +++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/OPTICSTypeAlgorithm.java @@ -33,7 +33,7 @@ import de.lmu.ifi.dbs.elki.result.optics.ClusterOrderResult; * * @author Erich Schubert * - * @apiviz.uses ClusterOrderResult + * @apiviz.has ClusterOrderResult * * @param <D> Distance type */ diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/package-info.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/package-info.java index 9314b725..660a7a4f 100644 --- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/package-info.java @@ -7,6 +7,8 @@ * More relaxed clustering algorithms are allowed to provide a result that is a fuzzy clustering, does not * partition the database complete or is in any other sense a relaxed clustering result. * + * @apiviz.exclude de.lmu.ifi.dbs.elki.algorithm.clustering.OPTICSXi.SteepAreaResult + * * @see de.lmu.ifi.dbs.elki.algorithm */ /* diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/ByLabelClustering.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/ByLabelClustering.java index 87c2c482..02350db3 100644 --- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/ByLabelClustering.java +++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/ByLabelClustering.java @@ -34,6 +34,7 @@ import de.lmu.ifi.dbs.elki.data.Cluster; import de.lmu.ifi.dbs.elki.data.Clustering; import de.lmu.ifi.dbs.elki.data.model.ClusterModel; import de.lmu.ifi.dbs.elki.data.model.Model; +import de.lmu.ifi.dbs.elki.data.type.NoSupportedDataTypeException; import de.lmu.ifi.dbs.elki.data.type.TypeInformation; import de.lmu.ifi.dbs.elki.data.type.TypeUtil; import de.lmu.ifi.dbs.elki.database.Database; @@ -122,12 +123,14 @@ public class ByLabelClustering extends AbstractAlgorithm<Clustering<Model>> impl @Override public Clustering<Model> run(Database database) { // Prefer a true class label - Relation<ClassLabel> relation = database.getRelation(TypeUtil.CLASSLABEL); - if(relation != null) { + try { + Relation<ClassLabel> relation = database.getRelation(TypeUtil.CLASSLABEL); return run(relation); } - // Otherwise, try any labellike. - return run(database.getRelation(getInputTypeRestriction()[0])); + catch(NoSupportedDataTypeException e) { + // Otherwise, try any labellike. + return run(database.getRelation(getInputTypeRestriction()[0])); + } } /** diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/ByLabelHierarchicalClustering.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/ByLabelHierarchicalClustering.java index 3bda8174..5b8041d7 100644 --- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/ByLabelHierarchicalClustering.java +++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/ByLabelHierarchicalClustering.java @@ -34,6 +34,7 @@ import de.lmu.ifi.dbs.elki.data.Cluster; import de.lmu.ifi.dbs.elki.data.Clustering; import de.lmu.ifi.dbs.elki.data.model.ClusterModel; import de.lmu.ifi.dbs.elki.data.model.Model; +import de.lmu.ifi.dbs.elki.data.type.NoSupportedDataTypeException; import de.lmu.ifi.dbs.elki.data.type.TypeInformation; import de.lmu.ifi.dbs.elki.data.type.TypeUtil; import de.lmu.ifi.dbs.elki.database.Database; @@ -80,12 +81,14 @@ public class ByLabelHierarchicalClustering extends AbstractAlgorithm<Clustering< @Override public Clustering<Model> run(Database database) { // Prefer a true class label - Relation<ClassLabel> relation = database.getRelation(TypeUtil.CLASSLABEL); - if(relation != null) { + try { + Relation<ClassLabel> relation = database.getRelation(TypeUtil.CLASSLABEL); return run(relation); } - // Otherwise, try any labellike. - return run(database.getRelation(getInputTypeRestriction()[0])); + catch(NoSupportedDataTypeException e) { + // Otherwise, try any labellike. + return run(database.getRelation(getInputTypeRestriction()[0])); + } } /** diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/trivial/ByLabelOutlier.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/trivial/ByLabelOutlier.java index 3c9b318f..62f083fb 100644 --- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/trivial/ByLabelOutlier.java +++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/trivial/ByLabelOutlier.java @@ -28,6 +28,7 @@ import java.util.regex.Pattern; import de.lmu.ifi.dbs.elki.algorithm.AbstractAlgorithm; import de.lmu.ifi.dbs.elki.algorithm.outlier.OutlierAlgorithm; import de.lmu.ifi.dbs.elki.data.ClassLabel; +import de.lmu.ifi.dbs.elki.data.type.NoSupportedDataTypeException; import de.lmu.ifi.dbs.elki.data.type.TypeInformation; import de.lmu.ifi.dbs.elki.data.type.TypeUtil; import de.lmu.ifi.dbs.elki.database.Database; @@ -93,12 +94,14 @@ public class ByLabelOutlier extends AbstractAlgorithm<OutlierResult> implements @Override public OutlierResult run(Database database) { // Prefer a true class label - Relation<ClassLabel> relation = database.getRelation(TypeUtil.CLASSLABEL); - if(relation != null) { + try { + Relation<ClassLabel> relation = database.getRelation(TypeUtil.CLASSLABEL); return run(relation); } - // Otherwise, try any labellike. - return run(database.getRelation(getInputTypeRestriction()[0])); + catch(NoSupportedDataTypeException e) { + // Otherwise, try any labellike. + return run(database.getRelation(getInputTypeRestriction()[0])); + } } /** diff --git a/src/de/lmu/ifi/dbs/elki/application/GeneratorXMLSpec.java b/src/de/lmu/ifi/dbs/elki/application/GeneratorXMLSpec.java index c09c74eb..373960a5 100644 --- a/src/de/lmu/ifi/dbs/elki/application/GeneratorXMLSpec.java +++ b/src/de/lmu/ifi/dbs/elki/application/GeneratorXMLSpec.java @@ -24,559 +24,63 @@ package de.lmu.ifi.dbs.elki.application; */ import java.io.File; -import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStreamWriter; -import java.net.URL; -import java.util.LinkedList; -import java.util.Random; -import java.util.regex.Pattern; +import java.util.List; -import javax.xml.XMLConstants; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.validation.Schema; -import javax.xml.validation.SchemaFactory; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.xml.sax.SAXException; - -import de.lmu.ifi.dbs.elki.data.synthetic.bymodel.GeneratorMain; +import de.lmu.ifi.dbs.elki.data.synthetic.bymodel.GeneratorInterface; +import de.lmu.ifi.dbs.elki.data.synthetic.bymodel.GeneratorInterfaceDynamic; import de.lmu.ifi.dbs.elki.data.synthetic.bymodel.GeneratorSingleCluster; -import de.lmu.ifi.dbs.elki.data.synthetic.bymodel.GeneratorStatic; import de.lmu.ifi.dbs.elki.data.synthetic.bymodel.distribution.Distribution; -import de.lmu.ifi.dbs.elki.data.synthetic.bymodel.distribution.GammaDistribution; -import de.lmu.ifi.dbs.elki.data.synthetic.bymodel.distribution.NormalDistribution; -import de.lmu.ifi.dbs.elki.data.synthetic.bymodel.distribution.UniformDistribution; +import de.lmu.ifi.dbs.elki.datasource.GeneratorXMLDatabaseConnection; +import de.lmu.ifi.dbs.elki.datasource.bundle.MultipleObjectsBundle; import de.lmu.ifi.dbs.elki.logging.Logging; import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector; +import de.lmu.ifi.dbs.elki.utilities.FormatUtil; import de.lmu.ifi.dbs.elki.utilities.exceptions.UnableToComplyException; -import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID; import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization; -import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.DoubleParameter; -import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.FileParameter; -import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter; -import de.lmu.ifi.dbs.elki.utilities.xml.XMLNodeIterator; /** * Generate a data set based on a specified model (using an XML specification) * * @author Erich Schubert * - * @apiviz.composedOf GeneratorMain - * @apiviz.has GeneratorSingleCluster oneway - - creates - * @apiviz.has GeneratorStatic oneway - - creates + * @apiviz.composedOf GeneratorXMLDatabaseConnection */ public class GeneratorXMLSpec extends AbstractApplication { - // TODO: move XML parsing into data package. - /** * The logger for this class. */ private static final Logging logger = Logging.getLogger(GeneratorXMLSpec.class); /** - * A pattern defining whitespace. - */ - public static final Pattern WHITESPACE_PATTERN = Pattern.compile("\\s+"); - - /** - * Parameter to give the configuration file - */ - public static final OptionID CONFIGFILE_ID = OptionID.getOrCreateOptionID("bymodel.spec", "The generator specification file."); - - /** - * Parameter to give the configuration file - */ - public static final OptionID RANDOMSEED_ID = OptionID.getOrCreateOptionID("bymodel.randomseed", "The random generator seed."); - - /** - * Parameter to give the configuration file - */ - public static final OptionID SIZE_SCALE_ID = OptionID.getOrCreateOptionID("bymodel.sizescale", "Factor for scaling the specified cluster sizes."); - - /** - * File name of the generators XML Schema file. + * Line separator for output */ - private static final String GENERATOR_SCHEMA_FILE = GeneratorXMLSpec.class.getPackage().getName().replace('.', '/') + '/' + "GeneratorByModel.xsd"; + public final static String LINE_SEPARATOR = System.getProperty("line.separator"); /** - * The configuration file. - */ - File specfile; - - /** - * Parameter for scaling the cluster sizes. - */ - double sizescale = 1.0; - - /** - * The actual generator class - */ - public GeneratorMain gen = new GeneratorMain(); - - /** - * Random generator used for initializing cluster generators. - */ - private Random clusterRandom = null; - - /** - * Set testAgainstModel flag + * Output file. */ - private boolean testAgainstModel = true; + private File outputFile; /** - * Output file. + * The original data source. */ - private File outputFile; + private GeneratorXMLDatabaseConnection generator; /** * Constructor. * * @param verbose Verbose flag * @param output Output file - * @param specfile Specification file - * @param sizescale Size scaling - * @param clusterRandom Random number generator + * @param generator GeneratorXMLDatabaseConnection */ - public GeneratorXMLSpec(boolean verbose, File output, File specfile, double sizescale, Random clusterRandom) { + public GeneratorXMLSpec(boolean verbose, File output, GeneratorXMLDatabaseConnection generator) { super(verbose); this.outputFile = output; - this.specfile = specfile; - this.sizescale = sizescale; - this.clusterRandom = clusterRandom; - if(this.clusterRandom == null) { - this.clusterRandom = new Random(); - } - } - - /** - * Load the XML configuration file. - * - * @throws UnableToComplyException - */ - private void loadXMLSpecification(File specfile) throws UnableToComplyException { - try { - InputStream in = new FileInputStream(specfile); - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); - URL url = ClassLoader.getSystemResource(GENERATOR_SCHEMA_FILE); - if(url != null) { - try { - Schema schema = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI).newSchema(url); - dbf.setSchema(schema); - dbf.setIgnoringElementContentWhitespace(true); - } - catch(Exception e) { - logger.warning("Could not set up XML Schema validation for speciciation file."); - } - } - else { - logger.warning("Could not set up XML Schema validation for speciciation file."); - } - Document doc = dbf.newDocumentBuilder().parse(in); - Node root = doc.getDocumentElement(); - if(root.getNodeName() == "dataset") { - processElementDataset(root); - } - else { - throw new UnableToComplyException("Experiment specification has incorrect document element: " + root.getNodeName()); - } - } - catch(FileNotFoundException e) { - throw new UnableToComplyException("Can't open specification file.", e); - } - catch(SAXException e) { - throw new UnableToComplyException("Error parsing specification file.", e); - } - catch(IOException e) { - throw new UnableToComplyException("IO Exception loading specification file.", e); - } - catch(ParserConfigurationException e) { - throw new UnableToComplyException("Parser Configuration Error", e); - } - } - - /** - * Process a 'dataset' Element in the XML stream. - * - * @param cur Current document nod - * @throws UnableToComplyException - */ - private void processElementDataset(Node cur) throws UnableToComplyException { - // *** get parameters - String seedstr = ((Element) cur).getAttribute("random-seed"); - if(seedstr != null && seedstr != "") { - clusterRandom = new Random((int) (Integer.valueOf(seedstr) * sizescale)); - } - String testmod = ((Element) cur).getAttribute("test-model"); - if(testmod != null && testmod != "") { - testAgainstModel = (Integer.valueOf(testmod) != 0); - } - // TODO: check for unknown attributes. - for(Node child : new XMLNodeIterator(cur.getFirstChild())) { - if(child.getNodeName() == "cluster") { - processElementCluster(child); - } - else if(child.getNodeName() == "static") { - processElementStatic(child); - } - else if(child.getNodeType() == Node.ELEMENT_NODE) { - logger.warning("Unknown element in XML specification file: " + child.getNodeName()); - } - } - } - - /** - * Process a 'cluster' Element in the XML stream. - * - * @param cur Current document nod - * @throws UnableToComplyException - */ - private void processElementCluster(Node cur) throws UnableToComplyException { - int size = -1; - double overweight = 1.0; - - String sizestr = ((Element) cur).getAttribute("size"); - if(sizestr != null && sizestr != "") { - size = (int) (Integer.valueOf(sizestr) * sizescale); - } - - String name = ((Element) cur).getAttribute("name"); - - String dcostr = ((Element) cur).getAttribute("density-correction"); - if(dcostr != null && dcostr != "") { - overweight = Double.valueOf(dcostr); - } - - if(size < 0) { - throw new UnableToComplyException("No valid cluster size given in specification file."); - } - if(name == null || name == "") { - throw new UnableToComplyException("No cluster name given in specification file."); - } - - // *** add new cluster object - Random newRand = new Random(clusterRandom.nextLong()); - GeneratorSingleCluster cluster = new GeneratorSingleCluster(name, size, overweight, newRand); - - // TODO: check for unknown attributes. - for(Node child : new XMLNodeIterator(cur.getFirstChild())) { - if(child.getNodeName() == "uniform") { - processElementUniform(cluster, child); - } - else if(child.getNodeName() == "normal") { - processElementNormal(cluster, child); - } - else if(child.getNodeName() == "gamma") { - processElementGamma(cluster, child); - } - else if(child.getNodeName() == "rotate") { - processElementRotate(cluster, child); - } - else if(child.getNodeName() == "translate") { - processElementTranslate(cluster, child); - } - else if(child.getNodeName() == "clip") { - processElementClipping(cluster, child); - } - else if(child.getNodeType() == Node.ELEMENT_NODE) { - logger.warning("Unknown element in XML specification file: " + child.getNodeName()); - } - } - - gen.addCluster(cluster); - } - - /** - * Process a 'uniform' Element in the XML stream. - * - * @param cluster - * @param cur Current document nod - * @throws UnableToComplyException - */ - private void processElementUniform(GeneratorSingleCluster cluster, Node cur) throws UnableToComplyException { - double min = 0.0; - double max = 1.0; - - String minstr = ((Element) cur).getAttribute("min"); - if(minstr != null && minstr != "") { - min = Double.valueOf(minstr); - } - String maxstr = ((Element) cur).getAttribute("max"); - if(maxstr != null && maxstr != "") { - max = Double.valueOf(maxstr); - } - - // *** new uniform generator - Random random = cluster.getNewRandomGenerator(); - Distribution generator = new UniformDistribution(min, max, random); - cluster.addGenerator(generator); - - // TODO: check for unknown attributes. - for(Node child : new XMLNodeIterator(cur.getFirstChild())) { - if(child.getNodeType() == Node.ELEMENT_NODE) { - logger.warning("Unknown element in XML specification file: " + child.getNodeName()); - } - } - } - - /** - * Process a 'normal' Element in the XML stream. - * - * @param cluster - * @param cur Current document nod - * @throws UnableToComplyException - */ - private void processElementNormal(GeneratorSingleCluster cluster, Node cur) throws UnableToComplyException { - double mean = 0.0; - double stddev = 1.0; - String meanstr = ((Element) cur).getAttribute("mean"); - if(meanstr != null && meanstr != "") { - mean = Double.valueOf(meanstr); - } - String stddevstr = ((Element) cur).getAttribute("stddev"); - if(stddevstr != null && stddevstr != "") { - stddev = Double.valueOf(stddevstr); - } - - // *** New normal distribution generator - Random random = cluster.getNewRandomGenerator(); - Distribution generator = new NormalDistribution(mean, stddev, random); - cluster.addGenerator(generator); - - // TODO: check for unknown attributes. - for(Node child : new XMLNodeIterator(cur.getFirstChild())) { - if(child.getNodeType() == Node.ELEMENT_NODE) { - logger.warning("Unknown element in XML specification file: " + child.getNodeName()); - } - } - } - - /** - * Process a 'gamma' Element in the XML stream. - * - * @param cluster - * @param cur Current document nod - * @throws UnableToComplyException - */ - private void processElementGamma(GeneratorSingleCluster cluster, Node cur) throws UnableToComplyException { - double k = 1.0; - double theta = 1.0; - String kstr = ((Element) cur).getAttribute("k"); - if(kstr != null && kstr != "") { - k = Double.valueOf(kstr); - } - String thetastr = ((Element) cur).getAttribute("theta"); - if(thetastr != null && thetastr != "") { - theta = Double.valueOf(thetastr); - } - - // *** New normal distribution generator - Random random = cluster.getNewRandomGenerator(); - Distribution generator = new GammaDistribution(k, theta, random); - cluster.addGenerator(generator); - - // TODO: check for unknown attributes. - for(Node child : new XMLNodeIterator(cur.getFirstChild())) { - if(child.getNodeType() == Node.ELEMENT_NODE) { - logger.warning("Unknown element in XML specification file: " + child.getNodeName()); - } - } - } - - /** - * Process a 'rotate' Element in the XML stream. - * - * @param cluster - * @param cur Current document nod - * @throws UnableToComplyException - */ - private void processElementRotate(GeneratorSingleCluster cluster, Node cur) throws UnableToComplyException { - int axis1 = 0; - int axis2 = 0; - double angle = 0.0; - - String a1str = ((Element) cur).getAttribute("axis1"); - if(a1str != null && a1str != "") { - axis1 = Integer.valueOf(a1str); - } - String a2str = ((Element) cur).getAttribute("axis2"); - if(a2str != null && a2str != "") { - axis2 = Integer.valueOf(a2str); - } - String anstr = ((Element) cur).getAttribute("angle"); - if(anstr != null && anstr != "") { - angle = Double.valueOf(anstr); - } - if(axis1 <= 0 || axis1 > cluster.getDim()) { - throw new UnableToComplyException("Invalid axis1 number given in specification file."); - } - if(axis1 <= 0 || axis1 > cluster.getDim()) { - throw new UnableToComplyException("Invalid axis2 number given in specification file."); - } - if(axis1 == axis2) { - throw new UnableToComplyException("Invalid axis numbers given in specification file."); - } - - // Add rotation to cluster. - cluster.addRotation(axis1 - 1, axis2 - 1, Math.toRadians(angle)); - - // TODO: check for unknown attributes. - for(Node child : new XMLNodeIterator(cur.getFirstChild())) { - if(child.getNodeType() == Node.ELEMENT_NODE) { - logger.warning("Unknown element in XML specification file: " + child.getNodeName()); - } - } - } - - /** - * Process a 'translate' Element in the XML stream. - * - * @param cluster - * @param cur Current document nod - * @throws UnableToComplyException - */ - private void processElementTranslate(GeneratorSingleCluster cluster, Node cur) throws UnableToComplyException { - Vector offset = null; - String vstr = ((Element) cur).getAttribute("vector"); - if(vstr != null && vstr != "") { - offset = parseVector(vstr); - } - if(offset == null) { - throw new UnableToComplyException("No translation vector given."); - } - - // *** add new translation - cluster.addTranslation(offset); - - // TODO: check for unknown attributes. - for(Node child : new XMLNodeIterator(cur.getFirstChild())) { - if(child.getNodeType() == Node.ELEMENT_NODE) { - logger.warning("Unknown element in XML specification file: " + child.getNodeName()); - } - } - } - - /** - * Process a 'clipping' Element in the XML stream. - * - * @param cluster - * @param cur Current document nod - * @throws UnableToComplyException - */ - private void processElementClipping(GeneratorSingleCluster cluster, Node cur) throws UnableToComplyException { - Vector cmin = null; - Vector cmax = null; - - String minstr = ((Element) cur).getAttribute("min"); - if(minstr != null && minstr != "") { - cmin = parseVector(minstr); - } - String maxstr = ((Element) cur).getAttribute("max"); - if(maxstr != null && maxstr != "") { - cmax = parseVector(maxstr); - } - if(cmin == null || cmax == null) { - throw new UnableToComplyException("No or incomplete clipping vectors given."); - } - - // *** set clipping - cluster.setClipping(cmin, cmax); - - // TODO: check for unknown attributes. - for(Node child : new XMLNodeIterator(cur.getFirstChild())) { - if(child.getNodeType() == Node.ELEMENT_NODE) { - logger.warning("Unknown element in XML specification file: " + child.getNodeName()); - } - } - } - - /** - * Process a 'static' cluster Element in the XML stream. - * - * @param cur Current document nod - * @throws UnableToComplyException - */ - private void processElementStatic(Node cur) throws UnableToComplyException { - String name = ((Element) cur).getAttribute("name"); - if(name == null) { - throw new UnableToComplyException("No cluster name given in specification file."); - } - - LinkedList<Vector> points = new LinkedList<Vector>(); - // TODO: check for unknown attributes. - for(Node child : new XMLNodeIterator(cur.getFirstChild())) { - if(child.getNodeName() == "point") { - processElementPoint(points, child); - } - else if(child.getNodeType() == Node.ELEMENT_NODE) { - logger.warning("Unknown element in XML specification file: " + child.getNodeName()); - } - } - // *** add new cluster object - GeneratorStatic cluster = new GeneratorStatic(name, points); - - gen.addCluster(cluster); - if(logger.isVerbose()) { - logger.verbose("Loaded cluster " + cluster.name + " from specification."); - } - } - - /** - * Parse a 'point' element (point vector for a static cluster) - * - * @param points current list of points (to append to) - * @param cur Current document nod - * @throws UnableToComplyException - */ - private void processElementPoint(LinkedList<Vector> points, Node cur) throws UnableToComplyException { - Vector point = null; - String vstr = ((Element) cur).getAttribute("vector"); - if(vstr != null && vstr != "") { - point = parseVector(vstr); - } - if(point == null) { - throw new UnableToComplyException("No translation vector given."); - } - - // *** add new point - points.add(point); - - // TODO: check for unknown attributes. - for(Node child : new XMLNodeIterator(cur.getFirstChild())) { - if(child.getNodeType() == Node.ELEMENT_NODE) { - logger.warning("Unknown element in XML specification file: " + child.getNodeName()); - } - } - } - - /** - * Parse a string into a vector. - * - * TODO: move this into utility package? - * - * @param s String to parse - * @return Vector - * @throws UnableToComplyException - */ - private Vector parseVector(String s) throws UnableToComplyException { - String[] entries = WHITESPACE_PATTERN.split(s); - double[] d = new double[entries.length]; - for(int i = 0; i < entries.length; i++) { - try { - d[i] = Double.valueOf(entries[i]); - } - catch(NumberFormatException e) { - throw new UnableToComplyException("Could not parse vector."); - } - } - return new Vector(d); + this.generator = generator; } /** @@ -584,15 +88,7 @@ public class GeneratorXMLSpec extends AbstractApplication { */ @Override public void run() throws UnableToComplyException { - if(logger.isVerbose()) { - logger.verbose("Loading specification ..."); - } - loadXMLSpecification(specfile); - if(logger.isVerbose()) { - logger.verbose("Generating clusters ..."); - } - gen.setTestAgainstModel(testAgainstModel); - gen.generate(); + MultipleObjectsBundle data = generator.loadData(); if(logger.isVerbose()) { logger.verbose("Writing output ..."); } @@ -604,7 +100,7 @@ public class GeneratorXMLSpec extends AbstractApplication { } OutputStreamWriter outStream = new FileWriter(outputFile, true); - gen.writeClusters(outStream); + writeClusters(outStream, data); outStream.flush(); outStream.close(); @@ -621,6 +117,68 @@ public class GeneratorXMLSpec extends AbstractApplication { } /** + * Write the resulting clusters to an output stream. + * + * @param outStream output stream + * @param data Generated data + * @throws IOException thrown on write errors + */ + public void writeClusters(OutputStreamWriter outStream, MultipleObjectsBundle data) throws IOException { + List<GeneratorInterface> clusters = generator.gen.getGenerators(); + // compute global discard values + int totalsize = 0; + int totaldisc = 0; + assert (clusters.size() > 0); + for(GeneratorInterface curclus : clusters) { + totalsize = totalsize + curclus.getSize(); + if(curclus instanceof GeneratorSingleCluster) { + totaldisc = totaldisc + ((GeneratorSingleCluster) curclus).getDiscarded(); + } + } + double globdens = (double) (totalsize + totaldisc) / totalsize; + outStream.write("########################################################" + LINE_SEPARATOR); + outStream.write("## Number of clusters: " + clusters.size() + LINE_SEPARATOR); + for(GeneratorInterface curclus : clusters) { + outStream.write("########################################################" + LINE_SEPARATOR); + outStream.write("## Cluster: " + curclus.getName() + LINE_SEPARATOR); + outStream.write("########################################################" + LINE_SEPARATOR); + outStream.write("## Size: " + curclus.getSize() + LINE_SEPARATOR); + if(curclus instanceof GeneratorSingleCluster) { + GeneratorSingleCluster cursclus = (GeneratorSingleCluster) curclus; + Vector cmin = cursclus.getClipmin(); + Vector cmax = cursclus.getClipmax(); + if(cmin != null && cmax != null) { + outStream.write("## Clipping: " + cmin.toString() + " - " + cmax.toString() + LINE_SEPARATOR); + } + outStream.write("## Density correction factor: " + cursclus.getDensityCorrection() + LINE_SEPARATOR); + outStream.write("## Generators:" + LINE_SEPARATOR); + for(Distribution gen : cursclus.getAxes()) { + outStream.write("## " + gen.toString() + LINE_SEPARATOR); + } + if(cursclus.getTrans() != null && cursclus.getTrans().getTransformation() != null) { + outStream.write("## Affine transformation matrix:" + LINE_SEPARATOR); + outStream.write(FormatUtil.format(cursclus.getTrans().getTransformation(), "## ") + LINE_SEPARATOR); + } + } + if(curclus instanceof GeneratorInterfaceDynamic) { + GeneratorSingleCluster cursclus = (GeneratorSingleCluster) curclus; + outStream.write("## Discards: " + cursclus.getDiscarded() + " Retries left: " + cursclus.getRetries() + LINE_SEPARATOR); + double corf = /* cursclus.overweight */(double) (cursclus.getSize() + cursclus.getDiscarded()) / cursclus.getSize() / globdens; + outStream.write("## Density correction factor estimation: " + corf + LINE_SEPARATOR); + + } + outStream.write("########################################################" + LINE_SEPARATOR); + for(Vector p : curclus.getPoints()) { + for(int i = 0; i < p.getRowDimensionality(); i++) { + outStream.write(p.get(i) + " "); + } + outStream.write(curclus.getName()); + outStream.write(LINE_SEPARATOR); + } + } + } + + /** * Parameterization class. * * @author Erich Schubert @@ -629,50 +187,26 @@ public class GeneratorXMLSpec extends AbstractApplication { */ public static class Parameterizer extends AbstractApplication.Parameterizer { /** - * The configuration file. - */ - File specfile = null; - - /** - * Parameter for scaling the cluster sizes. - */ - double sizescale = 1.0; - - /** - * Random generator used for initializing cluster generators. + * Output file. */ - private Random clusterRandom = null; + private File outputFile = null; /** - * Output file. + * Data generator */ - private File outputFile = null; + private GeneratorXMLDatabaseConnection generator = null; @Override protected void makeOptions(Parameterization config) { super.makeOptions(config); // Output file outputFile = getParameterOutputFile(config, "the file to write the generated data set into, if the file already exists, the generated points will be appended to this file."); - // Specification file - final FileParameter cfgparam = new FileParameter(CONFIGFILE_ID, FileParameter.FileType.INPUT_FILE); - if(config.grab(cfgparam)) { - specfile = cfgparam.getValue(); - } - // Cluster size scaling - final DoubleParameter scalepar = new DoubleParameter(SIZE_SCALE_ID, 1.0); - if(config.grab(scalepar)) { - sizescale = scalepar.getValue(); - } - // Random generator - final IntParameter seedpar = new IntParameter(RANDOMSEED_ID, true); - if(config.grab(seedpar)) { - clusterRandom = new Random(seedpar.getValue()); - } + generator = config.tryInstantiate(GeneratorXMLDatabaseConnection.class); } @Override protected GeneratorXMLSpec makeInstance() { - return new GeneratorXMLSpec(verbose, outputFile, specfile, sizescale, clusterRandom); + return new GeneratorXMLSpec(verbose, outputFile, generator); } } diff --git a/src/de/lmu/ifi/dbs/elki/application/internal/DocumentParameters.java b/src/de/lmu/ifi/dbs/elki/application/internal/DocumentParameters.java index b5bb516e..05af4b4d 100644 --- a/src/de/lmu/ifi/dbs/elki/application/internal/DocumentParameters.java +++ b/src/de/lmu/ifi/dbs/elki/application/internal/DocumentParameters.java @@ -196,39 +196,40 @@ public class DocumentParameters { public void run() { // Try a V3 style parameterizer first. Parameterizer par = ClassGenericsUtil.getParameterizer(cls); - if (par != null) { + if(par != null) { par.configure(track); - return; } - try { - Object instance = ClassGenericsUtil.tryInstantiate(Object.class, cls, track); - for(Pair<Object, Parameter<?, ?>> pair : track.getAllParameters()) { - if(pair.first == null) { - pair.first = instance; + else { + try { + ClassGenericsUtil.tryInstantiate(Object.class, cls, track); + } + catch(java.lang.NoSuchMethodException e) { + logger.warning("Could not instantiate class " + cls.getName() + " - no appropriate constructor or parameterizer found."); + } + catch(java.lang.reflect.InvocationTargetException e) { + if(e.getCause() instanceof RuntimeException) { + throw (RuntimeException) e.getCause(); + } + if(e.getCause() instanceof Error) { + throw (Error) e.getCause(); } - options.add(pair); + throw new RuntimeException(e.getCause()); } - } - catch(java.lang.NoSuchMethodException e) { - logger.warning("Could not instantiate class "+cls.getName()+" - no appropriate constructor or parameterizer found."); - } - catch(java.lang.reflect.InvocationTargetException e) { - if(e.getCause() instanceof RuntimeException) { - throw (RuntimeException) e.getCause(); + catch(RuntimeException e) { + throw e; } - if(e.getCause() instanceof Error) { - throw (Error) e.getCause(); + catch(Exception e) { + throw new RuntimeException(e); + } + catch(java.lang.Error e) { + throw new RuntimeException(e); } - throw new RuntimeException(e.getCause()); - } - catch(RuntimeException e) { - throw e; - } - catch(Exception e) { - throw new RuntimeException(e); } - catch(java.lang.Error e) { - throw new RuntimeException(e); + for(Pair<Object, Parameter<?, ?>> pair : track.getAllParameters()) { + if(pair.first == null) { + pair.first = cls; + } + options.add(pair); } } }, null); @@ -296,7 +297,7 @@ public class DocumentParameters { boolean inlist = false; if(byo != null) { for(Pair<Parameter<?, ?>, Class<?>> pair : byo) { - if(pair.second == c) { + if(pair.second.equals(c)) { inlist = true; break; } @@ -306,9 +307,6 @@ public class DocumentParameters { byopt.add(o.getOptionID(), new Pair<Parameter<?, ?>, Class<?>>(o, c)); } } - if(!byopt.contains(o.getOptionID(), new Pair<Parameter<?, ?>, Class<?>>(o, c))) { - byopt.add(o.getOptionID(), new Pair<Parameter<?, ?>, Class<?>>(o, c)); - } } es.shutdownNow(); logger.debug("byClass: " + byclass.size() + " byOpt: " + byopt.size()); @@ -435,7 +433,7 @@ public class DocumentParameters { elemdd.appendChild(elemp); // class restriction? if(opt instanceof ClassParameter<?>) { - appendClassRestriction(htmldoc, (ClassParameter<?>) opt, elemdd); + appendClassRestriction(htmldoc, ((ClassParameter<?>) opt).getRestrictionClass(), elemdd); } // default value? completions? appendDefaultValueIfSet(htmldoc, opt, elemdd); @@ -509,7 +507,7 @@ public class DocumentParameters { Collections.sort(opts, new SortByOption()); for(OptionID oid : opts) { - Parameter<?, ?> firstopt = byopt.get(oid).get(0).getFirst(); + final Parameter<?, ?> firstopt = byopt.get(oid).get(0).getFirst(); // DT = definition term Element optdt = htmldoc.createElement(HTMLUtil.HTML_DT_TAG); // Anchor for references @@ -533,8 +531,17 @@ public class DocumentParameters { optdd.appendChild(elemp); } // class restriction? + Class<?> superclass = null; if(firstopt instanceof ClassParameter<?>) { - appendClassRestriction(htmldoc, (ClassParameter<?>) firstopt, optdd); + // Find superclass heuristically + superclass = ((ClassParameter<?>) firstopt).getRestrictionClass(); + for (Pair<Parameter<?, ?>, Class<?>> clinst : byopt.get(oid)) { + ClassParameter<?> cls = (ClassParameter<?>) clinst.getFirst(); + if (!cls.getRestrictionClass().equals(superclass) && cls.getRestrictionClass().isAssignableFrom(superclass)) { + superclass = cls.getRestrictionClass(); + } + } + appendClassRestriction(htmldoc, superclass, optdd); } // default value? appendDefaultValueIfSet(htmldoc, firstopt, optdd); @@ -566,8 +573,8 @@ public class DocumentParameters { ClassParameter<?> cls = (ClassParameter<?>) clinst.getFirst(); if(cls.getRestrictionClass() != null) { // TODO: if it is null, it could still be different! - if(!cls.getRestrictionClass().equals(((ClassParameter<?>) firstopt).getRestrictionClass())) { - appendClassRestriction(htmldoc, cls, classli); + if(!cls.getRestrictionClass().equals(superclass)) { + appendClassRestriction(htmldoc, cls.getRestrictionClass(), classli); } } else { @@ -599,22 +606,22 @@ public class DocumentParameters { p.appendChild(defa); } - private static void appendClassRestriction(Document htmldoc, ClassParameter<?> opt, Element elemdd) { - if(opt.getRestrictionClass() == null) { - logger.warning("No restriction class for Parameter " + opt.getName()); + private static void appendClassRestriction(Document htmldoc, Class<?> restriction, Element elemdd) { + if(restriction == null) { + logger.warning("No restriction class!"); return; } Element p = htmldoc.createElement(HTMLUtil.HTML_P_TAG); p.appendChild(htmldoc.createTextNode(HEADER_CLASS_RESTRICTION)); - if(opt.getRestrictionClass().isInterface()) { + if(restriction.isInterface()) { p.appendChild(htmldoc.createTextNode(HEADER_CLASS_RESTRICTION_IMPLEMENTING)); } else { p.appendChild(htmldoc.createTextNode(HEADER_CLASS_RESTRICTION_EXTENDING)); } Element defa = htmldoc.createElement(HTMLUtil.HTML_A_TAG); - defa.setAttribute(HTMLUtil.HTML_HREF_ATTRIBUTE, linkForClassName(opt.getRestrictionClass().getName())); - defa.setTextContent(opt.getRestrictionClass().getName()); + defa.setAttribute(HTMLUtil.HTML_HREF_ATTRIBUTE, linkForClassName(restriction.getName())); + defa.setTextContent(restriction.getName()); p.appendChild(defa); elemdd.appendChild(p); } @@ -645,8 +652,8 @@ public class DocumentParameters { elemdd.appendChild(ul); } // Report when not in properties file. - if (Properties.ELKI_PROPERTIES.getProperty(opt.getRestrictionClass().getName()).length == 0) { - logger.warning(opt.getRestrictionClass().getName()+" not in properties. No autocompletion available in release GUI."); + if(Properties.ELKI_PROPERTIES.getProperty(opt.getRestrictionClass().getName()).length == 0) { + logger.warning(opt.getRestrictionClass().getName() + " not in properties. No autocompletion available in release GUI."); } } } diff --git a/src/de/lmu/ifi/dbs/elki/data/ClassLabel.java b/src/de/lmu/ifi/dbs/elki/data/ClassLabel.java index 7cef5e1e..3ec5874c 100644 --- a/src/de/lmu/ifi/dbs/elki/data/ClassLabel.java +++ b/src/de/lmu/ifi/dbs/elki/data/ClassLabel.java @@ -31,23 +31,16 @@ import de.lmu.ifi.dbs.elki.utilities.InspectionUtilFrequentlyScanned; * * @author Arthur Zimek */ -public abstract class ClassLabel implements Comparable<ClassLabel>, InspectionUtilFrequentlyScanned { +public abstract class ClassLabel implements Comparable<ClassLabel> { /** * ClassLabels need an empty constructor for dynamic access. Subsequently, the * init method must be called. */ protected ClassLabel() { - // requires subsequent call of init + // Initialized from factory } /** - * Initialization of a ClassLabel for the given label. - * - * @param label the label to create a ClassLabel - */ - public abstract void init(String label); - - /** * Any ClassLabel should ensure a natural ordering that is consistent with * equals. Thus, if <code>this.compareTo(o)==0</code>, then * <code>this.equals(o)</code> should be <code>true</code>. @@ -83,4 +76,16 @@ public abstract class ClassLabel implements Comparable<ClassLabel>, InspectionUt public int hashCode() { return toString().hashCode(); } -} + + /** + * Class label factory + * + * @author Erich Schubert + * + * @apiviz.has ClassLabel - - «creates» + * @apiviz.stereotype factory + */ + public static abstract class Factory<L extends ClassLabel> implements InspectionUtilFrequentlyScanned { + public abstract L makeFromString(String lbl); + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/data/ExternalID.java b/src/de/lmu/ifi/dbs/elki/data/ExternalID.java index 4ba44062..228b97d0 100644 --- a/src/de/lmu/ifi/dbs/elki/data/ExternalID.java +++ b/src/de/lmu/ifi/dbs/elki/data/ExternalID.java @@ -28,6 +28,8 @@ package de.lmu.ifi.dbs.elki.data; * External ID objects. * * @author Erich Schubert + * + * @apiviz.composedOf String */ public final class ExternalID { /** diff --git a/src/de/lmu/ifi/dbs/elki/data/HierarchicalClassLabel.java b/src/de/lmu/ifi/dbs/elki/data/HierarchicalClassLabel.java index 694324c7..499a40be 100644 --- a/src/de/lmu/ifi/dbs/elki/data/HierarchicalClassLabel.java +++ b/src/de/lmu/ifi/dbs/elki/data/HierarchicalClassLabel.java @@ -30,6 +30,8 @@ import java.util.regex.Pattern; * of classes. * * @author Arthur Zimek + * + * @apiviz.composedOf Comparable */ public class HierarchicalClassLabel extends ClassLabel { /** @@ -56,17 +58,9 @@ public class HierarchicalClassLabel extends ClassLabel { /** * Holds the names on the different levels. */ - // TODO: fix generics warnings. private Comparable<?>[] levelwiseNames; /** - * @see ClassLabel#ClassLabel() - */ - public HierarchicalClassLabel() { - super(); - } - - /** * Constructs a hierarchical class label from the given name, using the given * Pattern to match separators of different levels in the given name, and * setting the given separator-String to separate different levels in String @@ -78,7 +72,8 @@ public class HierarchicalClassLabel extends ClassLabel { * @param separator a separator String to separate different levels in the * String-representation of this HierarchicalClassLabel */ - public void init(String name, Pattern regex, String separator) { + public HierarchicalClassLabel(String name, Pattern regex, String separator) { + super(); this.separatorPattern = regex; this.separatorString = separator; String[] levelwiseStrings = separatorPattern.split(name); @@ -101,11 +96,9 @@ public class HierarchicalClassLabel extends ClassLabel { * separated by '.'. * * @param label a String describing a hierarchical class label - * @see #init(String, java.util.regex.Pattern, String) */ - @Override - public void init(String label) { - init(label, DEFAULT_SEPARATOR, DEFAULT_SEPARATOR_STRING); + public HierarchicalClassLabel(String label) { + this(label, DEFAULT_SEPARATOR, DEFAULT_SEPARATOR_STRING); } /** @@ -190,4 +183,19 @@ public class HierarchicalClassLabel extends ClassLabel { } return name.toString(); } -} + + /** + * Factory class + * + * @author Erich Schubert + * + * @apiviz.has HierarchicalClassLabel - - «creates» + * @apiviz.stereotype factory + */ + public static class Factory extends ClassLabel.Factory<HierarchicalClassLabel> { + @Override + public HierarchicalClassLabel makeFromString(String lbl) { + return new HierarchicalClassLabel(lbl); + } + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/data/LabelList.java b/src/de/lmu/ifi/dbs/elki/data/LabelList.java index d710bf37..9dc73c0f 100644 --- a/src/de/lmu/ifi/dbs/elki/data/LabelList.java +++ b/src/de/lmu/ifi/dbs/elki/data/LabelList.java @@ -31,6 +31,8 @@ import de.lmu.ifi.dbs.elki.utilities.FormatUtil; * A list of string labels * * @author Erich Schubert + * + * @apiviz.composedOf String */ public class LabelList extends ArrayList<String> { /** diff --git a/src/de/lmu/ifi/dbs/elki/data/SimpleClassLabel.java b/src/de/lmu/ifi/dbs/elki/data/SimpleClassLabel.java index da51aeaa..b71dd9bb 100644 --- a/src/de/lmu/ifi/dbs/elki/data/SimpleClassLabel.java +++ b/src/de/lmu/ifi/dbs/elki/data/SimpleClassLabel.java @@ -28,27 +28,22 @@ package de.lmu.ifi.dbs.elki.data; * A simple class label casting a String as it is as label. * * @author Arthur Zimek + * + * @apiviz.composedOf String */ public class SimpleClassLabel extends ClassLabel { /** * Holds the String designating the label. */ private String label; - + /** - * @see ClassLabel#ClassLabel() + * Constructor. + * + * @param label Label */ - public SimpleClassLabel() { + public SimpleClassLabel(String label) { super(); - } - - /** - * Provides a simple class label covering the given String. - * - * @param label the String to be cast as label - */ - @Override - public void init(String label) { this.label = label; } @@ -107,4 +102,19 @@ public class SimpleClassLabel extends ClassLabel { public String toString() { return label; } + + /** + * Factory class + * + * @author Erich Schubert + * + * @apiviz.has SimpleClassLabel - - «creates» + * @apiviz.stereotype factory + */ + public static class Factory extends ClassLabel.Factory<SimpleClassLabel> { + @Override + public SimpleClassLabel makeFromString(String lbl) { + return new SimpleClassLabel(lbl); + } + } }
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/data/model/ClusterModel.java b/src/de/lmu/ifi/dbs/elki/data/model/ClusterModel.java index c8b3e0eb..f40b4b73 100644 --- a/src/de/lmu/ifi/dbs/elki/data/model/ClusterModel.java +++ b/src/de/lmu/ifi/dbs/elki/data/model/ClusterModel.java @@ -30,6 +30,7 @@ package de.lmu.ifi.dbs.elki.data.model; * * @author Erich Schubert * + * @apiviz.landmark */ public final class ClusterModel extends BaseModel { /** diff --git a/src/de/lmu/ifi/dbs/elki/data/model/Model.java b/src/de/lmu/ifi/dbs/elki/data/model/Model.java index 58e9542b..d07fc926 100644 --- a/src/de/lmu/ifi/dbs/elki/data/model/Model.java +++ b/src/de/lmu/ifi/dbs/elki/data/model/Model.java @@ -29,7 +29,8 @@ package de.lmu.ifi.dbs.elki.data.model; * * @author Erich Schubert * + * @apiviz.landmark */ public interface Model { // currently, there are no requirements on a model. -} +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/GeneratorMain.java b/src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/GeneratorMain.java index 6400a747..eef7b13d 100644 --- a/src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/GeneratorMain.java +++ b/src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/GeneratorMain.java @@ -23,14 +23,18 @@ package de.lmu.ifi.dbs.elki.data.synthetic.bymodel; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import java.io.IOException; -import java.io.OutputStreamWriter; +import java.util.ArrayList; +import java.util.Collections; import java.util.LinkedList; import java.util.List; -import de.lmu.ifi.dbs.elki.data.synthetic.bymodel.distribution.Distribution; +import de.lmu.ifi.dbs.elki.data.ClassLabel; +import de.lmu.ifi.dbs.elki.data.DoubleVector; +import de.lmu.ifi.dbs.elki.data.SimpleClassLabel; +import de.lmu.ifi.dbs.elki.data.type.TypeUtil; +import de.lmu.ifi.dbs.elki.data.type.VectorFieldTypeInformation; +import de.lmu.ifi.dbs.elki.datasource.bundle.MultipleObjectsBundle; import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector; -import de.lmu.ifi.dbs.elki.utilities.FormatUtil; import de.lmu.ifi.dbs.elki.utilities.exceptions.UnableToComplyException; /** @@ -63,14 +67,9 @@ import de.lmu.ifi.dbs.elki.utilities.exceptions.UnableToComplyException; */ public class GeneratorMain { /** - * Line separator for output - */ - public final static String LINE_SEPARATOR = System.getProperty("line.separator"); - - /** * List of clusters to generate */ - private LinkedList<GeneratorInterface> clusters = new LinkedList<GeneratorInterface>(); + private LinkedList<GeneratorInterface> generators = new LinkedList<GeneratorInterface>(); /** * Add a cluster to the cluster list. @@ -78,7 +77,7 @@ public class GeneratorMain { * @param c cluster to add */ public void addCluster(GeneratorInterface c) { - clusters.add(c); + generators.add(c); } /** @@ -94,18 +93,18 @@ public class GeneratorMain { */ public void generate() throws UnableToComplyException { // we actually need some clusters. - if(clusters.size() < 1) { + if(generators.size() < 1) { throw new UnableToComplyException("No clusters specified."); } // Assert that cluster dimensions agree. - int dim = clusters.get(0).getDim(); - for(GeneratorInterface c : clusters) { + final int dim = generators.get(0).getDim(); + for(GeneratorInterface c : generators) { if(c.getDim() != dim) { throw new UnableToComplyException("Cluster dimensions do not agree."); } } // generate clusters - for(GeneratorInterface curclus : clusters) { + for(GeneratorInterface curclus : generators) { while(curclus.getPoints().size() < curclus.getSize()) { // generate the "missing" number of points List<Vector> newp = curclus.generate(curclus.getSize() - curclus.getPoints().size()); @@ -115,7 +114,7 @@ public class GeneratorMain { if(testAgainstModel) { double max = 0.0; double is = 0.0; - for(GeneratorInterface other : clusters) { + for(GeneratorInterface other : generators) { double d = other.getDensity(p) * other.getSize(); if(other == curclus) { is = d; @@ -143,66 +142,6 @@ public class GeneratorMain { } /** - * Write the resulting clusters to an output stream. - * - * @param outStream output stream - * @throws IOException thrown on write errors - */ - public void writeClusters(OutputStreamWriter outStream) throws IOException { - // compute global discard values - int totalsize = 0; - int totaldisc = 0; - assert (clusters.size() > 0); - for(GeneratorInterface curclus : clusters) { - totalsize = totalsize + curclus.getSize(); - if(curclus instanceof GeneratorSingleCluster) { - totaldisc = totaldisc + ((GeneratorSingleCluster) curclus).getDiscarded(); - } - } - double globdens = (double) (totalsize + totaldisc) / totalsize; - outStream.write("########################################################" + LINE_SEPARATOR); - outStream.write("## Number of clusters: " + clusters.size() + LINE_SEPARATOR); - for(GeneratorInterface curclus : clusters) { - outStream.write("########################################################" + LINE_SEPARATOR); - outStream.write("## Cluster: " + curclus.getName() + LINE_SEPARATOR); - outStream.write("########################################################" + LINE_SEPARATOR); - outStream.write("## Size: " + curclus.getSize() + LINE_SEPARATOR); - if(curclus instanceof GeneratorSingleCluster) { - GeneratorSingleCluster cursclus = (GeneratorSingleCluster) curclus; - Vector cmin = cursclus.getClipmin(); - Vector cmax = cursclus.getClipmax(); - if(cmin != null && cmax != null) { - outStream.write("## Clipping: " + cmin.toString() + " - " + cmax.toString() + LINE_SEPARATOR); - } - outStream.write("## Density correction factor: " + cursclus.getDensityCorrection() + LINE_SEPARATOR); - outStream.write("## Generators:" + LINE_SEPARATOR); - for(Distribution gen : cursclus.getAxes()) { - outStream.write("## " + gen.toString() + LINE_SEPARATOR); - } - if(cursclus.getTrans() != null && cursclus.getTrans().getTransformation() != null) { - outStream.write("## Affine transformation matrix:" + LINE_SEPARATOR); - outStream.write(FormatUtil.format(cursclus.getTrans().getTransformation(), "## ") + LINE_SEPARATOR); - } - } - if(curclus instanceof GeneratorInterfaceDynamic) { - GeneratorSingleCluster cursclus = (GeneratorSingleCluster) curclus; - outStream.write("## Discards: " + cursclus.getDiscarded() + " Retries left: " + cursclus.getRetries() + LINE_SEPARATOR); - double corf = /* cursclus.overweight */(double) (cursclus.getSize() + cursclus.getDiscarded()) / cursclus.getSize() / globdens; - outStream.write("## Density correction factor estimation: " + corf + LINE_SEPARATOR); - - } - outStream.write("########################################################" + LINE_SEPARATOR); - for(Vector p : curclus.getPoints()) { - for(int i = 0; i < p.getRowDimensionality(); i++) { - outStream.write(p.get(i) + " "); - } - outStream.write(curclus.getName()); - outStream.write(LINE_SEPARATOR); - } - } - } - - /** * Return value of the {@link #testAgainstModel} flag * * @return value of testAgainstModel @@ -219,4 +158,36 @@ public class GeneratorMain { public void setTestAgainstModel(boolean testAgainstModel) { this.testAgainstModel = testAgainstModel; } -} + + /** + * Access the generators. + * + * @return generators + */ + public List<GeneratorInterface> getGenerators() { + return Collections.unmodifiableList(generators); + } + + /** + * Get the objects bundle + * + * @return Bundle + */ + public MultipleObjectsBundle getBundle() { + final int dim = generators.get(0).getDim(); + final DoubleVector factory = new DoubleVector(new double[dim]); + MultipleObjectsBundle bundle = new MultipleObjectsBundle(); + VectorFieldTypeInformation<DoubleVector> type = new VectorFieldTypeInformation<DoubleVector>(DoubleVector.class, dim, factory); + bundle.appendColumn(type, new ArrayList<Object>()); + bundle.appendColumn(TypeUtil.CLASSLABEL, new ArrayList<Object>()); + + for(GeneratorInterface generator : generators) { + ClassLabel l = new SimpleClassLabel(generator.getName()); + for(Vector v : generator.getPoints()) { + DoubleVector dv = new DoubleVector(v); + bundle.appendSimple(dv, l); + } + } + return bundle; + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/datasource/DatabaseConnection.java b/src/de/lmu/ifi/dbs/elki/datasource/DatabaseConnection.java index 2900ab17..72b54f27 100644 --- a/src/de/lmu/ifi/dbs/elki/datasource/DatabaseConnection.java +++ b/src/de/lmu/ifi/dbs/elki/datasource/DatabaseConnection.java @@ -36,6 +36,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable; * * @author Arthur Zimek * + * @apiviz.landmark * @apiviz.has MultipleObjectsBundle */ public interface DatabaseConnection extends Parameterizable { diff --git a/src/de/lmu/ifi/dbs/elki/datasource/ExternalIDJoinDatabaseConnection.java b/src/de/lmu/ifi/dbs/elki/datasource/ExternalIDJoinDatabaseConnection.java index 9bad2941..aa777ca1 100644 --- a/src/de/lmu/ifi/dbs/elki/datasource/ExternalIDJoinDatabaseConnection.java +++ b/src/de/lmu/ifi/dbs/elki/datasource/ExternalIDJoinDatabaseConnection.java @@ -44,6 +44,8 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectListParamet * Joins multiple data sources by their label * * @author Erich Schubert + * + * @apiviz.uses ExternalID */ public class ExternalIDJoinDatabaseConnection extends AbstractDatabaseConnection implements Parameterizable { /** @@ -96,12 +98,12 @@ public class ExternalIDJoinDatabaseConnection extends AbstractDatabaseConnection for(int i = 0; i < first.dataLength(); i++) { ExternalID data = (ExternalID) first.data(i, lblcol); if(data == null) { - logger.warning("Object without ID encountered."); + logger.debug("Object without ID encountered."); continue; } Integer old = labelmap.put(data, i); if(old != null) { - logger.warning("Duplicate id encountered: " + data + " in rows " + old + " and " + i); + logger.debug("Duplicate id encountered: " + data + " in rows " + old + " and " + i); } } } @@ -153,7 +155,7 @@ public class ExternalIDJoinDatabaseConnection extends AbstractDatabaseConnection } Integer row = labelmap.get(data); if(row == null) { - logger.warning("ID not found for join: " + data + " in row " + i); + logger.debug("ID not found for join: " + data + " in row " + i); continue; } for(int d = 0; d < cur.metaLength(); d++) { diff --git a/src/de/lmu/ifi/dbs/elki/datasource/FileBasedDatabaseConnection.java b/src/de/lmu/ifi/dbs/elki/datasource/FileBasedDatabaseConnection.java index 168a85e4..39c6d2a2 100644 --- a/src/de/lmu/ifi/dbs/elki/datasource/FileBasedDatabaseConnection.java +++ b/src/de/lmu/ifi/dbs/elki/datasource/FileBasedDatabaseConnection.java @@ -40,6 +40,8 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.FileParameter; * Provides a file based database connection based on the parser to be set. * * @author Arthur Zimek + * + * @apiviz.landmark */ public class FileBasedDatabaseConnection extends InputStreamDatabaseConnection { /** diff --git a/src/de/lmu/ifi/dbs/elki/datasource/GeneratorXMLDatabaseConnection.java b/src/de/lmu/ifi/dbs/elki/datasource/GeneratorXMLDatabaseConnection.java new file mode 100644 index 00000000..40e4d5af --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/datasource/GeneratorXMLDatabaseConnection.java @@ -0,0 +1,636 @@ +package de.lmu.ifi.dbs.elki.datasource; +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2011 + 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 <http://www.gnu.org/licenses/>. + */ + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.LinkedList; +import java.util.Random; +import java.util.regex.Pattern; + +import javax.xml.XMLConstants; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.xml.sax.SAXException; + +import de.lmu.ifi.dbs.elki.application.GeneratorXMLSpec; +import de.lmu.ifi.dbs.elki.data.synthetic.bymodel.GeneratorMain; +import de.lmu.ifi.dbs.elki.data.synthetic.bymodel.GeneratorSingleCluster; +import de.lmu.ifi.dbs.elki.data.synthetic.bymodel.GeneratorStatic; +import de.lmu.ifi.dbs.elki.data.synthetic.bymodel.distribution.Distribution; +import de.lmu.ifi.dbs.elki.data.synthetic.bymodel.distribution.GammaDistribution; +import de.lmu.ifi.dbs.elki.data.synthetic.bymodel.distribution.NormalDistribution; +import de.lmu.ifi.dbs.elki.data.synthetic.bymodel.distribution.UniformDistribution; +import de.lmu.ifi.dbs.elki.datasource.bundle.MultipleObjectsBundle; +import de.lmu.ifi.dbs.elki.logging.Logging; +import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector; +import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException; +import de.lmu.ifi.dbs.elki.utilities.exceptions.UnableToComplyException; +import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer; +import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID; +import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization; +import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.DoubleParameter; +import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.FileParameter; +import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter; +import de.lmu.ifi.dbs.elki.utilities.xml.XMLNodeIterator; + +public class GeneratorXMLDatabaseConnection implements DatabaseConnection { + /** + * Logger + */ + private static Logging logger = Logging.getLogger(GeneratorXMLDatabaseConnection.class); + + /** + * A pattern defining whitespace. + */ + public static final Pattern WHITESPACE_PATTERN = Pattern.compile("\\s+"); + + /** + * Parameter to give the configuration file + */ + public static final OptionID CONFIGFILE_ID = OptionID.getOrCreateOptionID("bymodel.spec", "The generator specification file."); + + /** + * Parameter to give the configuration file + */ + public static final OptionID RANDOMSEED_ID = OptionID.getOrCreateOptionID("bymodel.randomseed", "The random generator seed."); + + /** + * Parameter to give the configuration file + */ + public static final OptionID SIZE_SCALE_ID = OptionID.getOrCreateOptionID("bymodel.sizescale", "Factor for scaling the specified cluster sizes."); + + /** + * File name of the generators XML Schema file. + */ + private static final String GENERATOR_SCHEMA_FILE = GeneratorXMLSpec.class.getPackage().getName().replace('.', '/') + '/' + "GeneratorByModel.xsd"; + + /** + * The configuration file. + */ + File specfile; + + /** + * Parameter for scaling the cluster sizes. + */ + double sizescale = 1.0; + + /** + * The actual generator class + */ + public GeneratorMain gen = new GeneratorMain(); + + /** + * Random generator used for initializing cluster generators. + */ + private Random clusterRandom = null; + + /** + * Set testAgainstModel flag + */ + private boolean testAgainstModel = true; + + /** + * Constructor. + * + * @param specfile Specification file + * @param sizescale Size scaling + * @param clusterRandom Random number generator + */ + public GeneratorXMLDatabaseConnection(File specfile, double sizescale, Random clusterRandom) { + super(); + this.specfile = specfile; + this.sizescale = sizescale; + this.clusterRandom = clusterRandom; + if(this.clusterRandom == null) { + this.clusterRandom = new Random(); + } + } + + @Override + public MultipleObjectsBundle loadData() { + if(logger.isVerbose()) { + logger.verbose("Loading specification ..."); + } + try { + loadXMLSpecification(); + } + catch(UnableToComplyException e) { + throw new AbortException("Cannot load XML specification", e); + } + if(logger.isVerbose()) { + logger.verbose("Generating clusters ..."); + } + gen.setTestAgainstModel(testAgainstModel); + try { + gen.generate(); + return gen.getBundle(); + } + catch(UnableToComplyException e) { + throw new AbortException("Data generation failed. ", e); + } + } + + /** + * Load the XML configuration file. + * + * @throws UnableToComplyException + */ + private void loadXMLSpecification() throws UnableToComplyException { + try { + InputStream in = new FileInputStream(specfile); + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); + URL url = ClassLoader.getSystemResource(GENERATOR_SCHEMA_FILE); + if(url != null) { + try { + Schema schema = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI).newSchema(url); + dbf.setSchema(schema); + dbf.setIgnoringElementContentWhitespace(true); + } + catch(Exception e) { + logger.warning("Could not set up XML Schema validation for speciciation file."); + } + } + else { + logger.warning("Could not set up XML Schema validation for speciciation file."); + } + Document doc = dbf.newDocumentBuilder().parse(in); + Node root = doc.getDocumentElement(); + if(root.getNodeName() == "dataset") { + processElementDataset(root); + } + else { + throw new UnableToComplyException("Experiment specification has incorrect document element: " + root.getNodeName()); + } + } + catch(FileNotFoundException e) { + throw new UnableToComplyException("Can't open specification file.", e); + } + catch(SAXException e) { + throw new UnableToComplyException("Error parsing specification file.", e); + } + catch(IOException e) { + throw new UnableToComplyException("IO Exception loading specification file.", e); + } + catch(ParserConfigurationException e) { + throw new UnableToComplyException("Parser Configuration Error", e); + } + } + + /** + * Process a 'dataset' Element in the XML stream. + * + * @param cur Current document nod + * @throws UnableToComplyException + */ + private void processElementDataset(Node cur) throws UnableToComplyException { + // *** get parameters + String seedstr = ((Element) cur).getAttribute("random-seed"); + if(seedstr != null && seedstr != "") { + clusterRandom = new Random((int) (Integer.valueOf(seedstr) * sizescale)); + } + String testmod = ((Element) cur).getAttribute("test-model"); + if(testmod != null && testmod != "") { + testAgainstModel = (Integer.valueOf(testmod) != 0); + } + // TODO: check for unknown attributes. + for(Node child : new XMLNodeIterator(cur.getFirstChild())) { + if(child.getNodeName() == "cluster") { + processElementCluster(child); + } + else if(child.getNodeName() == "static") { + processElementStatic(child); + } + else if(child.getNodeType() == Node.ELEMENT_NODE) { + logger.warning("Unknown element in XML specification file: " + child.getNodeName()); + } + } + } + + /** + * Process a 'cluster' Element in the XML stream. + * + * @param cur Current document nod + * @throws UnableToComplyException + */ + private void processElementCluster(Node cur) throws UnableToComplyException { + int size = -1; + double overweight = 1.0; + + String sizestr = ((Element) cur).getAttribute("size"); + if(sizestr != null && sizestr != "") { + size = (int) (Integer.valueOf(sizestr) * sizescale); + } + + String name = ((Element) cur).getAttribute("name"); + + String dcostr = ((Element) cur).getAttribute("density-correction"); + if(dcostr != null && dcostr != "") { + overweight = Double.valueOf(dcostr); + } + + if(size < 0) { + throw new UnableToComplyException("No valid cluster size given in specification file."); + } + if(name == null || name == "") { + throw new UnableToComplyException("No cluster name given in specification file."); + } + + // *** add new cluster object + Random newRand = new Random(clusterRandom.nextLong()); + GeneratorSingleCluster cluster = new GeneratorSingleCluster(name, size, overweight, newRand); + + // TODO: check for unknown attributes. + for(Node child : new XMLNodeIterator(cur.getFirstChild())) { + if(child.getNodeName() == "uniform") { + processElementUniform(cluster, child); + } + else if(child.getNodeName() == "normal") { + processElementNormal(cluster, child); + } + else if(child.getNodeName() == "gamma") { + processElementGamma(cluster, child); + } + else if(child.getNodeName() == "rotate") { + processElementRotate(cluster, child); + } + else if(child.getNodeName() == "translate") { + processElementTranslate(cluster, child); + } + else if(child.getNodeName() == "clip") { + processElementClipping(cluster, child); + } + else if(child.getNodeType() == Node.ELEMENT_NODE) { + logger.warning("Unknown element in XML specification file: " + child.getNodeName()); + } + } + + gen.addCluster(cluster); + } + + /** + * Process a 'uniform' Element in the XML stream. + * + * @param cluster + * @param cur Current document nod + * @throws UnableToComplyException + */ + private void processElementUniform(GeneratorSingleCluster cluster, Node cur) throws UnableToComplyException { + double min = 0.0; + double max = 1.0; + + String minstr = ((Element) cur).getAttribute("min"); + if(minstr != null && minstr != "") { + min = Double.valueOf(minstr); + } + String maxstr = ((Element) cur).getAttribute("max"); + if(maxstr != null && maxstr != "") { + max = Double.valueOf(maxstr); + } + + // *** new uniform generator + Random random = cluster.getNewRandomGenerator(); + Distribution generator = new UniformDistribution(min, max, random); + cluster.addGenerator(generator); + + // TODO: check for unknown attributes. + for(Node child : new XMLNodeIterator(cur.getFirstChild())) { + if(child.getNodeType() == Node.ELEMENT_NODE) { + logger.warning("Unknown element in XML specification file: " + child.getNodeName()); + } + } + } + + /** + * Process a 'normal' Element in the XML stream. + * + * @param cluster + * @param cur Current document nod + * @throws UnableToComplyException + */ + private void processElementNormal(GeneratorSingleCluster cluster, Node cur) throws UnableToComplyException { + double mean = 0.0; + double stddev = 1.0; + String meanstr = ((Element) cur).getAttribute("mean"); + if(meanstr != null && meanstr != "") { + mean = Double.valueOf(meanstr); + } + String stddevstr = ((Element) cur).getAttribute("stddev"); + if(stddevstr != null && stddevstr != "") { + stddev = Double.valueOf(stddevstr); + } + + // *** New normal distribution generator + Random random = cluster.getNewRandomGenerator(); + Distribution generator = new NormalDistribution(mean, stddev, random); + cluster.addGenerator(generator); + + // TODO: check for unknown attributes. + for(Node child : new XMLNodeIterator(cur.getFirstChild())) { + if(child.getNodeType() == Node.ELEMENT_NODE) { + logger.warning("Unknown element in XML specification file: " + child.getNodeName()); + } + } + } + + /** + * Process a 'gamma' Element in the XML stream. + * + * @param cluster + * @param cur Current document nod + * @throws UnableToComplyException + */ + private void processElementGamma(GeneratorSingleCluster cluster, Node cur) throws UnableToComplyException { + double k = 1.0; + double theta = 1.0; + String kstr = ((Element) cur).getAttribute("k"); + if(kstr != null && kstr != "") { + k = Double.valueOf(kstr); + } + String thetastr = ((Element) cur).getAttribute("theta"); + if(thetastr != null && thetastr != "") { + theta = Double.valueOf(thetastr); + } + + // *** New normal distribution generator + Random random = cluster.getNewRandomGenerator(); + Distribution generator = new GammaDistribution(k, theta, random); + cluster.addGenerator(generator); + + // TODO: check for unknown attributes. + for(Node child : new XMLNodeIterator(cur.getFirstChild())) { + if(child.getNodeType() == Node.ELEMENT_NODE) { + logger.warning("Unknown element in XML specification file: " + child.getNodeName()); + } + } + } + + /** + * Process a 'rotate' Element in the XML stream. + * + * @param cluster + * @param cur Current document nod + * @throws UnableToComplyException + */ + private void processElementRotate(GeneratorSingleCluster cluster, Node cur) throws UnableToComplyException { + int axis1 = 0; + int axis2 = 0; + double angle = 0.0; + + String a1str = ((Element) cur).getAttribute("axis1"); + if(a1str != null && a1str != "") { + axis1 = Integer.valueOf(a1str); + } + String a2str = ((Element) cur).getAttribute("axis2"); + if(a2str != null && a2str != "") { + axis2 = Integer.valueOf(a2str); + } + String anstr = ((Element) cur).getAttribute("angle"); + if(anstr != null && anstr != "") { + angle = Double.valueOf(anstr); + } + if(axis1 <= 0 || axis1 > cluster.getDim()) { + throw new UnableToComplyException("Invalid axis1 number given in specification file."); + } + if(axis1 <= 0 || axis1 > cluster.getDim()) { + throw new UnableToComplyException("Invalid axis2 number given in specification file."); + } + if(axis1 == axis2) { + throw new UnableToComplyException("Invalid axis numbers given in specification file."); + } + + // Add rotation to cluster. + cluster.addRotation(axis1 - 1, axis2 - 1, Math.toRadians(angle)); + + // TODO: check for unknown attributes. + for(Node child : new XMLNodeIterator(cur.getFirstChild())) { + if(child.getNodeType() == Node.ELEMENT_NODE) { + logger.warning("Unknown element in XML specification file: " + child.getNodeName()); + } + } + } + + /** + * Process a 'translate' Element in the XML stream. + * + * @param cluster + * @param cur Current document nod + * @throws UnableToComplyException + */ + private void processElementTranslate(GeneratorSingleCluster cluster, Node cur) throws UnableToComplyException { + Vector offset = null; + String vstr = ((Element) cur).getAttribute("vector"); + if(vstr != null && vstr != "") { + offset = parseVector(vstr); + } + if(offset == null) { + throw new UnableToComplyException("No translation vector given."); + } + + // *** add new translation + cluster.addTranslation(offset); + + // TODO: check for unknown attributes. + for(Node child : new XMLNodeIterator(cur.getFirstChild())) { + if(child.getNodeType() == Node.ELEMENT_NODE) { + logger.warning("Unknown element in XML specification file: " + child.getNodeName()); + } + } + } + + /** + * Process a 'clipping' Element in the XML stream. + * + * @param cluster + * @param cur Current document nod + * @throws UnableToComplyException + */ + private void processElementClipping(GeneratorSingleCluster cluster, Node cur) throws UnableToComplyException { + Vector cmin = null; + Vector cmax = null; + + String minstr = ((Element) cur).getAttribute("min"); + if(minstr != null && minstr != "") { + cmin = parseVector(minstr); + } + String maxstr = ((Element) cur).getAttribute("max"); + if(maxstr != null && maxstr != "") { + cmax = parseVector(maxstr); + } + if(cmin == null || cmax == null) { + throw new UnableToComplyException("No or incomplete clipping vectors given."); + } + + // *** set clipping + cluster.setClipping(cmin, cmax); + + // TODO: check for unknown attributes. + for(Node child : new XMLNodeIterator(cur.getFirstChild())) { + if(child.getNodeType() == Node.ELEMENT_NODE) { + logger.warning("Unknown element in XML specification file: " + child.getNodeName()); + } + } + } + + /** + * Process a 'static' cluster Element in the XML stream. + * + * @param cur Current document nod + * @throws UnableToComplyException + */ + private void processElementStatic(Node cur) throws UnableToComplyException { + String name = ((Element) cur).getAttribute("name"); + if(name == null) { + throw new UnableToComplyException("No cluster name given in specification file."); + } + + LinkedList<Vector> points = new LinkedList<Vector>(); + // TODO: check for unknown attributes. + for(Node child : new XMLNodeIterator(cur.getFirstChild())) { + if(child.getNodeName() == "point") { + processElementPoint(points, child); + } + else if(child.getNodeType() == Node.ELEMENT_NODE) { + logger.warning("Unknown element in XML specification file: " + child.getNodeName()); + } + } + // *** add new cluster object + GeneratorStatic cluster = new GeneratorStatic(name, points); + + gen.addCluster(cluster); + if(logger.isVerbose()) { + logger.verbose("Loaded cluster " + cluster.name + " from specification."); + } + } + + /** + * Parse a 'point' element (point vector for a static cluster) + * + * @param points current list of points (to append to) + * @param cur Current document nod + * @throws UnableToComplyException + */ + private void processElementPoint(LinkedList<Vector> points, Node cur) throws UnableToComplyException { + Vector point = null; + String vstr = ((Element) cur).getAttribute("vector"); + if(vstr != null && vstr != "") { + point = parseVector(vstr); + } + if(point == null) { + throw new UnableToComplyException("No translation vector given."); + } + + // *** add new point + points.add(point); + + // TODO: check for unknown attributes. + for(Node child : new XMLNodeIterator(cur.getFirstChild())) { + if(child.getNodeType() == Node.ELEMENT_NODE) { + logger.warning("Unknown element in XML specification file: " + child.getNodeName()); + } + } + } + + /** + * Parse a string into a vector. + * + * TODO: move this into utility package? + * + * @param s String to parse + * @return Vector + * @throws UnableToComplyException + */ + private Vector parseVector(String s) throws UnableToComplyException { + String[] entries = WHITESPACE_PATTERN.split(s); + double[] d = new double[entries.length]; + for(int i = 0; i < entries.length; i++) { + try { + d[i] = Double.valueOf(entries[i]); + } + catch(NumberFormatException e) { + throw new UnableToComplyException("Could not parse vector."); + } + } + return new Vector(d); + } + + /** + * Parameterization class. + * + * @author Erich Schubert + * + * @apiviz.exclude + */ + public static class Parameterizer extends AbstractParameterizer { + /** + * The configuration file. + */ + File specfile = null; + + /** + * Parameter for scaling the cluster sizes. + */ + double sizescale = 1.0; + + /** + * Random generator used for initializing cluster generators. + */ + private Random clusterRandom = null; + + @Override + protected void makeOptions(Parameterization config) { + super.makeOptions(config); + // Specification file + final FileParameter cfgparam = new FileParameter(CONFIGFILE_ID, FileParameter.FileType.INPUT_FILE); + if(config.grab(cfgparam)) { + specfile = cfgparam.getValue(); + } + // Cluster size scaling + final DoubleParameter scalepar = new DoubleParameter(SIZE_SCALE_ID, 1.0); + if(config.grab(scalepar)) { + sizescale = scalepar.getValue(); + } + // Random generator + final IntParameter seedpar = new IntParameter(RANDOMSEED_ID, true); + if(config.grab(seedpar)) { + clusterRandom = new Random(seedpar.getValue()); + } + } + + @Override + protected GeneratorXMLDatabaseConnection makeInstance() { + return new GeneratorXMLDatabaseConnection(specfile, sizescale, clusterRandom); + } + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/datasource/LabelJoinDatabaseConnection.java b/src/de/lmu/ifi/dbs/elki/datasource/LabelJoinDatabaseConnection.java index b91ccb80..b34566ae 100644 --- a/src/de/lmu/ifi/dbs/elki/datasource/LabelJoinDatabaseConnection.java +++ b/src/de/lmu/ifi/dbs/elki/datasource/LabelJoinDatabaseConnection.java @@ -44,6 +44,8 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectListParamet * Joins multiple data sources by their label * * @author Erich Schubert + * + * @apiviz.uses LabelList */ public class LabelJoinDatabaseConnection extends AbstractDatabaseConnection implements Parameterizable { /** diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/AttributeWiseErfNormalization.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/AttributeWiseErfNormalization.java index e2f99d35..d365a9ae 100644 --- a/src/de/lmu/ifi/dbs/elki/datasource/filter/AttributeWiseErfNormalization.java +++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/AttributeWiseErfNormalization.java @@ -35,6 +35,8 @@ import de.lmu.ifi.dbs.elki.math.MathUtil; * @author Erich Schubert * * @param <O> Object type + * + * @apiviz.uses NumberVector */ public class AttributeWiseErfNormalization<O extends NumberVector<O, ?>> extends AbstractNormalization<O> { /** diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/AttributeWiseMinMaxNormalization.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/AttributeWiseMinMaxNormalization.java index f2fe02c0..d9a636ec 100644 --- a/src/de/lmu/ifi/dbs/elki/datasource/filter/AttributeWiseMinMaxNormalization.java +++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/AttributeWiseMinMaxNormalization.java @@ -47,6 +47,8 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.Parameter; * * @author Elke Achtert * @param <V> vector type + * + * @apiviz.uses NumberVector */ // TODO: extract superclass AbstractAttributeWiseNormalization public class AttributeWiseMinMaxNormalization<V extends NumberVector<V, ?>> extends AbstractNormalization<V> { diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/AttributeWiseVarianceNormalization.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/AttributeWiseVarianceNormalization.java index 837f3ec5..3ae2fdad 100644 --- a/src/de/lmu/ifi/dbs/elki/datasource/filter/AttributeWiseVarianceNormalization.java +++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/AttributeWiseVarianceNormalization.java @@ -50,6 +50,8 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.Parameter; * * @author Erich Schubert * @param <V> vector type + * + * @apiviz.uses NumberVector */ // TODO: extract superclass AbstractAttributeWiseNormalization public class AttributeWiseVarianceNormalization<V extends NumberVector<V, ?>> extends AbstractNormalization<V> { diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/ClassLabelFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/ClassLabelFilter.java index ce79d612..1c9a2274 100644 --- a/src/de/lmu/ifi/dbs/elki/datasource/filter/ClassLabelFilter.java +++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/ClassLabelFilter.java @@ -45,6 +45,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter; * * @author Erich Schubert * + * @apiviz.uses LabelList oneway - - «reads» * @apiviz.has ClassLabel */ public class ClassLabelFilter implements ObjectFilter { @@ -74,18 +75,18 @@ public class ClassLabelFilter implements ObjectFilter { /** * The class label class to use. */ - private final Class<? extends ClassLabel> classLabelClass; + private final ClassLabel.Factory<?> classLabelFactory; /** * Constructor. * * @param classLabelIndex The index to convert - * @param classLabelClass The class label class to use + * @param classLabelFactory The class label factory to use */ - public ClassLabelFilter(int classLabelIndex, Class<? extends ClassLabel> classLabelClass) { + public ClassLabelFilter(int classLabelIndex, ClassLabel.Factory<?> classLabelFactory) { super(); this.classLabelIndex = classLabelIndex; - this.classLabelClass = classLabelClass; + this.classLabelFactory = classLabelFactory; } @Override @@ -112,8 +113,7 @@ public class ClassLabelFilter implements ObjectFilter { if(obj != null) { LabelList ll = (LabelList) obj; try { - ClassLabel lbl = classLabelClass.newInstance(); - lbl.init(ll.remove(classLabelIndex)); + ClassLabel lbl = classLabelFactory.makeFromString(ll.remove(classLabelIndex)); clscol.add(lbl); } catch(Exception e) { @@ -153,28 +153,28 @@ public class ClassLabelFilter implements ObjectFilter { protected Integer classLabelIndex; /** - * The class label class to use. + * The class label factory to use. */ - private Class<? extends ClassLabel> classLabelClass; + private ClassLabel.Factory<?> classLabelFactory; @Override protected void makeOptions(Parameterization config) { super.makeOptions(config); // parameter class label index final IntParameter classLabelIndexParam = new IntParameter(CLASS_LABEL_INDEX_ID, new GreaterEqualConstraint(0)); - final ObjectParameter<ClassLabel> classlabelClassParam = new ObjectParameter<ClassLabel>(CLASS_LABEL_CLASS_ID, ClassLabel.class, SimpleClassLabel.class); + final ObjectParameter<ClassLabel.Factory<?>> classlabelClassParam = new ObjectParameter<ClassLabel.Factory<?>>(CLASS_LABEL_CLASS_ID, ClassLabel.Factory.class, SimpleClassLabel.Factory.class); config.grab(classLabelIndexParam); config.grab(classlabelClassParam); if(classLabelIndexParam.isDefined() && classlabelClassParam.isDefined()) { classLabelIndex = classLabelIndexParam.getValue(); - classLabelClass = classlabelClassParam.getValue(); + classLabelFactory = classlabelClassParam.instantiateClass(config); } } @Override protected Object makeInstance() { - return new ClassLabelFilter(classLabelIndex, classLabelClass); + return new ClassLabelFilter(classLabelIndex, classLabelFactory); } } }
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/DoubleVectorProjectionFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/DoubleVectorProjectionFilter.java index d7aaf843..21b00b0d 100644 --- a/src/de/lmu/ifi/dbs/elki/datasource/filter/DoubleVectorProjectionFilter.java +++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/DoubleVectorProjectionFilter.java @@ -36,6 +36,8 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameteriz * onto a selected subset of attributes.</p>
*
* @author Arthur Zimek
+ *
+ * @apiviz.uses DoubleVector
*/
public class DoubleVectorProjectionFilter extends AbstractFeatureSelectionFilter<DoubleVector> {
/**
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/DoubleVectorRandomProjectionFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/DoubleVectorRandomProjectionFilter.java index 1fe7c1a9..802b00d6 100644 --- a/src/de/lmu/ifi/dbs/elki/datasource/filter/DoubleVectorRandomProjectionFilter.java +++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/DoubleVectorRandomProjectionFilter.java @@ -36,6 +36,8 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameteriz * </p>
*
* @author Arthur Zimek
+ *
+ * @apiviz.uses DoubleVector
*/
public class DoubleVectorRandomProjectionFilter extends AbstractRandomFeatureSelectionFilter<DoubleVector> {
/**
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/ExternalIDFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/ExternalIDFilter.java index 16933d4d..c53c2e4d 100644 --- a/src/de/lmu/ifi/dbs/elki/datasource/filter/ExternalIDFilter.java +++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/ExternalIDFilter.java @@ -41,6 +41,9 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter; * Class that turns a label column into an external ID column. * * @author Erich Schubert + * + * @apiviz.uses LabelList oneway - - «reads» + * @apiviz.has ExternalID oneway - - «produces» */ // TODO: use a non-string class for external ids? public class ExternalIDFilter implements ObjectFilter { diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/FilterByLabelFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/FilterByLabelFilter.java index 58c1d509..b950080d 100644 --- a/src/de/lmu/ifi/dbs/elki/datasource/filter/FilterByLabelFilter.java +++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/FilterByLabelFilter.java @@ -40,6 +40,8 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.PatternParameter; * A filter to sort the data set by some label. * * @author Erich Schubert + * + * @apiviz.uses LabelList oneway - - «reads» */ public class FilterByLabelFilter implements ObjectFilter { /** diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/FixedDBIDsFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/FixedDBIDsFilter.java index eda4b9ee..b49494e4 100644 --- a/src/de/lmu/ifi/dbs/elki/datasource/filter/FixedDBIDsFilter.java +++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/FixedDBIDsFilter.java @@ -41,7 +41,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter; * * @author Erich Schubert * - * @apiviz.uses DBID + * @apiviz.has DBID oneway - - «produces» */ public class FixedDBIDsFilter implements ObjectFilter { /** diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/InverseDocumentFrequencyNormalization.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/InverseDocumentFrequencyNormalization.java index 3b6e69c0..d8ffd71c 100644 --- a/src/de/lmu/ifi/dbs/elki/datasource/filter/InverseDocumentFrequencyNormalization.java +++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/InverseDocumentFrequencyNormalization.java @@ -37,6 +37,8 @@ import de.lmu.ifi.dbs.elki.data.type.TypeUtil; * frequency. * * @author Erich Schubert + * + * @apiviz.uses SparseFloatVector */ public class InverseDocumentFrequencyNormalization extends AbstractNormalization<SparseFloatVector> { /** diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/Normalization.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/Normalization.java index c21c7603..417c4456 100644 --- a/src/de/lmu/ifi/dbs/elki/datasource/filter/Normalization.java +++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/Normalization.java @@ -36,6 +36,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable; * * @author Arthur Zimek * + * @apiviz.landmark * @apiviz.has NonNumericFeaturesException * * @param <O> object type diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/SortByLabelFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/SortByLabelFilter.java index 0f633ad3..74bbe3ac 100644 --- a/src/de/lmu/ifi/dbs/elki/datasource/filter/SortByLabelFilter.java +++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/SortByLabelFilter.java @@ -36,6 +36,8 @@ import de.lmu.ifi.dbs.elki.logging.Logging; * A filter to sort the data set by some label. * * @author Erich Schubert + * + * @apiviz.uses de.lmu.ifi.dbs.elki.data.LabelList oneway - - «reads» */ public class SortByLabelFilter implements ObjectFilter { /** diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/SplitNumberVectorFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/SplitNumberVectorFilter.java index 0ad8b5cc..25ab7e89 100644 --- a/src/de/lmu/ifi/dbs/elki/datasource/filter/SplitNumberVectorFilter.java +++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/SplitNumberVectorFilter.java @@ -42,6 +42,8 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntListParameter; * Split an existing column into two types. * * @author Erich Schubert + * + * @apiviz.uses NumberVector */ public class SplitNumberVectorFilter<V extends NumberVector<V, ?>> implements ObjectFilter { /** diff --git a/src/de/lmu/ifi/dbs/elki/datasource/parser/ArffParser.java b/src/de/lmu/ifi/dbs/elki/datasource/parser/ArffParser.java index 9710b493..847349f2 100644 --- a/src/de/lmu/ifi/dbs/elki/datasource/parser/ArffParser.java +++ b/src/de/lmu/ifi/dbs/elki/datasource/parser/ArffParser.java @@ -1,4 +1,5 @@ package de.lmu.ifi.dbs.elki.datasource.parser; + /* This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures @@ -28,6 +29,11 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.StreamTokenizer; import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.TreeMap; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -36,6 +42,7 @@ import de.lmu.ifi.dbs.elki.data.DoubleVector; import de.lmu.ifi.dbs.elki.data.ExternalID; import de.lmu.ifi.dbs.elki.data.LabelList; import de.lmu.ifi.dbs.elki.data.SimpleClassLabel; +import de.lmu.ifi.dbs.elki.data.SparseFloatVector; import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation; import de.lmu.ifi.dbs.elki.data.type.TypeInformation; import de.lmu.ifi.dbs.elki.data.type.TypeUtil; @@ -43,6 +50,10 @@ import de.lmu.ifi.dbs.elki.data.type.VectorFieldTypeInformation; import de.lmu.ifi.dbs.elki.datasource.bundle.MultipleObjectsBundle; import de.lmu.ifi.dbs.elki.logging.Logging; import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException; +import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer; +import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID; +import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization; +import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.PatternParameter; /** * Parser to load WEKA .arff files into ELKI. @@ -83,12 +94,12 @@ public class ArffParser implements Parser { /** * Pattern to auto-convert columns to external ids. */ - public static final Pattern ARFF_MAGIC_EID = Pattern.compile("(ID|External-?ID)", Pattern.CASE_INSENSITIVE); + public static final String DEFAULT_ARFF_MAGIC_EID = "(ID|External-?ID)"; /** * Pattern to auto-convert columns to class labels. */ - public static final Pattern ARFF_MAGIC_CLASS = Pattern.compile("(Class|Class-?Label)", Pattern.CASE_INSENSITIVE); + public static final String DEFAULT_ARFF_MAGIC_CLASS = "(Class|Class-?Label)"; /** * Pattern for numeric columns @@ -100,250 +111,472 @@ public class ArffParser implements Parser { */ public static final Pattern EMPTY = Pattern.compile("^\\s*$"); + /** + * Pattern to recognize external ids + */ + Pattern magic_eid; + + /** + * Pattern to recognize class label columns + */ + Pattern magic_class; + + /** + * Constructor. + * + * @param magic_eid Magic to recognize external IDs + * @param magic_class Magic to recognize class labels + */ + public ArffParser(Pattern magic_eid, Pattern magic_class) { + super(); + this.magic_eid = magic_eid; + this.magic_class = magic_class; + } + + /** + * Constructor. + * + * @param magic_eid Magic to recognize external IDs + * @param magic_class Magic to recognize class labels + */ + public ArffParser(String magic_eid, String magic_class) { + this(Pattern.compile(magic_eid, Pattern.CASE_INSENSITIVE), Pattern.compile(magic_class, Pattern.CASE_INSENSITIVE)); + } + @Override public MultipleObjectsBundle parse(InputStream instream) { try { BufferedReader br = new BufferedReader(new InputStreamReader(instream)); - String line; - // Locate header line - while(true) { - line = br.readLine(); - if(line == null) { - throw new AbortException(ARFF_HEADER_RELATION + " not found in file."); - } - // Skip comments and empty lines - if(ARFF_COMMENT.matcher(line).matches() || EMPTY.matcher(line).matches()) { - continue; - } - // Break on relation statement - if(ARFF_HEADER_RELATION.matcher(line).matches()) { - break; - } - throw new AbortException("Expected relation declaration: " + line); - } ArrayList<String> names = new ArrayList<String>(); ArrayList<String> types = new ArrayList<String>(); - // Load attribute metadata - while(true) { - line = br.readLine(); - if(line == null) { - throw new AbortException(ARFF_HEADER_DATA + " not found in file."); - } - // Skip comments and empty lines - if(ARFF_COMMENT.matcher(line).matches() || EMPTY.matcher(line).matches()) { - continue; + + readHeader(br); + parseAttributeStatements(br, names, types); + + // Convert into column mapping. Prepare arrays to fill + int[] targ = new int[names.size()]; + TypeInformation[] elkitypes = new TypeInformation[names.size()]; + int[] dimsize = new int[names.size()]; + processColumnTypes(names, types, targ, elkitypes, dimsize); + + // Prepare bundle: + // This is a bit complicated to produce vector fields. + MultipleObjectsBundle bundle = new MultipleObjectsBundle(); + StreamTokenizer tokenizer = makeArffTokenizer(br); + + int state = 0; + + nextToken(tokenizer); + while(tokenizer.ttype != StreamTokenizer.TT_EOF) { + // Parse instance + if(tokenizer.ttype == StreamTokenizer.TT_EOL) { + // ignore empty lines } - // Break on data statement to continue - if(ARFF_HEADER_DATA.matcher(line).matches()) { - break; + else if(tokenizer.ttype != '{') { + if(state == 0) { + setupBundleHeaders(names, targ, elkitypes, dimsize, bundle, false); + state = 1; // dense + } + if(state != 1) { + throw new AbortException("Mixing dense and sparse vectors is currently not allowed."); + } + // Load a dense instance + bundle.appendSimple(loadDenseInstance(tokenizer, dimsize, elkitypes, bundle.metaLength())); } - // Expect an attribute specification - Matcher matcher = ARFF_HEADER_ATTRIBUTE.matcher(line); - if(matcher.matches()) { - String name = matcher.group(1); - if(name.charAt(0) == '\'' && name.charAt(name.length() - 1) == '\'') { - name = name.substring(1, name.length() - 1); + else { + if(state == 0) { + setupBundleHeaders(names, targ, elkitypes, dimsize, bundle, true); + state = 2; // dense } - else if(name.charAt(0) == '"' && name.charAt(name.length() - 1) == '"') { - name = name.substring(1, name.length() - 1); + if(state != 2) { + throw new AbortException("Mixing dense and sparse vectors is currently not allowed."); } - String type = matcher.group(2); - names.add(name); - types.add(type); - // logger.warning("Attribute name: " + name + " type: " + type); - continue; + bundle.appendSimple(loadSparseInstance(tokenizer, targ, dimsize, elkitypes, bundle.metaLength())); + } + if(tokenizer.ttype != StreamTokenizer.TT_EOF) { + nextToken(tokenizer); } - throw new AbortException("Unrecognized line: " + line); } - assert (names.size() == types.size()); - - int[] targ = new int[names.size()]; - TypeInformation[] etyp = new TypeInformation[names.size()]; - int[] dims = new int[names.size()]; + return bundle; + } + catch(IOException e) { + throw new AbortException("IO error in parser", e); + } + } - int next = 0; - for(int i = 0; i < targ.length; i++) { - // Turn into an external ID column. - if(ARFF_MAGIC_EID.matcher(names.get(i)).matches()) { - targ[i] = next; - etyp[next] = TypeUtil.EXTERNALID; - dims[next] = 1; - next++; - continue; + private Object[] loadSparseInstance(StreamTokenizer tokenizer, int[] targ, int[] dimsize, TypeInformation[] elkitypes, int metaLength) throws IOException { + // logger.warning("Sparse instance."); + Map<Integer, Object> map = new TreeMap<Integer, Object>(); + while(true) { + nextToken(tokenizer); + assert (tokenizer.ttype != StreamTokenizer.TT_EOF && tokenizer.ttype != StreamTokenizer.TT_EOL); + if(tokenizer.ttype == '}') { + nextToken(tokenizer); + assert (tokenizer.ttype == StreamTokenizer.TT_EOF || tokenizer.ttype == StreamTokenizer.TT_EOL); + break; + } + else { + // sparse token + if(tokenizer.ttype != StreamTokenizer.TT_NUMBER) { + throw new AbortException("Unexpected token type encountered: " + tokenizer.toString()); } - else if(ARFF_MAGIC_CLASS.matcher(names.get(i)).matches()) { - targ[i] = next; - etyp[next] = TypeUtil.CLASSLABEL; - dims[next] = 1; - next++; - continue; + int dim = (int) tokenizer.nval; + if(map.containsKey(dim)) { + throw new AbortException("Duplicate key in sparse vector: " + tokenizer.toString()); + } + nextToken(tokenizer); + if(tokenizer.ttype == StreamTokenizer.TT_NUMBER) { + map.put(dim, tokenizer.nval); + } + else if(tokenizer.ttype == StreamTokenizer.TT_WORD) { + map.put(dim, tokenizer.sval); } - else if(ARFF_NUMERIC.matcher(types.get(i)).matches()) { - if(next > 0 && etyp[next - 1] == TypeUtil.NUMBER_VECTOR_FIELD) { - targ[i] = next - 1; - dims[next - 1]++; + else { + throw new AbortException("Unexpected token type encountered: " + tokenizer.toString()); + } + } + } + Object[] data = new Object[metaLength]; + for(int out = 0; out < metaLength; out++) { + // Find the first index + int s = -1; + for(int i = 0; i < targ.length; i++) { + if(targ[i] == out && s < 0) { + s = i; + break; + } + } + assert (s >= 0); + if(elkitypes[out] == TypeUtil.NUMBER_VECTOR_FIELD) { + Map<Integer, Float> f = new HashMap<Integer, Float>(dimsize[out]); + for(Entry<Integer, Object> key : map.entrySet()) { + int i = key.getKey(); + if(i < s) { continue; } - else { - targ[i] = next; - etyp[next] = TypeUtil.NUMBER_VECTOR_FIELD; - dims[next] = 1; - next++; - continue; + if(i >= s + dimsize[out]) { + break; } + double v = (Double) key.getValue(); + f.put(i - s + 1, (float) v); } - else { - if(next > 0 && etyp[next - 1] == TypeUtil.LABELLIST) { - targ[i] = next - 1; - dims[next - 1]++; + data[out] = new SparseFloatVector(f, dimsize[out]); + } + else if(elkitypes[out] == TypeUtil.LABELLIST) { + // Build a label list out of successive labels + LabelList ll = new LabelList(); + for(Entry<Integer, Object> key : map.entrySet()) { + int i = key.getKey(); + if(i < s) { continue; } - else { - targ[i] = next; - etyp[next] = TypeUtil.LABELLIST; - dims[next] = 1; - next++; - continue; + if(i >= s + dimsize[out]) { + break; + } + String v = (String) key.getValue(); + if(ll.size() < i - s) { + logger.warning("Sparse consecutive labels are currently not correctly supported."); } + ll.add(v); + } + data[out] = ll; + } + else if(elkitypes[out] == TypeUtil.EXTERNALID) { + String val = (String) map.get(s); + if(val != null) { + data[out] = new ExternalID(val); + } + else { + throw new AbortException("External ID column not set in sparse instance." + tokenizer.toString()); + } + } + else if(elkitypes[out] == TypeUtil.CLASSLABEL) { + String val = (String) map.get(s); + if(val != null) { + // TODO: support other class label types. + ClassLabel lbl = new SimpleClassLabel(val); + data[out] = lbl; } + else { + throw new AbortException("Class label column not set in sparse instance." + tokenizer.toString()); + } + } + else { + throw new AbortException("Unsupported type for column " + "->" + out + ": " + ((elkitypes[out] != null) ? elkitypes[out].toString() : "null")); } + } + return data; + } - // Prepare bundle: - // This is a bit complicated to produce vector fields. - MultipleObjectsBundle bundle = new MultipleObjectsBundle(); - for(int in = 0, out = 0; in < targ.length; out++) { - int nin = in + 1; - for(; nin < targ.length; nin++) { - if(targ[nin] != targ[in]) { - break; + private Object[] loadDenseInstance(StreamTokenizer tokenizer, int[] dimsize, TypeInformation[] etyp, int outdim) throws IOException { + // logger.warning("Regular instance."); + Object[] data = new Object[outdim]; + for(int out = 0; out < outdim; out++) { + if(etyp[out] == TypeUtil.NUMBER_VECTOR_FIELD) { + // For multi-column vectors, read successive columns + double[] cur = new double[dimsize[out]]; + for(int k = 0; k < dimsize[out]; k++) { + if(tokenizer.ttype != StreamTokenizer.TT_NUMBER) { + throw new AbortException("Expected word token, got: " + tokenizer.toString()); } + cur[k] = tokenizer.nval; + nextToken(tokenizer); } - if(etyp[out] == TypeUtil.NUMBER_VECTOR_FIELD) { - String[] labels = new String[dims[out]]; - // Collect labels: - for(int i = 0; i < dims[out]; i++) { - labels[i] = names.get(out + i); + data[out] = new DoubleVector(cur); + } + else if(etyp[out] == TypeUtil.LABELLIST) { + // Build a label list out of successive labels + LabelList ll = new LabelList(); + for(int k = 0; k < dimsize[out]; k++) { + if(tokenizer.ttype != StreamTokenizer.TT_WORD) { + throw new AbortException("Expected word token, got: " + tokenizer.toString()); } - VectorFieldTypeInformation<DoubleVector> type = new VectorFieldTypeInformation<DoubleVector>(DoubleVector.class, dims[out], labels, new DoubleVector(new double[dims[out]])); - bundle.appendColumn(type, new ArrayList<DoubleVector>()); + ll.add(tokenizer.sval); + nextToken(tokenizer); } - else if(etyp[out] == TypeUtil.LABELLIST) { - String label = names.get(out); - for(int i = 1; i < dims[out]; i++) { - label = label + " " + names.get(out + i); - } - bundle.appendColumn(new SimpleTypeInformation<LabelList>(LabelList.class, label), new ArrayList<LabelList>()); + data[out] = ll; + } + else if(etyp[out] == TypeUtil.EXTERNALID) { + if(tokenizer.ttype != StreamTokenizer.TT_WORD) { + throw new AbortException("Expected word token, got: " + tokenizer.toString()); } - else if(etyp[out] == TypeUtil.EXTERNALID) { - bundle.appendColumn(new SimpleTypeInformation<ExternalID>(ExternalID.class, names.get(out)), new ArrayList<ExternalID>()); + data[out] = new ExternalID(tokenizer.sval); + nextToken(tokenizer); + } + else if(etyp[out] == TypeUtil.CLASSLABEL) { + if(tokenizer.ttype != StreamTokenizer.TT_WORD) { + throw new AbortException("Expected word token, got: " + tokenizer.toString()); } - else if(etyp[out] == TypeUtil.CLASSLABEL) { - bundle.appendColumn(new SimpleTypeInformation<ClassLabel>(ClassLabel.class, names.get(out)), new ArrayList<ClassLabel>()); + // TODO: support other class label types. + ClassLabel lbl = new SimpleClassLabel(tokenizer.sval); + data[out] = lbl; + nextToken(tokenizer); + } + else { + throw new AbortException("Unsupported type for column " + "->" + out + ": " + ((etyp[out] != null) ? etyp[out].toString() : "null")); + } + } + return data; + } + + /** + * Make a StreamTokenizer for the ARFF format. + * + * @param br Buffered reader + * @return Tokenizer + */ + private StreamTokenizer makeArffTokenizer(BufferedReader br) { + // Setup tokenizer + StreamTokenizer tokenizer = new StreamTokenizer(br); + { + tokenizer.whitespaceChars(0, ' '); + tokenizer.wordChars(' ' + 1, '\u00FF'); + tokenizer.whitespaceChars(',', ','); + tokenizer.commentChar('%'); + tokenizer.quoteChar('"'); + tokenizer.quoteChar('\''); + tokenizer.ordinaryChar('{'); + tokenizer.ordinaryChar('}'); + tokenizer.eolIsSignificant(true); + } + return tokenizer; + } + + /** + * Setup the headers for the object bundle. + * + * @param names Attribute names + * @param targ Target columns + * @param etyp ELKI type information + * @param dimsize Number of dimensions in the individual types + * @param bundle Output bundle + * @param sparse Flag to create sparse vectors + */ + private void setupBundleHeaders(ArrayList<String> names, int[] targ, TypeInformation[] etyp, int[] dimsize, MultipleObjectsBundle bundle, boolean sparse) { + for(int in = 0, out = 0; in < targ.length; out++) { + int nin = in + 1; + for(; nin < targ.length; nin++) { + if(targ[nin] != targ[in]) { + break; + } + } + if(etyp[out] == TypeUtil.NUMBER_VECTOR_FIELD) { + String[] labels = new String[dimsize[out]]; + // Collect labels: + for(int i = 0; i < dimsize[out]; i++) { + labels[i] = names.get(out + i); + } + if(!sparse) { + VectorFieldTypeInformation<DoubleVector> type = new VectorFieldTypeInformation<DoubleVector>(DoubleVector.class, dimsize[out], labels, new DoubleVector(new double[dimsize[out]])); + bundle.appendColumn(type, new ArrayList<DoubleVector>()); } else { - throw new AbortException("Unsupported type for column " + in + "->" + out + ": " + ((etyp[out] != null) ? etyp[out].toString() : "null")); + Map<Integer, Float> empty = Collections.emptyMap(); + VectorFieldTypeInformation<SparseFloatVector> type = new VectorFieldTypeInformation<SparseFloatVector>(SparseFloatVector.class, dimsize[out], labels, new SparseFloatVector(empty, dimsize[out])); + bundle.appendColumn(type, new ArrayList<SparseFloatVector>()); } - assert (out == bundle.metaLength() - 1); - // logger.warning("Added meta: " + bundle.meta(bundle.metaLength() - - // 1)); - in = nin; - } - // Setup tokenizer - StreamTokenizer tokenizer = new StreamTokenizer(br); - { - tokenizer.whitespaceChars(0, ' '); - tokenizer.wordChars(' ' + 1, '\u00FF'); - tokenizer.whitespaceChars(',', ','); - tokenizer.commentChar('%'); - tokenizer.quoteChar('"'); - tokenizer.quoteChar('\''); - tokenizer.ordinaryChar('{'); - tokenizer.ordinaryChar('}'); - tokenizer.eolIsSignificant(true); - } - - final int outdim = bundle.metaLength(); - nextToken(tokenizer); - while(tokenizer.ttype != StreamTokenizer.TT_EOF) { - // Parse instance - if(tokenizer.ttype == StreamTokenizer.TT_EOL) { - // ignore empty lines + } + else if(etyp[out] == TypeUtil.LABELLIST) { + String label = names.get(out); + for(int i = 1; i < dimsize[out]; i++) { + label = label + " " + names.get(out + i); } - else if(tokenizer.ttype != '{') { - // logger.warning("Regular instance."); - Object[] data = new Object[outdim]; - for(int out = 0; out < outdim; out++) { - if(etyp[out] == TypeUtil.NUMBER_VECTOR_FIELD) { - double[] cur = new double[dims[out]]; - for(int k = 0; k < dims[out]; k++) { - if(tokenizer.ttype != StreamTokenizer.TT_NUMBER) { - throw new AbortException("Expected word token, got: " + tokenizer.toString()); - } - cur[k] = tokenizer.nval; - nextToken(tokenizer); - } - data[out] = new DoubleVector(cur); - } - else if(etyp[out] == TypeUtil.LABELLIST) { - LabelList ll = new LabelList(); - for(int k = 0; k < dims[out]; k++) { - if(tokenizer.ttype != StreamTokenizer.TT_WORD) { - throw new AbortException("Expected word token, got: " + tokenizer.toString()); - } - ll.add(tokenizer.sval); - nextToken(tokenizer); - } - data[out] = ll; - } - else if(etyp[out] == TypeUtil.EXTERNALID) { - if(tokenizer.ttype != StreamTokenizer.TT_WORD) { - throw new AbortException("Expected word token, got: " + tokenizer.toString()); - } - data[out] = new ExternalID(tokenizer.sval); - nextToken(tokenizer); - } - else if(etyp[out] == TypeUtil.CLASSLABEL) { - if(tokenizer.ttype != StreamTokenizer.TT_WORD) { - throw new AbortException("Expected word token, got: " + tokenizer.toString()); - } - ClassLabel lbl = new SimpleClassLabel(); - lbl.init(tokenizer.sval); - data[out] = lbl; - nextToken(tokenizer); - } - else { - throw new AbortException("Unsupported type for column " + "->" + out + ": " + ((etyp[out] != null) ? etyp[out].toString() : "null")); - } - } - bundle.appendSimple(data); + bundle.appendColumn(new SimpleTypeInformation<LabelList>(LabelList.class, label), new ArrayList<LabelList>()); + } + else if(etyp[out] == TypeUtil.EXTERNALID) { + bundle.appendColumn(new SimpleTypeInformation<ExternalID>(ExternalID.class, names.get(out)), new ArrayList<ExternalID>()); + } + else if(etyp[out] == TypeUtil.CLASSLABEL) { + bundle.appendColumn(new SimpleTypeInformation<ClassLabel>(ClassLabel.class, names.get(out)), new ArrayList<ClassLabel>()); + } + else { + throw new AbortException("Unsupported type for column " + in + "->" + out + ": " + ((etyp[out] != null) ? etyp[out].toString() : "null")); + } + assert (out == bundle.metaLength() - 1); + in = nin; + } + } + + /** + * Read the dataset header part of the ARFF file, to ensure consistency. + * + * @param br Buffered Reader + * @throws IOException + */ + private void readHeader(BufferedReader br) throws IOException { + String line; + // Locate header line + while(true) { + line = br.readLine(); + if(line == null) { + throw new AbortException(ARFF_HEADER_RELATION + " not found in file."); + } + // Skip comments and empty lines + if(ARFF_COMMENT.matcher(line).matches() || EMPTY.matcher(line).matches()) { + continue; + } + // Break on relation statement + if(ARFF_HEADER_RELATION.matcher(line).matches()) { + break; + } + throw new AbortException("Expected relation declaration: " + line); + } + } + + /** + * Parse the "@attribute" section of the ARFF file. + * + * @param br Input + * @param names List (to fill) of attribute names + * @param types List (to fill) of attribute types + * @throws IOException + */ + private void parseAttributeStatements(BufferedReader br, ArrayList<String> names, ArrayList<String> types) throws IOException { + String line; + // Load attribute metadata + while(true) { + line = br.readLine(); + if(line == null) { + throw new AbortException(ARFF_HEADER_DATA + " not found in file."); + } + // Skip comments and empty lines + if(ARFF_COMMENT.matcher(line).matches() || EMPTY.matcher(line).matches()) { + continue; + } + // Break on data statement to continue + if(ARFF_HEADER_DATA.matcher(line).matches()) { + break; + } + // Expect an attribute specification + Matcher matcher = ARFF_HEADER_ATTRIBUTE.matcher(line); + if(matcher.matches()) { + String name = matcher.group(1); + if(name.charAt(0) == '\'' && name.charAt(name.length() - 1) == '\'') { + name = name.substring(1, name.length() - 1); + } + else if(name.charAt(0) == '"' && name.charAt(name.length() - 1) == '"') { + name = name.substring(1, name.length() - 1); + } + String type = matcher.group(2); + names.add(name); + types.add(type); + // logger.warning("Attribute name: " + name + " type: " + type); + continue; + } + throw new AbortException("Unrecognized line: " + line); + } + assert (names.size() == types.size()); + } + + /** + * Process the column types (and names!) into ELKI relation style. Note that + * this will for example merge successive numerical columns into a single + * vector. + * + * @param names Attribute names + * @param types Attribute types + * @param targ Target dimension mapping (ARFF to ELKI), return value + * @param etyp ELKI type information, return value + * @param dims Number of successive dimensions, return value + */ + private void processColumnTypes(ArrayList<String> names, ArrayList<String> types, int[] targ, TypeInformation[] etyp, int[] dims) { + int next = 0; + for(int i = 0; i < targ.length; i++) { + if(magic_eid != null && magic_eid.matcher(names.get(i)).matches()) { + // Turn into an external ID column. + targ[i] = next; + etyp[next] = TypeUtil.EXTERNALID; + dims[next] = 1; + next++; + continue; + } + else if(magic_class != null && magic_class.matcher(names.get(i)).matches()) { + // Type as ClassLabel + targ[i] = next; + etyp[next] = TypeUtil.CLASSLABEL; + dims[next] = 1; + next++; + continue; + } + else if(ARFF_NUMERIC.matcher(types.get(i)).matches()) { + // Create a number vector field + if(next > 0 && etyp[next - 1] == TypeUtil.NUMBER_VECTOR_FIELD) { + targ[i] = next - 1; + dims[next - 1]++; + continue; } else { - logger.warning("Sparse instance."); - while(true) { - nextToken(tokenizer); - assert (tokenizer.ttype != StreamTokenizer.TT_EOF && tokenizer.ttype != StreamTokenizer.TT_EOL); - if(tokenizer.ttype == '}') { - nextToken(tokenizer); - assert (tokenizer.ttype == StreamTokenizer.TT_EOF || tokenizer.ttype == StreamTokenizer.TT_EOL); - break; - } - else { - // sparse token - } - } - throw new AbortException("Sparse ARFF are not (yet) supported."); + targ[i] = next; + etyp[next] = TypeUtil.NUMBER_VECTOR_FIELD; + dims[next] = 1; + next++; + continue; } - if(tokenizer.ttype != StreamTokenizer.TT_EOF) { - nextToken(tokenizer); + } + else { + // Use LabelList + if(next > 0 && etyp[next - 1] == TypeUtil.LABELLIST) { + targ[i] = next - 1; + dims[next - 1]++; + continue; + } + else { + targ[i] = next; + etyp[next] = TypeUtil.LABELLIST; + dims[next] = 1; + next++; + continue; } } - return bundle; - } - catch(IOException e) { - throw new AbortException("IO error in parser", e); } } + /** + * Helper function for token handling. + * + * @param tokenizer Tokenizer + * @throws IOException + */ private void nextToken(StreamTokenizer tokenizer) throws IOException { tokenizer.nextToken(); if((tokenizer.ttype == '\'') || (tokenizer.ttype == '"')) { @@ -368,4 +601,51 @@ public class ArffParser implements Parser { logger.debug("token type: " + tokenizer.ttype); } } + + /** + * Parameterization class. + * + * @author Erich Schubert + * + * @apiviz.exclude + */ + public static class Parameterizer extends AbstractParameterizer { + /** + * Pattern for recognizing external ID attributes. + */ + public static final OptionID MAGIC_EID_ID = OptionID.getOrCreateOptionID("arff.externalid", "Pattern to recognize external ID attributes."); + + /** + * Pattern for recognizing class label attributes. + */ + public static final OptionID MAGIC_CLASS_ID = OptionID.getOrCreateOptionID("arff.classlabel", "Pattern to recognize class label attributes."); + + /** + * Pattern to recognize external ids + */ + Pattern magic_eid; + + /** + * Pattern to recognize class label columns + */ + Pattern magic_class; + + @Override + protected void makeOptions(Parameterization config) { + super.makeOptions(config); + PatternParameter eidP = new PatternParameter(MAGIC_EID_ID, DEFAULT_ARFF_MAGIC_EID); + if(config.grab(eidP)) { + magic_eid = eidP.getValue(); + } + PatternParameter classP = new PatternParameter(MAGIC_CLASS_ID, DEFAULT_ARFF_MAGIC_CLASS); + if(config.grab(classP)) { + magic_class = classP.getValue(); + } + } + + @Override + protected ArffParser makeInstance() { + return new ArffParser(magic_eid, magic_class); + } + } }
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractDatabaseDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractDatabaseDistanceFunction.java index e1055816..22e0cbc3 100644 --- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractDatabaseDistanceFunction.java +++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractDatabaseDistanceFunction.java @@ -32,6 +32,8 @@ import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; * * @author Elke Achtert * + * @apiviz.has AbstractDatabaseDistanceFunction.Instance + * * @param <O> the type of DatabaseObject to compute the distances in between * @param <D> the type of Distance used */ diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractIndexBasedDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractIndexBasedDistanceFunction.java index 97280ba6..dfefb355 100644 --- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractIndexBasedDistanceFunction.java +++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractIndexBasedDistanceFunction.java @@ -38,6 +38,9 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter; * * @author Elke Achtert * + * @apiviz.has AbstractIndexBasedDistanceFunction.Instance + * @apiviz.composedOf IndexFactory + * * @param <O> the type of object to compute the distances in between * @param <I> the type of Index used * @param <D> the type of Distance used diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractVectorDoubleDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractVectorDoubleDistanceFunction.java index b06d1fbc..4bc2a381 100644 --- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractVectorDoubleDistanceFunction.java +++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractVectorDoubleDistanceFunction.java @@ -35,6 +35,8 @@ import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance; * @author Erich Schubert * * @apiviz.landmark + * @apiviz.uses NumberVector + * @apiviz.has DoubleDistance */ public abstract class AbstractVectorDoubleDistanceFunction extends AbstractPrimitiveDistanceFunction<NumberVector<?, ?>, DoubleDistance> implements PrimitiveDoubleDistanceFunction<NumberVector<?, ?>> { /** diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/MinKDistance.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/MinKDistance.java index 76717626..9c03134c 100644 --- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/MinKDistance.java +++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/MinKDistance.java @@ -63,6 +63,9 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter; * * @author Erich Schubert * + * @apiviz.uses DistanceFunction + * @apiviz.has MinKDistance.Instance + * * @param <O> Database object type * @param <D> Distance type */ @@ -121,6 +124,8 @@ public class MinKDistance<O, D extends Distance<D>> extends AbstractDatabaseDist * Instance for an actual database. * * @author Erich Schubert + * + * @apiviz.uses KNNQuery */ public class Instance<T extends O> extends AbstractDatabaseDistanceQuery<T, D> { /** diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/SharedNearestNeighborJaccardDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/SharedNearestNeighborJaccardDistanceFunction.java index 99f6ec56..0b80f512 100644 --- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/SharedNearestNeighborJaccardDistanceFunction.java +++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/SharedNearestNeighborJaccardDistanceFunction.java @@ -39,8 +39,8 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameteriz * * @author Erich Schubert * - * @apiviz.has de.lmu.ifi.dbs.elki.index.preprocessed.snn.SharedNearestNeighborIndex.Factory - * @apiviz.uses Instance oneway - - «create» + * @apiviz.composedOf de.lmu.ifi.dbs.elki.index.preprocessed.snn.SharedNearestNeighborIndex.Factory + * @apiviz.has SharedNearestNeighborJaccardDistanceFunction.Instance oneway - - «create» * * @param <O> object type */ diff --git a/src/de/lmu/ifi/dbs/elki/gui/configurator/ClassListParameterConfigurator.java b/src/de/lmu/ifi/dbs/elki/gui/configurator/ClassListParameterConfigurator.java index e75a6f93..7be929b2 100644 --- a/src/de/lmu/ifi/dbs/elki/gui/configurator/ClassListParameterConfigurator.java +++ b/src/de/lmu/ifi/dbs/elki/gui/configurator/ClassListParameterConfigurator.java @@ -47,6 +47,14 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.TrackParame import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ClassListParameter; import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.Parameter; +/** + * Provide a configuration panel to choose classes with the help of a dropdown. + * Additionally, the classes can in turn have additional parameters. + * + * @author Erich Schubert + * + * @apiviz.uses ClassListParameter + */ public class ClassListParameterConfigurator extends AbstractSingleParameterConfigurator<ClassListParameter<?>> implements ActionListener, ChangeListener { final ConfiguratorPanel child; diff --git a/src/de/lmu/ifi/dbs/elki/gui/configurator/ClassParameterConfigurator.java b/src/de/lmu/ifi/dbs/elki/gui/configurator/ClassParameterConfigurator.java index 98e52444..34580f16 100644 --- a/src/de/lmu/ifi/dbs/elki/gui/configurator/ClassParameterConfigurator.java +++ b/src/de/lmu/ifi/dbs/elki/gui/configurator/ClassParameterConfigurator.java @@ -40,6 +40,14 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.TrackParame import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ClassParameter; import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.Parameter; +/** + * Provide a configuration panel to choose a class with the help of a dropdown. + * Additionally, the classes can in turn have additional parameters. + * + * @author Erich Schubert + * + * @apiviz.uses ClassParameter + */ public class ClassParameterConfigurator extends AbstractSingleParameterConfigurator<ClassParameter<?>> implements ActionListener, ChangeListener { final JComboBox value; diff --git a/src/de/lmu/ifi/dbs/elki/gui/configurator/ConfiguratorPanel.java b/src/de/lmu/ifi/dbs/elki/gui/configurator/ConfiguratorPanel.java index a4cf6977..5be0da35 100644 --- a/src/de/lmu/ifi/dbs/elki/gui/configurator/ConfiguratorPanel.java +++ b/src/de/lmu/ifi/dbs/elki/gui/configurator/ConfiguratorPanel.java @@ -38,6 +38,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.ListParamet import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.TrackParameters; import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ClassListParameter; import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ClassParameter; +import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.EnumParameter; import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.FileParameter; import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.Flag; import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.Parameter; @@ -125,6 +126,9 @@ public class ConfiguratorPanel extends JPanel implements ChangeListener { if(param instanceof FileParameter) { return new FileParameterConfigurator((FileParameter) param, this); } + if(param instanceof EnumParameter) { + return new EnumParameterConfigurator((EnumParameter<?>) param, this); + } return new TextParameterConfigurator(param, this); } diff --git a/src/de/lmu/ifi/dbs/elki/gui/configurator/EnumParameterConfigurator.java b/src/de/lmu/ifi/dbs/elki/gui/configurator/EnumParameterConfigurator.java new file mode 100644 index 00000000..ad12b7ce --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/gui/configurator/EnumParameterConfigurator.java @@ -0,0 +1,104 @@ +package de.lmu.ifi.dbs.elki.gui.configurator; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2011 + 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 <http://www.gnu.org/licenses/>. + */ + +import java.awt.GridBagConstraints; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JComboBox; +import javax.swing.JComponent; + +import de.lmu.ifi.dbs.elki.gui.util.DynamicParameters; +import de.lmu.ifi.dbs.elki.logging.LoggingUtil; +import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.EnumParameter; + +/** + * Panel to configure EnumParameters by offering a dropdown to choose from. + * + * TODO: offer radio buttons when just a few choices are available? + * + * @author Erich Schubert + * + * @apiviz.uses EnumParameter + */ +public class EnumParameterConfigurator extends AbstractSingleParameterConfigurator<EnumParameter<?>> implements ActionListener { + final JComboBox value; + + public EnumParameterConfigurator(EnumParameter<?> cp, JComponent parent) { + super(cp, parent); + // Input field + { + GridBagConstraints constraints = new GridBagConstraints(); + constraints.fill = GridBagConstraints.HORIZONTAL; + constraints.weightx = 1.0; + value = new JComboBox(); + value.setToolTipText(param.getShortDescription()); + value.setPrototypeDisplayValue(cp.getPossibleValues().iterator().next()); + parent.add(value, constraints); + finishGridRow(); + } + + if(!param.tookDefaultValue() && param.isDefined() && param.getGivenValue() != null) { + value.addItem(param.getValueAsString()); + value.setSelectedIndex(0); + } + + // For parameters with a default value, offer using the default + // For optional parameters, offer not specifying them. + if(cp.hasDefaultValue()) { + value.addItem(DynamicParameters.STRING_USE_DEFAULT + " " + cp.getDefaultValueAsString()); + } + else if(cp.isOptional()) { + value.addItem(DynamicParameters.STRING_OPTIONAL); + } + // Offer the shorthand version of class names. + for(String s : cp.getPossibleValues()) { + value.addItem(s); + } + value.addActionListener(this); + } + + @Override + public void actionPerformed(ActionEvent e) { + if(e.getSource() == value) { + fireValueChanged(); + } + else { + LoggingUtil.warning("actionPerformed triggered by unknown source: " + e.getSource()); + } + } + + @Override + public String getUserInput() { + String val = (String) value.getSelectedItem(); + if(val.startsWith(DynamicParameters.STRING_USE_DEFAULT)) { + return null; + } + if(val == DynamicParameters.STRING_OPTIONAL) { + return null; + } + return val; + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/gui/configurator/FileParameterConfigurator.java b/src/de/lmu/ifi/dbs/elki/gui/configurator/FileParameterConfigurator.java index add20f69..fd7168d3 100644 --- a/src/de/lmu/ifi/dbs/elki/gui/configurator/FileParameterConfigurator.java +++ b/src/de/lmu/ifi/dbs/elki/gui/configurator/FileParameterConfigurator.java @@ -39,6 +39,13 @@ import de.lmu.ifi.dbs.elki.gui.icons.StockIcon; import de.lmu.ifi.dbs.elki.logging.LoggingUtil; import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.FileParameter; +/** + * Provide a configuration panel to choose a file with a file selector button. + * + * @author Erich Schubert + * + * @apiviz.uses FileParameter + */ public class FileParameterConfigurator extends AbstractSingleParameterConfigurator<FileParameter> implements ActionListener { /** * The panel to store the components diff --git a/src/de/lmu/ifi/dbs/elki/gui/configurator/FlagParameterConfigurator.java b/src/de/lmu/ifi/dbs/elki/gui/configurator/FlagParameterConfigurator.java index 49fc0a13..15a4506f 100644 --- a/src/de/lmu/ifi/dbs/elki/gui/configurator/FlagParameterConfigurator.java +++ b/src/de/lmu/ifi/dbs/elki/gui/configurator/FlagParameterConfigurator.java @@ -33,6 +33,13 @@ import javax.swing.JComponent; import de.lmu.ifi.dbs.elki.logging.LoggingUtil; import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.Flag; +/** + * Provide a configuration panel to modify a boolean via a checkbox. + * + * @author Erich Schubert + * + * @apiviz.uses Flag + */ public class FlagParameterConfigurator extends AbstractParameterConfigurator<Flag> implements ActionListener { final JCheckBox value; diff --git a/src/de/lmu/ifi/dbs/elki/gui/configurator/TextParameterConfigurator.java b/src/de/lmu/ifi/dbs/elki/gui/configurator/TextParameterConfigurator.java index 5a9848aa..3bf3dbb2 100644 --- a/src/de/lmu/ifi/dbs/elki/gui/configurator/TextParameterConfigurator.java +++ b/src/de/lmu/ifi/dbs/elki/gui/configurator/TextParameterConfigurator.java @@ -34,6 +34,13 @@ import javax.swing.JTextField; import de.lmu.ifi.dbs.elki.logging.LoggingUtil; import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.Parameter; +/** + * Provide a configuration panel to input an arbitrary text parameter. + * + * @author Erich Schubert + * + * @apiviz.uses ClassParameter + */ // FIXME: update on focus loss? // FIXME: restrictions for number input? public class TextParameterConfigurator extends AbstractSingleParameterConfigurator<Parameter<?, ?>> implements ActionListener { diff --git a/src/de/lmu/ifi/dbs/elki/gui/multistep/MultiStepGUI.java b/src/de/lmu/ifi/dbs/elki/gui/multistep/MultiStepGUI.java index ae550837..49745002 100644 --- a/src/de/lmu/ifi/dbs/elki/gui/multistep/MultiStepGUI.java +++ b/src/de/lmu/ifi/dbs/elki/gui/multistep/MultiStepGUI.java @@ -58,12 +58,12 @@ import de.lmu.ifi.dbs.elki.workflow.OutputStep; * @author Erich Schubert * * @apiviz.landmark - * @apiviz.composedOf SettingsComboboxModel * @apiviz.composedOf AlgorithmTabPanel * @apiviz.composedOf EvaluationTabPanel * @apiviz.composedOf InputTabPanel * @apiviz.composedOf LoggingTabPanel * @apiviz.composedOf OutputTabPanel + * @apiviz.composedOf SavedSettingsTabPanel */ public class MultiStepGUI extends JPanel { /** diff --git a/src/de/lmu/ifi/dbs/elki/gui/multistep/panels/SavedSettingsTabPanel.java b/src/de/lmu/ifi/dbs/elki/gui/multistep/panels/SavedSettingsTabPanel.java index 147943eb..ab7fc852 100644 --- a/src/de/lmu/ifi/dbs/elki/gui/multistep/panels/SavedSettingsTabPanel.java +++ b/src/de/lmu/ifi/dbs/elki/gui/multistep/panels/SavedSettingsTabPanel.java @@ -46,6 +46,8 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.SerializedP * Tab panel to manage saved settings. * * @author Erich Schubert + * + * @apiviz.composedOf SavedSettingsTabPanel.SettingsComboboxModel */ public class SavedSettingsTabPanel extends JPanel { /** diff --git a/src/de/lmu/ifi/dbs/elki/gui/util/ParameterTable.java b/src/de/lmu/ifi/dbs/elki/gui/util/ParameterTable.java index ea41213a..fc7deac8 100644 --- a/src/de/lmu/ifi/dbs/elki/gui/util/ParameterTable.java +++ b/src/de/lmu/ifi/dbs/elki/gui/util/ParameterTable.java @@ -50,6 +50,7 @@ import javax.swing.table.TableColumn; import de.lmu.ifi.dbs.elki.logging.LoggingUtil; import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ClassListParameter; import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ClassParameter; +import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.EnumParameter; import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.FileParameter; import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.Flag; import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.Parameter; @@ -255,6 +256,19 @@ public class ParameterTable extends JTable { comboBox.addItem(Flag.NOT_SET); } } + // and for Enum parameters. + else if (option instanceof EnumParameter<?>) { + EnumParameter<?> ep = (EnumParameter<?>) option; + for (String s : ep.getPossibleValues()) { + if (ep.hasDefaultValue() && ep.getDefaultValueAsString().equals(s)) { + if (!(DynamicParameters.STRING_USE_DEFAULT + " " + ep.getDefaultValueAsString()).equals(val)) { + comboBox.addItem(DynamicParameters.STRING_USE_DEFAULT + " " + s); + } + } else if (!s.equals(val)) { + comboBox.addItem(s); + } + } + } // No completion for others } return c; @@ -616,6 +630,10 @@ public class ParameterTable extends JTable { activeEditor = fileNameEditor; return fileNameEditor.getTableCellEditorComponent(table, value, isSelected, row, column); } + if(option instanceof EnumParameter<?>) { + activeEditor = dropdownEditor; + return dropdownEditor.getTableCellEditorComponent(table, value, isSelected, row, column); + } } activeEditor = plaintextEditor; return plaintextEditor.getTableCellEditorComponent(table, value, isSelected, row, column); diff --git a/src/de/lmu/ifi/dbs/elki/index/IndexFactory.java b/src/de/lmu/ifi/dbs/elki/index/IndexFactory.java index c09f579b..b1eb649b 100644 --- a/src/de/lmu/ifi/dbs/elki/index/IndexFactory.java +++ b/src/de/lmu/ifi/dbs/elki/index/IndexFactory.java @@ -33,7 +33,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable; * @author Erich Schubert * * @apiviz.stereotype factory,interface - * @apiviz.uses Index oneway - - «create» + * @apiviz.has Index oneway - - «create» * * @param <V> Input object type * @param <I> Index type diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/AbstractPreprocessorIndex.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/AbstractPreprocessorIndex.java index 6ae84286..4b6fbe3a 100644 --- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/AbstractPreprocessorIndex.java +++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/AbstractPreprocessorIndex.java @@ -34,6 +34,8 @@ import de.lmu.ifi.dbs.elki.logging.Logging; * * @author Erich Schubert * + * @apiviz.composedOf WritableDataStore + * * @param <O> Object type * @param <R> Stored data type */ diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/LocalProjectionIndex.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/LocalProjectionIndex.java index 9bcbe9ce..8b4272d5 100644 --- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/LocalProjectionIndex.java +++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/LocalProjectionIndex.java @@ -55,7 +55,7 @@ public interface LocalProjectionIndex<V extends NumberVector<?, ?>, P extends Pr * @author Erich Schubert * * @apiviz.stereotype factory - * @apiviz.uses LocalProjectionIndex oneway - - «create» + * @apiviz.has LocalProjectionIndex oneway - - «create» * * @param <V> Vector type * @param <I> Index type diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/DiSHPreferenceVectorIndex.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/DiSHPreferenceVectorIndex.java index 09ba95b3..8626e5b7 100644 --- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/DiSHPreferenceVectorIndex.java +++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/DiSHPreferenceVectorIndex.java @@ -65,12 +65,11 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer; import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID; import de.lmu.ifi.dbs.elki.utilities.optionhandling.ParameterException; import de.lmu.ifi.dbs.elki.utilities.optionhandling.WrongParameterValueException; -import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.EqualStringConstraint; import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterConstraint; import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization; import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.DoubleListParameter; +import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.EnumParameter; import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter; -import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.StringParameter; /** * Preprocessor for DiSH preference vector assignment to objects of a certain @@ -607,19 +606,9 @@ public class DiSHPreferenceVectorIndex<V extends NumberVector<?, ?>> extends Abs } // parameter strategy - final StringParameter strategyP = new StringParameter(STRATEGY_ID, DEFAULT_STRATEGY.toString()); - strategyP.addConstraint(new EqualStringConstraint(new String[] { Strategy.APRIORI.toString(), Strategy.MAX_INTERSECTION.toString() })); + final EnumParameter<Strategy> strategyP = new EnumParameter<Strategy>(STRATEGY_ID, Strategy.class, DEFAULT_STRATEGY); if(config.grab(strategyP)) { - String strategyString = strategyP.getValue(); - if(strategyString.equals(Strategy.APRIORI.toString())) { - strategy = Strategy.APRIORI; - } - else if(strategyString.equals(Strategy.MAX_INTERSECTION.toString())) { - strategy = Strategy.MAX_INTERSECTION; - } - else { - config.reportError(new WrongParameterValueException(strategyP, strategyString)); - } + strategy = strategyP.getValue(); } } diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/DistanceEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/DistanceEntry.java index 63aa5978..b7bf3e0c 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/DistanceEntry.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/DistanceEntry.java @@ -30,6 +30,10 @@ import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; * belonging to this entry. * * @author Elke Achtert + * + * @apiviz.composedOf Distance + * @apiviz.uses Entry + * * @param <E> the type of Entry used in the index * @param <D> the type of Distance used */ diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/IndexTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/IndexTree.java index f16b0e0e..fa9c0e0a 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/IndexTree.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/IndexTree.java @@ -33,6 +33,7 @@ import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException; * * @author Elke Achtert * + * @apiviz.composedOf PageFile * @apiviz.has Node oneway - - contains * @apiviz.has TreeIndexHeader oneway * diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/IndexTreePath.java b/src/de/lmu/ifi/dbs/elki/index/tree/IndexTreePath.java index c8fa3e82..feb134e3 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/IndexTreePath.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/IndexTreePath.java @@ -33,6 +33,7 @@ import java.util.List; * @author Elke Achtert * * @apiviz.composedOf TreeIndexPathComponent + * @apiviz.uses Entry * * @param <E> the type of Entry used in the index */ diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/TreeIndexFactory.java b/src/de/lmu/ifi/dbs/elki/index/tree/TreeIndexFactory.java index fc479cba..b55700ec 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/TreeIndexFactory.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/TreeIndexFactory.java @@ -46,11 +46,12 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.LongParameter; * @author Erich Schubert * * @apiviz.stereotype factory,interface - * @apiviz.uses Index oneway - - «create» + * @apiviz.has Index oneway - - «create» * * @param <O> Object type * @param <I> Index type */ +// TODO: actually, this class should be called PagedIndexFactory? public abstract class TreeIndexFactory<O, I extends Index> implements IndexFactory<O, I> { /** * Optional parameter that specifies the name of the file storing the index. diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/TreeIndexPathComponent.java b/src/de/lmu/ifi/dbs/elki/index/tree/TreeIndexPathComponent.java index 1cc170f3..2309c7e5 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/TreeIndexPathComponent.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/TreeIndexPathComponent.java @@ -30,6 +30,9 @@ package de.lmu.ifi.dbs.elki.index.tree; * index of the component in its parent. * * @author Elke Achtert + * + * @apiviz.uses Entry oneway - - «references» + * * @param <E> the type of Entry used in the index */ public class TreeIndexPathComponent<E extends Entry> { diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppEntry.java index cc56d1fb..ef50e3bc 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppEntry.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppEntry.java @@ -32,10 +32,10 @@ import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry; * provided. * * @author Elke Achtert + * + * @apiviz.composedOf PolynomialApproximation */ - interface MkAppEntry<D extends NumberDistance<D, ?>> extends MTreeEntry<D> { - /** * Returns the approximated value at the specified k. * @@ -57,4 +57,4 @@ interface MkAppEntry<D extends NumberDistance<D, ?>> extends MTreeEntry<D> { * @param approximation the polynomial approximation to be set */ public void setKnnDistanceApproximation(PolynomialApproximation approximation); -} +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/ConvexHull.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/ConvexHull.java index d87986cb..7924c13d 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/ConvexHull.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/ConvexHull.java @@ -23,7 +23,6 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkcop; along with this program. If not, see <http://www.gnu.org/licenses/>. */ - /** * Holds the lower and upper hull for some values. * diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPEntry.java index bdc83f17..cd1155c3 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPEntry.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPEntry.java @@ -28,19 +28,21 @@ import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry; /** - * Defines the requirements for an entry in an MkCop-Tree node. - * Additionally to an entry in an M-Tree conservative approximation of the - * knn distances is provided. - * - * @author Elke Achtert + * Defines the requirements for an entry in an MkCop-Tree node. Additionally to + * an entry in an M-Tree conservative approximation of the knn distances is + * provided. + * + * @author Elke Achtert + * + * @apiviz.composedOf ApproximationLine */ interface MkCoPEntry<D extends NumberDistance<D, ?>> extends MTreeEntry<D> { /** * Returns the conservative approximated knn distance of the entry. - * + * * @param <O> Object type - * @param k the parameter k of the knn distance + * @param k the parameter k of the knn distance * @param distanceFunction the distance function * @return the conservative approximated knn distance of the entry */ @@ -48,15 +50,16 @@ interface MkCoPEntry<D extends NumberDistance<D, ?>> extends MTreeEntry<D> { /** * Returns the conservative approximation line. - * + * * @return the conservative approximation line */ public ApproximationLine getConservativeKnnDistanceApproximation(); /** * Sets the conservative approximation line - * - * @param conservativeApproximation the conservative approximation line to be set + * + * @param conservativeApproximation the conservative approximation line to be + * set */ public void setConservativeKnnDistanceApproximation(ApproximationLine conservativeApproximation); -} +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPTree.java index e6abc753..a2f684ad 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPTree.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPTree.java @@ -57,6 +57,7 @@ import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.UpdatableHeap; * @author Elke Achtert * * @apiviz.has MkCoPTreeNode oneway - - contains + * @apiviz.uses ConvexHull * * @param <O> Object type * @param <D> Distance type diff --git a/src/de/lmu/ifi/dbs/elki/math/MathUtil.java b/src/de/lmu/ifi/dbs/elki/math/MathUtil.java index f04fdef7..6856a44b 100644 --- a/src/de/lmu/ifi/dbs/elki/math/MathUtil.java +++ b/src/de/lmu/ifi/dbs/elki/math/MathUtil.java @@ -32,6 +32,11 @@ import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector; /** * A collection of math related utility functions. + * + * @author Arthur Zimekt + * @author Erich Schubert + * + * @apiviz.landmark */ public final class MathUtil { /** diff --git a/src/de/lmu/ifi/dbs/elki/persistent/ByteArrayUtil.java b/src/de/lmu/ifi/dbs/elki/persistent/ByteArrayUtil.java index 5b7c34df..f4959167 100644 --- a/src/de/lmu/ifi/dbs/elki/persistent/ByteArrayUtil.java +++ b/src/de/lmu/ifi/dbs/elki/persistent/ByteArrayUtil.java @@ -275,7 +275,7 @@ public final class ByteArrayUtil { } @Override - public int getByteSize(@SuppressWarnings("unused") Byte object) { + public int getByteSize(Byte object) { return getFixedByteSize(); } @@ -309,7 +309,7 @@ public final class ByteArrayUtil { } @Override - public int getByteSize(@SuppressWarnings("unused") Short object) { + public int getByteSize(Short object) { return getFixedByteSize(); } @@ -343,7 +343,7 @@ public final class ByteArrayUtil { } @Override - public int getByteSize(@SuppressWarnings("unused") Integer object) { + public int getByteSize(Integer object) { return getFixedByteSize(); } @@ -377,7 +377,7 @@ public final class ByteArrayUtil { } @Override - public int getByteSize(@SuppressWarnings("unused") Long object) { + public int getByteSize(Long object) { return getFixedByteSize(); } @@ -411,7 +411,7 @@ public final class ByteArrayUtil { } @Override - public int getByteSize(@SuppressWarnings("unused") Float object) { + public int getByteSize(Float object) { return getFixedByteSize(); } @@ -445,7 +445,7 @@ public final class ByteArrayUtil { } @Override - public int getByteSize(@SuppressWarnings("unused") Double object) { + public int getByteSize(Double object) { return getFixedByteSize(); } diff --git a/src/de/lmu/ifi/dbs/elki/properties/ELKI.properties b/src/de/lmu/ifi/dbs/elki/properties/ELKI.properties index 905b1751..5c45ecfa 100644 --- a/src/de/lmu/ifi/dbs/elki/properties/ELKI.properties +++ b/src/de/lmu/ifi/dbs/elki/properties/ELKI.properties @@ -178,9 +178,9 @@ de.lmu.ifi.dbs.elki.data.images.ComputeColorHistogram=\ de.lmu.ifi.dbs.elki.data.images.ComputeNaiveRGBColorHistogram,\ # ####################################################### # Classlabel - default package: de.lmu.ifi.dbs.elki.data -de.lmu.ifi.dbs.elki.data.ClassLabel=\ - de.lmu.ifi.dbs.elki.data.SimpleClassLabel,\ - de.lmu.ifi.dbs.elki.data.HierarchicalClassLabel,\ +de.lmu.ifi.dbs.elki.data.ClassLabel$Factory=\ + de.lmu.ifi.dbs.elki.data.SimpleClassLabel$Factory,\ + de.lmu.ifi.dbs.elki.data.HierarchicalClassLabel$Factory,\ # ####################################################### # Databases - default package: de.lmu.ifi.dbs.elki.database de.lmu.ifi.dbs.elki.database.Database=\ @@ -195,11 +195,12 @@ de.lmu.ifi.dbs.elki.database.UpdatableDatabase=\ # Database connections - default package: de.lmu.ifi.dbs.elki.database.connection de.lmu.ifi.dbs.elki.datasource.DatabaseConnection=\ de.lmu.ifi.dbs.elki.datasource.FileBasedDatabaseConnection,\ - de.lmu.ifi.dbs.elki.datasource.InputStreamDatabaseConnection,\ - de.lmu.ifi.dbs.elki.datasource.RandomDoubleVectorDatabaseConnection,\ - de.lmu.ifi.dbs.elki.datasource.LabelJoinDatabaseConnection,\ de.lmu.ifi.dbs.elki.datasource.ExternalIDJoinDatabaseConnection,\ + de.lmu.ifi.dbs.elki.datasource.LabelJoinDatabaseConnection,\ + de.lmu.ifi.dbs.elki.datasource.GeneratorXMLDatabaseConnection,\ + de.lmu.ifi.dbs.elki.datasource.RandomDoubleVectorDatabaseConnection,\ de.lmu.ifi.dbs.elki.datasource.EmptyDatabaseConnection,\ +# de.lmu.ifi.dbs.elki.datasource.InputStreamDatabaseConnection,\ # ####################################################### # distance functions - default package: de.lmu.ifi.dbs.elki.distance.distancefunction de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction=\ @@ -342,7 +343,7 @@ de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDoubleDistanceFunc de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.DimensionSelectingDistanceFunction,\ de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.DimensionsSelectingEuclideanDistanceFunction,\ # ####################################################### -# preprocessor based distance functions functions - default package: de.lmu.ifi.dbs.elki.distance.distancefunction +# preprocessor based distance functions - default package: de.lmu.ifi.dbs.elki.distance.distancefunction de.lmu.ifi.dbs.elki.distance.distancefunction.AbstractIndexBasedDistanceFunction=\ de.lmu.ifi.dbs.elki.distance.distancefunction.LocallyWeightedDistanceFunction,\ de.lmu.ifi.dbs.elki.distance.distancefunction.SharedNearestNeighborJaccardDistanceFunction,\ @@ -352,6 +353,9 @@ de.lmu.ifi.dbs.elki.distance.distancefunction.AbstractIndexBasedDistanceFunction de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.DiSHDistanceFunction,\ de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.HiSCDistanceFunction,\ # ####################################################### +# locally weighted distance functions - default package: de.lmu.ifi.dbs.elki.distance.distancefunction +de.lmu.ifi.dbs.elki.distance.distancefunction.LocallyWeightedDistanceFunction=\ +# ####################################################### # distance parser - default package: de.lmu.ifi.dbs.elki.datasource.parser de.lmu.ifi.dbs.elki.datasource.parser.DistanceParser=\ de.lmu.ifi.dbs.elki.datasource.parser.NumberDistanceParser,\ diff --git a/src/de/lmu/ifi/dbs/elki/result/DiscardResultHandler.java b/src/de/lmu/ifi/dbs/elki/result/DiscardResultHandler.java index ee65e64e..486a47a9 100644 --- a/src/de/lmu/ifi/dbs/elki/result/DiscardResultHandler.java +++ b/src/de/lmu/ifi/dbs/elki/result/DiscardResultHandler.java @@ -23,8 +23,6 @@ package de.lmu.ifi.dbs.elki.result; along with this program. If not, see <http://www.gnu.org/licenses/>. */ - - /** * A dummy result handler that discards the actual result, for use in * benchmarks. @@ -39,7 +37,6 @@ public class DiscardResultHandler implements ResultHandler { // empty constructor } - @SuppressWarnings("unused") @Override public void processNewResult(HierarchicalResult baseResult, Result newResult) { // always ignore the new result. diff --git a/src/de/lmu/ifi/dbs/elki/result/ResultHierarchy.java b/src/de/lmu/ifi/dbs/elki/result/ResultHierarchy.java index 101d6855..0ecf6f82 100644 --- a/src/de/lmu/ifi/dbs/elki/result/ResultHierarchy.java +++ b/src/de/lmu/ifi/dbs/elki/result/ResultHierarchy.java @@ -74,14 +74,12 @@ public class ResultHierarchy extends HierarchyHashmapList<Result> { fireResultAdded(child, parent); } - @SuppressWarnings("unused") @Override public void remove(Result parent, Result child) { // TODO: unlink from hierarchy, fire event throw new UnsupportedOperationException(); } - @SuppressWarnings("unused") @Override public void put(Result obj, List<Result> parents, List<Result> children) { // TODO: can we support this somehow? Or reduce visibility? diff --git a/src/de/lmu/ifi/dbs/elki/result/optics/ClusterOrderResult.java b/src/de/lmu/ifi/dbs/elki/result/optics/ClusterOrderResult.java index 9c5c6cdd..4a5a9636 100644 --- a/src/de/lmu/ifi/dbs/elki/result/optics/ClusterOrderResult.java +++ b/src/de/lmu/ifi/dbs/elki/result/optics/ClusterOrderResult.java @@ -267,13 +267,11 @@ public class ClusterOrderResult<D extends Distance<D>> extends BasicResult imple return null; // FIXME } - @SuppressWarnings("unused") @Override public void set(DBID id, D val) { throw new UnsupportedOperationException(); } - @SuppressWarnings("unused") @Override public void delete(DBID id) { throw new UnsupportedOperationException(); @@ -358,13 +356,11 @@ public class ClusterOrderResult<D extends Distance<D>> extends BasicResult imple return null; // FIXME } - @SuppressWarnings("unused") @Override public void set(DBID id, DBID val) { throw new UnsupportedOperationException(); } - @SuppressWarnings("unused") @Override public void delete(DBID id) { throw new UnsupportedOperationException(); diff --git a/src/de/lmu/ifi/dbs/elki/result/outlier/OutlierResult.java b/src/de/lmu/ifi/dbs/elki/result/outlier/OutlierResult.java index cafe4958..4389c7c8 100644 --- a/src/de/lmu/ifi/dbs/elki/result/outlier/OutlierResult.java +++ b/src/de/lmu/ifi/dbs/elki/result/outlier/OutlierResult.java @@ -33,6 +33,7 @@ import de.lmu.ifi.dbs.elki.result.OrderingResult; * * @author Erich Schubert * + * @apiviz.landmark * @apiviz.composedOf OutlierScoreMeta * @apiviz.composedOf Relation oneway - - contains * @apiviz.composedOf OrderingFromRelation diff --git a/src/de/lmu/ifi/dbs/elki/result/textwriter/TextWriter.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/TextWriter.java index 743e787f..bbe3212b 100644 --- a/src/de/lmu/ifi/dbs/elki/result/textwriter/TextWriter.java +++ b/src/de/lmu/ifi/dbs/elki/result/textwriter/TextWriter.java @@ -40,6 +40,7 @@ import de.lmu.ifi.dbs.elki.data.FeatureVector; import de.lmu.ifi.dbs.elki.data.HierarchicalClassLabel; import de.lmu.ifi.dbs.elki.data.LabelList; import de.lmu.ifi.dbs.elki.data.SimpleClassLabel; +import de.lmu.ifi.dbs.elki.data.model.ClusterModel; import de.lmu.ifi.dbs.elki.data.model.Model; import de.lmu.ifi.dbs.elki.data.type.TypeUtil; import de.lmu.ifi.dbs.elki.database.Database; @@ -301,9 +302,14 @@ public class TextWriter { owriter.writeObject(out, lbl, obj); } + Collection<Relation<?>> dbrels = db.getRelations(); // print the annotations if(ra != null) { for(Relation<?> a : ra) { + // Avoid duplicated output. + if (dbrels.contains(a)) { + continue; + } String label = a.getShortName(); Object value = a.get(objID); if(value == null) { @@ -350,6 +356,11 @@ public class TextWriter { // Write cluster information out.commentPrintLn("Cluster: " + naming.getNameFor(clus)); + Model model = clus.getModel(); + if (model != ClusterModel.CLUSTER) { + TextWriterWriterInterface<?> mwri = writers.getHandler(model); + mwri.writeObject(out, null, model); + } if(clus.getParents().size() > 0) { StringBuffer buf = new StringBuffer(); buf.append("Parents:"); diff --git a/src/de/lmu/ifi/dbs/elki/utilities/Util.java b/src/de/lmu/ifi/dbs/elki/utilities/Util.java index 639c0d64..fcaca269 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/Util.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/Util.java @@ -599,7 +599,7 @@ public final class Util { } @Override - public boolean add(@SuppressWarnings("unused") T e) { + public boolean add(T e) { throw new UnsupportedOperationException(); } diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/KNNList.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/KNNList.java index 8e0e2372..02a5264c 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/KNNList.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/KNNList.java @@ -137,22 +137,22 @@ public class KNNList<D extends Distance<D>> extends ArrayList<DistanceResultPair /* Make the list unmodifiable! */ @Override - public boolean add(@SuppressWarnings("unused") DistanceResultPair<D> e) { + public boolean add(DistanceResultPair<D> e) { throw new UnsupportedOperationException(); } @Override - public void add(@SuppressWarnings("unused") int index, @SuppressWarnings("unused") DistanceResultPair<D> element) { + public void add(int index, DistanceResultPair<D> element) { throw new UnsupportedOperationException(); } @Override - public boolean addAll(@SuppressWarnings("unused") Collection<? extends DistanceResultPair<D>> c) { + public boolean addAll(Collection<? extends DistanceResultPair<D>> c) { throw new UnsupportedOperationException(); } @Override - public boolean addAll(@SuppressWarnings("unused") int index, @SuppressWarnings("unused") Collection<? extends DistanceResultPair<D>> c) { + public boolean addAll(int index, Collection<? extends DistanceResultPair<D>> c) { throw new UnsupportedOperationException(); } @@ -162,17 +162,17 @@ public class KNNList<D extends Distance<D>> extends ArrayList<DistanceResultPair } @Override - public DistanceResultPair<D> remove(@SuppressWarnings("unused") int index) { + public DistanceResultPair<D> remove(int index) { throw new UnsupportedOperationException(); } @Override - public boolean remove(@SuppressWarnings("unused") Object o) { + public boolean remove(Object o) { throw new UnsupportedOperationException(); } @Override - public DistanceResultPair<D> set(@SuppressWarnings("unused") int index, @SuppressWarnings("unused") DistanceResultPair<D> element) { + public DistanceResultPair<D> set(int index, DistanceResultPair<D> element) { throw new UnsupportedOperationException(); } diff --git a/src/de/lmu/ifi/dbs/elki/utilities/iterator/UnmodifiableListIterator.java b/src/de/lmu/ifi/dbs/elki/utilities/iterator/UnmodifiableListIterator.java index 46affd34..0123216d 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/iterator/UnmodifiableListIterator.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/iterator/UnmodifiableListIterator.java @@ -87,12 +87,12 @@ public final class UnmodifiableListIterator<T> implements ListIterator<T> { } @Override - public void add(@SuppressWarnings("unused") T e) { + public void add(T e) { throw new UnsupportedOperationException(); } @Override - public void set(@SuppressWarnings("unused") T e) { + public void set(T e) { throw new UnsupportedOperationException(); } }
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/AbstractNumberConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/AbstractNumberConstraint.java index a631a316..6b49faea 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/AbstractNumberConstraint.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/AbstractNumberConstraint.java @@ -23,15 +23,16 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints; along with this program. If not, see <http://www.gnu.org/licenses/>. */ - /** * Abstract super class for constraints dealing with a certain number value. * * @author Elke Achtert + * + * @apiviz.uses de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.NumberParameter + * * @param <P> the type of the parameter to be tested by this constraint (e.g., Number, List<Number>) */ public abstract class AbstractNumberConstraint<P> implements ParameterConstraint<P> { - /** * The constraint value. */ @@ -45,4 +46,4 @@ public abstract class AbstractNumberConstraint<P> implements ParameterConstraint public AbstractNumberConstraint(Number constraintValue) { this.constraintValue = constraintValue; } -} +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/EqualStringConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/EqualStringConstraint.java index ea952a30..342ffd00 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/EqualStringConstraint.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/EqualStringConstraint.java @@ -35,6 +35,8 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.WrongParameterValueException * ) to be tested is equal to the specified constraint-strings. * * @author Steffi Wanka + * + * @apiviz.uses de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.StringParameter */ public class EqualStringConstraint implements ParameterConstraint<String> { /** diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/IntervalConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/IntervalConstraint.java index a2d5b8b3..8a9f1bcf 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/IntervalConstraint.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/IntervalConstraint.java @@ -27,148 +27,135 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.ParameterException; import de.lmu.ifi.dbs.elki.utilities.optionhandling.WrongParameterValueException; /** - * Represents an interval parameter constraint testing if a given value lies within - * the specified interval. - * The value of the number parameter ({@link de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.NumberParameter}) - * tested has to be greater than (or equal to, if specified) than the specified low constraint value - * and less than (or equal to, if specified) than the specified high constraint value. - * + * Represents an interval parameter constraint testing if a given value lies + * within the specified interval. The value of the number parameter ( + * {@link de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.NumberParameter} + * ) tested has to be greater than (or equal to, if specified) than the + * specified low constraint value and less than (or equal to, if specified) than + * the specified high constraint value. + * * @author Steffi Wanka + * + * @apiviz.uses de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.NumberParameter */ public class IntervalConstraint implements ParameterConstraint<Number> { + /** + * Available interval boundary types types: + * {@link IntervalConstraint.IntervalBoundary#OPEN} denotes an opend interval, + * i.e. less than (or greater than) comparison + * {@link IntervalConstraint.IntervalBoundary#CLOSE} denotes a closed + * interval, i.e. an equal to or less than (or equal to or greater than) + * comparison + * + * @apiviz.exclude + */ + public enum IntervalBoundary { /** - * Available interval boundary types types: - * {@link IntervalConstraint.IntervalBoundary#OPEN} denotes an opend interval, - * i.e. less than (or greater than) comparison - * {@link IntervalConstraint.IntervalBoundary#CLOSE} denotes a closed interval, - * i.e. an equal to or less than (or equal to or greater than) comparison - * - * @apiviz.exclude + * Open interval boundary */ - public enum IntervalBoundary { - /** - * Open interval boundary - */ - OPEN, - /** - * Closed interval boundary - */ - CLOSE - } - - /** - * The low constraint value (left interval boundary). - */ - private final Number lowConstraintValue; - - /** - * The interval boundary for the low constraint value (@see IntervalBoundary) - */ - private final IntervalBoundary lowBoundary; - - /** - * The high constraint value (right interval boundary). - */ - private final Number highConstraintValue; - + OPEN, /** - * The interval boundary for the high constraint value (@see IntervalBoundary) + * Closed interval boundary */ - private final IntervalBoundary highBoundary; + CLOSE + } + + /** + * The low constraint value (left interval boundary). + */ + private final Number lowConstraintValue; + + /** + * The interval boundary for the low constraint value (@see IntervalBoundary) + */ + private final IntervalBoundary lowBoundary; + + /** + * The high constraint value (right interval boundary). + */ + private final Number highConstraintValue; + + /** + * The interval boundary for the high constraint value (@see IntervalBoundary) + */ + private final IntervalBoundary highBoundary; + + /** + * Creates an IntervalConstraint parameter constraint. + * <p/> + * That is, the value of the number parameter given has to be greater than (or + * equal to, if specified) than the specified low constraint value and less + * than (or equal to, if specified) than the specified high constraint value. + * + * @param lowConstraintValue the low constraint value (left interval boundary) + * @param lowBoundary the interval boundary for the low constraint value (@see + * IntervalBoundary) + * @param highConstraintValue the high constraint value (right interval + * boundary) + * @param highBoundary the interval boundary for the high constraint value + * (@see IntervalBoundary) + */ + public IntervalConstraint(Number lowConstraintValue, IntervalBoundary lowBoundary, Number highConstraintValue, IntervalBoundary highBoundary) { + if(lowConstraintValue.doubleValue() >= highConstraintValue.doubleValue()) { + throw new IllegalArgumentException("Left interval boundary is greater than " + "or equal to right interval boundary!"); + } - /** - * Creates an IntervalConstraint parameter constraint. - * <p/> - * That is, the value of the number parameter given - * has to be greater than (or equal to, if specified) than the specified low constraint value - * and less than (or equal to, if specified) than the specified high constraint value. - * - * @param lowConstraintValue the low constraint value (left interval boundary) - * @param lowBoundary the interval boundary for the low constraint value (@see IntervalBoundary) - * @param highConstraintValue the high constraint value (right interval boundary) - * @param highBoundary the interval boundary for the high constraint value (@see IntervalBoundary) - */ - public IntervalConstraint(Number lowConstraintValue, IntervalBoundary lowBoundary, - Number highConstraintValue, IntervalBoundary highBoundary) { - if (lowConstraintValue.doubleValue() >= highConstraintValue.doubleValue()) { - throw new IllegalArgumentException("Left interval boundary is greater than " + - "or equal to right interval boundary!"); - } - - this.lowConstraintValue = lowConstraintValue; - this.lowBoundary = lowBoundary; - this.highConstraintValue = highConstraintValue; - this.highBoundary = highBoundary; + this.lowConstraintValue = lowConstraintValue; + this.lowBoundary = lowBoundary; + this.highConstraintValue = highConstraintValue; + this.highBoundary = highBoundary; + } + + /** + * Checks if the number value given by the number parameter is greater equal + * than the constraint value. If not, a parameter exception is thrown. + * + */ + @Override + public void test(Number t) throws ParameterException { + // lower value + if(lowBoundary.equals(IntervalBoundary.CLOSE)) { + if(t.doubleValue() < lowConstraintValue.doubleValue()) { + throw new WrongParameterValueException("Parameter Constraint Error: \n" + "The parameter value specified has to be " + "equal to or greater than " + lowConstraintValue.toString() + ". (current value: " + t.doubleValue() + ")\n"); + } + } + else if(lowBoundary.equals(IntervalBoundary.OPEN)) { + if(t.doubleValue() <= lowConstraintValue.doubleValue()) { + throw new WrongParameterValueException("Parameter Constraint Error: \n" + "The parameter value specified has to be " + "greater than " + lowConstraintValue.toString() + ". (current value: " + t.doubleValue() + ")\n"); + } } - /** - * Checks if the number value given by the number parameter is - * greater equal than the constraint - * value. If not, a parameter exception is thrown. - * - */ - @Override - public void test(Number t) throws ParameterException { - // lower value - if (lowBoundary.equals(IntervalBoundary.CLOSE)) { - if (t.doubleValue() < lowConstraintValue.doubleValue()) { - throw new WrongParameterValueException("Parameter Constraint Error: \n" + - "The parameter value specified has to be " + - "equal to or greater than " + - lowConstraintValue.toString() + - ". (current value: " + t.doubleValue() + ")\n"); - } - } - else if (lowBoundary.equals(IntervalBoundary.OPEN)) { - if (t.doubleValue() <= lowConstraintValue.doubleValue()) { - throw new WrongParameterValueException("Parameter Constraint Error: \n" + - "The parameter value specified has to be " + - "greater than " + - lowConstraintValue.toString() + - ". (current value: " + t.doubleValue() + ")\n"); - } - } - - // higher value - if (highBoundary.equals(IntervalBoundary.CLOSE)) { - if (t.doubleValue() > highConstraintValue.doubleValue()) { - throw new WrongParameterValueException("Parameter Constraint Error: \n" + - "The parameter value specified has to be " + - "equal to or less than " + - highConstraintValue.toString() + - ". (current value: " + t.doubleValue() + ")\n"); - } - } - else if (highBoundary.equals(IntervalBoundary.OPEN)) { - if (t.doubleValue() >= highConstraintValue.doubleValue()) { - throw new WrongParameterValueException("Parameter Constraint Error: \n" + - "The parameter value specified has to be " + - "less than " + - highConstraintValue.toString() + - ". (current value: " + t.doubleValue() + ")\n"); - } - } + // higher value + if(highBoundary.equals(IntervalBoundary.CLOSE)) { + if(t.doubleValue() > highConstraintValue.doubleValue()) { + throw new WrongParameterValueException("Parameter Constraint Error: \n" + "The parameter value specified has to be " + "equal to or less than " + highConstraintValue.toString() + ". (current value: " + t.doubleValue() + ")\n"); + } } + else if(highBoundary.equals(IntervalBoundary.OPEN)) { + if(t.doubleValue() >= highConstraintValue.doubleValue()) { + throw new WrongParameterValueException("Parameter Constraint Error: \n" + "The parameter value specified has to be " + "less than " + highConstraintValue.toString() + ". (current value: " + t.doubleValue() + ")\n"); + } + } + } - @Override - public String getDescription(String parameterName) { - String description = parameterName + " in "; - if (lowBoundary.equals(IntervalBoundary.CLOSE)) { - description += "["; - } - else if (lowBoundary.equals(IntervalBoundary.OPEN)) { - description += "("; - } - - description += lowConstraintValue.toString() + ", " + highConstraintValue; - - if (highBoundary.equals(IntervalBoundary.CLOSE)) { - description += "]"; - } - if (highBoundary.equals(IntervalBoundary.OPEN)) { - description += ")"; - } - return description; + @Override + public String getDescription(String parameterName) { + String description = parameterName + " in "; + if(lowBoundary.equals(IntervalBoundary.CLOSE)) { + description += "["; + } + else if(lowBoundary.equals(IntervalBoundary.OPEN)) { + description += "("; } -} + description += lowConstraintValue.toString() + ", " + highConstraintValue; + + if(highBoundary.equals(IntervalBoundary.CLOSE)) { + description += "]"; + } + if(highBoundary.equals(IntervalBoundary.OPEN)) { + description += ")"; + } + return description; + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ListSizeConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ListSizeConstraint.java index f2fef29d..5c6a5156 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ListSizeConstraint.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ListSizeConstraint.java @@ -35,6 +35,9 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ListParameter; * size constraint. * * @author Steffi Wanka + * + * @apiviz.uses de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ListParameter + * * @param <T> Parameter type */ public class ListSizeConstraint<T> implements ParameterConstraint<List<T>> { diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ParameterFlagGlobalConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ParameterFlagGlobalConstraint.java index bb2239b3..4c5b9262 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ParameterFlagGlobalConstraint.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ParameterFlagGlobalConstraint.java @@ -36,6 +36,10 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.Parameter; * the flag the parameter is tested for keeping its constraints or not. * * @author Steffi Wanka + * + * @apiviz.uses de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.Flag + * @apiviz.uses de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.Parameter + * * @param <C> Constraint type * @param <S> Parameter type */ diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/StringLengthConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/StringLengthConstraint.java index 4fc2592c..ac8c48b3 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/StringLengthConstraint.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/StringLengthConstraint.java @@ -32,6 +32,8 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.WrongParameterValueException * . * * @author Erich Schubert + * + * @apiviz.uses de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.StringParameter */ public class StringLengthConstraint implements ParameterConstraint<String> { /** diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/EmptyParameterization.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/EmptyParameterization.java index 6def810a..05a85b49 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/EmptyParameterization.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/EmptyParameterization.java @@ -37,7 +37,6 @@ public class EmptyParameterization extends AbstractParameterization { return false; } - @SuppressWarnings("unused") @Override public boolean setValueForOption(Parameter<?,?> opt) throws ParameterException { // Always return false, we don't have extra parameters, @@ -49,7 +48,7 @@ public class EmptyParameterization extends AbstractParameterization { * Default implementation, for flat parameterizations. */ @Override - public Parameterization descend(@SuppressWarnings("unused") Object option) { + public Parameterization descend(Object option) { return this; } }
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/ListParameterization.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/ListParameterization.java index 8366a089..8e751fe7 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/ListParameterization.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/ListParameterization.java @@ -138,7 +138,7 @@ public class ListParameterization extends AbstractParameterization { * Default implementation, for flat parameterizations. */ @Override - public Parameterization descend(@SuppressWarnings("unused") Object option) { + public Parameterization descend(Object option) { return this; } diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/SerializedParameterization.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/SerializedParameterization.java index 6d19cfd5..a4eeda1a 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/SerializedParameterization.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/SerializedParameterization.java @@ -166,7 +166,7 @@ public class SerializedParameterization extends AbstractParameterization { * Default implementation, for flat parameterizations. */ @Override - public Parameterization descend(@SuppressWarnings("unused") Object option) { + public Parameterization descend(Object option) { return this; } }
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/UnParameterization.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/UnParameterization.java index 4704e1da..5fc930db 100644 --- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/UnParameterization.java +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/UnParameterization.java @@ -51,7 +51,6 @@ public class UnParameterization implements Parameterization { } @Override - @SuppressWarnings("unused") public boolean checkConstraint(GlobalParameterConstraint constraint) { return false; } @@ -67,7 +66,6 @@ public class UnParameterization implements Parameterization { } @Override - @SuppressWarnings("unused") public boolean grab(Parameter<?, ?> opt) { return false; } @@ -78,13 +76,12 @@ public class UnParameterization implements Parameterization { } @Override - @SuppressWarnings("unused") public boolean setValueForOption(Parameter<?, ?> opt) throws ParameterException { return false; } @Override - public Parameterization descend(@SuppressWarnings("unused") Object option) { + public Parameterization descend(Object option) { return this; } diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/EnumParameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/EnumParameter.java new file mode 100644 index 00000000..afab86c8 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/EnumParameter.java @@ -0,0 +1,167 @@ +package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2011
+ 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 <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.ParameterException;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.UnspecifiedParameterException;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.WrongParameterValueException;
+
+/**
+ * Parameter class for a parameter specifying an enum type.
+ *
+ * <p>
+ * Usage:
+ *
+ * <pre>
+ * // Enum declaration.
+ * enum MyEnum { VALUE1, VALUE2 };
+ * // Parameter value holder.
+ * MyEnum myEnumParameter;
+ *
+ * // ...
+ *
+ * // Parameterization.
+ * EnumParameter<MyEnum> param = new EnumParameter<MyEnum>(ENUM_PROPERTY_ID, MyEnum.class);
+ * // OR
+ * EnumParameter<MyEnum> param = new EnumParameter<MyEnum>(ENUM_PROPERTY_ID, MyEnum.class, MyEnum.VALUE1);
+ * // OR
+ * EnumParameter<MyEnum> param = new EnumParameter<MyEnum>(ENUM_PROPERTY_ID, MyEnum.class, true);
+ *
+ * if(config.grab(param)) {
+ * myEnumParameter = param.getValue();
+ * }
+ *
+ * </p>
+ *
+ * @author Florian Nuecke
+ *
+ * @param <E> Enum type
+ */
+public class EnumParameter<E extends Enum<E>> extends Parameter<Enum<E>, E> {
+
+ /**
+ * Reference to the actual enum type, for T.valueOf().
+ */
+ protected Class<E> enumClass;
+
+ /**
+ * Constructs an enum parameter with the given optionID, constraints and
+ * default value.
+ *
+ * @param optionID the unique id of the parameter
+ * @param defaultValue the default value of the parameter
+ */
+ public EnumParameter(OptionID optionID, Class<E> enumClass, E defaultValue) {
+ super(optionID, defaultValue);
+ this.enumClass = enumClass;
+ }
+
+ /**
+ * Constructs an enum parameter with the given optionID, constraints and
+ * default value.
+ *
+ * @param optionID the unique id of the parameter
+ * @param optional Flag to signal an optional parameter.
+ */
+ public EnumParameter(OptionID optionID, Class<E> enumClass, boolean optional) {
+ super(optionID, optional);
+ this.enumClass = enumClass;
+ }
+
+ /**
+ * Constructs an enum parameter with the given optionID, constraints and
+ * default value.
+ *
+ * @param optionID the unique id of the parameter
+ */
+ public EnumParameter(OptionID optionID, Class<E> enumClass) {
+ super(optionID);
+ this.enumClass = enumClass;
+ }
+
+ @Override
+ public String getSyntax() {
+ return "<" + joinEnumNames(" | ") + ">";
+ }
+
+ @Override
+ protected E parseValue(Object obj) throws ParameterException {
+ if(obj == null) {
+ throw new UnspecifiedParameterException("Parameter \"" + getName() + "\": Null value given!");
+ }
+ if(obj instanceof String) {
+ try {
+ return Enum.valueOf(enumClass, (String) obj);
+ }
+ catch(IllegalArgumentException ex) {
+ throw new WrongParameterValueException("Enum parameter " + getName() + " is invalid (must be one of [" + joinEnumNames(", ") + "].");
+ }
+ }
+ throw new WrongParameterValueException("Enum parameter " + getName() + " is not given as a string.");
+ }
+
+ @Override
+ public String getValueAsString() {
+ return getValue().name();
+ }
+
+ /**
+ * Get a list of possible values for this enum parameter.
+ *
+ * @return list of strings representing possible enum values.
+ */
+ public Collection<String> getPossibleValues() {
+ // Convert to string array
+ final E[] enums = enumClass.getEnumConstants();
+ ArrayList<String> values = new ArrayList<String>(enums.length);
+ for(E t : enums) {
+ values.add(t.name());
+ }
+ return values;
+ }
+
+ /**
+ * Utility method for merging possible values into a string for informational
+ * messages.
+ *
+ * @param separator char sequence to use as a separator for enum values.
+ * @return <code>{VAL1}{separator}{VAL2}{separator}...</code>
+ */
+ private String joinEnumNames(String separator) {
+ E[] enumTypes = enumClass.getEnumConstants();
+ StringBuilder sb = new StringBuilder();
+ for(int i = 0; i < enumTypes.length; ++i) {
+ if(i > 0) {
+ sb.append(separator);
+ }
+ sb.append(enumTypes[i].name());
+ }
+ return sb.toString();
+ }
+
+}
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/VisualizationTask.java b/src/de/lmu/ifi/dbs/elki/visualization/VisualizationTask.java index c648a9dd..04d2c5eb 100644 --- a/src/de/lmu/ifi/dbs/elki/visualization/VisualizationTask.java +++ b/src/de/lmu/ifi/dbs/elki/visualization/VisualizationTask.java @@ -38,7 +38,7 @@ import de.lmu.ifi.dbs.elki.visualization.visualizers.VisFactory; * @apiviz.landmark * @apiviz.composedOf VisFactory * @apiviz.has SVGPlot - * @apiviz.has VisualizerContext + * @apiviz.has VisFactory * @apiviz.has Projection oneway - 0:1 * @apiviz.has Visualization oneway */ diff --git a/src/de/lmu/ifi/dbs/elki/visualization/VisualizerContext.java b/src/de/lmu/ifi/dbs/elki/visualization/VisualizerContext.java index ed30f3a3..532e7de5 100644 --- a/src/de/lmu/ifi/dbs/elki/visualization/VisualizerContext.java +++ b/src/de/lmu/ifi/dbs/elki/visualization/VisualizerContext.java @@ -397,17 +397,15 @@ public class VisualizerContext extends AnyMap<String> implements DataStoreListen } @Override - public void resultAdded(Result child, @SuppressWarnings("unused") Result parent) { + public void resultAdded(Result child, Result parent) { processNewResult(getResult(), child); } - @SuppressWarnings("unused") @Override public void resultChanged(Result current) { // FIXME: need to do anything? } - @SuppressWarnings("unused") @Override public void resultRemoved(Result child, Result parent) { // FIXME: implement diff --git a/src/de/lmu/ifi/dbs/elki/visualization/batikutil/JSVGUpdateSynchronizer.java b/src/de/lmu/ifi/dbs/elki/visualization/batikutil/JSVGUpdateSynchronizer.java index 96d99002..0ecb6e0e 100644 --- a/src/de/lmu/ifi/dbs/elki/visualization/batikutil/JSVGUpdateSynchronizer.java +++ b/src/de/lmu/ifi/dbs/elki/visualization/batikutil/JSVGUpdateSynchronizer.java @@ -226,12 +226,12 @@ class JSVGUpdateSynchronizer implements UpdateSynchronizer { * React to an update manager becoming available. */ @Override - public void managerStarted(@SuppressWarnings("unused") UpdateManagerEvent e) { + public void managerStarted(UpdateManagerEvent e) { makeRunnerIfNeeded(); } @Override - public void managerStopped(@SuppressWarnings("unused") UpdateManagerEvent e) { + public void managerStopped(UpdateManagerEvent e) { forgetSynchronizedRunner(); } } diff --git a/src/de/lmu/ifi/dbs/elki/visualization/gui/ResultWindow.java b/src/de/lmu/ifi/dbs/elki/visualization/gui/ResultWindow.java index a3b8a458..c5bdf408 100644 --- a/src/de/lmu/ifi/dbs/elki/visualization/gui/ResultWindow.java +++ b/src/de/lmu/ifi/dbs/elki/visualization/gui/ResultWindow.java @@ -165,7 +165,7 @@ public class ResultWindow extends JFrame implements ResultListener { exportItem.setEnabled(false); exportItem.addActionListener(new ActionListener() { @Override - public void actionPerformed(@SuppressWarnings("unused") ActionEvent ae) { + public void actionPerformed(ActionEvent ae) { saveCurrentPlot(); } }); @@ -174,7 +174,7 @@ public class ResultWindow extends JFrame implements ResultListener { quitItem.setMnemonic(KeyEvent.VK_Q); quitItem.addActionListener(new ActionListener() { @Override - public void actionPerformed(@SuppressWarnings("unused") ActionEvent e) { + public void actionPerformed(ActionEvent e) { close(); } }); @@ -184,7 +184,7 @@ public class ResultWindow extends JFrame implements ResultListener { overviewItem.setEnabled(false); overviewItem.addActionListener(new ActionListener() { @Override - public void actionPerformed(@SuppressWarnings("unused") ActionEvent ae) { + public void actionPerformed(ActionEvent ae) { showOverview(); } }); @@ -193,7 +193,7 @@ public class ResultWindow extends JFrame implements ResultListener { editItem.setMnemonic(KeyEvent.VK_T); editItem.addActionListener(new ActionListener() { @Override - public void actionPerformed(@SuppressWarnings("unused") ActionEvent ae) { + public void actionPerformed(ActionEvent ae) { showTableView(); } }); @@ -416,7 +416,7 @@ public class ResultWindow extends JFrame implements ResultListener { final JCheckBoxMenuItem visItem = new JCheckBoxMenuItem(name, enabled); visItem.addItemListener(new ItemListener() { @Override - public void itemStateChanged(@SuppressWarnings("unused") ItemEvent e) { + public void itemStateChanged(ItemEvent e) { // We need SwingUtilities to avoid a deadlock! SwingUtilities.invokeLater(new Runnable() { @Override @@ -432,7 +432,7 @@ public class ResultWindow extends JFrame implements ResultListener { final JRadioButtonMenuItem visItem = new JRadioButtonMenuItem(name, enabled); visItem.addItemListener(new ItemListener() { @Override - public void itemStateChanged(@SuppressWarnings("unused") ItemEvent e) { + public void itemStateChanged(ItemEvent e) { // We need SwingUtilities to avoid a deadlock! SwingUtilities.invokeLater(new Runnable() { @Override @@ -448,19 +448,16 @@ public class ResultWindow extends JFrame implements ResultListener { return null; } - @SuppressWarnings("unused") @Override public void resultAdded(Result child, Result parent) { updateVisualizerMenus(); } - @SuppressWarnings("unused") @Override public void resultChanged(Result current) { updateVisualizerMenus(); } - @SuppressWarnings("unused") @Override public void resultRemoved(Result child, Result parent) { updateVisualizerMenus(); diff --git a/src/de/lmu/ifi/dbs/elki/visualization/gui/SelectionTableWindow.java b/src/de/lmu/ifi/dbs/elki/visualization/gui/SelectionTableWindow.java index c2190e63..6bcf5f0b 100644 --- a/src/de/lmu/ifi/dbs/elki/visualization/gui/SelectionTableWindow.java +++ b/src/de/lmu/ifi/dbs/elki/visualization/gui/SelectionTableWindow.java @@ -163,14 +163,14 @@ public class SelectionTableWindow extends JFrame implements DataStoreListener, R closeButton = new JButton("close");
closeButton.addActionListener(new ActionListener() {
@Override
- public void actionPerformed(@SuppressWarnings("unused") ActionEvent arg0) {
+ public void actionPerformed(ActionEvent arg0) {
dispose();
}
});
deleteButton = new JButton("delete");
deleteButton.addActionListener(new ActionListener() {
@Override
- public void actionPerformed(@SuppressWarnings("unused") ActionEvent arg0) {
+ public void actionPerformed(ActionEvent arg0) {
handleDelete();
}
});
@@ -291,7 +291,7 @@ public class SelectionTableWindow extends JFrame implements DataStoreListener, R }
@Override
- public boolean isCellEditable(@SuppressWarnings("unused") int rowIndex, int columnIndex) {
+ public boolean isCellEditable(int rowIndex, int columnIndex) {
if(columnIndex == 0) {
return false;
}
@@ -310,8 +310,7 @@ public class SelectionTableWindow extends JFrame implements DataStoreListener, R }
if(columnIndex == 2 && aValue instanceof String) {
// FIXME: better class label handling!
- SimpleClassLabel lbl = new SimpleClassLabel();
- lbl.init((String) aValue);
+ SimpleClassLabel lbl = new SimpleClassLabel((String) aValue);
crep.set(id, lbl);
}
if(!(aValue instanceof String)) {
@@ -361,13 +360,11 @@ public class SelectionTableWindow extends JFrame implements DataStoreListener, R }
}
- @SuppressWarnings("unused")
@Override
public void resultAdded(Result child, Result parent) {
// TODO Auto-generated method stub
}
- @SuppressWarnings("unused")
@Override
public void resultRemoved(Result child, Result parent) {
// TODO Auto-generated method stub
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/gui/SimpleSVGViewer.java b/src/de/lmu/ifi/dbs/elki/visualization/gui/SimpleSVGViewer.java index e249eed3..a08be9b5 100644 --- a/src/de/lmu/ifi/dbs/elki/visualization/gui/SimpleSVGViewer.java +++ b/src/de/lmu/ifi/dbs/elki/visualization/gui/SimpleSVGViewer.java @@ -84,7 +84,7 @@ public class SimpleSVGViewer extends JFrame { exportItem.setMnemonic(KeyEvent.VK_E); exportItem.addActionListener(new ActionListener() { @Override - public void actionPerformed(@SuppressWarnings("unused") ActionEvent ae) { + public void actionPerformed(ActionEvent ae) { saveCurrentPlot(); } }); @@ -93,7 +93,7 @@ public class SimpleSVGViewer extends JFrame { quitItem.setMnemonic(KeyEvent.VK_Q); quitItem.addActionListener(new ActionListener() { @Override - public void actionPerformed(@SuppressWarnings("unused") ActionEvent e) { + public void actionPerformed(ActionEvent e) { close(); } }); diff --git a/src/de/lmu/ifi/dbs/elki/visualization/gui/detail/DetailView.java b/src/de/lmu/ifi/dbs/elki/visualization/gui/detail/DetailView.java index 99bbc78d..341aa69f 100644 --- a/src/de/lmu/ifi/dbs/elki/visualization/gui/detail/DetailView.java +++ b/src/de/lmu/ifi/dbs/elki/visualization/gui/detail/DetailView.java @@ -52,9 +52,9 @@ import de.lmu.ifi.dbs.elki.visualization.visualizers.VisualizerUtil; * * @author Erich Schubert * - * @apiviz.has VisualizerContext * @apiviz.has Visualization * @apiviz.has PlotItem + * @apiviz.uses VisualizerContext * @apiviz.uses VisualizationTask */ public class DetailView extends SVGPlot implements ResultListener { @@ -245,7 +245,6 @@ public class DetailView extends SVGPlot implements ResultListener { } } - @SuppressWarnings("unused") @Override public void resultAdded(Result child, Result parent) { // Ignore. The PlotItem will need to change. @@ -285,7 +284,6 @@ public class DetailView extends SVGPlot implements ResultListener { } } - @SuppressWarnings("unused") @Override public void resultRemoved(Result child, Result parent) { // Ignore. The PlotItem will need to change. diff --git a/src/de/lmu/ifi/dbs/elki/visualization/gui/overview/OverviewPlot.java b/src/de/lmu/ifi/dbs/elki/visualization/gui/overview/OverviewPlot.java index 5c8b8d44..f05719ae 100644 --- a/src/de/lmu/ifi/dbs/elki/visualization/gui/overview/OverviewPlot.java +++ b/src/de/lmu/ifi/dbs/elki/visualization/gui/overview/OverviewPlot.java @@ -64,7 +64,7 @@ import de.lmu.ifi.dbs.elki.visualization.visualizers.VisualizerUtil; * * @apiviz.landmark * @apiviz.has VisualizerContext - * @apiviz.composedOf PlotMap + * @apiviz.composedOf RectangleArranger * @apiviz.has DetailViewSelectedEvent * @apiviz.uses DetailView * @apiviz.uses de.lmu.ifi.dbs.elki.visualization.projections.Projection @@ -300,31 +300,33 @@ public class OverviewPlot extends SVGPlot implements ResultListener { boolean refreshcss = false; final int thumbsize = (int) Math.max(screenwidth / plotmap.getWidth(), screenheight / plotmap.getHeight()); for(Entry<PlotItem, double[]> ent : plotmap.entrySet()) { - PlotItem it = ent.getKey(); - for(Iterator<VisualizationTask> iter = it.visIterator(); iter.hasNext(); ) { - VisualizationTask task = iter.next(); - Element parent = vistoelem.get(new Pair<PlotItem, VisualizationTask>(it, task)); - if(parent == null) { - LoggingUtil.warning("No container element produced by " + task); - continue; - } - if(VisualizerUtil.thumbnailEnabled(task) && VisualizerUtil.isVisible(task)) { - // unhide when hidden. - if(parent.hasAttribute(SVGConstants.CSS_VISIBILITY_PROPERTY)) { - parent.removeAttribute(SVGConstants.CSS_VISIBILITY_PROPERTY); + for(Iterator<PlotItem> iter = ent.getKey().itemIterator(); iter.hasNext();) { + PlotItem it = iter.next(); + + for(VisualizationTask task : it.visualizations) { + Element parent = vistoelem.get(new Pair<PlotItem, VisualizationTask>(it, task)); + if(parent == null) { + LoggingUtil.warning("No container element found for " + task); + continue; } - // if not yet rendered, add a thumbnail - if(!parent.hasChildNodes()) { - makeThumbnail(thumbsize, it, task, parent); - refreshcss = true; + if(VisualizerUtil.thumbnailEnabled(task) && VisualizerUtil.isVisible(task)) { + // unhide when hidden. + if(parent.hasAttribute(SVGConstants.CSS_VISIBILITY_PROPERTY)) { + parent.removeAttribute(SVGConstants.CSS_VISIBILITY_PROPERTY); + } + // if not yet rendered, add a thumbnail + if(!parent.hasChildNodes()) { + makeThumbnail(thumbsize, it, task, parent); + refreshcss = true; + } } - } - else { - // hide if there is anything to hide. - if(parent != null && parent.hasChildNodes()) { - parent.setAttribute(SVGConstants.CSS_VISIBILITY_PROPERTY, SVGConstants.CSS_HIDDEN_VALUE); + else { + // hide if there is anything to hide. + if(parent != null && parent.hasChildNodes()) { + parent.setAttribute(SVGConstants.CSS_VISIBILITY_PROPERTY, SVGConstants.CSS_HIDDEN_VALUE); + } + // TODO: unqueue pending thumbnails } - // TODO: unqueue pending thumbnails } } } @@ -419,7 +421,7 @@ public class OverviewPlot extends SVGPlot implements ResultListener { } @Override - public void handleEvent(@SuppressWarnings("unused") Event evt) { + public void handleEvent(Event evt) { triggerSubplotSelectEvent(it); } } @@ -464,7 +466,6 @@ public class OverviewPlot extends SVGPlot implements ResultListener { scheduleUpdate(pr); } - @SuppressWarnings("unused") @Override public void resultAdded(Result child, Result parent) { logger.debug("result added: " + child); @@ -480,7 +481,6 @@ public class OverviewPlot extends SVGPlot implements ResultListener { lazyRefresh(); } - @SuppressWarnings("unused") @Override public void resultRemoved(Result child, Result parent) { logger.debug("result removed: " + child); diff --git a/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSColorStatic.java b/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSColorStatic.java index 359d3062..af28008e 100644 --- a/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSColorStatic.java +++ b/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSColorStatic.java @@ -47,7 +47,7 @@ public class OPTICSColorStatic implements OPTICSColorAdapter { } @Override - public int getColorForEntry(@SuppressWarnings("unused") ClusterOrderEntry<?> coe) { + public int getColorForEntry(ClusterOrderEntry<?> coe) { return color; } } diff --git a/src/de/lmu/ifi/dbs/elki/visualization/projector/HistogramFactory.java b/src/de/lmu/ifi/dbs/elki/visualization/projector/HistogramFactory.java index 06e94891..3836379a 100644 --- a/src/de/lmu/ifi/dbs/elki/visualization/projector/HistogramFactory.java +++ b/src/de/lmu/ifi/dbs/elki/visualization/projector/HistogramFactory.java @@ -40,8 +40,9 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter; * Produce one-dimensional projections. * * @author Erich Schubert + * + * @apiviz.has HistogramProjector */ -// TODO: re-add maxdim option public class HistogramFactory implements ProjectorFactory { /** * Maximum dimensionality diff --git a/src/de/lmu/ifi/dbs/elki/visualization/projector/HistogramProjector.java b/src/de/lmu/ifi/dbs/elki/visualization/projector/HistogramProjector.java index 5ddc7b32..40bd55ee 100644 --- a/src/de/lmu/ifi/dbs/elki/visualization/projector/HistogramProjector.java +++ b/src/de/lmu/ifi/dbs/elki/visualization/projector/HistogramProjector.java @@ -46,6 +46,8 @@ import de.lmu.ifi.dbs.elki.visualization.visualizers.visunproj.LabelVisFactory; * * @author Erich Schubert * + * @apiviz.has LinearScale + * * @param <V> Vector type */ public class HistogramProjector<V extends NumberVector<?, ?>> extends AbstractHierarchicalResult implements Projector { @@ -80,21 +82,26 @@ public class HistogramProjector<V extends NumberVector<?, ?>> extends AbstractHi @Override public Collection<PlotItem> arrange() { - List<PlotItem> layout = new ArrayList<PlotItem>(1); + List<PlotItem> layout = new ArrayList<PlotItem>(1 + dmax); List<VisualizationTask> tasks = ResultUtil.filterResults(this, VisualizationTask.class); if (tasks.size() > 0){ - PlotItem master = new PlotItem(dmax + .1, .5 + .1, null); - for(int d1 = 1; d1 <= dmax; d1++) { - Projection1D proj = new Simple1D(scales, d1); - final PlotItem it = new PlotItem(d1 - 1 + .1, 0. + .1, 1., .5, proj); + final double xoff = (dmax > 1) ? .1 : 0.; + final double hheight = .5; + final double lheight = .1; + PlotItem master = new PlotItem(dmax + xoff, hheight + lheight, null); + for(int d1 = 0; d1 < dmax; d1++) { + Projection1D proj = new Simple1D(scales, d1 + 1); + final PlotItem it = new PlotItem(d1 + xoff, lheight, 1., hheight, proj); it.visualizations = tasks; master.subitems.add(it); } layout.add(master); - for(int d1 = 1; d1 <= dmax; d1++) { - PlotItem it = new PlotItem(d1 - 1 + .1, 0, 1., .1, null); - final VisualizationTask task = new VisualizationTask("", null, null, new LabelVisFactory(DatabaseUtil.getColumnLabel(rel, d1))); - task.height = .1; + // Add labels + for(int d1 = 0; d1 < dmax; d1++) { + PlotItem it = new PlotItem(d1 + xoff, 0, 1., lheight, null); + LabelVisFactory lbl = new LabelVisFactory(DatabaseUtil.getColumnLabel(rel, d1 + 1)); + final VisualizationTask task = new VisualizationTask("", null, null, lbl); + task.height = lheight; task.width = 1; task.put(VisualizationTask.META_NODETAIL, true); it.visualizations.add(task); diff --git a/src/de/lmu/ifi/dbs/elki/visualization/projector/OPTICSProjectorFactory.java b/src/de/lmu/ifi/dbs/elki/visualization/projector/OPTICSProjectorFactory.java index 580eb532..25023029 100644 --- a/src/de/lmu/ifi/dbs/elki/visualization/projector/OPTICSProjectorFactory.java +++ b/src/de/lmu/ifi/dbs/elki/visualization/projector/OPTICSProjectorFactory.java @@ -36,6 +36,8 @@ import de.lmu.ifi.dbs.elki.visualization.opticsplot.OPTICSPlot; * Produce OPTICS plot projections * * @author Erich Schubert + * + * @apiviz.has OPTICSProjector */ public class OPTICSProjectorFactory implements ProjectorFactory { /** diff --git a/src/de/lmu/ifi/dbs/elki/visualization/projector/ProjectorFactory.java b/src/de/lmu/ifi/dbs/elki/visualization/projector/ProjectorFactory.java index d0996822..3dbb803f 100644 --- a/src/de/lmu/ifi/dbs/elki/visualization/projector/ProjectorFactory.java +++ b/src/de/lmu/ifi/dbs/elki/visualization/projector/ProjectorFactory.java @@ -33,6 +33,8 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable; * detecting appropriate relations in the database. * * @author Erich Schubert + * + * @apiviz.has Projector */ public interface ProjectorFactory extends ResultProcessor, Parameterizable { /** diff --git a/src/de/lmu/ifi/dbs/elki/visualization/projector/ScatterPlotFactory.java b/src/de/lmu/ifi/dbs/elki/visualization/projector/ScatterPlotFactory.java index 3d996bdc..5957233d 100644 --- a/src/de/lmu/ifi/dbs/elki/visualization/projector/ScatterPlotFactory.java +++ b/src/de/lmu/ifi/dbs/elki/visualization/projector/ScatterPlotFactory.java @@ -41,8 +41,9 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter; * Produce scatterplot projections. * * @author Erich Schubert + * + * @apiviz.has ScatterPlotProjector */ -// TODO: re-add maxdim option public class ScatterPlotFactory implements ProjectorFactory { /** * Maximum number of dimensions to visualize. @@ -114,7 +115,7 @@ public class ScatterPlotFactory implements ProjectorFactory { } @Override - protected Object makeInstance() { + protected ScatterPlotFactory makeInstance() { return new ScatterPlotFactory(maxdim); } } diff --git a/src/de/lmu/ifi/dbs/elki/visualization/projector/ScatterPlotProjector.java b/src/de/lmu/ifi/dbs/elki/visualization/projector/ScatterPlotProjector.java index ee692531..a090f523 100644 --- a/src/de/lmu/ifi/dbs/elki/visualization/projector/ScatterPlotProjector.java +++ b/src/de/lmu/ifi/dbs/elki/visualization/projector/ScatterPlotProjector.java @@ -48,9 +48,10 @@ import de.lmu.ifi.dbs.elki.visualization.visualizers.visunproj.LabelVisFactory; * * @author Erich Schubert * + * @apiviz.has LinearScale + * * @param <V> Vector type */ -// FIXME: re-add column labels public class ScatterPlotProjector<V extends NumberVector<?, ?>> extends AbstractHierarchicalResult implements Projector { /** * Relation we project diff --git a/src/de/lmu/ifi/dbs/elki/visualization/savedialog/SaveOptionsPanel.java b/src/de/lmu/ifi/dbs/elki/visualization/savedialog/SaveOptionsPanel.java index 9a678218..9c41fbab 100644 --- a/src/de/lmu/ifi/dbs/elki/visualization/savedialog/SaveOptionsPanel.java +++ b/src/de/lmu/ifi/dbs/elki/visualization/savedialog/SaveOptionsPanel.java @@ -171,7 +171,7 @@ public class SaveOptionsPanel extends JPanel { spinnerWidth = new JSpinner(modelWidth); spinnerWidth.addChangeListener(new ChangeListener() { @Override - public void stateChanged(@SuppressWarnings("unused") ChangeEvent e) { + public void stateChanged(ChangeEvent e) { if(aspectRatioLock.isSelected()) { int val = modelWidth.getNumber().intValue(); spinnerHeight.setValue(new Integer((int) Math.round(val / ratio))); @@ -183,7 +183,7 @@ public class SaveOptionsPanel extends JPanel { spinnerHeight = new JSpinner(modelHeight); spinnerHeight.addChangeListener(new ChangeListener() { @Override - public void stateChanged(@SuppressWarnings("unused") ChangeEvent e) { + public void stateChanged(ChangeEvent e) { if(aspectRatioLock.isSelected()) { int val = modelHeight.getNumber().intValue(); spinnerWidth.setValue(new Integer((int) Math.round(val * ratio))); @@ -207,7 +207,7 @@ public class SaveOptionsPanel extends JPanel { resetSizeButton = new JButton(STR_RESET_IMAGE_SIZE); resetSizeButton.addActionListener(new ActionListener() { @Override - public void actionPerformed(@SuppressWarnings("unused") ActionEvent e) { + public void actionPerformed(ActionEvent e) { modelWidth.setValue(width); modelHeight.setValue(height); aspectRatioLock.setSelected(true); diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/AbstractVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/AbstractVisualization.java index 8d1b184d..dab1c6dd 100644 --- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/AbstractVisualization.java +++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/AbstractVisualization.java @@ -169,7 +169,6 @@ public abstract class AbstractVisualization implements Visualization, ContextCha */ protected abstract void redraw(); - @SuppressWarnings("unused") @Override public void resultAdded(Result child, Result parent) { // Ignore by default @@ -183,7 +182,6 @@ public abstract class AbstractVisualization implements Visualization, ContextCha } } - @SuppressWarnings("unused") @Override public void resultRemoved(Result child, Result parent) { // Ignore by default. diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/AbstractOPTICSVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/AbstractOPTICSVisualization.java index 9cb95c23..bcf25a84 100644 --- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/AbstractOPTICSVisualization.java +++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/AbstractOPTICSVisualization.java @@ -39,7 +39,9 @@ import de.lmu.ifi.dbs.elki.visualization.visualizers.AbstractVisualization; * Abstract base class for OPTICS visualizer * * @author Erich Schubert - * + * + * @apiviz.uses OPTICSProjector + * * @param <D> */ public abstract class AbstractOPTICSVisualization<D extends Distance<D>> extends AbstractVisualization { @@ -47,12 +49,12 @@ public abstract class AbstractOPTICSVisualization<D extends Distance<D>> extends * The plot */ final protected OPTICSProjector<D> optics; - + /** * Width of plot (in display units) */ protected double plotwidth; - + /** * Height of plot (in display units) */ @@ -60,7 +62,7 @@ public abstract class AbstractOPTICSVisualization<D extends Distance<D>> extends /** * Constructor. - * + * * @param task Visualization task. */ public AbstractOPTICSVisualization(VisualizationTask task) { @@ -79,7 +81,7 @@ public abstract class AbstractOPTICSVisualization<D extends Distance<D>> extends final String transform = SVGUtil.makeMarginTransform(task.getWidth(), task.getHeight(), plotwidth, plotheight, margin / 2); SVGUtil.setAtt(layer, SVGConstants.SVG_TRANSFORM_ATTRIBUTE, transform); } - + /** * Access the raw cluster order * diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSClusterVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSClusterVisualization.java index 0898d9d0..542dcea7 100644 --- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSClusterVisualization.java +++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSClusterVisualization.java @@ -53,8 +53,7 @@ import de.lmu.ifi.dbs.elki.visualization.visualizers.Visualization; * * @author Erich Schubert * - * @apiviz.uses ClusterOrderResult - * @apiviz.uses OPTICSPlot + * @apiviz.uses Clustering oneway - - «visualizes» * * @param <D> Distance type (actually unused) */ @@ -210,7 +209,7 @@ public class OPTICSClusterVisualization<D extends Distance<D>> extends AbstractO } @Override - public boolean allowThumbnails(@SuppressWarnings("unused") VisualizationTask task) { + public boolean allowThumbnails(VisualizationTask task) { // Don't use thumbnails return false; } diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSPlotCutVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSPlotCutVisualization.java index 9f2a5734..08ca7504 100644 --- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSPlotCutVisualization.java +++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSPlotCutVisualization.java @@ -57,9 +57,6 @@ import de.lmu.ifi.dbs.elki.visualization.visualizers.Visualization; *
* @author Heidi Kolb
*
- * @apiviz.uses ClusterOrderResult oneway - 1 visualizes
- * @apiviz.uses OPTICSPlot oneway - 1 visualizes
- *
* @param <D> distance type
*/
public class OPTICSPlotCutVisualization<D extends Distance<D>> extends AbstractOPTICSVisualization<D> implements DragableArea.DragListener {
@@ -204,7 +201,7 @@ public class OPTICSPlotCutVisualization<D extends Distance<D>> extends AbstractO }
@Override
- public boolean startDrag(SVGPoint start, @SuppressWarnings("unused") Event evt) {
+ public boolean startDrag(SVGPoint start, Event evt) {
epsilon = getEpsilonFromY(plotheight - start.getY());
// opvis.unsetEpsilonExcept(this);
synchronizedRedraw();
@@ -212,7 +209,7 @@ public class OPTICSPlotCutVisualization<D extends Distance<D>> extends AbstractO }
@Override
- public boolean duringDrag(@SuppressWarnings("unused") SVGPoint start, SVGPoint end, @SuppressWarnings("unused") Event evt, boolean inside) {
+ public boolean duringDrag(SVGPoint start, SVGPoint end, Event evt, boolean inside) {
if(inside) {
epsilon = getEpsilonFromY(plotheight - end.getY());
}
@@ -222,7 +219,7 @@ public class OPTICSPlotCutVisualization<D extends Distance<D>> extends AbstractO }
@Override
- public boolean endDrag(@SuppressWarnings("unused") SVGPoint start, SVGPoint end, @SuppressWarnings("unused") Event evt, boolean inside) {
+ public boolean endDrag(SVGPoint start, SVGPoint end, Event evt, boolean inside) {
if(inside) {
epsilon = getEpsilonFromY(plotheight - end.getY());
// opvis.unsetEpsilonExcept(this);
@@ -294,7 +291,7 @@ public class OPTICSPlotCutVisualization<D extends Distance<D>> extends AbstractO }
@Override
- public boolean allowThumbnails(@SuppressWarnings("unused") VisualizationTask task) {
+ public boolean allowThumbnails(VisualizationTask task) {
// Don't use thumbnails
return false;
}
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSPlotSelectionVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSPlotSelectionVisualization.java index b75bd3b5..69bc781e 100644 --- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSPlotSelectionVisualization.java +++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSPlotSelectionVisualization.java @@ -59,8 +59,6 @@ import de.lmu.ifi.dbs.elki.visualization.visualizers.Visualization; *
* @author Heidi Kolb
*
- * @apiviz.uses ClusterOrderResult oneway - 1
- * @apiviz.uses OPTICSPlot oneway - 1
* @apiviz.uses DBIDSelection oneway - 1 visualizes
*
* @param <D> distance type
@@ -181,7 +179,7 @@ public class OPTICSPlotSelectionVisualization<D extends Distance<D>> extends Abs }
@Override
- public boolean startDrag(SVGPoint startPoint, @SuppressWarnings("unused") Event evt) {
+ public boolean startDrag(SVGPoint startPoint, Event evt) {
List<ClusterOrderEntry<D>> order = getClusterOrder();
int mouseActIndex = getSelectedIndex(order, startPoint);
if(mouseActIndex >= 0 && mouseActIndex < order.size()) {
@@ -196,7 +194,7 @@ public class OPTICSPlotSelectionVisualization<D extends Distance<D>> extends Abs }
@Override
- public boolean duringDrag(SVGPoint startPoint, SVGPoint dragPoint, @SuppressWarnings("unused") Event evt, @SuppressWarnings("unused") boolean inside) {
+ public boolean duringDrag(SVGPoint startPoint, SVGPoint dragPoint, Event evt, boolean inside) {
List<ClusterOrderEntry<D>> order = getClusterOrder();
int mouseDownIndex = getSelectedIndex(order, startPoint);
int mouseActIndex = getSelectedIndex(order, dragPoint);
@@ -213,7 +211,7 @@ public class OPTICSPlotSelectionVisualization<D extends Distance<D>> extends Abs }
@Override
- public boolean endDrag(SVGPoint startPoint, SVGPoint dragPoint, Event evt, @SuppressWarnings("unused") boolean inside) {
+ public boolean endDrag(SVGPoint startPoint, SVGPoint dragPoint, Event evt, boolean inside) {
List<ClusterOrderEntry<D>> order = getClusterOrder();
int mouseDownIndex = getSelectedIndex(order, startPoint);
int mouseActIndex = getSelectedIndex(order, dragPoint);
@@ -366,7 +364,7 @@ public class OPTICSPlotSelectionVisualization<D extends Distance<D>> extends Abs }
@Override
- public boolean allowThumbnails(@SuppressWarnings("unused") VisualizationTask task) {
+ public boolean allowThumbnails(VisualizationTask task) {
// Don't use thumbnails
return false;
}
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSPlotVisualizer.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSPlotVisualizer.java index 4af5d466..7f4e3248 100644 --- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSPlotVisualizer.java +++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSPlotVisualizer.java @@ -51,9 +51,6 @@ import de.lmu.ifi.dbs.elki.visualization.visualizers.Visualization; * * @author Erich Schubert * - * @apiviz.has OPTICSPlot oneway - 1 visualizes - * @apiviz.has ClusterOrderResult oneway - 1 visualizes - * * @param <D> Distance type */ public class OPTICSPlotVisualizer<D extends Distance<D>> extends AbstractOPTICSVisualization<D> { @@ -138,7 +135,7 @@ public class OPTICSPlotVisualizer<D extends Distance<D>> extends AbstractOPTICSV } @Override - public boolean allowThumbnails(@SuppressWarnings("unused") VisualizationTask task) { + public boolean allowThumbnails(VisualizationTask task) { // Don't use thumbnails return false; } diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSSteepAreaVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSSteepAreaVisualization.java index f9430145..b082836f 100644 --- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSSteepAreaVisualization.java +++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSSteepAreaVisualization.java @@ -215,7 +215,7 @@ public class OPTICSSteepAreaVisualization<D extends Distance<D>> extends Abstrac } @Override - public boolean allowThumbnails(@SuppressWarnings("unused") VisualizationTask task) { + public boolean allowThumbnails(VisualizationTask task) { // Don't use thumbnails return false; } diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/thumbs/ThumbnailVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/thumbs/ThumbnailVisualization.java index e352d599..25f55d41 100644 --- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/thumbs/ThumbnailVisualization.java +++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/thumbs/ThumbnailVisualization.java @@ -152,7 +152,7 @@ public class ThumbnailVisualization extends AbstractVisualization implements Thu } @Override - public void contentChanged(@SuppressWarnings("unused") DataStoreEvent e) { + public void contentChanged(DataStoreEvent e) { refreshThumbnail(); } diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/AbstractTooltipVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/AbstractTooltipVisualization.java index 9b8d19b6..4e0171ae 100644 --- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/AbstractTooltipVisualization.java +++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/AbstractTooltipVisualization.java @@ -172,7 +172,7 @@ public abstract class AbstractTooltipVisualization<NV extends NumberVector<NV, ? abstract protected void setupCSS(SVGPlot svgp); @Override - public void contentChanged(@SuppressWarnings("unused") DataStoreEvent e) { + public void contentChanged(DataStoreEvent e) { synchronizedRedraw(); } }
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/AxisVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/AxisVisualization.java index 4e927ace..4dc7e820 100644 --- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/AxisVisualization.java +++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/AxisVisualization.java @@ -158,7 +158,7 @@ public class AxisVisualization<NV extends NumberVector<NV, ?>> extends P2DVisual } @Override - public boolean allowThumbnails(@SuppressWarnings("unused") VisualizationTask task) { + public boolean allowThumbnails(VisualizationTask task) { // Don't use thumbnails return false; } diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/ClusterOrderVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/ClusterOrderVisualization.java index 644083f9..f758ff99 100644 --- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/ClusterOrderVisualization.java +++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/ClusterOrderVisualization.java @@ -108,7 +108,7 @@ public class ClusterOrderVisualization<NV extends NumberVector<NV, ?>> extends P } @Override - public void contentChanged(@SuppressWarnings("unused") DataStoreEvent e) { + public void contentChanged(DataStoreEvent e) { synchronizedRedraw(); } diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/ClusteringVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/ClusteringVisualization.java index 58f71ef3..4bef6e11 100644 --- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/ClusteringVisualization.java +++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/ClusteringVisualization.java @@ -101,7 +101,7 @@ public class ClusteringVisualization<NV extends NumberVector<NV, ?>> extends P2D } @Override - public void contentChanged(@SuppressWarnings("unused") DataStoreEvent e) { + public void contentChanged(DataStoreEvent e) { synchronizedRedraw(); } diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/MoveObjectsToolVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/MoveObjectsToolVisualization.java index 66b442f9..6d798247 100644 --- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/MoveObjectsToolVisualization.java +++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/MoveObjectsToolVisualization.java @@ -95,7 +95,7 @@ public class MoveObjectsToolVisualization<NV extends NumberVector<NV, ?>> extend }
@Override
- public void contextChanged(@SuppressWarnings("unused") ContextChangedEvent e) {
+ public void contextChanged(ContextChangedEvent e) {
synchronizedRedraw();
}
@@ -169,19 +169,19 @@ public class MoveObjectsToolVisualization<NV extends NumberVector<NV, ?>> extend }
@Override
- public boolean startDrag(@SuppressWarnings("unused") SVGPoint startPoint, @SuppressWarnings("unused") Event evt) {
+ public boolean startDrag(SVGPoint startPoint, Event evt) {
return true;
}
@Override
- public boolean duringDrag(SVGPoint startPoint, SVGPoint dragPoint, @SuppressWarnings("unused") Event evt, @SuppressWarnings("unused") boolean inside) {
+ public boolean duringDrag(SVGPoint startPoint, SVGPoint dragPoint, Event evt, boolean inside) {
deleteChildren(rtag);
rtag.appendChild(svgp.svgLine(startPoint.getX(), startPoint.getY(), dragPoint.getX(), dragPoint.getY()));
return true;
}
@Override
- public boolean endDrag(SVGPoint startPoint, SVGPoint dragPoint, @SuppressWarnings("unused") Event evt, @SuppressWarnings("unused") boolean inside) {
+ public boolean endDrag(SVGPoint startPoint, SVGPoint dragPoint, Event evt, boolean inside) {
Vector movingVector = new Vector(2);
movingVector.set(0, dragPoint.getX() - startPoint.getX());
movingVector.set(1, dragPoint.getY() - startPoint.getY());
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/SelectionConvexHullVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/SelectionConvexHullVisualization.java index 9e70ffd8..fde2c00d 100644 --- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/SelectionConvexHullVisualization.java +++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/SelectionConvexHullVisualization.java @@ -140,7 +140,7 @@ public class SelectionConvexHullVisualization<NV extends NumberVector<NV, ?>> ex }
@Override
- public void contentChanged(@SuppressWarnings("unused") DataStoreEvent e) {
+ public void contentChanged(DataStoreEvent e) {
synchronizedRedraw();
}
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/SelectionCubeVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/SelectionCubeVisualization.java index 7f6d9c04..087ec6af 100644 --- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/SelectionCubeVisualization.java +++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/SelectionCubeVisualization.java @@ -95,14 +95,8 @@ public class SelectionCubeVisualization<NV extends NumberVector<NV, ?>> extends */
protected boolean nofill = false;
- /**
- * The result we process
- */
- private SelectionResult result;
-
public SelectionCubeVisualization(VisualizationTask task, boolean nofill) {
super(task);
- this.result = task.getResult();
this.nofill = nofill;
addCSSClasses(svgp);
context.addContextChangeListener(this);
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/SelectionDotVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/SelectionDotVisualization.java index 283eafaa..06167532 100644 --- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/SelectionDotVisualization.java +++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/SelectionDotVisualization.java @@ -75,18 +75,12 @@ public class SelectionDotVisualization<NV extends NumberVector<NV, ?>> extends P public static final String MARKER = "selectionDotMarker";
/**
- * The selection result we work on
- */
- private SelectionResult result;
-
- /**
* Constructor.
*
* @param task Task
*/
public SelectionDotVisualization(VisualizationTask task) {
super(task);
- this.result = task.getResult();
context.addContextChangeListener(this);
context.addResultListener(this);
context.addDataStoreListener(this);
@@ -131,7 +125,7 @@ public class SelectionDotVisualization<NV extends NumberVector<NV, ?>> extends P }
@Override
- public void contentChanged(@SuppressWarnings("unused") DataStoreEvent e) {
+ public void contentChanged(DataStoreEvent e) {
synchronizedRedraw();
}
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/SelectionToolCubeVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/SelectionToolCubeVisualization.java index fc2af9da..ed0b456d 100644 --- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/SelectionToolCubeVisualization.java +++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/SelectionToolCubeVisualization.java @@ -101,18 +101,12 @@ public class SelectionToolCubeVisualization<NV extends NumberVector<NV, ?>> exte private Element etag;
/**
- * Our result
- */
- private SelectionResult result;
-
- /**
* Constructor.
*
* @param task Task
*/
public SelectionToolCubeVisualization(VisualizationTask task) {
super(task);
- this.result = task.getResult();
this.dim = DatabaseUtil.dimensionality(rel);
context.addContextChangeListener(this);
incrementalRedraw();
@@ -125,7 +119,7 @@ public class SelectionToolCubeVisualization<NV extends NumberVector<NV, ?>> exte }
@Override
- public void contextChanged(@SuppressWarnings("unused") ContextChangedEvent e) {
+ public void contextChanged(ContextChangedEvent e) {
synchronizedRedraw();
}
@@ -184,12 +178,12 @@ public class SelectionToolCubeVisualization<NV extends NumberVector<NV, ?>> exte }
@Override
- public boolean startDrag(@SuppressWarnings("unused") SVGPoint startPoint, @SuppressWarnings("unused") Event evt) {
+ public boolean startDrag(SVGPoint startPoint, Event evt) {
return true;
}
@Override
- public boolean duringDrag(SVGPoint startPoint, SVGPoint dragPoint, @SuppressWarnings("unused") Event evt, @SuppressWarnings("unused") boolean inside) {
+ public boolean duringDrag(SVGPoint startPoint, SVGPoint dragPoint, Event evt, boolean inside) {
deleteChildren(rtag);
double x = Math.min(startPoint.getX(), dragPoint.getX());
double y = Math.min(startPoint.getY(), dragPoint.getY());
@@ -200,7 +194,7 @@ public class SelectionToolCubeVisualization<NV extends NumberVector<NV, ?>> exte }
@Override
- public boolean endDrag(SVGPoint startPoint, SVGPoint dragPoint, @SuppressWarnings("unused") Event evt, @SuppressWarnings("unused") boolean inside) {
+ public boolean endDrag(SVGPoint startPoint, SVGPoint dragPoint, Event evt, boolean inside) {
deleteChildren(rtag);
if(startPoint.getX() != dragPoint.getX() || startPoint.getY() != dragPoint.getY()) {
updateSelection(proj, startPoint, dragPoint);
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/SelectionToolDotVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/SelectionToolDotVisualization.java index a50a6cbb..7593dac5 100644 --- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/SelectionToolDotVisualization.java +++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/SelectionToolDotVisualization.java @@ -95,18 +95,12 @@ public class SelectionToolDotVisualization<NV extends NumberVector<NV, ?>> exten Element etag;
/**
- * Our result
- */
- private SelectionResult result;
-
- /**
* Constructor.
*
* @param task Task
*/
public SelectionToolDotVisualization(VisualizationTask task) {
super(task);
- this.result = task.getResult();
context.addContextChangeListener(this);
incrementalRedraw();
}
@@ -118,7 +112,7 @@ public class SelectionToolDotVisualization<NV extends NumberVector<NV, ?>> exten }
@Override
- public void contextChanged(@SuppressWarnings("unused") ContextChangedEvent e) {
+ public void contextChanged(ContextChangedEvent e) {
synchronizedRedraw();
}
@@ -149,12 +143,12 @@ public class SelectionToolDotVisualization<NV extends NumberVector<NV, ?>> exten }
@Override
- public boolean startDrag(@SuppressWarnings("unused") SVGPoint startPoint, @SuppressWarnings("unused") Event evt) {
+ public boolean startDrag(SVGPoint startPoint, Event evt) {
return true;
}
@Override
- public boolean duringDrag(SVGPoint startPoint, SVGPoint dragPoint, @SuppressWarnings("unused") Event evt, @SuppressWarnings("unused") boolean inside) {
+ public boolean duringDrag(SVGPoint startPoint, SVGPoint dragPoint, Event evt, boolean inside) {
deleteChildren(rtag);
double x = Math.min(startPoint.getX(), dragPoint.getX());
double y = Math.min(startPoint.getY(), dragPoint.getY());
@@ -165,7 +159,7 @@ public class SelectionToolDotVisualization<NV extends NumberVector<NV, ?>> exten }
@Override
- public boolean endDrag(SVGPoint startPoint, SVGPoint dragPoint, Event evt, @SuppressWarnings("unused") boolean inside) {
+ public boolean endDrag(SVGPoint startPoint, SVGPoint dragPoint, Event evt, boolean inside) {
Mode mode = getInputMode(evt);
deleteChildren(rtag);
if(startPoint.getX() != dragPoint.getX() || startPoint.getY() != dragPoint.getY()) {
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/ToolBox2DVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/ToolBox2DVisualization.java index ba91975c..c2339fe2 100644 --- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/ToolBox2DVisualization.java +++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/ToolBox2DVisualization.java @@ -107,7 +107,7 @@ public class ToolBox2DVisualization<NV extends NumberVector<NV, ?>> extends P2DV }
@Override
- public void contextChanged(@SuppressWarnings("unused") ContextChangedEvent e) {
+ public void contextChanged(ContextChangedEvent e) {
synchronizedRedraw();
}
@@ -232,7 +232,7 @@ public class ToolBox2DVisualization<NV extends NumberVector<NV, ?>> extends P2DV EventTarget targ = (EventTarget) tag;
targ.addEventListener(SVGConstants.SVG_EVENT_CLICK, new EventListener() {
@Override
- public void handleEvent(@SuppressWarnings("unused") Event evt) {
+ public void handleEvent(Event evt) {
handleMouseClick(tool);
}
}, false);
@@ -252,7 +252,7 @@ public class ToolBox2DVisualization<NV extends NumberVector<NV, ?>> extends P2DV }
@Override
- public void resultAdded(Result child, @SuppressWarnings("unused") Result parent) {
+ public void resultAdded(Result child, Result parent) {
if(child instanceof VisualizationTask) {
VisualizationTask task = (VisualizationTask) child;
if(VisualizerUtil.isTool(task)) {
@@ -262,7 +262,7 @@ public class ToolBox2DVisualization<NV extends NumberVector<NV, ?>> extends P2DV }
@Override
- public void resultRemoved(Result child, @SuppressWarnings("unused") Result parent) {
+ public void resultRemoved(Result child, Result parent) {
if(child instanceof VisualizationTask) {
VisualizationTask task = (VisualizationTask) child;
if(VisualizerUtil.isTool(task)) {
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/TreeMBRVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/TreeMBRVisualization.java index 5fe6aac2..cc3dfbe8 100644 --- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/TreeMBRVisualization.java +++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/TreeMBRVisualization.java @@ -179,7 +179,7 @@ public class TreeMBRVisualization<NV extends NumberVector<NV, ?>, N extends Abst } @Override - public void contentChanged(@SuppressWarnings("unused") DataStoreEvent e) { + public void contentChanged(DataStoreEvent e) { synchronizedRedraw(); } diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/TreeSphereVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/TreeSphereVisualization.java index 1aec1ead..73a02ddb 100644 --- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/TreeSphereVisualization.java +++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/TreeSphereVisualization.java @@ -248,7 +248,7 @@ public class TreeSphereVisualization<NV extends NumberVector<NV, ?>, D extends N } @Override - public void contentChanged(@SuppressWarnings("unused") DataStoreEvent e) { + public void contentChanged(DataStoreEvent e) { synchronizedRedraw(); } diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/ClusterEvaluationVisFactory.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/ClusterEvaluationVisFactory.java index 469d6db5..405ba673 100644 --- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/ClusterEvaluationVisFactory.java +++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/ClusterEvaluationVisFactory.java @@ -123,7 +123,7 @@ public class ClusterEvaluationVisFactory extends AbstractVisFactory { } @Override - public boolean allowThumbnails(@SuppressWarnings("unused") VisualizationTask task) { + public boolean allowThumbnails(VisualizationTask task) { // Don't use thumbnails return false; } diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/CurveVisFactory.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/CurveVisFactory.java index a45f2007..4d0e3dc0 100644 --- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/CurveVisFactory.java +++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/CurveVisFactory.java @@ -235,7 +235,7 @@ public class CurveVisFactory extends AbstractVisFactory { } @Override - public boolean allowThumbnails(@SuppressWarnings("unused") VisualizationTask task) { + public boolean allowThumbnails(VisualizationTask task) { // TODO: depending on the curve complexity? return false; } diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/HistogramVisFactory.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/HistogramVisFactory.java index c8dfe0c8..81a77c13 100644 --- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/HistogramVisFactory.java +++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/HistogramVisFactory.java @@ -177,7 +177,7 @@ public class HistogramVisFactory extends AbstractVisFactory { } @Override - public boolean allowThumbnails(@SuppressWarnings("unused") VisualizationTask task) { + public boolean allowThumbnails(VisualizationTask task) { // TODO: depending on the histogram complexity? return false; } diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/KeyVisFactory.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/KeyVisFactory.java index 69813d99..e3a5dfd4 100644 --- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/KeyVisFactory.java +++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/KeyVisFactory.java @@ -116,7 +116,7 @@ public class KeyVisFactory extends AbstractVisFactory { } @Override - public boolean allowThumbnails(@SuppressWarnings("unused") VisualizationTask task) { + public boolean allowThumbnails(VisualizationTask task) { return false; } }
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/PixmapVisualizer.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/PixmapVisualizer.java index 06268dac..825d64b6 100644 --- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/PixmapVisualizer.java +++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/PixmapVisualizer.java @@ -135,7 +135,7 @@ public class PixmapVisualizer extends AbstractVisualization { } @Override - public boolean allowThumbnails(@SuppressWarnings("unused") VisualizationTask task) { + public boolean allowThumbnails(VisualizationTask task) { // Don't use thumbnails return false; } diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/SettingsVisFactory.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/SettingsVisFactory.java index 9be580f7..5d33fede 100644 --- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/SettingsVisFactory.java +++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/SettingsVisFactory.java @@ -149,7 +149,7 @@ public class SettingsVisFactory extends AbstractVisFactory { } @Override - public boolean allowThumbnails(@SuppressWarnings("unused") VisualizationTask task) { + public boolean allowThumbnails(VisualizationTask task) { return false; } }
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/SimilarityMatrixVisualizer.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/SimilarityMatrixVisualizer.java index f9b1ef52..17424519 100644 --- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/SimilarityMatrixVisualizer.java +++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/SimilarityMatrixVisualizer.java @@ -163,7 +163,7 @@ public class SimilarityMatrixVisualizer extends AbstractVisualization { } @Override - public boolean allowThumbnails(@SuppressWarnings("unused") VisualizationTask task) { + public boolean allowThumbnails(VisualizationTask task) { // Don't use thumbnails return false; } diff --git a/src/de/lmu/ifi/dbs/elki/workflow/EvaluationStep.java b/src/de/lmu/ifi/dbs/elki/workflow/EvaluationStep.java index 50081404..70a7478c 100644 --- a/src/de/lmu/ifi/dbs/elki/workflow/EvaluationStep.java +++ b/src/de/lmu/ifi/dbs/elki/workflow/EvaluationStep.java @@ -41,7 +41,6 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectListParamet * @author Erich Schubert * * @apiviz.has Evaluator - * @apiviz.has Result * @apiviz.uses Result */ public class EvaluationStep implements WorkflowStep { @@ -77,6 +76,8 @@ public class EvaluationStep implements WorkflowStep { * Class to handle running the evaluators on a database instance. * * @author Erich Schubert + * + * @apiviz.exclude */ public class Evaluation implements ResultListener { /** |