Revision: 16570
          http://sourceforge.net/p/gate/code/16570
Author:   nirajaswani
Date:     2013-03-07 17:38:30 +0000 (Thu, 07 Mar 2013)
Log Message:
-----------
when anonymous mode is disabled, user can now specify names of annotation sets 
that refer to individual annotators (param name is 
annotationSetNamesAsAnnotators)

Modified Paths:
--------------
    gate/trunk/plugins/Teamware_Tools/src/gate/qa/QAForTeamwarePR.java

Modified: gate/trunk/plugins/Teamware_Tools/src/gate/qa/QAForTeamwarePR.java
===================================================================
--- gate/trunk/plugins/Teamware_Tools/src/gate/qa/QAForTeamwarePR.java  
2013-03-07 17:16:18 UTC (rev 16569)
+++ gate/trunk/plugins/Teamware_Tools/src/gate/qa/QAForTeamwarePR.java  
2013-03-07 17:38:30 UTC (rev 16570)
@@ -20,6 +20,8 @@
 import gate.creole.metadata.Optional;
 import gate.creole.metadata.RunTime;
 import gate.persist.PersistenceException;
+import gate.qa.Measure;
+import gate.qa.QualityAssurancePR;
 import gate.security.SecurityException;
 import gate.util.OffsetComparator;
 
@@ -56,790 +58,878 @@
  */
 @CreoleResource(name = "QA Summariser for Teamware", comment = "The Quality 
Assurance PR for teamware", helpURL = 
"http://gate.ac.uk/userguide/sec:eval:qaForTW";)
 public class QAForTeamwarePR extends AbstractLanguageAnalyser implements
-  ProcessingResource {
-  /**
-   * types of annotations to use
-   */
-  private List<String> annotationTypes;
+               ProcessingResource {
+       /**
+        * types of annotations to use
+        */
+       private List<String> annotationTypes;
 
-  /**
-   * features to use
-   */
-  private List<String> featureNames;
+       /**
+        * features to use
+        */
+       private List<String> featureNames;
 
-  /**
-   * which measure
-   */
-  private Measure measure;
+       /**
+        * which measure
+        */
+       private Measure measure;
 
-  /**
-   * folder where the output files need to be stored
-   */
-  private URL outputFolderUrl;
+       /**
+        * folder where the output files need to be stored
+        */
+       private URL outputFolderUrl;
 
-  /**
-   * number formatter
-   */
-  protected NumberFormat f = NumberFormat.getInstance(Locale.ENGLISH);
+       /**
+        * number formatter
+        */
+       protected NumberFormat f = NumberFormat.getInstance(Locale.ENGLISH);
 
-  /**
-   * Quality Assurance PR used internally
-   */
-  private QualityAssurancePR assurancePR;
+       /**
+        * Quality Assurance PR used internally
+        */
+       private QualityAssurancePR assurancePR;
 
-  /**
-   * used for keeping record of documents annotated by individual annotators
-   */
-  private Map<String, Set<Object>> annotatorToDocuments;
+       /**
+        * used for keeping record of documents annotated by individual 
annotators
+        */
+       private Map<String, Set<Object>> annotatorToDocuments;
 
-  /**
-   * create combinations of annotators who have done annotations on same
-   * documents
-   */
-  private Map<String, Set<Object>> annotatorsPairToDocuments;
+       /**
+        * create combinations of annotators who have done annotations on same
+        * documents
+        */
+       private Map<String, Set<Object>> annotatorsPairToDocuments;
 
-  /**
-   * Map used for storing score results
-   */
-  private Map<String, Map<String, Result>> results = null;
+       /**
+        * Map used for storing score results
+        */
+       private Map<String, Map<String, Result>> results = null;
 
-  /**
-   * ignore annotators
-   */
-  private List<String> annotatorsToIgnore = null;
+       /**
+        * ignore annotators
+        */
+       private List<String> annotatorsToIgnore = null;
 
-  /**
-   * Controller with QA PR as part of it.
-   */
-  private SerialAnalyserController controller;
+       /**
+        * If this parameter is provided, it is assumed that the annonymous 
mode is
+        * not in place and therefore the names of annotation sets should be
+        * considered as author names.
+        */
+       private List<String> annotationSetNamesAsAnnotators = null;
 
-  /**
-   * name of the consensus annotation set
-   */
-  public static final String CONSENSUS_AS_NAME = "consensus";
+       /**
+        * Controller with QA PR as part of it.
+        */
+       private SerialAnalyserController controller;
 
-  /**
-   * Indicates if the consensus annotation set exists in documents
-   */
-  private boolean consensusExists = false;
+       /**
+        * name of the consensus annotation set
+        */
+       public static final String CONSENSUS_AS_NAME = "consensus";
 
-  /** Initialise this resource, and return it. */
-  public Resource init() throws ResourceInstantiationException {
-    f.setMaximumFractionDigits(2); // format used for all decimal values
-    f.setMinimumFractionDigits(2);
-    // using QualityAssurancePR internally to calculate QA stats
-    // but hiding this PR just in case
-    FeatureMap hideParams = Factory.newFeatureMap();
-    Gate.setHiddenAttribute(hideParams, true);
-    assurancePR =
-      (QualityAssurancePR)Factory.createResource("gate.qa.QualityAssurancePR",
-        Factory.newFeatureMap(), hideParams);
-    // we use controller to execute assurance PR
-    controller =
-      (SerialAnalyserController)Factory.createResource(
-        SerialAnalyserController.class.getName(), Factory.newFeatureMap(),
-        hideParams);
-    controller.add(assurancePR);
-    return this;
-  } // init()
+       private static final String ANNOTATOR_PREFIX = "TW_Annotator_";
 
-  /**
-   * The execute method
-   */
-  public void execute() throws ExecutionException {
-    // the corpus cannot be null or empty
-    if(corpus == null || corpus.size() == 0) { throw new ExecutionException(
-      "Corpus cannot be null or empty"); }
-    // similarly user must provide annotation types that they want to
-    // compare
-    if(annotationTypes == null || annotationTypes.isEmpty())
-      throw new ExecutionException(
-        "Please provide at least one annotation type to compare");
-    // also a measure to use for computation
-    if(measure == null) { throw new ExecutionException("No measure selected"); 
}
-    // check if we are processing the last document in the corpus
-    Document firstDocument = (Document)corpus.get(0);
-    if(firstDocument == document) {
-      annotatorToDocuments = new HashMap<String, Set<Object>>();
-      annotatorsPairToDocuments = new HashMap<String, Set<Object>>();
-      results = new HashMap<String, Map<String, Result>>();
-      consensusExists = false;
-    }
-    // checking if consensus annotation set exists
-    consensusExists =
-      (consensusExists || document.getNamedAnnotationSets().containsKey(
-        CONSENSUS_AS_NAME));
-    // annotators found in this document
-    Set<String> annotators = new HashSet<String>();
-    for(Object featureName : document.getFeatures().keySet()) {
-      if(featureName instanceof String) {
-        String fName = (String)featureName;
-        if(fName.startsWith("safe.asname.")) {
-          String annotatorName = (String)document.getFeatures().get(fName);
-          annotators.add(annotatorName);
-        }
-      }
-    }
-    // we need to ignore some of the annotators
-    if(annotatorsToIgnore != null && !annotatorsToIgnore.isEmpty()) {
-      annotators.removeAll(annotatorsToIgnore);
-    }
-    // if no annotators found print a warning
-    if(annotators.isEmpty() || annotators.size() == 1) {
-      System.err
-        .println("No annotators or only one annotator found for the document " 
+
-          document.getName() + "\n" +
-          "Please make sure the document is annotated using Teamware and " +
-          "annotated by atleast two annotators!");
-    }
-    // if documents are loaded from datastore, we store only the
-    // persistence Ids
-    // or the document object itself
-    Object persistenceId = getDocument().getLRPersistenceId();
-    Object toStore = document;
-    if(persistenceId != null) {
-      toStore = persistenceId;
-    }
-    // which annotator annotated what documents
-    for(String annotatorName : annotators) {
-      Set<Object> docs = annotatorToDocuments.get(annotatorName);
-      if(docs == null) {
-        docs = new HashSet<Object>();
-        annotatorToDocuments.put(annotatorName, docs);
-      }
-      docs.add(toStore);
-    }
-    // given annotator names, we need to find out possible pairings
-    List<String> sortedAnnNames = new ArrayList<String>(annotators);
-    Collections.sort(sortedAnnNames);
-    for(int i = 0; i < sortedAnnNames.size() - 1; i++) {
-      String annName1 = sortedAnnNames.get(i);
-      for(int j = i + 1; j < sortedAnnNames.size(); j++) {
-        String annName2 = sortedAnnNames.get(j);
-        String key = annName1 + ";" + annName2;
-        Set<Object> docs = annotatorsPairToDocuments.get(key);
-        if(docs == null) {
-          docs = new HashSet<Object>();
-          annotatorsPairToDocuments.put(key, docs);
-        }
-        docs.add(toStore);
-      }
-    }
-    // check if we are processing the last document in the corpus
-    Document lastDocument = (Document)corpus.get(corpus.size() - 1);
-    if(lastDocument != document) { return; }
-    // if documents are being loaded from a datastore, it should be
-    // deleted
-    // after it has been used
-    boolean deleteDocs = false;
-    // first iteration
-    // this is for obtaining IAA between each individual annotator and
-    // concensus
-    // annotation sets
-    for(String annName : annotatorToDocuments.keySet()) {
-      // documents annotated by the current annotator
-      Set<Object> docs = annotatorToDocuments.get(annName);
-      Corpus corpus;
-      try {
-        corpus = Factory.newCorpus("qaCorpus");
-      } catch(ResourceInstantiationException e1) {
-        throw new ExecutionException(e1);
-      }
-      // one doc at a time
-      for(Object aDoc : docs) {
-        // load from ds if not in memory already
-        Document gateDoc = null;
-        if(!(aDoc instanceof Document)) {
-          try {
-            gateDoc =
-              (Document)getCorpus().getDataStore().getLr(
-                DocumentImpl.class.getName(), aDoc);
-            deleteDocs = true;
-          } catch(PersistenceException e) {
-            throw new ExecutionException(e);
-          } catch(SecurityException e) {
-            throw new ExecutionException(e);
-          }
-        } else {
-          gateDoc = (Document)aDoc;
-        }
-        // creating temporary annotation set with annotator's name
-        // across all documents in the corpus and copying annotations
-        // produced
-        // by him in that document into his annotationset
-        createAnnSet(gateDoc, getSetName(gateDoc, annName), annName);
-        // add document to the corpus
-        // doc will remain in memory until all computations are done
-        corpus.add(gateDoc);
-      }
-      // calculating IAA stats between annotator's annotations and
-      // consensus annotation set
-      if(consensusExists) {
-        calculateIAA(corpus, annName, CONSENSUS_AS_NAME, annName);
-      }
-      // deleting newly created annotation set and unloading documents
-      // if necessary
-      for(int k = corpus.size() - 1; k >= 0; k--) {
-        Document aDoc = (Document)corpus.get(k);
-        if(deleteDocs) {
-          Factory.deleteResource(aDoc);
-          continue;
-        }
-        aDoc.removeAnnotationSet(annName);
-      }
-      // delete the corpus as well
-      Factory.deleteResource(corpus);
-    }
-    // preparing for second iteration
-    deleteDocs = false;
-    // second iteration
-    // this is for obtaining IAA between individual annotators
-    for(String annotatorsPair : annotatorsPairToDocuments.keySet()) {
-      // documents annotated by this pair of annotators
-      Set<Object> docs = annotatorsPairToDocuments.get(annotatorsPair);
-      Corpus corpus;
-      try {
-        corpus = Factory.newCorpus("qaCorpus");
-      } catch(ResourceInstantiationException e1) {
-        throw new ExecutionException(e1);
-      }
-      // annotators in this pair
-      String annotator1 =
-        annotatorsPair.substring(0, annotatorsPair.indexOf(';'));
-      String annotator2 =
-        annotatorsPair.substring(annotatorsPair.indexOf(';') + 1);
-      // one doc at a time
-      for(Object aDoc : docs) {
-        // load the doc from DS if needed
-        Document gateDoc = null;
-        if(!(aDoc instanceof Document)) {
-          try {
-            gateDoc =
-              (Document)getCorpus().getDataStore().getLr(
-                DocumentImpl.class.getName(), aDoc);
-            deleteDocs = true;
-          } catch(PersistenceException e) {
-            throw new ExecutionException(e);
-          } catch(SecurityException e) {
-            throw new ExecutionException(e);
-          }
-        } else {
-          gateDoc = (Document)aDoc;
-        }
-        // creating sets for individual annotators and copying
-        // annotations from
-        // their anonymous annotation sets into their own annotation set
-        createAnnSet(gateDoc, getSetName(gateDoc, annotator1), annotator1);
-        createAnnSet(gateDoc, getSetName(gateDoc, annotator2), annotator2);
-        // adding doc to the corpus
-        corpus.add(gateDoc);
-      }
-      // calculate IAA
-      calculateIAA(corpus, annotator1, annotator2, annotator1 + "-" +
-        annotator2);
-      // deleting temporarily created annotation sets and deleting docs
-      // from
-      // memory if docs were loaded from the DS
-      for(int k = corpus.size() - 1; k >= 0; k--) {
-        Document aDoc = (Document)corpus.get(k);
-        if(deleteDocs) {
-          Factory.deleteResource(aDoc);
-          continue;
-        }
-        aDoc.removeAnnotationSet(annotator1);
-        aDoc.removeAnnotationSet(annotator2);
-      }
-      // delete the corpus
-      Factory.deleteResource(corpus);
-    }
-    // generating summary
-    // only accept the files with document-stats at the end
-    File[] resultFiles =
-      new File(outputFolderUrl.getFile()).listFiles(new FileFilter() {
-        public boolean accept(File pathname) {
-          return pathname.getAbsolutePath().endsWith("-document-stats.html");
-        }
-      });
-    // authors found in the corpus
-    List<String> columnAuthorNames = new ArrayList<String>();
-    double consensusMacro = 0.0D;
-    double consensusMicro = 0.0D;
-    double annotatorMacro = 0.0D;
-    double annotatorMicro = 0.0D;
-    // no result file found so quitting the execution
-    if(resultFiles == null) {
-      System.err
-        .println("WARNING: not enough information (most probably annotators)"
-          + " found for the summary to be generated!");
-      return;
-    }
-    // one file at a time
-    for(File file : resultFiles) {
-      // finding author names
-      String fileName =
-        file.getName().substring(0,
-          file.getName().indexOf("-document-stats.html"));
-      int index = fileName.indexOf('-');
-      String author1 = null;
-      String author2 = null;
-      // if only one author found, it means this file is for author vs
-      // consensus
-      // IAA
-      if(index < 0) {
-        author1 = fileName;
-        author2 = CONSENSUS_AS_NAME;
-      } else {
-        author1 = fileName.substring(0, index);
-        author2 = fileName.substring(index + 1);
-      }
-      if(!columnAuthorNames.contains(author2)) {
-        columnAuthorNames.add(author2);
-      }
-      if(!columnAuthorNames.contains(author1)) {
-        columnAuthorNames.add(author1);
-      }
-      // loading the document-stats file as GATE document
-      // and utilizing original markups to collect the needed
-      // information
-      // create a gate document
-      Document aDoc = null;
-      try {
-        aDoc = Factory.newDocument(file.toURI().toURL());
-      } catch(ResourceInstantiationException e) {
-        throw new ExecutionException(e);
-      } catch(MalformedURLException e) {
-        throw new ExecutionException(e);
-      }
-      // we're interested in macro and micro averages figures only
-      // these are the last two rows in the document-stats
-      AnnotationSet omSet = aDoc.getAnnotations("Original markups");
-      List<Annotation> rows = new ArrayList<Annotation>(omSet.get("tr"));
-      Collections.sort(rows, new OffsetComparator());
-      // temporary result object
-      Result r = new Result();
-      r.documentFileName = file.getName();
-      // consider last row for micro summary
-      Annotation row = rows.get(rows.size() - 1);
-      List<Annotation> cols =
-        new ArrayList<Annotation>(omSet.getContained(Utils.start(row),
-          Utils.end(row)).get("td"));
-      Collections.sort(cols, new OffsetComparator());
-      // only interested in the last column
-      r.micro =
-        Double.parseDouble(Utils.stringFor(aDoc, cols.get(cols.size() - 1)));
-      // consider second last row for macro summary
-      row = rows.get(rows.size() - 2);
-      cols =
-        new ArrayList<Annotation>(omSet.getContained(Utils.start(row),
-          Utils.end(row)).get("td"));
-      Collections.sort(cols, new OffsetComparator());
-      // only interested in the last column
-      r.macro =
-        Double.parseDouble(Utils.stringFor(aDoc, cols.get(cols.size() - 1)));
-      // delete the document from GATe
-      Factory.deleteResource(aDoc);
-      // making two entries
-      // i.e. author1-author2 and author2-author1
-      Map<String, Result> authorResults = results.get(author1);
-      if(authorResults == null) {
-        authorResults = new HashMap<String, Result>();
-        results.put(author1, authorResults);
-      }
-      authorResults.put(author2, r);
-      authorResults = results.get(author2);
-      if(authorResults == null) {
-        authorResults = new HashMap<String, Result>();
-        results.put(author2, authorResults);
-      }
-      authorResults.put(author1, r);
-    }
-    // collected all the results
-    Collections.sort(columnAuthorNames);
-    // generating html file contents
-    StringBuffer buffer = new StringBuffer();
-    buffer.append("<html>\n<title>Summary of IAA Results</title>\n<body>\n");
-    buffer.append("<h1>Summary of IAA Results</h1>");
-    buffer.append("<b>AnnotationTypes:</b> ");
-    for(String aType : annotationTypes) {
-      buffer.append(aType + ";");
-    }
-    buffer.append("<br>");
-    buffer.append("<b>Features:</b> ");
-    if(featureNames != null && !featureNames.isEmpty()) {
-      for(String aFeature : featureNames) {
-        buffer.append(aFeature + ";");
-      }
-    }
-    buffer.append("<br>");
-    buffer.append("<b>Measure:</b> " + measure.toString() + "<br>");
-    buffer.append("<table border=\"1\">\n");
-    // first row
-    buffer.append("\t<tr>\n");
-    buffer.append("\t\t<td><b>Author Names</b></td>\n");
-    for(String author2 : columnAuthorNames) {
-      buffer.append("\t\t<td colspan=\"2\"><b>" + author2 + "</b></td>\n");
-    }
-    buffer.append("\t\t<td colspan=\"2\"><b> Averages </b></td>\n");
-    buffer.append("\t</tr>\n");
-    // second row
-    buffer.append("\t<tr>\n");
-    buffer.append("\t\t<td>&nbsp;</td>\n");
-    // additional columns for averages
-    for(int i = 0; i <= columnAuthorNames.size(); i++) {
-      buffer.append("\t\t<td><b>Macro</b></td>\n");
-      buffer.append("\t\t<td><b>Micro</b></td>\n");
-    }
-    buffer.append("\t</tr>\n");
-    // color coding with transperancy
-    // 1.0 = dark green
-    // ... as we proceed we lighten the green color
-    // 0.5 = white
-    // ... as we proceed we brighten the red color
-    // 0.0 = red
-    List<String> authorNamesList = new ArrayList<String>(results.keySet());
-    Collections.sort(authorNamesList);
-    // all rows onwards
-    // producing matrix
-    for(String author1 : authorNamesList) {
-      double annMacro = 0.0D;
-      double annMicro = 0.0D;
-      int docs = 0;
-      buffer.append("\t<tr>\n");
-      buffer.append("\t\t<td><b>" + author1 + "</b></td>\n");
-      Map<String, Result> resultsForAuthor1 = results.get(author1);
-      // columns
-      for(String author2 : columnAuthorNames) {
-        Result r = resultsForAuthor1.get(author2);
-        if(r == null) {
-          buffer.append("\t\t<td colspan=\"2\">&nbsp;</td>\n");
-        } else {
-          // append macro micro figures to the table
-          appendMacroMicroFigures(buffer, r.macro, r.micro);
-          if(author1.equals(CONSENSUS_AS_NAME)) {
-            consensusMacro += r.macro;
-            consensusMicro += r.micro;
-          } else {
-            annMacro += r.macro;
-            annMicro += r.micro;
-            docs++;
-          }
-        }
-      }
-      // adding averages to the last 2 columns
-      if(author1.equals(CONSENSUS_AS_NAME)) {
-        double caMacroAvg =
-          (double)(consensusMacro / (double)(columnAuthorNames.size() - 1));
-        double caMicroAvg =
-          (double)(consensusMicro / (double)(columnAuthorNames.size() - 1));
-        appendMacroMicroFigures(buffer, caMacroAvg, caMicroAvg);
-      } else {
-        double aaMacroAvg = (double)(annMacro / (double)(docs));
-        double aaMicroAvg = (double)(annMicro / (double)(docs));
-        annotatorMacro += aaMacroAvg;
-        annotatorMicro += aaMicroAvg;
-        appendMacroMicroFigures(buffer, aaMacroAvg, aaMicroAvg);
-      }
-      buffer.append("\t</tr>\n");
-      buffer.append("\t<tr>\n");
-      buffer.append("\t\t<td>&nbsp;</td>\n");
-      for(String author2 : columnAuthorNames) {
-        Result r = resultsForAuthor1.get(author2);
-        if(r == null) {
-          buffer.append("\t\t<td colspan=\"2\">&nbsp;</td>\n");
-        } else {
-          buffer.append("\t\t<td colspan=\"2\"><a target=\"_blank\" href=\"" +
-            r.documentFileName + "\">document</a></td>\n");
-        }
-      }
-      buffer.append("\t\t<td colspan=\"2\">&nbsp;</td>\n");
-    }
-    buffer.append("</table>\n");
-    buffer.append("<hr>");
-    if(consensusExists) {
-      buffer.append("<br><b>Avg. " + CONSENSUS_AS_NAME + " macro avg:</b> " +
-        (f.format((double)consensusMacro / (columnAuthorNames.size() - 1))));
-      buffer.append("<br><b>Avg. " + CONSENSUS_AS_NAME + " micro avg:</b> " +
-        (f.format((double)consensusMicro / (columnAuthorNames.size() - 1))));
-    }
-    // if consensus annotation set exists, make sure the number used in
-    // demoninator does not include consensus as one annotator
-    int totalAuthors =
-      consensusExists ? columnAuthorNames.size() - 1 : 
columnAuthorNames.size();
-    buffer.append("<br><b>Avg. IAA macro avg:</b> " +
-      (f.format((double)annotatorMacro / totalAuthors)));
-    buffer.append("<br><b>Avg. IAA micro avg:</b> " +
-      (f.format((double)annotatorMicro / totalAuthors)));
-    buffer.append("</body>\n</html>");
-    BufferedWriter bw = null;
-    try {
-      File indexFile = new File(outputFolderUrl.getFile(), "index.html");
-      bw = new BufferedWriter(new FileWriter(indexFile));
-      bw.write(buffer.toString());
-    } catch(IOException ioe) {
-      throw new ExecutionException(ioe);
-    } finally {
-      if(bw != null) {
-        try {
-          bw.close();
-        } catch(IOException e) {
-          throw new ExecutionException(e);
-        }
-      }
-    }
-  }
+       /**
+        * Indicates if the consensus annotation set exists in documents
+        */
+       private boolean consensusExists = false;
 
-  /**
-   * A method that adds two columns to the buffer - one for the macro figure 
and
-   * the other one for the micro figure. It also adds relevant style tag to 
give
-   * a proper color to each cell depending on the value of macro and micro
-   * figures. See documentation of the getStyleTag(double) for more information
-   * on how cell backgrounds are color coded.
-   * 
-   * @param buffer
-   * @param macro
-   * @param micro
-   */
-  private void appendMacroMicroFigures(StringBuffer buffer, double macro,
-                                       double micro) {
-    String macCol = getStyleTag(macro);
-    String micCol = getStyleTag(micro);
-    buffer.append("\t\t<td " + macCol + " >" + f.format(macro) + "</td>\n");
-    buffer.append("\t\t<td " + micCol + " >" + f.format(micro) + "</td>\n");
-  }
+       /** Initialise this resource, and return it. */
+       public Resource init() throws ResourceInstantiationException {
+               f.setMaximumFractionDigits(2); // format used for all decimal 
values
+               f.setMinimumFractionDigits(2);
+               // using QualityAssurancePR internally to calculate QA stats
+               // but hiding this PR just in case
+               FeatureMap hideParams = Factory.newFeatureMap();
+               Gate.setHiddenAttribute(hideParams, true);
+               assurancePR = (QualityAssurancePR) Factory.createResource(
+                               "gate.qa.QualityAssurancePR", 
Factory.newFeatureMap(),
+                               hideParams);
+               // we use controller to execute assurance PR
+               controller = (SerialAnalyserController) Factory.createResource(
+                               SerialAnalyserController.class.getName(),
+                               Factory.newFeatureMap(), hideParams);
+               controller.add(assurancePR);
+               return this;
+       } // init()
 
-  /**
-   * Gets the style tag based on the score. The color green is used for a cell
-   * background to indicate full agreement (i.e. 1.0). The background color
-   * becomes lighter as the agreement reduces towards 0.5. At 0.5 agreement, 
the
-   * background color of a cell is fully white. From 0.5 downwards, the color
-   * red is used and as the agreement reduces further, the color becomes darker
-   * with dark red at 0.0 agreement.
-   * 
-   * @param score
-   * @return
-   */
-  private String getStyleTag(double score) {
-    // two colors
-    Color gc = Color.GREEN;
-    Color rc = Color.RED;
-    Color c = null;
-    // if score is above .50, use the green color, otherwise the red one
-    if(score > 0.50) {
-      c =
-        new Color(gc.getRed(), gc.getGreen(), gc.getBlue(),
-          ((int)(score * 100) * 2) - 100);
-    } else {
-      c =
-        new Color(rc.getRed(), rc.getGreen(), rc.getBlue(),
-          100 - ((int)(score * 100) * 2));
-    }
-    return "style=\"background-color: rgba(" + c.getRed() + "," + c.getGreen() 
+
-      "," + c.getBlue() + "," + ((double)c.getAlpha() / 100) + ")\"";
-  }
+       /**
+        * The execute method
+        */
+       public void execute() throws ExecutionException {
+               // the corpus cannot be null or empty
+               if (corpus == null || corpus.size() == 0) {
+                       throw new ExecutionException("Corpus cannot be null or 
empty");
+               }
+               // similarly user must provide annotation types that they want 
to
+               // compare
+               if (annotationTypes == null || annotationTypes.isEmpty())
+                       throw new ExecutionException(
+                                       "Please provide at least one annotation 
type to compare");
+               // also a measure to use for computation
+               if (measure == null) {
+                       throw new ExecutionException("No measure selected");
+               }
+               // check if we are processing the last document in the corpus
+               Document firstDocument = (Document) corpus.get(0);
+               if (firstDocument == document) {
+                       annotatorToDocuments = new HashMap<String, 
Set<Object>>();
+                       annotatorsPairToDocuments = new HashMap<String, 
Set<Object>>();
+                       results = new HashMap<String, Map<String, Result>>();
+                       consensusExists = false;
+               }
+               // checking if consensus annotation set exists
+               consensusExists = (consensusExists || 
document.getNamedAnnotationSets()
+                               .containsKey(CONSENSUS_AS_NAME));
 
-  /**
-   * Given the annotator name, the method finds out the annotation set which
-   * contains annotations for that annotator
-   * 
-   * @param doc
-   * @param annotatorName
-   * @return
-   */
-  private String getSetName(Document doc, String annotatorName) {
-    String inputAS = null;
-    for(Object key : doc.getFeatures().keySet()) {
-      Object val = doc.getFeatures().get(key);
-      if(val.equals(annotatorName)) {
-        inputAS = key.toString().substring(12);
-        break;
-      }
-    }
-    return inputAS;
-  }
+               // this is where we store names of annotators
+               Set<String> annotators = new HashSet<String>();
 
-  /**
-   * Creating a temporary annotation set
-   * 
-   * @param doc
-   * @param inputAS
-   * @param outputAS
-   */
-  private void createAnnSet(Document doc, String inputAS, String outputAS) {
-    AnnotationSet inAS =
-      inputAS == null || inputAS.trim().length() == 0
-        ? doc.getAnnotations()
-        : doc.getAnnotations(inputAS);
-    inAS = inAS.get(new HashSet<String>(annotationTypes));
-    AnnotationSet outAS = doc.getAnnotations(outputAS);
-    for(Annotation a : inAS) {
-      outAS.add(a.getStartNode(), a.getEndNode(), a.getType(), 
a.getFeatures());
-    }
-  }
+               // we ignore the following block if anonymous mode was disabled
+               // and we determine that by checking if user has provided values
+               // for annotationSetNamesAsAnnotators
+               if (annotationSetNamesAsAnnotators == null
+                               || annotationSetNamesAsAnnotators.isEmpty()) {
+                       // annotators found in this document
+                       for (Object featureName : 
document.getFeatures().keySet()) {
+                               if (featureName instanceof String) {
+                                       String fName = (String) featureName;
+                                       if (fName.startsWith("safe.asname.")) {
+                                               String annotatorName = (String) 
document.getFeatures()
+                                                               .get(fName);
+                                               annotators.add(annotatorName);
+                                       }
+                               }
+                       }
 
-  /**
-   * A method that calculates IAA between the given annotation sets
-   * 
-   * @param corpus
-   * @param keyAS
-   * @param responseAS
-   * @param filePrefix
-   * @throws ExecutionException
-   */
-  private void calculateIAA(Corpus corpus, String keyAS, String responseAS,
-                            String filePrefix) throws ExecutionException {
-    try {
-      assurancePR.reInit();
-    } catch(ResourceInstantiationException rie) {
-      throw new ExecutionException(rie);
-    }
-    // lets set the params on qualityAssurancePR
-    assurancePR.setAnnotationTypes(annotationTypes);
-    assurancePR.setFeatureNames(featureNames == null
-      ? new ArrayList<String>()
-      : featureNames);
-    assurancePR.setMeasure(measure);
-    assurancePR.setOutputFolderUrl(outputFolderUrl);
-    // the remaining two params will be set later
-    assurancePR.setKeyASName(keyAS);
-    assurancePR.setResponseASName(responseAS);
-    controller.setCorpus(corpus);
-    controller.execute();
-    // QA PR produces two stats file, one for corpus and one for
-    // documents
-    // for QAForTeamware, we don't need corpus one
-    File corpusFile = new File(outputFolderUrl.getFile(), "corpus-stats.html");
-    corpusFile.delete();
-    File documentFile =
-      new File(outputFolderUrl.getFile(), "document-stats.html");
-    File documentOutFile =
-      new File(outputFolderUrl.getFile(), filePrefix + "-document-stats.html");
-    documentFile.renameTo(documentOutFile);
-  }
+                       // we need to ignore some of the annotators if we are 
instructed to
+                       // do
+                       // so
+                       if (annotatorsToIgnore != null && 
!annotatorsToIgnore.isEmpty()) {
+                               annotators.removeAll(annotatorsToIgnore);
+                       }
+               } else {
+                       // find out which of the annotationSetNamesAsAnnotators
+                       // has annotated this document
+                       for (String annotatorName : 
annotationSetNamesAsAnnotators) {
+                               if (document.getNamedAnnotationSets()
+                                               .containsKey(annotatorName)) {
+                                       annotators.add(annotatorName);
+                               }
+                       }
+               }
 
-  /**
-   * Method called when a PR is unloaded.
-   */
-  public void cleanup() {
-    super.cleanup();
-    Factory.deleteResource(assurancePR);
-    Factory.deleteResource(controller);
-  }
+               // if no annotators found print a warning
+               if (annotators.isEmpty() || annotators.size() == 1) {
+                       System.err
+                                       .println("No annotators or only one 
annotator found for the document "
+                                                       + document.getName()
+                                                       + "\n"
+                                                       + "Please make sure the 
document is annotated using Teamware and "
+                                                       + "annotated by atleast 
two annotators!");
+               }
 
-  /**
-   * Annotation types for which the stats should be calculated
-   * 
-   * @return
-   */
-  public List<String> getAnnotationTypes() {
-    return annotationTypes;
-  }
+               // if documents are loaded from datastore, we store only the
+               // persistence Ids
+               // or the document object itself
+               Object persistenceId = getDocument().getLRPersistenceId();
+               Object toStore = document;
+               if (persistenceId != null) {
+                       toStore = persistenceId;
+               }
 
-  /**
-   * Annotation types for which the stats should be calculated
-   * 
-   * @param annotationTypes
-   */
-  @RunTime
-  @CreoleParameter
-  public void setAnnotationTypes(List<String> annotationTypes) {
-    this.annotationTypes = annotationTypes;
-  }
+               // which annotator annotated what documents
+               for (String annotatorName : annotators) {
+                       Set<Object> docs = 
annotatorToDocuments.get(annotatorName);
+                       if (docs == null) {
+                               docs = new HashSet<Object>();
+                               annotatorToDocuments.put(annotatorName, docs);
+                       }
+                       docs.add(toStore);
+               }
 
-  /**
-   * Features names for which the stats should be calculated
-   * 
-   * @return
-   */
-  public List<String> getFeatureNames() {
-    return featureNames;
-  }
+               // given annotator names, we need to find out possible pairings
+               List<String> sortedAnnNames = new ArrayList<String>(annotators);
+               Collections.sort(sortedAnnNames);
+               for (int i = 0; i < sortedAnnNames.size() - 1; i++) {
+                       String annName1 = sortedAnnNames.get(i);
+                       for (int j = i + 1; j < sortedAnnNames.size(); j++) {
+                               String annName2 = sortedAnnNames.get(j);
+                               String key = annName1 + ";" + annName2;
+                               Set<Object> docs = 
annotatorsPairToDocuments.get(key);
+                               if (docs == null) {
+                                       docs = new HashSet<Object>();
+                                       annotatorsPairToDocuments.put(key, 
docs);
+                               }
+                               docs.add(toStore);
+                       }
+               }
 
-  /**
-   * Features names for which the stats should be calculated
-   * 
-   * @param featureNames
-   */
-  @RunTime
-  @Optional
-  @CreoleParameter
-  public void setFeatureNames(List<String> featureNames) {
-    this.featureNames = featureNames;
-  }
+               // check if we are processing the last document in the corpus
+               Document lastDocument = (Document) corpus.get(corpus.size() - 
1);
+               if (lastDocument != document) {
+                       return;
+               }
 
-  /**
-   * Measure to use for stats calculation
-   * 
-   * @return
-   */
-  public Measure getMeasure() {
-    return measure;
-  }
+               // if documents are being loaded from a datastore, it should be
+               // deleted
+               // after it has been used
+               boolean deleteDocs = false;
+               // first iteration
+               // this is for obtaining IAA between each individual annotator 
and
+               // concensus
+               // annotation sets
+               for (String annName : annotatorToDocuments.keySet()) {
+                       // documents annotated by the current annotator
+                       Set<Object> docs = annotatorToDocuments.get(annName);
+                       Corpus corpus;
+                       try {
+                               corpus = Factory.newCorpus("qaCorpus");
+                       } catch (ResourceInstantiationException e1) {
+                               throw new ExecutionException(e1);
+                       }
+                       // one doc at a time
+                       for (Object aDoc : docs) {
+                               // load from ds if not in memory already
+                               Document gateDoc = null;
+                               if (!(aDoc instanceof Document)) {
+                                       try {
+                                               gateDoc = (Document) 
getCorpus().getDataStore().getLr(
+                                                               
DocumentImpl.class.getName(), aDoc);
+                                               deleteDocs = true;
+                                       } catch (PersistenceException e) {
+                                               throw new ExecutionException(e);
+                                       } catch (SecurityException e) {
+                                               throw new ExecutionException(e);
+                                       }
+                               } else {
+                                       gateDoc = (Document) aDoc;
+                               }
+                               // creating temporary annotation set with 
annotator's name
+                               // across all documents in the corpus and 
copying annotations
+                               // produced
+                               // by him in that document into his 
annotationset
+                               createAnnSet(gateDoc, getSetName(gateDoc, 
annName), ANNOTATOR_PREFIX + annName);
 
-  /**
-   * Measure to use for stats calculation
-   * 
-   * @param measure
-   */
-  @RunTime
-  @CreoleParameter
-  public void setMeasure(Measure measure) {
-    this.measure = measure;
-  }
+                               // add document to the corpus
+                               // doc will remain in memory until all 
computations are done
+                               corpus.add(gateDoc);
+                       }
+                       // calculating IAA stats between annotator's 
annotations and
+                       // consensus annotation set
+                       if (consensusExists) {
+                               calculateIAA(corpus, ANNOTATOR_PREFIX + 
annName, CONSENSUS_AS_NAME, annName);
+                       }
 
-  /**
-   * URL of the folder to store output files into
-   * 
-   * @return
-   */
-  public URL getOutputFolderUrl() {
-    return outputFolderUrl;
-  }
+                       // deleting newly created annotation set and unloading 
documents
+                       // if necessary
+                       for (int k = corpus.size() - 1; k >= 0; k--) {
+                               Document aDoc = (Document) corpus.get(k);
+                               if (deleteDocs) {
+                                       Factory.deleteResource(aDoc);
+                                       continue;
+                               }
 
-  /**
-   * URL of the folder to store output files into
-   * 
-   * @param outputFolderUrl
-   */
-  @RunTime
-  @CreoleParameter(suffixes = "html")
-  public void setOutputFolderUrl(URL outputFolderUrl) {
-    this.outputFolderUrl = outputFolderUrl;
-  }
+                               aDoc.removeAnnotationSet(ANNOTATOR_PREFIX + 
annName);
+                       }
+                       // delete the corpus as well
+                       Factory.deleteResource(corpus);
+               }
 
-  /**
-   * annotators to ignore when computing IAA
-   * 
-   * @return
-   */
-  public List<String> getAnnotatorsToIgnore() {
-    return annotatorsToIgnore;
-  }
+               // preparing for second iteration
+               deleteDocs = false;
 
-  /**
-   * annotators to ingore when computing IAA
-   * 
-   * @param annotatorsToIgnore
-   */
-  @RunTime
-  @Optional
-  @CreoleParameter
-  public void setAnnotatorsToIgnore(List<String> annotatorsToIgnore) {
-    this.annotatorsToIgnore = annotatorsToIgnore;
-  }
+               // second iteration
+               // this is for obtaining IAA between individual annotators
+               for (String annotatorsPair : 
annotatorsPairToDocuments.keySet()) {
+                       // documents annotated by this pair of annotators
+                       Set<Object> docs = 
annotatorsPairToDocuments.get(annotatorsPair);
+                       Corpus corpus;
+                       try {
+                               corpus = Factory.newCorpus("qaCorpus");
+                       } catch (ResourceInstantiationException e1) {
+                               throw new ExecutionException(e1);
+                       }
+                       // annotators in this pair
+                       String annotator1 = annotatorsPair.substring(0,
+                                       annotatorsPair.indexOf(';'));
+                       String annotator2 = 
annotatorsPair.substring(annotatorsPair
+                                       .indexOf(';') + 1);
+                       // one doc at a time
+                       for (Object aDoc : docs) {
+                               // load the doc from DS if needed
+                               Document gateDoc = null;
+                               if (!(aDoc instanceof Document)) {
+                                       try {
+                                               gateDoc = (Document) 
getCorpus().getDataStore().getLr(
+                                                               
DocumentImpl.class.getName(), aDoc);
+                                               deleteDocs = true;
+                                       } catch (PersistenceException e) {
+                                               throw new ExecutionException(e);
+                                       } catch (SecurityException e) {
+                                               throw new ExecutionException(e);
+                                       }
+                               } else {
+                                       gateDoc = (Document) aDoc;
+                               }
+                               // creating sets for individual annotators and 
copying
+                               // annotations from
+                               // their anonymous annotation sets into their 
own annotation set
+                               createAnnSet(gateDoc, getSetName(gateDoc, 
annotator1),
+                                               ANNOTATOR_PREFIX + annotator1);
+                               createAnnSet(gateDoc, getSetName(gateDoc, 
annotator2),
+                                               ANNOTATOR_PREFIX + annotator2);
+                               // adding doc to the corpus
+                               corpus.add(gateDoc);
+                       }
+                       // calculate IAA
+                       calculateIAA(corpus, ANNOTATOR_PREFIX + annotator1,
+                                       ANNOTATOR_PREFIX + annotator2, 
annotator1 + "-"
+                                                       + annotator2);
+                       // deleting temporarily created annotation sets and 
deleting docs
+                       // from
+                       // memory if docs were loaded from the DS
+                       for (int k = corpus.size() - 1; k >= 0; k--) {
+                               Document aDoc = (Document) corpus.get(k);
+                               if (deleteDocs) {
+                                       Factory.deleteResource(aDoc);
+                                       continue;
+                               }
 
-  /**
-   * Storing individual results for each pair of annotators
-   * 
-   * @author niraj
-   */
-  class Result {
-    // macro average
-    double macro = 0.0D;
+                               aDoc.removeAnnotationSet(ANNOTATOR_PREFIX + 
annotator1);
+                               aDoc.removeAnnotationSet(ANNOTATOR_PREFIX + 
annotator2);
+                       }
+                       // delete the corpus
+                       Factory.deleteResource(corpus);
+               }
+               // generating summary
+               // only accept the files with document-stats at the end
+               File[] resultFiles = new File(outputFolderUrl.getFile())
+                               .listFiles(new FileFilter() {
+                                       public boolean accept(File pathname) {
+                                               return 
pathname.getAbsolutePath().endsWith(
+                                                               
"-document-stats.html");
+                                       }
+                               });
+               // authors found in the corpus
+               List<String> columnAuthorNames = new ArrayList<String>();
+               double consensusMacro = 0.0D;
+               double consensusMicro = 0.0D;
+               double annotatorMacro = 0.0D;
+               double annotatorMicro = 0.0D;
+               // no result file found so quitting the execution
+               if (resultFiles == null) {
+                       System.err
+                                       .println("WARNING: not enough 
information (most probably annotators)"
+                                                       + " found for the 
summary to be generated!");
+                       return;
+               }
+               // one file at a time
+               for (File file : resultFiles) {
+                       // finding author names
+                       String fileName = file.getName().substring(0,
+                                       
file.getName().indexOf("-document-stats.html"));
+                       int index = fileName.indexOf('-');
+                       String author1 = null;
+                       String author2 = null;
+                       // if only one author found, it means this file is for 
author vs
+                       // consensus
+                       // IAA
+                       if (index < 0) {
+                               author1 = fileName;
+                               author2 = CONSENSUS_AS_NAME;
+                       } else {
+                               author1 = fileName.substring(0, index);
+                               author2 = fileName.substring(index + 1);
+                       }
+                       if (!columnAuthorNames.contains(author2)) {
+                               columnAuthorNames.add(author2);
+                       }
+                       if (!columnAuthorNames.contains(author1)) {
+                               columnAuthorNames.add(author1);
+                       }
+                       // loading the document-stats file as GATE document
+                       // and utilizing original markups to collect the needed
+                       // information
+                       // create a gate document
+                       Document aDoc = null;
+                       try {
+                               aDoc = 
Factory.newDocument(file.toURI().toURL());
+                       } catch (ResourceInstantiationException e) {
+                               throw new ExecutionException(e);
+                       } catch (MalformedURLException e) {
+                               throw new ExecutionException(e);
+                       }
+                       // we're interested in macro and micro averages figures 
only
+                       // these are the last two rows in the document-stats
+                       AnnotationSet omSet = aDoc.getAnnotations("Original 
markups");
+                       List<Annotation> rows = new 
ArrayList<Annotation>(omSet.get("tr"));
+                       Collections.sort(rows, new OffsetComparator());
+                       // temporary result object
+                       Result r = new Result();
+                       r.documentFileName = file.getName();
+                       // consider last row for micro summary
+                       Annotation row = rows.get(rows.size() - 1);
+                       List<Annotation> cols = new ArrayList<Annotation>(omSet
+                                       .getContained(Utils.start(row), 
Utils.end(row)).get("td"));
+                       Collections.sort(cols, new OffsetComparator());
+                       // only interested in the last column
+                       r.micro = Double.parseDouble(Utils.stringFor(aDoc,
+                                       cols.get(cols.size() - 1)));
+                       // consider second last row for macro summary
+                       row = rows.get(rows.size() - 2);
+                       cols = new ArrayList<Annotation>(omSet.getContained(
+                                       Utils.start(row), 
Utils.end(row)).get("td"));
+                       Collections.sort(cols, new OffsetComparator());
+                       // only interested in the last column
+                       r.macro = Double.parseDouble(Utils.stringFor(aDoc,
+                                       cols.get(cols.size() - 1)));
+                       // delete the document from GATe
+                       Factory.deleteResource(aDoc);
+                       // making two entries
+                       // i.e. author1-author2 and author2-author1
+                       Map<String, Result> authorResults = 
results.get(author1);
+                       if (authorResults == null) {
+                               authorResults = new HashMap<String, Result>();
+                               results.put(author1, authorResults);
+                       }
+                       authorResults.put(author2, r);
+                       authorResults = results.get(author2);
+                       if (authorResults == null) {
+                               authorResults = new HashMap<String, Result>();
+                               results.put(author2, authorResults);
+                       }
+                       authorResults.put(author1, r);
+               }
+               // collected all the results
+               Collections.sort(columnAuthorNames);
+               // generating html file contents
+               StringBuffer buffer = new StringBuffer();
+               buffer.append("<html>\n<title>Summary of IAA 
Results</title>\n<body>\n");
+               buffer.append("<h1>Summary of IAA Results</h1>");
+               buffer.append("<b>AnnotationTypes:</b> ");
+               for (String aType : annotationTypes) {
+                       buffer.append(aType + ";");
+               }
+               buffer.append("<br>");
+               buffer.append("<b>Features:</b> ");
+               if (featureNames != null && !featureNames.isEmpty()) {
+                       for (String aFeature : featureNames) {
+                               buffer.append(aFeature + ";");
+                       }
+               }
+               buffer.append("<br>");
+               buffer.append("<b>Measure:</b> " + measure.toString() + "<br>");
+               buffer.append("<table border=\"1\">\n");
+               // first row
+               buffer.append("\t<tr>\n");
+               buffer.append("\t\t<td><b>Author Names</b></td>\n");
+               for (String author2 : columnAuthorNames) {
+                       buffer.append("\t\t<td colspan=\"2\"><b>" + author2 + 
"</b></td>\n");
+               }
+               buffer.append("\t\t<td colspan=\"2\"><b> Averages </b></td>\n");
+               buffer.append("\t</tr>\n");
+               // second row
+               buffer.append("\t<tr>\n");
+               buffer.append("\t\t<td>&nbsp;</td>\n");
+               // additional columns for averages
+               for (int i = 0; i <= columnAuthorNames.size(); i++) {
+                       buffer.append("\t\t<td><b>Macro</b></td>\n");
+                       buffer.append("\t\t<td><b>Micro</b></td>\n");
+               }
+               buffer.append("\t</tr>\n");
+               // color coding with transperancy
+               // 1.0 = dark green
+               // ... as we proceed we lighten the green color
+               // 0.5 = white
+               // ... as we proceed we brighten the red color
+               // 0.0 = red
+               List<String> authorNamesList = new 
ArrayList<String>(results.keySet());
+               Collections.sort(authorNamesList);
+               // all rows onwards
+               // producing matrix
+               for (String author1 : authorNamesList) {
+                       double annMacro = 0.0D;
+                       double annMicro = 0.0D;
+                       int docs = 0;
+                       buffer.append("\t<tr>\n");
+                       buffer.append("\t\t<td><b>" + author1 + "</b></td>\n");
+                       Map<String, Result> resultsForAuthor1 = 
results.get(author1);
+                       // columns
+                       for (String author2 : columnAuthorNames) {
+                               Result r = resultsForAuthor1.get(author2);
+                               if (r == null) {
+                                       buffer.append("\t\t<td 
colspan=\"2\">&nbsp;</td>\n");
+                               } else {
+                                       // append macro micro figures to the 
table
+                                       appendMacroMicroFigures(buffer, 
r.macro, r.micro);
+                                       if (author1.equals(CONSENSUS_AS_NAME)) {
+                                               consensusMacro += r.macro;
+                                               consensusMicro += r.micro;
+                                       } else {
+                                               annMacro += r.macro;
+                                               annMicro += r.micro;
+                                               docs++;
+                                       }
+                               }
+                       }
+                       // adding averages to the last 2 columns
+                       if (author1.equals(CONSENSUS_AS_NAME)) {
+                               double caMacroAvg = (double) (consensusMacro / 
(double) (columnAuthorNames
+                                               .size() - 1));
+                               double caMicroAvg = (double) (consensusMicro / 
(double) (columnAuthorNames
+                                               .size() - 1));
+                               appendMacroMicroFigures(buffer, caMacroAvg, 
caMicroAvg);
+                       } else {
+                               double aaMacroAvg = (double) (annMacro / 
(double) (docs));
+                               double aaMicroAvg = (double) (annMicro / 
(double) (docs));
+                               annotatorMacro += aaMacroAvg;
+                               annotatorMicro += aaMicroAvg;
+                               appendMacroMicroFigures(buffer, aaMacroAvg, 
aaMicroAvg);
+                       }
+                       buffer.append("\t</tr>\n");
+                       buffer.append("\t<tr>\n");
+                       buffer.append("\t\t<td>&nbsp;</td>\n");
+                       for (String author2 : columnAuthorNames) {
+                               Result r = resultsForAuthor1.get(author2);
+                               if (r == null) {
+                                       buffer.append("\t\t<td 
colspan=\"2\">&nbsp;</td>\n");
+                               } else {
+                                       buffer.append("\t\t<td colspan=\"2\"><a 
target=\"_blank\" href=\""
+                                                       + r.documentFileName + 
"\">document</a></td>\n");
+                               }
+                       }
+                       buffer.append("\t\t<td colspan=\"2\">&nbsp;</td>\n");
+               }
+               buffer.append("</table>\n");
+               buffer.append("<hr>");
+               if (consensusExists) {
+                       buffer.append("<br><b>Avg. "
+                                       + CONSENSUS_AS_NAME
+                                       + " macro avg:</b> "
+                                       + (f.format((double) consensusMacro
+                                                       / 
(columnAuthorNames.size() - 1))));
+                       buffer.append("<br><b>Avg. "
+                                       + CONSENSUS_AS_NAME
+                                       + " micro avg:</b> "
+                                       + (f.format((double) consensusMicro
+                                                       / 
(columnAuthorNames.size() - 1))));
+               }
+               // if consensus annotation set exists, make sure the number 
used in
+               // demoninator does not include consensus as one annotator
+               int totalAuthors = consensusExists ? columnAuthorNames.size() - 
1
+                               : columnAuthorNames.size();
+               buffer.append("<br><b>Avg. IAA macro avg:</b> "
+                               + (f.format((double) annotatorMacro / 
totalAuthors)));
+               buffer.append("<br><b>Avg. IAA micro avg:</b> "
+                               + (f.format((double) annotatorMicro / 
totalAuthors)));
+               buffer.append("</body>\n</html>");
+               BufferedWriter bw = null;
+               try {
+                       File indexFile = new File(outputFolderUrl.getFile(), 
"index.html");
+                       bw = new BufferedWriter(new FileWriter(indexFile));
+                       bw.write(buffer.toString());
+               } catch (IOException ioe) {
+                       throw new ExecutionException(ioe);
+               } finally {
+                       if (bw != null) {
+                               try {
+                                       bw.close();
+                               } catch (IOException e) {
+                                       throw new ExecutionException(e);
+                               }
+                       }
+               }
+       }
 
-    // micro average
-    double micro = 0.0D;
+       /**
+        * A method that adds two columns to the buffer - one for the macro 
figure
+        * and the other one for the micro figure. It also adds relevant style 
tag
+        * to give a proper color to each cell depending on the value of macro 
and
+        * micro figures. See documentation of the getStyleTag(double) for more
+        * information on how cell backgrounds are color coded.
+        * 
+        * @param buffer
+        * @param macro
+        * @param micro
+        */
+       private void appendMacroMicroFigures(StringBuffer buffer, double macro,
+                       double micro) {
+               String macCol = getStyleTag(macro);
+               String micCol = getStyleTag(micro);
+               buffer.append("\t\t<td " + macCol + " >" + f.format(macro) + 
"</td>\n");
+               buffer.append("\t\t<td " + micCol + " >" + f.format(micro) + 
"</td>\n");
+       }
 
-    // name of the file to link to
-    String documentFileName;
-  }
+       /**
+        * Gets the style tag based on the score. The color green is used for a 
cell
+        * background to indicate full agreement (i.e. 1.0). The background 
color
+        * becomes lighter as the agreement reduces towards 0.5. At 0.5 
agreement,
+        * the background color of a cell is fully white. From 0.5 downwards, 
the
+        * color red is used and as the agreement reduces further, the color 
becomes
+        * darker with dark red at 0.0 agreement.
+        * 
+        * @param score
+        * @return
+        */
+       private String getStyleTag(double score) {
+               // two colors
+               Color gc = Color.GREEN;
+               Color rc = Color.RED;
+               Color c = null;
+               // if score is above .50, use the green color, otherwise the 
red one
+               if (score > 0.50) {
+                       c = new Color(gc.getRed(), gc.getGreen(), gc.getBlue(),
+                                       ((int) (score * 100) * 2) - 100);
+               } else {
+                       c = new Color(rc.getRed(), rc.getGreen(), rc.getBlue(),
+                                       100 - ((int) (score * 100) * 2));
+               }
+               return "style=\"background-color: rgba(" + c.getRed() + ","
+                               + c.getGreen() + "," + c.getBlue() + ","
+                               + ((double) c.getAlpha() / 100) + ")\"";
+       }
+
+       /**
+        * Given the annotator name, the method finds out the annotation set 
which
+        * contains annotations for that annotator
+        * 
+        * @param doc
+        * @param annotatorName
+        * @return
+        */
+       private String getSetName(Document doc, String annotatorName) {
+
+               // if the annotatorName is inside the 
annotationSetNamesToAnnotators
+               // it means, this is not an anonymous mode
+               if (annotationSetNamesAsAnnotators != null
+                               && 
annotationSetNamesAsAnnotators.contains(annotatorName)) {
+                       return annotatorName;
+               }
+
+               // otherwise find out the annotator name from the document 
features
+               String inputAS = null;
+               for (Object key : doc.getFeatures().keySet()) {
+                       Object val = doc.getFeatures().get(key);
+                       if (val.equals(annotatorName)) {
+                               inputAS = key.toString().substring(12);
+                               break;
+                       }
+               }
+               return inputAS;
+       }
+
+       /**
+        * Creating a temporary annotation set
+        * 
+        * @param doc
+        * @param inputAS
+        * @param outputAS
+        */
+       private void createAnnSet(Document doc, String inputAS, String 
outputAS) {
+               // if both inputAS and outputAS are same, we just return
+               // no need to create a temporarity annotation set
+               if (inputAS.equals(outputAS))
+                       return;
+
+               AnnotationSet inAS = inputAS == null || inputAS.trim().length() 
== 0 ? doc
+                               .getAnnotations() : doc.getAnnotations(inputAS);
+               inAS = inAS.get(new HashSet<String>(annotationTypes));
+               AnnotationSet outAS = doc.getAnnotations(outputAS);
+               for (Annotation a : inAS) {
+                       outAS.add(a.getStartNode(), a.getEndNode(), a.getType(),
+                                       a.getFeatures());
+               }
+       }
+
+       /**
+        * A method that calculates IAA between the given annotation sets
+        * 
+        * @param corpus
+        * @param keyAS
+        * @param responseAS
+        * @param filePrefix
+        * @throws ExecutionException
+        */
+       private void calculateIAA(Corpus corpus, String keyAS, String 
responseAS,
+                       String filePrefix) throws ExecutionException {
+               try {
+                       assurancePR.reInit();
+               } catch (ResourceInstantiationException rie) {
+                       throw new ExecutionException(rie);
+               }
+               // lets set the params on qualityAssurancePR
+               assurancePR.setAnnotationTypes(annotationTypes);
+               assurancePR
+                               .setFeatureNames(featureNames == null ? new 
ArrayList<String>()
+                                               : featureNames);
+               assurancePR.setMeasure(measure);
+               assurancePR.setOutputFolderUrl(outputFolderUrl);
+               // the remaining two params will be set later
+               assurancePR.setKeyASName(keyAS);
+               assurancePR.setResponseASName(responseAS);
+               controller.setCorpus(corpus);
+               controller.execute();
+               // QA PR produces two stats file, one for corpus and one for
+               // documents
+               // for QAForTeamware, we don't need corpus one
+               File corpusFile = new File(outputFolderUrl.getFile(),
+                               "corpus-stats.html");
+               corpusFile.delete();
+               File documentFile = new File(outputFolderUrl.getFile(),
+                               "document-stats.html");
+               File documentOutFile = new File(outputFolderUrl.getFile(), 
filePrefix
+                               + "-document-stats.html");
+               documentFile.renameTo(documentOutFile);
+       }
+
+       /**
+        * Method called when a PR is unloaded.
+        */
+       public void cleanup() {
+               super.cleanup();
+               Factory.deleteResource(assurancePR);
+               Factory.deleteResource(controller);
+       }
+
+       /**
+        * Annotation types for which the stats should be calculated
+        * 
+        * @return
+        */
+       public List<String> getAnnotationTypes() {
+               return annotationTypes;
+       }
+
+       /**
+        * Annotation types for which the stats should be calculated
+        * 
+        * @param annotationTypes
+        */
+       @RunTime
+       @CreoleParameter
+       public void setAnnotationTypes(List<String> annotationTypes) {
+               this.annotationTypes = annotationTypes;
+       }
+
+       /**
+        * Features names for which the stats should be calculated
+        * 
+        * @return
+        */
+       public List<String> getFeatureNames() {
+               return featureNames;
+       }
+
+       /**
+        * Features names for which the stats should be calculated
+        * 
+        * @param featureNames
+        */
+       @RunTime
+       @Optional
+       @CreoleParameter
+       public void setFeatureNames(List<String> featureNames) {
+               this.featureNames = featureNames;
+       }
+
+       /**
+        * Measure to use for stats calculation
+        * 
+        * @return
+        */
+       public Measure getMeasure() {
+               return measure;
+       }
+
+       /**
+        * Measure to use for stats calculation
+        * 
+        * @param measure
+        */
+       @RunTime
+       @CreoleParameter
+       public void setMeasure(Measure measure) {
+               this.measure = measure;
+       }
+
+       /**
+        * URL of the folder to store output files into
+        * 
+        * @return
+        */
+       public URL getOutputFolderUrl() {
+               return outputFolderUrl;
+       }
+
+       /**
+        * URL of the folder to store output files into
+        * 
+        * @param outputFolderUrl
+        */
+       @RunTime
+       @CreoleParameter(suffixes = "html")
+       public void setOutputFolderUrl(URL outputFolderUrl) {
+               this.outputFolderUrl = outputFolderUrl;
+       }
+
+       /**
+        * annotators to ignore when computing IAA
+        * 
+        * @return
+        */
+       public List<String> getAnnotatorsToIgnore() {
+               return annotatorsToIgnore;
+       }
+
+       /**
+        * annotators to ingore when computing IAA. Please note that if there's 
at
+        * least one value provided for the annotationSetNamesAsAnnotators, this
+        * parameter will have no effect.
+        * 
+        * @param annotatorsToIgnore
+        */
+       @RunTime
+       @Optional
+       @CreoleParameter
+       public void setAnnotatorsToIgnore(List<String> annotatorsToIgnore) {
+               this.annotatorsToIgnore = annotatorsToIgnore;
+       }
+
+       public List<String> getAnnotationSetNamesAsAnnotators() {
+               return annotationSetNamesAsAnnotators;
+       }
+
+       /**
+        * If this parameter is provided, it is assumed that the anonymous mode 
is
+        * not in place and therefore the names of annotation sets should be
+        * considered as author names. Also note that if this parameter is 
provided
+        * the parameter annotatorsToIgnore is ignored entirely. In other 
words, it
+        * has no effect.
+        * 
+        * @param annotationSetNamesAsAnnotators
+        */
+       @RunTime
+       @Optional
+       @CreoleParameter
+       public void setAnnotationSetNamesAsAnnotators(
+                       List<String> annotationSetNamesAsAnnotators) {
+               this.annotationSetNamesAsAnnotators = 
annotationSetNamesAsAnnotators;
+       }
+
+       /**
+        * Storing individual results for each pair of annotators
+        * 
+        * @author niraj
+        */
+       class Result {
+               // macro average
+               double macro = 0.0D;
+
+               // micro average
+               double micro = 0.0D;
+
+               // name of the file to link to
+               String documentFileName;
+       }
 }

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.


------------------------------------------------------------------------------
Symantec Endpoint Protection 12 positioned as A LEADER in The Forrester  
Wave(TM): Endpoint Security, Q1 2013 and "remains a good choice" in the  
endpoint security space. For insight on selecting the right partner to 
tackle endpoint security challenges, access the full report. 
http://p.sf.net/sfu/symantec-dev2dev
_______________________________________________
GATE-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/gate-cvs

Reply via email to