/* * ContourWithR.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.geo.contouring; import org.rosuda.JRI.REXP; import org.rosuda.JRI.RVector; import org.rosuda.JRI.Rengine; /** * @author Marc Suchard */ public class ContourWithR implements ContourMaker { public ContourWithR(final double[] xValues, final double[] yValues) { this(xValues, yValues, 50); } public ContourWithR(final double[] xValues, final double[] yValues, int N) { this.xValues = xValues; this.yValues = yValues; this.N = N; } private final double[] xValues; private final double[] yValues; public ContourPath[] getContourPaths(double hpdValue) { makeContour(xValues, yValues, hpdValue, N); if (contourList == null) return null; ContourPath[] contourPaths = new ContourPath[getNumberContours()]; for(int i=0; i<getNumberContours(); i++) { double[][] cont = getContour(i); contourPaths[i] = new ContourPath(null,1,cont[0],cont[1]); } return contourPaths; } public void makeContour(double[] xValues, double[] yValues, double hpd) { makeContour(xValues, yValues, hpd, N); } public void makeContour(double[] xValues, double[] yValues, double hpd, int N) { REXP x = rEngine.eval("makeContour(" + makeRString(xValues) + "," + makeRString(yValues) + "," + hpd + "," + N + ")"); contourList = x.asVector(); } public int getNumberContours() { if (contourList != null) return contourList.size(); return 0; } public double[][] getContour(int whichContour) { if (contourList != null) { double[][] result = new double[2][]; RVector oneContour = contourList.at(whichContour).asVector(); result[0] = oneContour.at(1).asDoubleArray(); result[1] = oneContour.at(2).asDoubleArray(); return result; } return null; } private static Rengine rEngine = null; private int N; private RVector contourList = null; private static final String[] rArgs = {"--no-save", "--max-vsize=1G"}; private static final String[] rBootCommands = { "library(MASS)", "makeContour = function(var1, var2, prob=0.95, n=50, h=c(1,1)) {" + "post1 = kde2d(var1, var2, n = n, h=h); " + // This had h=h in argument "dx = diff(post1$x[1:2]); " + "dy = diff(post1$y[1:2]); " + "sz = sort(post1$z); " + "c1 = cumsum(sz) * dx * dy; " + "levels = sapply(prob, function(x) { approx(c1, sz, xout = 1 - x)$y }); " + "line = contourLines(post1$x, post1$y, post1$z, level = levels); " + "return(line) }" }; private String makeRString(double[] values) { StringBuffer sb = new StringBuffer("c("); sb.append(values[0]); for (int i = 1; i < values.length; i++) { sb.append(","); sb.append(values[i]); } sb.append(")"); return sb.toString(); } static public boolean processWithR = false; static { try { System.loadLibrary("jri"); processWithR = true; System.err.println("JRI loaded. Will process using R contouring."); // if (!Rengine.versionCheck()) { // throw new RuntimeException("JRI library version mismatch"); // } rEngine = new Rengine(rArgs, false, null); if (!rEngine.waitForR()) { throw new RuntimeException("Cannot load R"); } for (String command : rBootCommands) { rEngine.eval(command); } } catch (UnsatisfiedLinkError e) { System.err.println("JRI not available. Will process using Java contouring."); } } }