From 187082ef2b757707338a4b1766898b83445002cc Mon Sep 17 00:00:00 2001 From: sumanth Date: Sun, 21 Nov 2021 23:20:04 -0600 Subject: [PATCH 1/2] Replace Nd4J with Renjin for computing PCA. --- pom.xml | 49 +++--------- .../metnet/metaomgraph/ComputePCA.java | 67 +++++++--------- .../metnet/metaomgraph/utils/RenjinUtils.java | 77 +++++++++++++++++++ 3 files changed, 115 insertions(+), 78 deletions(-) create mode 100644 src/edu/iastate/metnet/metaomgraph/utils/RenjinUtils.java diff --git a/pom.xml b/pom.xml index bd77ab66..cce5785b 100644 --- a/pom.xml +++ b/pom.xml @@ -65,6 +65,11 @@ jitpack.io https://jitpack.io + + bedatadriven + bedatadriven public repo + https://nexus.bedatadriven.com/content/groups/public/ + @@ -185,45 +190,6 @@ flatlaf-intellij-themes 0.42 - - org.nd4j - nd4j-native - 1.0.0-beta7 - - - org.bytedeco - mkl-platform - - - org.nd4j - jackson - - - com.github.oshi - oshi-core - - - net.ericaro - neoitertools - - - commons-net - commons-net - - - org.nd4j - protobuf - - - com.google.flatbuffers - flatbuffers-java - - - com.jakewharton.byteunits - byteunits - - - com.github.lejon.T-SNE-Java tsne @@ -234,6 +200,11 @@ hierarchical-clustering 1.2.0 + + org.renjin + renjin-script-engine + RELEASE + \ No newline at end of file diff --git a/src/edu/iastate/metnet/metaomgraph/ComputePCA.java b/src/edu/iastate/metnet/metaomgraph/ComputePCA.java index d5e978c0..d6058aa6 100644 --- a/src/edu/iastate/metnet/metaomgraph/ComputePCA.java +++ b/src/edu/iastate/metnet/metaomgraph/ComputePCA.java @@ -3,65 +3,54 @@ */ package edu.iastate.metnet.metaomgraph; -import org.nd4j.linalg.api.ndarray.INDArray; -import org.nd4j.linalg.dimensionalityreduction.PCA; -import org.nd4j.linalg.factory.Nd4j; +import org.renjin.primitives.matrix.Matrix; +import org.renjin.script.*; +import org.renjin.sexp.Vector; + +import edu.iastate.metnet.metaomgraph.utils.RenjinUtils; + +import javax.script.*; /** * @author sumanth * * Class to compute the PCA - * uses the library nd4j to compute the PCA + * uses the R packages to compute the PCA */ public class ComputePCA { - private INDArray dataArray; + private double[][] data; /** * Constructor * @param data 2d array with m rows(selected samples) and n columns(selected feature/gene list) */ public ComputePCA(double[][] data) { - dataArray = Nd4j.createFromArray(data); + this.data = data; } /** - * Calculates pca reduced value of a matrix, for a given variance. A larger variance (99%) - * will result in a higher order feature set. - * The returned matrix is a projection of A onto principal components - * - * If PCA is computed directly, the library is somehow modifying the original data, hence - * compute the pca factors first and multiply the factors with the data to get the - * reduced dimensions. - * - * @param variance the amount of variance to preserve as a float 0 - 1 - * @param normalize whether to normalize (set features to have zero mean) - * @return the matrix representing a reduced feature set - */ - public double[][] projectData(double variance, boolean normalize){ - INDArray tempArr = dataArray.dup(); - INDArray pcaFactors = PCA.pca_factor(dataArray, variance, normalize); - INDArray reducedDimensions = tempArr.mmul(pcaFactors); - double[][] plotData = reducedDimensions.toDoubleMatrix(); - return plotData; - } - - /** - * Calculates pca vectors of a matrix, for a flags number of reduced features - * returns the reduced feature set - * The return is a projection of A onto principal nDims components - * - * If PCA is computed directly, the library is somehow modifying the original data, hence - * compute the pca factors first and multiply the factors with the data to get the - * reduced dimensions. - * + * Calculates pca vectors of the given matrix by reducing it into the number of dimensions. * @param numOfDims the number of components on which to project the features * @param normalize whether to normalize (set features to have zero mean) * @return the reduced parameters of the data */ public double[][] projectData(int numOfDims, boolean normalize){ - INDArray tempArr = dataArray.dup(); - INDArray pcaFactors = PCA.pca_factor(dataArray, numOfDims, normalize); - INDArray reducedDimensions = tempArr.mmul(pcaFactors); - double[][] plotData = reducedDimensions.toDoubleMatrix(); + ScriptEngine engine = RenjinUtils.getScriptEngine(); + + String dataRMatrix = RenjinUtils.fillRMatrixFrom2DArray("dataRMatrix", data, engine); + String center = "TRUE"; + if(!normalize) { + center = "FALSE"; + } + Vector pcaRVector = null; + try { + engine.eval("pca <- prcomp(" + dataRMatrix + ", scale. = TRUE, center = " + center + ")"); + pcaRVector = (Vector)engine.eval("pca$x"); + } catch (ScriptException e) { + e.printStackTrace(); + } + + double[][] plotData = RenjinUtils.get2DArrayFromRenjinVector(pcaRVector, data.length, numOfDims); + return plotData; } } diff --git a/src/edu/iastate/metnet/metaomgraph/utils/RenjinUtils.java b/src/edu/iastate/metnet/metaomgraph/utils/RenjinUtils.java new file mode 100644 index 00000000..e80907a8 --- /dev/null +++ b/src/edu/iastate/metnet/metaomgraph/utils/RenjinUtils.java @@ -0,0 +1,77 @@ +/** + * + */ +package edu.iastate.metnet.metaomgraph.utils; + +import javax.script.ScriptEngine; +import javax.script.ScriptException; + +import org.renjin.primitives.matrix.Matrix; +import org.renjin.script.RenjinScriptEngineFactory; +import org.renjin.sexp.Vector; + +/** + * @author sumanth + * This class contains all the utilities related to Renjin (https://www.renjin.org/) + */ +public class RenjinUtils { + + /** + * Initiate and return the script engine for further usage. + * @return ScriptEngine + */ + public static ScriptEngine getScriptEngine() { + // create a script engine manager: + RenjinScriptEngineFactory factory = new RenjinScriptEngineFactory(); + // create a Renjin engine: + ScriptEngine engine = factory.getScriptEngine(); + + return engine; + } + + /** + * Fill the R's matrix using 2d array. + * this method uses and returns the same matrixVariableName passed to it + * @param matrixVariableName name of the matrix variable + * @param data 2D array data + * @param engine renjins scriptengine + * @return matrixVariableName the same variable name passed to the method + */ + public static String fillRMatrixFrom2DArray(final String matrixVariableName, + final double[][] data, final ScriptEngine engine) { + engine.put(matrixVariableName, data[0]); + try { + engine.eval(matrixVariableName + " <- matrix(" + matrixVariableName + ", nr=1)"); + for(int i = 1; i < data.length; i++) { + engine.put("temp", data[i]); + engine.eval(matrixVariableName + " <- rbind(" + matrixVariableName + ", matrix(temp, nr=1))"); + } + } catch (ScriptException e) { + e.printStackTrace(); + } + + return matrixVariableName; + } + + /** + * Return the data in Vector form to 2D array. + * + * Note: This method is exception prone, call this carefully only if you know that the vector is of matrix type, + * and by giving the proper number of rows and columns you require in the output data. + * + * @param vector the vector datatype returned by r's script + * @param numOfRows num of rows in the return data type, should be less than or equal to the number of rows in vector + * @param numOfCols num of columns in the return data type, should be less than or equal to the number of columns in vector + * @return data 2D array + */ + public static double[][] get2DArrayFromRenjinVector(Vector vector, int numOfRows, int numOfCols){ + double[][] data = new double[numOfRows][numOfCols]; + Matrix rMatrix = new Matrix(vector); + for(int i = 0; i < numOfRows; i++) { + for(int j = 0; j < numOfCols; j++) { + data[i][j] = rMatrix.getElementAsDouble(i, j); + } + } + return data; + } +} From 511d89b58513b5988ccf7b9a4dc1b8e8146c2738 Mon Sep 17 00:00:00 2001 From: sumanth Date: Sun, 21 Nov 2021 23:27:37 -0600 Subject: [PATCH 2/2] Update ThirdPartyLibrary page --- src/edu/iastate/metnet/metaomgraph/ui/ThirdPartyLibs.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/edu/iastate/metnet/metaomgraph/ui/ThirdPartyLibs.java b/src/edu/iastate/metnet/metaomgraph/ui/ThirdPartyLibs.java index c8b93ebf..a224bd35 100644 --- a/src/edu/iastate/metnet/metaomgraph/ui/ThirdPartyLibs.java +++ b/src/edu/iastate/metnet/metaomgraph/ui/ThirdPartyLibs.java @@ -76,10 +76,10 @@ public ThirdPartyLibs() { addThirdPartyLibrary(name, websiteUrl, licenseUrl); rangePanel.add(new JSeparator(SwingConstants.HORIZONTAL)); - // nd4j - name = "nd4j"; - websiteUrl = "https://github.com/deeplearning4j/nd4j"; - licenseUrl = "https://github.com/deeplearning4j/nd4j/blob/master/LICENSE"; + // Renjin + name = "Renjin"; + websiteUrl = "https://www.renjin.org/"; + licenseUrl = "https://github.com/bedatadriven/renjin/blob/master/LICENSE.txt"; addThirdPartyLibrary(name, websiteUrl, licenseUrl); rangePanel.add(new JSeparator(SwingConstants.HORIZONTAL));