Skip to content
Snippets Groups Projects
Commit b0c7373e authored by tjc's avatar tjc
Browse files

add SNP graph

git-svn-id: svn+ssh://svn.internal.sanger.ac.uk/repos/svn/pathsoft/artemis/trunk@13445 ee4ac58c-ac51-4696-9907-e4b3aa274f04
parent e0a198a3
No related branches found
No related tags found
No related merge requests found
......@@ -149,11 +149,13 @@ public class BamView extends JPanel
private boolean isPairedStackView = false;
private boolean isStrandStackView = false;
private boolean isCoverage = false;
private boolean isSNPplot = false;
private FeatureDisplay feature_display;
private Selection selection;
private JPanel mainPanel;
private CoveragePanel coveragePanel;
private SnpPanel snpPanel;
private boolean showScale = true;
private boolean logScale = false;
private Ruler ruler;
......@@ -665,6 +667,12 @@ public class BamView extends JPanel
coveragePanel.setPixPerBase(pixPerBase);
coveragePanel.repaint();
}
if(isSNPplot)
{
snpPanel.setStartAndEnd(start, end);
snpPanel.setPixPerBase(pixPerBase);
snpPanel.repaint();
}
}
if(waitingFrame.isVisible())
......@@ -1892,6 +1900,10 @@ public class BamView extends JPanel
coveragePanel = new CoveragePanel(this);
bottomPanel.add(coveragePanel, BorderLayout.CENTER);
//
snpPanel = new SnpPanel(this, bases);
bottomPanel.add(snpPanel, BorderLayout.NORTH);
if(feature_display == null)
{
scrollBar = new JScrollBar(JScrollBar.HORIZONTAL, 1, nbasesInView, 1,
......@@ -1902,6 +1914,10 @@ public class BamView extends JPanel
public void adjustmentValueChanged(AdjustmentEvent e)
{
repaint();
if(coveragePanel != null)
coveragePanel.repaint();
if(snpPanel != null)
snpPanel.repaint();
}
});
bottomPanel.add(scrollBar, BorderLayout.SOUTH);
......@@ -1910,6 +1926,8 @@ public class BamView extends JPanel
mainPanel.add(bottomPanel, BorderLayout.SOUTH);
coveragePanel.setPreferredSize(new Dimension(900, 100));
coveragePanel.setVisible(false);
snpPanel.setPreferredSize(new Dimension(900, 100));
snpPanel.setVisible(false);
jspView.getVerticalScrollBar().setValue(
jspView.getVerticalScrollBar().getMaximum());
......@@ -2096,7 +2114,7 @@ public class BamView extends JPanel
viewMenu.add(checkBoxStrandStackView);
menu.add(viewMenu);
final JCheckBoxMenuItem checkBoxSNPs = new JCheckBoxMenuItem("SNPs");
final JCheckBoxMenuItem checkBoxSNPs = new JCheckBoxMenuItem("SNP marks");
//
JMenu colourMenu = new JMenu("Colour By");
colourMenu.add(colourByCoverageColour);
......@@ -2156,8 +2174,10 @@ public class BamView extends JPanel
}
});
showMenu.add(markInsertions);
showMenu.add(new JSeparator());
menu.add(showMenu);
//
JMenu graphMenu = new JMenu("Graph");
JCheckBoxMenuItem checkBoxCoverage = new JCheckBoxMenuItem("Coverage");
checkBoxCoverage.addActionListener(new ActionListener()
{
......@@ -2168,8 +2188,21 @@ public class BamView extends JPanel
repaint();
}
});
showMenu.add(checkBoxCoverage);
menu.add(showMenu);
graphMenu.add(checkBoxCoverage);
JCheckBoxMenuItem checkBoxSNP = new JCheckBoxMenuItem("SNP");
checkBoxSNP.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
isSNPplot = !isSNPplot;
snpPanel.setVisible(isSNPplot);
repaint();
}
});
graphMenu.add(checkBoxSNP);
menu.add(graphMenu);
if(feature_display != null)
{
......@@ -2250,7 +2283,7 @@ public class BamView extends JPanel
jspView.getViewport().setViewPosition(p);
}
private int getBaseAtStartOfView()
protected int getBaseAtStartOfView()
{
if(feature_display != null)
return feature_display.getForwardBaseAtLeftEdge();
......@@ -2581,12 +2614,20 @@ public class BamView extends JPanel
int width = feature_display.getMaxVisibleBases();
setZoomLevel(width);
repaint();
if(coveragePanel != null && coveragePanel.isVisible())
coveragePanel.repaint();
if(snpPanel != null && snpPanel.isVisible())
snpPanel.repaint();
}
else
{
setDisplay(event.getStart(),
event.getStart()+feature_display.getMaxVisibleBases(), event);
repaint();
if(coveragePanel != null && coveragePanel.isVisible())
coveragePanel.repaint();
if(snpPanel != null && snpPanel.isVisible())
snpPanel.repaint();
}
}
......
/* SnpPanel
*
* created: 2010
*
* This file is part of Artemis
*
* Copyright(C) 2010 Genome Research Limited
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or(at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
package uk.ac.sanger.artemis.components.alignment;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.GeneralPath;
import java.util.List;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JTextField;
import uk.ac.sanger.artemis.io.Range;
import uk.ac.sanger.artemis.sequence.Bases;
import uk.ac.sanger.artemis.util.OutOfRangeException;
import net.sf.samtools.AlignmentBlock;
import net.sf.samtools.SAMRecord;
public class SnpPanel extends JPanel
{
private static final long serialVersionUID = 1L;
private int start;
private int end;
private float pixPerBase;
private BamView bamView;
private JPopupMenu popup;
private Bases bases;
private float minBaseQualityFilter = 0;
public SnpPanel(final BamView bamView, Bases bases)
{
super();
setBackground(Color.white);
this.bamView = bamView;
this.bases = bases;
popup = new JPopupMenu();
JMenuItem configure = new JMenuItem("Filter by Base Quality...");
configure.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
// filter by base quality
JTextField filterField = new JTextField(Float.toString(minBaseQualityFilter));
int status = JOptionPane.showConfirmDialog(SnpPanel.this,
filterField, "Base Quality Filter",
JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
if(status == JOptionPane.CANCEL_OPTION)
return;
try
{
minBaseQualityFilter = Float.parseFloat(filterField.getText());
}
catch(NumberFormatException nfe)
{
JOptionPane.showMessageDialog(SnpPanel.this, nfe.getMessage(),
"Number Format", JOptionPane.WARNING_MESSAGE);
}
}
});
popup.add(configure);
addMouseListener(new PopupListener());
}
/**
* Override
*/
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
if(bases == null)
return;
List<SAMRecord> readsInView = bamView.getReadsInView();
if(readsInView == null)
return;
int windowSize = (bamView.getBasesInView()/300);
if(windowSize < 1)
windowSize = 1;
int nBins = Math.round((end-start+1.f)/windowSize);
int max = drawPlot(g2, nBins, windowSize);
String maxStr = Float.toString(max/windowSize);
FontMetrics fm = getFontMetrics(getFont());
g2.setColor(Color.black);
int xpos = getWidth() - fm.stringWidth(maxStr) -
bamView.getJspView().getVerticalScrollBar().getWidth();
g2.drawString(maxStr, xpos, fm.getHeight());
}
private int drawPlot(Graphics2D g2, int nBins, int windowSize)
{
//lines = CoveragePanel.getLineAttributes(bamView.bamList.size());
List<SAMRecord> readsInView = bamView.getReadsInView();
int snpCount[] = new int[nBins];
for(int i=0; i<snpCount.length; i++)
snpCount[i] = 0;
int max = 0;
for(int i=0; i<readsInView.size(); i++)
{
SAMRecord thisRead = readsInView.get(i);
max = calculateSNPs(thisRead, windowSize, nBins, snpCount, max);
}
g2.setColor(Color.red);
g2.setStroke(new BasicStroke(1.f));
if(windowSize == 1)
{
GeneralPath shape = new GeneralPath();
shape.moveTo(0,getHeight());
for(int i=0; i<snpCount.length; i++)
{
float xpos1 = ((i*windowSize) )*pixPerBase;
float xpos2 = ((i*windowSize) + windowSize)*pixPerBase;
shape.lineTo(xpos1,getHeight());
shape.lineTo(xpos1,
getHeight() - (((float)snpCount[i]/(float)max)*getHeight()));
shape.lineTo(xpos2,
getHeight() - (((float)snpCount[i]/(float)max)*getHeight()));
shape.lineTo(xpos2,getHeight());
}
shape.lineTo(getWidth(),getHeight());
g2.fill(shape);
}
else
{
for(int i=1; i<snpCount.length; i++)
{
int x0 = (int) (((i*windowSize) - windowSize/2.f)*pixPerBase);
int y0 = (int) (getHeight() - (((float)snpCount[i-1]/(float)max)*getHeight()));
int x1 = (int) ((((i+1)*windowSize) - windowSize/2.f)*pixPerBase);
int y1 = (int) (getHeight() - (((float)snpCount[i]/(float)max)*getHeight()));
g2.drawLine(x0, y0, x1, y1);
}
}
return max;
}
/**
* Display the SNPs for the given read.
* @param g2
* @param thisRead
* @param pixPerBase
* @param ypos
*/
private int calculateSNPs(SAMRecord thisRead,
int windowSize,
int nBins,
int[] snpCount,
int max)
{
int thisStart = thisRead.getAlignmentStart();
int thisEnd = thisRead.getAlignmentEnd();
int offset = bamView.getSequenceOffset(thisRead.getReferenceName());
// use alignment blocks of the contiguous alignment of
// subsets of read bases to a reference sequence
List<AlignmentBlock> blocks = thisRead.getAlignmentBlocks();
byte[] phredQuality = thisRead.getBaseQualities();
try
{
char[] refSeq = bases.getSubSequenceC(
new Range(thisStart+offset, thisEnd+offset), Bases.FORWARD);
byte[] readSeq = thisRead.getReadBases();
offset = offset - bamView.getBaseAtStartOfView();
for(int i=0; i<blocks.size(); i++)
{
AlignmentBlock block = blocks.get(i);
for(int j=0; j<block.getLength(); j++)
{
int readPos = block.getReadStart()-1+j;
int refPos = block.getReferenceStart()+j;
if (Character.toUpperCase(refSeq[refPos-thisStart]) != readSeq[readPos])
{
if(phredQuality[readPos] < minBaseQualityFilter)
continue;
int bin = (int)((refPos+offset) / windowSize);
if(bin < 0 || bin > nBins-1)
continue;
snpCount[bin]+=1;
if(snpCount[bin] > max)
max = snpCount[bin];
}
}
}
}
catch (OutOfRangeException e)
{
e.printStackTrace();
}
return max;
}
protected void setStartAndEnd(int start, int end)
{
this.start = start;
this.end = end;
}
protected void setPixPerBase(float pixPerBase)
{
this.pixPerBase = pixPerBase;
}
/**
* Popup menu listener
*/
class PopupListener extends MouseAdapter
{
JMenuItem gotoMateMenuItem;
JMenuItem showDetails;
public void mouseClicked(MouseEvent e)
{
}
public void mousePressed(MouseEvent e)
{
maybeShowPopup(e);
}
public void mouseReleased(MouseEvent e)
{
maybeShowPopup(e);
}
private void maybeShowPopup(MouseEvent e)
{
if(e.isPopupTrigger())
{
popup.show(e.getComponent(),
e.getX(), e.getY());
}
}
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment