import java.util.Collections;
import java.util.Iterator;
import java.util.List;
+import java.util.NoSuchElementException;
import java.util.Vector;
import java.util.concurrent.locks.ReentrantReadWriteLock;
if (copy != null)
{
hiddenColumns = new ArrayList<>();
- Iterator<int[]> it = copy.getBoundedIterator(start, end, true);
+ Iterator<int[]> it = copy.getBoundedIterator(start, end);
while (it.hasNext())
{
int[] region = it.next();
}
}
+ /**
+ * Get the number of distinct hidden regions
+ *
+ * @return number of regions
+ */
+ public int getNumberOfRegions()
+ {
+ try
+ {
+ LOCK.readLock().lock();
+ int num = 0;
+ if (hasHiddenColumns())
+ {
+ num = hiddenColumns.size();
+ }
+ return num;
+ } finally
+ {
+ LOCK.readLock().unlock();
+ }
+ }
+
@Override
public boolean equals(Object obj)
{
}
/**
- * Returns a copy of the vector of hidden regions, as an ArrayList. Before
- * using this method please consider if you really need access to the hidden
- * regions - a new (or existing!) method on HiddenColumns might be more
- * appropriate.
- *
- * @return hidden regions as an ArrayList of [start,end] pairs
- */
- public ArrayList<int[]> getHiddenColumnsCopy()
- {
- try
- {
- LOCK.readLock().lock();
- return copyHiddenRegionsToArrayList(0);
- } finally
- {
- LOCK.readLock().unlock();
- }
- }
-
- /**
* return all visible segments between the given start and end boundaries
*
* @param start
* (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)
{
}
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;
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();
// but where each hidden column region is shifted backwards by the number of
// preceding visible gaps
// update hidden columns at the same time
- ArrayList<int[]> regions = getHiddenColumnsCopy();
+ Iterator<int[]> regions = iterator();
ArrayList<int[]> newhidden = new ArrayList<>();
int numGapsBefore = 0;
int gapPosition = 0;
- for (int[] region : regions)
+ while (regions.hasNext())
{
// get region coordinates accounting for gaps
// we can rely on gaps not being *in* hidden regions because we already
// removed those
+ int[] region = regions.next();
while (gapPosition < region[0])
{
gapPosition++;
{
if (hiddenColumns != null)
{
- return new BoundedHiddenColsIterator(0, hiddenColumns.size(), true);
+ int last = hiddenColumns.get(hiddenColumns.size() - 1)[1];
+ return new BoundedHiddenColsIterator(0, last, true);
}
else
{
}
}
- public Iterator<int[]> getBoundedIterator(int start, int end,
- boolean useCopy)
+ public Iterator<int[]> getBoundedIterator(int start, int end)
{
- return new BoundedHiddenColsIterator(start, end, useCopy);
+ return new BoundedHiddenColsIterator(start, end, true);
}
- public Iterator<Integer> getBoundedStartIterator(int start, int end,
- boolean useCopy)
+ public Iterator<Integer> getBoundedStartIterator(int start, int end)
{
- return new BoundedStartRegionIterator(start, end, useCopy);
+ return new BoundedStartRegionIterator(start, end, true);
+ }
+
+ public Iterator<Integer> getVisibleColsIterator(int start, int end)
+ {
+ return new VisibleColsIterator(start, end, true);
}
/**
* @author kmourao
*
*/
-
-
class BoundedHiddenColsIterator implements Iterator<int[]>
{
-
private int start; // start position to iterate from
private int end; // end position to iterate to
* lower bound to iterate from
* @param upperBound
* upper bound to iterate to
- * @param opt
- * Option.OVERLAP: regions which overlap [lowerBound,upperBound]
- * are included Option.START: regions which start in
- * [lowerBound,upperBound] are included
- * @param useAbsolutePos
- * have bounds and return values with reference to absolute indices
- * (if false, use indices for visible columns)
* @param useCopyCols
* whether to make a local copy of hiddenColumns for iteration (set
* to true if calling from outwith the HiddenColumns class)
return result;
}
}
+
+ public class VisibleColsIterator implements Iterator<Integer>
+ {
+ private int last;
+
+ private int current;
+
+ private int next;
+
+ private List<int[]> localHidden = new ArrayList<>();
+
+ private int lasthiddenregion;
+
+ public VisibleColsIterator(int firstcol, int lastcol, boolean useCopy)
+ {
+ last = lastcol;
+ current = firstcol;
+ next = firstcol;
+ lasthiddenregion = -1;
+
+ try
+ {
+ if (useCopy)
+ {
+ // assume that if useCopy is false the calling code has locked
+ // hiddenColumns
+ LOCK.readLock().lock();
+ }
+
+ if (hiddenColumns != null)
+ {
+ int i = 0;
+ for (i = 0; i < hiddenColumns.size(); ++i)
+ {
+ if (current >= hiddenColumns.get(i)[0]
+ && current <= hiddenColumns.get(i)[1])
+ {
+ // current is hidden, move to right
+ current = hiddenColumns.get(i)[1] + 1;
+ next = current;
+ }
+ if (current < hiddenColumns.get(i)[0])
+ {
+ break;
+ }
+ }
+
+ lasthiddenregion = i - 1;
+
+ for (i = hiddenColumns.size() - 1; i >= 0; --i)
+ {
+ if (last >= hiddenColumns.get(i)[0]
+ && last <= hiddenColumns.get(i)[1])
+ {
+ // last is hidden, move to left
+ last = hiddenColumns.get(i)[0] - 1;
+ }
+ if (last > hiddenColumns.get(i)[1])
+ {
+ break;
+ }
+ }
+
+ // make a local copy of the bit we need
+ i = lasthiddenregion + 1;
+ while (i < hiddenColumns.size()
+ && hiddenColumns.get(i)[0] <= last)
+ {
+ int[] region = new int[] { hiddenColumns.get(i)[0],
+ hiddenColumns.get(i)[1] };
+ localHidden.add(region);
+ i++;
+ }
+ lasthiddenregion = -1;
+ }
+ } finally
+ {
+ if (useCopy)
+ {
+ LOCK.readLock().unlock();
+ }
+ }
+ }
+
+ @Override
+ public boolean hasNext()
+ {
+ return next <= last;
+ }
+
+ @Override
+ public Integer next()
+ {
+ if (next > last)
+ {
+ throw new NoSuchElementException();
+ }
+ current = next;
+ if ((localHidden != null)
+ && (lasthiddenregion + 1 < localHidden.size()))
+ {
+ // still some more hidden regions
+ if (next + 1 < localHidden.get(lasthiddenregion + 1)[0])
+ {
+ // next+1 is still before the next hidden region
+ next++;
+ }
+ else if ((next + 1 >= localHidden.get(lasthiddenregion + 1)[0])
+ && (next + 1 <= localHidden.get(lasthiddenregion + 1)[1]))
+ {
+ // next + 1 is in the next hidden region
+ next = localHidden.get(lasthiddenregion + 1)[1] + 1;
+ lasthiddenregion++;
+ }
+ }
+ else
+ {
+ // finished with hidden regions, just increment normally
+ next++;
+ }
+ return current;
+ }
+
+ @Override
+ public void remove()
+ {
+ throw new UnsupportedOperationException();
+ }
+ }
}