Search in sources :

Example 36 with Model

use of de.lmu.ifi.dbs.elki.data.model.Model in project elki by elki-project.

the class KMLOutputHandler method writeClusteringResult.

private void writeClusteringResult(XMLStreamWriter xmlw, Clustering<Model> clustering, Database database) throws XMLStreamException {
    xmlw.writeStartDocument();
    xmlw.writeCharacters("\n");
    xmlw.writeStartElement("kml");
    xmlw.writeDefaultNamespace("http://earth.google.com/kml/2.2");
    xmlw.writeStartElement("Document");
    {
        // TODO: can we automatically generate more helpful data here?
        xmlw.writeStartElement("name");
        xmlw.writeCharacters("ELKI KML output for " + clustering.getLongName());
        // name
        xmlw.writeEndElement();
        writeNewlineOnDebug(xmlw);
        // TODO: e.g. list the settings in the description?
        xmlw.writeStartElement("description");
        xmlw.writeCharacters("ELKI KML output for " + clustering.getLongName());
        // description
        xmlw.writeEndElement();
        writeNewlineOnDebug(xmlw);
    }
    List<Cluster<Model>> clusters = clustering.getAllClusters();
    Relation<NumberVector> coords = database.getRelation(TypeUtil.NUMBER_VECTOR_FIELD_2D);
    List<Cluster<Model>> topc = clustering.getToplevelClusters();
    Hierarchy<Cluster<Model>> hier = clustering.getClusterHierarchy();
    Map<Object, DoubleObjPair<Polygon>> hullmap = new HashMap<>();
    for (Cluster<Model> clu : topc) {
        buildHullsRecursively(clu, hier, hullmap, coords);
    }
    {
        final double projarea = 360. * 180. * .01;
        // TODO: generate styles from color scheme
        Iterator<Cluster<Model>> it = clusters.iterator();
        for (int i = 0; it.hasNext(); i++) {
            Cluster<Model> clus = it.next();
            // This is a prime based magic number, to produce a colorful output
            Color col = Color.getHSBColor(i / 4.294967291f, 1.f, .5f);
            DoubleObjPair<Polygon> pair = hullmap.get(clus);
            // Approximate area (using bounding box)
            double hullarea = SpatialUtil.volume(pair.second);
            final double relativeArea = Math.max(1. - (hullarea / projarea), 0.);
            // final double relativeSize = pair.first / coords.size();
            final double opacity = .65 * FastMath.sqrt(relativeArea) + .1;
            xmlw.writeStartElement("Style");
            xmlw.writeAttribute("id", "s" + i);
            writeNewlineOnDebug(xmlw);
            {
                xmlw.writeStartElement("LineStyle");
                xmlw.writeStartElement("width");
                xmlw.writeCharacters("0");
                // width
                xmlw.writeEndElement();
                // LineStyle
                xmlw.writeEndElement();
            }
            writeNewlineOnDebug(xmlw);
            {
                xmlw.writeStartElement("PolyStyle");
                xmlw.writeStartElement("color");
                // KML uses AABBGGRR format!
                xmlw.writeCharacters(String.format("%02x%02x%02x%02x", (int) (255 * Math.min(.75, opacity)), col.getBlue(), col.getGreen(), col.getRed()));
                // color
                xmlw.writeEndElement();
                // out.writeStartElement("fill");
                // out.writeCharacters("1"); // Default 1
                // out.writeEndElement(); // fill
                xmlw.writeStartElement("outline");
                xmlw.writeCharacters("0");
                // outline
                xmlw.writeEndElement();
                // PolyStyle
                xmlw.writeEndElement();
            }
            writeNewlineOnDebug(xmlw);
            // Style
            xmlw.writeEndElement();
            writeNewlineOnDebug(xmlw);
        }
    }
    Cluster<?> ignore = topc.size() == 1 ? topc.get(0) : null;
    Iterator<Cluster<Model>> it = clusters.iterator();
    for (int cnum = 0; it.hasNext(); cnum++) {
        Cluster<?> c = it.next();
        // Ignore sole toplevel cluster (usually: noise)
        if (c == ignore) {
            continue;
        }
        Polygon p = hullmap.get(c).second;
        xmlw.writeStartElement("Placemark");
        {
            xmlw.writeStartElement("name");
            xmlw.writeCharacters(c.getNameAutomatic());
            // name
            xmlw.writeEndElement();
            xmlw.writeStartElement("description");
            xmlw.writeCData(makeDescription(c).toString());
            // description
            xmlw.writeEndElement();
            xmlw.writeStartElement("styleUrl");
            xmlw.writeCharacters("#s" + cnum);
            // styleUrl
            xmlw.writeEndElement();
        }
        {
            xmlw.writeStartElement("Polygon");
            writeNewlineOnDebug(xmlw);
            if (compat) {
                xmlw.writeStartElement("altitudeMode");
                xmlw.writeCharacters("relativeToGround");
                // close altitude mode
                xmlw.writeEndElement();
                writeNewlineOnDebug(xmlw);
            }
            {
                xmlw.writeStartElement("outerBoundaryIs");
                xmlw.writeStartElement("LinearRing");
                xmlw.writeStartElement("coordinates");
                // Reverse anti-clockwise polygons.
                boolean reverse = (p.testClockwise() >= 0);
                ArrayListIter<double[]> itp = p.iter();
                if (reverse) {
                    itp.seek(p.size() - 1);
                }
                while (itp.valid()) {
                    double[] v = itp.get();
                    xmlw.writeCharacters(FormatUtil.format(v, ","));
                    if (compat && (v.length == 2)) {
                        xmlw.writeCharacters(",100");
                    }
                    xmlw.writeCharacters(" ");
                    if (!reverse) {
                        itp.advance();
                    } else {
                        itp.retract();
                    }
                }
                // close coordinates
                xmlw.writeEndElement();
                // close LinearRing
                xmlw.writeEndElement();
                // close *BoundaryIs
                xmlw.writeEndElement();
            }
            writeNewlineOnDebug(xmlw);
            // Polygon
            xmlw.writeEndElement();
        }
        // Placemark
        xmlw.writeEndElement();
        writeNewlineOnDebug(xmlw);
    }
    // Document
    xmlw.writeEndElement();
    // kml
    xmlw.writeEndElement();
    xmlw.writeEndDocument();
}
Also used : HashMap(java.util.HashMap) Color(java.awt.Color) Cluster(de.lmu.ifi.dbs.elki.data.Cluster) DoubleObjPair(de.lmu.ifi.dbs.elki.utilities.pairs.DoubleObjPair) NumberVector(de.lmu.ifi.dbs.elki.data.NumberVector) Model(de.lmu.ifi.dbs.elki.data.model.Model) Iterator(java.util.Iterator) PolygonsObject(de.lmu.ifi.dbs.elki.data.spatial.PolygonsObject) Polygon(de.lmu.ifi.dbs.elki.data.spatial.Polygon)

Example 37 with Model

use of de.lmu.ifi.dbs.elki.data.model.Model in project elki by elki-project.

the class KMLOutputHandler method processNewResult.

@Override
public void processNewResult(ResultHierarchy hier, Result newResult) {
    ArrayList<OutlierResult> ors = ResultUtil.filterResults(hier, newResult, OutlierResult.class);
    ArrayList<Clustering<?>> crs = ResultUtil.filterResults(hier, newResult, Clustering.class);
    if (ors.size() + crs.size() > 1) {
        throw new AbortException("More than one visualizable result found. The KML writer only supports a single result!");
    }
    Database database = ResultUtil.findDatabase(hier);
    for (OutlierResult outlierResult : ors) {
        try {
            XMLOutputFactory factory = XMLOutputFactory.newInstance();
            ZipOutputStream out = new ZipOutputStream(new FileOutputStream(filename));
            out.putNextEntry(new ZipEntry("doc.kml"));
            final XMLStreamWriter xmlw = factory.createXMLStreamWriter(out);
            writeOutlierResult(xmlw, outlierResult, database);
            xmlw.flush();
            xmlw.close();
            out.closeEntry();
            out.flush();
            out.close();
            if (autoopen) {
                Desktop.getDesktop().open(filename);
            }
        } catch (XMLStreamException e) {
            LOG.exception(e);
            throw new AbortException("XML error in KML output.", e);
        } catch (IOException e) {
            LOG.exception(e);
            throw new AbortException("IO error in KML output.", e);
        }
    }
    for (Clustering<?> clusteringResult : crs) {
        try {
            XMLOutputFactory factory = XMLOutputFactory.newInstance();
            ZipOutputStream out = new ZipOutputStream(new FileOutputStream(filename));
            out.putNextEntry(new ZipEntry("doc.kml"));
            final XMLStreamWriter xmlw = factory.createXMLStreamWriter(out);
            @SuppressWarnings("unchecked") Clustering<Model> cres = (Clustering<Model>) clusteringResult;
            writeClusteringResult(xmlw, cres, database);
            xmlw.flush();
            xmlw.close();
            out.closeEntry();
            out.flush();
            out.close();
            if (autoopen) {
                Desktop.getDesktop().open(filename);
            }
        } catch (XMLStreamException e) {
            LOG.exception(e);
            throw new AbortException("XML error in KML output.", e);
        } catch (IOException e) {
            LOG.exception(e);
            throw new AbortException("IO error in KML output.", e);
        }
    }
}
Also used : XMLOutputFactory(javax.xml.stream.XMLOutputFactory) ZipEntry(java.util.zip.ZipEntry) OutlierResult(de.lmu.ifi.dbs.elki.result.outlier.OutlierResult) IOException(java.io.IOException) Clustering(de.lmu.ifi.dbs.elki.data.Clustering) XMLStreamException(javax.xml.stream.XMLStreamException) ZipOutputStream(java.util.zip.ZipOutputStream) XMLStreamWriter(javax.xml.stream.XMLStreamWriter) FileOutputStream(java.io.FileOutputStream) Database(de.lmu.ifi.dbs.elki.database.Database) Model(de.lmu.ifi.dbs.elki.data.model.Model) AbortException(de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException)

Example 38 with Model

use of de.lmu.ifi.dbs.elki.data.model.Model in project elki by elki-project.

the class VisualizerContext method generateDefaultClustering.

/**
 * Generate a default (fallback) clustering.
 *
 * @return generated clustering
 */
private Clustering<Model> generateDefaultClustering() {
    final Database db = ResultUtil.findDatabase(hier);
    Clustering<Model> c = null;
    try {
        // Try to cluster by labels
        ByLabelHierarchicalClustering split = new ByLabelHierarchicalClustering();
        c = split.run(db);
    } catch (NoSupportedDataTypeException e) {
        // Put everything into one
        c = new TrivialAllInOne().run(db);
    }
    return c;
}
Also used : NoSupportedDataTypeException(de.lmu.ifi.dbs.elki.data.type.NoSupportedDataTypeException) Database(de.lmu.ifi.dbs.elki.database.Database) Model(de.lmu.ifi.dbs.elki.data.model.Model) TrivialAllInOne(de.lmu.ifi.dbs.elki.algorithm.clustering.trivial.TrivialAllInOne) ByLabelHierarchicalClustering(de.lmu.ifi.dbs.elki.algorithm.clustering.trivial.ByLabelHierarchicalClustering)

Example 39 with Model

use of de.lmu.ifi.dbs.elki.data.model.Model in project elki by elki-project.

the class VisualizerContext method makeStyleResult.

/**
 * Generate a new style result for the given style library.
 *
 * @param stylelib Style library
 */
protected void makeStyleResult(StyleLibrary stylelib) {
    final Database db = ResultUtil.findDatabase(hier);
    stylelibrary = stylelib;
    List<Clustering<? extends Model>> clusterings = Clustering.getClusteringResults(db);
    if (!clusterings.isEmpty()) {
        stylepolicy = new ClusterStylingPolicy(clusterings.get(0), stylelib);
    } else {
        Clustering<Model> c = generateDefaultClustering();
        stylepolicy = new ClusterStylingPolicy(c, stylelib);
    }
}
Also used : Database(de.lmu.ifi.dbs.elki.database.Database) Model(de.lmu.ifi.dbs.elki.data.model.Model) Clustering(de.lmu.ifi.dbs.elki.data.Clustering) ByLabelHierarchicalClustering(de.lmu.ifi.dbs.elki.algorithm.clustering.trivial.ByLabelHierarchicalClustering) ClusterStylingPolicy(de.lmu.ifi.dbs.elki.visualization.style.ClusterStylingPolicy)

Example 40 with Model

use of de.lmu.ifi.dbs.elki.data.model.Model in project elki by elki-project.

the class NaiveAgglomerativeHierarchicalClustering1 method run.

/**
 * Run the algorithm
 *
 * @param db Database
 * @param relation Relation
 * @return Clustering hierarchy
 */
public Result run(Database db, Relation<O> relation) {
    DistanceQuery<O> dq = db.getDistanceQuery(relation, getDistanceFunction());
    ArrayDBIDs ids = DBIDUtil.ensureArray(relation.getDBIDs());
    final int size = ids.size();
    LOG.verbose("Notice: SLINK is a much faster algorithm for single-linkage clustering!");
    // Compute the initial distance matrix.
    double[][] matrix = new double[size][size];
    DBIDArrayIter ix = ids.iter(), iy = ids.iter();
    for (int x = 0; ix.valid(); x++, ix.advance()) {
        iy.seek(0);
        for (int y = 0; y < x; y++, iy.advance()) {
            final double dist = dq.distance(ix, iy);
            matrix[x][y] = dist;
            matrix[y][x] = dist;
        }
    }
    // Initialize space for result:
    double[] height = new double[size];
    Arrays.fill(height, Double.POSITIVE_INFINITY);
    // Parent node, to track merges
    // have every object point to itself initially
    ArrayModifiableDBIDs parent = DBIDUtil.newArray(ids);
    // Active clusters, when not trivial.
    Int2ReferenceMap<ModifiableDBIDs> clusters = new Int2ReferenceOpenHashMap<>();
    // Repeat until everything merged, except the desired number of clusters:
    final int stop = size - numclusters;
    FiniteProgress prog = LOG.isVerbose() ? new FiniteProgress("Agglomerative clustering", stop, LOG) : null;
    for (int i = 0; i < stop; i++) {
        double min = Double.POSITIVE_INFINITY;
        int minx = -1, miny = -1;
        for (int x = 0; x < size; x++) {
            if (height[x] < Double.POSITIVE_INFINITY) {
                continue;
            }
            for (int y = 0; y < x; y++) {
                if (height[y] < Double.POSITIVE_INFINITY) {
                    continue;
                }
                if (matrix[x][y] < min) {
                    min = matrix[x][y];
                    minx = x;
                    miny = y;
                }
            }
        }
        assert (minx >= 0 && miny >= 0);
        // Avoid allocating memory, by reusing existing iterators:
        ix.seek(minx);
        iy.seek(miny);
        // Perform merge in data structure: x -> y
        // Since y < x, prefer keeping y, dropping x.
        height[minx] = min;
        parent.set(minx, iy);
        // Merge into cluster
        ModifiableDBIDs cx = clusters.get(minx);
        ModifiableDBIDs cy = clusters.get(miny);
        if (cy == null) {
            cy = DBIDUtil.newHashSet();
            cy.add(iy);
        }
        if (cx == null) {
            cy.add(ix);
        } else {
            cy.addDBIDs(cx);
            clusters.remove(minx);
        }
        clusters.put(miny, cy);
        // Update distance matrix for y:
        for (int j = 0; j < size; j++) {
            matrix[j][miny] = Math.min(matrix[j][minx], matrix[j][miny]);
            matrix[miny][j] = Math.min(matrix[minx][j], matrix[miny][j]);
        }
        LOG.incrementProcessed(prog);
    }
    LOG.ensureCompleted(prog);
    // Build the clustering result
    final Clustering<Model> dendrogram = new Clustering<>("Hierarchical-Clustering", "hierarchical-clustering");
    for (int x = 0; x < size; x++) {
        if (height[x] < Double.POSITIVE_INFINITY) {
            DBIDs cids = clusters.get(x);
            if (cids == null) {
                ix.seek(x);
                cids = DBIDUtil.deref(ix);
            }
            Cluster<Model> cluster = new Cluster<>("Cluster", cids);
            dendrogram.addToplevelCluster(cluster);
        }
    }
    return dendrogram;
}
Also used : FiniteProgress(de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress) Cluster(de.lmu.ifi.dbs.elki.data.Cluster) Clustering(de.lmu.ifi.dbs.elki.data.Clustering) Model(de.lmu.ifi.dbs.elki.data.model.Model) Int2ReferenceOpenHashMap(it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap)

Aggregations

Model (de.lmu.ifi.dbs.elki.data.model.Model)60 Database (de.lmu.ifi.dbs.elki.database.Database)29 Test (org.junit.Test)24 Clustering (de.lmu.ifi.dbs.elki.data.Clustering)21 Cluster (de.lmu.ifi.dbs.elki.data.Cluster)18 AbstractClusterAlgorithmTest (de.lmu.ifi.dbs.elki.algorithm.clustering.AbstractClusterAlgorithmTest)17 ClusterModel (de.lmu.ifi.dbs.elki.data.model.ClusterModel)13 ModifiableDBIDs (de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs)12 ELKIBuilder (de.lmu.ifi.dbs.elki.utilities.ELKIBuilder)11 DBIDs (de.lmu.ifi.dbs.elki.database.ids.DBIDs)10 ArrayList (java.util.ArrayList)9 DoubleVector (de.lmu.ifi.dbs.elki.data.DoubleVector)8 DBIDIter (de.lmu.ifi.dbs.elki.database.ids.DBIDIter)8 AbortException (de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException)8 FiniteProgress (de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress)7 HashMap (java.util.HashMap)5 ByLabelClustering (de.lmu.ifi.dbs.elki.algorithm.clustering.trivial.ByLabelClustering)3 SubspaceModel (de.lmu.ifi.dbs.elki.data.model.SubspaceModel)3 IndefiniteProgress (de.lmu.ifi.dbs.elki.logging.progress.IndefiniteProgress)3 CorePredicate (de.lmu.ifi.dbs.elki.algorithm.clustering.gdbscan.CorePredicate)2