JAL-2647 more iterators
authorkiramt <k.mourao@dundee.ac.uk>
Thu, 28 Sep 2017 12:16:05 +0000 (13:16 +0100)
committerkiramt <k.mourao@dundee.ac.uk>
Thu, 28 Sep 2017 12:16:05 +0000 (13:16 +0100)
src/jalview/analysis/Dna.java
src/jalview/appletgui/SeqCanvas.java
src/jalview/datamodel/HiddenColumns.java
src/jalview/gui/AlignViewport.java
src/jalview/gui/SeqCanvas.java
src/jalview/gui/VamsasApplication.java
test/jalview/analysis/DnaTest.java
test/jalview/datamodel/HiddenColumnsTest.java

index a10b037..c3408bd 100644 (file)
@@ -56,19 +56,19 @@ public class Dna
    * 'final' variables describe the inputs to the translation, which should not
    * be modified.
    */
-  final private List<SequenceI> selection;
+  private final List<SequenceI> selection;
 
-  final private String[] seqstring;
+  private final String[] seqstring;
 
-  final private int[] contigs;
+  private final List<int[]> contigs;
 
-  final private char gapChar;
+  private final char gapChar;
 
-  final private AlignmentAnnotation[] annotations;
+  private final AlignmentAnnotation[] annotations;
 
-  final private int dnaWidth;
+  private final int dnaWidth;
 
-  final private AlignmentI dataset;
+  private final AlignmentI dataset;
 
   /*
    * Working variables for the translation.
@@ -91,7 +91,7 @@ public class Dna
    * @param viewport
    * @param visibleContigs
    */
-  public Dna(AlignViewportI viewport, int[] visibleContigs)
+  public Dna(AlignViewportI viewport, List<int[]> visibleContigs)
   {
     this.selection = Arrays.asList(viewport.getSequenceSelection());
     this.seqstring = viewport.getViewAsString(true);
@@ -161,7 +161,7 @@ public class Dna
 
     int s;
     int sSize = selection.size();
-    List<SequenceI> pepseqs = new ArrayList<SequenceI>();
+    List<SequenceI> pepseqs = new ArrayList<>();
     for (s = 0; s < sSize; s++)
     {
       SequenceI newseq = translateCodingRegion(selection.get(s),
@@ -213,7 +213,7 @@ public class Dna
       if (dnarefs != null)
       {
         // intersect with pep
-        List<DBRefEntry> mappedrefs = new ArrayList<DBRefEntry>();
+        List<DBRefEntry> mappedrefs = new ArrayList<>();
         DBRefEntry[] refs = dna.getDBRefs();
         for (int d = 0; d < refs.length; d++)
         {
@@ -391,26 +391,30 @@ public class Dna
           String seqstring, AlignedCodonFrame acf,
           List<SequenceI> proteinSeqs)
   {
-    List<int[]> skip = new ArrayList<int[]>();
+    List<int[]> skip = new ArrayList<>();
     int skipint[] = null;
     ShiftList vismapping = new ShiftList(); // map from viscontigs to seqstring
     // intervals
-    int vc;
-    int[] scontigs = new int[contigs.length];
+    int vc = 0;
+    int[] scontigs = new int[contigs.size() * 2];
     int npos = 0;
-    for (vc = 0; vc < contigs.length; vc += 2)
+    int[] lastregion = null;
+    for (int[] region : contigs)
     {
-      if (vc == 0)
+      if (lastregion == null)
       {
-        vismapping.addShift(npos, contigs[vc]);
+        vismapping.addShift(npos, region[0]);
       }
       else
       {
         // hidden region
-        vismapping.addShift(npos, contigs[vc] - contigs[vc - 1] + 1);
+        vismapping.addShift(npos, region[0] - lastregion[1] + 1);
       }
-      scontigs[vc] = contigs[vc];
-      scontigs[vc + 1] = contigs[vc + 1];
+      lastregion = region;
+
+      scontigs[vc] = region[0];
+      scontigs[vc + 1] = region[1];
+      vc++;
     }
 
     // allocate a roughly sized buffer for the protein sequence
@@ -800,7 +804,7 @@ public class Dna
   public AlignmentI reverseCdna(boolean complement)
   {
     int sSize = selection.size();
-    List<SequenceI> reversed = new ArrayList<SequenceI>();
+    List<SequenceI> reversed = new ArrayList<>();
     for (int s = 0; s < sSize; s++)
     {
       SequenceI newseq = reverseSequence(selection.get(s).getName(),
index 20ec665..8d429c7 100755 (executable)
@@ -417,71 +417,71 @@ public class SeqCanvas extends Panel implements ViewportListenerI
           int canvasHeight, int startRes)
   {
     AlignmentI al = av.getAlignment();
-
+  
     FontMetrics fm = getFontMetrics(av.getFont());
-
+  
     LABEL_EAST = 0;
     LABEL_WEST = 0;
-
+  
     if (av.getScaleRightWrapped())
     {
       LABEL_EAST = fm.stringWidth(getMask());
     }
-
+  
     if (av.getScaleLeftWrapped())
     {
       LABEL_WEST = fm.stringWidth(getMask());
     }
-
+  
     int hgap = avcharHeight;
     if (av.getScaleAboveWrapped())
     {
       hgap += avcharHeight;
     }
-
+  
     int cWidth = (canvasWidth - LABEL_EAST - LABEL_WEST) / avcharWidth;
     int cHeight = av.getAlignment().getHeight() * avcharHeight;
-
+  
     av.setWrappedWidth(cWidth);
-
+  
     av.getRanges().setViewportStartAndWidth(startRes, cWidth);
-
+  
     int endx;
     int ypos = hgap;
-
+  
     int maxwidth = av.getAlignment().getWidth();
-
+  
     if (av.hasHiddenColumns())
     {
       maxwidth = av.getAlignment().getHiddenColumns()
               .findColumnPosition(maxwidth);
     }
-
+  
     while ((ypos <= canvasHeight) && (startRes < maxwidth))
     {
       endx = startRes + cWidth - 1;
-
+  
       if (endx > maxwidth)
       {
         endx = maxwidth;
       }
-
+  
       g.setColor(Color.black);
-
+  
       if (av.getScaleLeftWrapped())
       {
         drawWestScale(g, startRes, endx, ypos);
       }
-
+  
       if (av.getScaleRightWrapped())
       {
         g.translate(canvasWidth - LABEL_EAST, 0);
         drawEastScale(g, startRes, endx, ypos);
         g.translate(-(canvasWidth - LABEL_EAST), 0);
       }
-
+  
       g.translate(LABEL_WEST, 0);
-
+  
       if (av.getScaleAboveWrapped())
       {
         drawNorthScale(g, startRes, endx, ypos);
@@ -503,15 +503,15 @@ public class SeqCanvas extends Panel implements ViewportListenerI
                   { ypos - (avcharHeight / 2), ypos - (avcharHeight / 2), ypos - (avcharHeight / 2) + 8 }, 3);
         }
       }
-
+  
       if (g.getClip() == null)
       {
         g.setClip(0, 0, cWidth * avcharWidth, canvasHeight);
       }
-
+  
       drawPanel(g, startRes, endx, 0, al.getHeight() - 1, ypos);
       g.setClip(null);
-
+  
       if (av.isShowAnnotation())
       {
         g.translate(0, cHeight + ypos + 4);
@@ -519,17 +519,17 @@ public class SeqCanvas extends Panel implements ViewportListenerI
         {
           annotations = new AnnotationPanel(av);
         }
-
+  
         annotations.drawComponent(g, startRes, endx + 1);
         g.translate(0, -cHeight - ypos - 4);
       }
       g.translate(-LABEL_WEST, 0);
-
+  
       ypos += cHeight + getAnnotationHeight() + hgap;
-
+  
       startRes += cWidth;
     }
-
+  
   }
 
   AnnotationPanel annotations;
@@ -564,53 +564,44 @@ public class SeqCanvas extends Panel implements ViewportListenerI
       int blockStart = startRes;
       int blockEnd = endRes;
 
-      if (av.hasHiddenColumns())
+      HiddenColumns hidden = av.getAlignment().getHiddenColumns();
+      Iterator<int[]> regions = hidden.getBoundedVisRegionIterator(startRes,
+              endRes);
+      while (regions.hasNext())
       {
-        HiddenColumns hidden = av.getAlignment().getHiddenColumns();
-        for (int[] region : hidden.getHiddenColumnsCopy())
-        {
-          int hideStart = region[0];
-          int hideEnd = region[1];
+        int[] region = regions.next();
 
-          if (hideStart <= blockStart)
-          {
-            blockStart += (hideEnd - hideStart) + 1;
-            continue;
-          }
+        blockStart = region[0];
 
-          /*
-           * draw up to just before the next hidden region, or the end of
-           * the visible region, whichever comes first
-           */
-          blockEnd = Math.min(hideStart - 1, blockStart + screenYMax
-                  - screenY);
+        /*
+         * draw up to just before the next hidden region, or the end of
+         * the visible region, whichever comes first
+         */
+        blockEnd = Math.min(region[1], blockStart + screenYMax - screenY);
 
-          g1.translate(screenY * avcharWidth, 0);
+        g1.translate(screenY * avcharWidth, 0);
 
-          draw(g1, blockStart, blockEnd, startSeq, endSeq, offset);
+        draw(g1, blockStart, blockEnd, startSeq, endSeq, offset);
 
-          /*
-           * draw the downline of the hidden column marker (ScalePanel draws the
-           * triangle on top) if we reached it
-           */
-          if (av.getShowHiddenMarkers() && blockEnd == hideStart - 1)
-          {
-            g1.setColor(Color.blue);
-            g1.drawLine((blockEnd - blockStart + 1) * avcharWidth - 1,
-                    0 + offset,
-                    (blockEnd - blockStart + 1) * avcharWidth - 1,
-                    (endSeq - startSeq + 1) * avcharHeight + offset);
-          }
+        /*
+         * draw the downline of the hidden column marker (ScalePanel draws the
+         * triangle on top) if we reached it
+         */
+        if (av.getShowHiddenMarkers() && blockEnd == region[1])
+        {
+          g1.setColor(Color.blue);
+          g1.drawLine((blockEnd - blockStart + 1) * avcharWidth - 1,
+                  0 + offset, (blockEnd - blockStart + 1) * avcharWidth - 1,
+                  (endSeq - startSeq + 1) * avcharHeight + offset);
+        }
 
-          g1.translate(-screenY * avcharWidth, 0);
-          screenY += blockEnd - blockStart + 1;
-          blockStart = hideEnd + 1;
+        g1.translate(-screenY * avcharWidth, 0);
+        screenY += blockEnd - blockStart + 1;
 
-          if (screenY > screenYMax)
-          {
-            // already rendered last block
-            return;
-          }
+        if (screenY > screenYMax)
+        {
+          // already rendered last block
+          return;
         }
       }
       if (screenY <= screenYMax)
index eda8850..82e25b9 100644 (file)
@@ -740,28 +740,20 @@ public class HiddenColumns
    *          (first column inclusive from 0)
    * @param end
    *          (last column - not inclusive)
-   * @return int[] {i_start, i_end, ..} where intervals lie in
+   * @return List<int[]> {[i_start, i_end], ..} where intervals lie in
    *         start<=i_start<=i_end<end
    */
-  public int[] getVisibleContigs(int start, int end)
+  public List<int[]> getVisibleContigs(int start, int end)
   {
     try
     {
       LOCK.readLock().lock();
+      List<int[]> vcontigs = new ArrayList<>();
       if (hiddenColumns != null && hiddenColumns.size() > 0)
       {
-        // max limit on number of visible contigs
-        // so we can dimension array
-        int maxcontigs = end - start + 1;
-        if (maxcontigs > (hiddenColumns.size() + 1) * 2)
-        {
-          maxcontigs = (hiddenColumns.size() + 1) * 2;
-        }
-        int[] vcontigs = new int[maxcontigs];
         int vstart = start;
         int hideStart;
         int hideEnd;
-        int i = 0;
 
         for (int[] region : hiddenColumns)
         {
@@ -775,9 +767,8 @@ public class HiddenColumns
           }
           if (hideStart > vstart)
           {
-            vcontigs[i * 2] = vstart;
-            vcontigs[i * 2 + 1] = hideStart - 1;
-            i++;
+            int[] contig = new int[] { vstart, hideStart - 1 };
+            vcontigs.add(contig);
           }
           vstart = hideEnd + 1;
 
@@ -790,21 +781,16 @@ public class HiddenColumns
 
         if (vstart < end)
         {
-          vcontigs[i * 2] = vstart;
-          vcontigs[i * 2 + 1] = end - 1;
-          i++;
+          int[] contig = new int[] { vstart, end - 1 };
+          vcontigs.add(contig);
         }
-
-        // copy final array into array of correct size
-        int[] trimmmedContigs = new int[i * 2];
-        System.arraycopy(vcontigs, 0, trimmmedContigs, 0, i * 2);
-
-        return trimmmedContigs;
       }
       else
       {
-        return new int[] { start, end - 1 };
+        int[] contig = new int[] { start, end - 1 };
+        vcontigs.add(contig);
       }
+      return vcontigs;
     } finally
     {
       LOCK.readLock().unlock();
@@ -1539,6 +1525,11 @@ public class HiddenColumns
     return new BoundedStartRegionIterator(start, end, useCopy);
   }
 
+  public Iterator<int[]> getBoundedVisRegionIterator(int start, int end)
+  {
+    return new BoundedVisRegionIterator(start, end, true);
+  }
+
   /**
    * An iterator which iterates over hidden column regions in a range.
    * 
@@ -1742,4 +1733,125 @@ public class HiddenColumns
       return result;
     }
   }
+
+  class BoundedVisRegionIterator implements Iterator<int[]>
+  {
+    private int start; // start position to iterate from
+
+    private int end; // end position to iterate to
+
+    // current region in visColumns
+    private int[] currentRegion;
+
+    // current index in visColumns
+    private int currentPosition = 0;
+
+    private List<int[]> vcontigs = null;
+
+    /**
+     * Construct an iterator over visibleColumn regions bounded at
+     * [lowerBound,upperBound]
+     * 
+     * @param lowerBound
+     *          lower bound to iterate from
+     * @param upperBound
+     *          upper bound to iterate to
+     * @param useCopyCols
+     *          whether to make a local copy for iteration (set to true if
+     *          calling from outwith the HiddenColumns class)
+     */
+    BoundedVisRegionIterator(int lowerBound, int upperBound,
+            boolean useCopy)
+    {
+      try
+      {
+        start = lowerBound;
+        end = upperBound;
+
+        if (useCopy)
+        {
+          // assume that if useCopy is false the calling code has locked
+          // hiddenColumns
+          LOCK.readLock().lock();
+        }
+
+        int visStart = start;
+
+        if (hiddenColumns != null)
+        {
+          vcontigs = new ArrayList<>(hiddenColumns.size() + 1);
+
+          // navigate to start, keeping count of hidden columns
+          int i = 0;
+          int[] region = null;
+          while ((i < hiddenColumns.size())
+                  && (hiddenColumns.get(i)[0] <= start))
+          {
+            i++;
+          }
+          // if there was a hidden region before (i>=1), and it ended after
+          // start
+          // and before end, adjust visStart to be just after that region
+          if (i > 0)
+          {
+            region = hiddenColumns.get(i - 1);
+            if ((region[1] > start) && (region[1] < end))
+            {
+              visStart = region[1] + 1;
+            }
+            else if (region[1] >= end)
+            {
+              // previous hidden region covers whole range [start,end]
+              // early exit - vcontigs is empty
+              return;
+            }
+          }
+
+          // iterate from start to end, adding start positions of each
+          // hidden region. Positions are visible columns count, not absolute
+          while (i < hiddenColumns.size()
+                  && (hiddenColumns.get(i)[0] < end))
+          {
+            region = hiddenColumns.get(i);
+            int[] prevVisibleRegion = new int[] { visStart, region[0] - 1 };
+            vcontigs.add(prevVisibleRegion);
+            visStart = region[1] + 1;
+            i++;
+          }
+          // add on a final visible region if needed
+          if (visStart <= end)
+          {
+            int[] lastRegion = new int[] { visStart, end };
+            vcontigs.add(lastRegion);
+          }
+        }
+        else
+        {
+          vcontigs = new ArrayList<>();
+          int[] lastRegion = new int[] { start, end };
+          vcontigs.add(lastRegion);
+        }
+      } finally
+      {
+        if (useCopy)
+        {
+          LOCK.readLock().unlock();
+        }
+      }
+    }
+
+    @Override
+    public boolean hasNext()
+    {
+      return (currentPosition < vcontigs.size());
+    }
+
+    @Override
+    public int[] next()
+    {
+      currentRegion = vcontigs.get(currentPosition);
+      currentPosition++;
+      return currentRegion;
+    }
+  }
 }
index c22a37d..657f8f3 100644 (file)
@@ -476,9 +476,9 @@ public class AlignViewport extends AlignmentViewport
    *          area
    * @return
    */
-  public int[] getViewAsVisibleContigs(boolean selectedRegionOnly)
+  public List<int[]> getViewAsVisibleContigs(boolean selectedRegionOnly)
   {
-    int[] viscontigs = null;
+    List<int[]> viscontigs = null;
     int start = 0, end = 0;
     if (selectedRegionOnly && selectionGroup != null)
     {
@@ -614,10 +614,10 @@ public class AlignViewport extends AlignmentViewport
    */
   public SequenceI[][] collateForPDB(PDBEntry[] pdbEntries)
   {
-    List<SequenceI[]> seqvectors = new ArrayList<SequenceI[]>();
+    List<SequenceI[]> seqvectors = new ArrayList<>();
     for (PDBEntry pdb : pdbEntries)
     {
-      List<SequenceI> choosenSeqs = new ArrayList<SequenceI>();
+      List<SequenceI> choosenSeqs = new ArrayList<>();
       for (SequenceI sq : alignment.getSequences())
       {
         Vector<PDBEntry> pdbRefEntries = sq.getDatasetSequence()
@@ -679,7 +679,7 @@ public class AlignViewport extends AlignmentViewport
     return validCharWidth;
   }
 
-  private Hashtable<String, AutoCalcSetting> calcIdParams = new Hashtable<String, AutoCalcSetting>();
+  private Hashtable<String, AutoCalcSetting> calcIdParams = new Hashtable<>();
 
   public AutoCalcSetting getCalcIdSettingsFor(String calcId)
   {
index 1df6ae3..122e29a 100755 (executable)
@@ -855,24 +855,20 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
       int blockStart = startRes;
       int blockEnd = endRes;
 
-      for (int[] region : av.getAlignment().getHiddenColumns()
-              .getHiddenColumnsCopy())
+      HiddenColumns hidden = av.getAlignment().getHiddenColumns();
+      Iterator<int[]> regions = hidden.getBoundedVisRegionIterator(startRes,
+              endRes);
+      while (regions.hasNext())
       {
-        int hideStart = region[0];
-        int hideEnd = region[1];
+        int[] region = regions.next();
 
-        if (hideStart <= blockStart)
-        {
-          blockStart += (hideEnd - hideStart) + 1;
-          continue;
-        }
+        blockStart = region[0];
 
         /*
          * draw up to just before the next hidden region, or the end of
          * the visible region, whichever comes first
          */
-        blockEnd = Math.min(hideStart - 1, blockStart + screenYMax
-                - screenY);
+        blockEnd = Math.min(region[1], blockStart + screenYMax - screenY);
 
         g1.translate(screenY * charWidth, 0);
 
@@ -882,7 +878,7 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
          * draw the downline of the hidden column marker (ScalePanel draws the
          * triangle on top) if we reached it
          */
-        if (av.getShowHiddenMarkers() && blockEnd == hideStart - 1)
+        if (av.getShowHiddenMarkers() && blockEnd == region[1])
         {
           g1.setColor(Color.blue);
 
@@ -893,7 +889,6 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
 
         g1.translate(-screenY * charWidth, 0);
         screenY += blockEnd - blockStart + 1;
-        blockStart = hideEnd + 1;
 
         if (screenY > screenYMax)
         {
@@ -908,7 +903,7 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
         blockEnd = blockStart + screenYMax - screenY;
         g1.translate(screenY * charWidth, 0);
         draw(g1, blockStart, blockEnd, startSeq, endSeq, yOffset);
-
+      
         g1.translate(-screenY * charWidth, 0);
       }
     }
@@ -1124,19 +1119,15 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
       int blockStart = startRes;
       int blockEnd = endRes;
 
-      for (int[] region : av.getAlignment().getHiddenColumns()
-              .getHiddenColumnsCopy())
+      HiddenColumns hidden = av.getAlignment().getHiddenColumns();
+      Iterator<int[]> regions = hidden.getBoundedVisRegionIterator(startRes,
+              endRes);
+      while (regions.hasNext())
       {
-        int hideStart = region[0];
-        int hideEnd = region[1];
-
-        if (hideStart <= blockStart)
-        {
-          blockStart += (hideEnd - hideStart) + 1;
-          continue;
-        }
+        int[] region = regions.next();
 
-        blockEnd = hideStart - 1;
+        blockStart = region[0];
+        blockEnd = region[1];
 
         g.translate(screenY * charWidth, 0);
         drawPartialGroupOutline(g, group,
@@ -1144,7 +1135,6 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
 
         g.translate(-screenY * charWidth, 0);
         screenY += blockEnd - blockStart + 1;
-        blockStart = hideEnd + 1;
 
         if (screenY > (endRes - startRes))
         {
index d2086e0..3bf7c24 100644 (file)
@@ -42,6 +42,7 @@ import java.io.IOException;
 import java.util.Hashtable;
 import java.util.IdentityHashMap;
 import java.util.Iterator;
+import java.util.List;
 
 import javax.swing.JInternalFrame;
 
@@ -1076,14 +1077,14 @@ public class VamsasApplication implements SelectionSource, VamsasSource
                   {
                     // int[] intervals = colsel.getVisibleContigs(
                     // seqsel.getStartRes(), seqsel.getEndRes() + 1);
-                    int[] intervals = hidden.getVisibleContigs(
+                    List<int[]> intervals = hidden.getVisibleContigs(
                             seqsel.getStartRes(), seqsel.getEndRes() + 1);
-                    for (int iv = 0; iv < intervals.length; iv += 2)
+                    for (int[] region : intervals)
                     {
                       Seg s = new Seg();
-                      s.setStart(intervals[iv] + 1); // vamsas indices begin at
+                      s.setStart(region[0] + 1); // vamsas indices begin at
                       // 1, not zero.
-                      s.setEnd(intervals[iv + 1] + 1);
+                      s.setEnd(region[1] + 1);
                       s.setInclusive(true);
                       range.addSeg(s);
                     }
index d2fa99a..96ac0c3 100644 (file)
@@ -38,6 +38,8 @@ import jalview.io.FileFormat;
 import jalview.io.FormatAdapter;
 
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
 
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
@@ -135,7 +137,10 @@ public class DnaTest
             FileFormat.Fasta);
     HiddenColumns cs = new HiddenColumns();
     AlignViewportI av = new AlignViewport(alf, cs);
-    Dna dna = new Dna(av, new int[] { 0, alf.getWidth() - 1 });
+    int[] contig = new int[] { 0, alf.getWidth() - 1 };
+    List<int[]> contigs = new ArrayList<>();
+    contigs.add(contig);
+    Dna dna = new Dna(av, contigs);
     AlignmentI translated = dna.translateCdna();
     assertNotNull("Couldn't do a full width translation of test data.",
             translated);
@@ -163,7 +168,7 @@ public class DnaTest
         cs.hideColumns(0, ipos - 1);
       }
       cs.hideColumns(ipos + vwidth, alf.getWidth());
-      int[] vcontigs = cs.getVisibleContigs(0, alf.getWidth());
+      List<int[]> vcontigs = cs.getVisibleContigs(0, alf.getWidth());
       AlignViewportI av = new AlignViewport(alf, cs);
       Dna dna = new Dna(av, vcontigs);
       AlignmentI transAlf = dna.translateCdna();
@@ -190,7 +195,10 @@ public class DnaTest
             DataSourceType.PASTE, FileFormat.Fasta);
     HiddenColumns cs = new HiddenColumns();
     AlignViewportI av = new AlignViewport(alf, cs);
-    Dna dna = new Dna(av, new int[] { 0, alf.getWidth() - 1 });
+    int[] contig = new int[] { 0, alf.getWidth() - 1 };
+    List<int[]> contigs = new ArrayList<>();
+    contigs.add(contig);
+    Dna dna = new Dna(av, contigs);
     AlignmentI translated = dna.translateCdna();
     String aa = translated.getSequenceAt(0).getSequenceAsString();
     assertEquals(
@@ -213,7 +221,10 @@ public class DnaTest
     cs.hideColumns(24, 35); // hide codons 9-12
     cs.hideColumns(177, 191); // hide codons 60-64
     AlignViewportI av = new AlignViewport(alf, cs);
-    Dna dna = new Dna(av, new int[] { 0, alf.getWidth() - 1 });
+    int[] contig = new int[] { 0, alf.getWidth() - 1 };
+    List<int[]> contigs = new ArrayList<>();
+    contigs.add(contig);
+    Dna dna = new Dna(av, contigs);
     AlignmentI translated = dna.translateCdna();
     String aa = translated.getSequenceAt(0).getSequenceAsString();
     assertEquals("AACDDGGGGHHIIIKKLLLLLLMNNPPPPQQRRRRRRSSSSSSTTTTVVVVW", aa);
@@ -298,7 +309,10 @@ public class DnaTest
             .generate(12, 8, 97, 5, 5);
     HiddenColumns cs = new HiddenColumns();
     AlignViewportI av = new AlignViewport(cdna, cs);
-    Dna dna = new Dna(av, new int[] { 0, cdna.getWidth() - 1 });
+    int[] contig = new int[] { 0, cdna.getWidth() - 1 };
+    List<int[]> contigs = new ArrayList<>();
+    contigs.add(contig);
+    Dna dna = new Dna(av, contigs);
     AlignmentI translated = dna.translateCdna();
 
     /*
@@ -313,7 +327,10 @@ public class DnaTest
     }
     AlignmentI cdnaReordered = new Alignment(sorted);
     av = new AlignViewport(cdnaReordered, cs);
-    dna = new Dna(av, new int[] { 0, cdna.getWidth() - 1 });
+    contig = new int[] { 0, cdna.getWidth() - 1 };
+    contigs = new ArrayList<>();
+    contigs.add(contig);
+    dna = new Dna(av, contigs);
     AlignmentI translated2 = dna.translateCdna();
 
     /*
@@ -544,7 +561,10 @@ public class DnaTest
 
     HiddenColumns cs = new HiddenColumns();
     AlignViewportI av = new AlignViewport(al, cs);
-    Dna testee = new Dna(av, new int[] { 0, al.getWidth() - 1 });
+    int[] contig = new int[] { 0, al.getWidth() - 1 };
+    List<int[]> contigs = new ArrayList<>();
+    contigs.add(contig);
+    Dna testee = new Dna(av, contigs);
     AlignmentI reversed = testee.reverseCdna(false);
     assertEquals(1, reversed.getHeight());
     assertEquals(seqRev, reversed.getSequenceAt(0).getSequenceAsString());
index 19a5671..92e0f90 100644 (file)
@@ -188,8 +188,8 @@ public class HiddenColumnsTest
   {
     HiddenColumns cs = new HiddenColumns();
 
-    int[] visible = cs.getVisibleContigs(3, 10);
-    assertEquals("[3, 9]", Arrays.toString(visible));
+    List<int[]> visible = cs.getVisibleContigs(3, 10);
+    assertEquals("[3, 9]", Arrays.toString(visible.get(0)));
 
     cs.hideColumns(3, 6);
     cs.hideColumns(8, 9);
@@ -199,23 +199,29 @@ public class HiddenColumnsTest
 
     // start position is inclusive, end position exclusive
     visible = cs.getVisibleContigs(1, 13);
-    assertEquals("[1, 2, 7, 7, 10, 11]", Arrays.toString(visible));
+    assertEquals("[1, 2]", Arrays.toString(visible.get(0)));
+    assertEquals("[7, 7]", Arrays.toString(visible.get(1)));
+    assertEquals("[10, 11]", Arrays.toString(visible.get(2)));
 
     // Test start hidden, end visible
     visible = cs.getVisibleContigs(4, 14);
-    assertEquals("[7, 7, 10, 11, 13, 13]", Arrays.toString(visible));
+    assertEquals("[7, 7]", Arrays.toString(visible.get(0)));
+    assertEquals("[10, 11]", Arrays.toString(visible.get(1)));
+    assertEquals("[13, 13]", Arrays.toString(visible.get(2)));
 
     // Test start hidden, end hidden
     visible = cs.getVisibleContigs(3, 10);
-    assertEquals("[7, 7]", Arrays.toString(visible));
+    assertEquals("[7, 7]", Arrays.toString(visible.get(0)));
 
     // Test start visible, end hidden
     visible = cs.getVisibleContigs(0, 13);
-    assertEquals("[0, 2, 7, 7, 10, 11]", Arrays.toString(visible));
+    assertEquals("[0, 2]", Arrays.toString(visible.get(0)));
+    assertEquals("[7, 7]", Arrays.toString(visible.get(1)));
+    assertEquals("[10, 11]", Arrays.toString(visible.get(2)));
 
     // Test empty result
     visible = cs.getVisibleContigs(4, 6);
-    assertEquals("[]", Arrays.toString(visible));
+    assertEquals(0, visible.size());
   }
 
   @Test(groups = { "Functional" })
@@ -970,19 +976,18 @@ public class HiddenColumnsTest
             false);
 
     // confirm that original contigs are as expected
-    int[] oldcontigs = hidden.getVisibleContigs(0, 25);
-    int[] testcontigs = { 0, 14, 18, 24 };
-    assertTrue(Arrays.equals(oldcontigs, testcontigs));
+    List<int[]> visible = hidden.getVisibleContigs(0, 25);
+    assertEquals("[0, 14]", Arrays.toString(visible.get(0)));
+    assertEquals("[18, 24]", Arrays.toString(visible.get(1)));
 
     // propagate insertions
     HiddenColumns result = HiddenColumns.propagateInsertions(profileseq, al,
             view);
 
     // confirm that the contigs have changed to account for the gaps
-    int[] newcontigs = result.getVisibleContigs(0, 25);
-    testcontigs[1] = 10;
-    testcontigs[2] = 14;
-    assertTrue(Arrays.equals(newcontigs, testcontigs));
+    visible = result.getVisibleContigs(0, 25);
+    assertEquals("[0, 10]", Arrays.toString(visible.get(0)));
+    assertEquals("[14, 24]", Arrays.toString(visible.get(1)));
 
     // confirm the alignment has been changed so that the other sequences have
     // gaps inserted where the columns are hidden
@@ -1025,19 +1030,18 @@ public class HiddenColumnsTest
             false);
 
     // confirm that original contigs are as expected
-    int[] oldcontigs = hidden.getVisibleContigs(0, 20);
-    int[] testcontigs = { 0, 6, 11, 19 };
-    assertTrue(Arrays.equals(oldcontigs, testcontigs));
+    List<int[]> visible = hidden.getVisibleContigs(0, 20);
+    assertEquals("[0, 6]", Arrays.toString(visible.get(0)));
+    assertEquals("[11, 19]", Arrays.toString(visible.get(1)));
 
     // propagate insertions
     HiddenColumns result = HiddenColumns.propagateInsertions(profileseq, al,
             view);
 
     // confirm that the contigs have changed to account for the gaps
-    int[] newcontigs = result.getVisibleContigs(0, 20);
-    testcontigs[1] = 4;
-    testcontigs[2] = 7;
-    assertTrue(Arrays.equals(newcontigs, testcontigs));
+    visible = result.getVisibleContigs(0, 20);
+    assertEquals("[0, 4]", Arrays.toString(visible.get(0)));
+    assertEquals("[7, 19]", Arrays.toString(visible.get(1)));
 
     // confirm the alignment has been changed so that the other sequences have
     // gaps inserted where the columns are hidden
@@ -1430,4 +1434,65 @@ public class HiddenColumnsTest
     assertEquals(6, next);
     assertFalse(it.hasNext());
   }
+
+  @Test(groups = "Functional")
+  public void testVisRegionsIterator()
+  {
+    HiddenColumns h = new HiddenColumns();
+    Iterator<int[]> it = h.getBoundedVisRegionIterator(0, 15);
+
+    // no hidden columns = single visible contig
+    assertTrue(it.hasNext());
+    assertEquals("[0, 15]", Arrays.toString(it.next()));
+
+    // hidden column region at start
+    h.hideColumns(0, 5);
+    it = h.getBoundedVisRegionIterator(0, 15);
+    assertTrue(it.hasNext());
+    assertEquals("[6, 15]", Arrays.toString(it.next()));
+
+    // hidden column region at end
+    h = new HiddenColumns();
+    h.hideColumns(8, 15);
+    it = h.getBoundedVisRegionIterator(0, 15);
+    assertTrue(it.hasNext());
+    assertEquals("[0, 7]", Arrays.toString(it.next()));
+
+    // hidden column region across whole region
+    h = new HiddenColumns();
+    h.hideColumns(0, 20);
+    it = h.getBoundedVisRegionIterator(0, 15);
+    assertFalse(it.hasNext());
+
+    // hidden column region in middle
+    h = new HiddenColumns();
+    h.hideColumns(1, 14);
+    it = h.getBoundedVisRegionIterator(0, 15);
+    assertTrue(it.hasNext());
+    assertEquals("[0, 0]", Arrays.toString(it.next()));
+    assertTrue(it.hasNext());
+    assertEquals("[15, 15]", Arrays.toString(it.next()));
+
+    // hidden column region just off either end
+    h = new HiddenColumns();
+    h.hideColumns(3, 14);
+    it = h.getBoundedVisRegionIterator(4, 13);
+    assertFalse(it.hasNext());
+
+    // multiple regions
+    h = new HiddenColumns();
+    h.hideColumns(3, 5);
+    h.hideColumns(7, 11);
+    h.hideColumns(14, 19);
+    h.hideColumns(24, 25);
+    h.hideColumns(35, 39);
+    it = h.getBoundedVisRegionIterator(8, 26);
+    assertTrue(it.hasNext());
+    assertEquals("[12, 13]", Arrays.toString(it.next()));
+    assertTrue(it.hasNext());
+    assertEquals("[20, 23]", Arrays.toString(it.next()));
+    assertTrue(it.hasNext());
+    assertEquals("[26, 26]", Arrays.toString(it.next()));
+    assertFalse(it.hasNext());
+  }
 }