Skip to content

Commit 55ae9b8

Browse files
committed
Use PhenotypeHighlight for heat map column header highlighting
1 parent e46d7d7 commit 55ae9b8

File tree

11 files changed

+369
-139
lines changed

11 files changed

+369
-139
lines changed

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

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,16 @@
33
import java.util.ArrayList;
44
import java.util.LinkedHashSet;
55
import java.util.List;
6+
import java.util.Map;
67
import java.util.Optional;
78

8-
import org.baderlab.csplugins.enrichmentmap.model.Phenotype.Type;
9+
import org.baderlab.csplugins.enrichmentmap.model.PhenotypeHighlight.Highlight;
910

1011
public class CompressedClass implements ExpressionData {
1112

13+
private final boolean commonButDiffPheno;
1214
private final ExpressionCache expressionCache;
13-
private List<Phenotype> headers = new ArrayList<>();
15+
private List<PhenotypeHighlight> headers = new ArrayList<>();
1416

1517
/**
1618
* If the expressions are the same for multiple data sets then we will only get one data set passed in
@@ -22,52 +24,62 @@ public CompressedClass(EnrichmentMap map, List<EMDataSet> datasets, ExpressionCa
2224
// Special case. There is more than one dataset in the map, and they have the same expressions,
2325
// but the pheontypes are different. We want to show the phenotypes for the selected data sets
2426
// but we don't want to repeat all the expression data.
25-
if(ExpressionData.commonExpressionsButDifferentPhenotypes(map)) {
27+
commonButDiffPheno = ExpressionData.commonExpressionsButDifferentPhenotypes(map);
28+
29+
if(commonButDiffPheno) {
2630
// we only get passed one dataset because expressions are the same
2731
var dataset = datasets.get(0);
32+
var allDatasets = map.getDataSetList();
2833
var classPhenos = ExpressionData.getPhenotypesFromClassFile(dataset);
2934
var highlightPhenos = ExpressionData.getPhenotypesToHighlight(map.getDataSetList()); // get the phenotypes from all the data sets
30-
addHeaders(dataset, classPhenos, highlightPhenos);
35+
addHeaders(allDatasets, classPhenos, highlightPhenos);
3136

3237
} else {
3338
for(var dataset : datasets) {
3439
var classPhenos = ExpressionData.getPhenotypesFromClassFile(dataset);
3540
var highlightPhenos = ExpressionData.getPhenotypesToHighlight(dataset);
36-
addHeaders(dataset, classPhenos, highlightPhenos);
41+
addHeaders(List.of(dataset), classPhenos, highlightPhenos);
3742
}
3843
}
3944
}
4045

46+
@Override
47+
public boolean commonButDiffPheno() {
48+
return commonButDiffPheno;
49+
}
4150

42-
private void addHeaders(EMDataSet mainDataSet, LinkedHashSet<String> classPhenos, List<Phenotype> highlightPhenos) {
51+
private void addHeaders(List<EMDataSet> datasets, LinkedHashSet<String> classPhenos, Map<String,PhenotypeHighlight> highlightPhenos) {
4352
// move highlighted phenotypes to the front
44-
for(Phenotype pheno : highlightPhenos) {
53+
var phenos = new ArrayList<>(highlightPhenos.values());
54+
55+
for(PhenotypeHighlight pheno : phenos) {
4556
if(classPhenos.contains(pheno.getName())) {
4657
headers.add(pheno);
4758
}
4859
}
49-
for(Phenotype pheno : highlightPhenos) {
60+
for(PhenotypeHighlight pheno : phenos) {
5061
classPhenos.remove(pheno.getName());
5162
}
5263

5364
for(String phenoName : classPhenos) {
54-
headers.add(new Phenotype(mainDataSet, phenoName, Type.OTHER));
65+
headers.add(new PhenotypeHighlight(datasets, phenoName, Highlight.NONE));
5566
}
5667
}
5768

5869

5970
@Override
6071
public EMDataSet getDataSet(int idx) {
61-
return headers.get(idx).getDataSet();
72+
// all of the data sets should have the same expression values, so returning any one of them is fine.
73+
return getHighlight(idx).getDatasets().iterator().next();
6274
}
63-
75+
6476
@Override
6577
public String getName(int idx) {
66-
return getPhenotype(idx).getName();
78+
return getHighlight(idx).getName();
6779
}
6880

6981
@Override
70-
public Phenotype getPhenotype(int idx) {
82+
public PhenotypeHighlight getHighlight(int idx) {
7183
return headers.get(idx);
7284
}
7385

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

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import java.util.List;
44
import java.util.Optional;
55

6+
import org.baderlab.csplugins.enrichmentmap.model.PhenotypeHighlight.Highlight;
7+
68
public class CompressedDataSet implements ExpressionData {
79

810
private final ExpressionCache expressionCache;
@@ -29,10 +31,10 @@ public double getValue(int geneID, int idx, Compress compress, Transform transfo
2931
return Float.NaN;
3032

3133
switch (compress) {
32-
case DATASET_MEDIAN: return GeneExpression.median(expression.get());
33-
case DATASET_MAX: return GeneExpression.max(expression.get());
34-
case DATASET_MIN: return GeneExpression.min(expression.get());
35-
default: return Float.NaN;
34+
case DATASET_MEDIAN: return GeneExpression.median(expression.get());
35+
case DATASET_MAX: return GeneExpression.max(expression.get());
36+
case DATASET_MIN: return GeneExpression.min(expression.get());
37+
default: return Float.NaN;
3638
}
3739
}
3840

@@ -46,4 +48,16 @@ public String getName(int idx) {
4648
public int getSize() {
4749
return datasets.size();
4850
}
51+
52+
@Override
53+
public PhenotypeHighlight getHighlight(int col) {
54+
var dataSet = getDataSet(col);
55+
var name = getName(col);
56+
return new PhenotypeHighlight(dataSet, name, Highlight.NONE);
57+
}
58+
59+
@Override
60+
public boolean commonButDiffPheno() {
61+
return false;
62+
}
4963
}

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

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

3-
import java.util.ArrayList;
43
import java.util.Iterator;
4+
import java.util.LinkedHashMap;
55
import java.util.LinkedHashSet;
66
import java.util.List;
7+
import java.util.Map;
8+
9+
import org.baderlab.csplugins.enrichmentmap.model.PhenotypeHighlight.Highlight;
710

8-
import org.baderlab.csplugins.enrichmentmap.model.Phenotype.Type;
911

1012
/**
11-
* Common interface for different levels of compression.
13+
* Common interface for ways of representing (compressing) expression data for use in the HeatMap.
1214
*/
1315
public interface ExpressionData {
1416

15-
EMDataSet getDataSet(int col);
16-
17-
double getValue(int geneID, int col, Compress compress, Transform transform);
18-
19-
String getName(int col);
20-
21-
public default Phenotype getPhenotype(int col) {
22-
return null;
23-
};
24-
17+
/**
18+
* number of columns
19+
*/
2520
int getSize();
2621

27-
28-
2922
/**
30-
* Special case. There is more than one dataset in the map, and they have the same expressions,
31-
* but the pheontypes are different. We want to show the phenotypes for the selected data sets
32-
* but we don't want to repeat all the expression data.
23+
* column name
3324
*/
34-
static boolean commonExpressionsButDifferentPhenotypes(EnrichmentMap map) {
35-
return map != null && map.isCommonExpressionValues() && !phenotypesAreCommon(map);
36-
}
25+
String getName(int col);
3726

27+
/**
28+
* Returns expression value for given gene and column.
29+
*/
30+
double getValue(int geneID, int col, Compress compress, Transform transform);
31+
32+
/**
33+
* Returns a data set that contains the expression value. Note, if multiple data
34+
* sets have the same expression values, only one will be returned.
35+
*/
36+
EMDataSet getDataSet(int col);
3837

3938
/**
40-
* These are the phenotypes entered into the "Phenotypes" fields in the creation dialog.
41-
* They need to be highlighted in the table.
39+
* Info on how to highlight a column based on the classes and phenotypes.
40+
* Should not return null.
4241
*/
43-
static List<Phenotype> getPhenotypesToHighlight(List<EMDataSet> datasets) {
44-
List<Phenotype> phenos = new ArrayList<>();
45-
46-
for(var dataset : datasets) {
47-
var enrichments = dataset.getEnrichments();
48-
49-
String pheno1 = enrichments.getPhenotype1();
50-
if(pheno1 != null) {
51-
phenos.add(new Phenotype(dataset, pheno1, Type.POSITIVE));
52-
}
53-
String pheno2 = enrichments.getPhenotype2();
54-
if(pheno2 != null) {
55-
phenos.add(new Phenotype(dataset, pheno2, Type.NEGATIVE));
56-
}
57-
}
58-
59-
return phenos;
60-
}
42+
PhenotypeHighlight getHighlight(int col);
43+
6144

62-
static List<Phenotype> getPhenotypesToHighlight(EMDataSet dataset) {
63-
return getPhenotypesToHighlight(List.of(dataset));
64-
}
45+
boolean commonButDiffPheno();
6546

6647

6748
/**
@@ -84,7 +65,50 @@ static LinkedHashSet<String> getPhenotypesFromClassFile(EMDataSet dataset) {
8465
}
8566

8667

87-
static boolean phenotypesAreCommon(EnrichmentMap map) {
68+
/**
69+
* These are the phenotypes entered into the "Phenotypes" fields in the creation dialog.
70+
* They need to be highlighted in the table.
71+
*/
72+
static Map<String,PhenotypeHighlight> getPhenotypesToHighlight(List<EMDataSet> datasets) {
73+
Map<String,PhenotypeHighlight> phenoMap = new LinkedHashMap<>();
74+
75+
for (var dataset : datasets) {
76+
var enrichments = dataset.getEnrichments();
77+
78+
String phenoNamePos = enrichments.getPhenotype1();
79+
if(phenoNamePos != null) {
80+
var phenoHighlight = new PhenotypeHighlight(dataset, phenoNamePos, Highlight.POSITIVE);
81+
var existingPheno = phenoMap.get(phenoNamePos);
82+
phenoMap.put(phenoNamePos, phenoHighlight.merge(existingPheno));
83+
}
84+
85+
String phenoNameNeg = enrichments.getPhenotype2();
86+
if (phenoNameNeg != null) {
87+
var phenoHighlight = new PhenotypeHighlight(dataset, phenoNameNeg, Highlight.NEGATIVE);
88+
var existingPheno = phenoMap.get(phenoNameNeg);
89+
phenoMap.put(phenoNameNeg, phenoHighlight.merge(existingPheno));
90+
}
91+
}
92+
93+
return phenoMap;
94+
}
95+
96+
static Map<String,PhenotypeHighlight> getPhenotypesToHighlight(EMDataSet dataset) {
97+
return getPhenotypesToHighlight(List.of(dataset));
98+
}
99+
100+
101+
102+
/**
103+
* Special case. There is more than one dataset in the map, and they have the same expressions,
104+
* but the pheontypes are different. We want to show the phenotypes for the selected data sets
105+
* but we don't want to repeat all the expression data.
106+
*/
107+
static boolean commonExpressionsButDifferentPhenotypes(EnrichmentMap map) {
108+
return map != null && map.isCommonExpressionValues() && !phenotypesAreCommon(map);
109+
}
110+
111+
private static boolean phenotypesAreCommon(EnrichmentMap map) {
88112
Iterator<EMDataSet> iter = map.getDataSets().values().iterator();
89113
SetOfEnrichmentResults r = iter.next().getEnrichments();
90114
String p1 = r.getPhenotype1();

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

Lines changed: 0 additions & 38 deletions
This file was deleted.
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package org.baderlab.csplugins.enrichmentmap.model;
2+
3+
import java.util.LinkedHashMap;
4+
import java.util.LinkedHashSet;
5+
import java.util.List;
6+
import java.util.Objects;
7+
import java.util.Set;
8+
9+
public class PhenotypeHighlight {
10+
11+
public static enum Highlight {
12+
POSITIVE,
13+
NEGATIVE,
14+
NONE
15+
}
16+
17+
private final LinkedHashMap<EMDataSet, Highlight> highlights;
18+
private final String name; // A bit redundant, ExpressionData has the same information
19+
20+
21+
public PhenotypeHighlight(EMDataSet dataset, String name, Highlight highlight) {
22+
this.highlights = new LinkedHashMap<>();
23+
this.highlights.put(Objects.requireNonNull(dataset), Objects.requireNonNull(highlight));
24+
this.name = Objects.requireNonNull(name);
25+
}
26+
27+
public PhenotypeHighlight(List<EMDataSet> datasets, String name, Highlight highlight) {
28+
this.highlights = new LinkedHashMap<>();
29+
for(var ds : datasets) {
30+
this.highlights.put(ds, highlight);
31+
}
32+
this.name = Objects.requireNonNull(name);
33+
}
34+
35+
private PhenotypeHighlight(LinkedHashMap<EMDataSet, Highlight> highlights, String name) {
36+
this.highlights = highlights;
37+
this.name = name;
38+
}
39+
40+
public Set<EMDataSet> getDatasets() {
41+
return new LinkedHashSet<EMDataSet>(highlights.keySet());
42+
}
43+
44+
public String getName() {
45+
return name;
46+
}
47+
48+
public Highlight getHighlight(EMDataSet dataset) {
49+
return highlights.get(dataset);
50+
}
51+
52+
53+
public PhenotypeHighlight merge(PhenotypeHighlight that) {
54+
if(that == null)
55+
return this;
56+
57+
if(name.equals(that.name)) {
58+
var highlights = new LinkedHashMap<EMDataSet, Highlight>();
59+
highlights.putAll(this.highlights);
60+
highlights.putAll(that.highlights);
61+
return new PhenotypeHighlight(highlights, name);
62+
}
63+
64+
throw new IllegalArgumentException("Phenotype names do not match: " + name + " != " + that.name);
65+
}
66+
67+
@Override
68+
public String toString() {
69+
return "PhenotypeHighlight[name=" + name + ", highlights=" + highlights + "]";
70+
}
71+
72+
73+
}

0 commit comments

Comments
 (0)