Skip to content

Commit 16dd317

Browse files
committed
Refactor DataSetColorRange to handle log transform better. Refs #290.
1 parent bdcef31 commit 16dd317

File tree

7 files changed

+90
-153
lines changed

7 files changed

+90
-153
lines changed

EnrichmentMapPlugin/src/main/java/org/baderlab/csplugins/enrichmentmap/model/GeneExpression.java

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@
4646
import java.util.Arrays;
4747

4848
import org.apache.commons.math3.util.Precision;
49-
import org.baderlab.csplugins.enrichmentmap.view.util.FuncUtil;
5049

5150

5251
/**
@@ -129,11 +128,11 @@ public float[] rowNormalize() {
129128

130129

131130
public static float max(float[] expression) {
132-
return FuncUtil.reduceExpression(expression, Math::max);
131+
return reduceExpression(expression, Math::max);
133132
}
134133

135134
public static float min(float[] expression) {
136-
return FuncUtil.reduceExpression(expression, Math::min);
135+
return reduceExpression(expression, Math::min);
137136
}
138137

139138
public static float median(float[] expression) {
@@ -173,11 +172,14 @@ public static float closestToZero(float[] expression) {
173172

174173

175174
private float mean() {
176-
return FuncUtil.reduceExpression(expression, (x,y) -> x + y) / expression.length;
175+
return reduceExpression(expression, (x,y) -> x + y) / expression.length;
177176
}
178177

179178
private float std(final float mean) {
180-
float sum = FuncUtil.reduceExpression(expression, (s, exp) -> s + (float)Math.pow(exp - mean, 2));
179+
float sum = 0;
180+
for(float exp : expression) {
181+
sum += (float)Math.pow(Math.abs(exp - mean), 2);
182+
}
181183
return (float) Math.sqrt(sum) / expression.length;
182184
}
183185

@@ -189,6 +191,27 @@ public float[] rowLogTransform() {
189191
}
190192

191193

194+
195+
@FunctionalInterface
196+
private interface FloatFloatFunc {
197+
float apply(float x, float y);
198+
}
199+
200+
private static float reduceExpression(float[] expression, FloatFloatFunc op) {
201+
if(expression == null || expression.length == 0)
202+
return 0;
203+
float x = expression[0];
204+
for(int i = 1; i < expression.length; i++) {
205+
float e = expression[i];
206+
if(!Float.isFinite(x))
207+
x = e;
208+
else if(Float.isFinite(e))
209+
x = op.apply(x, e);
210+
}
211+
return x;
212+
}
213+
214+
192215
public String getName() {
193216
return name;
194217
}

EnrichmentMapPlugin/src/main/java/org/baderlab/csplugins/enrichmentmap/model/GeneExpressionMatrix.java

Lines changed: 42 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -44,16 +44,20 @@
4444
package org.baderlab.csplugins.enrichmentmap.model;
4545

4646
import java.util.HashMap;
47+
import java.util.Iterator;
4748
import java.util.Map;
4849
import java.util.Set;
4950

50-
import org.baderlab.csplugins.enrichmentmap.view.util.FuncUtil;
51+
import org.baderlab.csplugins.enrichmentmap.view.heatmap.HeatMapParams.Transform;
5152

5253
/**
5354
* Class representing a set of genes/proteins expresion profile
5455
*/
5556
public class GeneExpressionMatrix {
5657

58+
59+
60+
5761
//name of columns - specified by first or second row in the expression matrix
5862
private String[] columnNames;
5963
//number of conditions - number of columns
@@ -66,24 +70,8 @@ public class GeneExpressionMatrix {
6670
private Map<Integer, GeneExpression> expressionMatrix = new HashMap<>();
6771

6872

69-
public static float getMaxExpression(Map<Integer,GeneExpression> matrix) {
70-
return FuncUtil.reduceExpressionMatrix(matrix, GeneExpression::max, Math::max);
71-
}
72-
73-
public float getMaxExpression() {
74-
return getMaxExpression(expressionMatrix);
75-
}
76-
77-
public static float getMinExpression(Map<Integer,GeneExpression> matrix) {
78-
return FuncUtil.reduceExpressionMatrix(matrix, GeneExpression::min, Math::min);
79-
}
80-
81-
public float getMinExpression() {
82-
return getMinExpression(expressionMatrix);
83-
}
84-
8573
public float getClosestToZero() {
86-
float closest = getMaxExpression();
74+
float closest = getMinMax(Transform.AS_IS)[1];
8775
if(closest <= 0)
8876
return 0;
8977
for(GeneExpression expression : expressionMatrix.values()) {
@@ -96,25 +84,43 @@ public float getClosestToZero() {
9684
return closest;
9785
}
9886

99-
100-
/**
101-
* Compute the row Normalized version of the current expression matrix. Row
102-
* Normalization involves computing the mean and standard deviation for each
103-
* row in the matrix. Each value in that specific row has the mean
104-
* subtracted and is divided by the standard deviation. Row normalization is
105-
* computed lazily and cached with the expression matrix.
106-
* (Log normalization is computed on the fly)
107-
*/
108-
public synchronized Map<Integer, GeneExpression> rowNormalizeMatrix() {
109-
Map<Integer, GeneExpression> expressionMatrix_rowNormalized = new HashMap<>();
110-
for (Integer key : expressionMatrix.keySet()) {
111-
GeneExpression expression = (GeneExpression) expressionMatrix.get(key);
112-
GeneExpression norm_row = new GeneExpression(expression.getName(), expression.getDescription());
113-
float[] row_normalized = expression.rowNormalize();
114-
norm_row.setExpression(row_normalized);
115-
expressionMatrix_rowNormalized.put(key, norm_row);
87+
88+
public float[] getMinMax(Transform transform) {
89+
Iterator<GeneExpression> iter = expressionMatrix.values().iterator();
90+
if(!iter.hasNext())
91+
return null;
92+
93+
float[] normValues = getExpressions(iter.next(), transform);
94+
float min = GeneExpression.min(normValues);
95+
float max = GeneExpression.max(normValues);
96+
97+
while(iter.hasNext()) {
98+
normValues = getExpressions(iter.next(), transform);
99+
float newMin = GeneExpression.min(normValues);
100+
float newMax = GeneExpression.max(normValues);
101+
102+
if(!Float.isFinite(min))
103+
min = newMin;
104+
else if(Float.isFinite(newMin))
105+
min = Math.min(min, newMin);
106+
107+
if(!Float.isFinite(max))
108+
max = newMax;
109+
else if(Float.isFinite(newMax))
110+
max = Math.max(max, newMax);
111+
}
112+
113+
return new float[] { min, max };
114+
}
115+
116+
117+
private static float[] getExpressions(GeneExpression expression, Transform transform) {
118+
switch(transform) {
119+
default:
120+
case AS_IS: return expression.getExpression();
121+
case LOG_TRANSFORM: return expression.rowLogTransform();
122+
case ROW_NORMALIZE: return expression.rowNormalize();
116123
}
117-
return expressionMatrix_rowNormalized;
118124
}
119125

120126
//Getters and Setters

EnrichmentMapPlugin/src/main/java/org/baderlab/csplugins/enrichmentmap/view/heatmap/table/DataSetColorRange.java

Lines changed: 5 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
package org.baderlab.csplugins.enrichmentmap.view.heatmap.table;
22

3-
import java.util.Map;
43
import java.util.Optional;
54

6-
import org.baderlab.csplugins.enrichmentmap.model.GeneExpression;
75
import org.baderlab.csplugins.enrichmentmap.model.GeneExpressionMatrix;
86
import org.baderlab.csplugins.enrichmentmap.view.heatmap.HeatMapParams.Transform;
97
import org.baderlab.csplugins.org.mskcc.colorgradient.ColorGradientRange;
@@ -23,51 +21,12 @@ private DataSetColorRange(ColorGradientTheme theme, ColorGradientRange range) {
2321
* Reset color gradients based on a change in the data transformation.
2422
*/
2523
public static Optional<DataSetColorRange> create(GeneExpressionMatrix expression, Transform transform) {
26-
double minExpression = expression.getMinExpression();
27-
double maxExpression = expression.getMaxExpression();
24+
float[] minMax = expression.getMinMax(transform);
25+
if(minMax == null || minMax.length < 2)
26+
return Optional.empty();
2827

29-
double min;
30-
double max;
31-
32-
switch(transform) {
33-
case AS_IS:
34-
default:
35-
min = minExpression;
36-
max = Math.max(Math.abs(minExpression), maxExpression);
37-
break;
38-
39-
case ROW_NORMALIZE:
40-
Map<Integer,GeneExpression> rowNormalized = expression.rowNormalizeMatrix();
41-
min = GeneExpressionMatrix.getMinExpression(rowNormalized);
42-
max = GeneExpressionMatrix.getMaxExpression(rowNormalized);
43-
max = Math.max(Math.abs(min), max);
44-
break;
45-
46-
case LOG_TRANSFORM:
47-
//can't take a log of a negative number, if both the max and min are negative then log tranform won't work. issue a warning.
48-
if((minExpression <= 0) && (maxExpression <= 0)) {
49-
//both the max and min are probably negative values
50-
//JOptionPane.showMessageDialog(Cytoscape.getDesktop(),"Both the max and min expression are negative, log of negative numbers is not valid", "log normalization error", JOptionPane.WARNING_MESSAGE);
51-
min = 0;
52-
max = 0;
53-
}
54-
//if min expression is negative then use the max expression as the max
55-
else if(minExpression <= 0) {
56-
double closestToZeroExpression = expression.getClosestToZero();
57-
min = Math.min(Math.log(closestToZeroExpression), Math.log1p(maxExpression));
58-
max = Math.max(Math.log(closestToZeroExpression), Math.log1p(maxExpression));
59-
}
60-
//if the max expression is negative then use the min expression as the max (should never happen!)
61-
else if(maxExpression <= 0) {
62-
min = 0;
63-
max = Math.log1p(minExpression);
64-
} else {
65-
min = Math.log1p(minExpression);
66-
max = Math.log1p(maxExpression);
67-
max = Math.max(Math.abs(min), max);
68-
}
69-
break;
70-
}
28+
float min = minMax[0];
29+
float max = minMax[1];
7130

7231
if(!Double.isFinite(min) || !Double.isFinite(max) || (min == 0 && max == 0)) {
7332
return Optional.empty();

EnrichmentMapPlugin/src/main/java/org/baderlab/csplugins/enrichmentmap/view/util/FuncUtil.java

Lines changed: 0 additions & 49 deletions
This file was deleted.

EnrichmentMapPlugin/src/test/java/org/baderlab/csplugins/enrichmentmap/model/ExpressionOpsTest.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package org.baderlab.csplugins.enrichmentmap.model;
22

33
import static org.junit.Assert.assertEquals;
4-
import static org.junit.Assert.assertFalse;
54
import static org.junit.Assert.assertTrue;
65

76
import java.util.HashMap;
@@ -77,8 +76,8 @@ public void testExpressionMatrixOps() {
7776
GeneExpressionMatrix matrix = new GeneExpressionMatrix();
7877
matrix.setExpressionMatrix(map);
7978

80-
assertEquals(3.0f, matrix.getMaxExpression(), 0.0f);
81-
assertEquals(-3.0f, matrix.getMinExpression(), 0.0f);
79+
assertEquals(3.0f, matrix.getMinMax(Transform.AS_IS)[1], 0.0f);
80+
assertEquals(-3.0f, matrix.getMinMax(Transform.AS_IS)[0], 0.0f);
8281
assertEquals(1.0f, matrix.getClosestToZero(), 0.0f);
8382
}
8483

@@ -91,8 +90,8 @@ public void testExpressionMatrixOpsNaN() {
9190
GeneExpressionMatrix matrix = new GeneExpressionMatrix();
9291
matrix.setExpressionMatrix(map);
9392

94-
assertEquals(3.0f, matrix.getMaxExpression(), 0.0f);
95-
assertEquals(-3.0f, matrix.getMinExpression(), 0.0f);
93+
assertEquals(3.0f, matrix.getMinMax(Transform.AS_IS)[1], 0.0f);
94+
assertEquals(-3.0f, matrix.getMinMax(Transform.AS_IS)[0], 0.0f);
9695
assertEquals(1.0f, matrix.getClosestToZero(), 0.0f);
9796
}
9897

@@ -105,8 +104,8 @@ public void testExpressionMatrixOpsZeros() {
105104
GeneExpressionMatrix matrix = new GeneExpressionMatrix();
106105
matrix.setExpressionMatrix(map);
107106

108-
assertEquals(0f, matrix.getMaxExpression(), 0.0f);
109-
assertEquals(0f, matrix.getMinExpression(), 0.0f);
107+
assertEquals(0f, matrix.getMinMax(Transform.AS_IS)[1], 0.0f);
108+
assertEquals(0f, matrix.getMinMax(Transform.AS_IS)[0], 0.0f);
110109
assertEquals(0f, matrix.getClosestToZero(), 0.0f);
111110
}
112111

EnrichmentMapPlugin/src/test/java/org/baderlab/csplugins/enrichmentmap/model/ModelSerializerTest.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,8 +168,6 @@ private static void assertGeneExpressionMatrixEquals(GeneExpressionMatrix expect
168168
assertEquals(expected.getNumConditions(), actual.getNumConditions());
169169
assertEquals(expected.getExpressionUniverse(), actual.getExpressionUniverse());
170170
assertMapsEqual(ModelSerializerTest::assertGeneExpressionEquals, expected.getExpressionMatrix(), actual.getExpressionMatrix());
171-
assertEquals(expected.getMaxExpression(), actual.getMaxExpression(), 0.0);
172-
assertEquals(expected.getMinExpression(), actual.getMinExpression(), 0.0);
173171
assertEquals(expected.getClosestToZero(), actual.getClosestToZero(), 0.0);
174172
}
175173

EnrichmentMapPlugin/src/test/java/org/baderlab/csplugins/enrichmentmap/parsers/FileReaderTest.java

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import org.baderlab.csplugins.enrichmentmap.model.GSEAResult;
1616
import org.baderlab.csplugins.enrichmentmap.model.GenericResult;
1717
import org.baderlab.csplugins.enrichmentmap.model.LegacySupport;
18+
import org.baderlab.csplugins.enrichmentmap.view.heatmap.HeatMapParams.Transform;
1819
import org.cytoscape.service.util.CyServiceRegistrar;
1920
import org.cytoscape.work.TaskMonitor;
2021
import org.jukito.JukitoRunner;
@@ -102,8 +103,8 @@ public void testExpression1ReaderNormal(Provider<EnrichmentMapParameters> empFac
102103

103104
assertEquals(4, map.getDataSet(LegacySupport.DATASET1).getExpressionSets().getNumGenes());
104105
assertEquals(59, map.getDataSet(LegacySupport.DATASET1).getExpressionSets().getNumConditions());
105-
assertEquals(0.0087, map.getDataSet(LegacySupport.DATASET1).getExpressionSets().getMinExpression(), 0.00001);
106-
assertEquals(5.1315, map.getDataSet(LegacySupport.DATASET1).getExpressionSets().getMaxExpression(), 0.00001);
106+
assertEquals(0.0087, map.getDataSet(LegacySupport.DATASET1).getExpressionSets().getMinMax(Transform.AS_IS)[0], 0.00001);
107+
assertEquals(5.1315, map.getDataSet(LegacySupport.DATASET1).getExpressionSets().getMinMax(Transform.AS_IS)[1], 0.00001);
107108

108109
}
109110

@@ -146,11 +147,11 @@ public void testExpression1ReaderCommentLines(Provider<EnrichmentMapParameters>
146147
//There was one more gene in the expression file that wasn't in the set of genes
147148
//make sure it was was added
148149
assertEquals(4, map.getNumberOfGenes());
149-
assertEquals(5.1315, map.getDataSet(LegacySupport.DATASET1).getExpressionSets().getMaxExpression(), 0.00001);
150+
assertEquals(5.1315, map.getDataSet(LegacySupport.DATASET1).getExpressionSets().getMinMax(Transform.AS_IS)[1], 0.00001);
150151

151152
assertEquals(4, map.getDataSet(LegacySupport.DATASET1).getExpressionSets().getNumGenes());
152153
assertEquals(59, map.getDataSet(LegacySupport.DATASET1).getExpressionSets().getNumConditions());
153-
assertEquals(0.0087, map.getDataSet(LegacySupport.DATASET1).getExpressionSets().getMinExpression(), 0.00001);
154+
assertEquals(0.0087, map.getDataSet(LegacySupport.DATASET1).getExpressionSets().getMinMax(Transform.AS_IS)[0], 0.00001);
154155

155156

156157
}
@@ -196,8 +197,8 @@ public void testExpression1ReaderRnk(Provider<EnrichmentMapParameters> empFactor
196197

197198
assertEquals(4, map.getDataSet(LegacySupport.DATASET1).getExpressionSets().getNumGenes());
198199
assertEquals(3, map.getDataSet(LegacySupport.DATASET1).getExpressionSets().getNumConditions());
199-
assertEquals(0.4754, map.getDataSet(LegacySupport.DATASET1).getExpressionSets().getMinExpression(), 0.000001);
200-
assertEquals(0.5419, map.getDataSet(LegacySupport.DATASET1).getExpressionSets().getMaxExpression(), 0.000001);
200+
assertEquals(0.4754, map.getDataSet(LegacySupport.DATASET1).getExpressionSets().getMinMax(Transform.AS_IS)[0], 0.000001);
201+
assertEquals(0.5419, map.getDataSet(LegacySupport.DATASET1).getExpressionSets().getMinMax(Transform.AS_IS)[1], 0.000001);
201202
}
202203

203204
@Test
@@ -242,8 +243,8 @@ public void testExpression1ReaderEDBRnk(Provider<EnrichmentMapParameters> empFac
242243

243244
assertEquals(4, map.getDataSet(LegacySupport.DATASET1).getExpressionSets().getNumGenes());
244245
assertEquals(3, map.getDataSet(LegacySupport.DATASET1).getExpressionSets().getNumConditions());
245-
assertEquals(0.4754, map.getDataSet(LegacySupport.DATASET1).getExpressionSets().getMinExpression(), 0.00001);
246-
assertEquals(0.5419, map.getDataSet(LegacySupport.DATASET1).getExpressionSets().getMaxExpression(), 0.00001);
246+
assertEquals(0.4754, map.getDataSet(LegacySupport.DATASET1).getExpressionSets().getMinMax(Transform.AS_IS)[0], 0.00001);
247+
assertEquals(0.5419, map.getDataSet(LegacySupport.DATASET1).getExpressionSets().getMinMax(Transform.AS_IS)[1], 0.00001);
247248

248249
}
249250

0 commit comments

Comments
 (0)