package org.seqcode.projects.seqview.paintable;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Stroke;
import java.awt.geom.QuadCurve2D;
import java.io.File;
import java.util.EventObject;
import java.util.HashMap;
import java.util.List;
import org.seqcode.data.readdb.PairedHit;
import org.seqcode.gseutils.Listener;
import org.seqcode.projects.seqview.model.InteractionArcModel;
import org.seqcode.projects.seqview.model.SeqPairedEndModel;
import org.seqcode.viz.DynamicAttribute;
public class InteractionArcPainter extends RegionPaintable {
private InteractionArcModel model;
private InteractionArcProperties props;
private DynamicAttribute attrib;
public InteractionArcPainter (InteractionArcModel model) {
super();
this.model = model;
props = new InteractionArcProperties();
model.addEventListener(this);
attrib = DynamicAttribute.getGlobalAttributes();
}
public InteractionArcProperties getProperties() {return props;}
public void setProperties(InteractionArcProperties p) {props = p;}
public void savePropsInDir(File dir) {
super.savePropsInDir(dir);
saveModelPropsInDir(dir,model);
}
public void loadPropsInDir(File dir) {
super.loadPropsInDir(dir);
loadModelPropsInDir(dir,model);
}
public void cleanup() {
super.cleanup();
model.removeEventListener(this);
}
public synchronized void eventRegistered(EventObject e) {
if (e.getSource() == model && model.isReady()) {
setCanPaint(true);
setWantsPaint(true);
notifyListeners();
}
}
public void removeEventListener(Listener<EventObject> l) {
super.removeEventListener(l);
if (!hasListeners()) {
model.removeEventListener(this);
}
}
public void paintItem(Graphics2D g, int x1, int y1, int x2, int y2) {
if (!canPaint()) {
return;
}
if(!model.isReady()) { return; }
boolean differential = getProperties().Differential;
int width = x2 - x1;
int height = Math.max(y2 - y1,1);
int halfy = y2 - (height/2);
int regionStart = model.getRegion().getStart();
int regionEnd = model.getRegion().getEnd();
int regionWidth = model.getRegion().getWidth();
int linewidth = Math.max(getProperties().LineWidth,1);
Stroke oldStroke = g.getStroke();
g.setStroke(new BasicStroke((float)linewidth));
List<PairedHit> hits = model.getResults();
if(model.isDataError()){
g.setFont(attrib.getLargeLabelFont(width,height));
g.setColor(Color.RED);
g.drawString("ReadDB Data Error: " +getLabel(),x1 + g.getFont().getSize()*2,y1 + g.getFont().getSize());
}else if (getProperties().DrawTrackLabel) {
g.setFont(attrib.getLargeLabelFont(width,height));
g.setColor(Color.BLACK);
g.drawString("Paired " +getLabel(),x1 + g.getFont().getSize()*2,y1 + g.getFont().getSize());
}
int h = height;
float maxweight = 0;
g.setStroke(new BasicStroke(1.0f));
if (differential) {
g.setColor(Color.black);
g.drawLine(x1, halfy, x2, halfy);
for (int i = 0; i < hits.size(); i++) {
PairedHit hit = hits.get(i);
float tmpweight = hit.weight;
int leftx = getXPos(hit.leftPos, regionStart, regionEnd, x1, x2);
int rightx = getXPos(hit.rightPos, regionStart, regionEnd, x1, x2);
int midx = (leftx+rightx)/2;
int midy;
if (tmpweight>=0) {
midy = halfy - (int)(((double)(rightx-leftx)/(double)width) * height);
} else {
midy = halfy + (int)(((double)(rightx-leftx)/(double)width) * height);
}
tmpweight = Math.abs(tmpweight);
g.setStroke(new BasicStroke(tmpweight));
//g.setColor(new Color(0.0f, 0.0f, 0.0f, Math.min(1.0f, tmpweight/25f)));
g.setColor(new Color(0.0f, 0.0f, 0.0f, Math.min(1.0f, props.Alpha.floatValue())));
QuadCurve2D loop = new QuadCurve2D.Float(leftx, halfy, midx, midy, rightx, halfy);
g.draw(loop);
}
} else {
HashMap<PairedHit, Float> pairedReadCounter = new HashMap<PairedHit, Float>();
for (int i = 0; i < hits.size(); i++) {
PairedHit hit = hits.get(i);
if(pairedReadCounter.containsKey(hit))
pairedReadCounter.put(hit, pairedReadCounter.get(hit)+hit.weight);
else
pairedReadCounter.put(hit, hit.weight);
//If under the de-duplicate limit, draw the arc
if(pairedReadCounter.get(hit)<= props.DeDuplicate.floatValue()){
int leftx = getXPos(hit.leftPos, regionStart, regionEnd, x1, x2);
int rightx = getXPos(hit.rightPos, regionStart, regionEnd, x1, x2);
int midx = (leftx+rightx)/2;
int midy = y2 - (int)(((double)(rightx-leftx)/(double)width) * 2*height);
g.setColor(Color.BLACK);
float tmpweight = hit.weight;
if (tmpweight>maxweight) {
maxweight = tmpweight;
}
if (tmpweight>0.0f) {
g.setStroke(new BasicStroke(tmpweight/15f));
tmpweight = Math.max(0.0f, tmpweight);
//g.setColor(new Color(0.0f, 0.0f, 0.0f, Math.min(1.0f, tmpweight/100f)));
g.setColor(new Color(0.4f, 0.4f, 0.4f, props.Alpha.floatValue()));
QuadCurve2D loop = new QuadCurve2D.Float(leftx, y2, midx, midy, rightx, y2);
g.draw(loop);
}
}
}
//System.err.println("maxweight: "+maxweight);
}
g.setStroke(oldStroke);
}
}