package templates; import generator.KMLGenerator; import java.awt.Color; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.io.PrintWriter; import java.text.ParseException; import java.util.ArrayList; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import jebl.evolution.graphs.Node; import jebl.evolution.io.ImportException; import jebl.evolution.io.NexusImporter; import jebl.evolution.io.TreeImporter; import jebl.evolution.trees.RootedTree; import structure.Coordinates; import structure.Layer; import structure.Line; import structure.Polygon; import structure.Style; import structure.TimeLine; import utils.ThreadLocalSpreadDate; import utils.Utils; public class ContinuousTreeToKML { public long time; // how many millisecond one day holds private static final int DayInMillis = 86400000; // how many days one year holds private static final int DaysInYear = 365; // Earths radius in km private static final double EarthRadius = 6371; private RootedTree tree; private String HPDString; private String mrsdString; private ThreadLocalSpreadDate mrsd; private int numberOfIntervals; private double timescaler; private double rootHeight; private ArrayList<Layer> layers; private TimeLine timeLine; private double maxAltMapping; private double minPolygonRedMapping; private double minPolygonGreenMapping; private double minPolygonBlueMapping; private double minPolygonOpacityMapping; private double maxPolygonRedMapping; private double maxPolygonGreenMapping; private double maxPolygonBlueMapping; private double maxPolygonOpacityMapping; private double minBranchRedMapping; private double minBranchGreenMapping; private double minBranchBlueMapping; private double minBranchOpacityMapping; private double maxBranchRedMapping; private double maxBranchGreenMapping; private double maxBranchBlueMapping; private double maxBranchOpacityMapping; private double branchWidth; private String longitudeName; private String latitudeName; private double treeHeightMax; private TreeImporter importer; private PrintWriter writer; public ContinuousTreeToKML() { }// END: ContinuousTreeToKML() public void setTimescaler(double timescaler) { this.timescaler = timescaler; } public void setHPDString(String HPDString) { this.HPDString = HPDString; } public void setLongitudeName(String name) { longitudeName = name; } public void setLatitudeName(String name) { latitudeName = name; } public void setMrsdString(String mrsd) { mrsdString = mrsd; } public void setNumberOfIntervals(int number) { numberOfIntervals = number; } public void setMaxAltitudeMapping(double max) { maxAltMapping = max; } public void setKmlWriterPath(String kmlPath) throws FileNotFoundException { writer = new PrintWriter(kmlPath); } public void setTreePath(String path) throws FileNotFoundException { importer = new NexusImporter(new FileReader(path)); } public void setMinPolygonRedMapping(double min) { minPolygonRedMapping = min; } public void setMinPolygonGreenMapping(double min) { minPolygonGreenMapping = min; } public void setMinPolygonBlueMapping(double min) { minPolygonBlueMapping = min; } public void setMinPolygonOpacityMapping(double min) { minPolygonOpacityMapping = min; } public void setMaxPolygonRedMapping(double max) { maxPolygonRedMapping = max; } public void setMaxPolygonGreenMapping(double max) { maxPolygonGreenMapping = max; } public void setMaxPolygonBlueMapping(double max) { maxPolygonBlueMapping = max; } public void setMaxPolygonOpacityMapping(double max) { maxPolygonOpacityMapping = max; } public void setMinBranchRedMapping(double min) { minBranchRedMapping = min; } public void setMinBranchGreenMapping(double min) { minBranchGreenMapping = min; } public void setMinBranchBlueMapping(double min) { minBranchBlueMapping = min; } public void setMinBranchOpacityMapping(double min) { minBranchOpacityMapping = min; } public void setMaxBranchRedMapping(double max) { maxBranchRedMapping = max; } public void setMaxBranchGreenMapping(double max) { maxBranchGreenMapping = max; } public void setMaxBranchBlueMapping(double max) { maxBranchBlueMapping = max; } public void setMaxBranchOpacityMapping(double max) { maxBranchOpacityMapping = max; } public void setBranchWidth(double width) { branchWidth = width; } public void GenerateKML() throws IOException, ImportException, ParseException { // start timing time = -System.currentTimeMillis(); // import tree tree = (RootedTree) importer.importNextTree(); // this is for time calculations rootHeight = tree.getHeight(tree.getRootNode()); // this is for mappings treeHeightMax = Utils.getTreeHeightMax(tree); // This is a general time span for the tree mrsd = new ThreadLocalSpreadDate(mrsdString); timeLine = new TimeLine(mrsd.getTime() - (rootHeight * DayInMillis * DaysInYear * timescaler), mrsd .getTime(), numberOfIntervals); // this is to generate kml output KMLGenerator kmloutput = new KMLGenerator(); layers = new ArrayList<Layer>(); // Execute threads final int NTHREDS = Runtime.getRuntime().availableProcessors(); ExecutorService executor = Executors.newFixedThreadPool(NTHREDS); executor.submit(new Branches()); executor.submit(new Polygons()); executor.shutdown(); // Wait until all threads are finished while (!executor.isTerminated()) { } kmloutput.generate(writer, timeLine, layers); // stop timing time += System.currentTimeMillis(); }// END: GenerateKML // //////////////// // ---BRANCHES---// // //////////////// private class Branches implements Runnable { public void run() { try { // this is for Branches folder: Layer branchesLayer = new Layer("Branches", null); int branchStyleId = 1; for (Node node : tree.getNodes()) { if (!tree.isRoot(node)) { Double longitude = (Double) node .getAttribute(longitudeName); Double latitude = (Double) node .getAttribute(latitudeName); Double nodeHeight = Utils.getNodeHeight(tree, node); Node parentNode = tree.getParent(node); Double parentLongitude = (Double) parentNode .getAttribute(longitudeName); Double parentLatitude = (Double) parentNode .getAttribute(latitudeName); Double parentHeight = Utils.getNodeHeight(tree, parentNode); if (longitude != null && latitude != null && parentLongitude != null && parentLatitude != null) { /** * altitude mapping * */ double maxAltitude = Utils .map(Utils .rhumbDistance(parentLongitude, parentLatitude, longitude, latitude), 0, EarthRadius, 0, maxAltMapping); /** * Color mapping * */ int red = (int) Utils.map(nodeHeight, 0, treeHeightMax, minBranchRedMapping, maxBranchRedMapping); int green = (int) Utils.map(nodeHeight, 0, treeHeightMax, minBranchGreenMapping, maxBranchGreenMapping); int blue = (int) Utils.map(nodeHeight, 0, treeHeightMax, minBranchBlueMapping, maxBranchBlueMapping); /** * opacity mapping * */ int alpha = (int) Utils.map(nodeHeight, 0, treeHeightMax, maxBranchOpacityMapping, minBranchOpacityMapping); Color col = new Color(red, green, blue, alpha); Style linesStyle = new Style(col, branchWidth); linesStyle.setId("branch_style" + branchStyleId); branchStyleId++; double startTime = mrsd.minus((int) (nodeHeight * DaysInYear * timescaler)); double endTime = mrsd.minus((int) (parentHeight * DaysInYear * timescaler)); //TODO: correlate with node names Line line = new Line( (parentLongitude + "," + parentLatitude + ":" + longitude + "," + latitude), // name new Coordinates(parentLongitude, parentLatitude), // startCoords startTime, // double startime linesStyle, // style startstyle new Coordinates(longitude, latitude), // endCoords endTime, // double endtime linesStyle, // style endstyle maxAltitude, // double maxAltitude 0.0 // double duration ); branchesLayer.addItem(line); }// END: null checks }// END: root check }// END: nodes loop layers.add(branchesLayer); } catch (RuntimeException e) { e.printStackTrace(); } }// END: run }// END: Branches class // //////////////// // ---POLYGONS---// // //////////////// private class Polygons implements Runnable { public void run() { try { String modalityAttributeName = Utils.getModalityAttributeName(longitudeName, HPDString); // this is for Polygons folder: String polygonsDescription = null; Layer polygonsLayer = new Layer("Polygons", polygonsDescription); int polygonsStyleId = 1; for (Node node : tree.getNodes()) { if (!tree.isRoot(node)) { if (!tree.isExternal(node)) { Integer modality = (Integer) node .getAttribute(modalityAttributeName); if (modality != null) { for (int i = 1; i <= modality; i++) { Object[] longitudeHPD = Utils .getObjectArrayNodeAttribute(node, longitudeName + "_" + HPDString + "_" + i); Object[] latitudeHPD = Utils .getObjectArrayNodeAttribute(node, latitudeName + "_" + HPDString + "_" + i); /** * Color mapping * */ double nodeHeight = tree.getHeight(node); int red = (int) Utils.map(nodeHeight, 0, treeHeightMax, minPolygonRedMapping, maxPolygonRedMapping); int green = (int) Utils.map(nodeHeight, 0, treeHeightMax, minPolygonGreenMapping, maxPolygonGreenMapping); int blue = (int) Utils.map(nodeHeight, 0, treeHeightMax, minPolygonBlueMapping, maxPolygonBlueMapping); /** * opacity mapping * */ int alpha = (int) Utils.map(nodeHeight, 0, treeHeightMax, maxPolygonOpacityMapping, minPolygonOpacityMapping); Color col = new Color(red, green, blue, alpha); Style polygonsStyle = new Style(col, 0); polygonsStyle.setId("polygon_style" + polygonsStyleId); int days = (int) (nodeHeight * DaysInYear * timescaler); double startTime = mrsd.minus(days); //TODO: correlate with node names polygonsLayer.addItem(new Polygon("node" + polygonsStyleId + "_" + HPDString + "_" + i, // String name Utils.parsePolygons(longitudeHPD, latitudeHPD),// List<Coordinates> polygonsStyle, // Style style startTime, // double startime 0.0 // double duration )); polygonsStyleId++; }// END: modality loop }// END: null check }// END: external node check }// END: root check }// END: nodes loop layers.add(polygonsLayer); } catch (RuntimeException e) { e.printStackTrace(); } }// END: run }// END: polygons class }// END: ContinuousTreeToKML class