-
Notifications
You must be signed in to change notification settings - Fork 555
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* working poc * refactor logic into service, so clean * refactor for parameters builder, simplify min max logic, streamline service call * remove unused services and imports * remove more unused imports
- Loading branch information
Showing
4 changed files
with
345 additions
and
4 deletions.
There are no files selected for viewing
12 changes: 12 additions & 0 deletions
12
src/main/java/org/cbioportal/service/ClinicalDataDensityPlotService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package org.cbioportal.service; | ||
|
||
import org.cbioportal.model.ClinicalData; | ||
import org.cbioportal.model.DensityPlotData; | ||
import org.cbioportal.web.util.DensityPlotParameters; | ||
|
||
import java.math.BigDecimal; | ||
import java.util.List; | ||
|
||
public interface ClinicalDataDensityPlotService { | ||
DensityPlotData getDensityPlotData(List<ClinicalData> filteredClinicalData, DensityPlotParameters densityPlotParameters); | ||
} |
138 changes: 138 additions & 0 deletions
138
src/main/java/org/cbioportal/service/impl/ClinicalDataDensityPlotServiceImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
package org.cbioportal.service.impl; | ||
|
||
import org.apache.commons.lang3.math.NumberUtils; | ||
import org.apache.commons.math3.stat.correlation.PearsonsCorrelation; | ||
import org.apache.commons.math3.stat.correlation.SpearmansCorrelation; | ||
import org.cbioportal.model.ClinicalData; | ||
import org.cbioportal.model.DensityPlotBin; | ||
import org.cbioportal.model.DensityPlotData; | ||
import org.cbioportal.service.ClinicalDataDensityPlotService; | ||
import org.cbioportal.web.columnar.StudyViewColumnStoreController; | ||
import org.cbioportal.web.util.DensityPlotParameters; | ||
import org.springframework.stereotype.Service; | ||
|
||
import java.math.BigDecimal; | ||
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.stream.Collectors; | ||
|
||
@Service | ||
public class ClinicalDataDensityPlotServiceImpl implements ClinicalDataDensityPlotService { | ||
@Override | ||
public DensityPlotData getDensityPlotData(List<ClinicalData> sampleClinicalData, DensityPlotParameters densityPlotParameters) { | ||
DensityPlotData result = new DensityPlotData(); | ||
result.setBins(new ArrayList<>()); | ||
|
||
Map<String, List<ClinicalData>> clinicalDataGroupedBySampleId = sampleClinicalData.stream(). | ||
collect(Collectors.groupingBy(ClinicalData::getSampleId)); | ||
|
||
List<ClinicalData> extractedXYClinicalData = clinicalDataGroupedBySampleId.entrySet().stream() | ||
.filter(entry -> entry.getValue().size() == 2 && | ||
NumberUtils.isCreatable(entry.getValue().get(0).getAttrValue()) && | ||
NumberUtils.isCreatable(entry.getValue().get(1).getAttrValue()) | ||
).flatMap(entry -> entry.getValue().stream()) | ||
.toList(); | ||
|
||
if (extractedXYClinicalData.isEmpty()) { | ||
return result; | ||
} | ||
|
||
Map<Boolean, List<ClinicalData>> partition = extractedXYClinicalData.stream().collect( | ||
Collectors.partitioningBy(c -> c.getAttrId().equals(densityPlotParameters.getXAxisAttributeId()))); | ||
|
||
boolean useXLogScale = densityPlotParameters.getXAxisLogScale() && ClinicalDataDensityPlotServiceImpl.isLogScalePossibleForAttribute(densityPlotParameters.getXAxisAttributeId()); | ||
boolean useYLogScale = densityPlotParameters.getYAxisLogScale() && ClinicalDataDensityPlotServiceImpl.isLogScalePossibleForAttribute(densityPlotParameters.getYAxisAttributeId()); | ||
|
||
double[] xValues = partition.get(true).stream().mapToDouble( | ||
useXLogScale ? ClinicalDataDensityPlotServiceImpl::parseValueLog : ClinicalDataDensityPlotServiceImpl::parseValueLinear | ||
).toArray(); | ||
double[] yValues = partition.get(false).stream().mapToDouble( | ||
useYLogScale ? ClinicalDataDensityPlotServiceImpl::parseValueLog : ClinicalDataDensityPlotServiceImpl::parseValueLinear | ||
).toArray(); | ||
double[] xValuesCopy = Arrays.copyOf(xValues, xValues.length); | ||
double[] yValuesCopy = Arrays.copyOf(yValues, yValues.length); // Why copy these? | ||
Arrays.sort(xValuesCopy); | ||
Arrays.sort(yValuesCopy); | ||
|
||
double xAxisStartValue = densityPlotParameters.getXAxisStart() == null ? xValuesCopy[0] : | ||
(useXLogScale ? ClinicalDataDensityPlotServiceImpl.logScale(densityPlotParameters.getXAxisStart().doubleValue()) : densityPlotParameters.getXAxisStart().doubleValue()); | ||
double xAxisEndValue = densityPlotParameters.getXAxisEnd() == null ? xValuesCopy[xValuesCopy.length - 1] : | ||
(useXLogScale ? ClinicalDataDensityPlotServiceImpl.logScale(densityPlotParameters.getXAxisEnd().doubleValue()) : densityPlotParameters.getXAxisEnd().doubleValue()); | ||
double yAxisStartValue = densityPlotParameters.getYAxisStart() == null ? yValuesCopy[0] : | ||
(useYLogScale ? ClinicalDataDensityPlotServiceImpl.logScale(densityPlotParameters.getYAxisStart().doubleValue()) : densityPlotParameters.getYAxisStart().doubleValue()); | ||
double yAxisEndValue = densityPlotParameters.getYAxisEnd() == null ? yValuesCopy[yValuesCopy.length - 1] : | ||
(useYLogScale ? ClinicalDataDensityPlotServiceImpl.logScale(densityPlotParameters.getYAxisEnd().doubleValue()) : densityPlotParameters.getYAxisEnd().doubleValue()); | ||
double xAxisBinInterval = (xAxisEndValue - xAxisStartValue) / densityPlotParameters.getXAxisBinCount(); | ||
double yAxisBinInterval = (yAxisEndValue - yAxisStartValue) / densityPlotParameters.getYAxisBinCount(); | ||
List<DensityPlotBin> bins = result.getBins(); | ||
for (int i = 0; i < densityPlotParameters.getXAxisBinCount(); i++) { | ||
for (int j = 0; j < densityPlotParameters.getYAxisBinCount(); j++) { | ||
DensityPlotBin densityPlotBin = new DensityPlotBin(); | ||
densityPlotBin.setBinX(BigDecimal.valueOf(xAxisStartValue + (i * xAxisBinInterval))); | ||
densityPlotBin.setBinY(BigDecimal.valueOf(yAxisStartValue + (j * yAxisBinInterval))); | ||
densityPlotBin.setCount(0); | ||
bins.add(densityPlotBin); | ||
} | ||
} | ||
|
||
for (int i = 0; i < xValues.length; i++) { | ||
double xValue = xValues[i]; | ||
double yValue = yValues[i]; | ||
int xBinIndex = (int) ((xValue - xAxisStartValue) / xAxisBinInterval); | ||
int yBinIndex = (int) ((yValue - yAxisStartValue) / yAxisBinInterval); | ||
int index = (int) (((xBinIndex - (xBinIndex == densityPlotParameters.getXAxisBinCount() ? 1 : 0)) * densityPlotParameters.getYAxisBinCount()) + | ||
(yBinIndex - (yBinIndex == densityPlotParameters.getYAxisBinCount() ? 1 : 0))); | ||
DensityPlotBin densityPlotBin = bins.get(index); | ||
densityPlotBin.setCount(densityPlotBin.getCount() + 1); | ||
BigDecimal xValueBigDecimal = BigDecimal.valueOf(xValue); | ||
BigDecimal yValueBigDecimal = BigDecimal.valueOf(yValue); | ||
|
||
// Set new min and max as needed | ||
if (densityPlotBin.getMinX() == null || densityPlotBin.getMinX().compareTo(xValueBigDecimal) > 0){ | ||
densityPlotBin.setMinX(xValueBigDecimal); | ||
} | ||
if (densityPlotBin.getMaxX() == null || densityPlotBin.getMaxX().compareTo(xValueBigDecimal) < 0){ | ||
densityPlotBin.setMaxX(xValueBigDecimal); | ||
} | ||
if (densityPlotBin.getMinY() == null || densityPlotBin.getMinY().compareTo(yValueBigDecimal) > 0){ | ||
densityPlotBin.setMinY(yValueBigDecimal); | ||
} | ||
if (densityPlotBin.getMaxY() == null || densityPlotBin.getMaxY().compareTo(yValueBigDecimal) < 0){ | ||
densityPlotBin.setMaxY(yValueBigDecimal); | ||
} | ||
} | ||
|
||
if (xValues.length > 1) { | ||
// need at least 2 entries in each to compute correlation | ||
result.setPearsonCorr(new PearsonsCorrelation().correlation(xValues, yValues)); | ||
result.setSpearmanCorr(new SpearmansCorrelation().correlation(xValues, yValues)); | ||
} else { | ||
// if less than 1 entry, just set 0 correlation | ||
result.setSpearmanCorr(0.0); | ||
result.setPearsonCorr(0.0); | ||
} | ||
|
||
// filter out empty bins | ||
result.setBins(result.getBins().stream().filter((bin)->(bin.getCount() > 0)).collect(Collectors.toList())); | ||
return result; | ||
} | ||
|
||
|
||
private static boolean isLogScalePossibleForAttribute(String clinicalAttributeId) { | ||
return clinicalAttributeId.equals("MUTATION_COUNT"); | ||
} | ||
|
||
private static double logScale(double val) { | ||
return Math.log(1+val); | ||
} | ||
|
||
private static double parseValueLog(ClinicalData c) { | ||
return ClinicalDataDensityPlotServiceImpl.logScale(Double.parseDouble(c.getAttrValue())); | ||
} | ||
|
||
private static double parseValueLinear(ClinicalData c) { | ||
return Double.parseDouble(c.getAttrValue()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
118 changes: 118 additions & 0 deletions
118
src/main/java/org/cbioportal/web/util/DensityPlotParameters.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
package org.cbioportal.web.util; | ||
|
||
import java.math.BigDecimal; | ||
|
||
public class DensityPlotParameters { | ||
private final Integer xAxisBinCount; | ||
private final Integer yAxisBinCount; | ||
private final BigDecimal xAxisStart; | ||
private final BigDecimal xAxisEnd; | ||
private final BigDecimal yAxisStart; | ||
private final BigDecimal yAxisEnd; | ||
private final Boolean xAxisLogScale; | ||
private final Boolean yAxisLogScale; | ||
private final String xAxisAttributeId; | ||
private final String yAxisAttributeId; | ||
|
||
DensityPlotParameters(Builder builder) { | ||
this.xAxisBinCount = builder.xAxisBinCount; | ||
this.yAxisBinCount = builder.yAxisBinCount; | ||
this.xAxisStart = builder.xAxisStart; | ||
this.xAxisEnd = builder.xAxisEnd; | ||
this.yAxisStart = builder.yAxisStart; | ||
this.yAxisEnd = builder.yAxisEnd; | ||
this.xAxisAttributeId = builder.xAxisAttributeId; | ||
this.yAxisAttributeId = builder.yAxisAttributeId; | ||
this.xAxisLogScale = builder.xAxisLogScale; | ||
this.yAxisLogScale = builder.yAxisLogScale; | ||
} | ||
|
||
public Integer getXAxisBinCount() { | ||
return xAxisBinCount; | ||
} | ||
public Integer getYAxisBinCount() { | ||
return yAxisBinCount; | ||
} | ||
public BigDecimal getXAxisStart() { | ||
return xAxisStart; | ||
} | ||
public BigDecimal getXAxisEnd() { | ||
return xAxisEnd; | ||
} | ||
public BigDecimal getYAxisStart() { | ||
return yAxisStart; | ||
} | ||
public BigDecimal getYAxisEnd() { | ||
return yAxisEnd; | ||
} | ||
public Boolean getXAxisLogScale() { | ||
return xAxisLogScale; | ||
} | ||
public Boolean getYAxisLogScale() { | ||
return yAxisLogScale; | ||
} | ||
public String getXAxisAttributeId() { | ||
return xAxisAttributeId; | ||
} | ||
public String getYAxisAttributeId() { | ||
return yAxisAttributeId; | ||
} | ||
|
||
public static class Builder { | ||
private Integer xAxisBinCount; | ||
private Integer yAxisBinCount; | ||
private BigDecimal xAxisStart; | ||
private BigDecimal xAxisEnd; | ||
private BigDecimal yAxisStart; | ||
private BigDecimal yAxisEnd; | ||
private Boolean xAxisLogScale; | ||
private Boolean yAxisLogScale; | ||
private String xAxisAttributeId; | ||
private String yAxisAttributeId; | ||
|
||
public Builder xAxisBinCount(Integer xAxisBinCount) { | ||
this.xAxisBinCount = xAxisBinCount; | ||
return this; | ||
} | ||
public Builder yAxisBinCount(Integer yAxisBinCount) { | ||
this.yAxisBinCount = yAxisBinCount; | ||
return this; | ||
} | ||
public Builder xAxisStart(BigDecimal xAxisStart) { | ||
this.xAxisStart = xAxisStart; | ||
return this; | ||
} | ||
public Builder xAxisEnd(BigDecimal xAxisEnd) { | ||
this.xAxisEnd = xAxisEnd; | ||
return this; | ||
} | ||
public Builder yAxisStart(BigDecimal yAxisStart) { | ||
this.yAxisStart = yAxisStart; | ||
return this; | ||
} | ||
public Builder yAxisEnd(BigDecimal yAxisEnd) { | ||
this.yAxisEnd = yAxisEnd; | ||
return this; | ||
} | ||
public Builder xAxisLogScale(Boolean xAxisLogScale) { | ||
this.xAxisLogScale = xAxisLogScale; | ||
return this; | ||
} | ||
public Builder yAxisLogScale(Boolean yAxisLogScale) { | ||
this.yAxisLogScale = yAxisLogScale; | ||
return this; | ||
} | ||
public Builder xAxisAttributeId(String xAxisAttributeId) { | ||
this.xAxisAttributeId = xAxisAttributeId; | ||
return this; | ||
} | ||
public Builder yAxisAttributeId(String yAxisAttributeId) { | ||
this.yAxisAttributeId = yAxisAttributeId; | ||
return this; | ||
} | ||
public DensityPlotParameters build() { | ||
return new DensityPlotParameters(this); | ||
|
||
} | ||
} | ||
} |