package de.lmu.ifi.dbs.elki.data;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
Copyright (C) 2015
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
*/
import java.util.Comparator;
import de.lmu.ifi.dbs.elki.data.model.Model;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
import de.lmu.ifi.dbs.elki.result.textwriter.TextWriteable;
import de.lmu.ifi.dbs.elki.result.textwriter.TextWriterStream;
/**
* Generic cluster class, that may or not have hierarchical information. Note
* that every cluster MUST have a DBIDs, since it implements the interface, too.
* Calls to the interface are proxied to the inner group object.
*
* A hierarchy object of class SimpleHierarchy will be created automatically
* when a list of parents and children is provided. Alternatively, a
* pre-existing hierarchy object can be provided, e.g. when there is a single
* hierarchy object used for keeping all the hierarchy information in one
* object.
*
* @param Model object type
*
* @author Erich Schubert
* @since 0.2
*
* @apiviz.landmark
*
* @apiviz.composedOf DBIDs
* @apiviz.composedOf Model
*/
public class Cluster implements TextWriteable {
/**
* Cluster name.
*/
protected String name = null;
/**
* Cluster data.
*/
private DBIDs ids = null;
/**
* Cluster model.
*/
private M model = null;
/**
* Noise?
*/
private boolean noise = false;
/**
* Full constructor
*
* @param name Cluster name. May be null.
* @param ids Object Group
* @param noise Noise flag
* @param model Model. May be null.
*/
public Cluster(String name, DBIDs ids, boolean noise, M model) {
super();
this.name = name;
this.ids = ids;
this.noise = noise;
this.model = model;
}
/**
* Constructor without hierarchy information.
*
* @param name Cluster name. May be null.
* @param ids Object group
* @param model Model
*/
public Cluster(String name, DBIDs ids, M model) {
this(name, ids, false, model);
}
/**
* Constructor without hierarchy information and name
*
* @param ids Object group
* @param noise Noise flag
* @param model Model
*/
public Cluster(DBIDs ids, boolean noise, M model) {
this(null, ids, noise, model);
}
/**
* Constructor without hierarchy information and name
*
* @param ids Object group
* @param model Model
*/
public Cluster(DBIDs ids, M model) {
this(null, ids, false, model);
}
/**
* Constructor without hierarchy information and model
*
* @param name Cluster name. May be null.
* @param ids Object group
* @param noise Noise flag
*/
public Cluster(String name, DBIDs ids, boolean noise) {
this(name, ids, noise, null);
}
/**
* Constructor without hierarchy information and model
*
* @param name Cluster name. May be null.
* @param ids Object group
*/
public Cluster(String name, DBIDs ids) {
this(name, ids, false, null);
}
/**
* Constructor without hierarchy information and name and model
*
* @param ids Cluster name. May be null.
* @param noise Noise flag
*/
public Cluster(DBIDs ids, boolean noise) {
this(null, ids, noise, null);
}
/**
* Constructor without hierarchy information and name and model
*
* @param ids Object group
*/
public Cluster(DBIDs ids) {
this(null, ids, false, null);
}
/**
* Delegate to database object group.
*
* @return Cluster size retrieved from object group.
*/
public int size() {
return ids.size();
}
/**
* Return either the assigned name or the suggested label
*
* @return a name for the cluster
*/
public String getNameAutomatic() {
if(name != null) {
return name;
}
if(isNoise()) {
return "Noise";
}
else {
return "Cluster";
}
}
/**
* Get Cluster name. May be null.
*
* @return cluster name, or null
*/
public String getName() {
return name;
}
/**
* Set Cluster name
*
* @param name new cluster name
*/
public void setName(String name) {
this.name = name;
}
/**
* Access group object
*
* @return database object group
*/
public DBIDs getIDs() {
return ids;
}
/**
* Access group object
*
* @param g set database object group
*/
public void setIDs(DBIDs g) {
ids = g;
}
/**
* Access model object
*
* @return Cluster model
*/
public M getModel() {
return model;
}
/**
* Access model object
*
* @param model New cluster model
*/
public void setModel(M model) {
this.model = model;
}
/**
* Write to a textual representation. Writing the actual group data will be
* handled by the caller, this is only meant to write the meta information.
*
* @param out output writer stream
* @param label Label to prefix
*/
@Override
public void writeToText(TextWriterStream out, String label) {
String name = getNameAutomatic();
if(name != null) {
out.commentPrintLn("Cluster name: " + name);
}
out.commentPrintLn("Cluster noise flag: " + isNoise());
out.commentPrintLn("Cluster size: " + ids.size());
// also print model, if any and printable
if(getModel() != null && (getModel() instanceof TextWriteable)) {
((TextWriteable) getModel()).writeToText(out, label);
}
}
/**
* Getter for noise flag.
*
* @return noise flag
*/
public boolean isNoise() {
return noise;
}
/**
* Setter for noise flag.
*
* @param noise new noise flag value
*/
public void setNoise(boolean noise) {
this.noise = noise;
}
/**
* A partial comparator for Clusters, based on their name. Useful for sorting
* clusters. Do NOT use in e.g. a TreeSet since it is
* inconsistent with equals.
*/
public static Comparator> BY_NAME_SORTER = new Comparator>() {
@Override
public int compare(Cluster> o1, Cluster> o2) {
if(o1 == o2) {
return 0;
}
// sort by label if possible
if(o1 != null && o1.name != null && o2 != null && o2.name != null) {
int lblresult = o1.name.compareTo(o2.getName());
if(lblresult != 0) {
return lblresult;
}
}
int hashresult = o1.hashCode() - o2.hashCode();
if(hashresult != 0) {
return hashresult;
}
return 0;
}
};
/** {@inheritDoc} */
@Override
public String toString() {
String mstr = (model == null) ? "null" : model.toString();
String nstr = noise ? ",noise" : "";
return "Cluster(size=" + size() + ",model=" + mstr + nstr + ")";
}
}