[Jtreeview-cvs] jtreeview commit notification
Brought to you by:
alokito
From: Ray <rq...@us...> - 2006-08-16 19:13:54
|
Update of /cvsroot/jtreeview/LinkedView/src/edu/stanford/genetics/treeview/plugin/karyoview In directory sc8-pr-cvs6.sourceforge.net:/tmp/cvs-serv24062/src/edu/stanford/genetics/treeview/plugin/karyoview Added Files: CoordinatesSettingsPanel.java NearestAverager.java KaryoColorPresetEditor.java ChromosomeLocus.java IntervalAverager.java KaryoDrawer.java BitmapKaryoViewExportPanel.java KaryoscopeFactory.java KaryoViewExportPanel.java KaryoColorSet.java Averager.java LinearChromosome.java CircularChromosome.java KaryoColorPresets.java ChromosomeLoci.java KaryoPanel.java FileSetEditor.java CoordinatesPresets.java Chromosome.java DisplaySettingsPanel.java KaryoViewParameterPanel.java KaryoExportPanel.java CoordinatesPresetEditor.java GifKaryoViewExportPanel.java KaryoView.java Genome.java NeighborAverager.java GroupAverager.java Log Message: bug1540281 - preliminary checkin: introduce new "plugin" package (moving lots of files), updated plugin message window. --- NEW FILE: GroupAverager.java --- /* BEGIN_HEADER Java TreeView * * $Author: rqluk $ * $RCSfile: GroupAverager.java,v $ * $Revision: 1.1 $ * $Date: 2006/08/16 19:13:50 $ * $Name: $ * * This file is part of Java TreeView * Copyright (C) 2001-2003 Alok Saldanha, All Rights Reserved. Modified by Alex Segal 2004/08/13. Modifications Copyright (C) Lawrence Berkeley Lab. * * This software is provided under the GNU GPL Version 2. In particular, * * 1) If you modify a source file, make a comment in it containing your name and the date. * 2) If you distribute a modified version, you must do it under the GPL 2. * 3) Developers are encouraged but not required to notify the Java TreeView maintainers at al...@ge... when they make a useful addition. It would be nice if significant contributions could be merged into the main distribution. * * A full copy of the license can be found in gpl.txt or online at * http://www.gnu.org/licenses/gpl.txt * * END_HEADER */ package edu.stanford.genetics.treeview.plugin.karyoview; import edu.stanford.genetics.treeview.*; /** * encapsulates routines common to averagers of groups of things */ abstract class GroupAverager extends Averager { /** * the sole method to be implemented by subclasses, which things to average? */ abstract protected ChromosomeLocus [] getContributors(ChromosomeLocus locus); abstract protected String getPre(); public String[] getDescription(ChromosomeLocus locus, int col) { HeaderInfo geneInfo = karyoView.getGeneInfo(); if (locus == null) { message[0] = "Locus is null"; message[1] = ""; } else { ChromosomeLocus []cont = getContributors(locus); message[0] = getPre() + " locus " + geneInfo.getHeader(locus.getCdtIndex(), "YORF"); message[1] = "Mean of " + cont.length + " loci: " + summarizeYorf(cont); } return message; } private String summarizeYorf(ChromosomeLocus [] loci) { HeaderInfo geneInfo = karyoView.getGeneInfo(); if (loci.length == 0) { return "No loci contribute"; } try { String ret = geneInfo.getHeader(loci[0].getCdtIndex(), "YORF"); for(int i = 1; i < loci.length; i++) { if (loci[i] != null) { ret += ", " + geneInfo.getHeader(loci[i].getCdtIndex(), "YORF"); } } return ret; } catch (Exception e) { LogBuffer.println("failed to summarize loci in GroupAverager!: " + e.toString()); return "failed to summarize loci!: " + e.toString(); } } public double getValue(ChromosomeLocus locus, int col) { if (locus == null) return 0.0; int row = locus.getCdtIndex(); ChromosomeLocus [] loci = getContributors(locus); double sum = 0.0; int n = 0; DataMatrix dataMatrix = karyoView.getDataMatrix(); int numCol = karyoView.getNumCol(); for (int i = 0; i < loci.length; i++) { if (loci[i] == null) continue; int index = loci[i].getCdtIndex(); if (index == -1) continue; sum += dataMatrix.getValue(col, index); n++; } return sum/n; } protected boolean isNodata(ChromosomeLocus locus) { DataMatrix dataMatrix = karyoView.getDataMatrix(); int numCol = karyoView.getNumCol(); try { double value = dataMatrix.getValue( karyoView.getCurrentCol() , locus.getCdtIndex()); return (karyoView.getNodata() == value); } catch (java.lang.ArrayIndexOutOfBoundsException e) { // LogPanel.println("GroupAverager.isNoData() got cdt index " + locus.getCdtIndex() + " out of bounds "); return true; } } protected double getDist(ChromosomeLocus first, ChromosomeLocus second) { int firstArm = first.getArm(); int secondArm = second.getArm(); if (firstArm == secondArm) { return Math.abs(first.getPosition() - second.getPosition()); } else { return Math.abs(first.getPosition() + second.getPosition()); } } protected double square(double pos) { return pos * pos; } } --- NEW FILE: CoordinatesSettingsPanel.java --- /* BEGIN_HEADER Java TreeView * * $Author: rqluk $ * $RCSfile: CoordinatesSettingsPanel.java,v $ * $Revision: 1.1 $ * $Date: 2006/08/16 19:13:49 $ * $Name: $ * * This file is part of Java TreeView * Copyright (C) 2001-2003 Alok Saldanha, All Rights Reserved. Modified by Alex Segal 2004/08/13. Modifications Copyright (C) Lawrence Berkeley Lab. * * This software is provided under the GNU GPL Version 2. In particular, * * 1) If you modify a source file, make a comment in it containing your name and the date. * 2) If you distribute a modified version, you must do it under the GPL 2. * 3) Developers are encouraged but not required to notify the Java TreeView maintainers at al...@ge... when they make a useful addition. It would be nice if significant contributions could be merged into the main distribution. * * A full copy of the license can be found in gpl.txt or online at * http://www.gnu.org/licenses/gpl.txt * * END_HEADER */ package edu.stanford.genetics.treeview.plugin.karyoview; import edu.stanford.genetics.treeview.*; // for settings panel import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.io.File; class CoordinatesSettingsPanel extends JPanel implements SettingsPanel { private KaryoPanel karyoPanel; /** Setter for karyoPanel */ public void setKaryoPanel(KaryoPanel karyoPanel) { this.karyoPanel = karyoPanel; } /** Getter for karyoPanel */ public KaryoPanel getKaryoPanel() { return karyoPanel; } private CoordinatesPresets coordinatesPresets; /** Setter for coordinatesPresets */ public void setCoordinatesPresets(CoordinatesPresets coordinatesPresets) { this.coordinatesPresets = coordinatesPresets; } /** Getter for coordinatesPresets */ public CoordinatesPresets getCoordinatesPresets() { return coordinatesPresets; } public CoordinatesSettingsPanel(KaryoPanel karyoPanel, CoordinatesPresets coordsPresets, ViewFrame frame) { setKaryoPanel(karyoPanel); setCoordinatesPresets(coordsPresets); setFrame(frame); configureWidgets(); addWidgets(); } public void setEnabled(boolean enabled) { fileButton.setEnabled(enabled); originalButton.setEnabled(enabled); for (int i =0; i < presetButtons.length; i++) { presetButtons[i].setEnabled(enabled); } } private JButton fileButton, originalButton; private JButton [] presetButtons; private ViewFrame frame = null; /** Setter for frame */ public void setFrame(ViewFrame frame) { this.frame = frame; } /** Getter for frame */ public ViewFrame getFrame() { return frame; } private void addWidgets() { this.removeAll(); setLayout(new GridBagLayout()); GridBagConstraints gc = new GridBagConstraints(); gc.weightx = 100; gc.weighty = 100; gc.gridx = 0; gc.gridy = 0; gc.gridwidth = 1; gc.gridheight = 1; add(originalButton, gc); JPanel presetPanel = new JPanel(); for (int i =0; i < presetButtons.length;i++) { presetPanel.add(presetButtons[i]); } presetPanel.setBorder(BorderFactory.createLineBorder(Color.black)); gc.gridy = 1; // add(new JScrollPane(presetPanel, JScrollPane.VERTICAL_SCROLLBAR_NEVER, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS), gbc); add(presetPanel, gc); gc.gridy = 2; add(fileButton, gc); } private void configureWidgets() { originalButton = new JButton("Extract from Cdt"); originalButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { karyoPanel.useOriginal(); } }); final CoordinatesPresets presets = getCoordinatesPresets(); int nPresets = presets.getNumPresets(); presetButtons = new JButton[nPresets]; for (int i = 0; i < nPresets; i++) { JButton presetButton = new JButton((presets.getPresetNames()) [i]); final int index = i; presetButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { switchFileset(presets.getFileSet(index)); } }); presetButtons[index] = presetButton; } fileButton = new JButton("Edit Presets..."); fileButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { SettingsPanel presetEditor = KaryoscopeFactory.getCoordinatesPresetsEditor(); JDialog popup = new JDialog(getFrame(), "Edit Coordinates Presets"); SettingsPanelHolder holder = new SettingsPanelHolder(popup, getFrame().getApp().getGlobalConfig().getRoot()); holder.addSettingsPanel(presetEditor); popup.getContentPane().add(holder); popup.setModal(true); popup.pack(); popup.setVisible(true); configureWidgets(); addWidgets(); revalidate(); repaint(); } }); } private void switchFileset(FileSet fileSet1) { try { setEnabled(false); karyoPanel.getGenome(fileSet1); } catch (LoadException ex) { setEnabled(true); LogBuffer.println("CoordinatesSettingsPanel got error" + ex.toString()); JOptionPane.showMessageDialog(getFrame(), ex.toString(), "Load Error", JOptionPane.ERROR_MESSAGE); } } public void synchronizeTo() { } public void synchronizeFrom() { } } --- NEW FILE: ChromosomeLocus.java --- /* BEGIN_HEADER Java TreeView * * $Author: rqluk $ * $RCSfile: ChromosomeLocus.java,v $ * $Revision: 1.1 $ * $Date: 2006/08/16 19:13:49 $ * $Name: $ * * This file is part of Java TreeView * Copyright (C) 2001-2003 Alok Saldanha, All Rights Reserved. Modified by Alex Segal 2004/08/13. Modifications Copyright (C) Lawrence Berkeley Lab. * * This software is provided under the GNU GPL Version 2. In particular, * * 1) If you modify a source file, make a comment in it containing your name and the date. * 2) If you distribute a modified version, you must do it under the GPL 2. * 3) Developers are encouraged but not required to notify the Java TreeView maintainers at al...@ge... when they make a useful addition. It would be nice if significant contributions could be merged into the main distribution. * * A full copy of the license can be found in gpl.txt or online at * http://www.gnu.org/licenses/gpl.txt * * END_HEADER */ package edu.stanford.genetics.treeview.plugin.karyoview; /** * The purpose of this class is purely to hold information about the location of * various loci. It does not hold any exporession data directly, although * it hold a unique integer, the cdtIndex, which ought to be used to look up any values * in a table. */ class ChromosomeLocus { public static final int LEFT = 1; public static final int RIGHT = 2; public static final int CIRCULAR = 3; private int chromosome; // you should follow organism convention here private int arm; //currently, must be linearized genome private double position; // distance from centromere. you do the math private int cdtIndex; // row index of cdt corresponding to locus. private ChromosomeLocus leftLocus = null; // left neightbor or null private ChromosomeLocus rightLocus = null; // right neightbor or null // full getters and setters... public int getChromosome() {return chromosome;} public int getArm() {return arm;} public double getPosition() {return position;} public int getCdtIndex() {return cdtIndex;} public ChromosomeLocus getLeft() {return leftLocus;} public ChromosomeLocus getRight() {return rightLocus;} public void setChromosome(int chr) {this.chromosome = chr;} public void setArm(int arm) {this.arm = arm;} public void setPosition(double pos) {this.position = pos;} public void setCdtIndex(int idx) {this.cdtIndex = idx;} public void setLeft(ChromosomeLocus left) {leftLocus = left;} public void setRight(ChromosomeLocus right) {rightLocus = right;} ChromosomeLocus(int chr, int arm, double pos, int index) { this.chromosome = chr; this.arm = arm; this.position = pos; this.cdtIndex = index; } public String getText(int arm) { if (arm == LEFT) { return "Left"; } else { return "Right"; } } public String toString() { return "Chr " + chromosome + ", arm " + getText(arm) + ", pos " + position + ", row in cdt " + cdtIndex; } } --- NEW FILE: KaryoView.java --- /* BEGIN_HEADER Java TreeView * * $Author: rqluk $ * $RCSfile: KaryoView.java,v $ * $Revision: 1.1 $ * $Date: 2006/08/16 19:13:50 $ * $Name: $ * * This file is part of Java TreeView * Copyright (C) 2001-2003 Alok Saldanha, All Rights Reserved. Modified by Alex Segal 2004/08/13. Modifications Copyright (C) Lawrence Berkeley Lab. * * This software is provided under the GNU GPL Version 2. In particular, * * 1) If you modify a source file, make a comment in it containing your name and the date. * 2) If you distribute a modified version, you must do it under the GPL 2. * 3) Developers are encouraged but not required to notify the Java TreeView maintainers at al...@ge... when they make a useful addition. It would be nice if significant contributions could be merged into the main distribution. * * A full copy of the license can be found in gpl.txt or online at * http://www.gnu.org/licenses/gpl.txt * * END_HEADER */ package edu.stanford.genetics.treeview.plugin.karyoview; import java.awt.*; import java.awt.event.*; import java.util.Observable; import java.util.Observer; import javax.swing.*; import edu.stanford.genetics.treeview.*; /** * This class is a model view that displays the karyoscope view for a * single experiment in the dataset. * * There is really quite a lot of complexity involved. I have decided to factor * out all knowledge of where things are positioned into the KaryoDrawer class. * * I have retained knowledge of averaging in this class, as well as most of the * component mechanics. This is to facilitate the use of KaryoDrawer for drawing * to images with configurable parameters. */ public class KaryoView extends ModelView implements Observer { private KaryoViewParameterPanel parameterPanel = null; public KaryoViewParameterPanel getParameterPanel(){return parameterPanel;} public void setParameterPanel(KaryoViewParameterPanel p) { parameterPanel = p;} /** * current experiment column to view */ private int currentCol = 0; public int getCurrentCol() { return currentCol;} public void setCurrentCol(int n) { if (currentCol == n) return; currentCol = n; recalculateAverages(); offscreenValid = false; } private KaryoDrawer karyoDrawer = null; /** Setter for karyoDrawer */ public void setKaryoDrawer(KaryoDrawer karyoDrawer) { if (this.karyoDrawer != null) { this.karyoDrawer.deleteObserver(this); } this.karyoDrawer = karyoDrawer; if (this.karyoDrawer != null) { this.karyoDrawer.addObserver(this); } } /** Getter for karyoDrawer */ public KaryoDrawer getKaryoDrawer() { return karyoDrawer; } /* averaging accessors */ private AveragerSettingsPanel averagerSettingsPanel; public SettingsPanel getAveragerSettingsPanel() { return averagerSettingsPanel; } public int getAveragingType() { return averager.getType(); } public String getAveragingArg() { return averager.getArg(); } private int defaultAverager = Averager.INTERVAL; public void setSimpleAveraging() { averagerSettingsPanel.setEnabled(false); configNode.setAttribute("averager", simpleAverager.getType(), defaultAverager); recalculateAverages(); } public void setNearestAveraging(int num) { averagerSettingsPanel.setEnabled(false); configNode.setAttribute("averager", nearestAverager.getType(), defaultAverager); nearestAverager.setNum(num); recalculateAverages(); } public void setNeighborAveraging(int num) { averagerSettingsPanel.setEnabled(false); configNode.setAttribute("averager", neighborAverager.getType(), defaultAverager); neighborAverager.setNum(num); recalculateAverages(); } public void setIntervalAveraging(double width) { averagerSettingsPanel.setEnabled(false); configNode.setAttribute("averager", intervalAverager.getType(), defaultAverager); intervalAverager.setWidth(width); recalculateAverages(); } private Averager getAverager(int type) { switch(type) { case Averager.SIMPLE: return simpleAverager; case Averager.NEAREST: return nearestAverager; case Averager.NEIGHBOR: return neighborAverager; case Averager.INTERVAL: return intervalAverager; } return getAverager(defaultAverager); } /* Some private state variables... */ private Averager simpleAverager; private NeighborAverager neighborAverager; private NearestAverager nearestAverager; private IntervalAverager intervalAverager; private JScrollPane scrollPane; private DataMatrix dataMatrix; /** Setter for dataMatrix */ public void setDataMatrix(DataMatrix dataMatrix) { this.dataMatrix = dataMatrix; } /** Getter for dataMatrix */ public DataMatrix getDataMatrix() { return dataMatrix; } /** Getter for numCol */ public int getNumCol() { return dataMatrix.getNumCol(); } private int numRow; private double nodata; /** Setter for nodata */ public void setNodata(double nodata) { this.nodata = nodata; } /** Getter for nodata */ public double getNodata() { return nodata; } private HeaderInfo experimentInfo; private HeaderInfo geneInfo; /** Setter for geneInfo */ public void setGeneInfo(HeaderInfo geneInfo) { this.geneInfo = geneInfo; } /** Getter for geneInfo */ public HeaderInfo getGeneInfo() { return geneInfo; } /** * removes any pointers to exteral objects to aid GC */ public void cleanup() { dataMatrix = null; scrollPane = null; karyoDrawer = null; experimentInfo = null; geneInfo = null; } public void update(Observable o, Object arg) { if (o == karyoDrawer) { offscreenValid = false; revalidate(); repaint(); } else { LogBuffer.println("KaryoView got weird update from " + o); } } /** * for viewing DataModels */ public KaryoView(KaryoDrawer karyoDrawer, DataModel tvmodel) { setKaryoDrawer(karyoDrawer); dataMatrix = tvmodel.getDataMatrix(); nodata = DataModel.NODATA; experimentInfo = tvmodel.getArrayHeaderInfo(); geneInfo = tvmodel.getGeneHeaderInfo(); simpleAverager = new Averager(); simpleAverager.setKaryoView(this); nearestAverager = new NearestAverager(); nearestAverager.setKaryoView(this); neighborAverager = new NeighborAverager(); neighborAverager.setKaryoView(this); intervalAverager = new IntervalAverager(); intervalAverager.setKaryoView(this); averagerSettingsPanel = new AveragerSettingsPanel(this); averager = simpleAverager; averageTimer = new javax.swing.Timer(1000, new TimerListener()); averageTimer.stop(); mouseTracker = new MouseTracker(); statusText[1] = "Mouse over for info on genes..."; statusText[2] = ""; statusText[3] = ""; scrollPane = new JScrollPane(this); panel = scrollPane; addMouseMotionListener(mouseTracker); addMouseListener(mouseTracker); addKeyListener(mouseTracker); } ProgressMonitor averagerMonitor; javax.swing.Timer averageTimer; AveragerTask averagerTask; class TimerListener implements ActionListener { // manages the averagermonitor public void actionPerformed(ActionEvent evt) { if (averagerMonitor.isCanceled() || averagerTask.done()) { averagerMonitor.close(); averagerTask.stop(); // Toolkit.getDefaultToolkit().beep(); averagerSettingsPanel.setEnabled(true); averageTimer.stop(); if (averagerTask.done()) { averagerMonitor.setNote("Averaging complete"); } } else { averagerMonitor.setNote(averagerTask.getMessage()); averagerMonitor.setProgress(averagerTask.getCurrent()); } repaint(); } } class AveragerTask { private int current = 0; private String statMessage; /** * Called to start the task. I don't know why we bother with the ActualTask class, so don't ask. */ void go() { setCurrent(0); final SwingWorker worker = new SwingWorker() { public Object construct() { return new ActualTask(); } }; worker.start(); } /** * Called from ProgressBarDemo to find out how much work needs * to be done. */ int getLengthOfTask() { return karyoDrawer.getGenome().getNumLoci(); } /** * Called from ProgressBarDemo to find out how much has been done. */ int getCurrent() { return current; } void setCurrent(int i) { current = i; } public void incrCurrent() { current++; } /** * called to stop the averaging on a cancel... */ void stop() { current = getLengthOfTask(); } /** * Called from ProgressBarDemo to find out if the task has completed. */ boolean done() { if (current >= getLengthOfTask()) { return true; } else { return false; } } String getMessage() { return statMessage; } class ActualTask { ActualTask() { karyoDrawer.setNodata(nodata); Genome genome = karyoDrawer.getGenome(); int nchr = genome.getMaxChromosome(); setCurrent(0); // System.out.println("Actual task started, length " + getLengthOfTask()); for (int i = 1; i <= nchr; i++) { statMessage = "Processing Chromosome " + i; ChromosomeLocus start = genome.getChromosome(i).getLeftEnd(); if (start == null) { // nothing on chromosome... continue; } ChromosomeLocus current = start; int currentCol = getCurrentCol(); double nodata = getNodata(); do { if (done()) break; if (current.getCdtIndex() != -1) { try { karyoDrawer.setMapValue(current, averager.getValue(current, currentCol)); } catch (java.lang.ArrayIndexOutOfBoundsException e) { karyoDrawer.setMapValue(current, nodata); } } else { karyoDrawer.setMapValue(current, nodata); } current = current.getRight(); incrCurrent(); } while ((current != start) && (current != null)); if (done()) break; } stop(); } } } public void recalculateAverages() { averager = getAverager(configNode.getAttribute("averager", defaultAverager)); // only need to calculate averages for loci which are in genome... averagerTask = new AveragerTask(); averagerMonitor = new ProgressMonitor(this, "Calculating Averaged Values", "Note", 0, averagerTask.getLengthOfTask()); averagerMonitor.setProgress(0); averagerTask.go(); averageTimer.start(); } Averager averager = null; MouseTracker mouseTracker = new MouseTracker(); public synchronized void paintComposite (Graphics g) { mouseTracker.paintComposite(g); } /** * override parent so as to avoid running out of memory at high zooms. */ public void paintComponent(Graphics g) { Dimension newsize = getSize(); if (newsize == null) { return;} // karyoDrawer.notifyObservers(); if (karyoDrawer.getPixelPerVal() == 0) { if (getKaryoDrawer().getGenome().getMaxChromosome() > 0) { if (getKaryoDrawer().getGenome().getNonemptyCount() > 0) { redoScale(); } else { return; } } } // System.out.println("repaint called on KaryoView " + newsize); // update offscreenBuffer if necessary g.setColor(Color.white); g.fillRect(0,0,newsize.width, newsize.height); if (isEnabled()) { offscreenValid = false; updateBuffer(g); paintComposite(g); } } Rectangle clipRect = new Rectangle(); public void updateBuffer(Graphics g) { if (justZoomed) { justZoomed = false; scrollPane.getViewport().setViewPosition(zoomPoint); repaint(); return; } try { clipRect = g.getClipBounds(clipRect); } catch (java.lang.NoSuchMethodError e) { clipRect.setBounds(g.getClipBounds()); } karyoDrawer.paint(g, clipRect); } /* private int nChromosomes = 0; private int chrIndex = -1; private int armIndex = -1; private int posIndex = -1; private int orfIndex = -1; */ public String viewName() { return "KaryoView"; } /** * This method is called to make the karyoview fit on the screen. * It will set the desired width and height, and then ask the KaryoDrawer * to adjust the pixels per value and pixels per row to something sensible. */ Rectangle repaintRect = new Rectangle(); public void redoScale() { // Exception e = new Exception(); e.printStackTrace(); Dimension size = scrollPane.getViewport().getExtentSize(); karyoDrawer.setWidth(size.width); karyoDrawer.setHeight(size.height); karyoDrawer.autoScale(); revalidate(); repaintRect.setBounds(0, 0, size.width, size.height); repaint(repaintRect); if (parameterPanel != null) { parameterPanel.getValues(); } } public String [] getExperiments() { String [] names = new String[getNumCol()]; for (int i = 0; i < getNumCol();i++) { names[i] = experimentInfo.getHeader(i)[0]; } return names; } public Dimension getPreferredSize() { if (karyoDrawer.getWidth() >= 0) { Dimension p = new Dimension(karyoDrawer.getWidth(),karyoDrawer.getHeight()); return p; } else { return super.getPreferredSize(); } } public boolean isChromosomeVisible(int i) { JViewport viewport = scrollPane.getViewport(); Rectangle clipRect = viewport.getViewRect(); int min = karyoDrawer.minVisibleChromosome(clipRect); int max = karyoDrawer.maxVisibleChromosome(clipRect); System.out.println("min " + min + " max " + max); if (i <= max && i >= min) { return true; } else { return false; } } private boolean justZoomed = false; private Point zoomPoint = new Point(); private void zoomRectangle(Rectangle r) { JViewport viewport = scrollPane.getViewport(); Dimension visible = viewport.getExtentSize(); // calculate scale factors... double sx = (double) visible.width / r.width; double sy = (double) visible.height / r.height; /* Dimension scrollPaneSize = scrollPane.getSize(); Dimension viewportSize = viewport.getSize(); Dimension viewSize = viewport.getViewSize(); System.out.println("scrollPaneSize " + scrollPaneSize); System.out.println("viewPort " + viewport); System.out.println("viewportSize " + viewportSize); System.out.println("extentSize " + visible); System.out.println("viewSize " + viewSize); System.out.println("zoomto " + r); */ // System.out.println("was " + getPreferredSize()); karyoDrawer.setWidth((int) (karyoDrawer.getWidth() * sx)); karyoDrawer.setHeight((int) (karyoDrawer.getHeight() * sy)); karyoDrawer.setPixelPerMap(sx * karyoDrawer.getPixelPerMap()); karyoDrawer.setPixelPerVal(sy * karyoDrawer.getPixelPerVal()); // System.out.println("now " + getPreferredSize()); revalidate(); zoomPoint.setLocation((int) (sx * r.x), (int) (sy * r.y)); justZoomed = true; scrollPane.repaint(); if (parameterPanel != null) { parameterPanel.getValues(); } } /** * Zoom with the specified factor, keeping the specified point in the same relative place. * * If the point is null, it keeps the center in the same place. */ private void zoomFactor(double factor, Point point) { JViewport viewport = scrollPane.getViewport(); Dimension visible = viewport.getExtentSize(); Point r = viewport.getViewPosition(); if (point == null) { point = new Point(r.x + visible.width/2, r.y + visible.height/2); } // zooms view out... karyoDrawer.setWidth((int) (karyoDrawer.getWidth() * factor)); karyoDrawer.setHeight((int) (karyoDrawer.getHeight() * factor)); karyoDrawer.setPixelPerMap(karyoDrawer.getPixelPerMap() * factor); karyoDrawer.setPixelPerVal(karyoDrawer.getPixelPerVal() * factor); revalidate(); zoomPoint.setLocation((int) (point.x*factor - (point.x - r.x)), (int) (point.y*factor - (point.y - r.y))); justZoomed = true; scrollPane.repaint(); if (parameterPanel != null) { parameterPanel.getValues(); } } /** * follows mouse around, communicates with KaryoView by calling drawBad * and being called by paintComposite() */ class MouseTracker implements MouseMotionListener, MouseListener, KeyListener { /* key listener */ public void keyPressed (KeyEvent e) { // Invoked when a key has been pressed. } public void keyReleased (KeyEvent e) { //ÊÊInvoked when a key has been released. } public void keyTyped (KeyEvent e) { //ÊÊInvoked when a key has been typed switch (e.getKeyChar()) { case '-': zoomFactor(0.5, startPoint); startPoint.x = (int)(startPoint.x * 0.5); startPoint.y = (int)(startPoint.y * 0.5); mouseMoved(new MouseEvent (KaryoView.this, MouseEvent.MOUSE_MOVED, 10, 0, startPoint.x, startPoint.y, 1, false)); break; case '+': zoomFactor(2.0, startPoint); startPoint.x = (int)(startPoint.x * 2.0); startPoint.y = (int)(startPoint.y * 2.0); mouseMoved(new MouseEvent (KaryoView.this, MouseEvent.MOUSE_MOVED, 10, 0, startPoint.x, startPoint.y, 1, false)); break; } } Point startPoint = new Point(); Point endPoint = new Point(); /* dragRect is non-null when the mouse is dragging */ Rectangle dragRect = null; /* * tip and highlight are non-null when the mouse is in the view * they are also set to null when the mouse is released on a zoom */ Point tip = null; // keeps track of the tip of the most recent gene Rectangle highlight = null; // box around tip in which to draw highlight Rectangle repaintRect = new Rectangle(); public void mouseEntered(MouseEvent e) { requestFocus(); } public void mouseExited(MouseEvent e) { repaint(repaintRect); if (tip != null) { repaintRect.setLocation(tip.x, tip.y); } repaintRect.setSize(0,0); if (highlight != null) { repaintRect.add(highlight); } tip = null; highlight = null; repaint(repaintRect); updateStatus(null); } public void mouseClicked(MouseEvent e) { if (viewFrame.windowActive() == false) return; int xpos = (int) e.getX(); int ypos = (int) e.getY(); startPoint.setLocation(xpos, ypos); ChromosomeLocus closest = karyoDrawer.getClosest(startPoint); if (closest != null) { int closestIndex = closest.getCdtIndex(); if (closestIndex != -1) { if (viewFrame != null) { viewFrame.displayURL(closestIndex); } } } } // MouseMotionListener public void mouseMoved(MouseEvent e) { int xpos = e.getX(); int ypos = e.getY(); startPoint.setLocation(xpos, ypos); ChromosomeLocus closest = karyoDrawer.getClosest(startPoint); updateStatus(closest); moveHighlight(closest); } // Mouse Listener public void mousePressed(MouseEvent e) { mouseExited(e); if (viewFrame.windowActive() == false) return; // initialize startpoint and endpoint startPoint.setLocation(e.getX(), e.getY()); endPoint.setLocation(startPoint.x, startPoint.y); // setup dragrect dragRect = new Rectangle(); dragRect.setLocation(startPoint.x, startPoint.y); dragRect.setSize(endPoint.x - dragRect.x, endPoint.y - dragRect.y); // repaint. repaint(dragRect); } public void mouseReleased(MouseEvent e) { if (viewFrame.windowActive() == false) return; if (dragRect == null) return; mouseDragged(e); repaintRect.setBounds(dragRect); // need to set null for repaint.... tip = null; highlight = null; dragRect = null; // System.out.println("Repainting rect"); repaint(repaintRect); if (repaintRect.width > 3) { if (repaintRect.height > 3) { zoomRectangle(repaintRect); } } } // MouseMotionListener public void mouseDragged(MouseEvent e) { // move dragRect if (dragRect == null) { LogBuffer.println("dragRect null"); return; } endPoint.setLocation(e.getX(), e.getY()); dragRect.setLocation(startPoint.x, startPoint.y); dragRect.setSize(0,0); dragRect.add(endPoint.x, endPoint.y); // animate! repaint(repaintRect); repaintRect.setBounds(dragRect); repaintRect.grow(1,1); repaint(repaintRect); } public void paintComposite (Graphics g) { // composite the rectangles... if (highlight != null) { g.setColor(karyoDrawer.getKaryoColorSet().getColor("Highlight")); int lx = highlight.x; int ux = lx + highlight.width; int uy = highlight.y; int ly = uy + highlight.height; g.drawLine(lx,ly,ux,uy); g.drawLine(lx,uy,ux,ly); // g.fillRect(highlight.x, highlight.y, // highlight.width, highlight.height); } if (tip != null) { int mouseX = (int) startPoint.x; int mouseY = (int) startPoint.y; g.drawLine(mouseX, mouseY, tip.x, tip.y); } if (dragRect != null) { drawBand(dragRect, g); } } private void drawBand(Rectangle l, Graphics g) { g.setColor(Color.yellow); // g.setXORMode(getBackground()); doesn't work. don't know why not - probbaly not using setBackground()??? g.drawRect(l.x, l.y, l.width, l.height); g.setPaintMode(); } private void removeHighlight() { // don't you love english? highlight = null; tip = null; repaint(repaintRect); return; } private void moveHighlight(ChromosomeLocus locus) { if (locus == null) { removeHighlight(); return; } double val = 0; try { val = averager.getValue(locus, getCurrentCol()); } catch (Exception e) { removeHighlight(); return; } if (val == nodata) { removeHighlight(); return; } // locate pixel of top of gene... tip = karyoDrawer.getEnd(locus); if (highlight == null) { highlight = new Rectangle(); } highlight.setBounds(tip.x-5, tip.y-5, 11, 11); // System.out.println("moved highlight to " + geneX + ", " + geneY + " locus " + locus.toString()); repaint(repaintRect); repaintRect.setLocation(tip.x, tip.y); repaintRect.setSize(0,0); repaintRect.add(highlight); repaintRect.add(tip); repaintRect.add(startPoint); repaintRect.grow(1,1); repaint(repaintRect); } } private void updateStatus(ChromosomeLocus locus) { if (locus == null) { statusText[0] = "KeyBoard Shortcuts:"; statusText[1] = ""; statusText[2] = "'+' zooms in on mouse"; statusText[3] = "'-' zooms out on mouse"; statusText[4] = ""; // LogPanel.println("KaryoView.updateStatus(): Locus was " + locus); } else { int chr = locus.getChromosome(); int arm = locus.getArm(); double pos = locus.getPosition(); int closestIndex = locus.getCdtIndex(); statusText[0] = "Cursor is over Chromosome " + chr + " arm " + arm + " position " + pos; if (closestIndex != -1) { statusText[1] = geneInfo.getHeader(closestIndex,"NAME"); double val = karyoDrawer.getMapValue(closestIndex); if (val == nodata) { statusText[2] = "Value: No Data"; } else { statusText[2] = "Value: " + val; } String [] desc = averager.getDescription(locus, getCurrentCol()); statusText[3] = desc[0]; statusText[4] = desc[1]; } else { statusText[1] = "Mouse over for info on genes..."; statusText[2] = ""; statusText[3] = ""; statusText[4] = ""; } } if (status != null) { status.setMessages(getStatus()); } } private String [] statusText = new String[5]; // method from ModelView public String[] getStatus() { return statusText; } private int getClosest(int chr, int arm, double pos) { /* return chromosomeLoci.getClosestLocus(chr, arm, pos).getCdtIndex(); */ return 0; } private ConfigNode configNode = new DummyConfigNode("KaryoView"); /** Setter for configNode */ public void bindConfig(ConfigNode configNode) { this.configNode = configNode; simpleAverager.bindConfig( getFirst("SimpleAverager")); intervalAverager.bindConfig(getFirst("IntervalAverager")); nearestAverager.bindConfig( getFirst("NearestAverager")); neighborAverager.bindConfig( getFirst("NeighborAverager")); } /** Getter for configNode */ public ConfigNode getConfigNode() { return configNode; } /** * always returns an instance of the node, even if it has to create it. */ private ConfigNode getFirst(String name) { ConfigNode cand = getConfigNode().fetchFirst(name); return (cand == null)? getConfigNode().create(name) : cand; } /** * Inner class to manage the settings of the extant averagers. */ private class AveragerSettingsPanel extends JPanel implements SettingsPanel { private KaryoView karyoView; /** Setter for karyoView */ public void setKaryoView(KaryoView karyoView) { this.karyoView = karyoView; } /** Getter for karyoView */ public KaryoView getKaryoView() { return karyoView; } public void setEnabled(boolean enabled) { simpleButton.setEnabled(enabled); nearestButton.setEnabled(enabled); neighborButton.setEnabled(enabled); intervalButton.setEnabled(enabled); nearestField.setEnabled(enabled); neighborField.setEnabled(enabled); intervalField.setEnabled(enabled); } private JButton simpleButton, nearestButton, neighborButton, intervalButton; private JTextField nearestField, neighborField, intervalField; public AveragerSettingsPanel(KaryoView karyoView) { setKaryoView(karyoView); configureWidgets(); addWidgets(); } private void addWidgets() { setLayout(new GridBagLayout()); GridBagConstraints gc = new GridBagConstraints(); gc.weightx = 100; gc.weighty = 100; gc.gridx = 0; gc.gridy = 0; gc.gridwidth = 1; gc.gridheight = 1; add(new JLabel("Options")); gc.gridy = 1; add(simpleButton, gc); gc.gridy = 2; add(nearestButton, gc); gc.gridy = 3; add(neighborButton, gc); gc.gridy = 4; add(intervalButton, gc); gc.gridx = 1; gc.gridy = 0; add(new JLabel("Options")); gc.gridy = 2; add(nearestField, gc); gc.gridy = 3; add(neighborField, gc); gc.gridy = 4; add(intervalField, gc); } private void configureWidgets() { // fields to enter data in nearestField = new JTextField("" + nearestAverager.getNum()); neighborField = new JTextField("" + neighborAverager.getNum()); intervalField = new JTextField("" + intervalAverager.getWidth()); nearestField.setColumns(5); neighborField.setColumns(5); intervalField.setColumns(5); // buttons to choose from... // type = new ButtonGroup(); simpleButton = new JButton("No Averaging"); simpleButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { karyoView.setSimpleAveraging(); } }); // type.add(simpleButton); nearestButton = new JButton("Nearest :"); nearestButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { karyoView.setNearestAveraging(Integer.parseInt(nearestField.getText())); } }); neighborButton = new JButton("Neighbor :"); neighborButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { karyoView.setNeighborAveraging(Integer.parseInt(neighborField.getText())); } }); intervalButton = new JButton("Interval :"); intervalButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Double width = new Double(intervalField.getText()); karyoView.setIntervalAveraging(width.doubleValue()); } }); } public void synchronizeTo() { } public void synchronizeFrom() { } } } /** * just for parsing chromosome info... */ class KaryoParseException extends Exception { public KaryoParseException(String m) { super(m); } } --- NEW FILE: KaryoDrawer.java --- /* BEGIN_HEADER Java TreeView * * $Author: rqluk $ * $RCSfile: KaryoDrawer.java,v $i * $Revision: 1.1 $ * $Date: 2006/08/16 19:13:49 $ * $Name: $ * * This file is part of Java TreeView * Copyright (C) 2001-2003 Alok Saldanha, All Rights Reserved. Modified by Alex Segal 2004/08/13. Modifications Copyright (C) Lawrence Berkeley Lab. * * This software is provided under the GNU GPL Version 2. In particular, * * 1) If you modify a source file, make a comment in it containing your name and the date. * 2) If you distribute a modified version, you must do it under the GPL 2. * 3) Developers are encouraged but not required to notify the Java TreeView maintainers at al...@ge... when they make a useful addition. It would be nice if significant contributions could be merged into the main distribution. * * A full copy of the license can be found in gpl.txt or online at * http://www.gnu.org/licenses/gpl.txt * * END_HEADER */ package edu.stanford.genetics.treeview.plugin.karyoview; import java.awt.*; import java.util.Observable; import java.util.Observer; import edu.stanford.genetics.treeview.*; /** * This is observable because it signals changes to the drawer * it is an observer of the selection. */ public class KaryoDrawer extends Observable implements Observer { /* * begin state variables and accessors */ /** * The genome to render */ private Genome genome; /** Setter for genome */ public void setGenome(Genome genome) { this.genome = genome; setChanged(); } /** Getter for genome */ public Genome getGenome() { return genome; } /** * The colors to render with. */ private KaryoColorSet karyoColorSet = new KaryoColorSet("KaryoDrawerColorSet"); /** Setter for karyoColorSet */ private void setKaryoColorSet(KaryoColorSet karyoColorSet) { this.karyoColorSet = karyoColorSet; } /** Getter for karyoColorSet */ public KaryoColorSet getKaryoColorSet() { return karyoColorSet; } /** * The selection model to indicate. */ private TreeSelectionI geneSelection; /** Setter for geneSelection */ public void setGeneSelection(TreeSelectionI geneSelection) { if (this.geneSelection != null) { this.geneSelection.deleteObserver(this); } setChanged(); this.geneSelection = geneSelection; if (this.geneSelection != null) { this.geneSelection.addObserver(this); } } /** Getter for geneSelection */ public TreeSelectionI getGeneSelection() { return geneSelection; } /** * value to skip and not render, since the loci doesn't know it's own expression. */ private double nodata; /** Setter for nodata */ public void setNodata(double nodata) { this.nodata = nodata; } /** Getter for nodata */ public double getNodata() { return nodata; } /** * height and width are the actual width and height of the target area to draw to. */ private int height = 0; /** Setter for height */ public void setHeight(int height) { if (this.height == height) return; this.height = height; setChanged(); } /** Getter for height */ public int getHeight() { return height; } /** * height and width are the actual width and height of the target area to draw to. */ private int width = 0; /** Setter for width */ public void setWidth(int width) { if (this.width == width) return; this.width = width; setChanged(); } /** Getter for width */ public int getWidth() { return width; } /** * pixelPerMap is horizontal pixels per arbitrary unit along chromosome */ private double pixelPerMap; /** Setter for pixelPerMap */ public void setPixelPerMap(double pixelPerMap) { this.pixelPerMap = pixelPerMap; setChanged(); } /** Getter for pixelPerMap */ public double getPixelPerMap() { return pixelPerMap; } /** * pixelPerVal is vertical pixels per expression unit. */ private double pixelPerVal; /** Setter for pixelPerVal */ public void setPixelPerVal(double pixelPerVal) { this.pixelPerVal = pixelPerVal; // System.out.println("setting ppv to " + pixelPerVal + " stack:" ); // Exception e = new Exception(); e.printStackTrace(); setChanged(); } /** Getter for pixelPerVal */ public double getPixelPerVal() { return pixelPerVal; } private int defaultIconSize = 2; /** Setter for iconSize */ public void setIconSize(int iconSize) { configNode.setAttribute("iconSize", iconSize, defaultIconSize); // System.out.println("iconsize changed to " + iconSize); setChanged(); } /** Getter for iconSize */ public int getIconSize() { // System.out.println("iconsize gotten " + iconSize); return configNode.getAttribute("iconSize", defaultIconSize); } private int [] iconSizes = new int [] {1, 3, 5, 7}; /** Setter for iconSizes public void setIconSizes(int [] iconSizes) { this.iconSizes = iconSizes; } */ /** Getter for iconSizes */ public int [] getIconSizes() { return iconSizes; } private int defaultIconType = 2; /** Setter for iconType */ public void setIconType(int iconType) { configNode.setAttribute("iconType", iconType, defaultIconType); setChanged(); } /** Getter for iconType */ public int getIconType() { return configNode.getAttribute("iconType", defaultIconType); } private String [] iconTypes = new String [] {"None", "Circle", "Disc"}; /** Setter for iconTypes */ public void setIconTypes(String [] iconTypes) { this.iconTypes = iconTypes; } /** Getter for iconTypes */ public String [] getIconTypes() { return iconTypes; } /* XXX stuff I should support at some point ... */ /** * base of log for scale lines... */ private double defaultLinesBase = 2.0; /** Setter for linesBase */ public void setLinesBase(double linesBase) { if (getLinesBase() == linesBase) return; configNode.setAttribute("linesBase", linesBase, defaultLinesBase); setChanged(); } /** Getter for linesBase */ public double getLinesBase() { return configNode.getAttribute("linesBase", defaultLinesBase); } /** * include scale lines above? */ private int defaultLinesAbove = 0; /** Setter for linesAbove */ public void setLinesAbove(boolean linesAbove) { if (getLinesAbove() == linesAbove) return; int val = (linesAbove == true)?1:0; configNode.setAttribute("linesAbove", val, defaultLinesAbove); setChanged(); } /** Getter for linesAbove */ public boolean getLinesAbove() { return (configNode.getAttribute("linesAbove", defaultLinesAbove) == 1); } private int defaultLinesMax = 5; /** Setter for linesMax */ public void setLinesMax(int linesMax) { if (getLinesMax() == linesMax) return; configNode.setAttribute("linesMax", linesMax, defaultLinesMax); setChanged(); } /** Getter for linesMax */ public int getLinesMax() { return configNode.getAttribute("linesMax", defaultLinesMax); } /** * include scale lines below? */ private int defaultLinesBelow = 0; /** Setter for linesBelow */ public void setLinesBelow(boolean linesBelow) { if (linesBelow == getLinesBelow()) return; int val = (linesBelow == true)?1:0; configNode.setAttribute("linesBelow", val, defaultLinesBelow); setChanged(); } /** Getter for linesBelow */ public boolean getLinesBelow() { return (configNode.getAttribute("linesBelow", defaultLinesBelow) == 1); } /** * include bar chart? */ private int defaultDrawBars = 1; public boolean getBarChart() { return (configNode.getAttribute("drawBars", defaultDrawBars) == 1); } public void setBarChart(boolean drawBars) { int val = (drawBars == true)?1:0; configNode.setAttribute("drawBars", val, defaultDrawBars); setChanged(); } /** * include line chart? */ private int defaultDrawLines = 0; public boolean getLineChart() { return (configNode.getAttribute("drawLines", defaultDrawLines) == 1); } public void setLineChart(boolean drawLines) { int val = (drawLines == true)?1:0; configNode.setAttribute("drawLines", val, defaultDrawLines); setChanged(); } /* end stuff I should support at some point ... */ /* * end state variables and accessors */ /* Some private state variables... */ private double [] mapValues; public void setMapValue(int i, double val) { if (i < 0) return; setChanged(); mapValues[i] = val; } public void setMapValue(ChromosomeLocus locus, double val) { setMapValue(locus.getCdtIndex(), val); } public double getMapValue(int i) { return mapValues[i]; } /** * removes any pointers to exteral objects to aid GC */ public void cleanup() { geneSelection = null; mapValues = null; } public void update(Observable o, Object arg) { if (o == geneSelection) { setChanged(); notifyObservers(); } else { LogBuffer.println("KaryoView got weird update from " + o); } } public KaryoDrawer(Genome genome, TreeSelectionI selection, double nodata) { super(); // set all locals to default values.... mapValues = new double[selection.getNumIndexes()]; setGenome(genome); setGeneSelection(selection); setNodata(nodata); setHeight(100); setWidth(100); autoScale(); // sets pixelPerMap, pixelPerVal... } /** * Adjusts pixels per map, pixels per value so that the karyoview will * fit nicely in the current width/height combination. */ public void autoScale() { Genome loci = getGenome(); int nChr = loci.getMaxChromosome(); if (nChr == 0) return; Dimension d = new Dimension(width, height / nChr); // System.out.println("Each chromosome gets the follow dimension: " + d); int minNonempty = -1; for (int i = 1; i <= nChr; i++) { if (loci.getChromosome(i).isEmpty() == false) { if (hasData(loci.getChromosome(i))) { minNonempty = i; break; } } } if (minNonempty == -1) { // System.out.println("using min ppv of 1"); setPixelPerMap(1); setPixelPerVal(1); } else { double minPpm = getOptPpm(loci.getChromosome(minNonempty), d); double minPpv = getOptPpv(loci.getChromosome(minNonempty), d); for (int i = minNonempty+1; i <= nChr; i++) { // System.out.println("testing " + i + " best so far is ppm " + minPpm + ", ppv " + minPpv); double ppm = getOptPpm(loci.getChromosome(i), d); double ppv = getOptPpv(loci.getChromosome(i), d); if (ppv != 0) { if (ppm < minPpm) minPpm = ppm; if (ppv < minPpv) minPpv = ppv; } } // System.out.println("using min ppv of " + minPpv); setPixelPerMap(minPpm); setPixelPerVal(minPpv); } } private int border = 5; private int yborder = 0; /** * determine the optimal pixels per map for drawing this chromosome * on the specified dimension */ private double getOptPpv(Chromosome chr, Dimension d) { double opt = 0.0; if (chr.getMaxPosition(ChromosomeLocus.CIRCULAR) == 0.0) { // linear chromosome... double maxVal = getMaxAbsVal(chr.getLeftEnd()); if (maxVal != 0.0) { opt = (d.height - 2 * yborder) / (1.5 * maxVal); } /* double sum = getSumAbsVal(chr.getLeftEnd()); int count = getCount(chr.getLeftEnd()); if (count != 0) { double maxVal = sum / (double)count * (double) 4; opt = (d.height - 2 * yborder) / (2 * maxVal); } */ } return opt; } /** * determine the optimal pixels per map for drawing this chromosome * on the specified dimension */ private boolean hasData(Chromosome chr) { if (chr.getMaxPosition(ChromosomeLocus.CIRCULAR) == 0.0) { // linear chromosome... ChromosomeLocus start = chr.getLeftEnd(); ChromosomeLocus locus = start; do { int cdtIndex = locus.getCdtIndex(); if (cdtIndex >= 0) { double abs = mapValues[cdtIndex]; if (abs == nodata) { // ignore nodata... } else { return true; } } locus = locus.getRight(); } while ((locus != start) && (locus != null)); } return false; } /** * determine the optimal pixels per val for drawing this chromosome * on the specified dimension */ private double getOptPpm(Chromosome chr, Dimension d) { double opt = 0.0; if (chr.getMaxPosition(ChromosomeLocus.CIRCULAR) == 0.0) { // linear chromosome... double maxPos = chr.getMaxPosition(); opt = (d.width - 2 * border) / (2 * maxPos); } return opt; } /** * This function traverses the chromosomes, starting at start and calling getRight() until * it reaches end. It keeps track of and returns the maximum abs value it finds. */ private double getMaxAbsVal(ChromosomeLocus start) { double maxVal = 0.0; if (start == null) return maxVal; ChromosomeLocus locus = start; do { int cdtIndex = locus.getCdtIndex(); if (cdtIndex >= 0) { double abs = mapValues[cdtIndex]; if (abs == nodata) { // ignore nodata... } else { abs = Math.abs(abs); if (abs > maxVal) maxVal = abs; } } locus = locus.getRight(); } while ((locus != start) && (locus != null)); return maxVal; } /** * This function traverses the chromosomes, starting at start and calling getRight() until * it reaches end. It keeps track of and returns the running total abs of the values it finds. */ private double getSumAbsVal(ChromosomeLocus start) { double sum = 0.0; if (start == null) return sum; ChromosomeLocus locus = start; do { int cdtIndex = locus.getCdtIndex(); if (cdtIndex >= 0) { double abs = mapValues[cdtIndex]; if (abs == nodata) { // ignore nodata... } else { abs = Math.abs(abs); sum += abs; } } locus = locus.getRight(); } while ((locus != start) && (locus != null)); return sum; } /** * This function traverses the chromosomes, starting at start and calling getRight() until * it reaches end. It keeps track of and returns the running total non-missing loci it finds. */ private int getCount(ChromosomeLocus start) { int count = 0; if (start == null) return count; ChromosomeLocus locus = start; do { int cdtIndex = locus.getCdtIndex(); if (cdtIndex >= 0) { double abs = mapValues[cdtIndex]; if (abs == nodata) { // ignore nodata... } else { count++; } } locus = locus.getRight(); } while ((locus != start) && (locus != null)); return count; } /** * This not-so-object-oriented code is necessary since I don't want the Chromosome to know about * graphics. I could define a ChromosomeDrawer class with appropriate subclasses, and have to manage * those, but I'm lazy about it. * * @return the position of the locus in pixels, if the centromere is at xcenter. */ private int getLinearPosition(ChromosomeLocus locus, int xcenter) { if (locus == null) return 0; int arm = locus.getArm(); double pos = locus.getPosition(); int x; if (arm == ChromosomeLocus.LEFT) { x = xcenter - (int)(pos * getPixelPerMap()); } else { x = xcenter + (int)(pos * getPixelPerMap()); } return x; } /** * @return the distance of the farthest end from the centromere in pixels */ public int getFarthestEndDistance(Chromosome chr) { int max = 0; if (chr.getMaxPosition(ChromosomeLocus.CIRCULAR) == 0.0) { // linear chromosome... double maxPos = chr.getMaxPosition(); max = (int) (maxPos * getPixelPerMap()); } return max; } public void paintChromosome(Graphics g, LinearChromosome linear, Rectangle destination) { /* don't do this! it prevents the important case of lines overlapping... g.setColor(getKaryoColorSet().getColor("Background")); g.fillRect(destination.x,destination.y,destination.width,destination.height); */ int xcenter = destination.width / 2 + destination.x; int ycenter = destination.height / 2 + destination.y; ChromosomeLocus leftMost = linear.getLeftEnd(); ChromosomeLocus rightMost = linear.getRightEnd(); int leftEnd = getLinearPosition( leftMost, xcenter); int rightEnd = getLinearPosition(rightMost, xcenter); // actual line representing chromosome... g.setColor(getKaryoColorSet().getColor("Genome")); g.drawLine(leftEnd, ycenter, rightEnd, ycenter); if (getLinesAbove() || getLinesBelow()) { int i = 2; // log(0) is undefined, log(1) is always zero. int maxInt = i + getLinesMax(); double base = getLinesBase(); double logE = Math.log(base); double ppv = getPixelPerVal(); double thisval = Math.log(i++) / logE; int thisy = (int) (ppv * thisval); int lasty = 0; g.setColor(getKaryoColorSet().getColor("Line")); // while (thisy < destination.height / 2) { while (i <= maxInt && ((lasty +1 ) < thisy)) { if (getLinesAbove()) g.drawLine(leftEnd, ycenter - thisy, rightEnd, ycenter - thisy); if (getLinesBelow()) g.drawLine(leftEnd, ycenter + thisy, rightEnd, ycenter + thisy); lasty = thisy; thisval = Math.log(i++) / logE; thisy = (int) (ppv * thisval); } } // could use clipRect to speed up... // int minX = clipRect.x; // int maxX = minX + clipRect.width; ChromosomeLocus locus = linear.getLeftEnd(); int lastX = 0; int lastY = 0; ChromosomeLocus lastLocus = null; while (locus != null) { int cdtIndex = locus.getCdtIndex(); if (cdtIndex >= 0 ) { int x = getLinearPosition(locus, xcenter); // XXX need to do a better job here... if ((geneSelection != null) && geneSelection.isIndexSelected(cdtIndex)) { g.setColor(getKaryoColorSet().getColor("Highlight")); int diameter = iconSizes[ getIconSize()]; int radius = (diameter - 1) /2; switch (getIconType()) { case 0: break; case 1: g.fillOval(x-radius, ycenter - radius, diameter,diameter); break; case 2: g.drawOval(x-radius, ycenter - radius, diameter,diameter); break; } } // could use clipRect to speed up... // if (x < minX) continue; // if (x > maxX) continue; double val = mapValues[cdtIndex]; int yend = ycenter; if (val != nodata) { yend -= (int) (val * getPixelPerVal()); // System.out.println("chr " + locus.getChromosome() + " arm " + arm + " pos " + pos +" val " + val + " length " + val * getPixelPerVal()); if (getBarChart()) { // need to abstract to ColorConverter... if (val > 0 ) { g.setColor(getKaryoColorSet().getColor("Up")); } else { g.setColor(getKaryoColorSet().getColor("Down")); } g.drawLine(x, ycenter, x, yend); } if (getLineChart()) { if (lastLocus != null) { g.setColor(getKaryoColorSet().getColor("Line")); g.drawLine(lastX, lastY, x, yend); } lastLocus = locus; lastX = x; lastY = yend; } } } locus = locus.getRight(); } g.setColor(Color.blue); g.drawOval(xcenter - 3, ycenter - 3, 5,5); } /** * This gets the starting pixel for chromosome chr, where chr is a number from 0 to nchr-1. * If chr == nchr, will return the max pixel */ public int getStartingY(int chr) { int nChromosomes = genome.getMaxChromosome(); if (chr == nChromosomes) { return getHeight(); } if (nChromosomes == 0) { return 0; } return (chr * getHeight())/nChromosomes; } public int minVisibleChromosome(Rectangle clipRect) { int minChr = 0; int nChromosomes = genome.getMaxChromosome(); while (getStartingY(minChr) < clipRect.y) { minChr++; if (minChr == nChromosomes) break; } if (minChr < 2) return 1; return minChr; } public int maxVisibleChromosome(Rectangle clipRect) { int maxChr = 1; int nChromosomes = genome.getMaxChromosome(); while (getStartingY(maxChr) < clipRect.y +clipRect.height) { maxChr++; if (maxChr == nChromosomes) break; } if (maxChr > nChromosomes) maxChr = nChromosomes; return maxChr; } public void paintBackground(Graphics g, Rectangle clipRect) { if (clipRect != null) { g.setColor(getKaryoColorSet().getColor("Background")); g.fillRect(clipRect.x,clipRect.y,clipRect.width,clipRect.height); } } public void paint(Graphics g, Rectangle clipRect) { // background... paintBackground(g, clipRect); // System.out.println("drawing to clip " + clipRect); int... [truncated message content] |