diff --git a/uk/ac/sanger/artemis/components/alignment/BamView.java b/uk/ac/sanger/artemis/components/alignment/BamView.java index 9b2c0184bad0ef5e90d47c2d9ad687e0851d3f49..1f09dc1e9b742ed31f67b59c2fbca2da935a5757 100644 --- a/uk/ac/sanger/artemis/components/alignment/BamView.java +++ b/uk/ac/sanger/artemis/components/alignment/BamView.java @@ -27,6 +27,7 @@ import java.awt.AlphaComposite; import java.awt.BasicStroke; import java.awt.BorderLayout; import java.awt.Color; +import java.awt.Component; import java.awt.Composite; import java.awt.Dimension; import java.awt.FlowLayout; @@ -124,6 +125,8 @@ public class BamView extends JPanel private Vector<String> seqNames = new Vector<String>(); private String bam; + private SAMRecordFlagPredicate samRecordFlagPredicate; + private Bases bases; private JScrollPane jspView; private JScrollBar scrollBar; @@ -439,7 +442,12 @@ public class BamView extends JPanel { cnt++; SAMRecord samRecord = it.next(); - readsInView.add(samRecord); + + if( samRecordFlagPredicate == null || + !samRecordFlagPredicate.testPredicate(samRecord)) + { + readsInView.add(samRecord); + } if(cnt > checkMemAfter) { @@ -1611,6 +1619,42 @@ public class BamView extends JPanel { topPanel = new JMenuBar(); frame.setJMenuBar((JMenuBar)topPanel); + + JMenu fileMenu = new JMenu("File"); + topPanel.add(fileMenu); + + JMenuItem readBam = new JMenuItem("Read BAM..."); + fileMenu.add(readBam); + readBam.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + String[] s = new String[0]; + BamView.main(s); + BamView.this.setVisible(false); + + Component comp = BamView.this; + + while( !(comp instanceof JFrame) ) + comp = comp.getParent(); + ((JFrame)comp).dispose(); + } + }); + + JMenuItem exit = new JMenuItem("Exit"); + fileMenu.add(exit); + exit.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + int status = JOptionPane.showConfirmDialog(BamView.this, + "Close BamView?", "Close", + JOptionPane.OK_CANCEL_OPTION); + if(status != JOptionPane.OK_OPTION) + return; + System.exit(0); + } + }); } if(seqNames.size() > 1) @@ -2004,6 +2048,17 @@ public class BamView extends JPanel } }); } + + JMenuItem filter = new JMenuItem("Filter by Flag..."); + menu.add(filter); + filter.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + new SAMRecordFilter(BamView.this); + } + }); + } public void setVisible(boolean visible) @@ -2510,6 +2565,19 @@ public class BamView extends JPanel viewDetail.appendString("\nSecond Of Pair "+ (thisSAMRecord.getSecondOfPairFlag() ? "yes" : "no"), Level.DEBUG); } + + protected SAMRecordFlagPredicate getSamRecordFlagPredicate() + { + return samRecordFlagPredicate; + } + + protected void setSamRecordFlagPredicate( + SAMRecordFlagPredicate samRecordFlagPredicate) + { + laststart = -1; + lastend = -1; + this.samRecordFlagPredicate = samRecordFlagPredicate; + } class PairedRead { @@ -2579,6 +2647,4 @@ public class BamView extends JPanel view.jspView.getVerticalScrollBar().getMaximum()); frame.setVisible(true); } - - } diff --git a/uk/ac/sanger/artemis/components/alignment/SAMRecordFilter.java b/uk/ac/sanger/artemis/components/alignment/SAMRecordFilter.java new file mode 100644 index 0000000000000000000000000000000000000000..ecca4ee92bbc16fe98765c5fd879dea3936592c3 --- /dev/null +++ b/uk/ac/sanger/artemis/components/alignment/SAMRecordFilter.java @@ -0,0 +1,76 @@ +package uk.ac.sanger.artemis.components.alignment; + +import java.awt.GridLayout; + +import javax.swing.JCheckBox; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + + +class SAMRecordFilter extends JPanel +{ + private static final long serialVersionUID = 1L; + + public SAMRecordFilter(final BamView bamView) + { + super(); + int nflags = SAMRecordFlagPredicate.FLAGS.length; + setLayout(new GridLayout(nflags, 2)); + + final JCheckBox flagCheck[] = new JCheckBox[nflags]; + for(int j=0; j<nflags; j++) + { + flagCheck[j] = new JCheckBox( + SAMRecordFlagPredicate.FLAGS_DESCRUIPTION[j], false); + flagCheck[j].addChangeListener(new ChangeListener() + { + public void stateChanged(ChangeEvent e) + { + filterChange(bamView, flagCheck); + } + }); + add(flagCheck[j]); + } + + int status = JOptionPane.showConfirmDialog(bamView, + this, "Filter Out Reads Based on Flag", + JOptionPane.OK_CANCEL_OPTION); + + if(status != JOptionPane.OK_OPTION) + return; + } + + private void filterChange(final BamView bamView, + final JCheckBox flagCheck[]) + { + int nflags = SAMRecordFlagPredicate.FLAGS.length; + int flagsChecked = 0; + for(int j=0; j<nflags; j++) + { + if(flagCheck[j].isSelected()) + flagsChecked++; + } + + bamView.setSamRecordFlagPredicate(null); + + if(flagsChecked == 0) + { + bamView.repaint(); + return; + } + + int flagsOn[] = new int[flagsChecked]; + int num = 0; + for(int j=0; j<nflags; j++) + { + if(flagCheck[j].isSelected()) + flagsOn[num++] = SAMRecordFlagPredicate.FLAGS[j]; + } + + bamView.setSamRecordFlagPredicate(new SAMRecordFlagPredicate(flagsOn)); + bamView.repaint(); + } + +} \ No newline at end of file diff --git a/uk/ac/sanger/artemis/components/alignment/SAMRecordFlagPredicate.java b/uk/ac/sanger/artemis/components/alignment/SAMRecordFlagPredicate.java new file mode 100644 index 0000000000000000000000000000000000000000..dfd71f73e895f7ec02c7372fed887b19a35b94b3 --- /dev/null +++ b/uk/ac/sanger/artemis/components/alignment/SAMRecordFlagPredicate.java @@ -0,0 +1,98 @@ +/* SAMRecordPredicate + * + * 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 flag. + **/ +public class SAMRecordFlagPredicate implements SAMRecordPredicate +{ + private int flag[]; + + private static final int READ_PAIRED_FLAG = 0x1; + private static final int PROPER_PAIR_FLAG = 0x2; + private static final int READ_UNMAPPED_FLAG = 0x4; + private static final int MATE_UNMAPPED_FLAG = 0x8; + private static final int READ_STRAND_FLAG = 0x10; + private static final int MATE_STRAND_FLAG = 0x20; + private static final int FIRST_OF_PAIR_FLAG = 0x40; + private static final int SECOND_OF_PAIR_FLAG = 0x80; + private static final int NOT_PRIMARY_ALIGNMENT_FLAG = 0x100; + private static final int READ_FAILS_VENDOR_QUALITY_CHECK_FLAG = 0x200; + private static final int DUPLICATE_READ_FLAG = 0x400; + + protected static final String[] FLAGS_DESCRUIPTION = + { + "Read Paired", + "Proper Pair", + "Read Unmapped", + "Mate Unmapped", + "Read on Negative Strand", + "Mate on Negative Strand", + "First of Pair", + "Second of Pair", + "Not Primary Alignment", + "Read Fails Vendor Quality Check", + "Duplicate Read" + }; + + protected static int[] FLAGS = + { + READ_PAIRED_FLAG, + PROPER_PAIR_FLAG, + READ_UNMAPPED_FLAG, + MATE_UNMAPPED_FLAG, + READ_STRAND_FLAG, + MATE_STRAND_FLAG, + FIRST_OF_PAIR_FLAG, + SECOND_OF_PAIR_FLAG, + NOT_PRIMARY_ALIGNMENT_FLAG, + READ_FAILS_VENDOR_QUALITY_CHECK_FLAG, + DUPLICATE_READ_FLAG + }; + + + public SAMRecordFlagPredicate(int flag[]) + { + this.flag = flag; + } + + /** + * 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) + { + for(int i=0; i<flag.length; i++) + { + if((samRecord.getFlags() & flag[i]) == flag[i]) + return true; + } + return false; + } +} + + diff --git a/uk/ac/sanger/artemis/components/alignment/SAMRecordPredicate.java b/uk/ac/sanger/artemis/components/alignment/SAMRecordPredicate.java new file mode 100644 index 0000000000000000000000000000000000000000..4b9fe5ed10c99013a74c2d848393904260c80e40 --- /dev/null +++ b/uk/ac/sanger/artemis/components/alignment/SAMRecordPredicate.java @@ -0,0 +1,41 @@ +/* SAMRecordPredicate + * + * 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; + +/** + * Each object that implements this interface represents a predicate that can + * be tested with a SAMRecord reference. + **/ + +public interface SAMRecordPredicate { + /** + * 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. + **/ + boolean testPredicate (final SAMRecord samRecord); +} + +