package org.seqcode.viz.genomicplot;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.seqcode.data.motifdb.WeightMatrix;
import org.seqcode.deepseq.experiments.Sample;
import org.seqcode.genome.location.Gene;
import org.seqcode.genome.location.Point;
import org.seqcode.genome.location.Region;
import org.seqcode.genome.location.StrandedRegion;
import org.seqcode.gsebricks.verbs.location.RefGeneGenerator;
import org.seqcode.gsebricks.verbs.motifs.WeightMatrixScoreProfile;
import org.seqcode.gsebricks.verbs.motifs.WeightMatrixScorer;
import org.seqcode.gseutils.Pair;
import org.seqcode.viz.paintable.AbstractPaintable;
public class ChipSeqFigurePaintable extends FigurePaintable{
private int topBorder=50, bottomBorder=50;
private int leftBorder=25, rightBorder=25;
private List<String> exptNames;
private Map<String, AbstractPaintable> exptPainters = new HashMap<String, AbstractPaintable>();
private RefGeneGenerator<Region> geneGen;
protected List<List<Gene>> geneSets=new ArrayList<List<Gene>>();
protected List<String> geneSetNames = new ArrayList<String>();
public ChipSeqFigurePaintable(FigureOptions opts){
options = opts;
reverseIt=options.reverseOrder;
chr = options.gRegion.getChrom();
rstart = options.gRegion.getStart();
rstop = options.gRegion.getEnd();
exptNames = options.exptNames;
//Initialize genes
if(options.useDBGenes){
geneSetNames.add("Reference");
ArrayList<Gene> geneSet = new ArrayList<Gene>();
geneGen = new RefGeneGenerator<Region>(options.genome, "refGene");
geneGen.retrieveExons(true);
geneGen.setWantAlias(true);
Iterator<Gene> gi = geneGen.execute(options.gRegion);
while(gi.hasNext()) {
geneSet.add(gi.next());
}geneSets.add(geneSet);
}if(options.transcriptGTF != null){//Load GTF
geneSetNames.add(options.transcriptGTF.getName());
ArrayList<Gene> geneSet = new ArrayList<Gene>();
geneSet.addAll(loadGenes(options.transcriptGTF, options.gRegion));
geneSets.add(geneSet);
}
//layout.setRegions(genes);
//Initialize thin painters
for(String t : exptNames){
List<Pair<Point,Point>> inters = options.experiments.get(t).inters;
Sample sample = options.experiments.get(t).exptSample;
ArrayList<Region> sites = options.experiments.get(t).peaks;
if(options.experiments.get(t).preFormattedDataFile != null){
//Initialize a DiffSeqExptPaintable, even for non-diff experiments
DiffSeqExptPaintable dp = new DiffSeqExptPaintable(options.gconfig, options.gRegion, options.experiments.get(t).preFormattedDataFile, options.experiments.get(t).diffWinWidth, options.experiments.get(t).diffWinStep, options.experiments.get(t).scaling );
dp.setMaxLogFold(options.experiments.get(t).yMax);
if(options.experiments.get(t).isDiff)
dp.setMinLogFold(options.experiments.get(t).yMax);
else
dp.setMinLogFold(0);
dp.setReverse(options.reverseOrder);
dp.setNegColor(options.diffExptNegColor);
dp.setPosColor(options.diffExptPosColor);
exptPainters.put(t, dp);
}else if(sample!=null){
if(options.experiments.get(t).isDiff && options.experiments.get(t).baseExpt != null){
Sample otherSample = options.experiments.get(t).baseExptSample;
//Initialize a DiffSeqExptPaintable
DiffSeqExptPaintable dp = new DiffSeqExptPaintable(options.gconfig, options.gRegion, sample, otherSample, options.experiments.get(t).diffWinWidth, options.experiments.get(t).diffWinStep, options.experiments.get(t).scaling );
dp.setMaxLogFold(options.experiments.get(t).yMax);
dp.setMinLogFold(options.experiments.get(t).yMax);
dp.setReverse(options.reverseOrder);
dp.setNegColor(options.diffExptNegColor);
dp.setPosColor(options.diffExptPosColor);
exptPainters.put(t, dp);
}else{
//Initialize the ThinOverlapPaintable
ThinOverlapPaintable tp = new ThinOverlapPaintable(options.gRegion, sites, sample, options.readExt, options.experiments.get(t).pairedReads, options.experiments.get(t).inters);
tp.setReverse(options.reverseOrder);
tp.setMaxOverlap(options.experiments.get(t).yMax);
tp.setLoopColor(options.loopColor);
tp.setInterColor(options.interColor);
tp.setBgColor(options.experiments.get(t).exptBgColor);
tp.setBgThick(options.exptBgThick);
tp.setHighlightColor(options.experiments.get(t).exptPeakColor);
tp.setHighlightThick(options.exptPeakThick);
tp.setFilledColumns(options.experiments.get(t).filledColumns);
exptPainters.put(t, tp);
}
}
}
}
public void paintItem (Graphics g, int x1, int y1, int x2, int y2){
Graphics2D g2d = (Graphics2D)g;
FontMetrics metrics = g2d.getFontMetrics();
int screenSizeX = x2-x1;
int screenSizeY = y2-y1;
g2d.setColor(Color.white);
g2d.fillRect(0, 0, screenSizeX, screenSizeY);
topBound = topBorder;
bottomBound = screenSizeY-bottomBorder;
leftBound = leftBorder+30;
rightBound = screenSizeX-rightBorder;
baseLine = bottomBound-200;
int offset=0;
for(String t : exptNames){
AbstractPaintable p = exptPainters.get(t);
p.paintItem(g, leftBound, baseLine-offset-options.experiments.get(t).exptTrackHeight, rightBound, baseLine-offset);
//Draw motifs
if( options.experiments.get(t).motif != null){
drawMotifs(g2d, baseLine-offset, options.experiments.get(t).motif, options.experiments.get(t).motifThres);
}
//Draw the axis
g2d.setColor(Color.lightGray);
g2d.setStroke(new BasicStroke(1.0f));
//g2d.drawLine(leftBound, baseLine-offset-motifHeight, rightBound, baseLine-offset-motifHeight);
//Experiment label
if(options.drawExptLabels){
g2d.setColor(Color.gray);
g2d.setFont(new Font("Ariel", Font.BOLD, options.labelFontSize));
metrics = g2d.getFontMetrics();
AffineTransform oldtrans = g2d.getTransform();
AffineTransform newtrans = new AffineTransform();
newtrans.translate(leftBound-(metrics.getHeight()), baseLine-offset+metrics.getHeight()-(options.experiments.get(t).exptTrackHeight/2));
newtrans.rotate(Math.toRadians(-90));
g2d.setTransform(newtrans);
g2d.drawString(t,(-1*metrics.stringWidth(t))/2,0);
g2d.setTransform(oldtrans);
}
offset+=(options.experiments.get(t).exptTrackHeight+options.motifHeight+10);
}
//Gene tracks
offset = options.motifHeight;
for(int i=0; i<geneSetNames.size(); i++){
offset += drawGenes(g2d, x1, baseLine+offset+options.geneHeight, x2, geneSets.get(i), options.drawGeneLabels, geneSetNames.get(i));
}
//Draw some coordinates
g2d.setColor(Color.black);
g2d.setFont(new Font("Ariel", Font.PLAIN, options.fontSize));
metrics = g2d.getFontMetrics();
AffineTransform oldtrans = g2d.getTransform();
AffineTransform newtrans = new AffineTransform();
String text = reverseIt ? new String("chr"+chr+":"+rstop) : new String("chr"+chr+":"+rstart);
newtrans.translate(leftBound, baseLine+30+metrics.stringWidth(text));
newtrans.rotate(Math.toRadians(-90));
g2d.setTransform(newtrans);
g2d.drawString(text,0,0);
g2d.setTransform(oldtrans);
newtrans = new AffineTransform();
text = reverseIt ? new String("chr"+chr+":"+rstart) : new String("chr"+chr+":"+rstop);
newtrans.translate(rightBound+(metrics.getHeight()/2), baseLine+30+metrics.stringWidth(text));
newtrans.rotate(Math.toRadians(-90));
g2d.setTransform(newtrans);
g2d.drawString(text,0,0);
g2d.setTransform(oldtrans);
}
private void drawMotifs(Graphics2D g2d, int currLine, WeightMatrix wm, double thres){
ArrayList<StrandedRegion> motifLocs = new ArrayList<StrandedRegion>();
WeightMatrixScorer scorer = new WeightMatrixScorer(wm);
WeightMatrixScoreProfile profiler = scorer.execute(options.gRegion);
for(int z=0; z<options.gRegion.getWidth(); z++){
double currScore= profiler.getMaxScore(z);
if(currScore>=thres){
motifLocs.add(new StrandedRegion(options.genome, chr, rstart+z, rstart+z+wm.length(), profiler.getMaxStrand(z)));
}
}
for(StrandedRegion sr : motifLocs){
Color currCol = options.motifColor;
int start = sr.getStart();
if(sr.getStrand()=='-'){start = sr.getEnd();}
int gx1 = xcoord(start)-(options.motifWidth/2);
g2d.setColor(currCol);
if((sr.getStrand()=='+' && !reverseIt) || (sr.getStrand()=='-' && reverseIt)){
int [] xPoints = {gx1, gx1, gx1+options.motifWidth};
int [] yPoints = {currLine, currLine+options.motifHeight, currLine+(options.motifHeight/2)};
g2d.fillPolygon(xPoints, yPoints, 3);
}else{
gx1 = xcoord(sr.getEnd())+(options.motifWidth/2);
int [] xPoints = {gx1, gx1, gx1-options.motifWidth};
int [] yPoints = {currLine, currLine+options.motifHeight, currLine+(options.motifHeight/2)};
g2d.fillPolygon(xPoints, yPoints, 3);
}
}
}
}