package gem;
import org.apache.batik.dom.GenericDOMImplementation;
import org.apache.batik.svggen.SVGGraphics2D;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import java.awt.*;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.*;
import java.util.List;
/**
* Creates an SVG figure showing GEM results.
*
* @author Emek Demir
* @author Ozgun Babur
*/
public class Plot
{
/**
* Flag to control grouping method. Results can be grouped by modulator (groupMod = true)
* or by targets (groupMod = false).
*/
static boolean groupMod = true;
public static final AlphaComposite text =
AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f);
public static final AlphaComposite box =
AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f);
public static final Font modfont = new Font("Verdana", Font.PLAIN, 12);
public static final Font targetfont = new Font("Verdana", Font.PLAIN, 8);
public static final Font labelfont = new Font("Verdana", Font.PLAIN, 6);
/**
* Each figure is drawn for just one factor gene.
*/
static String factorName;
//public static Font upFont;
//public static Font downFont;
public static void main(String[] args) throws Throwable
{
String file = "result/Result_fdr0.05_var1.0_AR_duo_prostate";
generateHistoplot(file + ".xls", file + ".svg");
}
/**
* Draws the list of group.
*
* @param g2d
* @param modlist
*/
public void paint(Graphics2D g2d, List<Group> modlist)
{
Collections.sort(modlist);
int i = 0;
Group[][] page = new Group[(modlist.size()/5)+ (modlist.size()%5==0 ? 0 : 1)][5];
for (Group mod : modlist)
{
page[i/5][i%5]=mod;
i++;
}
int rowStart = 60;
for (int rowi = 0; rowi < page.length; rowi++)
{
// if (rowi < 99 || rowi > 150) continue;
Group[] row = page[rowi];
int top = 0;
int bottom = 0;
for (Group mod : row)
{
if (mod!=null)
{
top = Math.max(top, mod.getTop());
bottom = Math.max(bottom, mod.getBottom());
}
}
int rowCenter = rowStart + 10 * top + 6;
int rowbottom = rowCenter + 10 * bottom + 42;
setText(g2d);
g2d.setFont(modfont);
g2d.drawString(factorName,10,rowCenter+5);
g2d.setFont(labelfont);
g2d.drawString("activates",30,rowCenter-7);
g2d.setFont(labelfont);
g2d.drawString("inhibits",30,rowCenter+12);
for (int col = 0; col < row.length; col++)
{
Group mod = row[col];
if (mod!=null)
{
drawGroup(g2d, mod, 50 + 120 * col, rowStart, rowCenter, rowbottom);
}
}
rowStart = rowbottom;
}
}
/**
* Draws a group.
*
* @param g2d
* @param mod
* @param x
* @param rowstart
* @param rowCenter
* @param rowbottom
*/
private void drawGroup(Graphics2D g2d, Group mod,
int x, int rowstart, int rowCenter, int rowbottom)
{
mod.sortMembers();
g2d.setColor(Color.LIGHT_GRAY);
g2d.drawRect(x+27,rowstart-25,110,rowbottom-rowstart-10);
setText(g2d);
g2d.setFont(modfont);
String name = mod.getName();
FontMetrics fm = g2d.getFontMetrics();
int width = fm.stringWidth(name);
int margin= (120-width)/2+27;
g2d.drawString (name, x+margin, rowstart-10);
g2d.setFont(labelfont);
g2d.drawString("Enhances",x+33,rowstart);
g2d.drawString("Attenuates",x+67,rowstart);
g2d.drawString("Inverts",x+107,rowstart);
for (Cat cat : Cat.values())
{
List<String> targets = mod.get(cat);
if (targets != null)
{
setBox(g2d, cat);
Rectangle bounds = cat.getBounds(mod.getHeight(cat) * 10, x, rowCenter);
g2d.fill(bounds);
setText(g2d);
int i=0;
for (String target : targets)
{
i++;
g2d.drawString(target, bounds.x+2, bounds.y-2+i*10);
}
}
}
}
/**
* Sets color to the category.
*
* @param g2d
* @param cat
*/
private void setBox(Graphics2D g2d, Cat cat)
{
g2d.setPaint(cat.getColor());
g2d.setComposite(box);
}
/**
* Switches to text color.
*
* @param g2d
*/
private void setText(Graphics2D g2d)
{
g2d.setPaint(Color.BLACK);
g2d.setComposite(text);
}
public static void generateHistoplot(String tripFile, String outFile) throws IOException
{
// Get a DOMImplementation.
DOMImplementation domImpl = GenericDOMImplementation.getDOMImplementation();
// Create an instance of org.w3c.dom.Document.
String svgNS = "http://www.w3.org/2000/svg";
Document document = domImpl.createDocument(svgNS, "svg", null);
// Create an instance of the SVG Generator.
SVGGraphics2D svgGenerator = new SVGGraphics2D(document);
// Read the triplet data
List<Triplet> list = Triplet.readTrips(tripFile);
for (Triplet t : list)
{
t.backFromURLToIDs();
t.pvalGamma = Difference.calcGammaPval(t);
}
list = Triplet.selectModulator(list, "UBE2I");
// StageAnalyzer.removeBadTars(list);
for (Triplet t : list)
{
t.backFromIDToSymbol();
}
// Remove unclassified triplets
Triplet.keepClassified(list);
// Among the triplets with same M, F, and T, keep only the one with the most significant
// gamma
Triplet.keepMostSignif(list);
HashMap<String, Group> map = process(list);
// Filter out unqualyfying groups
filterGroups(map);
System.out.println("map.size() = " + map.size());
// Render using SVG Graphics2D implementation.
Plot plot = new Plot();
// try
// {
// intiVerticalFonts();
// }
// catch (NoninvertibleTransformException e)
// {
// e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
// }
plot.paint(svgGenerator, new ArrayList<Group>(map.values()));
// Finally, stream out SVG to the standard output using
// UTF-8 encoding.
boolean useCSS = true; // we want to use CSS style attributes
Writer out = new OutputStreamWriter(new FileOutputStream(outFile), "UTF-8");
svgGenerator.stream(out, useCSS);
}
// private static void intiVerticalFonts() throws NoninvertibleTransformException
// {
// AffineTransform fontAT = new AffineTransform();
// fontAT.rotate(-Math.PI/2.0);
// upFont = labelfont.deriveFont(fontAT);
//
// fontAT.invert();
// fontAT.createInverse();
// downFont = labelfont.deriveFont(fontAT);
// }
/**
* Reads triplets and generated Mod list.
*
* @param trips
* @return
* @throws IOException
*/
private static HashMap<String, Group> process(List<Triplet> trips) throws IOException
{
HashMap<String, Group> model = new HashMap<String, Group>();
for (Triplet t : trips)
{
if (factorName == null)
{
factorName = t.factor;
}
String modul = groupMod ? t.modulator : t.target;
if (!model.containsKey(modul)) model.put(modul, new Group(modul));
Group mod = model.get(modul);
String tar = groupMod ? t.target : t.modulator;
if (t.categ.startsWith("MoA")) continue;
Cat cat = Cat.valueOf(t.categ.replace(" ", "_"));
if (cat == null) continue;
if (mod.get(cat) == null) mod.put(cat, new ArrayList<String>());
List<String> tars = mod.get(cat);
if (!tars.contains(tar)) tars.add(tar);
}
return model;
}
/**
* Filters out unqualifying groups.
*
* @param map
*/
private static void filterGroups(HashMap<String, Group> map)
{
for (String key : new HashSet<String>(map.keySet()))
{
Group mod = map.get(key);
if (mod.getSize() < 3)
{
map.remove(key);
}
}
}
/**
* This can be a group of targets with a common modulator, or a group of modulators with a
* common target.
*/
static class Group implements Comparable
{
private String name;
HashMap<Cat, List<String>> cats = new HashMap<Cat, List<String>>();
public Group(String modName)
{
this.name = modName;
}
public int compareTo(Object o)
{
return ((Group) o).getSize() - this.getSize();
}
public int getSize()
{
int i=0;
for (List<String> strings : cats.values())
{
i += strings == null ? 0 : strings.size();
}
return i;
}
public int getTop()
{
return Math.max(getHeight(Cat.Enhances_Activation),
Math.max(getHeight(Cat.Attenuates_Activation),
getHeight(Cat.Inverts_Activation)));
}
public int getBottom()
{
return Math.max(getHeight(Cat.Enhances_Inhibition),
Math.max(getHeight(Cat.Attenuates_Inhibition),
getHeight(Cat.Inverts_Inhibition)));
}
public int getHeight(Cat cat)
{
return cats.get(cat) == null ? 0 : cats.get(cat).size();
}
public String getName()
{
return name;
}
public List<String> get(Cat cat)
{
return cats.get(cat);
}
public void put(Cat cat, List<String> targets)
{
this.cats.put(cat, targets);
}
public void sortMembers()
{
for (List<String> list : cats.values())
{
Collections.sort(list);
}
}
}
/**
* A categoty of modulation.
*/
enum Cat
{
Enhances_Activation(33, 137, 33, 1, 1),
Attenuates_Activation(144, 238, 144, 1, 2),
Inverts_Activation(253, 48, 48, 1, 3),
Enhances_Inhibition(106, 33, 137, 0, 1),
Attenuates_Inhibition(210, 143, 238, 0, 2),
Inverts_Inhibition(253, 207, 47, 0, 3);
private Color color;
private int v, h;
Cat(int r, int g, int b, int v, int h)
{
color = new Color(r, g, b);
this.v = v;
this.h = h;
}
public Color getColor()
{
return color;
}
public Rectangle getBounds(int height, int x, int y)
{
return new Rectangle(x + h * 34, y - v * (height + 4) + 2, 32, height);
}
}
}