diff --git a/uk/ac/sanger/artemis/components/alignment/BamView.java b/uk/ac/sanger/artemis/components/alignment/BamView.java index 1f09dc1e9b742ed31f67b59c2fbca2da935a5757..7abe2392c55cede07dc78150b89e57bbaa4aae07 100644 --- a/uk/ac/sanger/artemis/components/alignment/BamView.java +++ b/uk/ac/sanger/artemis/components/alignment/BamView.java @@ -126,6 +126,7 @@ public class BamView extends JPanel private String bam; private SAMRecordFlagPredicate samRecordFlagPredicate; + private SAMRecordMapQPredicate samRecordMapQPredicate; private Bases bases; private JScrollPane jspView; @@ -251,18 +252,22 @@ public class BamView extends JPanel mouseOverSAMRecord.getReadName() + "\n" + mouseOverSAMRecord.getAlignmentStart() + ".." + mouseOverSAMRecord.getAlignmentEnd() + "\nisize=" + - mouseOverSAMRecord.getInferredInsertSize() + "\nrname="; + mouseOverSAMRecord.getInferredInsertSize() + "\nmapq=" + + mouseOverSAMRecord.getMappingQuality()+"\nrname="+ + mouseOverSAMRecord.getReferenceName(); - if(mouseOverSAMRecord.getProperPairFlag() && !mouseOverSAMRecord.getMateUnmappedFlag()) + if( mouseOverSAMRecord.getReadPairedFlag() && + mouseOverSAMRecord.getProperPairFlag() && + !mouseOverSAMRecord.getMateUnmappedFlag()) { msg = msg + - mouseOverSAMRecord.getReferenceName() + "\nstrand (read/mate): "+ + "\nstrand (read/mate): "+ (mouseOverSAMRecord.getReadNegativeStrandFlag() ? "-" : "+")+" / "+ (mouseOverSAMRecord.getMateNegativeStrandFlag() ? "-" : "+"); } else msg = msg + - mouseOverSAMRecord.getReferenceName() + "\nstrand (read/mate): "+ + "\nstrand (read/mate): "+ (mouseOverSAMRecord.getReadNegativeStrandFlag() ? "-" : "+"); if(msg != null && mouseOverInsertion != null) @@ -446,7 +451,9 @@ public class BamView extends JPanel if( samRecordFlagPredicate == null || !samRecordFlagPredicate.testPredicate(samRecord)) { - readsInView.add(samRecord); + if(samRecordMapQPredicate == null || + samRecordMapQPredicate.testPredicate(samRecord)) + readsInView.add(samRecord); } if(cnt > checkMemAfter) @@ -2058,7 +2065,7 @@ public class BamView extends JPanel new SAMRecordFilter(BamView.this); } }); - + menu.add(new JSeparator()); } public void setVisible(boolean visible) @@ -2532,6 +2539,7 @@ public class BamView extends JPanel viewDetail.appendString("Length "+thisSAMRecord.getReadLength()+"\n", Level.DEBUG); viewDetail.appendString("Reference Name "+thisSAMRecord.getReferenceName()+"\n", Level.DEBUG); viewDetail.appendString("Inferred Size "+thisSAMRecord.getInferredInsertSize()+"\n", Level.DEBUG); + viewDetail.appendString("Mapping Quality "+thisSAMRecord.getMappingQuality()+"\n", Level.DEBUG); if(thisSAMRecord.getProperPairFlag() && !thisSAMRecord.getMateUnmappedFlag()) { @@ -2579,6 +2587,19 @@ public class BamView extends JPanel this.samRecordFlagPredicate = samRecordFlagPredicate; } + protected SAMRecordMapQPredicate getSamRecordMapQPredicate() + { + return samRecordMapQPredicate; + } + + protected void setSamRecordMapQPredicate( + SAMRecordMapQPredicate samRecordMapQPredicate) + { + laststart = -1; + lastend = -1; + this.samRecordMapQPredicate = samRecordMapQPredicate; + } + class PairedRead { SAMRecord sam1; diff --git a/uk/ac/sanger/artemis/components/alignment/SAMRecordFilter.java b/uk/ac/sanger/artemis/components/alignment/SAMRecordFilter.java index db00c329fc06397e403890b8944340ff27697b18..f716302e838635d76ef2a5673d78ad0a4b4feedf 100644 --- a/uk/ac/sanger/artemis/components/alignment/SAMRecordFilter.java +++ b/uk/ac/sanger/artemis/components/alignment/SAMRecordFilter.java @@ -1,30 +1,89 @@ package uk.ac.sanger.artemis.components.alignment; -import java.awt.GridLayout; +import java.awt.Dimension; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Point; +import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JFrame; -import javax.swing.JOptionPane; +import javax.swing.JLabel; import javax.swing.JPanel; +import javax.swing.JSeparator; +import javax.swing.JTextField; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; -import uk.ac.sanger.artemis.components.Utilities; - - +/** + * Filter reads bases on their mapping quality (mapq) or the + * flags that are set in the BAM file. + */ class SAMRecordFilter extends JPanel { private static final long serialVersionUID = 1L; public SAMRecordFilter(final BamView bamView) { - super(); + super(new GridBagLayout()); int nflags = SAMRecordFlagPredicate.FLAGS.length; - setLayout(new GridLayout(nflags+1, 2)); - + GridBagConstraints c = new GridBagConstraints(); + + int nrows = 0; + c.ipadx = 5; + c.ipady = 2; + c.gridx = 0; + c.gridwidth = 2; + c.anchor = GridBagConstraints.WEST; + c.gridy = nrows++; + + // MAPQ + add(new JLabel("Mappying quality (mapq) cut-off:"),c); + + c.gridy = nrows++; + c.gridwidth = 1; + final JTextField cutOff = new JTextField(12); + if(bamView.getSamRecordMapQPredicate() != null) + cutOff.setText(Integer.toString(bamView.getSamRecordMapQPredicate().cutOff)); + + cutOff.addKeyListener(new KeyAdapter() + { + public void keyPressed(KeyEvent e) + { + if (e.getKeyCode() == KeyEvent.VK_ENTER) + setQualityCutOff(cutOff, bamView); + } + }); + add(cutOff,c); + + c.gridx = 1; + final JButton setCutOff = new JButton("SET"); + setCutOff.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + setQualityCutOff(cutOff, bamView); + } + }); + add(setCutOff,c); + + // FLAGS + c.gridwidth = 2; + c.gridx = 0; + c.gridy = nrows++; + add(new JSeparator(),c); + + c.gridy = nrows++; + add(new JLabel("Reads can be filtered using the FLAG column in the BAM file."),c); + c.gridy = nrows++; + add(new JLabel("Selecting any of the options below hides the reads with that"),c); + c.gridy = nrows++; + add(new JLabel("flag set."),c); final JCheckBox flagCheck[] = new JCheckBox[nflags]; final SAMRecordFlagPredicate predicate = bamView.getSamRecordFlagPredicate(); @@ -44,10 +103,12 @@ class SAMRecordFilter extends JPanel filterChange(bamView, flagCheck); } }); - add(flagCheck[j]); + + c.gridy = nrows++; + add(flagCheck[j], c); } - final JFrame f = new JFrame("Filter Out Reads Based on Flag"); + final JFrame f = new JFrame("Filter Settings"); JButton closeFrame = new JButton("Close"); closeFrame.addActionListener(new ActionListener() { @@ -56,14 +117,51 @@ class SAMRecordFilter extends JPanel f.dispose(); } }); - add(closeFrame); + c.gridx = 1; + c.gridy = nrows++; + c.fill = GridBagConstraints.NONE; + add(closeFrame, c); f.getContentPane().add(this); f.pack(); - Utilities.centreFrame(f); + + rightJustifyFrame(f); f.setVisible(true); } + private void rightJustifyFrame(JFrame frame) + { + final Dimension screen = Toolkit.getDefaultToolkit().getScreenSize(); + int yPos = (screen.height - frame.getSize().height) / 2; + int xPos = screen.width - frame.getSize().width; + if(yPos < 10) + yPos = 10; + + frame.setLocation(new Point(xPos, yPos)); + } + + private void setQualityCutOff(final JTextField cutOff, + final BamView bamView) + { + String cutOffStr = cutOff.getText().trim(); + if(cutOffStr.equals("")) + bamView.setSamRecordMapQPredicate(null); + else + { + try + { + SAMRecordMapQPredicate predicate = + new SAMRecordMapQPredicate(Integer.parseInt(cutOffStr)); + bamView.setSamRecordMapQPredicate(predicate); + } + catch(NumberFormatException nfe) + { + bamView.setSamRecordMapQPredicate(null); + } + } + bamView.repaint(); + } + private void filterChange(final BamView bamView, final JCheckBox flagCheck[]) { diff --git a/uk/ac/sanger/artemis/components/alignment/SAMRecordMapQPredicate.java b/uk/ac/sanger/artemis/components/alignment/SAMRecordMapQPredicate.java new file mode 100644 index 0000000000000000000000000000000000000000..60136aecfaad7147627e6cdc84888b826bd60c86 --- /dev/null +++ b/uk/ac/sanger/artemis/components/alignment/SAMRecordMapQPredicate.java @@ -0,0 +1,52 @@ +/* SAMRecordMapQPredicate + * + * This file is part of Artemis + * + * Copyright (C) 2009 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 net.sf.samtools.SAMRecord; + +/** + * Test the SAMRecord mapping quality - mapq flag. + **/ +public class SAMRecordMapQPredicate implements SAMRecordPredicate +{ + protected int cutOff; + + public SAMRecordMapQPredicate(int cutOff) + { + this.cutOff = cutOff; + } + + /** + * Test the given SAMRecord against this predicate. + * @param feature The SAMRecord to test the predicate against. + * @return Return true if and only if this predicate is true for the given + * SAMRecord. + **/ + public boolean testPredicate (final SAMRecord samRecord) + { + if(samRecord.getMappingQuality() > cutOff) + return true; + return false; + } +} + +