eu.crydee.alignment.aligner.ae.MetricsOneVsOneC.java Source code

Java tutorial

Introduction

Here is the source code for eu.crydee.alignment.aligner.ae.MetricsOneVsOneC.java

Source

/*
 * Copyright 2014 Hugo m09? Mougard.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package eu.crydee.alignment.aligner.ae;

import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Lists;
import com.google.common.collect.Table;
import eu.crydee.alignment.aligner.ts.Document;
import eu.crydee.alignment.metricslab.model.Alignment;
import eu.crydee.alignment.metricslab.model.Complete;
import eu.crydee.alignment.metricslab.model.annotations.Metric;
import eu.crydee.alignment.metricslab.model.exceptions.TAFParseException;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.stream.Collectors;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.math3.stat.descriptive.SummaryStatistics;
import org.apache.commons.math3.stat.inference.TestUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.uima.UimaContext;
import org.apache.uima.analysis_engine.AnalysisEngineProcessException;
import org.apache.uima.fit.component.JCasAnnotator_ImplBase;
import org.apache.uima.fit.descriptor.ConfigurationParameter;
import org.apache.uima.fit.util.JCasUtil;
import org.apache.uima.jcas.JCas;
import org.apache.uima.resource.ResourceInitializationException;

/**
 *
 * @author Hugo m09? Mougard
 */
public class MetricsOneVsOneC extends JCasAnnotator_ImplBase {

    private static final Logger logger = LogManager.getLogger(MetricsOneVsOneC.class);

    public static final String PARAM_TAF_FOLDER_1 = "TAF_FOLDER_1";
    @ConfigurationParameter(name = PARAM_TAF_FOLDER_1, mandatory = true)
    private String tafFolder1;

    public static final String PARAM_TAF_FOLDER_2 = "TAF_FOLDER_2";
    @ConfigurationParameter(name = PARAM_TAF_FOLDER_2, mandatory = true)
    private String tafFolder2;

    public static final String PARAM_LEFT_ALGO_NAME = "LEFT_ALGO_NAME";
    @ConfigurationParameter(name = PARAM_LEFT_ALGO_NAME, mandatory = true)
    private String leftAlgoName;

    public static final String PARAM_RIGHT_ALGO_NAME = "RIGHT_ALGO_NAME";
    @ConfigurationParameter(name = PARAM_RIGHT_ALGO_NAME, mandatory = true)
    private String rightAlgoName;

    public static final String PARAM_HTML_OUTPUT_FILEPATH = "HTML_OUTPUT_FILEPATH";
    @ConfigurationParameter(name = PARAM_HTML_OUTPUT_FILEPATH, mandatory = true)
    private String htmlFilepath;

    public static final String PARAM_METRICS_TO_SUMMARIZE = "METRICS_TO_SUMMARIZE";
    @ConfigurationParameter(name = PARAM_METRICS_TO_SUMMARIZE, mandatory = true)
    String[] keysArray;

    private Table<String, String, Pair<Double, Double>> results;
    private Map<String, Pair<Method, String>> methodsMetadata;
    private List<String> keys;

    @Override
    public void initialize(UimaContext context) throws ResourceInitializationException {
        super.initialize(context);
        results = HashBasedTable.create();
        keys = Lists.newArrayList(keysArray);
        methodsMetadata = Arrays.stream(Complete.class.getMethods())
                .map(m -> Pair.of(m, m.getAnnotation(Metric.class)))
                .filter(p -> p.getRight() != null && keys.contains(p.getRight().key()))
                .collect(Collectors.toMap(p -> p.getRight().key(), p -> Pair.of(p.getLeft(), p.getRight().name())));
    }

    @Override
    public void process(JCas jcas) throws AnalysisEngineProcessException {
        String name = JCasUtil.selectSingle(jcas, Document.class).getName();
        try {
            Alignment alignment1 = Alignment.fromTAF(
                    FileUtils.readFileToString(new File(tafFolder1, name + ".taf"), StandardCharsets.UTF_8)),
                    alignment2 = Alignment.fromTAF(FileUtils.readFileToString(new File(tafFolder2, name + ".taf"),
                            StandardCharsets.UTF_8));
            for (String k : keys) {
                double r1 = (double) methodsMetadata.get(k).getLeft().invoke(alignment1.complete),
                        r2 = (double) methodsMetadata.get(k).getLeft().invoke(alignment2.complete);
                results.put(name, k, Pair.of(r1, r2));
            }
        } catch (TAFParseException ex) {
            logger.error("Couldn't parse the TAF when trying to compute graph " + "metrics.");
            throw new AnalysisEngineProcessException(ex);
        } catch (IOException ex) {
            logger.error("Couldn't read the TAF when trying to compute graph " + "metrics.");
            throw new AnalysisEngineProcessException(ex);
        } catch (IllegalArgumentException | IllegalAccessException | InvocationTargetException ex) {
            logger.error("Couldn't compute one of the metrics.");
            throw new AnalysisEngineProcessException(ex);
        }
    }

    @Override
    public void collectionProcessComplete() throws AnalysisEngineProcessException {
        try {
            String template = IOUtils.toString(getClass()
                    .getResourceAsStream("/eu/crydee/alignment/aligner/ae/" + "metrics-one-vs-one-template.html"));
            template = template.replace("@@TITLE@@",
                    "Metrics comparator" + LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME));
            template = template.replace("@@LEFTALGO@@", leftAlgoName);
            template = template.replace("@@RIGHTALGO@@", rightAlgoName);
            StringBuilder sb = new StringBuilder();
            sb.append("<table class=\"table table-condensed\">\n").append("            <thead>\n")
                    .append("                <tr>\n").append("                    <th>Document\\Metric</th>\n");
            for (String key : keys) {
                sb.append("                    <th colspan=\"2\">").append(methodsMetadata.get(key).getRight())
                        .append("</th>\n");
            }
            sb.append("                <tr>\n").append("            </thead>\n").append("            <tbody>\n")
                    .append("                <tr>\n").append("                    <td>\n")
                    .append("                        <strong>Total</strong>\n")
                    .append("                    </td>\n");
            for (String key : keys) {
                SummaryStatistics ss1 = new SummaryStatistics(), ss2 = new SummaryStatistics();
                List<Pair<Double, Double>> column = results.column(key).values().stream().peek(p -> {
                    ss1.addValue(p.getLeft());
                    ss2.addValue(p.getRight());
                }).collect(Collectors.toList());
                boolean significant = TestUtils.pairedTTest(column.stream().mapToDouble(p -> p.getLeft()).toArray(),
                        column.stream().mapToDouble(p -> p.getRight()).toArray(), 0.05);
                double mean1 = ss1.getMean(), mean2 = ss2.getMean();
                boolean above = mean1 > mean2;
                String summary1 = String.format("%.3f", mean1) + "<small class=\"text-muted\">" + ""
                        + String.format("%.3f", ss1.getStandardDeviation()) + "</small>",
                        summary2 = String.format("%.3f", mean2) + "<small class=\"text-muted\">" + ""
                                + String.format("%.3f", ss2.getStandardDeviation()) + "</small>";
                sb.append("                    <td class=\"")
                        .append(significant ? (above ? "success" : "danger") : "warning").append("\">")
                        .append(summary1).append("</td>\n");
                sb.append("                    <td class=\"")
                        .append(significant ? (!above ? "success" : "danger") : "warning").append("\">")
                        .append(summary2).append("</td>\n");
            }
            sb.append("                </tr>\n");
            SortedSet<String> rows = new TreeSet<>(results.rowKeySet());
            for (String row : rows) {
                sb.append("                <tr>\n").append("                    <td>").append(row)
                        .append("</td>\n");
                for (String key : keys) {
                    Pair<Double, Double> r = results.get(row, key);
                    sb.append("                    <td>").append(String.format("%.3f", r.getLeft()))
                            .append("</td>\n").append("                    <td>")
                            .append(String.format("%.3f", r.getRight())).append("</td>\n");

                }
                sb.append("                </tr>\n");
            }
            sb.append("            </tbody>\n").append("        </table>");
            FileUtils.write(new File(htmlFilepath), template.replace("@@TABLE@@", sb.toString()),
                    StandardCharsets.UTF_8);
        } catch (IOException ex) {
            logger.error("IO problem with the HTML output.");
            throw new AnalysisEngineProcessException(ex);
        }
    }
}