{ rules = new XMLSyntaxRule[] { AttributeRule.newDoubleRule(MCMCOperator.WEIGHT), new ElementRule(CaseToCaseTreeLikelihood.class) }; }
@Override public XMLSyntaxRule[] getSyntaxRules() { return new XMLSyntaxRule[] { AttributeRule.newDoubleRule(MCMCOperator.WEIGHT), new ElementRule(AlloppSpeciesBindings.class), new ElementRule(AlloppSpeciesNetworkModel.class) }; }
/** @author Arman D. Bilge */ public class HostSwitchOperatorParser extends AbstractXMLObjectParser { public static final String HOST_SWITCH_OPERATOR = "hostSwitchOperator"; public static final String SAMPLE_NO_HOST = "sampleNoHost"; public static final String HOST_TREE = "hostTree"; public static final String SYMBIONT_TREE = "symbiontTree"; @Override public String getParserName() { return HOST_SWITCH_OPERATOR; } @Override public Object parseXMLObject(XMLObject xo) throws XMLParseException { final double weight = xo.getDoubleAttribute(MCMCOperator.WEIGHT); final boolean usingNoHost = xo.hasAttribute(SAMPLE_NO_HOST) ? xo.getBooleanAttribute(SAMPLE_NO_HOST) : false; XMLObject cxo = xo.getChild(HOST_TREE); final Tree hostTree = (Tree) cxo.getChild(Tree.class); cxo = xo.getChild(SYMBIONT_TREE); final MutableTree symbiontTree = (MutableTree) cxo.getChild(MutableTree.class); final CophylogenyLikelihood cophylogenyLikelihood = (CophylogenyLikelihood) xo.getChild(CophylogenyLikelihood.class); return new HostSwitchOperator( hostTree, symbiontTree, cophylogenyLikelihood, usingNoHost, weight); } @Override public XMLSyntaxRule[] getSyntaxRules() { return rules; } @Override public String getParserDescription() { return "This basic operator switchs hosts on the symbiont tree while maintaining biological validity."; } @SuppressWarnings("rawtypes") @Override public Class getReturnType() { return HostSwitchOperator.class; } private final XMLSyntaxRule[] rules = { AttributeRule.newDoubleRule(MCMCOperator.WEIGHT), AttributeRule.newBooleanRule(SAMPLE_NO_HOST, true), new ElementRule(HOST_TREE, new XMLSyntaxRule[] {new ElementRule(Tree.class)}), new ElementRule(SYMBIONT_TREE, new XMLSyntaxRule[] {new ElementRule(MutableTree.class)}), new ElementRule(CophylogenyLikelihood.class) }; }
{ rules = new XMLSyntaxRule[] { AttributeRule.newBooleanRule(NON_INFORMATIVE, true), AttributeRule.newDoubleRule(DF, true), new ElementRule( SCALE_MATRIX, new XMLSyntaxRule[] {new ElementRule(MatrixParameter.class)}, true), new ElementRule( DATA, new XMLSyntaxRule[] { new ElementRule(MatrixParameter.class, 1, Integer.MAX_VALUE) }) }; }
/** Parser for MicrosatelliteModelSelectOperatorParser */ public class MicrosatelliteModelSelectOperatorParser extends AbstractXMLObjectParser { public static final String MODEL_INDICATORS = "modelIndicators"; public static final String MODEL_CHOOSE = "modelChoose"; public String getParserName() { return "msatModelSelectOperator"; } public Object parseXMLObject(XMLObject xo) throws XMLParseException { double weight = xo.getDoubleAttribute(MCMCOperator.WEIGHT); Parameter modelChoose = (Parameter) xo.getElementFirstChild(MODEL_CHOOSE); XMLObject xoInd = xo.getChild(MODEL_INDICATORS); int childNum = xoInd.getChildCount(); System.out.println("There are 12 potential models"); Parameter[] modelIndicators = new Parameter[childNum]; for (int i = 0; i < modelIndicators.length; i++) { modelIndicators[i] = (Parameter) xoInd.getChild(i); } return new MicrosatelliteModelSelectOperator(modelChoose, modelIndicators, weight); } // ************************************************************************ // AbstractXMLObjectParser implementation // ************************************************************************ public String getParserDescription() { return "This element returns a microsatellite averaging operator on a given parameter."; } public Class getReturnType() { return MCMCOperator.class; } public XMLSyntaxRule[] getSyntaxRules() { return rules; } private XMLSyntaxRule[] rules = new XMLSyntaxRule[] { AttributeRule.newDoubleRule(MCMCOperator.WEIGHT), new ElementRule(MODEL_CHOOSE, new XMLSyntaxRule[] {new ElementRule(Parameter.class)}), new ElementRule( MODEL_INDICATORS, new XMLSyntaxRule[] {new ElementRule(Parameter.class, 1, Integer.MAX_VALUE)}), }; }
/** * An independent normal distribution sampler to propose new (independent) values from a provided * normal distribution model. * * @author Marc Suchard * @author Guy Baele */ public class MultivariateNormalIndependenceSampler extends AbstractCoercableOperator { public static final String OPERATOR_NAME = "multivariateNormalIndependenceSampler"; public static final String SCALE_FACTOR = "scaleFactor"; public static final String SET_SIZE_MEAN = "setSizeMean"; private double scaleFactor; private final Parameter parameter; private final int dim; private double setSizeMean; private final SelfControlledCaseSeries sccs; public MultivariateNormalIndependenceSampler( Parameter parameter, SelfControlledCaseSeries sccs, double setSizeMean, double weight, double scaleFactor, CoercionMode mode) { super(mode); this.scaleFactor = scaleFactor; this.parameter = parameter; setWeight(weight); dim = parameter.getDimension(); setWeight(weight); this.sccs = sccs; this.setSizeMean = setSizeMean; } public String getPerformanceSuggestion() { return ""; } public String getOperatorName() { return "independentNormalDistribution(" + parameter.getVariableName() + ")"; } /** change the parameter and return the hastings ratio. */ public double doOperation() throws OperatorFailedException { double[] mean = sccs.getMode(); double[] currentValue = parameter.getParameterValues(); double[] newValue = new double[dim]; Set<Integer> updateSet = new HashSet<Integer>(); if (setSizeMean != -1.0) { final int listLength = Poisson.nextPoisson(setSizeMean); while (updateSet.size() < listLength) { int newInt = MathUtils.nextInt(parameter.getDimension()); if (!updateSet.contains(newInt)) { updateSet.add(newInt); } } } else { for (int i = 0; i < dim; ++i) { updateSet.add(i); } } double logq = 0; for (Integer i : updateSet) { newValue[i] = mean[i] + scaleFactor * MathUtils.nextGaussian(); if (UPDATE_ALL) { parameter.setParameterValueQuietly(i, newValue[i]); } else { parameter.setParameterValue(i, newValue[i]); } logq += (NormalDistribution.logPdf(currentValue[i], mean[i], scaleFactor) - NormalDistribution.logPdf(newValue[i], mean[i], scaleFactor)); } // for (Integer i : updateSet) { // parameter.setParameterValueQuietly(i, newValue[i]); // } if (UPDATE_ALL) { parameter.setParameterValueNotifyChangedAll(0, parameter.getParameterValue(0)); } return logq; } private static final boolean UPDATE_ALL = false; public static XMLObjectParser PARSER = new AbstractXMLObjectParser() { public String getParserName() { return OPERATOR_NAME; } public Object parseXMLObject(XMLObject xo) throws XMLParseException { CoercionMode mode = CoercionMode.parseMode(xo); double weight = xo.getDoubleAttribute(WEIGHT); double scaleFactor = xo.getDoubleAttribute(SCALE_FACTOR); if (scaleFactor <= 0.0) { throw new XMLParseException("scaleFactor must be greater than 0.0"); } Parameter parameter = (Parameter) xo.getChild(Parameter.class); SelfControlledCaseSeries sccs = (SelfControlledCaseSeries) xo.getChild(SelfControlledCaseSeries.class); double setSizeMean = xo.getAttribute(SET_SIZE_MEAN, -1.0); return new MultivariateNormalIndependenceSampler( parameter, sccs, setSizeMean, weight, scaleFactor, mode); } // ************************************************************************ // AbstractXMLObjectParser implementation // ************************************************************************ public XMLSyntaxRule[] getSyntaxRules() { return rules; } private final XMLSyntaxRule[] rules = { AttributeRule.newDoubleRule(SCALE_FACTOR), AttributeRule.newDoubleRule(WEIGHT), AttributeRule.newBooleanRule(AUTO_OPTIMIZE, true), AttributeRule.newDoubleRule(SET_SIZE_MEAN, true), new ElementRule(SelfControlledCaseSeries.class), new ElementRule(Parameter.class), }; public String getParserDescription() { return "This element returns an independence sampler from a provided normal distribution model."; } public Class getReturnType() { return MultivariateNormalIndependenceSampler.class; } }; public double getCoercableParameter() { return Math.log(scaleFactor); } public void setCoercableParameter(double value) { scaleFactor = Math.exp(value); } public double getRawParameter() { return scaleFactor; } }
/** * @author Marc A. Suchard * @author Philippe Lemey */ public class Polygon2D { public static final String POLYGON = "polygon"; public static final String CLOSED = "closed"; public static final String FILL_VALUE = "fillValue"; public static final String CIRCLE = "circle"; public static final String NUMBER_OF_POINTS = "numberOfPoints"; public static final String RADIUS = "radius"; public static final String CENTER = "center"; public static final String LATITUDE = "latitude"; public static final String LONGITUDE = "longitude"; public Polygon2D(double[] x, double[] y) { if (x.length != y.length) { throw new RuntimeException("Unbalanced arrays"); } if (x[0] != x[x.length - 1] && y[0] != y[y.length - 1]) { double[] newX = new double[x.length + 1]; double[] newY = new double[y.length + 1]; System.arraycopy(x, 0, newX, 0, x.length); System.arraycopy(y, 0, newY, 0, y.length); newX[x.length] = x[0]; newY[y.length] = y[0]; this.x = newX; this.y = newY; } else { this.x = x; this.y = y; } length = this.x.length - 1; } public Polygon2D(List<Point2D> points, boolean closed) { this.point2Ds = points; if (!closed) { Point2D start = points.get(0); points.add(start); } convertPointsToArrays(); length = points.size() - 1; } public Polygon2D() { length = 0; point2Ds = new ArrayList<Point2D>(); } public String getID() { return id; } public Polygon2D(Element e) { // System.err.println("parsing polygon"); List<Element> children = e.getChildren(); id = e.getAttributeValue(XMLParser.ID); parseCoordinates(e); } private void parseCoordinates(Element element) { if (element.getName().equalsIgnoreCase(KMLCoordinates.COORDINATES)) { String value = element.getTextTrim(); StringTokenizer st1 = new StringTokenizer(value, KMLCoordinates.POINT_SEPARATORS); int count = st1.countTokens(); // System.out.println(count + " tokens"); point2Ds = new ArrayList<Point2D>(count); for (int i = 0; i < count; i++) { String line = st1.nextToken(); StringTokenizer st2 = new StringTokenizer(line, KMLCoordinates.SEPARATOR); if (st2.countTokens() < 2 || st2.countTokens() > 3) throw new IllegalArgumentException( "All KML coordinates must contain (X,Y) or (X,Y,Z) values. Error in element '" + line + "'"); final double x = Double.valueOf(st2.nextToken()); final double y = Double.valueOf(st2.nextToken()); point2Ds.add(new Point2D.Double(x, y)); } convertPointsToArrays(); length = point2Ds.size() - 1; } else { for (Object child : element.getChildren()) { if (child instanceof Element) { parseCoordinates((Element) child); } } } } Shape getShape() { GeneralPath path = new GeneralPath(); List<Point2D> points = point2Ds; path.moveTo((float) points.get(0).getX(), (float) points.get(0).getY()); for (int i = 1; i < points.size(); i++) { path.lineTo((float) points.get(i).getX(), (float) points.get(i).getY()); } path.closePath(); return path; } private void convertPointsToArrays() { final int length = point2Ds.size(); if (x == null || x.length != length) { x = new double[length]; y = new double[length]; } Iterator<Point2D> it = point2Ds.iterator(); for (int i = 0; i < length; i++) { final Point2D point = it.next(); x[i] = point.getX(); y[i] = point.getY(); } } public void addPoint2D(Point2D point2D) { if (point2Ds.size() == 0) point2Ds.add(point2D); else if (point2Ds.size() == 1) { point2Ds.add(point2D); point2Ds.add(point2Ds.get(0)); } else { Point2D last = point2Ds.remove(point2Ds.size() - 1); point2Ds.add(point2D); if (!last.equals(point2D)) point2Ds.add(last); } convertPointsToArrays(); length = point2Ds.size() - 1; } public Point2D getPoint2D(int x) { if (x > length + 1) { throw new RuntimeException("Polygon only has length" + length); } else { return point2Ds.get(x); } } public boolean containsPoint2D(Point2D Point2D) { final double inX = Point2D.getX(); final double inY = Point2D.getY(); boolean contains = false; // Take a horizontal ray from (inX,inY) to the right. // If ray across the polygon edges an odd # of times, the point is inside. for (int i = 0, j = length - 1; i < length; j = i++) { if ((((y[i] <= inY) && (inY < y[j])) || ((y[j] <= inY) && (inY < y[i]))) && (inX < (x[j] - x[i]) * (inY - y[i]) / (y[j] - y[i]) + x[i])) contains = !contains; } return contains; } public boolean bordersPoint2D(Point2D Point2D) { boolean borders = false; Iterator<Point2D> it = point2Ds.iterator(); for (int i = 0; i < length; i++) { Point2D point = it.next(); if (point.equals(Point2D)) { borders = true; } } return borders; } public void setFillValue(double value) { fillValue = value; } public double getFillValue() { return fillValue; } public double getLength() { return length; } // public boolean containsPoint2D(Point2D Point2D) { // this takes 3 times as long as the above // code, why??? // // final double inX = Point2D.getX(); // final double inY = Point2D.getY(); // boolean contains = false; // // // Take a horizontal ray from (inX,inY) to the right. // // If ray across the polygon edges an odd # of times, the Point2D is inside. // // final Point2D end = point2Ds.get(length-1); // assumes closed // double xi = end.getX(); // double yi = end.getY(); // // Iterator<Point2D> listIterator = point2Ds.iterator(); // // for(int i=0; i<length; i++) { // // final double xj = xi; // final double yj = yi; // // final Point2D next = listIterator.next(); // xi = next.getX(); // yi = next.getY(); // // if ((((yi <= inY) && (inY < yj)) || // ((yj <= inY) && (inY < yi))) && // (inX < (xj - xi) * (inY - yi) / (yj - yi) + xi)) // contains = !contains; // } // return contains; // } private enum Side { left, right, top, bottom } public Polygon2D clip(Rectangle2D boundingBox) { LinkedList<Point2D> clippedPolygon = new LinkedList<Point2D>(); Point2D p; // current Point2D Point2D p2; // next Point2D // make copy of original polygon to work with LinkedList<Point2D> workPoly = new LinkedList<Point2D>(point2Ds); // loop through all for clipping edges for (Side side : Side.values()) { clippedPolygon.clear(); for (int i = 0; i < workPoly.size() - 1; i++) { p = workPoly.get(i); p2 = workPoly.get(i + 1); if (isInsideClip(p, side, boundingBox)) { if (isInsideClip(p2, side, boundingBox)) // here both point2Ds are inside the clipping window so add the second one clippedPolygon.add(p2); else // the seond Point2D is outside so add the intersection Point2D clippedPolygon.add(intersectionPoint2D(side, p, p2, boundingBox)); } else { // so first Point2D is outside the window here if (isInsideClip(p2, side, boundingBox)) { // the following Point2D is inside so add the insection Point2D and also p2 clippedPolygon.add(intersectionPoint2D(side, p, p2, boundingBox)); clippedPolygon.add(p2); } } } // make sure that first and last element are the same, we want a closed polygon if (!clippedPolygon.getFirst().equals(clippedPolygon.getLast())) clippedPolygon.add(clippedPolygon.getFirst()); // we have to keep on working with our new clipped polygon workPoly = new LinkedList<Point2D>(clippedPolygon); } return new Polygon2D(clippedPolygon, true); } public void transformByMapping(CartogramMapping mapping) { for (int i = 0; i < length + 1; i++) { point2Ds.set(i, mapping.map(point2Ds.get(i))); } convertPointsToArrays(); } public void swapXYs() { for (int i = 0; i < length + 1; i++) { point2Ds.set(i, new Point2D.Double(point2Ds.get(i).getY(), point2Ds.get(i).getX())); } convertPointsToArrays(); } public void rescale( double longMin, double longwidth, double gridXSize, double latMax, double latwidth, double gridYSize) { for (int i = 0; i < length + 1; i++) { point2Ds.set( i, new Point2D.Double( ((point2Ds.get(i).getX() - longMin) * (gridXSize / longwidth)), ((latMax - point2Ds.get(i).getY()) * (gridYSize / latwidth)))); } convertPointsToArrays(); } public void rescaleToPositiveCoordinates() { double[][] xyMinMax = getXYMinMax(); double shiftX = 0; double shiftY = 0; if (xyMinMax[0][0] < 0) { shiftX = -xyMinMax[0][0]; } if (xyMinMax[1][0] < 0) { shiftY = -xyMinMax[1][0]; } if ((shiftX < 0) || (shiftY < 0)) { for (int i = 0; i < length + 1; i++) { point2Ds.set( i, new Point2D.Double(point2Ds.get(i).getX() + shiftX, point2Ds.get(i).getY() + shiftY)); } convertPointsToArrays(); } } public double[][] getXYMinMax() { int[] indicesX = new int[x.length]; int[] indicesY = new int[y.length]; HeapSort.sort(x, indicesX); HeapSort.sort(y, indicesY); double[][] returnArray = new double[2][2]; returnArray[0][0] = x[indicesX[0]]; returnArray[0][1] = x[indicesX[indicesX.length - 1]]; returnArray[1][0] = y[indicesY[0]]; returnArray[1][1] = y[indicesY[indicesY.length - 1]]; return returnArray; } // Here is a formula for the area of a polygon with vertices {(xk,yk): k = 1,...,n}: // Area = 1/2 [(x1*y2 - x2*y1) + (x2*y3 - x3*y2) + ... + (xn*y1 - x1*yn)]. // This formula appears in an Article by Gil Strang of MIT // on p. 253 of the March 1993 issue of The American Mathematical Monthly, with the note that it // is // "known, but not well known". There is also a very brief discussion of proofs and other // references, // including an article by Bart Braden of Northern Kentucky U., a known Mathematica enthusiast. public double calculateArea() { // rescaleToPositiveCoordinates(); double area = 0; // we can implement it like this because the polygon is closed (point2D.get(0) = // point2D.get(length + 1) for (int i = 0; i < length; i++) { area += (x[i] * y[i + 1] - x[i + 1] * y[i]); } return (Math.abs(area / 2)); } public Point2D getCentroid() { // rescaleToPositiveCoordinates(); Point2D centroid = new Point2D.Double(); double area = calculateArea(); double cx = 0, cy = 0; double factor; // we can implement it like this because the polygon is closed (point2D.get(0) = // point2D.get(length + 1) for (int i = 0; i < length; i++) { factor = (x[i] * y[i + 1] - x[i + 1] * y[i]); cx += (x[i] * x[i + 1]) * factor; cy += (y[i] * y[i + 1]) * factor; } double constant = 1 / (area * 6); cx *= constant; cy *= constant; centroid.setLocation(cx, cy); System.out.println("centroid = " + cx + "," + cy); return centroid; } private static LinkedList<Point2D> getCirclePoints( double centerLat, double centerLong, int numberOfPoints, double radius) { LinkedList<Point2D> Point2Ds = new LinkedList<Point2D>(); double lat1, long1; double d_rad; double delta_pts; double radial, lat_rad, dlon_rad, lon_rad; // convert coordinates to radians lat1 = Math.toRadians(centerLat); long1 = Math.toRadians(centerLong); // radius is in meters d_rad = radius / 6378137; // loop through the array and write points for (int i = 0; i <= numberOfPoints; i++) { delta_pts = 360 / (double) numberOfPoints; radial = Math.toRadians((double) i * delta_pts); // This algorithm is limited to distances such that dlon < pi/2 lat_rad = Math.asin( Math.sin(lat1) * Math.cos(d_rad) + Math.cos(lat1) * Math.sin(d_rad) * Math.cos(radial)); dlon_rad = Math.atan2( Math.sin(radial) * Math.sin(d_rad) * Math.cos(lat1), Math.cos(d_rad) - Math.sin(lat1) * Math.sin(lat_rad)); lon_rad = ((long1 + dlon_rad + Math.PI) % (2 * Math.PI)) - Math.PI; Point2Ds.add(new Point2D.Double(Math.toDegrees(lat_rad), Math.toDegrees(lon_rad))); } return Point2Ds; } private static boolean isInsideClip(Point2D p, Side side, Rectangle2D boundingBox) { if (side == Side.top) return (p.getY() <= boundingBox.getMaxY()); else if (side == Side.bottom) return (p.getY() >= boundingBox.getMinY()); else if (side == Side.left) return (p.getX() >= boundingBox.getMinX()); else if (side == Side.right) return (p.getX() <= boundingBox.getMaxX()); else throw new RuntimeException("Error in Polygon"); } private static Point2D intersectionPoint2D( Side side, Point2D p1, Point2D p2, Rectangle2D boundingBox) { if (side == Side.top) { final double topEdge = boundingBox.getMaxY(); return new Point2D.Double( p1.getX() + (topEdge - p1.getY()) * (p2.getX() - p1.getX()) / (p2.getY() - p1.getY()), topEdge); } else if (side == Side.bottom) { final double bottomEdge = boundingBox.getMinY(); return new Point2D.Double( p1.getX() + (bottomEdge - p1.getY()) * (p2.getX() - p1.getX()) / (p2.getY() - p1.getY()), bottomEdge); } else if (side == Side.right) { final double rightEdge = boundingBox.getMaxX(); return new Point2D.Double( rightEdge, p1.getY() + (rightEdge - p1.getX()) * (p2.getY() - p1.getY()) / (p2.getX() - p1.getX())); } else if (side == Side.left) { final double leftEdge = boundingBox.getMinX(); return new Point2D.Double( leftEdge, p1.getY() + (leftEdge - p1.getX()) * (p2.getY() - p1.getY()) / (p2.getX() - p1.getX())); } return null; } public String toString() { StringBuffer sb = new StringBuffer(); sb.append(POLYGON).append("[\n"); for (Point2D pt : point2Ds) { sb.append("\t"); sb.append(pt); sb.append("\n"); } sb.append("]"); return sb.toString(); } public static void readKMLElement(Element element, List<Polygon2D> polygons) { if (element.getName().equalsIgnoreCase(POLYGON)) { Polygon2D polygon = new Polygon2D(element); polygons.add(polygon); } else { for (Object child : element.getChildren()) { if (child instanceof Element) { readKMLElement((Element) child, polygons); } } } } public static List<Polygon2D> readKMLFile(String fileName) { List<Polygon2D> polygons = new ArrayList<Polygon2D>(); try { SAXBuilder builder = new SAXBuilder(); builder.setValidation(false); builder.setIgnoringElementContentWhitespace(true); Document doc = builder.build(new File(fileName)); Element root = doc.getRootElement(); if (!root.getName().equalsIgnoreCase("KML")) throw new RuntimeException("Not a KML file"); readKMLElement(root, polygons); } catch (IOException e) { e.printStackTrace(); } catch (JDOMException e) { e.printStackTrace(); } return polygons; } // // public Element toXML() { // return new KMLCoordinates(x,y).toXML(); // } public static XMLObjectParser PARSER = new AbstractXMLObjectParser() { public String getParserName() { return POLYGON; } public Object parseXMLObject(XMLObject xo) throws XMLParseException { LinkedList<Point2D> Point2Ds = new LinkedList<Point2D>(); boolean closed; Polygon2D polygon; if (xo.getChild(Polygon2D.class) != null) { // This is a regular polygon polygon = (Polygon2D) xo.getChild(Polygon2D.class); } else { // This is an arbitrary polygon KMLCoordinates coordinates = (KMLCoordinates) xo.getChild(KMLCoordinates.class); closed = xo.getAttribute(CLOSED, false); if ((!closed && coordinates.length < 3) || (closed && coordinates.length < 4)) throw new XMLParseException( "Insufficient point2Ds in polygon '" + xo.getId() + "' to define a polygon in 2D"); for (int i = 0; i < coordinates.length; i++) Point2Ds.add(new Point2D.Double(coordinates.x[i], coordinates.y[i])); polygon = new Polygon2D(Point2Ds, closed); } polygon.setFillValue(xo.getAttribute(FILL_VALUE, 0.0)); return polygon; } // ************************************************************************ // AbstractXMLObjectParser implementation // ************************************************************************ public String getParserDescription() { return "This element represents a polygon."; } public Class getReturnType() { return Polygon2D.class; } public XMLSyntaxRule[] getSyntaxRules() { return rules; } private XMLSyntaxRule[] rules = new XMLSyntaxRule[] { new XORRule(new ElementRule(KMLCoordinates.class), new ElementRule(Polygon2D.class)), AttributeRule.newBooleanRule(CLOSED, true), AttributeRule.newDoubleRule(FILL_VALUE, true), }; }; public static XMLObjectParser CIRCLE_PARSER = new AbstractXMLObjectParser() { public String getParserName() { return CIRCLE; } public Object parseXMLObject(XMLObject xo) throws XMLParseException { double latitude = xo.getDoubleAttribute(LATITUDE); double longitude = xo.getDoubleAttribute(LONGITUDE); double radius = xo.getDoubleAttribute(RADIUS); int num = xo.getAttribute(NUMBER_OF_POINTS, 50); // default = 50 LinkedList<Point2D> Point2Ds = getCirclePoints(latitude, longitude, num, radius); return new Polygon2D(Point2Ds, true); } // ************************************************************************ // AbstractXMLObjectParser implementation // ************************************************************************ public String getParserDescription() { return "This element represents a regular circle polygon."; } public Class getReturnType() { return Polygon2D.class; } public XMLSyntaxRule[] getSyntaxRules() { return rules; } private XMLSyntaxRule[] rules = new XMLSyntaxRule[] { AttributeRule.newDoubleRule(LATITUDE), AttributeRule.newDoubleRule(LONGITUDE), AttributeRule.newDoubleRule(RADIUS), AttributeRule.newIntegerRule(NUMBER_OF_POINTS, true), }; }; public static void main(String[] args) { Polygon2D polygon = new Polygon2D(); polygon.addPoint2D(new Point2D.Double(-10, -10)); polygon.addPoint2D(new Point2D.Double(-10, 50)); polygon.addPoint2D(new Point2D.Double(10, 50)); polygon.addPoint2D(new Point2D.Double(10, -10)); System.out.println(polygon); System.out.println(""); Point2D pt = new Point2D.Double(0, 0); System.out.println("polygon contains " + pt + ": " + polygon.containsPoint2D(pt)); pt = new Point2D.Double(100, 100); System.out.println("polygon contains " + pt + ": " + polygon.containsPoint2D(pt)); System.out.println(""); Rectangle2D boundingBox = new Rectangle2D.Double(0, 0, 100, 100); // defines lower-left corner and width/height System.out.println(boundingBox); Polygon2D myClip = polygon.clip(boundingBox); System.out.println(myClip); } protected List<Point2D> point2Ds; protected int length; private double fillValue; private String id; protected double[] x; protected double[] y; }
/** @author Wai Lok Sibon Li */ public class ContinuousBranchRatesParser extends AbstractXMLObjectParser { public static final String CONTINUOUS_BRANCH_RATES = "continuousBranchRates"; public static final String DISTRIBUTION = "distribution"; // public static final String RATE_CATEGORIES = "rateCategories"; public static final String RATE_CATEGORY_QUANTILES = "rateCategoryQuantiles"; public static final String SINGLE_ROOT_RATE = "singleRootRate"; // public static final String OVERSAMPLING = "overSampling"; public static final String NORMALIZE = "normalize"; public static final String NORMALIZE_BRANCH_RATE_TO = "normalizeBranchRateTo"; // public static final String NORMALIZED_MEAN = "normalizedMean"; public String getParserName() { return CONTINUOUS_BRANCH_RATES; } public Object parseXMLObject(XMLObject xo) throws XMLParseException { // final int overSampling = xo.getAttribute(OVERSAMPLING, 1); final boolean normalize = xo.getAttribute(NORMALIZE, false); final double normalizeBranchRateTo = xo.getAttribute(NORMALIZE_BRANCH_RATE_TO, Double.NaN); TreeModel tree = (TreeModel) xo.getChild(TreeModel.class); ParametricDistributionModel distributionModel = (ParametricDistributionModel) xo.getElementFirstChild(DISTRIBUTION); // Parameter rateCategoryParameter = (Parameter) xo.getElementFirstChild(RATE_CATEGORIES); Parameter rateCategoryQuantilesParameter = (Parameter) xo.getElementFirstChild(RATE_CATEGORY_QUANTILES); Logger.getLogger("dr.evomodel").info("Using continuous relaxed clock model."); // Logger.getLogger("dr.evomodel").info(" over sampling = " + overSampling); Logger.getLogger("dr.evomodel") .info(" parametric model = " + distributionModel.getModelName()); // Logger.getLogger("dr.evomodel").info(" rate categories = " + // rateCategoryParameter.getDimension()); Logger.getLogger("dr.evomodel") .info(" rate categories = " + rateCategoryQuantilesParameter.getDimension()); if (normalize) { Logger.getLogger("dr.evomodel") .info(" mean rate is normalized to " + normalizeBranchRateTo); } if (xo.hasAttribute(SINGLE_ROOT_RATE)) { // singleRootRate = xo.getBooleanAttribute(SINGLE_ROOT_RATE); Logger.getLogger("dr.evomodel").warning(" WARNING: single root rate is not implemented!"); } /* if (xo.hasAttribute(NORMALIZED_MEAN)) { dbr.setNormalizedMean(xo.getDoubleAttribute(NORMALIZED_MEAN)); }*/ return new ContinuousBranchRates( tree, /*rateCategoryParameter, */ rateCategoryQuantilesParameter, distributionModel, /*overSampling,*/ normalize, normalizeBranchRateTo); } // ************************************************************************ // AbstractXMLObjectParser implementation // ************************************************************************ public String getParserDescription() { return "This element returns a continuous relaxed clock model." + "The branch rates are drawn from a continuous parametric distribution."; } public Class getReturnType() { return ContinuousBranchRates.class; } public XMLSyntaxRule[] getSyntaxRules() { return rules; } private XMLSyntaxRule[] rules = new XMLSyntaxRule[] { AttributeRule.newBooleanRule( SINGLE_ROOT_RATE, true, "Whether only a single rate should be used for the two children branches of the root"), // AttributeRule.newDoubleRule(NORMALIZED_MEAN, true, "The mean rate to constrain branch // rates to once branch lengths are taken into account"), // AttributeRule.newIntegerRule(OVERSAMPLING, true, "The integer factor for oversampling the // distribution model (1 means no oversampling)"), AttributeRule.newBooleanRule( NORMALIZE, true, "Whether the mean rate has to be normalized to a particular value"), AttributeRule.newDoubleRule( NORMALIZE_BRANCH_RATE_TO, true, "The mean rate to normalize to, if normalizing"), new ElementRule(TreeModel.class), new ElementRule( DISTRIBUTION, ParametricDistributionModel.class, "The distribution model for rates among branches", false), /*new ElementRule(RATE_CATEGORIES, Parameter.class, "The rate categories parameter", false), */ new ElementRule(RATE_CATEGORY_QUANTILES, Parameter.class, "The quantiles for", false), }; }
/** @author Marc Suchard */ public class MultivariateDistributionLikelihood extends AbstractDistributionLikelihood { public static final String MVN_PRIOR = "multivariateNormalPrior"; public static final String MVN_MEAN = "meanParameter"; public static final String MVN_PRECISION = "precisionParameter"; public static final String MVN_CV = "coefficientOfVariation"; public static final String WISHART_PRIOR = "multivariateWishartPrior"; public static final String INV_WISHART_PRIOR = "multivariateInverseWishartPrior"; public static final String DIRICHLET_PRIOR = "dirichletPrior"; public static final String DF = "df"; public static final String SCALE_MATRIX = "scaleMatrix"; public static final String MVGAMMA_PRIOR = "multivariateGammaPrior"; public static final String MVGAMMA_SHAPE = "shapeParameter"; public static final String MVGAMMA_SCALE = "scaleParameter"; public static final String COUNTS = "countsParameter"; public static final String NON_INFORMATIVE = "nonInformative"; public static final String MULTIVARIATE_LIKELIHOOD = "multivariateDistributionLikelihood"; public static final String DATA_AS_MATRIX = "dataAsMatrix"; // public static final String TREE_TRAIT = "treeTraitNormalDistribution"; public static final String TREE_TRAIT = "treeTraitNormalDistributionLikelihood"; public static final String TREE_TRAIT_NORMAL = "treeTraitNormalDistribution"; public static final String ROOT_VALUE = "rootValue"; public static final String CONDITION = "conditionOnRoot"; public static final String DATA = "data"; private final MultivariateDistribution distribution; private final Transform[] transforms; public MultivariateDistributionLikelihood( String name, ParametricMultivariateDistributionModel model) { this(name, model, null); } public MultivariateDistributionLikelihood( String name, ParametricMultivariateDistributionModel model, Transform[] transforms) { super(model); this.distribution = model; this.transforms = transforms; } public MultivariateDistributionLikelihood(String name, MultivariateDistribution distribution) { this(name, distribution, null); } public MultivariateDistributionLikelihood( String name, MultivariateDistribution distribution, Transform[] transforms) { super(new DefaultModel(name)); this.distribution = distribution; this.transforms = transforms; } public MultivariateDistributionLikelihood(MultivariateDistribution distribution) { this(distribution, null); } public MultivariateDistributionLikelihood( MultivariateDistribution distribution, Transform[] transforms) { this(distribution.getType(), distribution, transforms); } public String toString() { return getClass().getName() + "(" + getLogLikelihood() + ")"; } public double calculateLogLikelihood() { double logL = 0.0; for (Attribute<double[]> data : dataList) { double[] x = data.getAttributeValue(); if (transforms != null) { double[] y = new double[x.length]; for (int i = 0; i < x.length; ++i) { logL += transforms[i].getLogJacobian(x[i]); y[i] = transforms[i].transform(x[i]); } logL += distribution.logPdf(y); } else { logL += distribution.logPdf(x); } } return logL; } @Override public void addData(Attribute<double[]> data) { super.addData(data); if (data instanceof Variable && getModel() instanceof DefaultModel) { ((DefaultModel) getModel()).addVariable((Variable) data); } } public MultivariateDistribution getDistribution() { return distribution; } public static Transform[] parseListOfTransforms(XMLObject xo, int maxDim) throws XMLParseException { Transform[] transforms = null; boolean anyTransforms = false; for (int i = 0; i < xo.getChildCount(); ++i) { if (xo.getChild(i) instanceof Transform.ParsedTransform) { Transform.ParsedTransform t = (Transform.ParsedTransform) xo.getChild(i); if (transforms == null) { transforms = Transform.Util.getListOfNoTransforms(maxDim); } t.end = Math.max(t.end, maxDim); if (t.start < 0 || t.end < 0 || t.start > t.end) { throw new XMLParseException("Invalid bounds for transform in " + xo.getId()); } for (int j = t.start; j < t.end; j += t.every) { transforms[j] = t.transform; anyTransforms = true; } } } if (anyTransforms) { StringBuilder sb = new StringBuilder("Using distributional transforms in " + xo.getId() + "\n"); for (int i = 0; i < transforms.length; ++i) { if (transforms[i] != Transform.NONE) { sb.append("\t") .append(transforms[i].getTransformName()) .append(" on index ") .append(i + 1) .append("\n"); } } sb.append("Please cite:\n").append(Citable.Utils.getCitationString(Transform.LOG)); Logger.getLogger("dr.utils.Transform").info(sb.toString()); } return transforms; } public static XMLObjectParser DIRICHLET_PRIOR_PARSER = new AbstractXMLObjectParser() { public String getParserName() { return DIRICHLET_PRIOR; } public Object parseXMLObject(XMLObject xo) throws XMLParseException { XMLObject cxo = xo.getChild(COUNTS); Parameter counts = (Parameter) cxo.getChild(Parameter.class); DirichletDistribution dirichlet = new DirichletDistribution(counts.getParameterValues()); MultivariateDistributionLikelihood likelihood = new MultivariateDistributionLikelihood(dirichlet); cxo = xo.getChild(DATA); for (int j = 0; j < cxo.getChildCount(); j++) { if (cxo.getChild(j) instanceof Parameter) { likelihood.addData((Parameter) cxo.getChild(j)); } else { throw new XMLParseException( "illegal element in " + xo.getName() + " element " + cxo.getName()); } } return likelihood; } public XMLSyntaxRule[] getSyntaxRules() { return rules; } private final XMLSyntaxRule[] rules = { new ElementRule(COUNTS, new XMLSyntaxRule[] {new ElementRule(Parameter.class)}), new ElementRule( DATA, new XMLSyntaxRule[] {new ElementRule(Parameter.class)}, 1, Integer.MAX_VALUE), }; public String getParserDescription() { return "Calculates the likelihood of some data under a Dirichlet distribution."; } public Class getReturnType() { return Likelihood.class; } }; public static XMLObjectParser INV_WISHART_PRIOR_PARSER = new AbstractXMLObjectParser() { public String getParserName() { return INV_WISHART_PRIOR; } public Object parseXMLObject(XMLObject xo) throws XMLParseException { int df = xo.getIntegerAttribute(DF); XMLObject cxo = xo.getChild(SCALE_MATRIX); MatrixParameter scaleMatrix = (MatrixParameter) cxo.getChild(MatrixParameter.class); InverseWishartDistribution invWishart = new InverseWishartDistribution(df, scaleMatrix.getParameterAsMatrix()); MultivariateDistributionLikelihood likelihood = new MultivariateDistributionLikelihood(invWishart); cxo = xo.getChild(DATA); for (int j = 0; j < cxo.getChildCount(); j++) { if (cxo.getChild(j) instanceof MatrixParameter) { likelihood.addData((MatrixParameter) cxo.getChild(j)); } else { throw new XMLParseException( "illegal element in " + xo.getName() + " element " + cxo.getName()); } } return likelihood; } public XMLSyntaxRule[] getSyntaxRules() { return rules; } private final XMLSyntaxRule[] rules = { AttributeRule.newDoubleRule(DF), new ElementRule( SCALE_MATRIX, new XMLSyntaxRule[] {new ElementRule(MatrixParameter.class)}), }; public String getParserDescription() { return "Calculates the likelihood of some data under an Inverse-Wishart distribution."; } public Class getReturnType() { return Likelihood.class; } }; public static XMLObjectParser WISHART_PRIOR_PARSER = new AbstractXMLObjectParser() { public String getParserName() { return WISHART_PRIOR; } public Object parseXMLObject(XMLObject xo) throws XMLParseException { MultivariateDistributionLikelihood likelihood; if (xo.hasAttribute(NON_INFORMATIVE) && xo.getBooleanAttribute(NON_INFORMATIVE)) { // Make non-informative settings XMLObject cxo = xo.getChild(DATA); int dim = ((MatrixParameter) cxo.getChild(0)).getColumnDimension(); likelihood = new MultivariateDistributionLikelihood(new WishartDistribution(dim)); } else { if (!xo.hasAttribute(DF) || !xo.hasChildNamed(SCALE_MATRIX)) { throw new XMLParseException("Must specify both a df and scaleMatrix"); } double df = xo.getDoubleAttribute(DF); XMLObject cxo = xo.getChild(SCALE_MATRIX); MatrixParameter scaleMatrix = (MatrixParameter) cxo.getChild(MatrixParameter.class); likelihood = new MultivariateDistributionLikelihood( new WishartDistribution(df, scaleMatrix.getParameterAsMatrix())); } XMLObject cxo = xo.getChild(DATA); for (int j = 0; j < cxo.getChildCount(); j++) { if (cxo.getChild(j) instanceof MatrixParameter) { likelihood.addData((MatrixParameter) cxo.getChild(j)); } else { throw new XMLParseException( "illegal element in " + xo.getName() + " element " + cxo.getName()); } } return likelihood; } public XMLSyntaxRule[] getSyntaxRules() { return rules; } private final XMLSyntaxRule[] rules; { rules = new XMLSyntaxRule[] { AttributeRule.newBooleanRule(NON_INFORMATIVE, true), AttributeRule.newDoubleRule(DF, true), new ElementRule( SCALE_MATRIX, new XMLSyntaxRule[] {new ElementRule(MatrixParameter.class)}, true), new ElementRule( DATA, new XMLSyntaxRule[] { new ElementRule(MatrixParameter.class, 1, Integer.MAX_VALUE) }) }; } public String getParserDescription() { return "Calculates the likelihood of some data under a Wishart distribution."; } public Class getReturnType() { return Likelihood.class; } }; public static XMLObjectParser MULTIVARIATE_LIKELIHOOD_PARSER = new AbstractXMLObjectParser() { public String getParserName() { return MULTIVARIATE_LIKELIHOOD; } public Object parseXMLObject(XMLObject xo) throws XMLParseException { XMLObject cxo = xo.getChild(DistributionLikelihoodParser.DISTRIBUTION); ParametricMultivariateDistributionModel distribution = (ParametricMultivariateDistributionModel) cxo.getChild(ParametricMultivariateDistributionModel.class); // Parse transforms here int maxDim = distribution.getMean().length; Transform[] transforms = parseListOfTransforms(xo, maxDim); MultivariateDistributionLikelihood likelihood = new MultivariateDistributionLikelihood(xo.getId(), distribution, transforms); boolean dataAsMatrix = xo.getAttribute(DATA_AS_MATRIX, false); cxo = xo.getChild(DATA); if (cxo != null) { for (int j = 0; j < cxo.getChildCount(); j++) { if (cxo.getChild(j) instanceof Parameter) { Parameter data = (Parameter) cxo.getChild(j); if (data instanceof MatrixParameter) { MatrixParameter matrix = (MatrixParameter) data; if (dataAsMatrix) { likelihood.addData(matrix); } else { if (matrix.getParameter(0).getDimension() != distribution.getMean().length) throw new XMLParseException( "dim(" + data.getStatisticName() + ") = " + matrix.getParameter(0).getDimension() + " is not equal to dim(" + distribution.getType() + ") = " + distribution.getMean().length + " in " + xo.getName() + "element"); for (int i = 0; i < matrix.getParameterCount(); i++) { likelihood.addData(matrix.getParameter(i)); } } } else { if (data.getDimension() != distribution.getMean().length) throw new XMLParseException( "dim(" + data.getStatisticName() + ") = " + data.getDimension() + " is not equal to dim(" + distribution.getType() + ") = " + distribution.getMean().length + " in " + xo.getName() + "element"); likelihood.addData(data); } } else { throw new XMLParseException("illegal element in " + xo.getName() + " element"); } } } return likelihood; } public XMLSyntaxRule[] getSyntaxRules() { return rules; } private final XMLSyntaxRule[] rules = { new ElementRule( DistributionLikelihoodParser.DISTRIBUTION, new XMLSyntaxRule[] {new ElementRule(ParametricMultivariateDistributionModel.class)}), AttributeRule.newBooleanRule(DATA_AS_MATRIX, true), new ElementRule(Transform.ParsedTransform.class, 0, Integer.MAX_VALUE), new ElementRule( DATA, new XMLSyntaxRule[] {new ElementRule(Parameter.class, 1, Integer.MAX_VALUE)}, true) }; public String getParserDescription() { return "Calculates the likelihood of some data under a given multivariate distribution."; } public Class getReturnType() { return MultivariateDistributionLikelihood.class; } }; public static XMLObjectParser MVN_PRIOR_PARSER = new AbstractXMLObjectParser() { public String getParserName() { return MVN_PRIOR; } public Object parseXMLObject(XMLObject xo) throws XMLParseException { XMLObject cxo = xo.getChild(MVN_MEAN); Parameter mean = (Parameter) cxo.getChild(Parameter.class); cxo = xo.getChild(MVN_PRECISION); MatrixParameter precision = (MatrixParameter) cxo.getChild(MatrixParameter.class); if (mean.getDimension() != precision.getRowDimension() || mean.getDimension() != precision.getColumnDimension()) throw new XMLParseException( "Mean and precision have wrong dimensions in " + xo.getName() + " element"); Transform[] transforms = parseListOfTransforms(xo, mean.getDimension()); MultivariateDistributionLikelihood likelihood = new MultivariateDistributionLikelihood( new MultivariateNormalDistribution( mean.getParameterValues(), precision.getParameterAsMatrix()), transforms); cxo = xo.getChild(DATA); if (cxo != null) { for (int j = 0; j < cxo.getChildCount(); j++) { if (cxo.getChild(j) instanceof Parameter) { Parameter data = (Parameter) cxo.getChild(j); if (data instanceof MatrixParameter) { MatrixParameter matrix = (MatrixParameter) data; if (matrix.getParameter(0).getDimension() != mean.getDimension()) throw new XMLParseException( "dim(" + data.getStatisticName() + ") = " + matrix.getParameter(0).getDimension() + " is not equal to dim(" + mean.getStatisticName() + ") = " + mean.getDimension() + " in " + xo.getName() + "element"); for (int i = 0; i < matrix.getParameterCount(); i++) { likelihood.addData(matrix.getParameter(i)); } } else { if (data.getDimension() != mean.getDimension()) throw new XMLParseException( "dim(" + data.getStatisticName() + ") = " + data.getDimension() + " is not equal to dim(" + mean.getStatisticName() + ") = " + mean.getDimension() + " in " + xo.getName() + "element"); likelihood.addData(data); } } else { throw new XMLParseException("illegal element in " + xo.getName() + " element"); } } } return likelihood; } public XMLSyntaxRule[] getSyntaxRules() { return rules; } private final XMLSyntaxRule[] rules = { new ElementRule(MVN_MEAN, new XMLSyntaxRule[] {new ElementRule(Parameter.class)}), new ElementRule( MVN_PRECISION, new XMLSyntaxRule[] {new ElementRule(MatrixParameter.class)}), new ElementRule(Transform.ParsedTransform.class, 0, Integer.MAX_VALUE), new ElementRule( DATA, new XMLSyntaxRule[] {new ElementRule(Parameter.class, 1, Integer.MAX_VALUE)}, true) }; public String getParserDescription() { return "Calculates the likelihood of some data under a given multivariate-normal distribution."; } public Class getReturnType() { return MultivariateDistributionLikelihood.class; } }; public static XMLObjectParser MVGAMMA_PRIOR_PARSER = new AbstractXMLObjectParser() { public String getParserName() { return MVGAMMA_PRIOR; } public Object parseXMLObject(XMLObject xo) throws XMLParseException { double[] shape; double[] scale; if (xo.hasChildNamed(MVGAMMA_SHAPE)) { XMLObject cxo = xo.getChild(MVGAMMA_SHAPE); shape = ((Parameter) cxo.getChild(Parameter.class)).getParameterValues(); cxo = xo.getChild(MVGAMMA_SCALE); scale = ((Parameter) cxo.getChild(Parameter.class)).getParameterValues(); if (shape.length != scale.length) throw new XMLParseException( "Shape and scale have wrong dimensions in " + xo.getName() + " element"); } else { XMLObject cxo = xo.getChild(MVN_MEAN); double[] mean = ((Parameter) cxo.getChild(Parameter.class)).getParameterValues(); cxo = xo.getChild(MVN_CV); double[] cv = ((Parameter) cxo.getChild(Parameter.class)).getParameterValues(); if (mean.length != cv.length) throw new XMLParseException( "Mean and CV have wrong dimensions in " + xo.getName() + " element"); final int dim = mean.length; shape = new double[dim]; scale = new double[dim]; for (int i = 0; i < dim; i++) { double c2 = cv[i] * cv[i]; shape[i] = 1.0 / c2; scale[i] = c2 * mean[i]; } } MultivariateDistributionLikelihood likelihood = new MultivariateDistributionLikelihood( new MultivariateGammaDistribution(shape, scale)); XMLObject cxo = xo.getChild(DATA); for (int j = 0; j < cxo.getChildCount(); j++) { if (cxo.getChild(j) instanceof Parameter) { Parameter data = (Parameter) cxo.getChild(j); likelihood.addData(data); if (data.getDimension() != shape.length) throw new XMLParseException( "dim(" + data.getStatisticName() + ") != " + shape.length + " in " + xo.getName() + "element"); } else { throw new XMLParseException("illegal element in " + xo.getName() + " element"); } } return likelihood; } public XMLSyntaxRule[] getSyntaxRules() { return rules; } private final XMLSyntaxRule[] rules = { new XORRule( new ElementRule( MVGAMMA_SHAPE, new XMLSyntaxRule[] {new ElementRule(Parameter.class)}), new ElementRule(MVN_MEAN, new XMLSyntaxRule[] {new ElementRule(Parameter.class)})), new XORRule( new ElementRule( MVGAMMA_SCALE, new XMLSyntaxRule[] {new ElementRule(Parameter.class)}), new ElementRule(MVN_CV, new XMLSyntaxRule[] {new ElementRule(Parameter.class)})), new ElementRule( DATA, new XMLSyntaxRule[] {new ElementRule(Parameter.class, 1, Integer.MAX_VALUE)}) }; public String getParserDescription() { return "Calculates the likelihood of some data under a given multivariate-gamma distribution."; } public Class getReturnType() { return MultivariateDistributionLikelihood.class; } }; public static XMLObjectParser TREE_TRAIT_MODEL = new AbstractXMLObjectParser() { public String getParserName() { return TREE_TRAIT_NORMAL; } public Object parseXMLObject(XMLObject xo) throws XMLParseException { boolean conditionOnRoot = xo.getAttribute(CONDITION, false); FullyConjugateMultivariateTraitLikelihood traitModel = (FullyConjugateMultivariateTraitLikelihood) xo.getChild(FullyConjugateMultivariateTraitLikelihood.class); TreeTraitNormalDistributionModel treeTraitModel; if (xo.getChild(ROOT_VALUE) != null) { XMLObject cxo = xo.getChild(ROOT_VALUE); Parameter rootValue = (Parameter) cxo.getChild(Parameter.class); treeTraitModel = new TreeTraitNormalDistributionModel(traitModel, rootValue, conditionOnRoot); } else { treeTraitModel = new TreeTraitNormalDistributionModel(traitModel, conditionOnRoot); } return treeTraitModel; } public XMLSyntaxRule[] getSyntaxRules() { return rules; } private final XMLSyntaxRule[] rules = { AttributeRule.newBooleanRule(CONDITION, true), new ElementRule(FullyConjugateMultivariateTraitLikelihood.class) }; public String getParserDescription() { return "Parses TreeTraitNormalDistributionModel"; } public Class getReturnType() { return TreeTraitNormalDistributionModel.class; } }; public static XMLObjectParser TREE_TRAIT_DISTRIBUTION = new AbstractXMLObjectParser() { public String getParserName() { return TREE_TRAIT; } public Object parseXMLObject(XMLObject xo) throws XMLParseException { /* boolean conditionOnRoot = xo.getAttribute(CONDITION, false); FullyConjugateMultivariateTraitLikelihood traitModel = (FullyConjugateMultivariateTraitLikelihood) xo.getChild(FullyConjugateMultivariateTraitLikelihood.class); */ TreeTraitNormalDistributionModel treeTraitModel = (TreeTraitNormalDistributionModel) xo.getChild(TreeTraitNormalDistributionModel.class); MultivariateDistributionLikelihood likelihood = new MultivariateDistributionLikelihood( // new TreeTraitNormalDistributionModel(traitModel, conditionOnRoot) treeTraitModel); XMLObject cxo = xo.getChild(DATA); for (int j = 0; j < cxo.getChildCount(); j++) { if (cxo.getChild(j) instanceof Parameter) { likelihood.addData((Parameter) cxo.getChild(j)); } else { throw new XMLParseException( "illegal element in " + xo.getName() + " element " + cxo.getName()); } } return likelihood; } public XMLSyntaxRule[] getSyntaxRules() { return rules; } private final XMLSyntaxRule[] rules = { // AttributeRule.newBooleanRule(CONDITION, true), // new ElementRule(FullyConjugateMultivariateTraitLikelihood.class), new ElementRule(TreeTraitNormalDistributionModel.class), new ElementRule( DATA, new XMLSyntaxRule[] {new ElementRule(Parameter.class, 1, Integer.MAX_VALUE)}) }; public String getParserDescription() { return "Calculates the likelihood of some data under a given multivariate-gamma distribution."; } public Class getReturnType() { return MultivariateDistributionLikelihood.class; } }; }
/** * A Gibbs operator for allocation of items to clusters under a distance dependent Chinese * restaurant process. * * @author Gabriela Cybis * @author Marc Suchard */ public class DistanceDependentCRPGibbsOperator extends SimpleMCMCOperator implements GibbsOperator { public static final String DDCRP_GIBBS_OPERATOR = "distanceDependentCRPGibbsOperator"; private final Parameter chiParameter; private final double[][] depMatrix; public NPAntigenicLikelihood modelLikelihood; private Parameter links = null; private Parameter assignments = null; // double[][] x; double k0; double v0; double[] m; double[][] T0Inv; double logDetT0; public DistanceDependentCRPGibbsOperator( Parameter links, Parameter assignments, Parameter chiParameter, NPAntigenicLikelihood Likelihood, double weight) { this.links = links; this.assignments = assignments; this.modelLikelihood = Likelihood; this.chiParameter = chiParameter; this.depMatrix = Likelihood.getLogDepMatrix(); for (int i = 0; i < links.getDimension(); i++) { links.setParameterValue(i, i); } setWeight(weight); // double[][] x=modelLikelihood.getData(); // modelLikelihood.printInformtion(x[0][0]); this.m = new double[2]; m[0] = modelLikelihood.priorMean.getParameterValue(0); m[1] = modelLikelihood.priorMean.getParameterValue(1); this.v0 = 2; this.k0 = modelLikelihood.priorPrec.getParameterValue(0) / modelLikelihood.clusterPrec.getParameterValue(0); this.T0Inv = new double[2][2]; T0Inv[0][0] = v0 / modelLikelihood.clusterPrec.getParameterValue(0); T0Inv[1][1] = v0 / modelLikelihood.clusterPrec.getParameterValue(0); T0Inv[1][0] = 0.0; T0Inv[0][1] = 0.0; this.logDetT0 = -Math.log(T0Inv[0][0] * T0Inv[1][1]); } /** @return the parameter this operator acts on. */ public Parameter getParameter() { return (Parameter) links; } /** * @return the Variable this operator acts on. * <p>public Variable getVariable() { return clusteringParameter; } */ /** change the parameter and return the hastings ratio. */ public final double doOperation() { int index = MathUtils.nextInt(links.getDimension()); int oldGroup = (int) assignments.getParameterValue(index); /* * Set index customer link to index and all connected to it to a new assignment (min value empty) */ int minEmp = minEmpty(modelLikelihood.getLogLikelihoodsVector()); links.setParameterValue(index, index); int[] visited = connected(index, links); int ii = 0; while (visited[ii] != 0) { assignments.setParameterValue(visited[ii] - 1, minEmp); ii++; } /* * Adjust likvector for group separated */ modelLikelihood.setLogLikelihoodsVector(oldGroup, getLogLikGroup(oldGroup)); modelLikelihood.setLogLikelihoodsVector(minEmp, getLogLikGroup(minEmp)); int maxFull = maxFull(modelLikelihood.getLogLikelihoodsVector()); double[] liks = modelLikelihood.getLogLikelihoodsVector(); /* * computing likelihoods of joint groups */ double[] crossedLiks = new double[maxFull + 1]; for (int ll = 0; ll < maxFull + 1; ll++) { if (ll != minEmp) { crossedLiks[ll] = getLogLik2Group(ll, minEmp); } } /* * Add logPrior */ double[] logP = new double[links.getDimension()]; for (int jj = 0; jj < links.getDimension(); jj++) { logP[jj] += depMatrix[index][jj]; int n = (int) assignments.getParameterValue(jj); if (n != minEmp) { logP[jj] += crossedLiks[n] - liks[n] - liks[minEmp]; } } logP[index] = Math.log(chiParameter.getParameterValue(0)); /* * possibilidade de mandar p zero as probs muito pequenas */ /* * Gibbs sampling */ this.rescale(logP); // Improve numerical stability this.exp(logP); // Transform back to probability-scale int k = MathUtils.randomChoicePDF(logP); links.setParameterValue(index, k); int newGroup = (int) assignments.getParameterValue(k); ii = 0; while (visited[ii] != 0) { assignments.setParameterValue(visited[ii] - 1, newGroup); ii++; } /* * updating conditional likelihood vector */ modelLikelihood.setLogLikelihoodsVector(newGroup, getLogLikGroup(newGroup)); if (newGroup != minEmp) { modelLikelihood.setLogLikelihoodsVector(minEmp, 0); } sampleMeans(maxFull); return 0.0; } /* * find min Empty */ public int minEmpty(double[] logLikVector) { int isEmpty = 0; int i = 0; while (isEmpty == 0) { if (logLikVector[i] == 0) { isEmpty = 1; } else { if (i == logLikVector.length - 1) { isEmpty = 1; } i++; } } return i; } /* * find max Full */ public int maxFull(double[] logLikVector) { int isEmpty = 1; int i = logLikVector.length - 1; while (isEmpty == 1) { if (logLikVector[i] != 0) { isEmpty = 0; } else { i--; } } return i; } /* * find customers connected to i */ public int[] connected(int i, Parameter clusteringParameter) { int n = clusteringParameter.getDimension(); int[] visited = new int[n + 1]; visited[0] = i + 1; int tv = 1; for (int j = 0; j < n; j++) { if (visited[j] != 0) { int curr = visited[j] - 1; /*look forward */ int forward = (int) clusteringParameter.getParameterValue(curr); visited[tv] = forward + 1; tv++; // Check to see if is isn't already on the list for (int ii = 0; ii < tv - 1; ii++) { if (visited[ii] == forward + 1) { tv--; visited[tv] = 0; } } /*look back */ for (int jj = 0; jj < n; jj++) { if ((int) clusteringParameter.getParameterValue(jj) == curr) { visited[tv] = jj + 1; tv++; for (int ii = 0; ii < tv - 1; ii++) { if (visited[ii] == jj + 1) { tv--; visited[tv] = 0; } } } } } } return visited; } private void printInformtion(Parameter par) { StringBuffer sb = new StringBuffer("parameter \n"); for (int j = 0; j < par.getDimension(); j++) { sb.append(par.getParameterValue(j)); } Logger.getLogger("dr.evomodel").info(sb.toString()); }; public double getLogLikGroup(int groupNumber) { double L = 0.0; int ngroup = 0; for (int i = 0; i < assignments.getDimension(); i++) { if ((int) assignments.getParameterValue(i) == groupNumber) { ngroup++; } } if (ngroup != 0) { double[][] group = new double[ngroup][2]; double mean[] = new double[2]; int count = 0; for (int i = 0; i < assignments.getDimension(); i++) { if ((int) assignments.getParameterValue(i) == groupNumber) { group[count][0] = modelLikelihood.getData()[i][0]; group[count][1] = modelLikelihood.getData()[i][1]; mean[0] += group[count][0]; mean[1] += group[count][1]; count++; } } mean[0] /= ngroup; mean[1] /= ngroup; double kn = k0 + ngroup; double vn = v0 + ngroup; double[][] sumdif = new double[2][2]; for (int i = 0; i < ngroup; i++) { sumdif[0][0] += (group[i][0] - mean[0]) * (group[i][0] - mean[0]); sumdif[0][1] += (group[i][0] - mean[0]) * (group[i][1] - mean[1]); sumdif[1][0] += (group[i][0] - mean[0]) * (group[i][1] - mean[1]); sumdif[1][1] += (group[i][1] - mean[1]) * (group[i][1] - mean[1]); } double[][] TnInv = new double[2][2]; TnInv[0][0] = T0Inv[0][0] + ngroup * (k0 / kn) * (mean[0] - m[0]) * (mean[0] - m[0]) + sumdif[0][0]; TnInv[0][1] = T0Inv[0][1] + ngroup * (k0 / kn) * (mean[1] - m[1]) * (mean[0] - m[0]) + sumdif[0][1]; TnInv[1][0] = T0Inv[1][0] + ngroup * (k0 / kn) * (mean[0] - m[0]) * (mean[1] - m[1]) + sumdif[1][0]; TnInv[1][1] = T0Inv[1][1] + ngroup * (k0 / kn) * (mean[1] - m[1]) * (mean[1] - m[1]) + sumdif[1][1]; double logDetTn = -Math.log(TnInv[0][0] * TnInv[1][1] - TnInv[0][1] * TnInv[1][0]); L += -(ngroup) * Math.log(Math.PI); L += Math.log(k0) - Math.log(kn); L += (vn / 2) * logDetTn - (v0 / 2) * logDetT0; L += GammaFunction.lnGamma(vn / 2) + GammaFunction.lnGamma((vn / 2) - 0.5); L += -GammaFunction.lnGamma(v0 / 2) - GammaFunction.lnGamma((v0 / 2) - 0.5); } return L; } /* OLD public double getLogLikGroup(int groupNumber){ double L =0.0; int ngroup=0; for (int i=0;i<assignments.getDimension(); i++){ if((int) assignments.getParameterValue(i) == groupNumber){ ngroup++;}} if (ngroup != 0){ double[] group = new double[2*ngroup]; int count = 0; for (int i=0;i<assignments.getDimension(); i++){ if((int) assignments.getParameterValue(i) == groupNumber){ group[count] = modelLikelihood.getData()[i][0]; group[ngroup+count] = modelLikelihood.getData()[i][1]; count+=1;}} double[][] var = new double[2*ngroup][2*ngroup]; double[] mean = new double[2*ngroup]; double m0 = modelLikelihood.getPriorMean().getParameterValue(0); double m1 = modelLikelihood.getPriorMean().getParameterValue(1); double vp = modelLikelihood.getPriorPrec().getParameterValue(0); double vc = modelLikelihood.getClusterPrec().getParameterValue(0); for (int i=0; i<ngroup; i++){ mean[i]=m0; mean[ngroup+i]=m1; for (int l=0;l<ngroup;l++){ var[i][ngroup+l]=0; var[ngroup+i][l]=0; if (l==i){var[i][l]= vp+ vc; var[ngroup+i][ngroup+l]= vp+ vc;} else { var[i][l] = vp; var[ngroup+i][ngroup+l]= vp;} } } double[][] precision = new SymmetricMatrix(var).inverse().toComponents(); L = new MultivariateNormalDistribution(mean, precision).logPdf(group); } return L; } */ public double getLogLik2Group(int group1, int group2) { double L = 0.0; int ngroup1 = 0; for (int i = 0; i < assignments.getDimension(); i++) { if ((int) assignments.getParameterValue(i) == group1) { ngroup1++; } } int ngroup2 = 0; for (int i = 0; i < assignments.getDimension(); i++) { if ((int) assignments.getParameterValue(i) == group2) { ngroup2++; } } int ngroup = (ngroup1 + ngroup2); if (ngroup != 0) { double[][] group = new double[ngroup][2]; double mean[] = new double[2]; int count = 0; for (int i = 0; i < assignments.getDimension(); i++) { if ((int) assignments.getParameterValue(i) == group1) { group[count][0] = modelLikelihood.getData()[i][0]; group[count][1] = modelLikelihood.getData()[i][1]; mean[0] += group[count][0]; mean[1] += group[count][1]; count += 1; } } for (int i = 0; i < assignments.getDimension(); i++) { if ((int) assignments.getParameterValue(i) == group2) { group[count][0] = modelLikelihood.getData()[i][0]; group[count][1] = modelLikelihood.getData()[i][1]; mean[0] += group[count][0]; mean[1] += group[count][1]; count += 1; } } mean[0] /= ngroup; mean[1] /= ngroup; double kn = k0 + ngroup; double vn = v0 + ngroup; double[][] sumdif = new double[2][2]; for (int i = 0; i < ngroup; i++) { sumdif[0][0] += (group[i][0] - mean[0]) * (group[i][0] - mean[0]); sumdif[0][1] += (group[i][0] - mean[0]) * (group[i][1] - mean[1]); sumdif[1][0] += (group[i][0] - mean[0]) * (group[i][1] - mean[1]); sumdif[1][1] += (group[i][1] - mean[1]) * (group[i][1] - mean[1]); } double[][] TnInv = new double[2][2]; TnInv[0][0] = T0Inv[0][0] + ngroup * (k0 / kn) * (mean[0] - m[0]) * (mean[0] - m[0]) + sumdif[0][0]; TnInv[0][1] = T0Inv[0][1] + ngroup * (k0 / kn) * (mean[1] - m[1]) * (mean[0] - m[0]) + sumdif[0][1]; TnInv[1][0] = T0Inv[1][0] + ngroup * (k0 / kn) * (mean[0] - m[0]) * (mean[1] - m[1]) + sumdif[1][0]; TnInv[1][1] = T0Inv[1][1] + ngroup * (k0 / kn) * (mean[1] - m[1]) * (mean[1] - m[1]) + sumdif[1][1]; double logDetTn = -Math.log(TnInv[0][0] * TnInv[1][1] - TnInv[0][1] * TnInv[1][0]); L += -(ngroup) * Math.log(Math.PI); L += Math.log(k0) - Math.log(kn); L += (vn / 2) * logDetTn - (v0 / 2) * logDetT0; L += GammaFunction.lnGamma(vn / 2) + GammaFunction.lnGamma((vn / 2) - 0.5); L += -GammaFunction.lnGamma(v0 / 2) - GammaFunction.lnGamma((v0 / 2) - 0.5); } return L; } /*public double getLogLik2Group(int group1, int group2){ double L =0.0; int ngroup1=0; for (int i=0;i<assignments.getDimension(); i++){ if((int) assignments.getParameterValue(i) == group1 ){ ngroup1++;}} int ngroup2=0; for (int i=0;i<assignments.getDimension(); i++){ if((int) assignments.getParameterValue(i) == group2 ){ ngroup2++;}} int ngroup = (ngroup1+ngroup2); if (ngroup != 0){ double[] group = new double[2*ngroup]; int count = 0; for (int i=0;i<assignments.getDimension(); i++){ if((int) assignments.getParameterValue(i) == group1 ){ group[count] = modelLikelihood.getData()[i][0]; group[count+ngroup] = modelLikelihood.getData()[i][1]; count+=1;}} for (int i=0;i<assignments.getDimension(); i++){ if((int) assignments.getParameterValue(i) == group2 ){ group[count] = modelLikelihood.getData()[i][0]; group[count+ngroup] = modelLikelihood.getData()[i][1]; count+=1;}} double[][] var = new double[2*ngroup][2*ngroup]; double[] mean = new double[2*ngroup]; double m0 = modelLikelihood.getPriorMean().getParameterValue(0); double m1 = modelLikelihood.getPriorMean().getParameterValue(1); double vp = modelLikelihood.getPriorPrec().getParameterValue(0); double vc = modelLikelihood.getClusterPrec().getParameterValue(0); for (int i=0; i<ngroup; i++){ mean[i]=m0; mean[i+ngroup]=m1; for (int l=0;l<ngroup;l++){ var[i][ngroup+l]=0; var[ngroup+i][l]=0; if (l==i){var[i][l]= vp+ vc; var[ngroup+i][ngroup+l]= vp+ vc;} else { var[i][l] = vp; var[ngroup+i][ngroup+l]= vp;} } } double[][] precision = new SymmetricMatrix(var).inverse().toComponents(); L = new MultivariateNormalDistribution(mean, precision).logPdf(group); } return L; } */ public void sampleMeans(int maxFull) { double[][] means = new double[maxFull + 2][2]; // sample mean vector for each cluster for (int i = 0; i < maxFull + 1; i++) { // Find all elements in cluster int ngroup = 0; for (int ii = 0; ii < assignments.getDimension(); ii++) { if ((int) assignments.getParameterValue(ii) == i) { ngroup++; } } if (ngroup != 0) { double[][] group = new double[ngroup][2]; double[] groupMean = new double[2]; int count = 0; for (int ii = 0; ii < assignments.getDimension(); ii++) { if ((int) assignments.getParameterValue(ii) == i) { group[count][0] = modelLikelihood.getData()[ii][0]; group[count][1] = modelLikelihood.getData()[ii][1]; groupMean[0] += group[count][0]; groupMean[1] += group[count][1]; count += 1; } } groupMean[0] /= ngroup; groupMean[1] /= ngroup; double kn = k0 + ngroup; double vn = v0 + ngroup; double[][] sumdif = new double[2][2]; for (int jj = 0; jj < ngroup; jj++) { sumdif[0][0] += (group[jj][0] - groupMean[0]) * (group[jj][0] - groupMean[0]); sumdif[0][1] += (group[jj][0] - groupMean[0]) * (group[jj][1] - groupMean[1]); sumdif[1][0] += (group[jj][0] - groupMean[0]) * (group[jj][1] - groupMean[1]); sumdif[1][1] += (group[jj][1] - groupMean[1]) * (group[jj][1] - groupMean[1]); } double[][] TnInv = new double[2][2]; TnInv[0][0] = T0Inv[0][0] + ngroup * (k0 / kn) * (groupMean[0] - m[0]) * (groupMean[0] - m[0]) + sumdif[0][0]; TnInv[0][1] = T0Inv[0][1] + ngroup * (k0 / kn) * (groupMean[1] - m[1]) * (groupMean[0] - m[0]) + sumdif[0][1]; TnInv[1][0] = T0Inv[1][0] + ngroup * (k0 / kn) * (groupMean[0] - m[0]) * (groupMean[1] - m[1]) + sumdif[1][0]; TnInv[1][1] = T0Inv[1][1] + ngroup * (k0 / kn) * (groupMean[1] - m[1]) * (groupMean[1] - m[1]) + sumdif[1][1]; Matrix Tn = new SymmetricMatrix(TnInv).inverse(); double[] posteriorMean = new double[2]; // compute posterior mean posteriorMean[0] = (k0 * m[0] + ngroup * groupMean[0]) / (k0 + ngroup); posteriorMean[1] = (k0 * m[1] + ngroup * groupMean[1]) / (k0 + ngroup); // compute posterior Precision double[][] posteriorPrecision = new WishartDistribution(vn, Tn.toComponents()).nextWishart(); posteriorPrecision[0][0] *= kn; posteriorPrecision[1][0] *= kn; posteriorPrecision[0][1] *= kn; posteriorPrecision[1][1] *= kn; double[] sample = new MultivariateNormalDistribution(posteriorMean, posteriorPrecision) .nextMultivariateNormal(); means[i][0] = sample[0]; means[i][1] = sample[1]; } } // Fill in cluster means for each observation for (int j = 0; j < assignments.getDimension(); j++) { double[] group = new double[2]; group[0] = means[(int) assignments.getParameterValue(j)][0]; group[1] = means[(int) assignments.getParameterValue(j)][1]; modelLikelihood.setMeans(j, group); } } private void exp(double[] logX) { for (int i = 0; i < logX.length; ++i) { logX[i] = Math.exp(logX[i]); // if(logX[i]<1E-5){logX[i]=0;} } } private void rescale(double[] logX) { double max = this.max(logX); for (int i = 0; i < logX.length; ++i) { logX[i] -= max; } } private double max(double[] x) { double max = x[0]; for (double xi : x) { if (xi > max) { max = xi; } } return max; } // MCMCOperator INTERFACE public final String getOperatorName() { return DDCRP_GIBBS_OPERATOR; } public final void optimize(double targetProb) { throw new RuntimeException("This operator cannot be optimized!"); } public boolean isOptimizing() { return false; } public void setOptimizing(boolean opt) { throw new RuntimeException("This operator cannot be optimized!"); } public double getMinimumAcceptanceLevel() { return 0.1; } public double getMaximumAcceptanceLevel() { return 0.4; } public double getMinimumGoodAcceptanceLevel() { return 0.20; } public double getMaximumGoodAcceptanceLevel() { return 0.30; } public String getPerformanceSuggestion() { if (Utils.getAcceptanceProbability(this) < getMinimumAcceptanceLevel()) { return ""; } else if (Utils.getAcceptanceProbability(this) > getMaximumAcceptanceLevel()) { return ""; } else { return ""; } } public static XMLObjectParser PARSER = new AbstractXMLObjectParser() { public static final String CHI = "chi"; public static final String LIKELIHOOD = "likelihood"; public static final String ASSIGNMENTS = "assignments"; public static final String LINKS = "links"; public static final String DEP_MATRIX = "depMatrix"; public String getParserName() { return DDCRP_GIBBS_OPERATOR; } /* (non-Javadoc) * @see dr.xml.AbstractXMLObjectParser#parseXMLObject(dr.xml.XMLObject) */ public Object parseXMLObject(XMLObject xo) throws XMLParseException { double weight = xo.getDoubleAttribute(MCMCOperator.WEIGHT); XMLObject cxo = xo.getChild(ASSIGNMENTS); Parameter assignments = (Parameter) cxo.getChild(Parameter.class); cxo = xo.getChild(LINKS); Parameter links = (Parameter) cxo.getChild(Parameter.class); cxo = xo.getChild(CHI); Parameter chiParameter = (Parameter) cxo.getChild(Parameter.class); cxo = xo.getChild(LIKELIHOOD); NPAntigenicLikelihood likelihood = (NPAntigenicLikelihood) cxo.getChild(NPAntigenicLikelihood.class); return new DistanceDependentCRPGibbsOperator( links, assignments, chiParameter, likelihood, weight); } // ************************************************************************ // AbstractXMLObjectParser implementation // ************************************************************************ public String getParserDescription() { return "An operator that picks a new allocation of an item to a cluster under the Dirichlet process."; } public Class getReturnType() { return DistanceDependentCRPGibbsOperator.class; } public XMLSyntaxRule[] getSyntaxRules() { return rules; } private final XMLSyntaxRule[] rules = { AttributeRule.newDoubleRule(MCMCOperator.WEIGHT), new ElementRule( CHI, new XMLSyntaxRule[] { new ElementRule(Parameter.class), }), new ElementRule( LIKELIHOOD, new XMLSyntaxRule[] { new ElementRule(Likelihood.class), }, true), new ElementRule(ASSIGNMENTS, new XMLSyntaxRule[] {new ElementRule(Parameter.class)}), new ElementRule(LINKS, new XMLSyntaxRule[] {new ElementRule(Parameter.class)}), }; }; public int getStepCount() { return 1; } }
/** * @author Marc A. Suchard * @author Philippe Lemey */ public class NewPolygon2D { public static final String POLYGON = "polygon"; public static final String CLOSED = "closed"; public static final String FILL_VALUE = "fillValue"; public NewPolygon2D(GeneralPath path) { this.path = path; } public NewPolygon2D(Element e) { List<Element> children = e.getChildren(); // for (int a = 0; a < children.size(); a++) { for (Element childElement : children) { // Element childElement = (Element) children.get(a); if (childElement.getName().equals(KMLCoordinates.COORDINATES)) { String value = childElement.getTextTrim(); StringTokenizer st1 = new StringTokenizer(value, "\n"); int count = st1.countTokens(); // System.out.println(count); // point2Ds = new LinkedList<Point2D>(); this.path = new GeneralPath(); for (int i = 0; i < count; i++) { String line = st1.nextToken(); StringTokenizer st2 = new StringTokenizer(line, ","); if (st2.countTokens() != 3) throw new IllegalArgumentException( "All KML coordinates must contain (X,Y,Z) values. Three dimensions not found in element '" + line + "'"); final float x = Float.valueOf(st2.nextToken()); final float y = Float.valueOf(st2.nextToken()); if (i == 0) { path.moveTo(x, y); } else { path.lineTo(x, y); } // point2Ds.add(new Point2D.Double(x, y)); } // length = point2Ds.size() - 1; break; } } } public NewPolygon2D() { path = new GeneralPath(); } public void moveTo(Point2D pt) { path.moveTo((float) pt.getX(), (float) pt.getY()); } public void lineTo(Point2D pt) { path.lineTo((float) pt.getX(), (float) pt.getY()); } public boolean contains(Point2D pt) { return path.contains(pt); } public void closePath() { path.closePath(); } public void setFillValue(double value) { fillValue = value; } public double getFillValue() { return fillValue; } public NewPolygon2D clip(Rectangle2D boundingBox) { Area thisArea = new Area(path); thisArea.intersect(new Area(boundingBox)); PathIterator iterator = thisArea.getPathIterator(null); double[] v = new double[2]; while (!iterator.isDone()) { int type = iterator.currentSegment(v); System.err.println(":" + v[0] + v[1] + "\n"); iterator.next(); } System.exit(-1); GeneralPath path = new GeneralPath(thisArea); path.closePath(); NewPolygon2D newPolygon = new NewPolygon2D(path); newPolygon.setFillValue(this.getFillValue()); return newPolygon; } public String toString() { StringBuffer sb = new StringBuffer(); sb.append("polygon("); sb.append(fillValue); sb.append(")[\n"); PathIterator iterator = path.getPathIterator(null); float[] values = new float[2]; while (!iterator.isDone()) { int type = iterator.currentSegment(values); Point2D pt = new Point2D.Double(values[0], values[1]); sb.append("\t"); sb.append(pt); sb.append("\n"); iterator.next(); } // sb.append(iterator); // for(Point2D pt : point2Ds) { // sb.append("\t"); // sb.append(pt); // sb.append("\n"); // } // sb.append(path.toString()); sb.append("]"); return sb.toString(); } public static XMLObjectParser PARSER = new AbstractXMLObjectParser() { public String getParserName() { return POLYGON; } public Object parseXMLObject(XMLObject xo) throws XMLParseException { KMLCoordinates coordinates = (KMLCoordinates) xo.getChild(KMLCoordinates.class); boolean closed = xo.getAttribute(CLOSED, false); if ((!closed && coordinates.length < 3) || (closed && coordinates.length < 4)) throw new XMLParseException( "Insufficient points in polygon '" + xo.getId() + "' to define a polygon in 2D"); NewPolygon2D polygon = new NewPolygon2D(); polygon.moveTo(new Point2D.Double(coordinates.x[0], coordinates.y[0])); int length = coordinates.length; if (closed) length--; for (int i = 1; i < length; i++) polygon.lineTo(new Point2D.Double(coordinates.x[i], coordinates.y[i])); polygon.lineTo(new Point2D.Double(coordinates.x[0], coordinates.y[0])); // polygon.closePath(); polygon.setFillValue(xo.getAttribute(FILL_VALUE, 0.0)); return polygon; } // ************************************************************************ // AbstractXMLObjectParser implementation // ************************************************************************ public String getParserDescription() { return "This element represents a polygon."; } public Class getReturnType() { return Polygon2D.class; } public XMLSyntaxRule[] getSyntaxRules() { return rules; } private XMLSyntaxRule[] rules = new XMLSyntaxRule[] { new ElementRule(KMLCoordinates.class), AttributeRule.newBooleanRule(CLOSED, true), AttributeRule.newDoubleRule(FILL_VALUE, true), }; }; public static void main(String[] args) { NewPolygon2D polygon = new NewPolygon2D(); polygon.moveTo(new Point2D.Double(-10, -10)); polygon.lineTo(new Point2D.Double(-10, 50)); polygon.lineTo(new Point2D.Double(10, 50)); polygon.lineTo(new Point2D.Double(10, -10)); polygon.lineTo(new Point2D.Double(-10, -10)); // polygon.closePath(); System.out.println(polygon); System.out.println(""); // System.exit(-1); Point2D pt = new Point2D.Double(0, 0); System.out.println("polygon contains " + pt + ": " + polygon.contains(pt)); pt = new Point2D.Double(100, 100); System.out.println("polygon contains " + pt + ": " + polygon.contains(pt)); System.out.println(""); Rectangle2D boundingBox = new Rectangle2D.Double(0, 0, 100, 100); // defines lower-left corner and width/height System.out.println(boundingBox); NewPolygon2D myClip = polygon.clip(boundingBox); System.out.println(myClip); } private double fillValue; private GeneralPath path; }