From 3dc28a9251f18a2066bcbe91fbe19863dc783a16 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Euzenat?= <Jerome.Euzenat@inria.fr>
Date: Sat, 17 Dec 2011 18:54:13 +0000
Subject: [PATCH] - Implemented LaTeX output for GroupEval

---
 html/relnotes.html                            |   3 +-
 .../inrialpes/exmo/align/cli/GroupEval.java   | 634 +++++++++++-------
 2 files changed, 389 insertions(+), 248 deletions(-)

diff --git a/html/relnotes.html b/html/relnotes.html
index c138c22c..daf714c9 100644
--- a/html/relnotes.html
+++ b/html/relnotes.html
@@ -73,7 +73,8 @@ with a warning:
 <li>Implemented <tt>extractss</tt> for ** alignments in <tt>DistanceAlignment</tt> (impl)</li>
 <li>Changed default type of <tt>StringDistAlignment</tt> to "?*" for
   preserving the previous behaviour (impl)</li>
-<li>Added level lines in the triangle display of <tt>GroupEval</tt> (util)</li>
+<li>Added level lines in the triangle display of <tt>GroupEval</tt> (cli)</li>
+<li>Implemented LaTeX output in <tt>GroupEval</tt> (cli)</li>
 <li>Added <tt>BasicAlignment.deleteAllCells()</tt> (impl)</li>
 <li>Added a guard in <tt>loadOntology</tt> for OWLAPI 3.0, in case the
   ontology has no URI (ontowrap)</li>
diff --git a/src/fr/inrialpes/exmo/align/cli/GroupEval.java b/src/fr/inrialpes/exmo/align/cli/GroupEval.java
index fdc7b9a9..458446d4 100644
--- a/src/fr/inrialpes/exmo/align/cli/GroupEval.java
+++ b/src/fr/inrialpes/exmo/align/cli/GroupEval.java
@@ -38,6 +38,7 @@ import fr.inrialpes.exmo.ontowrap.OntowrapException;
 import java.io.File;
 import java.io.PrintStream;
 import java.io.FileOutputStream;
+import java.io.FileNotFoundException;
 import java.lang.Integer;
 import java.util.Hashtable;
 import java.util.Vector;
@@ -280,9 +281,21 @@ public class GroupEval {
      * This does not only print the results but compute the average as well
      */
     public void print( Vector<Vector> result ) {
-	if ( type.equals("html") ) printHTML( result );
-	else if ( type.equals("tex") ) printLATEX( result );
-	else if ( type.equals("triangle") ) printTRIANGLE( result );
+	PrintStream writer = null;
+	try {
+	    if ( filename == null ) {
+		writer = System.out;
+	    } else {
+		writer = new PrintStream(new FileOutputStream( filename ));
+	    }
+	    if ( type.equals("html") ) printHTML( result, writer );
+	    else if ( type.equals("tex") ) printLATEX( result, writer );
+	    else if ( type.equals("triangle") ) printTRIANGLE( result, writer );
+	} catch ( FileNotFoundException fnfex) {
+	    fnfex.printStackTrace();
+	} finally {
+	    writer.close();
+	}
     }
 
     /**
@@ -290,7 +303,7 @@ public class GroupEval {
      * Added level lines provides by Christian Meilicke (U. Mannheim)
      * See his program in comment below
      */
-    public void printTRIANGLE( Vector<Vector> result ) {
+    public void printTRIANGLE( Vector<Vector> result, PrintStream writer ) {
 	// variables for computing iterative harmonic means
 	int expected = 0; // expected so far
 	int foundVect[]; // found so far
@@ -323,62 +336,62 @@ public class GroupEval {
 		}
 	    }
 	}
-	System.out.println("\\documentclass[11pt]{book}");
-	System.out.println();
-	System.out.println("\\usepackage{pgf}");
-	System.out.println("\\usepackage{tikz}");
-	System.out.println();
-	System.out.println("\\begin{document}");
-	System.out.println("\\date{today}");
-	System.out.println("");
-	System.out.println("\n%% Plot generated by GenPlot of alignapi");
-	System.out.println("\\begin{tikzpicture}[cap=round]");
-	System.out.println("% Draw grid");
-	//System.out.println("\\draw[step=1cm,very thin,color=gray] (-0.2,-0.2) grid (10.0,9.0);");
-	System.out.println("\\draw[|-|] (-0,0) -- (10,0);");
-	System.out.println("%\\draw[dashed,very thin] (0,0) -- (5,8.66) -- (10,0);");
-	System.out.println("\\draw[dashed,very thin] (10,0) arc (0:60:10cm);");
-	System.out.println("\\draw[dashed,very thin] (0,0) arc (180:120:10cm);");
-
-	System.out.println("%% Level lines for recall");
-	System.out.println("\\draw[dashed] (10,0) arc (0:60:10cm) node[anchor=south east]  {{\\tiny R=1.}};");
-	System.out.println("\\draw[dotted,very thin] (9,0) arc (0:63:9cm) node[anchor=south east] {{\\tiny R=.9}};");
-	System.out.println("\\draw[dotted,very thin] (8,0) arc (0:66:8cm) node[anchor=south east]  {{\\tiny R=.8}};");
-	System.out.println("\\draw[dotted,very thin] (7,0) arc (0:70:7cm) node[anchor=south east]  {{\\tiny R=.7}};");
-	System.out.println("\\draw[dotted,very thin] (6,0) arc (0:73:6cm) node[anchor=south east]  {{\\tiny R=.6}};");
-	System.out.println("\\draw[dotted,very thin] (5,0) arc (0:76:5cm) node[anchor=south east] {{\\tiny R=.5}};");
-	System.out.println("\\draw[dotted,very thin] (4,0) arc (0:78:4cm) node[anchor=south east] {{\\tiny R=.4}};");
-	System.out.println("\\draw[dotted,very thin] (3,0) arc (0:80:3cm) node[anchor=south east] {{\\tiny R=.3}};");
-	System.out.println("\\draw[dotted,very thin] (2,0) arc (0:82:2cm) node[anchor=south east] {{\\tiny R=.2}};");
-	System.out.println("\\draw[dotted,very thin] (1,0) arc (0:84:1cm) node[anchor=south east] {{\\tiny R=.1}};");
-	System.out.println("%% Level lines for precision");
-	System.out.println("\\draw[dashed] (0,0) arc (180:120:10cm) node[anchor=south west] {{\\tiny P=1.}};");
-	System.out.println("\\draw[dotted,very thin] (1,0) arc (180:117:9cm) node[anchor=south west] {{\\tiny P=.9}};");
-	System.out.println("\\draw[dotted,very thin] (2,0) arc (180:114:8cm) node[anchor=south west] {{\\tiny P=.8}};");
-	System.out.println("\\draw[dotted,very thin] (3,0) arc (180:110:7cm) node[anchor=south west] {{\\tiny P=.7}};");
-	System.out.println("\\draw[dotted,very thin] (4,0) arc (180:107:6cm) node[anchor=south west] {{\\tiny P=.6}};");
-	System.out.println("\\draw[dotted,very thin] (5,0) arc (180:105:5cm) node[anchor=south west] {{\\tiny P=.5}};");
-	System.out.println("\\draw[dotted,very thin] (6,0) arc (180:103:4cm) node[anchor=south west] {{\\tiny P=.4}};");
-	System.out.println("\\draw[dotted,very thin] (7,0) arc (180:100:3cm) node[anchor=south west] {{\\tiny P=.3}};");
-	System.out.println("\\draw[dotted,very thin] (8,0) arc (180:96:2cm) node[anchor=south west] {{\\tiny P=.2}};");
-	System.out.println("\\draw[dotted,very thin] (9,0) arc (180:90:1cm) node[anchor=south west] {{\\tiny P=.1}};");
-	System.out.println("%% Level lines for F-measure");
-	System.out.println("\\draw[very thin,densely dotted] plot[smooth] coordinates { (0.56,3.29) (1.55,3.10) (2.46,2.68) (3.31,2.05) (4.12,1.19) (5.00,0.00) (6.42,1.79) (9.44,3.29)};");
-	System.out.println("\\draw (0.56,3.29) node[anchor=south west] {\\tiny{F=0.5}};");
-	System.out.println("\\draw[very thin,densely dotted] plot[smooth] coordinates { (0.92,4.19) (1.96,4.05) (2.95,3.78) (3.93,3.48) (5.00,3.32) (6.56,3.63) (9.08,4.19)};");
-	System.out.println("\\draw (0.92,4.19) node[anchor=south west] {\\tiny{F=0.6}};");
-	System.out.println("\\draw[very thin,densely dotted] plot[smooth] coordinates { (1.45,5.19) (2.59,5.11) (3.74,4.98) (5.00,4.90) (6.73,5.03) (8.55,5.19)};");
-	System.out.println("\\draw (1.45,5.19) node[anchor=south west] {\\tiny{F=0.7}};");
-	System.out.println("\\draw[very thin,densely dotted] plot[smooth] coordinates { (2.22,6.29) (3.54,6.27) (5.00,6.24) (6.91,6.28) (7.78,6.29)};");
-	System.out.println("\\draw (2.22,6.29) node[anchor=south west] {\\tiny{F=0.8}};");
-	System.out.println("\\draw[very thin,densely dotted] plot[smooth] coordinates { (3.35,7.47) (5.00,7.48) (6.65,7.47)};");
-	System.out.println("\\draw (3.35,7.47) node[anchor=south west] {\\tiny{F=0.9}};");
-
-	System.out.println("\\draw (0,-0.3) node {$recall$};");
-	System.out.println("\\draw (10,-0.3) node {$precision$};");
-	//System.out.println("\\draw (0,-0.3) node {0.}; ");
-	//System.out.println("\\draw (10,-0.3) node {1.}; ");
-	System.out.println("% Plots");
+	writer.println("\\documentclass[11pt]{book}");
+	writer.println();
+	writer.println("\\usepackage{pgf}");
+	writer.println("\\usepackage{tikz}");
+	writer.println();
+	writer.println("\\begin{document}");
+	writer.println("\\date{today}");
+	writer.println("");
+	writer.println("\n%% Plot generated by GroupEval of alignapi");
+	writer.println("\\begin{tikzpicture}[cap=round]");
+	writer.println("% Draw grid");
+	//writer.println("\\draw[step=1cm,very thin,color=gray] (-0.2,-0.2) grid (10.0,9.0);");
+	writer.println("\\draw[|-|] (-0,0) -- (10,0);");
+	writer.println("%\\draw[dashed,very thin] (0,0) -- (5,8.66) -- (10,0);");
+	writer.println("\\draw[dashed,very thin] (10,0) arc (0:60:10cm);");
+	writer.println("\\draw[dashed,very thin] (0,0) arc (180:120:10cm);");
+
+	writer.println("%% Level lines for recall");
+	writer.println("\\draw[dashed] (10,0) arc (0:60:10cm) node[anchor=south east]  {{\\tiny R=1.}};");
+	writer.println("\\draw[dotted,very thin] (9,0) arc (0:63:9cm) node[anchor=south east] {{\\tiny R=.9}};");
+	writer.println("\\draw[dotted,very thin] (8,0) arc (0:66:8cm) node[anchor=south east]  {{\\tiny R=.8}};");
+	writer.println("\\draw[dotted,very thin] (7,0) arc (0:70:7cm) node[anchor=south east]  {{\\tiny R=.7}};");
+	writer.println("\\draw[dotted,very thin] (6,0) arc (0:73:6cm) node[anchor=south east]  {{\\tiny R=.6}};");
+	writer.println("\\draw[dotted,very thin] (5,0) arc (0:76:5cm) node[anchor=south east] {{\\tiny R=.5}};");
+	writer.println("\\draw[dotted,very thin] (4,0) arc (0:78:4cm) node[anchor=south east] {{\\tiny R=.4}};");
+	writer.println("\\draw[dotted,very thin] (3,0) arc (0:80:3cm) node[anchor=south east] {{\\tiny R=.3}};");
+	writer.println("\\draw[dotted,very thin] (2,0) arc (0:82:2cm) node[anchor=south east] {{\\tiny R=.2}};");
+	writer.println("\\draw[dotted,very thin] (1,0) arc (0:84:1cm) node[anchor=south east] {{\\tiny R=.1}};");
+	writer.println("%% Level lines for precision");
+	writer.println("\\draw[dashed] (0,0) arc (180:120:10cm) node[anchor=south west] {{\\tiny P=1.}};");
+	writer.println("\\draw[dotted,very thin] (1,0) arc (180:117:9cm) node[anchor=south west] {{\\tiny P=.9}};");
+	writer.println("\\draw[dotted,very thin] (2,0) arc (180:114:8cm) node[anchor=south west] {{\\tiny P=.8}};");
+	writer.println("\\draw[dotted,very thin] (3,0) arc (180:110:7cm) node[anchor=south west] {{\\tiny P=.7}};");
+	writer.println("\\draw[dotted,very thin] (4,0) arc (180:107:6cm) node[anchor=south west] {{\\tiny P=.6}};");
+	writer.println("\\draw[dotted,very thin] (5,0) arc (180:105:5cm) node[anchor=south west] {{\\tiny P=.5}};");
+	writer.println("\\draw[dotted,very thin] (6,0) arc (180:103:4cm) node[anchor=south west] {{\\tiny P=.4}};");
+	writer.println("\\draw[dotted,very thin] (7,0) arc (180:100:3cm) node[anchor=south west] {{\\tiny P=.3}};");
+	writer.println("\\draw[dotted,very thin] (8,0) arc (180:96:2cm) node[anchor=south west] {{\\tiny P=.2}};");
+	writer.println("\\draw[dotted,very thin] (9,0) arc (180:90:1cm) node[anchor=south west] {{\\tiny P=.1}};");
+	writer.println("%% Level lines for F-measure");
+	writer.println("\\draw[very thin,densely dotted] plot[smooth] coordinates { (0.56,3.29) (1.55,3.10) (2.46,2.68) (3.31,2.05) (4.12,1.19) (5.00,0.00) (6.42,1.79) (9.44,3.29)};");
+	writer.println("\\draw (0.56,3.29) node[anchor=south west] {\\tiny{F=0.5}};");
+	writer.println("\\draw[very thin,densely dotted] plot[smooth] coordinates { (0.92,4.19) (1.96,4.05) (2.95,3.78) (3.93,3.48) (5.00,3.32) (6.56,3.63) (9.08,4.19)};");
+	writer.println("\\draw (0.92,4.19) node[anchor=south west] {\\tiny{F=0.6}};");
+	writer.println("\\draw[very thin,densely dotted] plot[smooth] coordinates { (1.45,5.19) (2.59,5.11) (3.74,4.98) (5.00,4.90) (6.73,5.03) (8.55,5.19)};");
+	writer.println("\\draw (1.45,5.19) node[anchor=south west] {\\tiny{F=0.7}};");
+	writer.println("\\draw[very thin,densely dotted] plot[smooth] coordinates { (2.22,6.29) (3.54,6.27) (5.00,6.24) (6.91,6.28) (7.78,6.29)};");
+	writer.println("\\draw (2.22,6.29) node[anchor=south west] {\\tiny{F=0.8}};");
+	writer.println("\\draw[very thin,densely dotted] plot[smooth] coordinates { (3.35,7.47) (5.00,7.48) (6.65,7.47)};");
+	writer.println("\\draw (3.35,7.47) node[anchor=south west] {\\tiny{F=0.9}};");
+
+	writer.println("\\draw (0,-0.3) node {$recall$};");
+	writer.println("\\draw (10,-0.3) node {$precision$};");
+	//writer.println("\\draw (0,-0.3) node {0.}; ");
+	//writer.println("\\draw (10,-0.3) node {1.}; ");
+	writer.println("% Plots");
 	int k = 0;
 	for ( String m: listAlgo ) {
 	    double precision = (double)correctVect[k]/foundVect[k];
@@ -387,16 +400,321 @@ public class GroupEval {
 	    double a = ((prec2-(recall*recall)+1)/2);
 	    double b = java.lang.Math.sqrt( prec2 - (a*a) );
 	    a = a*10; b = b*10; //for printing scale 10.
-	    System.out.println("\\draw plot[mark=+,] coordinates {("+a+","+b+")};");
-	    System.out.println("\\draw ("+(a+.01)+","+(b+.01)+") node[anchor=south west] {"+m+"};");
+	    writer.println("\\draw plot[mark=+,] coordinates {("+a+","+b+")};");
+	    writer.println("\\draw ("+(a+.01)+","+(b+.01)+") node[anchor=south west] {"+m+"};");
+	    k++;
+	}
+	writer.println("\\end{tikzpicture}");
+	writer.println();
+	writer.println("\\end{document}");
+    }
+
+    public void printHTML( Vector<Vector> result, PrintStream writer ) {
+	// variables for computing iterative harmonic means
+	int expected = 0; // expected so far
+	int foundVect[]; // found so far
+	int correctVect[]; // correct so far
+	long timeVect[]; // time so far
+	Formatter formatter = new Formatter(writer);
+
+	fsize = format.length();
+	// JE: the h-means computation should be put out as well
+	// Print the header
+	if ( embedded != true ) writer.println("<html><head></head><body>");
+	writer.println("<table border='2' frame='sides' rules='groups'>");
+	writer.println("<colgroup align='center' />");
+	// for each algo <td spancol='2'>name</td>
+	for ( String m : listAlgo ) {
+	    writer.println("<colgroup align='center' span='"+fsize+"' />");
+	}
+	// For each file do a
+	writer.println("<thead valign='top'><tr><th>algo</th>");
+	// for each algo <td spancol='2'>name</td>
+	for ( String m : listAlgo ) {
+	    writer.println("<th colspan='"+fsize+"'>"+m+"</th>");
+	}
+	writer.println("</tr></thead><tbody><tr><td>test</td>");
+	// for each algo <td>Prec.</td><td>Rec.</td>
+	for ( String m : listAlgo ) {
+	    for ( int i = 0; i < fsize; i++){
+		writer.print("<td>");
+		if ( format.charAt(i) == 'p' ) {
+		    writer.print("Prec.");
+		} else if ( format.charAt(i) == 'f' ) {
+		    writer.print("FMeas.");
+		} else if ( format.charAt(i) == 'o' ) {
+		    writer.print("Over.");
+		} else if ( format.charAt(i) == 't' ) {
+		    writer.print("Time");
+		} else if ( format.charAt(i) == 'r' ) {
+		    writer.print("Rec.");
+		}
+		writer.println("</td>");
+	    }
+	    //writer.println("<td>Prec.</td><td>Rec.</td>");
+	}
+	writer.println("</tr></tbody><tbody>");
+	foundVect = new int[ listAlgo.size() ];
+	correctVect = new int[ listAlgo.size() ];
+	timeVect = new long[ listAlgo.size() ];
+	for( int k = listAlgo.size()-1; k >= 0; k-- ) {
+	    foundVect[k] = 0;
+	    correctVect[k] = 0;
+	    timeVect[k] = 0;
+	}
+	// </tr>
+	// For each directory <tr>
+	boolean colored = false;
+	for ( Vector test : result ) {
+	    int nexpected = -1;
+	    if ( colored == true && color != null ){
+		colored = false;
+		writer.println("<tr bgcolor=\""+color+"\">");
+	    } else {
+		colored = true;
+		writer.println("<tr>");
+	    };
+	    // Print the directory <td>bla</td>
+	    writer.println("<td>"+(String)test.get(0)+"</td>");
+	    // For each record print the values <td>bla</td>
+	    Enumeration f = test.elements();
+	    f.nextElement();
+	    for( int k = 0 ; f.hasMoreElements() ; k++) {
+		PRecEvaluator eval = (PRecEvaluator)f.nextElement();
+		if ( eval != null ){
+		    // iterative H-means computation
+		    if ( nexpected == -1 ){
+			expected += eval.getExpected();
+			nexpected = 0;
+		    }
+		    foundVect[k] += eval.getFound();
+		    correctVect[k] += eval.getCorrect();
+		    timeVect[k] += eval.getTime();
+		    
+		    for ( int i = 0 ; i < fsize; i++){
+			writer.print("<td>");
+			if ( format.charAt(i) == 'p' ) {
+			    formatter.format("%1.2f", eval.getPrecision());
+			} else if ( format.charAt(i) == 'f' ) {
+			    formatter.format("%1.2f", eval.getFmeasure());
+			} else if ( format.charAt(i) == 'o' ) {
+			    formatter.format("%1.2f", eval.getOverall());
+			} else if ( format.charAt(i) == 't' ) {
+			    if ( eval.getTime() == 0 ){
+				writer.print("-");
+			    } else {
+				formatter.format("%1.2f", eval.getTime());
+			    }
+			} else if ( format.charAt(i) == 'r' ) {
+			    formatter.format("%1.2f", eval.getRecall());
+			}
+			writer.println("</td>");
+		    }
+		} else {
+		    writer.println("<td>n/a</td><td>n/a</td>");
+		}
+	    }
+	    writer.println("</tr>");
+	}
+	writer.print("<tr bgcolor=\"yellow\"><td>H-mean</td>");
+	// Here we are computing a sheer average.
+	// While in the column results we print NaN when the returned
+	// alignment is empty,
+	// here we use the real values, i.e., add 0 to both correctVect and
+	// foundVect, so this is OK for computing the average.
+	int k = 0;
+	// ???
+	for ( String m : listAlgo ) {
+	    double precision = (double)correctVect[k]/foundVect[k];
+	    double recall = (double)correctVect[k]/expected;
+	    for ( int i = 0 ; i < fsize; i++){
+		writer.print("<td>");
+		if ( format.charAt(i) == 'p' ) {
+		    formatter.format("%1.2f", precision);
+		} else if ( format.charAt(i) == 'f' ) {
+		    formatter.format("%1.2f", 2 * precision * recall / (precision + recall));
+		} else if ( format.charAt(i) == 'o' ) {
+		    formatter.format("%1.2f", recall * (2 - (1 / precision)));
+		} else if ( format.charAt(i) == 't' ) {
+		    if ( timeVect[k] == 0 ){
+			writer.print("-");
+		    } else {
+			formatter.format("%1.2f", timeVect[k]);
+		    }
+		} else if ( format.charAt(i) == 'r' ) {
+		    formatter.format("%1.2f", recall);
+		}
+		writer.println("</td>");
+	    };
+	    k++;
+	}
+	writer.println("</tr>");
+	writer.println("</tbody></table>");
+	writer.println("<p><small>n/a: result alignment not provided or not readable<br />");
+	writer.println("NaN: division per zero, likely due to empty alignment.</small></p>");
+	if ( embedded != true ) writer.println("</body></html>");
+    }
+
+    public void printLATEX( Vector<Vector> result, PrintStream writer ) {
+	// variables for computing iterative harmonic means
+	int expected = 0; // expected so far
+	int foundVect[]; // found so far
+	int correctVect[]; // correct so far
+	long timeVect[]; // time so far
+	Formatter formatter = new Formatter(writer);
+
+	fsize = format.length();
+	// JE: the h-means computation should be put out as well
+	// Print the header
+	writer.println("\\documentclass[11pt]{book}");
+	writer.println();
+	writer.println("\\begin{document}");
+	writer.println("\\date{today}");
+	writer.println("");
+	writer.println("\n%% Plot generated by GroupEval of alignapi");
+	writer.println("\\setlength{\\tabcolsep}{3pt} % May be changed");
+	writer.println("\\begin{table}");
+	writer.print("\\begin{tabular}{|l||");
+	for ( int i = listAlgo.size(); i > 0; i-- ) {
+	    for ( int j = fsize; j > 0; j-- ) writer.print("c");
+	    writer.print("|");
+	}
+	writer.println("}");
+	writer.println("\\hline");
+	// For each file do a
+	writer.print("algo");
+	// for each algo <td spancol='2'>name</td>
+	for ( String m : listAlgo ) {
+	    writer.print(" & \\multicolumn{"+fsize+"}{c|}{"+m+"}");
+	}
+	writer.println(" \\\\ \\hline");
+	writer.print("test");
+	// for each algo <td>Prec.</td><td>Rec.</td>
+	for ( String m : listAlgo ) {
+	    for ( int i = 0; i < fsize; i++){
+		writer.print(" & ");
+		if ( format.charAt(i) == 'p' ) {
+		    writer.print("Prec.");
+		} else if ( format.charAt(i) == 'f' ) {
+		    writer.print("FMeas.");
+		} else if ( format.charAt(i) == 'o' ) {
+		    writer.print("Over.");
+		} else if ( format.charAt(i) == 't' ) {
+		    writer.print("Time");
+		} else if ( format.charAt(i) == 'r' ) {
+		    writer.print("Rec.");
+		}
+	    }
+	}
+	writer.println(" \\\\ \\hline");
+	foundVect = new int[ listAlgo.size() ];
+	correctVect = new int[ listAlgo.size() ];
+	timeVect = new long[ listAlgo.size() ];
+	for( int k = listAlgo.size()-1; k >= 0; k-- ) {
+	    foundVect[k] = 0;
+	    correctVect[k] = 0;
+	    timeVect[k] = 0;
+	}
+	for ( Vector test : result ) {
+	    int nexpected = -1;
+	    // Print the directory 
+	    writer.print((String)test.get(0));
+	    // For each record print the values
+	    Enumeration f = test.elements();
+	    f.nextElement();
+	    for( int k = 0 ; f.hasMoreElements() ; k++) {
+		PRecEvaluator eval = (PRecEvaluator)f.nextElement();
+		if ( eval != null ){
+		    // iterative H-means computation
+		    if ( nexpected == -1 ){
+			expected += eval.getExpected();
+			nexpected = 0;
+		    }
+		    foundVect[k] += eval.getFound();
+		    correctVect[k] += eval.getCorrect();
+		    timeVect[k] += eval.getTime();
+		    
+		    for ( int i = 0 ; i < fsize; i++){
+			writer.print(" & ");
+			if ( format.charAt(i) == 'p' ) {
+			    formatter.format("%1.2f", eval.getPrecision());
+			} else if ( format.charAt(i) == 'f' ) {
+			    formatter.format("%1.2f", eval.getFmeasure());
+			} else if ( format.charAt(i) == 'o' ) {
+			    formatter.format("%1.2f", eval.getOverall());
+			} else if ( format.charAt(i) == 't' ) {
+			    if ( eval.getTime() == 0 ){
+				writer.print("-");
+			    } else {
+				formatter.format("%1.2f", eval.getTime());
+			    }
+			} else if ( format.charAt(i) == 'r' ) {
+			    formatter.format("%1.2f", eval.getRecall());
+			}
+		    }
+		} else {
+		    writer.print(" & \\multicolumn{"+fsize+"}{c|}{n/a}");
+		}
+	    }
+	    writer.println(" \\\\");
+	}
+	writer.print("H-mean");
+	// Here we are computing a sheer average.
+	// While in the column results we print NaN when the returned
+	// alignment is empty,
+	// here we use the real values, i.e., add 0 to both correctVect and
+	// foundVect, so this is OK for computing the average.
+	int k = 0;
+	// ???
+	for ( String m : listAlgo ) {
+	    double precision = (double)correctVect[k]/foundVect[k];
+	    double recall = (double)correctVect[k]/expected;
+	    for ( int i = 0 ; i < fsize; i++){
+		writer.print(" & ");
+		if ( format.charAt(i) == 'p' ) {
+		    formatter.format("%1.2f", precision);
+		} else if ( format.charAt(i) == 'f' ) {
+		    formatter.format("%1.2f", 2 * precision * recall / (precision + recall));
+		} else if ( format.charAt(i) == 'o' ) {
+		    formatter.format("%1.2f", recall * (2 - (1 / precision)));
+		} else if ( format.charAt(i) == 't' ) {
+		    if ( timeVect[k] == 0 ){
+			writer.print("-");
+		    } else {
+			formatter.format("%1.2f", timeVect[k]);
+		    }
+		} else if ( format.charAt(i) == 'r' ) {
+		    formatter.format("%1.2f", recall);
+		}
+	    };
 	    k++;
 	}
-	System.out.println("\\end{tikzpicture}");
-	System.out.println();
-	System.out.println("\\end{document}");
+	writer.println(" \\\\ \\hline");
+	writer.println("\\end{tabular}");
+	writer.println("\\caption{Plot generated by GroupEval of alignapi \\protect\\footnote{n/a: result alignment not provided or not readable -- NaN: division per zero, likely due to empty alignment.}}");
+	writer.println("\\end{table}");
+	writer.println("\\end{document}");
     }
 
-    /*
+    public void usage() {
+	System.out.println("usage: GroupEval [options]");
+	System.out.println("options are:");
+	System.out.println("\t--format=prfot -r prfot\tSpecifies the output order (precision/recall/f-measure/overall/time)");
+	// Apparently not implemented
+	//System.out.println("\t--sup=algo -s algo\tSpecifies if dominant columns are algorithms or measure");
+	System.out.println("\t--output=filename -o filename\tSpecifies a file to which the output will go");
+	System.out.println("\t--reference=filename -r filename\tSpecifies the name of the reference alignment file (default: refalign.rdf)");
+
+	System.out.println("\t--type=html|xml|tex|ascii|triangle -t html|xml|tex|ascii\tSpecifies the output format");
+	System.out.println("\t--list=algo1,...,algon -l algo1,...,algon\tSequence of the filenames to consider");
+	System.out.println("\t--color=color -c color\tSpecifies if the output must color even lines of the output");
+	System.out.println("\t--debug[=n] -d [n]\t\tReport debug info at level n");
+	System.out.println("\t--help -h\t\t\tPrint this message");
+	System.err.print("\n"+GroupEval.class.getPackage().getImplementationTitle()+" "+GroupEval.class.getPackage().getImplementationVersion());
+	System.err.println(" ($Id$)\n");
+    }
+
+/*
       // Here is the code provided by Christian Meilicke and modified by JE
       // For computing the F-measure level line in the Triangle representation
       // The class can be put in FMeasureLines.java and compiled.
@@ -493,13 +811,9 @@ public class FMeasureLines {
 	return new double[]{pp, pr};
     }
 }
-     */
-
-    public void printLATEX( Vector result ) {
-    }
+*/
 
-    /* A few comments on how and why computing "weighted harmonic means"
-       (J�r�me Euzenat)
+/* A few comments on how and why computing "weighted harmonic means" (J�r�me Euzenat)
 
 Let Ai be the found alignment for test i, let Ri be the reference alignment for test i.
 Let |A| be the size of A, i.e., the number of correspondences.
@@ -543,182 +857,8 @@ and
 	correctVect[k] / expected
 
 which the program does...
-    */
-    public void printHTML( Vector<Vector> result ) {
-	// variables for computing iterative harmonic means
-	int expected = 0; // expected so far
-	int foundVect[]; // found so far
-	int correctVect[]; // correct so far
-	long timeVect[]; // time so far
-	PrintStream writer = null;
-	fsize = format.length();
-	// JE: the writer should be put out
-	// JE: the h-means computation should be put out as well
-	try {
-	    // Print result
-	    if ( filename == null ) {
-		writer = System.out;
-	    } else {
-		writer = new PrintStream(new FileOutputStream( filename ));
-	    }
-	    Formatter formatter = new Formatter(writer);
-
-	    // Print the header
-	    if ( embedded != true ) writer.println("<html><head></head><body>");
-	    writer.println("<table border='2' frame='sides' rules='groups'>");
-	    writer.println("<colgroup align='center' />");
-	    // for each algo <td spancol='2'>name</td>
-	    for ( String m : listAlgo ) {
-		writer.println("<colgroup align='center' span='"+fsize+"' />");
-	    }
-	    // For each file do a
-	    writer.println("<thead valign='top'><tr><th>algo</th>");
-	    // for each algo <td spancol='2'>name</td>
-	    for ( String m : listAlgo ) {
-		writer.println("<th colspan='"+fsize+"'>"+m+"</th>");
-	    }
-	    writer.println("</tr></thead><tbody><tr><td>test</td>");
-	    // for each algo <td>Prec.</td><td>Rec.</td>
-	    for ( String m : listAlgo ) {
-		for ( int i = 0; i < fsize; i++){
-		    writer.print("<td>");
-		    if ( format.charAt(i) == 'p' ) {
-			writer.print("Prec.");
-		    } else if ( format.charAt(i) == 'f' ) {
-			writer.print("FMeas.");
-		    } else if ( format.charAt(i) == 'o' ) {
-			writer.print("Over.");
-		    } else if ( format.charAt(i) == 't' ) {
-			writer.print("Time");
-		    } else if ( format.charAt(i) == 'r' ) {
-			writer.print("Rec.");
-		    }
-		    writer.println("</td>");
-		}
-		//writer.println("<td>Prec.</td><td>Rec.</td>");
-	    }
-	    writer.println("</tr></tbody><tbody>");
-	    foundVect = new int[ listAlgo.size() ];
-	    correctVect = new int[ listAlgo.size() ];
-	    timeVect = new long[ listAlgo.size() ];
-	    for( int k = listAlgo.size()-1; k >= 0; k-- ) {
-		foundVect[k] = 0;
-		correctVect[k] = 0;
-		timeVect[k] = 0;
-	    }
-	    // </tr>
-	    // For each directory <tr>
-	    boolean colored = false;
-	    for ( Vector test : result ) {
-		int nexpected = -1;
-		if ( colored == true && color != null ){
-		    colored = false;
-		    writer.println("<tr bgcolor=\""+color+"\">");
-		} else {
-		    colored = true;
-		    writer.println("<tr>");
-		};
-		// Print the directory <td>bla</td>
-		writer.println("<td>"+(String)test.get(0)+"</td>");
-		// For each record print the values <td>bla</td>
-		Enumeration f = test.elements();
-		f.nextElement();
-		for( int k = 0 ; f.hasMoreElements() ; k++) {
-		    PRecEvaluator eval = (PRecEvaluator)f.nextElement();
-		    if ( eval != null ){
-			// iterative H-means computation
-			if ( nexpected == -1 ){
-			    expected += eval.getExpected();
-			    nexpected = 0;
-			}
-			foundVect[k] += eval.getFound();
-			correctVect[k] += eval.getCorrect();
-			timeVect[k] += eval.getTime();
-
-			for ( int i = 0 ; i < fsize; i++){
-			    writer.print("<td>");
-			    if ( format.charAt(i) == 'p' ) {
-				formatter.format("%1.2f", eval.getPrecision());
-			    } else if ( format.charAt(i) == 'f' ) {
-				formatter.format("%1.2f", eval.getFmeasure());
-			    } else if ( format.charAt(i) == 'o' ) {
-				formatter.format("%1.2f", eval.getOverall());
-			    } else if ( format.charAt(i) == 't' ) {
-				if ( eval.getTime() == 0 ){
-				    writer.print("-");
-				} else {
-				    formatter.format("%1.2f", eval.getTime());
-				}
-			    } else if ( format.charAt(i) == 'r' ) {
-				formatter.format("%1.2f", eval.getRecall());
-			    }
-			    writer.println("</td>");
-			}
-		    } else {
-			writer.println("<td>n/a</td><td>n/a</td>");
-		    }
-		}
-		writer.println("</tr>");
-	    }
-	    writer.print("<tr bgcolor=\"yellow\"><td>H-mean</td>");
-	    // Here we are computing a sheer average.
-	    // While in the column results we print NaN when the returned
-	    // alignment is empty,
-	    // here we use the real values, i.e., add 0 to both correctVect and
-	    // foundVect, so this is OK for computing the average.
-	    int k = 0;
-	    // ???
-	    for ( String m : listAlgo ) {
-		double precision = (double)correctVect[k]/foundVect[k];
-		double recall = (double)correctVect[k]/expected;
-		for ( int i = 0 ; i < fsize; i++){
-		    writer.print("<td>");
-		    if ( format.charAt(i) == 'p' ) {
-			formatter.format("%1.2f", precision);
-		    } else if ( format.charAt(i) == 'f' ) {
-			formatter.format("%1.2f", 2 * precision * recall / (precision + recall));
-		    } else if ( format.charAt(i) == 'o' ) {
-			formatter.format("%1.2f", recall * (2 - (1 / precision)));
-		    } else if ( format.charAt(i) == 't' ) {
-			if ( timeVect[k] == 0 ){
-			    writer.print("-");
-			} else {
-			    formatter.format("%1.2f", timeVect[k]);
-			}
-		    } else if ( format.charAt(i) == 'r' ) {
-			formatter.format("%1.2f", recall);
-		    }
-		    writer.println("</td>");
-		};
-		k++;
-	    }
-	    writer.println("</tr>");
-	    writer.println("</tbody></table>");
-	    writer.println("<p><small>n/a: result alignment not provided or not readable<br />");
-	    writer.println("NaN: division per zero, likely due to empty alignment.</small></p>");
-	    if ( embedded != true ) writer.println("</body></html>");
-	    writer.close();
-	} catch (Exception ex) {
-	    ex.printStackTrace();
-	}
-    }
+*/
 
-    public void usage() {
-	System.out.println("usage: GroupEval [options]");
-	System.out.println("options are:");
-	System.out.println("\t--format=prfot -r prfot\tSpecifies the output order (precision/recall/f-measure/overall/time)");
-	// Apparently not implemented
-	//System.out.println("\t--sup=algo -s algo\tSpecifies if dominant columns are algorithms or measure");
-	System.out.println("\t--output=filename -o filename\tSpecifies a file to which the output will go");
-	System.out.println("\t--reference=filename -r filename\tSpecifies the name of the reference alignment file (default: refalign.rdf)");
 
-	System.out.println("\t--type=html|xml|tex|ascii|triangle -t html|xml|tex|ascii\tSpecifies the output format");
-	System.out.println("\t--list=algo1,...,algon -l algo1,...,algon\tSequence of the filenames to consider");
-	System.out.println("\t--color=color -c color\tSpecifies if the output must color even lines of the output");
-	System.out.println("\t--debug[=n] -d [n]\t\tReport debug info at level n");
-	System.out.println("\t--help -h\t\t\tPrint this message");
-	System.err.print("\n"+GroupEval.class.getPackage().getImplementationTitle()+" "+GroupEval.class.getPackage().getImplementationVersion());
-	System.err.println(" ($Id$)\n");
-    }
 }
 
-- 
GitLab