package View;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.JPanel;
import Control.Controller;
import Control.Zoomable;
import Model.Exon;
import Model.Gene;
import Model.Subset;
import Model.Transcript;
import Model.Treatment;
import Model.alignments.Alignment;
public class GeneViewport extends JPanel {
private static final long serialVersionUID = -5340964981177582500L;
private static GeneViewport instance = null;
private Zoomable z;
protected GeneViewport() {
this.setBackground(new Color(240, 240, 240));
this.repaint();
z = Zoomable.getInstance();
z.registerComponent(this);
}
public static GeneViewport getInstance() {
if (instance == null) {
instance = new GeneViewport();
}
return instance;
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Gene gene = Controller.getInstance().getCurrentGene();
if (gene == null) {
return;
}
int geneDistance = gene.getValidDistance();
int offset = Controller.getInstance().getOffset();
int totalDistance = geneDistance + 2 * offset;
if (!z.isSet())
z.autoZoom(totalDistance);
totalDistance = z.calcDist(totalDistance);
g.setColor(new Color(230, 230, 230));
g.fillRect(z.calcDist(offset), 0, z.calcDist(geneDistance), getHeight());
Treatment active = Controller.getInstance().getLastTreatment();
int yoffset = 0;
if (active != null) {
Font bigSize = new Font("Georgia", Font.PLAIN, 18);
Font normal = g.getFont();
g.setFont(bigSize);
g.setColor(new Color(80, 80, 80));
g.drawString("Treatment " + active.getTreatmentID(), 8, g
.getFontMetrics().getHeight() + 2);
yoffset = g.getFontMetrics().getHeight() + 8;
g.setFont(normal);
}
if (Controller.getInstance().isCollapsed()) {
drawCollapsedSubsets(gene, 0, yoffset, getWidth(), getHeight() - 40
- yoffset);
} else {
drawSubsets(0, yoffset, getWidth(), getHeight() - 40 - yoffset);
}
drawGeneModel(g, gene, z.calcDist(offset), getHeight() - 40, 40);
}
private void drawCollapsedSubsets(Gene g, int x, int y, int width,
int height) {
// TODO: Calculate max size
Gene gene = Controller.getInstance().getCurrentGene();
// Draw the treatments in the background lightly
List<Integer> activeTreatments = Controller.getInstance()
.getActiveTreatments();
for (int treatment : activeTreatments) {
Treatment t = gene.getTreatmentByID(treatment);
if (t != null) {
drawCollapsedSubsetsByTreatment(t, x, y, width, height, 40);
}
}
// Get the currently active treatment
Treatment active = Controller.getInstance().getLastTreatment();
if (active != null) {
drawCollapsedSubsetsByTreatment(active, x, y, width, height, 255);
}
}
private void drawCollapsedSubsetsByTreatment(Treatment t, int x, int y,
int width, int height, int opaqueness) {
if (t == null) {
return;
}
List<Subset> subsetList = t.getAllSubsets();
List<Alignment> allSubsets = new ArrayList<Alignment>();
Subset subset0 = null;
for (Subset subset : subsetList) {
if (subset.getSubsetID() != 0) {
allSubsets.addAll(new ArrayList<Alignment>(subset
.getAllAlignments().values()));
} else {
subset0 = subset;
}
}
Collections.sort(allSubsets);
Subset collapsed = new Subset(-1, allSubsets, t);
int subsetHeight = (int) Math.round(Math
.floor(((height - 10) * 1.0) / 2.0));
drawSubset(collapsed, 0, 0, width, subsetHeight, opaqueness);
drawSubset(subset0, 0, height - subsetHeight, width, subsetHeight,
opaqueness);
}
private void drawSubsets(int x, int y, int width, int height) {
Gene gene = Controller.getInstance().getCurrentGene();
// Draw the treatments in the background lightly
List<Integer> activeTreatments = Controller.getInstance()
.getActiveTreatments();
for (int treatment : activeTreatments) {
Treatment t = gene.getTreatmentByID(treatment);
if (t != null) {
drawSubsetsByTreatment(t, x, y, width, height, 40);
}
}
// Get the currently active treatment
Treatment active = Controller.getInstance().getLastTreatment();
if (active != null) {
drawSubsetsByTreatment(active, x, y, width, height, 255);
}
}
private void drawSubsetsByTreatment(Treatment t, int x, int y, int width,
int height, int opaqueness) {
if (t == null) {
return;
}
// Get the subset list
List<Subset> subsetList = t.getAllSubsets();
// Calculate the subset Height
int subsetHeight = (int) Math.round(Math.floor(((height - 10) * 1.0)
/ subsetList.size()));
// Draw the Subsets
for (Subset s : subsetList) {
int sID = s.getSubsetID();
int subsetStart = (sID == 0) ? (height - subsetHeight) : (sID - 1)
* subsetHeight;
subsetStart += y;
drawSubset(s, x, subsetStart, width, subsetHeight, opaqueness);
}
}
private void drawSubset(Subset s, int x, int y, int width, int height,
int opaqueness) {
// Draw the Background
int maxWidth = s.getTreatmentParent().getGeneParent()
.getValidDistance()
+ 2 * Controller.getInstance().getOffset();
int positionPerPixel = (int) Math.round(maxWidth * 1.0
/ this.getPreferredSize().width);
int barWidth = positionPerPixel;
// Calculate how many positions per bar
Object[] obj = calculateMax(s, barWidth);
if (obj == null || obj.length != 3) {
return;
}
int maxCount = (Integer) obj[0];
int total = (Integer) obj[1];
@SuppressWarnings("unchecked")
HashMap<Integer, Integer> counts = (HashMap<Integer, Integer>) obj[2];
Graphics2D g2d = (Graphics2D) this.getGraphics();
g2d.setColor(new Color(167, 219, 216));
g2d.drawLine(x, y + height - 16, x + width, y + height - 16);
FontMetrics fontmetrics = g2d.getFontMetrics();
if (opaqueness == 255) {
Color textColor = new Color(150, 150, 150);
g2d.setColor(textColor);
if (s.getSubsetID() == -1) {
g2d.drawString("Collapsed Subset", x + 8, y + height);
} else {
g2d.drawString("Subset " + s.getSubsetID(), x + 8, y + height);
}
String totalString = Integer.toString(total);
g2d.drawString(totalString, x + width - 8
- g2d.getFontMetrics().stringWidth(totalString), y + height);
}
drawBars(s.getTreatmentParent().getColor(), counts, maxCount, y,
barWidth, height - (fontmetrics.getHeight() + 2), opaqueness);
}
private void drawBars(Color color, HashMap<Integer, Integer> counts,
int maxCount, int y, int barWidth, int height, int opaqueness) {
Graphics2D g2d = (Graphics2D) this.getGraphics();
for (Map.Entry<Integer, Integer> entry : counts.entrySet()) {
if (entry.getValue() > 0) {
int barHeight = (int) Math.round(entry.getValue() * 1.0
/ maxCount * (height * .8));
int geneOffset = Controller.getInstance().getOffset();
g2d.setColor(new Color(color.getRed(), color.getGreen(), color
.getBlue(), opaqueness));
g2d.fillRect(z.calcDist(geneOffset + entry.getKey()), y
+ (height - barHeight - 1), barWidth - 1, barHeight);
}
}
}
private Object[] calculateMax(Subset s, int barWidth) {
Gene g = s.getTreatmentParent().getGeneParent();
int offset = Controller.getInstance().getOffset();
double positionsPerBar = barWidth * z.getPositions();
int min = -1 * offset;
int max = g.getValidDistance() + offset;
HashMap<Integer, Alignment> alignments = s.getAllAlignments();
int maxCount = 0;
int total = 0;
// Go Backwards and calculate Max
HashMap<Integer, Integer> counts = new HashMap<Integer, Integer>();
for (int i = -1; i > min; i = i
- ((int) Math.floor(positionsPerBar) + 1)) {
int count = 0;
for (int num = i; num > i - positionsPerBar; num--) {
if (alignments.containsKey(num)) {
Alignment a = alignments.get(num);
count += a.getCount();
}
}
counts.put(i, count);
if (maxCount < count) {
maxCount = count;
}
total += count;
}
// Go Forward and calculate Max
for (int i = 0; i < max; i += (int) Math.ceil(positionsPerBar)) {
int count = 0;
for (int num = i; num < i + positionsPerBar; num++) {
if (alignments.containsKey(num)) {
Alignment a = alignments.get(num);
count += a.getCount();
}
}
counts.put(i, count);
if (maxCount < count) {
maxCount = count;
}
total += count;
}
Object[] o = { maxCount, total, counts };
return o;
}
/**
*
* @param g
* @param gene
* @param x
* The x offset to start at to draw the Gene
* @param y
* The y offset to start at to draw the Gene
* @param maxHeight
*/
private void drawGeneModel(Graphics g, Gene gene, int x, int y,
int maxHeight) {
int transcriptSize = gene.getTranscripts().size(); // The number of
// transcripts
int middle = (int) Math.round(maxHeight * 1.0 / 2) - 5; // Find the
// middle of the
// area able to
// draw in.
int border = 20;
int above = transcriptSize / 2;
int startY = (transcriptSize % 2 == 0) ? middle - above * border / 2
: middle - above * border;
List<Transcript> transcripts = gene.getTranscripts();
int index = 0;
for (Transcript t : transcripts) {
List<Exon> exons = t.getAllExons();
for (Exon exon : exons) {
int exonOffset = exon.getBounds().start
- gene.getValidPosition().start;
drawExon(g, exon, x + z.calcDist(exonOffset), y + startY
+ border * index, 10);
}
index++;
}
}
private void drawExon(Graphics g, Exon e, int x, int y, int barHeight) {
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(new Color(100, 144, 138));
Rectangle2D.Double geneRect = new Rectangle2D.Double(x, y, z.calcDist(e
.getBounds().getDistance()), barHeight);
g2d.fill(geneRect);
g2d.setColor(new Color(65, 93, 89));
g2d.draw(geneRect);
if (e.hasSharedLeft()) {
g2d.fill(new Rectangle2D.Double(x + 1, y, 2, barHeight));
}
if (e.hasSharedRight()) {
g2d.fill(new Rectangle2D.Double(x
+ z.calcDist(e.getBounds().getDistance()) - 2, y, 2,
barHeight));
}
}
/**
* Draws the Gene Model for the current gene. Starts the Gene at (x,y) with
* given bar height.
*/
private void drawGene(Graphics g, Gene gene, int x, int y, int barHeight) {
Graphics2D g2d = (Graphics2D) g;
// Draw the current gene bounds.
g2d.setColor(new Color(78, 205, 196));
Rectangle2D.Double geneRect = new Rectangle2D.Double(x, y,
z.calcDist(gene.getValidDistance()), barHeight);
g2d.fill(geneRect);
g2d.setColor(new Color(48, 126, 120));
g2d.draw(geneRect);
}
}
|