X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fdatamodel%2FHiddenColumns.java;h=d1345e339e319c86e9b49dfa9bad290db36f16db;hb=a0a2e9033dcb76747839e93ea6680b0191a31a79;hp=78629758f43a552be76ae7c7c989195aec06da04;hpb=d35e6861455e97d57143fd7881fb4a35167a2b9d;p=jalview.git diff --git a/src/jalview/datamodel/HiddenColumns.java b/src/jalview/datamodel/HiddenColumns.java index 7862975..d1345e3 100644 --- a/src/jalview/datamodel/HiddenColumns.java +++ b/src/jalview/datamodel/HiddenColumns.java @@ -42,7 +42,8 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; * * - getVisibleColsIterator: iterates over the visible *columns* * - * For performance reasons, provide bounds where possible. + * For performance reasons, provide bounds where possible. Note that column + * numbering begins at 0 throughout this class. * * @author kmourao * @@ -68,7 +69,7 @@ public class HiddenColumns * list of hidden column [start, end] ranges; the list is maintained in * ascending start column order */ - private ArrayList hiddenColumns; + private List hiddenColumns; /** * Constructor @@ -93,29 +94,7 @@ public class HiddenColumns */ public HiddenColumns(HiddenColumns copy) { - try - { - LOCK.writeLock().lock(); - numColumns = 0; - if (copy != null) - { - if (copy.hiddenColumns != null) - { - hiddenColumns = new ArrayList<>(); - Iterator it = copy.iterator(); - while (it.hasNext()) - { - int[] region = it.next(); - hiddenColumns.add(region); - numColumns += region[1] - region[0] + 1; - } - cursor.resetCursor(hiddenColumns); - } - } - } finally - { - LOCK.writeLock().unlock(); - } + this(copy, Integer.MIN_VALUE, Integer.MAX_VALUE, 0); } /** @@ -188,10 +167,28 @@ public class HiddenColumns wasAlreadyLocked = true; } + int previndex = 0; + int prevHiddenCount = 0; + int regionindex = 0; if (hiddenColumns == null) { hiddenColumns = new ArrayList<>(); } + else + { + // set up cursor reset values + HiddenCursorPosition cursorPos = cursor.findRegionForColumn(start); + regionindex = cursorPos.getRegionIndex(); + + if (regionindex > 0) + { + // get previous index and hidden count for updating the cursor later + previndex = regionindex - 1; + int[] prevRegion = hiddenColumns.get(previndex); + prevHiddenCount = cursorPos.getHiddenSoFar() + - (prevRegion[1] - prevRegion[0] + 1); + } + } /* * new range follows everything else; check first to avoid looping over whole hiddenColumns collection @@ -208,18 +205,23 @@ public class HiddenColumns * appropriate */ boolean added = false; - for (int i = 0; !added && i < hiddenColumns.size(); i++) + if (regionindex > 0) { - added = insertRangeAtRegion(i, start, end); - } // for + added = insertRangeAtRegion(regionindex - 1, start, end); + } + if (!added && regionindex < hiddenColumns.size()) + { + insertRangeAtRegion(regionindex, start, end); + } } - if (!wasAlreadyLocked) - { - cursor.resetCursor(hiddenColumns); - // reset the number of columns so they will be recounted - numColumns = 0; - } + // reset the cursor to just before our insertion point: this saves + // a lot of reprocessing in large alignments + cursor.resetCursor(hiddenColumns, previndex, prevHiddenCount); + + // reset the number of columns so they will be recounted + numColumns = 0; + } finally { if (!wasAlreadyLocked) @@ -287,6 +289,9 @@ public class HiddenColumns break; } region[1] = Math.max(nextRegion[1], end); + + // in theory this is faster than hiddenColumns.remove(i+1) + // benchmarking results a bit ambivalent hiddenColumns.subList(i + 1, i + 2).clear(); } added = true; @@ -457,14 +462,14 @@ public class HiddenColumns markHiddenRegions(hidden); hidden.andNot(gaps); hiddenColumns = null; - this.hideMarkedBits(hidden); + this.hideColumns(hidden); // for each sequence in the alignment, except the profile sequence, // insert gaps corresponding to each hidden region but where each hidden // column region is shifted backwards by the number of preceding visible // gaps update hidden columns at the same time Iterator regions = hiddenColumns.iterator(); - ArrayList newhidden = new ArrayList<>(); + List newhidden = new ArrayList<>(); int numGapsBefore = 0; int gapPosition = 0; @@ -618,15 +623,14 @@ public class HiddenColumns { // numColumns is out of date, so recalculate int size = 0; - if (hiddenColumns != null) + + Iterator it = hiddenColumns.iterator(); + while (it.hasNext()) { - Iterator it = hiddenColumns.iterator(); - while (it.hasNext()) - { - int[] range = it.next(); - size += range[1] - range[0] + 1; - } + int[] range = it.next(); + size += range[1] - range[0] + 1; } + numColumns = size; } @@ -710,7 +714,7 @@ public class HiddenColumns * int column index in alignment view (count from zero) * @return alignment column index for column */ - public int adjustForHiddenColumns(int column) + public int visibleToAbsoluteColumn(int column) { try { @@ -719,7 +723,7 @@ public class HiddenColumns if (hiddenColumns != null) { - result += cursor.getHiddenOffset(column).getHiddenSoFar(); + result += cursor.findRegionForVisColumn(column).getHiddenSoFar(); } return result; @@ -732,13 +736,14 @@ public class HiddenColumns /** * Use this method to find out where a column will appear in the visible * alignment when hidden columns exist. If the column is not visible, then the - * left-most visible column will always be returned. + * index of the next visible column on the left will be returned (or 0 if + * there is no visible column on the left) * * @param hiddenColumn * the column index in the full alignment including hidden columns * @return the position of the column in the visible alignment */ - public int findColumnPosition(int hiddenColumn) + public int absoluteToVisibleColumn(int hiddenColumn) { try { @@ -804,7 +809,7 @@ public class HiddenColumns int distance = visibleDistance; // in case startColumn is in a hidden region, move it to the left - int start = adjustForHiddenColumns(findColumnPosition(startColumn)); + int start = visibleToAbsoluteColumn(absoluteToVisibleColumn(startColumn)); Iterator it = new ReverseRegionsIterator(0, start, hiddenColumns); @@ -843,6 +848,8 @@ public class HiddenColumns * @param alPos * the absolute (visible) alignmentPosition to find the next hidden * column for + * @return the index of the next hidden column, or alPos if there is no next + * hidden column */ public int getHiddenBoundaryRight(int alPos) { @@ -925,7 +932,9 @@ public class HiddenColumns if (regionindex > -1 && regionindex < hiddenColumns.size()) { int[] region = hiddenColumns.get(regionindex); - if (column >= region[0] && column <= region[1]) + // already know that column <= region[1] as cursor returns containing + // region or region to right + if (column >= region[0]) { return false; } @@ -1057,7 +1066,7 @@ public class HiddenColumns if (foundStart) { - return findColumnPosition(start); + return absoluteToVisibleColumn(start); } // otherwise, sequence was completely hidden return visPrev; @@ -1075,8 +1084,12 @@ public class HiddenColumns */ public void makeVisibleAnnotation(AlignmentAnnotation alignmentAnnotation) { - makeVisibleAnnotation(0, alignmentAnnotation.annotations.length, + if (alignmentAnnotation != null + && alignmentAnnotation.annotations != null) + { + makeVisibleAnnotation(0, alignmentAnnotation.annotations.length, alignmentAnnotation); + } } /** @@ -1100,7 +1113,8 @@ public class HiddenColumns int startFrom = start; int endAt = end; - if (alignmentAnnotation.annotations != null) + if (alignmentAnnotation != null + && alignmentAnnotation.annotations != null) { if (hiddenColumns != null && hiddenColumns.size() > 0) { @@ -1185,6 +1199,9 @@ public class HiddenColumns try { LOCK.readLock().lock(); + + // we don't use getSize()>0 here because it has to iterate over + // the full hiddenColumns collection and so will be much slower return hiddenColumns != null && hiddenColumns.size() > 0; } finally { @@ -1194,9 +1211,9 @@ public class HiddenColumns /** * - * @return true if there are more than one set of columns hidden + * @return true if there is more than one hidden column region */ - public boolean hasManyHiddenColumns() + public boolean hasMultiHiddenColumnRegions() { try { @@ -1239,7 +1256,7 @@ public class HiddenColumns * @param inserts * - columns map to bits starting from zero */ - public void hideMarkedBits(BitSet inserts) + public void hideColumns(BitSet inserts) { try { @@ -1317,7 +1334,7 @@ public class HiddenColumns higestRange = (range[1] >= endPos) ? range : higestRange; } - if (lowestRange[0] == -1 && lowestRange[1] == -1) + if (lowestRange[0] == -1) // includes (lowestRange[1] == -1) { startPos = alignmentStartEnd[0]; } @@ -1326,7 +1343,7 @@ public class HiddenColumns startPos = lowestRange[1] + 1; } - if (higestRange[0] == -1 && higestRange[1] == -1) + if (higestRange[0] == -1) // includes (higestRange[1] == -1) { endPos = alignmentStartEnd[1]; } @@ -1346,14 +1363,15 @@ public class HiddenColumns * * @param res * visible residue position, unadjusted for hidden columns - * @return region as [start,end] or null if no matching region is found + * @return region as [start,end] or null if no matching region is found. If + * res is adjacent to two regions, returns the left region. */ public int[] getRegionWithEdgeAtRes(int res) { try { LOCK.readLock().lock(); - int adjres = adjustForHiddenColumns(res); + int adjres = visibleToAbsoluteColumn(res); int[] reveal = null; @@ -1373,16 +1391,6 @@ public class HiddenColumns { reveal = hiddenColumns.get(regionindex); } - // or try the next region - else - { - regionindex++; - if (regionindex < hiddenColumns.size() - && hiddenColumns.get(regionindex)[0] == adjres + 1) - { - reveal = hiddenColumns.get(regionindex); - } - } } return reveal; @@ -1400,7 +1408,7 @@ public class HiddenColumns try { LOCK.readLock().lock(); - return new BoundedHiddenColsIterator(hiddenColumns); + return new HiddenColsIterator(hiddenColumns); } finally { LOCK.readLock().unlock(); @@ -1421,7 +1429,7 @@ public class HiddenColumns try { LOCK.readLock().lock(); - return new BoundedHiddenColsIterator(start, end, hiddenColumns); + return new HiddenColsIterator(start, end, hiddenColumns); } finally { LOCK.readLock().unlock(); @@ -1444,7 +1452,7 @@ public class HiddenColumns LOCK.readLock().lock(); // get absolute position of column in alignment - int absoluteStart = adjustForHiddenColumns(start); + int absoluteStart = visibleToAbsoluteColumn(start); // Get cursor position and supply it to the iterator: // Since we want visible region start, we look for a cursor for the @@ -1502,8 +1510,8 @@ public class HiddenColumns int adjend = end; if (useVisibleCoords) { - adjstart = adjustForHiddenColumns(start); - adjend = adjustForHiddenColumns(end); + adjstart = visibleToAbsoluteColumn(start); + adjend = visibleToAbsoluteColumn(end); } try