diff --git a/pom.xml b/pom.xml index 1c3463d..5dda3b5 100644 --- a/pom.xml +++ b/pom.xml @@ -1,175 +1,175 @@ 4.0.0 org.scijava pom-scijava 13.2.1 sc.fiji Colocalisation_Analysis - 2.2.4-SNAPSHOT + 3.0.0-SNAPSHOT Coloc 2 Fiji's plugin for colocalization analysis. https://imagej.net/Coloc_2 2009 Fiji http://fiji.sc/ GNU General Public License v3+ http://www.gnu.org/licenses/gpl.html repo chalkie666 Daniel James White http://imagej.net/User:White lead reviewer support maintainer tomka Tom Kazimiers http://imagej.net/User:Kazimiers lead debugger reviewer etarena Ellen Arena http://imagej.net/User:Etarena developer debugger reviewer support ctrueden Curtis Rueden http://imagej.net/User:Rueden maintainer Johannes Schindelin http://imagej.net/User:Schindelin founder dscho Jan Eglinger http://imagej.net/User:Eglinger imagejan Leonardo Guizzetti leonardicus Mark Hiner http://imagej.net/User:Hinerm hinerm Jean-Yves Tinevez http://imagej.net/User:JeanYvesTinevez tinevez ImageJ Forum http://forum.imagej.net/ scm:git:git://github.com/fiji/Colocalisation_Analysis scm:git:git@github.com:fiji/Colocalisation_Analysis HEAD https://github.com/fiji/Colocalisation_Analysis github.com https://github.com/fiji/Colocalisation_Analysis Travis CI https://travis-ci.org/fiji/Colocalisation_Analysis gpl_v3 Fiji developers. imagej.public http://maven.imagej.net/content/groups/public sc.fiji fiji-lib net.imagej ij net.imglib2 imglib2 net.imglib2 imglib2-algorithm net.imglib2 imglib2-ij com.itextpdf itextpdf junit junit test diff --git a/src/main/java/algorithms/SpearmanRankCorrelation.java b/src/main/java/algorithms/SpearmanRankCorrelation.java index eb7c795..456b557 100644 --- a/src/main/java/algorithms/SpearmanRankCorrelation.java +++ b/src/main/java/algorithms/SpearmanRankCorrelation.java @@ -1,331 +1,331 @@ /*- * #%L * Fiji's plugin for colocalization analysis. * %% * Copyright (C) 2009 - 2017 Fiji developers. * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program. If not, see * . * #L% */ package algorithms; import gadgets.DataContainer; import java.util.Arrays; import java.util.Comparator; import net.imglib2.RandomAccessibleInterval; import net.imglib2.TwinCursor; import net.imglib2.type.logic.BitType; import net.imglib2.type.numeric.RealType; import net.imglib2.view.Views; import results.ResultHandler; /* * This code has been heavily adapted from Numerical Recipces: The Art of Scientific Computing. * 3rd ed., 2007. Other formulations have been gathered from Wolfram's MathWorld: * http://mathworld.wolfram.com/SpearmanRankCorrelationCoefficient.html * * Adapted from code written by Dan White and Tom Kazimiers * * @author Leonardo Guizzetti */ /** * This algorithm calculates Spearman's rank correlation coefficient (Spearman's rho) * * @param */ public class SpearmanRankCorrelation> extends Algorithm { // the resulting Spearman rho value - static double rhoValue; - static double tStatisticSpearman; - static int dfSpearman; + double rhoValue; + double tStatisticSpearman; + int dfSpearman; // create two paired arrays: one with raw pixel values and one for the corresponding ranks - static double[][] data; - static double[] ch1raw; - static double[] ch2raw; - static double[] ch1ranks; - static double[] ch2ranks; + double[][] data; + double[] ch1raw; + double[] ch2raw; + double[] ch1ranks; + double[] ch2ranks; public SpearmanRankCorrelation() { super("Spearman's Rank Corelation calculation"); } @Override public void execute(DataContainer container) throws MissingPreconditionException { // get the 2 images for the calculation of Spearman's rho RandomAccessibleInterval img1 = container.getSourceImage1(); RandomAccessibleInterval img2 = container.getSourceImage2(); RandomAccessibleInterval mask = container.getMask(); TwinCursor cursor = new TwinCursor(img1.randomAccess(), img2.randomAccess(), Views.iterable(mask).localizingCursor()); // calculate Spearman's rho value rhoValue = calculateSpearmanRank(cursor); } /** * Calculates Spearman's Rank Correlation Coefficient (Spearman's rho) for * two images. * * @param cursor A TwinCursor that iterates over two images * @return Spearman's rank correlation coefficient (rho) value */ - public static > double calculateSpearmanRank(TwinCursor cursor) { + public > double calculateSpearmanRank(TwinCursor cursor) { // Step 0: Count the pixels first. int n = 0; while (cursor.hasNext()) { n++; cursor.fwd(); } cursor.reset(); data = new double[n][2]; for (int i = 0; i < n; i++) { cursor.fwd(); T type1 = cursor.getFirst(); T type2 = cursor.getSecond(); data[i][0] = type1.getRealDouble(); data[i][1] = type2.getRealDouble(); } return calculateSpearmanRank(data); } /** * Calculates Spearman's Rank Correlation Coefficient (Spearman's rho) for * two images. * * @param data A 2D array containing the data to be ranked * @return Spearman's rank correlation coefficient (rho) value */ - public static double calculateSpearmanRank(double[][] data) { + public double calculateSpearmanRank(double[][] data) { final int n = data.length; ch1raw = new double[n]; ch2raw = new double[n]; ch1ranks = new double[n]; ch2ranks = new double[n]; /** * Here's the concept. Rank-transform the data, then run * the Pearson correlation on the transformed data. * * 1) We will sort the dataset by one column, extract the * column values and rank them, and replace the data by * the ranks. * 2) Repeat the process now with the remaining column. * 3) Calculate the coefficient from the individual rank * columns, the t-statistic and the df's of the test. */ // Step 1: Sort the raw data, by column #2 (arbitrary choice). Arrays.sort(data, new Comparator() { @Override public int compare(double[] row1, double[] row2) { return Double.compare(row1[1], row2[1]); } }); for (int i = 0; i < n; i++) { ch2raw[i] = data[i][1]; } // Rank the data then replace them into the dataset. ch2ranks = rankValues(ch2raw); for (int i = 0; i < n; i++) { data[i][1] = ch2ranks[i]; } // Step 2: Repeat step 1 with the other data column. Arrays.sort(data, new Comparator() { @Override public int compare(double[] row1, double[] row2) { return Double.compare(row1[0], row2[0]); } }); for (int i = 0; i < n; i++) { ch1raw[i] = data[i][0]; } ch1ranks = rankValues(ch1raw); for (int i = 0; i < n; i++) { data[i][0] = ch1ranks[i]; ch2ranks[i] = data[i][1]; } // Step 3: Compute statistics. rhoValue = calculateRho(ch1ranks, ch2ranks); tStatisticSpearman = getTStatistic(rhoValue, n); dfSpearman = getSpearmanDF(n); return rhoValue; } /** * Returns degrees of freedom for Spearman's rank correlation. * * @param n - N (number of data pairs) * @return Spearman's rank degrees of freedom. */ - public static int getSpearmanDF(int n) { + public int getSpearmanDF(int n) { return n - 2; } /** * Returns associated T-Statistic for Spearman's rank correlation. * * @param rho - Spearman's rho * @param n - N (number of data pairs) * @return Spearman's rank correlation t-statistic */ - public static double getTStatistic(double rho, int n) { + public double getTStatistic(double rho, int n) { double rho_squared = rho * rho; return rho * Math.sqrt( (n - 2) / (1 - rho_squared) ); } /** * Returns sorted rankings for a list of sorted values. * * @param sortedVals - The sorted absolute values * @return ranked sorted list of values */ - public static double[] rankValues(double[] sortedVals) { + public double[] rankValues(double[] sortedVals) { int len = sortedVals.length; int start = 0; int end = 0; double[] newranks = new double[len]; double avg = 0, ranksum = 0; boolean ties_found = false; // first assign ranks, ascending from 1 for (int i=0; i handler) { super.processResults(handler); handler.handleValue("Spearman's rank correlation value", rhoValue, 8); handler.handleValue("Spearman's correlation t-statistic", tStatisticSpearman, 4); handler.handleValue("t-statistic degrees of freedom", dfSpearman); } } diff --git a/src/test/java/tests/CommutativityTest.java b/src/test/java/tests/CommutativityTest.java index 94bcee5..338ea51 100644 --- a/src/test/java/tests/CommutativityTest.java +++ b/src/test/java/tests/CommutativityTest.java @@ -1,103 +1,104 @@ /*- * #%L * Fiji's plugin for colocalization analysis. * %% * Copyright (C) 2009 - 2017 Fiji developers. * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program. If not, see * . * #L% */ package tests; import static org.junit.Assert.assertEquals; import net.imglib2.RandomAccessibleInterval; import net.imglib2.TwinCursor; import net.imglib2.type.logic.BitType; import net.imglib2.type.numeric.RealType; import net.imglib2.view.Views; import org.junit.Test; import algorithms.LiICQ; import algorithms.MandersColocalization; import algorithms.MandersColocalization.MandersResults; import algorithms.MissingPreconditionException; import algorithms.PearsonsCorrelation; import algorithms.SpearmanRankCorrelation; public class CommutativityTest extends ColocalisationTest { /** * This test makes sure the test images A and B lead to the same results, * regardless whether they are added in the order A, B or B, A to the data * container. * * @throws MissingPreconditionException */ @Test public void cummutativityTest() throws MissingPreconditionException { assertCommutativity(zeroCorrelationImageCh1, zeroCorrelationImageCh2, zeroCorrelationAlwaysTrueMask, zeroCorrelationImageCh1Mean, zeroCorrelationImageCh2Mean); assertCommutativity(positiveCorrelationImageCh1, positiveCorrelationImageCh1, positiveCorrelationAlwaysTrueMask, positiveCorrelationImageCh1Mean, positiveCorrelationImageCh2Mean); assertCommutativity(syntheticNegativeCorrelationImageCh1, syntheticNegativeCorrelationImageCh2, syntheticNegativeCorrelationAlwaysTrueMask, syntheticNegativeCorrelationImageCh1Mean, syntheticNegativeCorrelationImageCh2Mean); } protected static > void assertCommutativity( RandomAccessibleInterval ch1, RandomAccessibleInterval ch2, RandomAccessibleInterval mask, double mean1, double mean2) throws MissingPreconditionException { // create a twin value range cursor that iterates over all pixels of the input data TwinCursor cursor1 = new TwinCursor(ch1.randomAccess(), ch2.randomAccess(), Views.iterable(mask).localizingCursor()); TwinCursor cursor2 = new TwinCursor(ch1.randomAccess(), ch2.randomAccess(), Views.iterable(mask).localizingCursor()); // get the Pearson's values double pearsonsR1 = PearsonsCorrelation.fastPearsons(cursor1); double pearsonsR2 = PearsonsCorrelation.fastPearsons(cursor2); // check Pearsons R is the same assertEquals(pearsonsR1, pearsonsR2, 0.0001); // get Li's ICQ values double icq1 = LiICQ.calculateLisICQ(cursor1, mean1, mean2); double icq2 = LiICQ.calculateLisICQ(cursor2, mean2, mean1); // check Li's ICQ is the same assertEquals(icq1, icq2, 0.0001); // get Manders values MandersColocalization mc = new MandersColocalization(); MandersResults manders1 = mc.calculateMandersCorrelation(cursor1, ch1.randomAccess().get().createVariable()); MandersResults manders2 = mc.calculateMandersCorrelation(cursor2, ch2.randomAccess().get().createVariable()); // check Manders m1 and m2 values are the same assertEquals(manders1.m1, manders2.m2, 0.0001); assertEquals(manders1.m2, manders2.m1, 0.0001); // calculate Spearman's Rank rho values - double rho1 = SpearmanRankCorrelation.calculateSpearmanRank(cursor1); - double rho2 = SpearmanRankCorrelation.calculateSpearmanRank(cursor2); + SpearmanRankCorrelation src = new SpearmanRankCorrelation(); + double rho1 = src.calculateSpearmanRank(cursor1); + double rho2 = src.calculateSpearmanRank(cursor2); // make sure both ranks are the same assertEquals(rho1, rho2, 0.0001); } } diff --git a/src/test/java/tests/SpearmanRankTest.java b/src/test/java/tests/SpearmanRankTest.java index 277d8c7..64ba2d3 100644 --- a/src/test/java/tests/SpearmanRankTest.java +++ b/src/test/java/tests/SpearmanRankTest.java @@ -1,136 +1,138 @@ /*- * #%L * Fiji's plugin for colocalization analysis. * %% * Copyright (C) 2009 - 2017 Fiji developers. * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program. If not, see * . * #L% */ package tests; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import algorithms.MissingPreconditionException; import algorithms.SpearmanRankCorrelation; import net.imglib2.TwinCursor; import net.imglib2.type.numeric.integer.UnsignedByteType; import net.imglib2.view.Views; import org.junit.Test; /** * This class contains JUnit 4 test cases for the calculation of * Spearman's Rank Correlation (rho). * * @author Leonardo Guizzetti */ public class SpearmanRankTest extends ColocalisationTest { /** * Checks Spearman's Rank Correlation rho for positive correlated images. */ @Test public void spearmanPositiveCorrTest() throws MissingPreconditionException { TwinCursor cursor = new TwinCursor( positiveCorrelationImageCh1.randomAccess(), positiveCorrelationImageCh2.randomAccess(), Views.iterable(positiveCorrelationAlwaysTrueMask).localizingCursor()); // calculate Spearman's Rank rho value - double rho = SpearmanRankCorrelation.calculateSpearmanRank(cursor); + double rho = new SpearmanRankCorrelation().calculateSpearmanRank(cursor); // Rho value = 0.5463... assertTrue(rho > 0.546 && rho < 0.547); } /** * Checks Spearman's Rank Correlation value for zero correlated images. The rho value * should be about zero. */ @Test public void spearmanZeroCorrTest() throws MissingPreconditionException { TwinCursor cursor = new TwinCursor( zeroCorrelationImageCh1.randomAccess(), zeroCorrelationImageCh2.randomAccess(), Views.iterable(zeroCorrelationAlwaysTrueMask).localizingCursor()); // calculate Spearman's Rank rho value - double rho = SpearmanRankCorrelation.calculateSpearmanRank(cursor); + double rho = new SpearmanRankCorrelation().calculateSpearmanRank(cursor); // Rho value = -0.11... assertTrue(Math.abs(rho) < 0.012); } /** * Checks Spearman's Rank Correlation value for slightly negative correlated synthetic data. * */ @Test public void statisticsTest() throws MissingPreconditionException { double[][] data = new double[][] { {1,113}, {2,43}, {3,11}, {6,86}, {5,59}, {8,47}, {4,92}, {0,152}, {6,23}, {4,9}, {7,33}, {3,69}, {2,75}, {9,135}, {3,30} }; int n = data.length; + final SpearmanRankCorrelation src = new SpearmanRankCorrelation(); + /* * Check the arithmetic for the rho calculation. * Rho is exactly -0.1743 (to 4 decimal points) using the * exact calculation for Spearman's rho as implemented here. */ - double rho = SpearmanRankCorrelation.calculateSpearmanRank(data); + double rho = src.calculateSpearmanRank(data); assertEquals(-0.1743, rho, 0.001); // check the degrees of freedom calculation ( df = n - 2 ) int df = 0; - df = SpearmanRankCorrelation.getSpearmanDF(n); + df = src.getSpearmanDF(n); assertEquals(df, n - 2); // check the t-statistic calculation ( t = rho * sqrt( df / (1-rho^2) ) ) // The t-stat = -0.6382 double tstat = 0.0; - tstat = SpearmanRankCorrelation.getTStatistic(rho, n); + tstat = src.getTStatistic(rho, n); assertEquals(-0.6382, tstat, 0.001); } /** * Checks Spearman's Rank Correlation value for synthetic test image. * This tests the same dataset as the statisticsTest() but tests reading in image * data, the rank transform, and the calling of the statistics calculation methods. */ @Test public void spearmanSyntheticNegCorrTest() throws MissingPreconditionException { TwinCursor cursor = new TwinCursor( syntheticNegativeCorrelationImageCh1.randomAccess(), syntheticNegativeCorrelationImageCh2.randomAccess(), Views.iterable(syntheticNegativeCorrelationAlwaysTrueMask).localizingCursor()); // calculate Spearman's Rank rho value - double rho = SpearmanRankCorrelation.calculateSpearmanRank(cursor); + double rho = new SpearmanRankCorrelation().calculateSpearmanRank(cursor); assertTrue((rho > -0.178) && (rho < -0.173)); } }