/*
* AntigenicPlotter.java
*
* Copyright (c) 2002-2015 Alexei Drummond, Andrew Rambaut and Marc Suchard
*
* This file is part of BEAST.
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership and licensing.
*
* BEAST is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* BEAST is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with BEAST; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
*/
package dr.app.tools;
import dr.app.beast.BeastVersion;
import dr.app.util.Arguments;
import dr.evolution.io.Importer;
import dr.evolution.io.NexusImporter;
import dr.evolution.tree.NodeRef;
import dr.evolution.tree.Tree;
import dr.geo.KMLCoordinates;
import dr.geo.KernelDensityEstimator2D;
import dr.geo.contouring.*;
import dr.inference.trace.*;
import dr.math.Procrustes;
import dr.util.Version;
import org.apache.commons.math.linear.*;
import org.apache.commons.math.stat.StatUtils;
import org.apache.commons.math.stat.correlation.Covariance;
import org.jdom.Element;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;
import javax.transaction.xa.Xid;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.io.*;
import java.util.*;
/*
* @author Marc Suchard and Andrew Rambaut
*/
public class AntigenicPlotter {
private final static Version version = new BeastVersion();
public final static ContourMode CONTOUR_MODE = ContourMode.SNYDER;
public final static double HPD_VALUE = 0.95;
public static final int GRIDSIZE = 200;
public AntigenicPlotter(int burnin,
boolean tabFormat,
boolean discreteModel,
final String inputFileName,
final String treeFileName,
final String outputFileName
) throws IOException {
double[][] reference = null;
List<String> tipLabels = null;
if (treeFileName != null) {
System.out.println("Reading tree file...");
NexusImporter importer = new NexusImporter(new FileReader(treeFileName));
try {
Tree tree = importer.importNextTree();
reference = new double[tree.getExternalNodeCount()][2];
tipLabels = new ArrayList<String>();
for (int i = 0; i < tree.getExternalNodeCount(); i++) {
NodeRef tip = tree.getExternalNode(i);
tipLabels.add(tree.getNodeTaxon(tip).getId());
reference[i][0] = (Double)tree.getNodeAttribute(tip, "antigenic1");
reference[i][1] = (Double)tree.getNodeAttribute(tip, "antigenic2");
}
} catch (Importer.ImportException e) {
e.printStackTrace();
return;
}
}
System.out.println("Reading log file...");
FileReader fileReader = new FileReader(inputFileName);
try {
File file = new File(inputFileName);
LogFileTraces traces = new LogFileTraces(inputFileName, file);
traces.loadTraces();
if (burnin == -1) {
burnin = (int) (traces.getMaxState() / 10);
}
traces.setBurnIn(burnin);
System.out.println();
System.out.println("burnIn <= " + burnin);
System.out.println("maxState = " + traces.getMaxState());
System.out.println();
int traceCount = traces.getTraceCount();
if (discreteModel) {
// for the discrete model, there are 4 sets of traces, pairs coordinates, cluster allocations, and cluster sizes
traceCount /= 4;
} else {
// for continuous, just pairs of coordinates
traceCount /= 2;
}
int stateCount = traces.getStateCount();
double[][][] data;
String[] labels = new String[traceCount];
if (tipLabels != null) {
data = new double[stateCount][tipLabels.size()][2];
} else {
data = new double[stateCount][traceCount][2];
}
for (int i = 0; i < traceCount; i++) {
String name = traces.getTraceName(i * 2);
name = name.substring(0, name.length() - 1);
if (tipLabels != null) {
int index = tipLabels.indexOf(name);
if (index != -1) {
for (int j = 0; j < stateCount; j++) {
data[j][index][0] = traces.getStateValue(i * 2, j);
data[j][index][1] = traces.getStateValue((i * 2) + 1, j);
}
}
} else {
for (int j = 0; j < stateCount; j++) {
data[j][i][0] = traces.getStateValue(i * 2, j);
data[j][i][1] = traces.getStateValue((i * 2) + 1, j);
}
labels[i] = name;
}
}
int[][] clusterIndices = null;
int[][] clusterSizes = null;
if (discreteModel) {
clusterIndices = new int[stateCount][traceCount];
clusterSizes = new int[stateCount][traceCount];
for (int i = 0; i < traceCount; i++) {
for (int j = 0; j < stateCount; j++) {
clusterIndices[j][i] = (int)traces.getStateValue((traceCount * 2) + i, j);
clusterSizes[j][i] = (int)traces.getStateValue((traceCount * 3) + i, j);
}
}
Map<BitSet, Integer> clusterMap = new HashMap<BitSet, Integer>();
for (int i = 0; i < stateCount; i++) {
BitSet[] clusters = new BitSet[clusterIndices[i].length];
for (int j = 0; j < clusterIndices[i].length; j++) {
BitSet bits = clusters[clusterIndices[i][j]];
if (bits == null) {
bits = new BitSet();
clusters[clusterIndices[i][j]] = bits;
}
bits.set(j);
Integer count = clusterMap.get(bits);
if (count == null) {
count = 0;
}
clusterMap.put(bits, count+1);
}
Arrays.sort(clusters, new Comparator<BitSet>() {
public int compare(BitSet bitSet1, BitSet bitSet2) {
if (bitSet1 == null) {
return -1;
}
if (bitSet2 == null) {
return 1;
}
return bitSet2.cardinality() - bitSet1.cardinality();
}
});
}
for (BitSet bits : clusterMap.keySet()) {
int count = clusterMap.get(bits);
if (count > 1) {
System.out.print(count);
for (int i = bits.nextSetBit(0); i >= 0; i = bits.nextSetBit(i+1)) {
System.out.print("\t" + labels[i]);
}
System.out.println();
}
}
}
if (tipLabels != null) {
labels = new String[tipLabels.size()];
tipLabels.toArray(labels);
}
if (reference != null) {
procrustinate(data, reference);
} else {
procrustinate(data);
}
if (tabFormat) {
writeTabformat(outputFileName, labels, data);
} else {
if (discreteModel) {
writeKML(outputFileName, labels, data, clusterIndices, clusterSizes);
} else {
writeKML(outputFileName, labels, data);
}
}
} catch (Exception e) {
System.err.println("Error Parsing Input File: " + e.getMessage());
e.printStackTrace(System.err);
return;
}
fileReader.close();
}
private void procrustinate(final double[][][] data) {
RealMatrix Xstar = new Array2DRowRealMatrix(data[data.length - 1]);
for (int i = 0; i < data.length - 1; i++) {
RealMatrix X = new Array2DRowRealMatrix(data[i]);
RealMatrix Xnew = Procrustes.procrustinate(X, Xstar, true, true);
data[i] = Xnew.getData();
}
}
private void procrustinate(final double[][][] data, final double[][] reference) {
RealMatrix Xstar = new Array2DRowRealMatrix(reference);
for (int i = 0; i < data.length; i++) {
RealMatrix X = new Array2DRowRealMatrix(data[i]);
RealMatrix Xnew = Procrustes.procrustinate(X, Xstar, true, true);
data[i] = Xnew.getData();
}
}
private void writeTabformat(String fileName, String[] labels, double[][][] data) {
int[] traceOrder = sortTraces(labels);
try {
PrintWriter writer = new PrintWriter(new FileWriter(fileName));
writer.print("state");
for (int j = 0; j < data[0].length; j++) {
writer.print("\t"+labels[traceOrder[j]] + "_1");
writer.print("\t"+labels[traceOrder[j]] + "_2");
}
writer.println();
for (int i = 0; i < data.length; i++) {
writer.print(i);
for (int j = 0; j < data[i].length; j++) {
writer.print("\t" + data[i][traceOrder[j]][0]+"\t"+data[i][traceOrder[j]][1]);
}
writer.println();
}
writer.close();
} catch (IOException e) {
System.err.println("Error opening file: " + fileName);
System.exit(-1);
}
}
private void writeKML(String fileName, String[] labels, double[][][] data) {
int[] traceOrder = sortTraces(labels);
// Element hpdSchema = new Element("Schema");
// hpdSchema.setAttribute("id", "HPD_Schema");
// hpdSchema.addContent(new Element("SimpleField")
// .setAttribute("name", "Label")
// .setAttribute("type", "string")
// .addContent(new Element("displayName").addContent("Label")));
// hpdSchema.addContent(new Element("SimpleField")
// .setAttribute("name", "Point")
// .setAttribute("type", "double")
// .addContent(new Element("displayName").addContent("Point")));
// hpdSchema.addContent(new Element("SimpleField")
// .setAttribute("name", "Year")
// .setAttribute("type", "double")
// .addContent(new Element("displayName").addContent("Year")));
// hpdSchema.addContent(new Element("SimpleField")
// .setAttribute("name", "HPD")
// .setAttribute("type", "double")
// .addContent(new Element("displayName").addContent("HPD")));
Element traceSchema = new Element("Schema");
traceSchema.setAttribute("id", "Trace_Schema");
traceSchema.addContent(new Element("SimpleField")
.setAttribute("name", "Label")
.setAttribute("type", "string")
.addContent(new Element("displayName").addContent("Label")));
traceSchema.addContent(new Element("SimpleField")
.setAttribute("name", "Trace")
.setAttribute("type", "double")
.addContent(new Element("displayName").addContent("Trace")));
traceSchema.addContent(new Element("SimpleField")
.setAttribute("name", "Year")
.setAttribute("type", "double")
.addContent(new Element("displayName").addContent("Year")));
traceSchema.addContent(new Element("SimpleField")
.setAttribute("name", "State")
.setAttribute("type", "double")
.addContent(new Element("displayName").addContent("State")));
Element centroidSchema = new Element("Schema");
centroidSchema.setAttribute("id", "Centroid_Schema");
centroidSchema.addContent(new Element("SimpleField")
.setAttribute("name", "Label")
.setAttribute("type", "string")
.addContent(new Element("displayName").addContent("Label")));
centroidSchema.addContent(new Element("SimpleField")
.setAttribute("name", "Year")
.setAttribute("type", "double")
.addContent(new Element("displayName").addContent("Year")));
centroidSchema.addContent(new Element("SimpleField")
.setAttribute("name", "Trace")
.setAttribute("type", "double")
.addContent(new Element("displayName").addContent("Trace")));
// final Element contourFolderElement = new Element("Folder");
// Element contourFolderNameElement = new Element("name");
// contourFolderNameElement.addContent("HPDs");
// contourFolderElement.addContent(contourFolderNameElement);
final Element traceFolderElement = new Element("Folder");
Element traceFolderNameElement = new Element("name");
traceFolderNameElement.addContent("traces");
traceFolderElement.addContent(traceFolderNameElement);
final Element centroidFolderElement = new Element("Folder");
Element centroidFolderNameElement = new Element("name");
centroidFolderNameElement.addContent("centroids");
centroidFolderElement.addContent(centroidFolderNameElement);
Element documentNameElement = new Element("name");
String documentName = fileName;
if (documentName.endsWith(".kml"))
documentName = documentName.replace(".kml", "");
documentNameElement.addContent(documentName);
final Element documentElement = new Element("Document");
documentElement.addContent(documentNameElement);
documentElement.addContent(traceSchema);
documentElement.addContent(centroidSchema);
// documentElement.addContent(hpdSchema);
documentElement.addContent(centroidFolderElement);
documentElement.addContent(traceFolderElement);
// documentElement.addContent(contourFolderElement);
final Element rootElement = new Element("kml");
rootElement.addContent(documentElement);
Element traceElement = generateTraceElement(labels, data, traceOrder);
traceFolderElement.addContent(traceElement);
Element centroidElement = generateCentroidElement(labels, data, traceOrder);
centroidFolderElement.addContent(centroidElement);
// Element contourElement = generateKDEElement(0.95, labels, data, traceOrder);
// contourFolderElement.addContent(contourElement);
PrintStream resultsStream;
try {
resultsStream = new PrintStream(new File(fileName));
XMLOutputter xmlOutputter = new XMLOutputter(Format.getPrettyFormat().setTextMode(Format.TextMode.PRESERVE));
xmlOutputter.output(rootElement, resultsStream);
} catch (IOException e) {
System.err.println("Error opening file: " + fileName);
System.exit(-1);
}
}
/**
* Discrete KML
* @param fileName
* @param labels
* @param data
* @param clusterIndices
* @param clusterSizes
*/
private void writeKML(String fileName, String[] labels, double[][][] data, int[][] clusterIndices, int[][] clusterSizes) {
int[] traceOrder = sortTraces(labels);
Element traceSchema = new Element("Schema");
traceSchema.setAttribute("id", "Cluster_Schema");
traceSchema.addContent(new Element("SimpleField")
.setAttribute("name", "Label")
.setAttribute("type", "string")
.addContent(new Element("displayName").addContent("Label")));
traceSchema.addContent(new Element("SimpleField")
.setAttribute("name", "Number")
.setAttribute("type", "double")
.addContent(new Element("displayName").addContent("Number")));
traceSchema.addContent(new Element("SimpleField")
.setAttribute("name", "Year")
.setAttribute("type", "double")
.addContent(new Element("displayName").addContent("Year")));
traceSchema.addContent(new Element("SimpleField")
.setAttribute("name", "State")
.setAttribute("type", "double")
.addContent(new Element("displayName").addContent("State")));
Element virusSchema = new Element("Schema");
virusSchema.setAttribute("id", "Virus_Schema");
virusSchema.addContent(new Element("SimpleField")
.setAttribute("name", "Label")
.setAttribute("type", "string")
.addContent(new Element("displayName").addContent("Label")));
virusSchema.addContent(new Element("SimpleField")
.setAttribute("name", "Year")
.setAttribute("type", "double")
.addContent(new Element("displayName").addContent("Year")));
virusSchema.addContent(new Element("SimpleField")
.setAttribute("name", "Trace")
.setAttribute("type", "double")
.addContent(new Element("displayName").addContent("Trace")));
// final Element contourFolderElement = new Element("Folder");
// Element contourFolderNameElement = new Element("name");
// contourFolderNameElement.addContent("HPDs");
// contourFolderElement.addContent(contourFolderNameElement);
final Element traceFolderElement = new Element("Folder");
Element traceFolderNameElement = new Element("name");
traceFolderNameElement.addContent("traces");
traceFolderElement.addContent(traceFolderNameElement);
final Element clustersFolderElement = new Element("Folder");
Element clustersFolderNameElement = new Element("name");
clustersFolderNameElement.addContent("clusters");
clustersFolderElement.addContent(clustersFolderNameElement);
Element documentNameElement = new Element("name");
String documentName = fileName;
if (documentName.endsWith(".kml"))
documentName = documentName.replace(".kml", "");
documentNameElement.addContent(documentName);
final Element documentElement = new Element("Document");
documentElement.addContent(documentNameElement);
documentElement.addContent(traceSchema);
documentElement.addContent(virusSchema);
// documentElement.addContent(hpdSchema);
documentElement.addContent(clustersFolderElement);
documentElement.addContent(traceFolderElement);
// documentElement.addContent(contourFolderElement);
final Element rootElement = new Element("kml");
rootElement.addContent(documentElement);
Element traceElement = generateTraceElement(labels, data, traceOrder);
traceFolderElement.addContent(traceElement);
Element clustersElement = generateClusterElement(labels, data, clusterIndices, clusterSizes, traceOrder);
clustersFolderElement.addContent(clustersElement);
// Element contourElement = generateKDEElement(0.95, labels, data, traceOrder);
// contourFolderElement.addContent(contourElement);
PrintStream resultsStream;
try {
resultsStream = new PrintStream(new File(fileName));
XMLOutputter xmlOutputter = new XMLOutputter(Format.getPrettyFormat().setTextMode(Format.TextMode.PRESERVE));
xmlOutputter.output(rootElement, resultsStream);
} catch (IOException e) {
System.err.println("Error opening file: " + fileName);
System.exit(-1);
}
}
private int[] sortTraces(final String[] labels) {
Map<Label, Integer> orderMap = new HashMap<Label, Integer>();
List<Label> labelList = new ArrayList<Label>();
int i = 0;
for (String label : labels) {
Label l = new Label(label);
labelList.add(l);
orderMap.put(l, i);
i++;
}
Collections.sort(labelList);
int[] order = new int[labels.length];
i = 0;
for (Label label : labelList) {
int index = orderMap.get(label);
order[i] = index;
i++;
}
return order;
}
class Label implements Comparable<Label> {
Label(final String label) {
this.label = label;
String[] parts = label.split("[/_-]");
try {
year = Integer.parseInt(parts[parts.length - 1]);
} catch (NumberFormatException nfe) {
return;
}
if (year < 12) {
year += 2000;
} else {
year += 1900;
}
}
public int compareTo(final Label label) {
return this.year - label.year;
}
String label;
int year;
}
private Element generateKDEElement(double hpdValue, String[] labels, double[][][] points, int[] order) {
Element traceElement = new Element("Folder");
Element nameElement = new Element("name");
String name = "intervals";
nameElement.addContent(name);
traceElement.addContent(nameElement);
for (int j = 0; j < points[0].length; j++) {
double x[] = new double[points.length];
double y[] = new double[points.length];
for (int i = 0; i < points.length; i++) {
x[i] = points[i][order[j]][0];
y[i] = points[i][order[j]][1];
}
ContourMaker contourMaker;
if (CONTOUR_MODE == ContourMode.JAVA)
contourMaker = new KernelDensityEstimator2D(x, y, GRIDSIZE);
else if (CONTOUR_MODE == ContourMode.R)
contourMaker = new ContourWithR(x, y, GRIDSIZE);
else if (CONTOUR_MODE == ContourMode.SNYDER)
contourMaker = new ContourWithSynder(x, y, GRIDSIZE);
else
throw new RuntimeException("Unimplemented ContourModel!");
ContourPath[] paths = contourMaker.getContourPaths(HPD_VALUE);
int pathCounter = 1;
for (ContourPath path : paths) {
KMLCoordinates coords = new KMLCoordinates(path.getAllX(), path.getAllY());
//because KML polygons require long,lat,alt we need to switch lat and long first
coords.switchXY();
Element placemarkElement = generatePlacemarkElementWithPolygon(hpdValue, coords, -1, pathCounter);
//testing how many points are within the polygon
traceElement.addContent(placemarkElement);
pathCounter ++;
}
}
return traceElement;
}
private Element generateTraceElement(String[] labels, double[][][] points, int[] order) {
Element traceElement = new Element("Folder");
Element nameElement = new Element("name");
String name = "points";
nameElement.addContent(name);
traceElement.addContent(nameElement);
for (int i = 0; i < points.length; i++) {
for (int j = 0; j < points[i].length; j++) {
Element placemarkElement = new Element("Placemark");
placemarkElement.addContent(generateTraceData(labels[order[j]], j, i));
Element pointElement = new Element("Point");
Element coordinates = new Element("coordinates");
coordinates.addContent(points[i][order[j]][1]+","+points[i][order[j]][0]+",0");
pointElement.addContent(coordinates);
placemarkElement.addContent(pointElement);
traceElement.addContent(placemarkElement);
}
}
return traceElement;
}
private Element generateTraceData(String label, int trace, int state) {
Element data = new Element("ExtendedData");
Element schemaData = new Element("SchemaData");
schemaData.setAttribute("schemaUrl", "Trace_Schema");
schemaData.addContent(new Element("SimpleData").setAttribute("name", "Label").addContent(label));
Label l = new Label(label);
schemaData.addContent(new Element("SimpleData").setAttribute("name", "Year").addContent(Integer.toString(l.year)));
schemaData.addContent(new Element("SimpleData").setAttribute("name", "Trace").addContent(Integer.toString(trace)));
schemaData.addContent(new Element("SimpleData").setAttribute("name", "State").addContent(Integer.toString(state)));
data.addContent(schemaData);
return data;
}
private Element generateCentroidElement(String[] labels, double[][][] points, int[] order) {
Element centroidElement = new Element("Folder");
Element nameElement = new Element("name");
String name = "centroids";
nameElement.addContent(name);
centroidElement.addContent(nameElement);
double[][] centroids = new double[points[0].length][points[0][0].length];
for (int i = 0; i < points.length; i++) {
for (int j = 0; j < points[i].length; j++) {
for (int k = 0; k < points[i][j].length; k++) {
centroids[j][k] += points[i][j][k];
}
}
}
for (int j = 0; j < points[0].length; j++) {
for (int k = 0; k < points[0][j].length; k++) {
centroids[j][k] /= points.length;
}
}
for (int j = 0; j < points[0].length; j++) {
Element placemarkElement = new Element("Placemark");
placemarkElement.addContent(generateCentroidData(labels[order[j]], j));
Element pointElement = new Element("Point");
Element coordinates = new Element("coordinates");
coordinates.addContent(centroids[order[j]][1]+","+centroids[order[j]][0]+",0");
pointElement.addContent(coordinates);
placemarkElement.addContent(pointElement);
centroidElement.addContent(placemarkElement);
}
return centroidElement;
}
private Element generateCentroidData(String label, int trace) {
Element data = new Element("ExtendedData");
Element schemaData = new Element("SchemaData");
schemaData.setAttribute("schemaUrl", "Centroid_Schema");
schemaData.addContent(new Element("SimpleData").setAttribute("name", "Label").addContent(label));
Label l = new Label(label);
schemaData.addContent(new Element("SimpleData").setAttribute("name", "Year").addContent(Integer.toString(l.year)));
schemaData.addContent(new Element("SimpleData").setAttribute("name", "Trace").addContent(Integer.toString(trace)));
data.addContent(schemaData);
return data;
}
private Element generateClusterElement(String[] labels, double[][][] points, int[][] clusterIndices, int[][] clusterSizes, int[] traceOrder) {
Element element = new Element("Folder");
Element nameElement = new Element("name");
String name = "clusters";
nameElement.addContent(name);
element.addContent(nameElement);
double[][] centroids = new double[points[0].length][points[0][0].length];
for (int i = 0; i < points.length; i++) {
for (int j = 0; j < points[i].length; j++) {
for (int k = 0; k < points[i][j].length; k++) {
centroids[j][k] += points[i][j][k];
}
}
}
for (int j = 0; j < points[0].length; j++) {
for (int k = 0; k < points[0][j].length; k++) {
centroids[j][k] /= points.length;
}
}
for (int j = 0; j < points[0].length; j++) {
Element placemarkElement = new Element("Placemark");
placemarkElement.addContent(generateCentroidData(labels[traceOrder[j]], j));
Element pointElement = new Element("Point");
Element coordinates = new Element("coordinates");
coordinates.addContent(centroids[traceOrder[j]][1]+","+centroids[traceOrder[j]][0]+",0");
pointElement.addContent(coordinates);
placemarkElement.addContent(pointElement);
element.addContent(placemarkElement);
}
return element;
}
private Element generateClusterData(String label, int trace) {
Element data = new Element("ExtendedData");
Element schemaData = new Element("SchemaData");
schemaData.setAttribute("schemaUrl", "Centroid_Schema");
schemaData.addContent(new Element("SimpleData").setAttribute("name", "Label").addContent(label));
Label l = new Label(label);
schemaData.addContent(new Element("SimpleData").setAttribute("name", "Year").addContent(Integer.toString(l.year)));
schemaData.addContent(new Element("SimpleData").setAttribute("name", "Trace").addContent(Integer.toString(trace)));
data.addContent(schemaData);
return data;
}
private Element generatePlacemarkElementWithPolygon(double hpdValue, KMLCoordinates coords, int pointNumber, int pathCounter) {
Element placemarkElement = new Element("Placemark");
String name;
Element placemarkNameElement = new Element("name");
name = "kde_" + pathCounter;
placemarkNameElement.addContent(name);
placemarkElement.addContent(placemarkNameElement);
placemarkElement.addContent(generateContourData(name, pointNumber, hpdValue));
Element polygonElement = new Element("Polygon");
Element altitudeMode = new Element("altitudeMode");
altitudeMode.addContent("clampToGround");
polygonElement.addContent(altitudeMode);
Element tessellate = new Element("tessellate");
tessellate.addContent("1");
polygonElement.addContent(tessellate);
Element outerBoundaryIs = new Element("outerBoundaryIs");
Element LinearRing = new Element("LinearRing");
LinearRing.addContent(coords.toXML());
outerBoundaryIs.addContent(LinearRing);
polygonElement.addContent(outerBoundaryIs);
placemarkElement.addContent(polygonElement);
return placemarkElement;
}
private Element generateContourData(String label, int point, double hpd) {
Element data = new Element("ExtendedData");
Element schemaData = new Element("SchemaData");
schemaData.setAttribute("schemaUrl", "HPD_Schema");
schemaData.addContent(new Element("SimpleData").setAttribute("name", "Label").addContent(label));
// Label l = new Label(label);
// schemaData.addContent(new Element("SimpleData").setAttribute("name", "Year").addContent(Integer.toString(l.year)));
schemaData.addContent(new Element("SimpleData").setAttribute("name", "Point").addContent(Integer.toString(point)));
if (hpd > 0) {
schemaData.addContent(new Element("SimpleData").setAttribute("name", "HPD").addContent(Double.toString(hpd)));
}
data.addContent(schemaData);
return data;
}
public static void printTitle() {
System.out.println();
centreLine("AntigenicPlotter " + version.getVersionString() + ", " + version.getDateString(), 60);
centreLine("BEAST time vs. parameter density analysis", 60);
centreLine("by", 60);
centreLine("Andrew Rambaut and Marc A. Suchard", 60);
System.out.println();
System.out.println();
}
public static void centreLine(String line, int pageWidth) {
int n = pageWidth - line.length();
int n1 = n / 2;
for (int i = 0; i < n1; i++) {
System.out.print(" ");
}
System.out.println(line);
}
public static void printUsage(Arguments arguments) {
arguments.printUsage("antigenicplotter", "<input-file-name> [<output-file-name>]");
System.out.println();
System.out.println(" Example: antigenicplotter -burnin 100 locations.log locations.kml");
System.out.println();
}
//Main method
public static void main(String[] args) throws IOException {
String inputFileName = null;
String outputFileName = null;
String treeFileName = null;
printTitle();
Arguments arguments = new Arguments(
new Arguments.Option[]{
new Arguments.IntegerOption("burnin", "the number of states to be considered as 'burn-in' [default = 0]"),
new Arguments.Option("discrete", "generated under the discrete antigenic model [default = continuous]"),
new Arguments.Option("tab", "generate tab delimited file [default = KML]"),
new Arguments.Option("help", "option to print this message")
});
try {
arguments.parseArguments(args);
} catch (Arguments.ArgumentException ae) {
System.out.println(ae);
printUsage(arguments);
System.exit(1);
}
if (arguments.hasOption("help")) {
printUsage(arguments);
System.exit(0);
}
int burnin = -1;
if (arguments.hasOption("burnin")) {
burnin = arguments.getIntegerOption("burnin");
}
boolean tabFormat = arguments.hasOption("tab");
boolean discreteModel = arguments.hasOption("discrete");
String[] args2 = arguments.getLeftoverArguments();
if (args2.length > 3) {
System.err.println("Unknown option: " + args2[3]);
System.err.println();
printUsage(arguments);
System.exit(1);
}
if (args2.length == 2) {
inputFileName = args2[0];
outputFileName = args2[1];
} else if (args2.length == 3) {
inputFileName = args2[0];
treeFileName = args2[1];
outputFileName = args2[2];
} else {
System.err.println("Missing input or output file name");
printUsage(arguments);
System.exit(1);
}
new AntigenicPlotter(burnin,
tabFormat,
discreteModel,
inputFileName,
treeFileName,
outputFileName
);
System.exit(0);
}
}