package org.broad.igv.cursor;
import org.apache.commons.math.stat.StatUtils;
import org.broad.igv.feature.BasicFeature;
import org.broad.igv.feature.EncodePeakFeature;
import org.broad.igv.feature.SignalFeature;
import org.broad.igv.util.collections.DoubleArrayList;
import java.awt.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author jrobinso
* Date: 1/14/14
* Time: 12:57 PM
*/
public class CursorTrack {
public enum SignalField {Score, Signal, PValue, QValue}
Map<String, List<BasicFeature>> featureMap;
Map<String, Integer> longestFeature;
private Color color = new Color(0, 0, 150);
private String name;
Class featureType;
boolean hasScore = false;
private SignalField signalField = SignalField.Score;
private Map<SignalField, Range> scales;
public static class Range {
double min;
double max;
private Range(double min, double max) {
this.min = min;
this.max = max;
}
public double getMax() {
return max;
}
public double getMin() {
return min;
}
}
public CursorTrack(Map<String, List<BasicFeature>> featureMap, Class featureType) {
this.featureMap = featureMap;
this.featureType = featureType;
this.longestFeature = new HashMap();
// Gather statistics for setting scales.
boolean isEncodePeak = featureType == EncodePeakFeature.class;
DoubleArrayList signals = isEncodePeak ? new DoubleArrayList(50000) : null;
DoubleArrayList qvalues = isEncodePeak ? new DoubleArrayList(50000) : null;
DoubleArrayList pvalues = isEncodePeak ? new DoubleArrayList(50000) : null;
for (Map.Entry<String, List<BasicFeature>> entry : featureMap.entrySet()) {
String chr = entry.getKey();
List<BasicFeature> features = entry.getValue();
int longest = 0;
for (BasicFeature f : features) {
float s = f.getScore();
hasScore = hasScore || !Float.isNaN(s);
if (isEncodePeak) {
EncodePeakFeature pf = (EncodePeakFeature) f;
signals.add(pf.getSignal());
qvalues.add(pf.getQValue());
pvalues.add(pf.getPValue());
}
final int length = f.getLength();
if (length > longest) longest = length;
}
longestFeature.put(chr, longest);
}
scales = new HashMap<SignalField, Range>();
scales.put(SignalField.Score, new Range(0, 1000));
double[] s = signals.toArray();
double sMin = 0;
double sMax = StatUtils.percentile(s, 90);
scales.put(SignalField.Signal, new Range(sMin, sMax));
double[] q = qvalues.toArray();
scales.put(SignalField.QValue, new Range(0, StatUtils.percentile(q, 90)));
double[] p = pvalues.toArray();
scales.put(SignalField.PValue, new Range(0, StatUtils.percentile(p, 90)));
}
public Range getScale() {
return scales.get(signalField);
}
public List<BasicFeature> getFeatures(String chr) {
return featureMap.get(chr);
}
public int getLongestFeatureLength(String chr) {
Integer lf = longestFeature.get(chr);
return lf == null ? -1 : lf;
}
public Map<String, List<BasicFeature>> getFeatureMap() {
return featureMap;
}
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public SignalField getSignalField() {
return signalField;
}
public void setSignalField(SignalField signalField) {
System.out.println("Set signal field: " + signalField);
this.signalField = signalField;
}
public SignalField[] getAllSignalFields() {
if (!hasScore) return noSignalsArray;
else if (featureType == EncodePeakFeature.class) return signalsArray;
else return scoreOnlyArray;
}
public float getSignal(BasicFeature feature) {
if (signalField == SignalField.Score) {
return feature.getScore();
} else {
SignalFeature sf = (SignalFeature) feature;
switch (signalField) {
case Signal:
return sf.getSignal();
case QValue:
return sf.getQValue();
case PValue:
return sf.getPValue();
default:
return feature.getScore();
}
}
}
// Some static arrays for effecienty
private static SignalField[] noSignalsArray = new SignalField[0];
private static SignalField[] scoreOnlyArray = new SignalField[]{SignalField.Score};
private static SignalField[] signalsArray = new SignalField[]{
SignalField.Score, SignalField.Signal, SignalField.PValue, SignalField.QValue};
}