From ee5910a1d0ba890e309345e09df6f74285521477 Mon Sep 17 00:00:00 2001
From: tcarver <tjc>
Date: Tue, 11 Mar 2014 15:04:12 +0000
Subject: [PATCH] refactor for read count and rpkm calculations

---
 .../components/alignment/BamUtils.java        | 208 ++++++++--
 .../artemis/components/alignment/BamView.java |  37 +-
 .../components/alignment/MappedReads.java     | 359 ++++--------------
 .../components/alignment/ReadCount.java       |  40 ++
 .../components/alignment/ReadCountDialog.java |   7 +-
 5 files changed, 319 insertions(+), 332 deletions(-)
 create mode 100644 uk/ac/sanger/artemis/components/alignment/ReadCount.java

diff --git a/uk/ac/sanger/artemis/components/alignment/BamUtils.java b/uk/ac/sanger/artemis/components/alignment/BamUtils.java
index c064061f3..f66801196 100644
--- a/uk/ac/sanger/artemis/components/alignment/BamUtils.java
+++ b/uk/ac/sanger/artemis/components/alignment/BamUtils.java
@@ -28,12 +28,15 @@ import java.util.Hashtable;
 import java.util.List;
 import java.util.Vector;
 
+import javax.swing.JProgressBar;
+
 import net.sf.samtools.AlignmentBlock;
 import net.sf.samtools.SAMFileReader;
 import net.sf.samtools.SAMRecord;
 import net.sf.samtools.util.CloseableIterator;
 import uk.ac.sanger.artemis.Feature;
 import uk.ac.sanger.artemis.FeatureSegmentVector;
+import uk.ac.sanger.artemis.FeatureVector;
 import uk.ac.sanger.artemis.io.Range;
 
 class BamUtils
@@ -69,24 +72,21 @@ class BamUtils
    * @return
    */
   protected static float[] getCount(
+      final BamView bamView,
       final int start,
       final int end,
       final String bam,
-      final String refName,
-      final Hashtable<String, SAMFileReader> samFileReaderHash,
-      final Vector<String> seqNames,
-      final HashMap<String, Integer> offsetLengths,
-      final boolean concatSequences, 
-      final HashMap<String, Integer> seqLengths,
-      final SAMRecordPredicate samRecordFlagPredicate,
-      final SAMRecordMapQPredicate samRecordMapQPredicate,
       final boolean contained,
       final boolean useStrandTag)
   {
+    final Vector<String> seqNames = bamView.getSeqNames();
+    final HashMap<String, Integer> offsetLengths = bamView.getOffsetLengths();
+    final HashMap<String, Integer> seqLengths = bamView.getSeqLengths();
+
     int cnt[] = new int[2];
     cnt[0] = 0;
     cnt[1] = 0;
-    if(concatSequences)
+    if(bamView.isConcatSequences())
     {
       int len = 0;
       int lastLen = 1;
@@ -108,8 +108,7 @@ class BamUtils
           if(thisEnd > thisLength)
             thisEnd = thisLength;
 
-          cnt = count(bam, samFileReaderHash, name, thisStart, thisEnd, 
-              samRecordFlagPredicate, samRecordMapQPredicate, contained, true, useStrandTag);
+          cnt = count(bamView, bam, thisStart, thisEnd, contained, true, useStrandTag);
 
         }
         lastLen = len;
@@ -117,8 +116,7 @@ class BamUtils
     }
     else
     {
-      cnt = count(bam, samFileReaderHash, refName, start, end, 
-          samRecordFlagPredicate, samRecordMapQPredicate, contained, true, useStrandTag);
+      cnt = count(bamView, bam, start, end, contained, true, useStrandTag);
     }
     
     float cntf[] = new float[2];
@@ -127,17 +125,20 @@ class BamUtils
     return cntf;
   }
 
-  protected static int[] count(final String bam, 
-                    final Hashtable<String, SAMFileReader> samFileReaderHash, 
-                    final String refName, 
-                    final int start, 
-                    final int end,
-                    final SAMRecordPredicate samRecordFlagPredicate,
-                    final SAMRecordPredicate samRecordMapQPredicate,
-                    final boolean contained,
-                    final boolean byStrand,
-                    final boolean useStrandTag)
+  protected static int[] count(
+          final BamView bamView,
+          final String bam, 
+          final int start,
+          final int end,
+          final boolean contained,
+          final boolean byStrand,
+          final boolean useStrandTag)
   {
+    final String refName = (String) bamView.getCombo().getSelectedItem();
+    final Hashtable<String, SAMFileReader> samFileReaderHash = bamView.getSamFileReaderHash();
+    final SAMRecordPredicate samRecordFlagPredicate = bamView.getSamRecordFlagPredicate();
+    final SAMRecordPredicate samRecordMapQPredicate = bamView.getSamRecordMapQPredicate();
+
     int cnt[] = new int[2];
     cnt[0] = 0;
     cnt[1] = 0;
@@ -164,29 +165,89 @@ class BamUtils
     it.close();
     return cnt;
   }
+  
+  protected static int[] calc(
+      final BamView bamView, 
+      final String refName, 
+      final int sequenceLength,
+      final boolean useStrandTag,
+      final JProgressBar progressBar)
+  {
+    int mappedReads[] = new int[bamView.bamList.size()];
+    int MAX_BASE_CHUNK = 2000 * 60;
+    boolean contained = false;
+    for (int i = 0; i < sequenceLength; i += MAX_BASE_CHUNK)
+    {
+      if(progressBar != null)
+        progressBar.setValue(i);
+      int sbegc = i;
+      int sendc = i + MAX_BASE_CHUNK - 1;
+
+      for (int j = 0; j < bamView.bamList.size(); j++)
+      {
+        String bam = bamView.bamList.get(j);
+        if (bamView.isConcatSequences())
+        {
+          int len = 0;
+          int lastLen = 1;
+          for (String name : bamView.getSeqNames())
+          {
+            int thisLength = bamView.getSeqLengths().get(name);
+            len += thisLength;
+
+            if ((lastLen >= sbegc && lastLen < sendc)
+                || (len >= sbegc && len < sendc)
+                || (sbegc >= lastLen && sbegc < len)
+                || (sendc >= lastLen && sendc < len))
+            {
+              int offset = bamView.getOffsetLengths().get(name);
+              int thisStart = sbegc - offset;
+              if (thisStart < 1)
+                thisStart = 1;
+              int thisEnd = sendc - offset;
+              if (thisEnd > thisLength)
+                thisEnd = thisLength;
+
+              mappedReads[j] += BamUtils.count(bamView, bam, thisStart, thisEnd, 
+                  contained, false, useStrandTag)[0];
+            }
+            lastLen = len;
+          }
+        }
+        else
+        {
+          mappedReads[j] += BamUtils.count(bamView, bam, sbegc, sendc,
+              contained, false, useStrandTag)[0];
+        }
+      }
+    }
+    return mappedReads;
+  }
 
   /**
    * Return the coverage for each base in a range for the forward and
    * reverse strand.
+   * @param bamView
    * @param bamFile
-   * @param samFileReaderHash
-   * @param refName
    * @param start
    * @param end
-   * @param samRecordFlagPredicate
-   * @param samRecordMapQPredicate
+   * @param concatShift
+   * @param cnt
    * @return
    */
-  protected static int[][] countOverRange(final String bamFile,
-                                          final Hashtable<String, SAMFileReader> samFileReaderHash, 
-                                          final String refName,
-                                          final int start, 
-                                          final int end,
-                                          final int concatShift,
-                                          final int cnt[][],
-                                          final SAMRecordPredicate samRecordFlagPredicate,
-                                          final SAMRecordPredicate samRecordMapQPredicate)
+  protected static int[][] countOverRange(
+      final BamView bamView,
+      final String bamFile, 
+      final int start, 
+      final int end, 
+      final int concatShift, 
+      final int cnt[][])
   {
+    final String refName = (String) bamView.getCombo().getSelectedItem();
+    final Hashtable<String, SAMFileReader> samFileReaderHash = bamView.getSamFileReaderHash();
+    final SAMRecordPredicate samRecordFlagPredicate = bamView.getSamRecordFlagPredicate();
+    final SAMRecordPredicate samRecordMapQPredicate = bamView.getSamRecordMapQPredicate();
+
     SAMFileReader inputSam = samFileReaderHash.get(bamFile);
     final CloseableIterator<SAMRecord> it = 
         inputSam.query(refName, start, end, false);
@@ -226,5 +287,80 @@ class BamUtils
     it.close();
     return cnt;
   }
+
+  /**
+   * For a list of features calculate the read count for each
+   * @param bamView
+   * @param features
+   * @param contained
+   * @param useIntrons
+   * @param useStrandTag
+   * @param mappedReads
+   * @param progressBar
+   * @return
+   */
+  protected static Hashtable<String, List<ReadCount>> calculateMappedReads(
+      final BamView bamView,
+      final FeatureVector features,
+      final boolean contained, 
+      final boolean useIntrons,
+      final boolean useStrandTag,
+      final int mappedReads[],
+      final JProgressBar progressBar)
+  {
+    final Hashtable<String, List<ReadCount>> featureReadCount = 
+        new Hashtable<String, List<ReadCount>>();
+    for (int i = 0; i < features.size(); i++)
+    {
+      final Feature f = features.elementAt(i);
+      if(progressBar != null)
+        progressBar.setValue(i);
+
+      int start = f.getRawFirstBase();
+      int end = f.getRawLastBase();
+      final float fLen = BamUtils.getFeatureLength(f);
+      List<ReadCount> sampleCounts = new Vector<ReadCount>();
+
+      for (int j = 0; j < bamView.bamList.size(); j++)
+      {
+        final String bam = bamView.bamList.get(j);
+        float cnt[] = new float[2];
+
+        cnt = BamUtils.getCount(bamView, start, end, bam, contained, useStrandTag);
+        if (!useIntrons && f.getSegments().size() > 1)
+        {
+          // remove reads contained by intron
+          for (int k = 0; k < f.getSegments().size()-1; k++)
+          {
+            int seg = k;
+            int nextSeg = k+1;
+            if(!f.isForwardFeature())
+            {
+              seg = f.getSegments().size()-k-1;
+              nextSeg = seg-1;
+            }
+
+            start = f.getSegments().elementAt(seg).getRawRange().getEnd();
+            end = f.getSegments().elementAt(nextSeg).getRawRange().getStart();
+
+            float tmpcnt[] = new float[2];
+            tmpcnt = BamUtils.getCount(bamView, start, end, bam, true, useStrandTag);
+            cnt[0] -= tmpcnt[0];
+            cnt[1] -= tmpcnt[1];
+          }
+        }
+        
+        if (mappedReads != null)
+        {
+          cnt[0] = (cnt[0] / (((float) mappedReads[j] / 1000000.f) * (fLen / 1000.f)));
+          cnt[1] = (cnt[1] / (((float) mappedReads[j] / 1000000.f) * (fLen / 1000.f)));
+        }
+
+        sampleCounts.add( new ReadCount(cnt, f.isForwardFeature()) );
+      }
+      featureReadCount.put(ReadCountDialog.getFeatureName(f), sampleCounts);
+    }
+    return featureReadCount;
+  }
 }
 
diff --git a/uk/ac/sanger/artemis/components/alignment/BamView.java b/uk/ac/sanger/artemis/components/alignment/BamView.java
index 8df3a9b15..602196b38 100644
--- a/uk/ac/sanger/artemis/components/alignment/BamView.java
+++ b/uk/ac/sanger/artemis/components/alignment/BamView.java
@@ -2582,9 +2582,7 @@ public class BamView extends JPanel
           return;
         //JOptionPane.showMessageDialog(null, yBox, "Read Count Option", JOptionPane.INFORMATION_MESSAGE);
         
-        new MappedReads(features, (String)combo.getSelectedItem(), samFileReaderHash, bamList,
-            seqNames, offsetLengths, concatSequences, seqLengths, 
-            samRecordFlagPredicate, samRecordMapQPredicate,
+        new MappedReads(BamView.this, features,
             !overlap.isSelected(), spliced.isSelected(), colourByStrandTag.isSelected());
       } 
     });
@@ -2622,16 +2620,12 @@ public class BamView extends JPanel
         else if(bases != null)
           seqlen = bases.getLength();
         
-        new MappedReads(features, (String)combo.getSelectedItem(),
-            samFileReaderHash, bamList, seqNames, offsetLengths, concatSequences, 
-            seqLengths, seqlen, samRecordFlagPredicate, samRecordMapQPredicate,
+        new MappedReads(BamView.this, features, seqlen,
             !overlap.isSelected(), spliced.isSelected(), allRefSeqs.isSelected(),
             colourByStrandTag.isSelected());
-      } 
+      }
     });
-    
-    
-    
+
     final JMenuItem createFeatures = new JMenuItem("Create features from coverage peaks ...");
     analyse.add(createFeatures);
     if(feature_display == null)
@@ -3676,6 +3670,26 @@ public class BamView extends JPanel
     return combo;
   }
   
+  protected Hashtable<String, SAMFileReader>  getSamFileReaderHash()
+  {
+    return samFileReaderHash;
+  }
+  
+  protected Vector<String> getSeqNames()
+  {
+    return seqNames;
+  }
+  
+  protected HashMap<String, Integer> getSeqLengths()
+  {
+    return seqLengths;
+  }
+  
+  protected HashMap<String, Integer> getOffsetLengths()
+  {
+    return offsetLengths;
+  }
+  
   private String getVersion()
   {
     final ClassLoader cl = this.getClass().getClassLoader();
@@ -4275,8 +4289,7 @@ public class BamView extends JPanel
         minBams.setValue(groupsFrame.getMaximumBamsInGroup());
       }
 
-      new MappedReads((String)combo.getSelectedItem(),BamView.this, samFileReaderHash,
-          seqNames, offsetLengths, concatSequences, seqLengths, 
+      new MappedReads(BamView.this,
           (useGroup.isSelected() ? groupsFrame : null), threshold.getValue(), 
           minSize.getValue(), minBams.getValue(), cbOpposite.isSelected(), true);
     }
diff --git a/uk/ac/sanger/artemis/components/alignment/MappedReads.java b/uk/ac/sanger/artemis/components/alignment/MappedReads.java
index 7b13366f2..d47b5283c 100644
--- a/uk/ac/sanger/artemis/components/alignment/MappedReads.java
+++ b/uk/ac/sanger/artemis/components/alignment/MappedReads.java
@@ -9,7 +9,6 @@ import java.awt.event.ActionListener;
 import java.io.File;
 import java.text.DecimalFormat;
 import java.util.Enumeration;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Hashtable;
 import java.util.List;
@@ -37,188 +36,93 @@ import uk.ac.sanger.artemis.sequence.MarkerRange;
 import uk.ac.sanger.artemis.util.OutOfRangeException;
 import uk.ac.sanger.artemis.util.ReadOnlyException;
 
-import net.sf.samtools.SAMFileReader;
-
 public class MappedReads
 {
   private JProgressBar progressBar;
   private JLabel progressTxt = new JLabel();
 
   private FeatureVector features;
-  private String refName;
-  private Hashtable<String, SAMFileReader> samFileReaderHash;
-  private List<String> bamList;
-  private List<Short> hideBamList;
-  private Vector<String> seqNames;
-  private HashMap<String, Integer> offsetLengths;
-  private boolean concatSequences;
-  private HashMap<String, Integer> seqLengths;
-  private int sequenceLength;
-  private SAMRecordPredicate samRecordFlagPredicate;
-  private SAMRecordMapQPredicate samRecordMapQPredicate;
+  private BamView bamView;
+
   private boolean contained;
   private boolean useIntrons;
   private boolean useStrandTag = false;
-  private JDialog dialog = new JDialog((JFrame)null, "Calculating", true);;
-    
-  private int mappedReads[];
+  private JDialog dialog = new JDialog((JFrame)null, "Calculating", true);
     
   /**
    * Calculate the total number of mapped reads.
-   * @param refName
-   * @param samFileReaderHash
-   * @param bamList
-   * @param seqNames
-   * @param offsetLengths
-   * @param concatSequences
-   * @param seqLengths
+   * @param bamView
+   * @param features
    * @param sequenceLength
+   * @param contained
+   * @param useIntrons
+   * @param allRefSeqs
+   * @param useStrandTag
    */
   public MappedReads(
+      final BamView bamView,
       final FeatureVector features,
-      final String refName,
-      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 int sequenceLength,
-      final SAMRecordPredicate samRecordFlagPredicate,
-      SAMRecordMapQPredicate samRecordMapQPredicate,
       final boolean contained, 
       final boolean useIntrons,
       final boolean allRefSeqs,
       final boolean useStrandTag)
   {
     this.features = features;
-    this.refName = refName;
-    this.samFileReaderHash = samFileReaderHash;
-    this.bamList = bamList;
-    this.seqNames = seqNames;
-    this.offsetLengths = offsetLengths;
-    this.concatSequences = concatSequences;
-    this.seqLengths = seqLengths;
-    this.sequenceLength = sequenceLength;
-    this.samRecordFlagPredicate = samRecordFlagPredicate;
-    this.samRecordMapQPredicate = samRecordMapQPredicate;
+    this.bamView = bamView;
     this.contained = contained;
     this.useIntrons = useIntrons;
     this.useStrandTag = useStrandTag;
-    
-    progressBar = new JProgressBar(0, sequenceLength);
-    progressBar.setValue(0);
-    progressBar.setStringPainted(true);
 
-    JPanel panel = new JPanel(new BorderLayout());
-    progressTxt.setText("Total number of mapped reads");
-    panel.add(progressTxt, BorderLayout.NORTH);
-    panel.add(progressBar, BorderLayout.CENTER);
-
-    dialog.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
-    panel.setOpaque(true);
-    dialog.setContentPane(panel);
-    dialog.pack();
-    centerDialog();
-
-    CalculateTotalMappedReads cmr = new CalculateTotalMappedReads(allRefSeqs);
+    showProgress(sequenceLength, "Total number of mapped reads");
+    CalculateTotalMappedReads cmr = new CalculateTotalMappedReads(allRefSeqs, sequenceLength);
     cmr.start();
     dialog.setVisible(true);
   }
 
   /**
    * Read count for selected features.
+   * @param bamView
    * @param features
-   * @param refName
-   * @param samFileReaderHash
-   * @param bamList
-   * @param seqNames
-   * @param offsetLengths
-   * @param concatSequences
-   * @param seqLengths
-   * @param samRecordFlagPredicate
-   * @param samRecordMapQPredicate
    * @param contained
    * @param useIntrons
+   * @param useStrandTag
    */
   public MappedReads(
+      final BamView bamView,
       final FeatureVector features, 
-      final String refName,
-      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 boolean contained, 
       final boolean useIntrons,
       final boolean useStrandTag)
   {
+    this.bamView = bamView;
     this.features = features;
-    this.refName = refName;
-    this.samFileReaderHash = samFileReaderHash;
-    this.bamList = bamList;
-    this.seqNames = seqNames;
-    this.offsetLengths = offsetLengths;
-    this.concatSequences = concatSequences;
-    this.seqLengths = seqLengths;
-    this.samRecordFlagPredicate = samRecordFlagPredicate;
-    this.samRecordMapQPredicate = samRecordMapQPredicate;
+    this.bamView = bamView;
     this.contained = contained;
     this.useIntrons = useIntrons;
     this.useStrandTag = useStrandTag;
-    
-    progressBar = new JProgressBar(0, features.size());
-    progressBar.setValue(0);
-    progressBar.setStringPainted(true);
 
-    JPanel panel = new JPanel(new BorderLayout());
-    progressTxt.setText("Number of mapped reads for "+features.size()+" features");
-    panel.add(progressTxt, BorderLayout.NORTH);
-    panel.add(progressBar, BorderLayout.CENTER);
-
-    panel.setOpaque(true);
-    dialog.setContentPane(panel);
-    dialog.pack();
-    centerDialog();
-    
-    CalculateMappedReads cmr = new CalculateMappedReads();
+    showProgress(features.size(), "Number of mapped reads for "+features.size()+" features");
+    CalculateMappedReads cmr = new CalculateMappedReads(null);
     cmr.start();
     dialog.setVisible(true);
   }
-  
-  
 
   /**
    * Search for new features based on a threshold of read counts in the intergenic 
    * 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 refName
    * @param bamView
-   * @param samFileReaderHash
-   * @param bamList
-   * @param seqNames
-   * @param offsetLengths
-   * @param concatSequences
-   * @param seqLengths
    * @param groupsFrame
    * @param threshold
    * @param minSize
    * @param minBams
-   * @param readsOnOppositeStrand assume reads are on the opposite strand if true.
+   * @param readsOnOppositeStrand
    * @param contained
    */
   public MappedReads(  
-      final String refName,
       final BamView bamView,
-      final Hashtable<String, SAMFileReader> samFileReaderHash,
-      final Vector<String> seqNames,
-      final HashMap<String, Integer> offsetLengths,
-      final boolean concatSequences,
-      final HashMap<String, Integer> seqLengths,
       final GroupBamFrame groupsFrame,
       final int threshold,
       final int minSize,
@@ -226,26 +130,26 @@ public class MappedReads
       final boolean readsOnOppositeStrand,
       final boolean contained)
   {
-    this.refName = refName;
-    this.samFileReaderHash = samFileReaderHash;
-    this.bamList = bamView.bamList;
-    this.hideBamList = bamView.hideBamList;
-    this.seqNames = seqNames;
-    this.offsetLengths = offsetLengths;
-    this.concatSequences = concatSequences;
-    this.seqLengths = seqLengths;
-    this.samRecordFlagPredicate = bamView.getSamRecordFlagPredicate();
-    this.samRecordMapQPredicate = bamView.getSamRecordMapQPredicate();
-    
+    this.bamView = bamView;
     this.contained = contained;
     
     final FeatureDisplay feature_display = bamView.getFeatureDisplay();
-    progressBar = new JProgressBar(0, feature_display.getSequenceLength());
+    showProgress(feature_display.getSequenceLength(), "");
+    final CalculateNewFeatures cmr = new CalculateNewFeatures(
+        feature_display, (String) bamView.getCombo().getSelectedItem(), groupsFrame, 
+        threshold, minSize, minBams, readsOnOppositeStrand);
+    cmr.start();
+    dialog.setVisible(true);
+  }
+  
+  private void showProgress(int progressBarMax, String txt)
+  {
+    progressBar = new JProgressBar(0, progressBarMax);
     progressBar.setValue(0);
     progressBar.setStringPainted(true);
 
     JPanel panel = new JPanel(new BorderLayout());
-    progressTxt.setText("");
+    progressTxt.setText(txt);
     panel.add(progressTxt, BorderLayout.NORTH);
     panel.add(progressBar, BorderLayout.CENTER);
 
@@ -254,11 +158,6 @@ public class MappedReads
     dialog.setContentPane(panel);
     dialog.pack();
     centerDialog();
-    
-    final CalculateNewFeatures cmr = new CalculateNewFeatures(
-        feature_display, refName, groupsFrame, threshold, minSize, minBams, readsOnOppositeStrand);
-    cmr.start();
-    dialog.setVisible(true);
   }
 
   private void centerDialog()
@@ -274,55 +173,18 @@ public class MappedReads
   
   class CalculateMappedReads extends SwingWorker
   {
-    Hashtable<String, List<ReadCount>> featureReadCount;
+    private Hashtable<String, List<ReadCount>> featureReadCount;
+    private int mappedReads[];
+    
+    public CalculateMappedReads(final int mappedReads[])
+    {
+      this.mappedReads = mappedReads;
+    }
+    
     public Object construct()
     {
-      featureReadCount = new Hashtable<String, List<ReadCount>>();
-      for (int i = 0; i < features.size(); i++)
-      {
-        Feature f = features.elementAt(i);
-        progressBar.setValue(i);
-
-        int start = f.getRawFirstBase();
-        int end = f.getRawLastBase();
-        float fLen = BamUtils.getFeatureLength(f);
-        List<ReadCount> sampleCounts = new Vector<ReadCount>();
-
-        for (int j = 0; j < bamList.size(); j++)
-        {
-          String bam = bamList.get(j);
-          float cnt[] = new float[2];
-
-          if (!useIntrons && f.getSegments().size() > 1)
-          {
-            for (int k = 0; k < f.getSegments().size(); k++)
-            {
-              start = f.getSegments().elementAt(k).getRawRange().getStart();
-              end = f.getSegments().elementAt(k).getRawRange().getEnd();
-              float tmpcnt[] = new float[2];
-              tmpcnt = BamUtils.getCount(start, end, bam, refName, samFileReaderHash,
-                  seqNames, offsetLengths, concatSequences, seqLengths,
-                  samRecordFlagPredicate, samRecordMapQPredicate, contained, useStrandTag);
-              cnt[0] += tmpcnt[0];
-              cnt[1] += tmpcnt[1];
-            }
-          }
-          else
-            cnt = BamUtils.getCount(start, end, bam, refName, samFileReaderHash, seqNames,
-                offsetLengths, concatSequences, seqLengths,
-                samRecordFlagPredicate, samRecordMapQPredicate, contained, useStrandTag);
-
-          if (mappedReads != null)
-          {
-            cnt[0] = (cnt[0] / (((float) mappedReads[j] / 1000000.f) * (fLen / 1000.f)));
-            cnt[1] = (cnt[1] / (((float) mappedReads[j] / 1000000.f) * (fLen / 1000.f)));
-          }
-
-          sampleCounts.add( new ReadCount(cnt, f.isForwardFeature()) );
-        }
-        
-        featureReadCount.put(ReadCountDialog.getFeatureName(f), sampleCounts);
-      }
+      featureReadCount = BamUtils.calculateMappedReads(bamView, features, 
+          contained, useIntrons, useStrandTag, mappedReads, progressBar);
       return null;
     }
        
@@ -341,9 +203,9 @@ public class MappedReads
       final StringBuilder titleToSave = new StringBuilder();
       final StringBuilder body = new StringBuilder();
       
-      for (int j = 0; j < bamList.size(); j++)
+      for (int j = 0; j < bamView.bamList.size(); j++)
       {
-        String bam = bamList.get(j);
+        String bam = bamView.bamList.get(j);
         hdr.append("#BAM: " + bam);
         if (mappedReads != null)
         {
@@ -369,7 +231,7 @@ public class MappedReads
           }
           titleToSave.append("\t");
           title.append("\t");
-          for (String bam: bamList)
+          for (String bam: bamView.bamList)
           {
             String name = new File(bam).getName();
             titleToSave.append(name+"\t");
@@ -409,7 +271,7 @@ public class MappedReads
           }
           title.append("\t");
           titleToSave.append("\t");
-          for (int j = 0; j < bamList.size(); j++)
+          for (int j = 0; j < bamView.bamList.size(); j++)
           {
             if(mappedReads != null)
             {
@@ -481,88 +343,43 @@ public class MappedReads
   class CalculateTotalMappedReads extends SwingWorker
   {
     private boolean useAllRefSeqs;
-    CalculateTotalMappedReads(boolean useAllRefSeqs)
+    private int sequenceLength;
+    
+    CalculateTotalMappedReads(boolean useAllRefSeqs, final int sequenceLength)
     {
       this.useAllRefSeqs = useAllRefSeqs;
+      this.sequenceLength = sequenceLength;
     }
     
     public Object construct()
     {
-      mappedReads = new int[bamList.size()];
-      if(concatSequences || !useAllRefSeqs)
-        calc(refName, sequenceLength);
+      int mappedReads[] = null;
+      if(bamView.isConcatSequences() || !useAllRefSeqs)
+      {
+        String refName = (String) bamView.getCombo().getSelectedItem();
+        mappedReads = BamUtils.calc(bamView, refName, sequenceLength, 
+            useStrandTag, progressBar);
+      }
       else
       {
-        for (String name : seqNames)
+        for (String name : bamView.getSeqNames())
         {
           progressTxt.setText(name);
-          int thisLength = seqLengths.get(name);
+          int thisLength = bamView.getSeqLengths().get(name);
           progressBar.setValue(0);
           progressBar.setMaximum(thisLength);
-          calc(name, thisLength);
+          mappedReads = BamUtils.calc(bamView, name, thisLength, 
+              useStrandTag, progressBar);
         }
       }
       
       progressBar.setValue(0);
       progressBar.setMaximum(features.size());
       progressTxt.setText("RPKM values for "+features.size()+" features");
-      CalculateMappedReads cmr = new CalculateMappedReads();
+      CalculateMappedReads cmr = new CalculateMappedReads(mappedReads);
       cmr.start();
       return null;
     }
-    
-    private void calc(final String refName, final int sequenceLength)
-    {
-      int MAX_BASE_CHUNK = 2000 * 60;
-      boolean contained = false;
-      for (int i = 0; i < sequenceLength; i += MAX_BASE_CHUNK)
-      {
-        progressBar.setValue(i);
-        int sbegc = i;
-        int sendc = i + MAX_BASE_CHUNK - 1;
-
-        for (int j = 0; j < bamList.size(); j++)
-        {
-          String bam = bamList.get(j);
-          if (concatSequences)
-          {
-            int len = 0;
-            int lastLen = 1;
-            for (String name : seqNames)
-            {
-              int thisLength = seqLengths.get(name);
-              len += thisLength;
-
-              if ((lastLen >= sbegc && lastLen < sendc)
-                  || (len >= sbegc && len < sendc)
-                  || (sbegc >= lastLen && sbegc < len)
-                  || (sendc >= lastLen && sendc < len))
-              {
-                int offset = offsetLengths.get(name);
-                int thisStart = sbegc - offset;
-                if (thisStart < 1)
-                  thisStart = 1;
-                int thisEnd = sendc - offset;
-                if (thisEnd > thisLength)
-                  thisEnd = thisLength;
-
-                mappedReads[j] += BamUtils.count(bam, samFileReaderHash, name,
-                    thisStart, thisEnd, samRecordFlagPredicate,
-                    samRecordMapQPredicate, contained, false, useStrandTag)[0];
-
-              }
-              lastLen = len;
-            }
-          }
-          else
-          {
-            mappedReads[j] += BamUtils.count(bam, samFileReaderHash, refName, sbegc,
-                sendc, samRecordFlagPredicate, samRecordMapQPredicate,
-                contained, false, useStrandTag)[0];
-          }
-        }
-      }
-    }
   }
   
   /**
@@ -572,7 +389,6 @@ public class MappedReads
   {
     private EntryGroup entryGroup;
     private Bases bases;
-    private String refSeq;
     private int threshold;
     private int minSize;
     private int minBams;
@@ -589,7 +405,7 @@ public class MappedReads
     {
       entryGroup = feature_display.getEntryGroup();
       bases = feature_display.getBases();
-      this.refSeq = refSeq;
+
       this.groupsFrame = groupsFrame;
       this.threshold = threshold;
       this.minSize = minSize;
@@ -620,14 +436,14 @@ public class MappedReads
       int revStart = -1;
       final List<MarkerObj> fwdMarkers = new Vector<MarkerObj>();
       final List<MarkerObj> revMarkers = new Vector<MarkerObj>();
-      for (short i = 0; i < bamList.size(); i++)
+      for (short i = 0; i < bamView.bamList.size(); i++)
       {
-        if(hideBamList.contains(i))
+        if(bamView.hideBamList.contains(i))
           continue;
         
         for(int j=beg; j<end; j+=MAX_BASE_CHUNK)
         {
-          progressBar.setValue((j + (i*end)) / bamList.size());
+          progressBar.setValue((j + (i*end)) / bamView.bamList.size());
           if(j > end)
             continue;
           int start = j;
@@ -640,12 +456,12 @@ public class MappedReads
               for (int col = 0; col < 2; col++)
                 cnt[row][col] = 0;
             
-            if (concatSequences)
+            if (bamView.isConcatSequences())
             {
-              for (String name : seqNames)
+              for (String name : bamView.getSeqNames())
               {
-                int len = seqLengths.get(name);
-                int offset = offsetLengths.get(name);
+                int len = bamView.getSeqLengths().get(name);
+                int offset = bamView.getOffsetLengths().get(name);
                 
                 if( (start >= offset && start <= offset+len) ||
                     (stop >= offset  && start <= offset+len) )
@@ -662,17 +478,15 @@ public class MappedReads
                     concatShift = offset-start;
 
                   cnt =
-                    BamUtils.countOverRange(bamList.get(i), samFileReaderHash, 
-                        name, thisStart, thisEnd, concatShift, cnt,
-                        samRecordFlagPredicate, samRecordMapQPredicate);
+                    BamUtils.countOverRange(bamView, bamView.bamList.get(i), 
+                        thisStart, thisEnd, concatShift, cnt);
                 }
               }
             }
             else
               cnt =
-                BamUtils.countOverRange(bamList.get(i), samFileReaderHash, 
-                    refSeq, start, stop, 0, cnt,
-                    samRecordFlagPredicate, samRecordMapQPredicate);
+                BamUtils.countOverRange(bamView, bamView.bamList.get(i),  
+                    start, stop, 0, cnt);
 
             for(int k=0; k<cnt.length; k++)
             {
@@ -741,7 +555,7 @@ public class MappedReads
             Hashtable<String, Integer> groupCluster = new Hashtable<String, Integer>();
             for(int j=0; j<bamIdxList.size(); j++)
             {
-              File f = new File(bamList.get(j));
+              File f = new File(bamView.bamList.get(j));
               String grp = groupsFrame.getGroupName( f.getName() );
               if(groupCluster.containsKey(grp))
               {
@@ -894,23 +708,4 @@ public class MappedReads
       dialog.dispose();
     }
   }
-  
-  class ReadCount
-  {
-    private float senseCnt = 0;
-    private float antiCnt  = 0;
-    ReadCount(float[] cnt, boolean isFwd)
-    {
-      if(isFwd)
-      {
-        senseCnt = cnt[0];
-        antiCnt  = cnt[1];
-      }
-      else
-      {
-        senseCnt = cnt[1];
-        antiCnt  = cnt[0];
-      }
-    }
-  }
 }
diff --git a/uk/ac/sanger/artemis/components/alignment/ReadCount.java b/uk/ac/sanger/artemis/components/alignment/ReadCount.java
new file mode 100644
index 000000000..5d940ed3b
--- /dev/null
+++ b/uk/ac/sanger/artemis/components/alignment/ReadCount.java
@@ -0,0 +1,40 @@
+/* 
+ * This file is part of Artemis
+ *
+ * Copyright (C) 2014  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;
+
+class ReadCount
+{
+  protected float senseCnt = 0;
+  protected float antiCnt  = 0;
+  ReadCount(float[] cnt, boolean isFwd)
+  {
+    if(isFwd)
+    {
+      senseCnt = cnt[0];
+      antiCnt  = cnt[1];
+    }
+    else
+    {
+      senseCnt = cnt[1];
+      antiCnt  = cnt[0];
+    }
+  }
+}
\ No newline at end of file
diff --git a/uk/ac/sanger/artemis/components/alignment/ReadCountDialog.java b/uk/ac/sanger/artemis/components/alignment/ReadCountDialog.java
index 17861ff96..35b5bc879 100644
--- a/uk/ac/sanger/artemis/components/alignment/ReadCountDialog.java
+++ b/uk/ac/sanger/artemis/components/alignment/ReadCountDialog.java
@@ -138,11 +138,14 @@ import uk.ac.sanger.artemis.util.StringVector;
       if(qNames == null)
       {
         qNames = new StringVector();
-        Object objs[] = systematicListSelectionPanel.getResultArray();
+        Object objs[];
+        if(systematicListSelectionPanel != null)
+          objs = systematicListSelectionPanel.getResultArray();
+        else
+          objs = Options.getOptions().getSystematicQualifierNames().toArray();
         for(Object o: objs)
           qNames.add((String)o);
       }
-      
       return pickName(f, qNames);
     }
     
-- 
GitLab