public class HiddenColumns
{
private static final ReentrantReadWriteLock LOCK = new ReentrantReadWriteLock();
-
+
/*
* list of hidden column [start, end] ranges; the list is maintained in
* ascending start column order
*/
- private Vector<int[]> hiddenColumns;
+ private ArrayList<int[]> hiddenColumns;
+
+ /**
+ * Constructor
+ */
+ public HiddenColumns()
+ {
+ }
/**
- * This Method is used to return all the HiddenColumn regions
+ * Copy constructor
+ *
+ * @param copy
+ */
+ public HiddenColumns(HiddenColumns copy)
+ {
+ try
+ {
+ LOCK.writeLock().lock();
+ if (copy != null)
+ {
+ if (copy.hiddenColumns != null)
+ {
+ hiddenColumns = copy.copyHiddenRegionsToArrayList();
+ }
+ }
+ } finally
+ {
+ LOCK.writeLock().unlock();
+ }
+ }
+
+ /**
+ * This method is used to return all the HiddenColumn regions and is intended
+ * to remain private. External callers which need a copy of the regions can
+ * call getHiddenColumnsCopyAsList.
*
* @return empty list or List of hidden column intervals
*/
- public List<int[]> getHiddenRegions()
+ private List<int[]> getHiddenRegions()
{
return hiddenColumns == null ? Collections.<int[]> emptyList()
: hiddenColumns;
{
LOCK.readLock().lock();
StringBuilder regionBuilder = new StringBuilder();
- for (int[] range : hiddenColumns)
+ if (hiddenColumns != null)
{
- regionBuilder.append(delimiter).append(range[0]).append(between)
- .append(range[1]);
- }
+ for (int[] range : hiddenColumns)
+ {
+ regionBuilder.append(delimiter).append(range[0]).append(between)
+ .append(range[1]);
+ }
- regionBuilder.deleteCharAt(0);
+ regionBuilder.deleteCharAt(0);
+ }
return regionBuilder.toString();
} finally
{
{
LOCK.readLock().lock();
int size = 0;
- if (hasHidden())
+ if (hasHiddenColumns())
{
for (int[] range : hiddenColumns)
{
}
}
return size;
- }
- finally
- {
- LOCK.readLock().unlock();
- }
- }
-
- /**
- * Answers if there are any hidden columns
- *
- * @return true if there are hidden columns
- */
- public boolean hasHidden()
- {
- try
- {
- LOCK.readLock().lock();
- return (hiddenColumns != null) && (!hiddenColumns.isEmpty());
} finally
{
LOCK.readLock().unlock();
}
-
}
@Override
{
for (int i = 0; i < hiddenColumns.size(); i++)
{
- int[] region = hiddenColumns.elementAt(i);
+ int[] region = hiddenColumns.get(i);
if (result >= region[0])
{
result += region[1] - region[0] + 1;
int[] region;
do
{
- region = hiddenColumns.elementAt(index++);
+ region = hiddenColumns.get(index++);
if (hiddenColumn > region[1])
{
result -= region[1] + 1 - region[0];
{
LOCK.readLock().lock();
- int distance = visibleDistance;
+ int distance = visibleDistance;
- // in case startColumn is in a hidden region, move it to the left
- int start = adjustForHiddenColumns(findColumnPosition(startColumn));
+ // in case startColumn is in a hidden region, move it to the left
+ int start = adjustForHiddenColumns(findColumnPosition(startColumn));
- // get index of hidden region to left of start
- int index = getHiddenIndexLeft(start);
- if (index == -1)
- {
- // no hidden regions to left of startColumn
- return start - distance;
- }
+ // get index of hidden region to left of start
+ int index = getHiddenIndexLeft(start);
+ if (index == -1)
+ {
+ // no hidden regions to left of startColumn
+ return start - distance;
+ }
- // walk backwards through the alignment subtracting the counts of visible
- // columns from distance
- int[] region;
- int gap = 0;
- int nextstart = start;
+ // walk backwards through the alignment subtracting the counts of visible
+ // columns from distance
+ int[] region;
+ int gap = 0;
+ int nextstart = start;
- while ((index > -1) && (distance - gap > 0))
- {
- // subtract the gap to right of region from distance
- distance -= gap;
- start = nextstart;
+ while ((index > -1) && (distance - gap > 0))
+ {
+ // subtract the gap to right of region from distance
+ distance -= gap;
+ start = nextstart;
- // calculate the next gap
- region = hiddenColumns.get(index);
- gap = start - region[1];
+ // calculate the next gap
+ region = hiddenColumns.get(index);
+ gap = start - region[1];
- // set start to just to left of current region
- nextstart = region[0] - 1;
- index--;
- }
+ // set start to just to left of current region
+ nextstart = region[0] - 1;
+ index--;
+ }
- if (distance - gap > 0)
- {
- // fell out of loop because there are no more hidden regions
- distance -= gap;
- return nextstart - distance;
- }
- return start - distance;
+ if (distance - gap > 0)
+ {
+ // fell out of loop because there are no more hidden regions
+ distance -= gap;
+ return nextstart - distance;
+ }
+ return start - distance;
} finally
{
LOCK.readLock().unlock();
try
{
LOCK.readLock().lock();
- List<Integer> positions = new ArrayList<>(
- hiddenColumns.size());
+ List<Integer> positions = null;
- positions.add(hiddenColumns.elementAt(0)[0]);
- for (int i = 1; i < hiddenColumns.size(); ++i)
+ if (hiddenColumns != null)
{
+ positions = new ArrayList<>(hiddenColumns.size());
- int result = 0;
- if (hiddenColumns != null)
+ positions.add(hiddenColumns.get(0)[0]);
+ for (int i = 1; i < hiddenColumns.size(); ++i)
{
- int index = 0;
- int gaps = 0;
- do
+
+ int result = 0;
+ if (hiddenColumns != null)
{
- int[] region = hiddenColumns.elementAt(index);
- gaps += region[1] + 1 - region[0];
- result = region[1] + 1;
- index++;
- } while (index <= i);
+ int index = 0;
+ int gaps = 0;
+ do
+ {
+ int[] region = hiddenColumns.get(index);
+ gaps += region[1] + 1 - region[0];
+ result = region[1] + 1;
+ index++;
+ } while (index <= i);
- result -= gaps;
+ result -= gaps;
+ }
+ positions.add(result);
}
- positions.add(result);
+ }
+ else
+ {
+ positions = new ArrayList<>();
}
return positions;
- }
- finally
+ } finally
{
LOCK.readLock().unlock();
}
int index = 0;
do
{
- int[] region = hiddenColumns.elementAt(index);
+ int[] region = hiddenColumns.get(index);
if (alPos < region[0])
{
return region[0];
{
LOCK.readLock().lock();
- if (hiddenColumns != null)
- {
- int index = hiddenColumns.size() - 1;
- do
+ if (hiddenColumns != null)
{
- int[] region = hiddenColumns.elementAt(index);
- if (alPos > region[1])
+ int index = hiddenColumns.size() - 1;
+ do
{
- return region[1];
- }
+ int[] region = hiddenColumns.get(index);
+ if (alPos > region[1])
+ {
+ return region[1];
+ }
- index--;
- } while (index > -1);
- }
+ index--;
+ } while (index > -1);
+ }
- return alPos;
+ return alPos;
} finally
{
LOCK.readLock().unlock();
{
LOCK.readLock().lock();
- if (hiddenColumns != null)
- {
- int index = hiddenColumns.size() - 1;
- do
+ if (hiddenColumns != null)
{
- int[] region = hiddenColumns.elementAt(index);
- if (pos > region[1])
+ int index = hiddenColumns.size() - 1;
+ do
{
- return index;
- }
+ int[] region = hiddenColumns.get(index);
+ if (pos > region[1])
+ {
+ return index;
+ }
- index--;
- } while (index > -1);
- }
+ index--;
+ } while (index > -1);
+ }
- return -1;
+ return -1;
} finally
{
LOCK.readLock().unlock();
*/
public void hideColumns(int start, int end)
{
- hideColumns(start, end, false);
- }
-
- /**
- * Adds the specified column range to the hidden columns
- *
- * @param start
- * @param end
- */
- private void hideColumns(int start, int end, boolean alreadyLocked)
- {
+ boolean wasAlreadyLocked = false;
try
{
-
- if (!alreadyLocked)
+ // check if the write lock was already locked by this thread,
+ // as this method can be called internally in loops within HiddenColumns
+ if (!LOCK.isWriteLockedByCurrentThread())
{
LOCK.writeLock().lock();
}
+ else
+ {
+ wasAlreadyLocked = true;
+ }
if (hiddenColumns == null)
{
- hiddenColumns = new Vector<>();
+ hiddenColumns = new ArrayList<>();
}
/*
*/
for (int i = 0; i < hiddenColumns.size(); i++)
{
- int[] region = hiddenColumns.elementAt(i);
+ int[] region = hiddenColumns.get(i);
if (end < region[0] - 1)
{
/*
* insert discontiguous preceding range
*/
- hiddenColumns.insertElementAt(new int[] { start, end }, i);
+ hiddenColumns.add(i, new int[] { start, end });
return;
}
}
return;
}
- }
+ }
- /*
- * remaining case is that the new range follows everything else
- */
- hiddenColumns.addElement(new int[] { start, end });
+ /*
+ * remaining case is that the new range follows everything else
+ */
+ hiddenColumns.add(new int[] { start, end });
} finally
{
- if (!alreadyLocked)
+ if (!wasAlreadyLocked)
{
LOCK.writeLock().unlock();
}
{
LOCK.readLock().lock();
- if (hiddenColumns != null)
- {
- for (int[] region : hiddenColumns)
+ if (hiddenColumns != null)
{
- if (column >= region[0] && column <= region[1])
+ for (int[] region : hiddenColumns)
{
- return false;
+ if (column >= region[0] && column <= region[1])
+ {
+ return false;
+ }
}
}
- }
- return true;
+ return true;
} finally
{
LOCK.readLock().unlock();
}
}
- /**
- * ColumnSelection
- */
- public HiddenColumns()
- {
- }
-
- /**
- * Copy constructor
- *
- * @param copy
- */
- public HiddenColumns(HiddenColumns copy)
- {
- try
- {
-
- LOCK.readLock().lock();
- if (copy != null)
- {
- if (copy.hiddenColumns != null)
- {
- hiddenColumns = copy.copyHiddenRegions();
- }
- }
- }
- finally
- {
- LOCK.readLock().unlock();
- }
- }
-
- private Vector<int[]> copyHiddenRegions()
+ private ArrayList<int[]> copyHiddenRegionsToArrayList()
{
- Vector<int[]> copy = new Vector<>(hiddenColumns.size());
- for (int i = 0, j = hiddenColumns.size(); i < j; i++)
+ int size = 0;
+ if (hiddenColumns != null)
{
- int[] rh;
- int[] cp;
- rh = hiddenColumns.elementAt(i);
- if (rh != null)
- {
- cp = new int[rh.length];
- System.arraycopy(rh, 0, cp, 0, rh.length);
- copy.addElement(cp);
- }
+ size = hiddenColumns.size();
}
- return copy;
- }
+ ArrayList<int[]> copy = new ArrayList<>(size);
- private ArrayList<int[]> copyHiddenRegionsToArrayList()
- {
- ArrayList<int[]> copy = new ArrayList<>(hiddenColumns.size());
- for (int i = 0, j = hiddenColumns.size(); i < j; i++)
+ for (int i = 0, j = size; i < j; i++)
{
int[] rh;
int[] cp;
- rh = hiddenColumns.elementAt(i);
+ rh = hiddenColumns.get(i);
if (rh != null)
{
cp = new int[rh.length];
copy.add(cp);
}
}
- return copy;
- }
- public Vector<int[]> getHiddenColumnsCopy()
- {
- try
- {
- LOCK.readLock().lock();
- return copyHiddenRegions();
- } finally
- {
- LOCK.readLock().unlock();
- }
+ return copy;
}
- public ArrayList<int[]> getHiddenColumnsCopyAsList()
+ /**
+ * 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
{
int hSize = hiddenColumns.size();
for (int i = 0; i < hSize; i++)
{
- int[] region = hiddenColumns.elementAt(i);
+ int[] region = hiddenColumns.get(i);
if (region[0] > start && start + change > region[1])
{
deletedHiddenColumns.add(region);
- hiddenColumns.removeElementAt(i);
+ hiddenColumns.remove(i);
i--;
hSize--;
continue;
{
for (int i = 0; i < hiddenColumns.size(); i++)
{
- int[] region = hiddenColumns.elementAt(i);
+ int[] region = hiddenColumns.get(i);
if (region[0] >= start)
{
region[0] -= change;
}
if (region[1] < region[0])
{
- hiddenColumns.removeElementAt(i--);
+ hiddenColumns.remove(i--);
}
if (region[0] < 0)
}
}
}
- }
- finally
+ } finally
{
LOCK.writeLock().unlock();
}
{
return new int[] { start, end - 1 };
}
- }
- finally
+ } finally
{
LOCK.readLock().unlock();
}
{
LOCK.readLock().lock();
int iSize = seqs.length;
- String selections[] = new String[iSize];
+ String[] selections = new String[iSize];
if (hiddenColumns != null && hiddenColumns.size() > 0)
{
for (int i = 0; i < iSize; i++)
}
return selections;
- }
- finally
+ } finally
{
LOCK.readLock().unlock();
}
}
// otherwise, sequence was completely hidden
return new int[] { visPrev, visNext, 0, 0, firstP, lastP };
- }
- finally
+ } finally
{
LOCK.readLock().unlock();
}
{
alignmentAnnotation.restrict(start, end);
}
- }
- finally
+ } finally
{
LOCK.readLock().unlock();
}
List<int[]> inserts = sr.getInsertions();
for (int[] r : inserts)
{
- hideColumns(r[0], r[1], true);
+ hideColumns(r[0], r[1]);
}
} finally
{
{
for (int i = 0; i < hiddenColumns.size(); i++)
{
- int[] region = hiddenColumns.elementAt(i);
+ int[] region = hiddenColumns.get(i);
for (int j = region[0]; j < region[1] + 1; j++)
{
sel.addElement(j);
}
hiddenColumns = null;
- }
- finally
+ } finally
{
LOCK.writeLock().unlock();
}
LOCK.writeLock().lock();
for (int i = 0; i < hiddenColumns.size(); i++)
{
- int[] region = hiddenColumns.elementAt(i);
+ int[] region = hiddenColumns.get(i);
if (start == region[0])
{
for (int j = region[0]; j < region[1] + 1; j++)
sel.addElement(j);
}
- hiddenColumns.removeElement(region);
+ hiddenColumns.remove(region);
break;
}
}
{
hiddenColumns = null;
}
- }
- finally
+ } finally
{
LOCK.writeLock().unlock();
}
* @param intervals
* @return
*/
- private boolean pruneIntervalVector(final List<int[]> shifts,
- Vector<int[]> intervals)
+ private boolean pruneIntervalList(final List<int[]> shifts,
+ ArrayList<int[]> intervals)
{
boolean pruned = false;
int i = 0;
int j = intervals.size() - 1;
int s = 0;
int t = shifts.size() - 1;
- int hr[] = intervals.elementAt(i);
- int sr[] = shifts.get(s);
+ int[] hr = intervals.get(i);
+ int[] sr = shifts.get(s);
while (i <= j && s <= t)
{
boolean trailinghn = hr[1] >= sr[0];
{
if (i < j)
{
- hr = intervals.elementAt(++i);
+ hr = intervals.get(++i);
}
else
{
{
if (trailinghc)
{ // deleted hidden region.
- intervals.removeElementAt(i);
+ intervals.remove(i);
pruned = true;
j--;
if (i <= j)
{
- hr = intervals.elementAt(i);
+ hr = intervals.get(i);
}
continue;
}
// delete any intervals intersecting.
if (hiddenColumns != null)
{
- pruneIntervalVector(shifts, hiddenColumns);
+ pruneIntervalList(shifts, hiddenColumns);
if (hiddenColumns != null && hiddenColumns.size() == 0)
{
hiddenColumns = null;
}
}
- }
- finally
+ } finally
{
LOCK.writeLock().unlock();
}
// recover mapping between sequence's non-gap positions and positions
// mapping to view.
pruneDeletions(ShiftList.parseMap(origseq.gapMap()));
- int[] viscontigs = al.getHiddenColumns().getVisibleContigs(0,
- profileseq.getLength());
+ int[] viscontigs = getVisibleContigs(0, profileseq.getLength());
int spos = 0;
int offset = 0;
}
else
{
- al.getSequenceAt(s).setSequence(
- sq.substring(0, spos + offset) + sb.toString()
- + sq.substring(spos + offset));
+ al.getSequenceAt(s).setSequence(sq.substring(0, spos + offset)
+ + sb.toString() + sq.substring(spos + offset));
}
}
}
{
// pad the final region with gaps.
StringBuffer sb = new StringBuffer();
- for (int s = 0, ns = profileseq.getLength() - spos - offset; s < ns; s++)
+ for (int s = 0, ns = profileseq.getLength() - spos
+ - offset; s < ns; s++)
{
sb.append(gc);
}
}
}
return hashCode;
- }
- finally
+ } finally
{
LOCK.readLock().unlock();
}
.nextSetBit(lastSet))
{
lastSet = inserts.nextClearBit(firstSet);
- hideColumns(firstSet, lastSet - 1, true);
+ hideColumns(firstSet, lastSet - 1);
}
} finally
{
{
inserts.set(range[0], range[1] + 1);
}
- }
- finally
+ } finally
{
LOCK.readLock().unlock();
}
}
+ /**
+ * Finds the hidden region (if any) which starts or ends at res
+ *
+ * @param res
+ * visible residue position, unadjusted for hidden columns
+ * @return region as [start,end] or null if no matching region is found
+ */
+ public int[] getRegionWithEdgeAtRes(int res)
+ {
+ try
+ {
+ LOCK.readLock().lock();
+ int adjres = adjustForHiddenColumns(res);
+
+ int[] reveal = null;
+ if (hiddenColumns != null)
+ {
+ for (int[] region : hiddenColumns)
+ {
+ if (adjres + 1 == region[0] || adjres - 1 == region[1])
+ {
+ reveal = region;
+ break;
+ }
+ }
+ }
+ return reveal;
+ } finally
+ {
+ LOCK.readLock().unlock();
+ }
+ }
+
}