Commit c8dae14a authored by lafabregue's avatar lafabregue
Browse files

first released version v6.0

parents
temporary/*
*.class
# eclipse specific git ignore
*.pydevproject
.project
.metadata
bin/**
tmp/**
tmp/**/*
*.tmp
*.bak
*.swp
*~.nib
local.properties
.classpath
.settings/
.loadpath
*.hprof
temporary/*
*.class
# eclipse specific git ignore
*.pydevproject
.project
.metadata
bin/**
tmp/**
tmp/**/*
*.tmp
*.bak
*.swp
*~.nib
local.properties
.classpath
.settings/
.loadpath
*.hprof
File added
File added
File added
package jcl;
import java.awt.Color;
import java.io.IOException;
import java.io.Serializable;
import java.text.NumberFormat;
import java.util.Arrays;
import java.util.Observable;
import java.util.Vector;
import javax.swing.JInternalFrame;
import jcl.clustering.Cluster;
import jcl.clustering.ClusteringResult;
import jcl.data.Data;
import jcl.evaluation.QualityIndex;
import jcl.evaluation.clustering.ClusteringQuality;
import jcl.jcld.RmiServer;
import jcl.jcld.database.SSHParameters;
import jcl.learning.LearningMethod;
import jcl.learning.methods.ClassifierUtils;
import jcl.utils.exceptions.MethodNotImplementedException;
/**
* <p>
* Classe abstraite implantant le concept de classification non supervisee.
* </p>
* <p>
* Une classification pourra etre simple (une methode d'apprentissage unique) ou
* hybride (methode Samarah).
* </p>
*
* @author WEMMERT Cedric
*/
public abstract class Classification extends Observable implements
Serializable, Cloneable {
/** savoir si le calcul deporte est active */
transient private static boolean use_Rmi = false;
/** les config du server rmi */
transient private static RmiServer rmiServer = null;
/** paramtre de la connection ssh si besoin */
public SSHParameters sshParameters = null;
/** panel ou il faut afficher la non disponibiliter du server rmi */
transient public JInternalFrame container_;
/** titre de la classid pour le tabedpane en hybridclassification */
public String title;
private long timeExec = 0;
//pour la classif multires de mustic
private boolean intermediaire = false;
private Data histogrammesDecomp=null;
/**
* <p>
* Methode utilisee pour le debuggage. Affiche le contenu de la memoire.
* </p>
*
* @param comment
* commentaire affiche en plus du contenu memoire
*/
public static void printMemory(final String comment) {
final NumberFormat nf = NumberFormat.getInstance();
nf.setMinimumFractionDigits(2);
nf.setMaximumFractionDigits(2);
Runtime.getRuntime().gc();
System.out.println(comment);
final long total = Runtime.getRuntime().totalMemory();
final long free = Runtime.getRuntime().freeMemory();
final double ratioFree = (100. * free) / total;
final long used = total - free;
final double ratioUsed = (100. * used) / total;
final long max = Runtime.getRuntime().maxMemory();
System.out.println("Used memory: " + (used / (1024 * 1024)) + " Mo ("
+ nf.format(ratioUsed) + "%)");
System.out.println("Free memory: " + (free / (1024 * 1024)) + " Mo ("
+ nf.format(ratioFree) + "%)");
System.out.println("Total memory: " + (total / (1024 * 1024)) + " Mo");
System.out.println("Max memory: " + (max / (1024 * 1024)) + " Mo");
System.out.println();
}
/** Le resultat de la classification */
protected ClusteringResult clusteringResult = null;
/** Le nom de la classification */
private String name = "";
/**
* <p>
* Constructeur avec un nom.
* </p>
*
* @param name
* le nom de la classif
*/
public Classification(final String name) {
this.name = name;
}
/**
* Constructeur
*
* @param _name
* le nom de la classification
* @param _result
* le resultat de classification
*/
public Classification(final String _name, final ClusteringResult _result) {
this.name = _name;
this.clusteringResult = _result;
}
/**
* <p>
* Methode de calcul de la distance entre deux classes.
* </p>
*
* @param k1
* le numero de la premiere classe
* @param k2
* le numero de la seconde classe
* @return la distance entre la classe k1 et k2
*/
public double centroidsDistance(final int k1, final int k2) {
return this.getClusteringResult().centroidsDistance(k1, k2);
}
/**
* <p>
* Methode creant le resultat de classification :
* </p>
* <ul>
* <li>clustering des donnees dans le cas simple;</li>
* <li>fusion par vote dans le cas hybride.</li>
* </ul>
*/
abstract public void classify();
@Override
abstract public Object clone();
/**
* <p>
* Methode de calcul de la distance entre un objet et une classe.
* </p>
*
* @param object
* l'objet
* @param k
* le numero de la classe
* @return la distance entre l'objet object et la classe k
*/
public double distance(final int object, final int k) {
final Data data = this.getData();
final ClusteringResult result = this.getClusteringResult();
final Cluster clusterK = result.getCluster(k);
return clusterK.distance(data.getDataObject(object));
}
/**
* <p>
* Methode d'acces aux methodes de classification.
* </p>
*
* @return la liste des classifiers utilises
*/
abstract public LearningMethod[] getAllClassifiers();
/**
* <p>
* Accesseur au resultat de classification.
* </p>
*
* @return le resultat de la classification
*/
public ClusteringResult getClusteringResult() {
if (this.clusteringResult == null) {
this.classify();
}
return this.clusteringResult;
}
/**
* <p>
* Methode renvoyant un texte descriptif de la comparaison entre un resultat
* donne en parametre et le resultat courant.
* </p>
*
* @param matrix
* la matrice diagonalisee de comparaison
* @param som
* la matrice de confusion entre les deux resultats
* @param res
* le resultat a comparer
* @return un texte en HTML decrivant la qualite et la comparaison des
* resultats
*/
public String getComparisonInfos(final double[][] matrix,
final int[][] som, final ClusteringResult res) {
String texte = "<html>";
final int nbClassesReal = res.getNbClusters();
// meilleure somme de pixel classe pour chaque classe
final int[] best = new int[nbClassesReal];
// classes qui correspondent le mieux aux classes reels -1 si aucune
final int[] clas = new int[nbClassesReal];
Arrays.fill(clas, -1);
/** @todo revoir le calcul et les statistiques qu'on veut afficher... */
for (int i = 1; i < matrix.length - 1; i++) {
int ind = 0;
double max = 0;
boolean great = true;
// on cherche le max de la ligne
for (int j = 1; j < matrix[0].length - 1; j++) {
if (matrix[i][j] > max) {
max = matrix[i][j];
ind = j;
}
}
// on regarde si s'est le max de la colonne
for (int j = 1; j < matrix.length - 1; j++) {
if (matrix[j][ind] > max) {
great = false;
}
}
if (great) {
best[ind - 1] = som[i - 1][ind - 1];
clas[ind - 1] = i - 1;
}
}
int max = 0;
for (final int element : best) {
max += element;
}
final NumberFormat nf2 = NumberFormat.getInstance();
nf2.setMaximumFractionDigits(2);
texte += "<h3>Information</h3>";
texte += "<hr>";
texte += "<p>Nb attributes : "
+ this.getData().getDataObject(0).getNbAttributes() + "</p>";
texte += "<p>Nb objects" + " : " + this.getData().getNbObjects()
+ "</p>";
texte += "<p>" + "Nb match" + " : " + "</p>";
texte += "<ul>";
for (int i = 0; i < nbClassesReal; i++) {
if (clas[i] != -1) {
texte += "<li>"
+ res.getLegend(i)
+ " : "
+ best[i]
+ "/"
+ res.getCard(i)
+ " "
+ (int) (((double) best[i] / (double) res.getCard(i)) * 100)
+ "% (" + this.getClusteringResult().getLegend(clas[i])
+ ") </li>";
} else {
texte += "<li>" + res.getLegend(i) + " : " + best[i] + "/"
+ res.getCard(i) + " (None)" + "</li>";
}
}
texte += "</ul>";
texte += "<hr>";
final int percent = (int) (((double) max / (double) this.getData()
.getNbObjects()) * 100.0);
texte += "<p>" + "Nb well classified" + " : " + max + " (" + percent
+ "%)</p>";
final ClusteringQuality evaluation = this.getClusteringResult()
.evaluate();
texte += "<table>";
for (int i = 0; i < evaluation.getNbAccuracyIndices(); i++) {
final QualityIndex qualityIndex = evaluation.getAccuracyIndex(i);
texte += "<tr><td>" + qualityIndex.getName()
+ "</td><td>:</td><td>"
+ nf2.format(qualityIndex.getValue()) + "</td></tr>";
}
texte += "</table>";
texte += "</html>";
return texte;
}
/**
* <p>
* Accesseur aux donnees de la classification.
* </p>
*
* @return les donnees de la classification
*/
abstract public Data getData();
/**
* <p>
* Methode recreant un nouveau resultat a partir de cette classification en
* applicant espece de filtre median. Methode redefinie uniquement dans
* SingleClassification pour le moment.
* </p>
*
* @return une nouvelle classification
*/
public Classification getFilterResult() {
return null;
}
/**
* <p>
* Methode abstraite renvoyant les parametres de classification au format
* HTML.
* </p>
*
* @return les parametres de la classification
*/
abstract public String getHTMLParameters();
/**
* <p>
* Methode renvoyant des informations sur un cluster.
* </p>
*
* @param c
* le cluster a utiliser
* @return un vecteur d'objets decrivant ce cluster
*/
public abstract Vector<Object> getInfos(Cluster c);
/**
* <p>
* Accesseur au resultat a priori.
* </p>
*
* @return le resultat optimal connu pour cette classification
*/
public ClusteringResult getKnownResult() {
return this.getData().getKnownResult();
}
/**
* <p>
* Methode d'acces a la methode de classification.
* </p>
*
* @return le classifieur associe s'il existe, null sinon
*
*/
abstract public LearningMethod getLearningMethod();
/**
* <p>
* Methode d'acces au nom de la classification.
* </p>
*
* @return le nom de la classification
*/
public String getName() {
return this.name;
}
/**
* <p>
* Methode renvoyant le nombre d'attributs de la classification.
* </p>
*
* @return le nombre d'attributs des donnees
*/
abstract public int getNbAttributes();
/**
* <p>
* Methode renvoyant le nombre de classes du resultat.
* </p>
*
* @return le nombre de classes du resultat ou 0 si aucun resultat
*/
public int getNbClusters() {
int ret = 0;
if (this.getClusteringResult() != null) {
ret = this.getClusteringResult().getNbClusters();
}
return ret;
}
/**
* <p>
* Methode recreant un nouveau resultat a partir de cette classification
* base sur les couleurs passes en parametres, provenant d'une matrice de
* confusion calculee a partir d'un ensemble de ROI. Methode redefinie
* uniquement dans SingleClassification pour le moment.
* </p>
*
* @param colors
* les couleurs
* @return une nouvelle classification
*/
public Classification getNewClusteringResult(final Color[] colors) {
if (colors == null) {
return null;
}
return this;
}
/**
* <p>
* Mehode abstraite renvoyant les parametres de classification au format
* texte
* </p>
*
* @return Les parametres de la classification.
*/
abstract public String getTextParameters();
/**
* <p>
* Methode abstraite renvoyant le type de classification hybride ou non.
* </p>
*
* @return une description du type de methode de classification
*/
abstract public int getType();
/**
* <p>
* Methode permettant de savoir si la classification est hybride ou non.
* </p>
*
* @return vrai si la classification est hybride
*/
public boolean isHybrid() {
return false;
}
/**
* <p>
* Methode permettant de savoir si la classification est multiresolution ou non.
* </p>
*
* @return vrai si la classification est multiresolution
*/
public boolean isMultiresolution() {
return false;
}
public void setHistogrammesDecomp(Data histogrammesDecomp) {
this.histogrammesDecomp = histogrammesDecomp;
}
public Data getHistogrammesDecomp() {
return histogrammesDecomp;
}
public void setIntermediaire(boolean b){
this.intermediaire=true;
}
public boolean isIntermediaire() {
return intermediaire;
}
public Color [] getColorHistogrammesDecomp(){
return null;
}
/**
* <p>
* Methode permettant de savoir si la classification est de type MacLaw ou
* non.
* </p>
*
* @return vrai si la classification est de type MacLaw
*/
public boolean isMaclaw() {
boolean res = false;
if (this.getLearningMethod() != null) {
res = (this.getLearningMethod().getType() == ClassifierUtils.MACLAW);
}
return res;
}
/**
* <p>
* Methode pour savoir si une classe est lockee ou non.
* </p>
*
* @param classNumber
* le numero de la classe a tester
* @return vrai si la classe est lockee
*/
public boolean isLocked(final int classNumber) {
return this.getClusteringResult().isLocked(classNumber);
}
/**
* <p>
* Methode lancant la classification (creation du resultat).
* </p>
*
* @throws MethodNotImplementedException
*/
abstract public void learn() throws MethodNotImplementedException;
/**
* <p>
* Methode de lockage d'une classe.
* </p>
*
* @param classNumber
* le numero de la classe a traiter
*/
public void lockClass(final int classNumber) {
this.getClusteringResult().lock(classNumber);
}
/**
* <p>
* Methode de fusion de classes en une classe.
*
* </p>
*
* @param cr
* la liste des classes a fusionner
* @throws MethodNotImplementedException
* si la methode de classification n'implante pas cet operateur
*/
abstract public void merge(Vector<Integer> cr)
throws MethodNotImplementedException;
/**
* <p>
* Methode de suppression d'une classe.
* </p>
<