diff --git a/uk/ac/sanger/artemis/components/alignment/BamView.java b/uk/ac/sanger/artemis/components/alignment/BamView.java index e610135d095c1a6f217884ff079058ddecc3565d..3ead683c1405093fa72b98e77e1f4772b395a765 100644 --- a/uk/ac/sanger/artemis/components/alignment/BamView.java +++ b/uk/ac/sanger/artemis/components/alignment/BamView.java @@ -35,6 +35,8 @@ import java.awt.FlowLayout; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Graphics2D; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.Point; import java.awt.Rectangle; @@ -87,6 +89,7 @@ import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; +import javax.swing.JRadioButton; import javax.swing.JScrollBar; import javax.swing.JScrollPane; import javax.swing.JSeparator; @@ -152,7 +155,7 @@ public class BamView extends JPanel private HashMap<String, Integer> offsetLengths; private Vector<String> seqNames = new Vector<String>(); protected List<String> bamList; - private List<Integer> hideBamList = new Vector<Integer>(); + protected List<Integer> hideBamList = new Vector<Integer>(); private SAMRecordPredicate samRecordFlagPredicate; private SAMRecordMapQPredicate samRecordMapQPredicate; @@ -2352,36 +2355,7 @@ public class BamView extends JPanel { if(feature_display == null) return; - - final Box yBox = Box.createVerticalBox(); - final TextFieldInt threshold = new TextFieldInt(); - final TextFieldInt minSize = new TextFieldInt(); - final TextFieldInt minBams = new TextFieldInt(); - - threshold.setValue(6); - minSize.setValue(6); - minBams.setValue(bamList.size()); - - yBox.add(new JLabel("Minimum number of reads:")); - yBox.add(threshold); - yBox.add(new JLabel("Minimum number of BAMs for reads to be present in:")); - yBox.add(minBams); - yBox.add(new JLabel("Minimum feature size:")); - yBox.add(minSize); - - int status = - JOptionPane.showConfirmDialog(BamView.this, yBox, - "Options", JOptionPane.OK_CANCEL_OPTION); - if(status == JOptionPane.CANCEL_OPTION) - return; - - if(minBams.getValue() > bamList.size()) - minBams.setValue(bamList.size()); - - new MappedReads(feature_display, (String)combo.getSelectedItem(), - samFileReaderHash, bamList, seqNames, offsetLengths, - concatSequences, seqLengths, samRecordFlagPredicate, samRecordMapQPredicate, - threshold.getValue(), minSize.getValue(), minBams.getValue(), true); + new CreateFeatures(groupsFrame); } }); @@ -3690,7 +3664,101 @@ public class BamView extends JPanel { SAMRecord sam1; SAMRecord sam2; - } + } + + class CreateFeatures + { + CreateFeatures(final GroupBamFrame groupsFrame) + { + final TextFieldInt threshold = new TextFieldInt(); + final TextFieldInt minSize = new TextFieldInt(); + final TextFieldInt minBams = new TextFieldInt(); + + threshold.setValue(6); + minSize.setValue(6); + minBams.setValue( (groupsFrame.getNumberOfGroups() == 1 ? + bamList.size() : groupsFrame.getMaximumBamsInGroup()) ); + + final JPanel gridPanel = new JPanel(new GridBagLayout()); + GridBagConstraints c = new GridBagConstraints(); + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.HORIZONTAL; + c.gridx = 0; + c.gridy = 0; + + gridPanel.add(new JLabel("Minimum number of reads:"), c); + c.gridy++; + gridPanel.add(threshold, c); + + c.gridy++; + gridPanel.add(new JSeparator(), c); + c.gridy++; + gridPanel.add(new JLabel("Minimum number of BAMs for reads to be present in:"), c); + c.gridy++; + gridPanel.add(minBams, c); + + JRadioButton useAllBams = new JRadioButton("out of all BAMs", (groupsFrame.getNumberOfGroups() == 1)); + JRadioButton useGroup = new JRadioButton("within a group", (groupsFrame.getNumberOfGroups() != 1)); + + if(groupsFrame.getNumberOfGroups() == 1) + useGroup.setEnabled(false); + + ButtonGroup group = new ButtonGroup(); + group.add(useAllBams); + group.add(useGroup); + + Box xBox = Box.createHorizontalBox(); + xBox.add(useAllBams); + xBox.add(useGroup); + xBox.add(Box.createHorizontalGlue()); + c.gridy++; + gridPanel.add(xBox, c); + + c.gridy++; + gridPanel.add(new JSeparator(), c); + c.gridy++; + gridPanel.add(new JLabel("Minimum feature size:"), c); + c.gridy++; + gridPanel.add(minSize, c); + + int status = + JOptionPane.showConfirmDialog(feature_display, gridPanel, + "Options", JOptionPane.OK_CANCEL_OPTION); + if(status == JOptionPane.CANCEL_OPTION) + return; + + if(!useGroup.isSelected() && minBams.getValue() > bamList.size()) + { + status = + JOptionPane.showConfirmDialog(feature_display, + "The minimum number of BAMs setting can not be\n"+ + "greater than the total number of BAM files.\n"+ + "Set this to the number of BAMs (i.e. "+bamList.size()+").", + "Options", JOptionPane.OK_CANCEL_OPTION); + if(status == JOptionPane.CANCEL_OPTION) + return; + minBams.setValue(bamList.size()); + } + else if(useGroup.isSelected() && minBams.getValue() > groupsFrame.getMaximumBamsInGroup()) + { + status = + JOptionPane.showConfirmDialog(feature_display, + "Minimum number of BAMs setting can not be greater than\n"+ + "the total number of BAM files found in any of the groups.\n"+ + "Set this to the greatest number of BAM files in any\n"+ + "group (i.e. "+groupsFrame.getMaximumBamsInGroup()+").", + "Options", JOptionPane.OK_CANCEL_OPTION); + if(status == JOptionPane.CANCEL_OPTION) + return; + minBams.setValue(groupsFrame.getMaximumBamsInGroup()); + } + + new MappedReads((String)combo.getSelectedItem(),BamView.this, samFileReaderHash, + seqNames, offsetLengths, concatSequences, seqLengths, + (useGroup.isSelected() ? groupsFrame : null), + threshold.getValue(), minSize.getValue(), minBams.getValue(), true); + } + } public static void main(String[] args) { diff --git a/uk/ac/sanger/artemis/components/alignment/GroupBamFrame.java b/uk/ac/sanger/artemis/components/alignment/GroupBamFrame.java index f953cf0e2ce56c880cc3c4a1269e9355b3d063fe..148a80d90a4ed68ec98c554fea6bd47aa9e29caa 100644 --- a/uk/ac/sanger/artemis/components/alignment/GroupBamFrame.java +++ b/uk/ac/sanger/artemis/components/alignment/GroupBamFrame.java @@ -191,18 +191,73 @@ class GroupBamFrame extends JFrame bamPanel.add(new JLabel(bamView.getImageIcon(col)), c); c.gridx = 2; - JComboBox groupList = new JComboBox( groups ); - bamPanel.add(groupList, c); + JComboBox groupCombo = new JComboBox( groups ); + bamPanel.add(groupCombo, c); if(bamGroupMap.containsKey(cbBam)) - groupList.setSelectedItem( + groupCombo.setSelectedItem( (String) bamGroupMap.get(cbBam).getSelectedItem()); - bamGroupMap.put(cbBam, groupList); + bamGroupMap.put(cbBam, groupCombo); } } } + /** + * For a give BAM file return the group it belongs to. + * @param bamName + * @return + */ + protected String getGroupName(final String bamName) + { + Iterator<JCheckBoxMenuItem> it = bamGroupMap.keySet().iterator(); + while(it.hasNext()) + { + JCheckBoxMenuItem cbs = it.next(); + if(cbs.getText().equals(bamName)) + return (String) bamGroupMap.get(cbs).getSelectedItem(); + } + return null; + } + + protected int getNumberOfGroups() + { + return groups.length; + } + + /** + * Find the maximum number of BAM files found in the groups. + * @return + */ + protected int getMaximumBamsInGroup() + { + int max = 1; + int grpMax[] = new int[getNumberOfGroups()]; + for(int i=0; i<grpMax.length; i++) + grpMax[i] = 0; + Iterator<JCheckBoxMenuItem> it = bamGroupMap.keySet().iterator(); + while(it.hasNext()) + { + JCheckBoxMenuItem cbs = it.next(); + String grp = (String) bamGroupMap.get(cbs).getSelectedItem(); + for(int i=0; i<groups.length; i++) + { + if(grp.equals(groups[i])) + { + grpMax[i]++; + break; + } + } + } + + for(int i=0; i<grpMax.length; i++) + { + if(grpMax[i] > max) + max = grpMax[i]; + } + return max; + } + private void updateGroupPanel() { groupPanel.removeAll(); diff --git a/uk/ac/sanger/artemis/components/alignment/MappedReads.java b/uk/ac/sanger/artemis/components/alignment/MappedReads.java index a6ca6f05e2356c85efc4e496de2d58f0842e37be..94fa5a864f6d8537de1725f731b7be5aee20330f 100644 --- a/uk/ac/sanger/artemis/components/alignment/MappedReads.java +++ b/uk/ac/sanger/artemis/components/alignment/MappedReads.java @@ -4,6 +4,7 @@ import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.Point; import java.awt.Toolkit; +import java.io.File; import java.text.DecimalFormat; import java.util.Arrays; import java.util.HashMap; @@ -45,6 +46,7 @@ public class MappedReads private String refName; private Hashtable<String, SAMFileReader> samFileReaderHash; private List<String> bamList; + private List<Integer> hideBamList; private Vector<String> seqNames; private HashMap<String, Integer> offsetLengths; private boolean concatSequences; @@ -187,32 +189,29 @@ public class MappedReads * and anti-sense regions of existing annotations. This should exclude rRNA and * tRNA regions. If two or more BAM files are loaded it should create features * based on the combined read peak span. - * @param feature_display * @param refName + * @param bamView * @param samFileReaderHash * @param bamList * @param seqNames * @param offsetLengths * @param concatSequences * @param seqLengths - * @param samRecordFlagPredicate - * @param samRecordMapQPredicate + * @param groupsFrame * @param threshold * @param minSize * @param minBams * @param contained */ - public MappedReads( - final FeatureDisplay feature_display, + public MappedReads( final String refName, + final BamView bamView, final Hashtable<String, SAMFileReader> samFileReaderHash, - final List<String> bamList, final Vector<String> seqNames, final HashMap<String, Integer> offsetLengths, final boolean concatSequences, final HashMap<String, Integer> seqLengths, - final SAMRecordPredicate samRecordFlagPredicate, - final SAMRecordMapQPredicate samRecordMapQPredicate, + final GroupBamFrame groupsFrame, final int threshold, final int minSize, final int minBams, @@ -220,15 +219,18 @@ public class MappedReads { this.refName = refName; this.samFileReaderHash = samFileReaderHash; - this.bamList = bamList; + this.bamList = bamView.bamList; + this.hideBamList = bamView.hideBamList; this.seqNames = seqNames; this.offsetLengths = offsetLengths; this.concatSequences = concatSequences; this.seqLengths = seqLengths; - this.samRecordFlagPredicate = samRecordFlagPredicate; - this.samRecordMapQPredicate = samRecordMapQPredicate; + this.samRecordFlagPredicate = bamView.getSamRecordFlagPredicate(); + this.samRecordMapQPredicate = bamView.getSamRecordMapQPredicate(); + this.contained = contained; + final FeatureDisplay feature_display = bamView.getFeatureDisplay(); progressBar = new JProgressBar(0, feature_display.getSequenceLength()); progressBar.setValue(0); progressBar.setStringPainted(true); @@ -245,7 +247,7 @@ public class MappedReads centerDialog(); final CalculateNewFeatures cmr = new CalculateNewFeatures( - feature_display, refName, threshold, minSize, minBams); + feature_display, refName, groupsFrame, threshold, minSize, minBams); cmr.start(); dialog.setVisible(true); } @@ -443,15 +445,19 @@ public class MappedReads private int threshold; private int minSize; private int minBams; + private GroupBamFrame groupsFrame; - CalculateNewFeatures(final FeatureDisplay feature_display, - final String refSeq, final int threshold, + CalculateNewFeatures(final FeatureDisplay feature_display, + final String refSeq, + final GroupBamFrame groupsFrame, + final int threshold, final int minSize, final int minBams) { entryGroup = feature_display.getEntryGroup(); bases = feature_display.getBases(); this.refSeq = refSeq; + this.groupsFrame = groupsFrame; this.threshold = threshold; this.minSize = minSize; this.minBams = minBams; @@ -470,12 +476,11 @@ public class MappedReads public Object construct() { - int MAX_BASE_CHUNK = 2000 * 60; + final int MAX_BASE_CHUNK = 2000 * 60; Key excluseKeys[] = { new Key("rRNA"), new Key("tRNA") }; - int seqlen = bases.getLength(); final int beg = 1; - final int end = seqlen; + final int end = bases.getLength(); int fwdStart = -1; int revStart = -1; @@ -483,6 +488,9 @@ public class MappedReads final List<MarkerObj> revMarkers = new Vector<MarkerObj>(); for (int i = 0; i < bamList.size(); i++) { + if(hideBamList.contains(i)) + continue; + for(int j=beg; j<end; j+=MAX_BASE_CHUNK) { progressBar.setValue((j + (i*end)) / bamList.size()); @@ -594,6 +602,31 @@ public class MappedReads if(bamIdxList.size() >= minBams) { + if(groupsFrame != null && minBams > 1) + { + boolean foundMinBams = false; + Hashtable<String, Integer> groupCluster = new Hashtable<String, Integer>(); + for(int j=0; j<bamIdxList.size(); j++) + { + File f = new File(bamList.get(j)); + String grp = groupsFrame.getGroupName( f.getName() ); + if(groupCluster.containsKey(grp)) + { + int val = groupCluster.get(grp)+1; + if(val >= minBams) + { + foundMinBams = true; + break; + } + groupCluster.put(grp, val); + } + else + groupCluster.put(grp, 1); + } + if(!foundMinBams) + continue; + } + // create a new feature try { @@ -638,7 +671,7 @@ public class MappedReads final EntryGroup entryGroup, final int bamIdx) { - if(cnt > threshold && fStart == -1) // START FEATURE + if(cnt >= threshold && fStart == -1) // START FEATURE { boolean exclude = false; try