From 577afa99ff4e5f02e564bc0c981901de6bd711ce Mon Sep 17 00:00:00 2001 From: tjc <tjc@ee4ac58c-ac51-4696-9907-e4b3aa274f04> Date: Wed, 2 Mar 2011 16:32:21 +0000 Subject: [PATCH] change zoom out so it switches to a coverage plot git-svn-id: svn+ssh://svn.internal.sanger.ac.uk/repos/svn/pathsoft/artemis/trunk@15638 ee4ac58c-ac51-4696-9907-e4b3aa274f04 --- .../alignment/AbstractGraphPanel.java | 5 +- .../artemis/components/alignment/BamView.java | 274 ++++++++++----- .../components/alignment/CoveragePanel.java | 330 ++++++++++++------ .../components/alignment/SnpPanel.java | 2 +- 4 files changed, 418 insertions(+), 193 deletions(-) diff --git a/uk/ac/sanger/artemis/components/alignment/AbstractGraphPanel.java b/uk/ac/sanger/artemis/components/alignment/AbstractGraphPanel.java index d06e68d6e..17d9d1e01 100644 --- a/uk/ac/sanger/artemis/components/alignment/AbstractGraphPanel.java +++ b/uk/ac/sanger/artemis/components/alignment/AbstractGraphPanel.java @@ -31,6 +31,7 @@ import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import javax.swing.JCheckBox; +import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JMenuItem; import javax.swing.JOptionPane; @@ -49,7 +50,7 @@ public class AbstractGraphPanel extends JPanel protected int userWinSize = 1; protected JPopupMenu popup = new JPopupMenu(); - public void initPopupMenu(final JPanel graphPanel) + public void initPopupMenu(final JPanel graphPanel, JComponent menu) { final JMenuItem setScale = new JMenuItem("Set the Window Size..."); setScale.addActionListener(new ActionListener() @@ -97,7 +98,7 @@ public class AbstractGraphPanel extends JPanel graphPanel.repaint(); } }); - popup.add(setScale); + menu.add(setScale); addMouseListener(new PopupListener()); } diff --git a/uk/ac/sanger/artemis/components/alignment/BamView.java b/uk/ac/sanger/artemis/components/alignment/BamView.java index 630b0298d..3a66ed5bd 100644 --- a/uk/ac/sanger/artemis/components/alignment/BamView.java +++ b/uk/ac/sanger/artemis/components/alignment/BamView.java @@ -148,9 +148,7 @@ public class BamView extends JPanel private boolean isOrientation = false; private boolean isSingle = false; private boolean isSNPs = false; - private boolean isStackView = true; - private boolean isPairedStackView = false; - private boolean isStrandStackView = false; + private boolean isCoverage = false; private boolean isSNPplot = false; @@ -175,18 +173,29 @@ public class BamView extends JPanel private JMenu bamFilesMenu = new JMenu("BAM files"); private JCheckBoxMenuItem logMenuItem = new JCheckBoxMenuItem("Use Log Scale", logScale); - private JCheckBoxMenuItem checkBoxStackView = new JCheckBoxMenuItem("Stack View", isStackView); + + private JCheckBoxMenuItem cbStackView = new JCheckBoxMenuItem("Stack", true); + private JCheckBoxMenuItem cbPairedStackView = new JCheckBoxMenuItem("Paired Stack"); + private JCheckBoxMenuItem cbStrandStackView = new JCheckBoxMenuItem("Strand Stack"); + private JCheckBoxMenuItem cbIsizeStackView = new JCheckBoxMenuItem("Inferred Size", false); + private JCheckBoxMenuItem cbCoverageView = new JCheckBoxMenuItem("Coverage", false); + private JCheckBoxMenuItem cbLastSelected; + + private ButtonGroup buttonGroup = new ButtonGroup(); + private JCheckBoxMenuItem colourByCoverageColour = new JCheckBoxMenuItem("Coverage Plot Colours"); private JCheckBoxMenuItem baseQualityColour = new JCheckBoxMenuItem("Base Quality"); private JCheckBoxMenuItem markInsertions = new JCheckBoxMenuItem("Mark Insertions", true); private AlphaComposite translucent = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f); + private CoveragePanel coverageView = new CoveragePanel(); + /** Used to colour the frames. */ - private Color lightGrey = new Color(200, 200, 200); - private Color darkGreen = new Color(0, 150, 0); - private Color darkOrange = new Color(255,140,0); - private Color deepPink = new Color(139,10,80); + private static Color LIGHT_GREY = new Color(200, 200, 200); + private static Color DARK_GREEN = new Color(0, 150, 0); + private static Color DARK_ORANGE = new Color(255,140,0); + private static Color DEEP_PINK = new Color(139,10,80); private Point lastMousePoint = null; private SAMRecord mouseOverSAMRecord = null; @@ -195,6 +204,7 @@ public class BamView extends JPanel // record of where a mouse drag starts private int dragStart = -1; + private static int MAX_BASES = 26000; private int maxHeight = 800; private boolean concatSequences = false; @@ -270,6 +280,12 @@ public class BamView extends JPanel MultiLineToolTipUI.initialize(); setToolTipText(""); + + buttonGroup.add(cbStackView); + buttonGroup.add(cbPairedStackView); + buttonGroup.add(cbStrandStackView); + buttonGroup.add(cbIsizeStackView); + buttonGroup.add(cbCoverageView); } public String getToolTipText() @@ -392,7 +408,7 @@ public class BamView extends JPanel * Read a SAM or BAM file. * @throws IOException */ - private void readFromBamPicard(int start, int end, int bamIndex) + private void readFromBamPicard(int start, int end, int bamIndex, float pixPerBase) throws IOException { // Open the input file. Automatically detects whether input is SAM or BAM @@ -426,7 +442,7 @@ public class BamView extends JPanel thisEnd = thisLength; //System.out.println("READ "+seqNames.get(i)+" "+thisStart+".."+thisEnd); - iterateOverBam(inputSam, seqNames.get(i), thisStart, thisEnd, bamIndex); + iterateOverBam(inputSam, seqNames.get(i), thisStart, thisEnd, bamIndex, pixPerBase); } lastLen = len; } @@ -434,7 +450,7 @@ public class BamView extends JPanel else { String refName = (String) combo.getSelectedItem(); - iterateOverBam(inputSam, refName, start, end, bamIndex); + iterateOverBam(inputSam, refName, start, end, bamIndex, pixPerBase); } //inputSam.close(); @@ -452,7 +468,7 @@ public class BamView extends JPanel */ private void iterateOverBam(final SAMFileReader inputSam, String refName, int start, int end, - int bamIndex) + int bamIndex, float pixPerBase) { boolean multipleBAM = false; if(bamList.size() > 1) @@ -478,7 +494,12 @@ public class BamView extends JPanel { if(multipleBAM) samRecord.setAttribute("FL", bamIndex); - readsInView.add(samRecord); + + if(isCoverageView(pixPerBase) || isCoverage) + coverageView.addRecord(samRecord); + + if(!isCoverageView(pixPerBase)) + readsInView.add(samRecord); } } @@ -610,11 +631,18 @@ public class BamView extends JPanel end = seqLength; } + boolean changeToStackView = false; MemoryMXBean memory = ManagementFactory.getMemoryMXBean(); if(laststart != start || - lastend != end) + lastend != end || + coverageView.isRedraw()) { + if(isCoverageView(pixPerBase) || isCoverage) + { + coverageView.init(this, pixPerBase, start, end); + } + synchronized (this) { try @@ -626,11 +654,11 @@ public class BamView extends JPanel readsInView = new Vector<SAMRecord>(); else readsInView.clear(); - + for(int i=0; i<bamList.size(); i++) { if(!hideBamList.contains(i)) - readFromBamPicard(start, end, i); + readFromBamPicard(start, end, i, pixPerBase); } float heapFractionUsedAfter = (float) ((float) memory.getHeapMemoryUsage().getUsed() / (float) memory.getHeapMemoryUsage().getMax()); @@ -640,19 +668,17 @@ public class BamView extends JPanel // System.out.println("Heap memory used "+heapFractionUsedAfter); if ((heapFractionUsedAfter - heapFractionUsedBefore) > 0.06 - && !isStackView && heapFractionUsedAfter > 0.8) + && !isStackView() && heapFractionUsedAfter > 0.8) { - checkBoxStackView.setSelected(true); - isStackView = true; + cbStackView.setSelected(true); changeToStackView = true; } - if ((!isStackView && !isStrandStackView) - || pixPerBase * 1.08f >= ALIGNMENT_PIX_PER_BASE) + if((!isStackView() && !isStrandStackView()) || isBaseAlignmentView(pixPerBase)) { Collections.sort(readsInView, new SAMRecordComparator()); } - else if( (isStackView || isStrandStackView) && + else if( (isStackView() || isStrandStackView()) && bamList.size() > 1) { // merge multiple BAM files @@ -679,18 +705,26 @@ public class BamView extends JPanel //System.out.println(start+".."+end+" " + // "sequence length = "+getSequenceLength()+ // " pixPerBase="+pixPerBase); - + laststart = start; lastend = end; - if(showBaseAlignment) + + if(showBaseAlignment) drawBaseAlignment(g2, seqLength, pixPerBase, start, end); else { - if(isStackView) + if(isCoverageView(pixPerBase)) + { + int hgt = jspView.getVisibleRect().height; + g2.translate(0, getHeight()-hgt); + coverageView.draw(g2, getWidth(), hgt); + coverageView.drawMax(g2); + } + else if(isStackView()) drawStackView(g2, seqLength, pixPerBase, start, end); - else if(isPairedStackView) + else if(isPairedStackView()) drawPairedStackView(g2, seqLength, pixPerBase, start, end); - else if(isStrandStackView) + else if(isStrandStackView()) drawStrandStackView(g2, seqLength, pixPerBase, start, end); else drawLineView(g2, seqLength, pixPerBase, start, end); @@ -778,7 +812,7 @@ public class BamView extends JPanel refSeq = bases.getSubSequence(new Range(refSeqStart, seqEnd), Bases.FORWARD).toUpperCase(); - g2.setColor(lightGrey); + g2.setColor(LIGHT_GREY); g2.fillRect(0, ypos-11, mainPanel.getWidth(), 11); drawSelectionRange(g2, ALIGNMENT_PIX_PER_BASE, start, end); g2.setColor(Color.black); @@ -925,7 +959,7 @@ public class BamView extends JPanel if(insertions == null) insertions = new Hashtable<Integer, String>(); - g2.setColor(deepPink); + g2.setColor(DEEP_PINK); int xscreen = (refPos+1)*ALIGNMENT_PIX_PER_BASE; insertions.put(xscreen, @@ -1001,9 +1035,9 @@ public class BamView extends JPanel if (baseQuality < 10) g2.setColor(Color.blue); else if (baseQuality < 20) - g2.setColor(darkGreen); + g2.setColor(DARK_GREEN); else if (baseQuality < 30) - g2.setColor(darkOrange); + g2.setColor(DARK_ORANGE); else g2.setColor(Color.black); } @@ -1189,7 +1223,7 @@ public class BamView extends JPanel ypos = ypos-2; } else - g2.setColor(darkGreen); + g2.setColor(DARK_GREEN); lstStart = recordStart; lstEnd = recordEnd; @@ -1283,7 +1317,7 @@ public class BamView extends JPanel ypos = ypos + ystep; } else - g2.setColor(darkGreen); + g2.setColor(DARK_GREEN); lstStart = recordStart; lstEnd = recordEnd; @@ -1494,7 +1528,7 @@ public class BamView extends JPanel if(colourByCoverageColour.isSelected()) g2.setColor(getColourByCoverageColour(samRecord)); else if(offTheTop) - g2.setColor(darkOrange); + g2.setColor(DARK_ORANGE); else if(samRecord.getReadNegativeStrandFlag() && samRecord.getMateNegativeStrandFlag()) // strand of the query (1 for reverse) g2.setColor(Color.red); @@ -2143,104 +2177,83 @@ public class BamView extends JPanel menu.add(new JSeparator()); JMenu viewMenu = new JMenu("Views"); - ButtonGroup group = new ButtonGroup(); - final JCheckBoxMenuItem checkBoxPairedStackView = new JCheckBoxMenuItem("Paired Stack View"); - final JCheckBoxMenuItem checkBoxStrandStackView = new JCheckBoxMenuItem("Strand Stack View"); - final JCheckBoxMenuItem checkIsizeStackView = new JCheckBoxMenuItem("Inferred Size View", false); - checkBoxStackView.setFont(checkIsizeStackView.getFont()); - baseQualityColour.setFont(checkIsizeStackView.getFont()); - colourByCoverageColour.setFont(checkIsizeStackView.getFont()); - markInsertions.setFont(checkIsizeStackView.getFont()); - - group.add(checkBoxStackView); - group.add(checkBoxPairedStackView); - group.add(checkBoxStrandStackView); - group.add(checkIsizeStackView); - - checkIsizeStackView.addActionListener(new ActionListener() + cbStackView.setFont(cbIsizeStackView.getFont()); + baseQualityColour.setFont(cbIsizeStackView.getFont()); + colourByCoverageColour.setFont(cbIsizeStackView.getFont()); + markInsertions.setFont(cbIsizeStackView.getFont()); + + cbIsizeStackView.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { laststart = -1; lastend = -1; - if(checkIsizeStackView.isSelected()) - { - isStackView = false; - isPairedStackView = false; - isStrandStackView = false; + if(isIsizeStackView()) logMenuItem.setEnabled(true); - } repaint(); } }); - viewMenu.add(checkIsizeStackView); + viewMenu.add(cbIsizeStackView); - checkBoxStackView.addActionListener(new ActionListener() + cbStackView.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { laststart = -1; lastend = -1; - isStackView = !isStackView; - - if(isStackView) - { - isPairedStackView = !isStackView; - isStrandStackView = !isStackView; - checkBoxPairedStackView.setSelected(!isStackView); - checkBoxStrandStackView.setSelected(!isStackView); + + if(isStackView()) logMenuItem.setEnabled(false); - } repaint(); } }); - viewMenu.add(checkBoxStackView); + viewMenu.add(cbStackView); - checkBoxPairedStackView.addActionListener(new ActionListener() + cbPairedStackView.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { laststart = -1; lastend = -1; - isPairedStackView = !isPairedStackView; - if(isPairedStackView) - { - isStackView = !isPairedStackView; - isStrandStackView = !isPairedStackView; - checkBoxStackView.setSelected(!isPairedStackView); - checkBoxStrandStackView.setSelected(!isPairedStackView); + if(cbPairedStackView.isSelected()) logMenuItem.setEnabled(false); - } repaint(); } }); - viewMenu.add(checkBoxPairedStackView); + viewMenu.add(cbPairedStackView); - checkBoxStrandStackView.addActionListener(new ActionListener() + cbStrandStackView.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { laststart = -1; lastend = -1; - isStrandStackView = !isStrandStackView; - - if(isStrandStackView) + + if(isStrandStackView()) { - isStackView = !isStrandStackView; - isPairedStackView = !isStrandStackView; - checkBoxStackView.setSelected(!isStrandStackView); - checkBoxPairedStackView.setSelected(!isStrandStackView); setViewportMidPoint(); logMenuItem.setEnabled(false); } repaint(); } }); - viewMenu.add(checkBoxStrandStackView); + viewMenu.add(cbStrandStackView); + + cbCoverageView.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + laststart = -1; + lastend = -1; + repaint(); + } + }); + viewMenu.add(cbCoverageView); + menu.add(viewMenu); final JCheckBoxMenuItem checkBoxSNPs = new JCheckBoxMenuItem("SNP marks"); @@ -2325,6 +2338,8 @@ public class BamView extends JPanel { isCoverage = !isCoverage; coveragePanel.setVisible(isCoverage); + laststart = -1; + lastend = -1; repaint(); } }); @@ -2387,7 +2402,7 @@ public class BamView extends JPanel } menu.add(new JSeparator()); - logMenuItem.setFont(checkIsizeStackView.getFont()); + logMenuItem.setFont(cbIsizeStackView.getFont()); menu.add(logMenuItem); logMenuItem.addActionListener(new ActionListener() { @@ -2407,7 +2422,13 @@ public class BamView extends JPanel new SAMRecordFilter(BamView.this); } }); - menu.add(new JSeparator()); + + // + JMenu coverageMenu = new JMenu("Coverage Options"); + coverageView.init(this, 0.f, 0, 0); + coverageView.createMenus(coverageMenu, BamView.this); + viewMenu.add(new JSeparator()); + viewMenu.add(coverageMenu); } public void setVisible(boolean visible) @@ -2442,7 +2463,7 @@ public class BamView extends JPanel this.nbasesInView = nbasesInView; float pixPerBase = getPixPerBaseByWidth(); - if(pixPerBase*1.08f >= ALIGNMENT_PIX_PER_BASE) + if(isBaseAlignmentView(pixPerBase)) { pixPerBase = ALIGNMENT_PIX_PER_BASE; this.nbasesInView = (int)(mainPanel.getWidth()/pixPerBase); @@ -2457,9 +2478,20 @@ public class BamView extends JPanel } else if(jspView != null) { + if(!cbCoverageView.isSelected() && nbasesInView >= MAX_BASES) + { + cbLastSelected = getSelectedCheckBoxMenuItem(); + cbCoverageView.setSelected(true); + } + else if(cbCoverageView.isSelected() && nbasesInView < MAX_BASES && cbLastSelected != null) + { + cbLastSelected.setSelected(true); + cbLastSelected = null; + } + jspView.setColumnHeaderView(null); - if(!isStrandStackView) + if(!isStrandStackView()) jspView.getVerticalScrollBar().setValue( jspView.getVerticalScrollBar().getMaximum()); showBaseAlignment = false; @@ -2661,6 +2693,63 @@ public class BamView extends JPanel fileIndex = (Integer) samRecord.getAttribute("FL"); return lines[fileIndex].getLineColour(); } + + protected int getMaxBases() + { + return MAX_BASES; + } + + protected void setMaxBases(int max) + { + MAX_BASES = max; + } + + private boolean isStackView() + { + return cbStackView.isSelected(); + } + + private boolean isPairedStackView() + { + return cbPairedStackView.isSelected(); + } + + private boolean isStrandStackView() + { + return cbStrandStackView.isSelected(); + } + + private boolean isCoverageView(float pixPerBase) + { + if(isBaseAlignmentView(pixPerBase)) + return false; + return cbCoverageView.isSelected(); + } + + private boolean isIsizeStackView() + { + return cbIsizeStackView.isSelected(); + } + + private boolean isBaseAlignmentView(float pixPerBase) + { + if(pixPerBase*1.08f >= ALIGNMENT_PIX_PER_BASE) + return true; + return false; + } + + private JCheckBoxMenuItem getSelectedCheckBoxMenuItem() + { + if(isStackView()) + return cbStackView; + if(isPairedStackView()) + return cbPairedStackView; + if(isStrandStackView()) + return cbStrandStackView; + if(isIsizeStackView()) + return cbIsizeStackView; + return cbCoverageView; + } private Selection getSelection() { @@ -2672,6 +2761,11 @@ public class BamView extends JPanel return readsInView; } + protected Hashtable<String, int[]> getCoveragePlotData() + { + return coverageView.getPlotData(); + } + protected int getBasesInView() { return nbasesInView; diff --git a/uk/ac/sanger/artemis/components/alignment/CoveragePanel.java b/uk/ac/sanger/artemis/components/alignment/CoveragePanel.java index 62336f11c..130ddaf4c 100644 --- a/uk/ac/sanger/artemis/components/alignment/CoveragePanel.java +++ b/uk/ac/sanger/artemis/components/alignment/CoveragePanel.java @@ -29,6 +29,8 @@ import java.awt.Color; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Graphics2D; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.geom.GeneralPath; @@ -36,8 +38,13 @@ import java.util.Enumeration; import java.util.Hashtable; import java.util.List; -import javax.swing.JCheckBoxMenuItem; +import javax.swing.JCheckBox; +import javax.swing.JComponent; +import javax.swing.JLabel; import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JTextField; import net.sf.samtools.AlignmentBlock; import net.sf.samtools.SAMRecord; @@ -45,46 +52,62 @@ import net.sf.samtools.SAMRecord; public class CoveragePanel extends AbstractGraphPanel { private static final long serialVersionUID = 1L; - private BamView jamView; + private BamView bamView; private static LineAttributes lines[]; private boolean includeCombined = false; + private Hashtable<String, int[]> plots; + private int combinedCoverage[]; + private int nBins; + private int windowSize; + private int max; + private boolean redraw = false; + private boolean setMaxBases = false; - public CoveragePanel(final BamView jamView) + protected CoveragePanel(final BamView bamView) + { + this(); + this.bamView = bamView; + //initPopupMenu(this, popup); + createMenus(popup, this); + addMouseListener(new PopupListener()); + } + + protected CoveragePanel() { super(); setBackground(Color.white); - this.jamView = jamView; - initPopupMenu(this); - - JMenuItem configure = new JMenuItem("Configure..."); + addMouseListener(new PopupListener()); + setMaxBases = true; + } + + protected void createMenus(JComponent menu, final JPanel panel) + { + JMenuItem configure = new JMenuItem("Configure Line(s)..."); configure.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { - int size = jamView.bamList.size(); + int size = bamView.bamList.size(); if(includeCombined) size++; lines = - LineAttributes.configurePlots(jamView.bamList, + LineAttributes.configurePlots(bamView.bamList, getLineAttributes(size), CoveragePanel.this); } }); - popup.add(configure); + menu.add(configure); - if(jamView.bamList.size() > 1) + JMenuItem optMenu = new JMenuItem("Options..."); + optMenu.addActionListener(new ActionListener() { - final JCheckBoxMenuItem showCombined = new JCheckBoxMenuItem("Show Combined Plot", false); - showCombined.addActionListener(new ActionListener() + public void actionPerformed(ActionEvent e) { - public void actionPerformed(ActionEvent e) - { - includeCombined = showCombined.isSelected(); - repaint(); - } - }); - popup.add(showCombined); - } + defineOpts(); + panel.repaint(); + } + }); + menu.add(optMenu); } /** @@ -94,15 +117,27 @@ import net.sf.samtools.SAMRecord; { super.paintComponent(g); Graphics2D g2 = (Graphics2D)g; - - List<SAMRecord> readsInView = jamView.getReadsInView(); + List<SAMRecord> readsInView = bamView.getReadsInView(); if(readsInView == null) return; - - int windowSize; + drawPlot(g2); + drawMax(g2); + } + + protected void init(BamView bamView, float pixPerBase, int start, int end) + { + this.bamView = bamView; + setPixPerBase(pixPerBase); + setStartAndEnd(start, end); + init(); + redraw = false; + } + + private void init() + { if(autoWinSize) { - windowSize = (jamView.getBasesInView()/200); + windowSize = (bamView.getBasesInView()/300); userWinSize = windowSize; } else @@ -110,84 +145,97 @@ import net.sf.samtools.SAMRecord; if(windowSize < 1) windowSize = 1; + nBins = Math.round((end-start+1.f)/windowSize); - int nBins = Math.round((end-start+1.f)/windowSize); - int max = drawPlot(g2, nBins, windowSize); - + plots = new Hashtable<String, int[]>(); + combinedCoverage = null; + if(includeCombined) + { + combinedCoverage = new int[nBins]; + for(int k=0; k<combinedCoverage.length; k++) + combinedCoverage[k] = 0; + plots.put("-1", combinedCoverage); + } + max = 0; + } + + protected void drawMax(Graphics2D g2) + { String maxStr = Float.toString(max/windowSize); FontMetrics fm = getFontMetrics(getFont()); g2.setColor(Color.black); - int xpos = getWidth() - fm.stringWidth(maxStr) - - jamView.getJspView().getVerticalScrollBar().getWidth(); + int xpos = bamView.getJspView().getVisibleRect().width - fm.stringWidth(maxStr) - + bamView.getJspView().getVerticalScrollBar().getWidth(); g2.drawString(maxStr, xpos, fm.getHeight()); } + private void drawPlot(Graphics2D g2) + { + init(); + max = 0; + plots = bamView.getCoveragePlotData(); + Enumeration<String> plotEum = plots.keys(); + while(plotEum.hasMoreElements()) + { + String fileName = (String) plotEum.nextElement(); + int[] thisPlot = plots.get(fileName); + for(int i=1; i<thisPlot.length; i++) + if(max < thisPlot[i]) + max = thisPlot[i]; + } + + draw(g2, getWidth(), getHeight()); + } - private int drawPlot(Graphics2D g2, int nBins, int windowSize) + protected void addRecord(SAMRecord thisRead) { - List<SAMRecord> readsInView = jamView.getReadsInView(); - List<String> bamList = jamView.bamList; - final Hashtable<String, Integer[]> plots = new Hashtable<String, Integer[]>(); + int offset = bamView.getSequenceOffset(thisRead.getReferenceName()); + offset = offset - bamView.getBaseAtStartOfView(); + + String fileName; + if(bamView.bamList.size() > 1) + fileName = bamView.bamList.get((Integer) thisRead.getAttribute("FL")); + else + fileName = bamView.bamList.get(0); + int coverage[] = plots.get(fileName); - Integer combinedCoverage[] = null; - if(includeCombined) + if(coverage == null) { - combinedCoverage = new Integer[nBins]; - for(int k=0; k<combinedCoverage.length; k++) - combinedCoverage[k] = 0; - plots.put("-1", combinedCoverage); - } + coverage = new int[nBins]; + for(int k=0; k<coverage.length; k++) + coverage[k] = 0; + plots.put(fileName, coverage); + } - int max = 0; - for(int i=0; i<readsInView.size(); i++) + List<AlignmentBlock> blocks = thisRead.getAlignmentBlocks(); + for(int j=0; j<blocks.size(); j++) { - SAMRecord thisRead = readsInView.get(i); - int offset = jamView.getSequenceOffset(thisRead.getReferenceName()); - offset = offset - jamView.getBaseAtStartOfView(); - - String fileName; - if(bamList.size() > 1) - fileName = bamList.get((Integer) thisRead.getAttribute("FL")); - else - fileName = bamList.get(0); - Integer coverage[] = plots.get(fileName); - - if(coverage == null) - { - coverage = new Integer[nBins]; - for(int k=0; k<coverage.length; k++) - coverage[k] = 0; - plots.put(fileName, coverage); - } - - List<AlignmentBlock> blocks = thisRead.getAlignmentBlocks(); - for(int j=0; j<blocks.size(); j++) + AlignmentBlock block = blocks.get(j); + for(int k=0; k<block.getLength(); k++) { - AlignmentBlock block = blocks.get(j); - - for(int k=0; k<block.getLength(); k++) + int pos = block.getReferenceStart() + k + offset; + int bin = pos/windowSize; + if(bin < 0 || bin > nBins-1) + continue; + + coverage[bin]+=1; + if(coverage[bin] > max) + max = coverage[bin]; + + if(includeCombined) { - int pos = block.getReferenceStart() + k + offset; - int bin = pos/windowSize; - if(bin < 0 || bin > nBins-1) - continue; - - coverage[bin]+=1; - if(coverage[bin] > max) - max = coverage[bin]; - - if(includeCombined) - { - combinedCoverage[bin]+=1; - if(combinedCoverage[bin] > max) - max = combinedCoverage[bin]; - } - } - } + combinedCoverage[bin]+=1; + if(combinedCoverage[bin] > max) + max = combinedCoverage[bin]; + } + } } - - int size = jamView.bamList.size(); + } + + protected void draw(Graphics2D g2, int wid, int hgt) + { + int size = bamView.bamList.size(); if(includeCombined) { lines = getLineAttributes(size+1); @@ -200,13 +248,13 @@ import net.sf.samtools.SAMRecord; while(plotEum.hasMoreElements()) { String fileName = (String) plotEum.nextElement(); - Integer[] thisPlot = plots.get(fileName); - + int[] thisPlot = plots.get(fileName); + int index; if(fileName.equals("-1")) index = lines.length-1; else - index = bamList.indexOf(fileName); + index = bamView.bamList.indexOf(fileName); g2.setColor(lines[index].getLineColour()); @@ -216,10 +264,10 @@ import net.sf.samtools.SAMRecord; for(int i=1; i<thisPlot.length; i++) { int x0 = (int) ((((i-1)*(windowSize)) - windowSize/2.f)*pixPerBase); - int y0 = (int) (getHeight() - (((float)thisPlot[i-1]/(float)max)*getHeight())); + int y0 = (int) (hgt - (((float)thisPlot[i-1]/(float)max)*hgt)); int x1 = (int) (((i*(windowSize)) - windowSize/2.f)*pixPerBase); - int y1 = (int) (getHeight() - (((float)thisPlot[i]/(float)max)*getHeight())); - + int y1 = (int) (hgt - (((float)thisPlot[i]/(float)max)*hgt)); + g2.drawLine(x0, y0, x1, y1); } } @@ -228,28 +276,26 @@ import net.sf.samtools.SAMRecord; g2.setComposite(makeComposite(0.75f)); GeneralPath shape = new GeneralPath(); - shape.moveTo(0,getHeight()); + shape.moveTo(0,hgt); for(int i=0; i<thisPlot.length; i++) { float xpos = ((i*(windowSize)) - windowSize/2.f)*pixPerBase; shape.lineTo(xpos, - getHeight() - (((float)thisPlot[i]/(float)max)*getHeight())); + hgt - (((float)thisPlot[i]/(float)max)*hgt)); } - shape.lineTo(getWidth(),getHeight()); + shape.lineTo(wid,hgt); g2.fill(shape); } } - return max; } private AlphaComposite makeComposite(float alpha) { int type = AlphaComposite.SRC_OVER; return(AlphaComposite.getInstance(type, alpha)); - } - - + } + protected static LineAttributes[] getLineAttributes(int nsize) { if(lines == null) @@ -263,4 +309,88 @@ import net.sf.samtools.SAMRecord; } return lines; } + + /** + * @return the redraw + */ + protected boolean isRedraw() + { + return redraw; + } + + private void defineOpts() + { + final JPanel opts = new JPanel(new GridBagLayout()); + final GridBagConstraints c = new GridBagConstraints(); + + final JTextField newBaseMax = new JTextField(Integer.toString(bamView.getMaxBases()), 10); + c.gridy = 0; + if(setMaxBases) + { + final JLabel labMax1 = new JLabel("Zoom level before switching"); + final JLabel labMax2 = new JLabel("to coverage view (in bases):"); + c.anchor = GridBagConstraints.WEST; + opts.add(labMax1, c); + c.gridy = c.gridy+1; + opts.add(labMax2, c); + opts.add(newBaseMax, c); + } + + final JTextField newWinSize = new JTextField(Integer.toString(userWinSize), 10); + final JLabel lab = new JLabel("Window size:"); + lab.setEnabled(!autoWinSize); + newWinSize.setEnabled(!autoWinSize); + + c.gridy = c.gridy+1; + c.anchor = GridBagConstraints.EAST; + opts.add(lab, c); + opts.add(newWinSize, c); + + final JCheckBox autoSet = new JCheckBox("Automatically set window size", autoWinSize); + autoSet.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + lab.setEnabled(!autoSet.isSelected()); + newWinSize.setEnabled(!autoSet.isSelected()); + } + }); + c.anchor = GridBagConstraints.WEST; + c.gridy = c.gridy+1; + c.gridwidth = GridBagConstraints.REMAINDER; + opts.add(autoSet, c); + + final JCheckBox showCombined = new JCheckBox("Show Combined Plot", includeCombined); + if(bamView.bamList.size() == 1) + showCombined.setEnabled(false); + c.gridy = c.gridy+1; + opts.add(showCombined, c); + + String window_options[] = { "OK", "Cancel" }; + int select = JOptionPane.showOptionDialog(null, opts, "Coverage Options", + JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, null, + window_options, window_options[0]); + + if(select == 1) + return; + + redraw = true; + autoWinSize = autoSet.isSelected(); + includeCombined = showCombined.isSelected(); + try + { + userWinSize = Integer.parseInt(newWinSize.getText().trim()); + if(setMaxBases) + bamView.setMaxBases(Integer.parseInt(newBaseMax.getText().trim())); + } + catch (NumberFormatException nfe) + { + return; + } + } + + protected Hashtable<String, int[]> getPlotData() + { + return plots; + } } \ No newline at end of file diff --git a/uk/ac/sanger/artemis/components/alignment/SnpPanel.java b/uk/ac/sanger/artemis/components/alignment/SnpPanel.java index 80b4349bd..453ae6fae 100644 --- a/uk/ac/sanger/artemis/components/alignment/SnpPanel.java +++ b/uk/ac/sanger/artemis/components/alignment/SnpPanel.java @@ -60,7 +60,7 @@ import net.sf.samtools.SAMRecord; setBackground(Color.white); this.bamView = bamView; this.bases = bases; - initPopupMenu(this); + initPopupMenu(this, popup); JMenuItem configure = new JMenuItem("Filter by Base Quality..."); configure.addActionListener(new ActionListener() -- GitLab