}
+ /**
+ * Construct an iterator over hiddenColums bounded at [lowerBound,upperBound]
+ *
+ * @param pos
+ * a hidden cursor position to start from - may be null
+ * @param lowerBound
+ * lower bound to iterate from - will be ignored if pos != null
+ * @param upperBound
+ * upper bound to iterate to
+ * @param hiddenColumns
+ * the hidden columns collection to use
+ */
+ BoundedStartRegionIterator(HiddenCursorPosition pos, int lowerBound,
+ int upperBound, List<int[]> hiddenColumns)
+ {
+ start = lowerBound;
+ end = upperBound;
+
+ if (hiddenColumns != null)
+ {
+ positions = new ArrayList<>(hiddenColumns.size());
+
+ // navigate to start, keeping count of hidden columns
+ int i = 0;
+ int hiddenSoFar = 0;
+
+ if (pos != null)
+ {
+ // use the cursor position provided
+ i = pos.getRegionIndex();
+ hiddenSoFar = pos.getHiddenSoFar();
+ }
+ else
+ {
+ // navigate to start
+ while ((i < hiddenColumns.size())
+ && (hiddenColumns.get(i)[0] < start + hiddenSoFar))
+ {
+ int[] region = hiddenColumns.get(i);
+ hiddenSoFar += region[1] - region[0] + 1;
+ i++;
+ }
+ }
+
+ // 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 + hiddenSoFar))
+ {
+ int[] region = hiddenColumns.get(i);
+ positions.add(region[0] - hiddenSoFar);
+ hiddenSoFar += region[1] - region[0] + 1;
+ i++;
+ }
+ }
+ else
+ {
+ positions = new ArrayList<>();
+ }
+
+ }
+
@Override
public boolean hasNext()
{
try
{
LOCK.readLock().lock();
- return new BoundedStartRegionIterator(start, end, hiddenColumns);
+
+ // get absolute position of column in alignment
+ int absoluteStart = adjustForHiddenColumns(start);
+
+ // Get cursor position and supply it to the iterator:
+ // Since we want visible region start, we look for a cursor for the
+ // (absoluteStart-1), then if absoluteStart is the start of a visible
+ // region we'll get the cursor pointing to the region before, which is
+ // what we want
+ HiddenCursorPosition pos = cursor
+ .findRegionForColumn(absoluteStart - 1);
+
+ return new BoundedStartRegionIterator(pos, start, end,
+ hiddenColumns);
} finally
{
LOCK.readLock().unlock();
* boundaries
*
* @param start
- * (first column inclusive from 0)
+ * first column, inclusive from 0, absolute value
* @param end
- * (last column - not inclusive)
+ * last column - not inclusive, absolute value
*/
public Iterator<int[]> getVisContigsIterator(int start, int end)
{
public Iterator<int[]> getVisibleBlocksIterator(int start, int end,
boolean useVisibleCoords)
{
+ int adjstart = start;
+ int adjend = end;
if (useVisibleCoords)
{
- // TODO
- // we should really just convert start and end here with
- // adjustForHiddenColumns
- // and then create a VisibleContigsIterator
- // but without a cursor this will be horribly slow in some situations
- // ... so until then...
- // return new VisibleBlocksVisBoundsIterator(start, end, true);
- try
- {
- LOCK.readLock().lock();
- int adjstart = adjustForHiddenColumns(start);
- int adjend = adjustForHiddenColumns(end);
- return new VisibleContigsIterator(adjstart, adjend + 1,
- hiddenColumns);
- } finally
- {
- LOCK.readLock().unlock();
- }
+ adjstart = adjustForHiddenColumns(start);
+ adjend = adjustForHiddenColumns(end);
}
- else
- {
- try
- {
- LOCK.readLock().lock();
- return new VisibleContigsIterator(start, end + 1, hiddenColumns);
- } finally
- {
- LOCK.readLock().unlock();
- }
- }
- }
-
- /**
- * An iterator which iterates over visible regions in a range. The range is
- * specified in terms of visible column positions. Provides a special
- * "endsAtHidden" indicator to allow callers to determine if the final visible
- * column is adjacent to a hidden region.
- */
- public class VisibleBlocksVisBoundsIterator implements Iterator<int[]>
- {
- private List<int[]> vcontigs = new ArrayList<>();
-
- private int currentPosition = 0;
-
- private boolean endsAtHidden = false;
-
- /**
- * Constructor for iterator over visible regions in a range.
- *
- * @param start
- * start position in terms of visible column position
- * @param end
- * end position in terms of visible column position
- * @param usecopy
- * whether to use a local copy of hidden columns
- */
- VisibleBlocksVisBoundsIterator(int start, int end, boolean usecopy)
- {
- /* actually this implementation always uses a local copy but this may change in future */
- try
- {
- if (usecopy)
- {
- LOCK.readLock().lock();
- }
-
- if (hiddenColumns != null && hiddenColumns.size() > 0)
- {
- int blockStart = start;
- int blockEnd = end;
- int hiddenSoFar = 0;
- int visSoFar = 0;
-
- // iterate until a region begins within (start,end]
- int i = 0;
- while ((i < hiddenColumns.size())
- && (hiddenColumns.get(i)[0] <= blockStart + hiddenSoFar))
- {
- hiddenSoFar += hiddenColumns.get(i)[1] - hiddenColumns.get(i)[0]
- + 1;
- i++;
- }
-
- blockStart += hiddenSoFar; // convert start to absolute position
- blockEnd += hiddenSoFar; // convert end to absolute position
-
- // iterate from start to end, adding each visible region. Positions
- // are
- // absolute, and all hidden regions which overlap [start,end] are
- // used.
- while (i < hiddenColumns.size()
- && (hiddenColumns.get(i)[0] <= blockEnd))
- {
- int[] region = hiddenColumns.get(i);
-
- // end position of this visible region is either just before the
- // start of the next hidden region, or the absolute position of
- // 'end', whichever is lowest
- blockEnd = Math.min(blockEnd, region[0] - 1);
-
- vcontigs.add(new int[] { blockStart, blockEnd });
- visSoFar += blockEnd - blockStart + 1;
-
- // next visible region starts after this hidden region
- blockStart = region[1] + 1;
-
- hiddenSoFar += region[1] - region[0] + 1;
-
- // reset blockEnd to absolute position of 'end', assuming we've now
- // passed all hidden regions before end
- blockEnd = end + hiddenSoFar;
-
- i++;
- }
- if (visSoFar < end - start + 1)
- {
- // the number of visible columns we've accounted for is less than
- // the number specified by end-start; work out the end position of
- // the last visible region
- blockEnd = blockStart + end - start - visSoFar;
- vcontigs.add(new int[] { blockStart, blockEnd });
-
- // if the last visible region ends at the next hidden region, set
- // endsAtHidden=true
- if (i < hiddenColumns.size()
- && hiddenColumns.get(i)[0] - 1 == blockEnd)
- {
- endsAtHidden = true;
- }
- }
- }
- else
- {
- // there are no hidden columns, return a single visible contig
- vcontigs.add(new int[] { start, end });
- endsAtHidden = false;
- }
- } finally
- {
- if (usecopy)
- {
- LOCK.readLock().unlock();
- }
- }
- }
-
- @Override
- public boolean hasNext()
- {
- return (currentPosition < vcontigs.size());
- }
-
- @Override
- public int[] next()
+ try
{
- int[] result = vcontigs.get(currentPosition);
- currentPosition++;
- return result;
- }
+ LOCK.readLock().lock();
- public boolean endsAtHidden()
+ return new VisibleContigsIterator(adjstart, adjend + 1,
+ hiddenColumns);
+ } finally
{
- return endsAtHidden;
+ LOCK.readLock().unlock();
}
}
}
// Could be done with synchronisation but benchmarking shows this way is 2x
// faster
private final AtomicReference<HiddenCursorPosition> cursorPos = new AtomicReference<>(
- new HiddenCursorPosition(0, 0, 0));
+ new HiddenCursorPosition(0, 0));
protected HiddenColumnsCursor()
{
{
firstColumn = hiddenColumns.get(0)[0];
HiddenCursorPosition oldpos = cursorPos.get();
- HiddenCursorPosition newpos = new HiddenCursorPosition(0, 0, 0);
+ HiddenCursorPosition newpos = new HiddenCursorPosition(0, 0);
cursorPos.compareAndSet(oldpos, newpos);
}
}
// update the cursor position
HiddenCursorPosition newpos = new HiddenCursorPosition(index,
- oldpos.getHiddenSoFar(), oldpos.getNumColumns());
+ oldpos.getHiddenSoFar());
cursorPos.compareAndSet(oldpos, newpos);
}
hiddenColumns = hiddenCols;
}
}
HiddenCursorPosition newpos = new HiddenCursorPosition(index,
- hiddenCount, oldpos.getNumColumns());
+ hiddenCount);
cursorPos.compareAndSet(oldpos, newpos);
return newpos;
}
}
HiddenCursorPosition newpos = new HiddenCursorPosition(index,
- hiddenCount, oldpos.getNumColumns());
+ hiddenCount);
cursorPos.compareAndSet(oldpos, newpos);
return newpos;
}