From 5e92df41fe4f6fa8b50c3a65000bdb8ddcdc901f Mon Sep 17 00:00:00 2001 From: kiramt Date: Fri, 22 Sep 2017 10:50:46 +0100 Subject: [PATCH] JAL-2674 add bounds to findHiddenRegionPositions --- src/jalview/appletgui/ScalePanel.java | 9 +- src/jalview/appletgui/SeqCanvas.java | 9 +- src/jalview/datamodel/HiddenColumns.java | 222 ++++++++----------------- src/jalview/gui/ScalePanel.java | 8 +- src/jalview/gui/SeqCanvas.java | 8 +- test/jalview/datamodel/HiddenColumnsTest.java | 28 +++- 6 files changed, 99 insertions(+), 185 deletions(-) diff --git a/src/jalview/appletgui/ScalePanel.java b/src/jalview/appletgui/ScalePanel.java index 514c3f9..e00db7c 100755 --- a/src/jalview/appletgui/ScalePanel.java +++ b/src/jalview/appletgui/ScalePanel.java @@ -436,17 +436,12 @@ public class ScalePanel extends Panel if (av.getShowHiddenMarkers()) { int widthx = 1 + endx - startx; - List positions = hidden.findHiddenRegionPositions(); + List positions = hidden.findHiddenRegionPositions(startx, + startx + widthx + 1); for (int pos : positions) { - res = pos - startx; - if (res < 0 || res > widthx) - { - continue; - } - gg.fillPolygon( new int[] { -1 + res * avCharWidth - avcharHeight / 4, diff --git a/src/jalview/appletgui/SeqCanvas.java b/src/jalview/appletgui/SeqCanvas.java index f59967d..5667b6e 100755 --- a/src/jalview/appletgui/SeqCanvas.java +++ b/src/jalview/appletgui/SeqCanvas.java @@ -491,16 +491,12 @@ public class SeqCanvas extends Panel implements ViewportListenerI HiddenColumns hidden = av.getAlignment().getHiddenColumns(); g.setColor(Color.blue); int res; - List positions = hidden.findHiddenRegionPositions(); + List positions = hidden.findHiddenRegionPositions(startRes, + endx + 1); for (int pos : positions) { res = pos - startRes; - if (res < 0 || res > endx - startRes) - { - continue; - } - gg.fillPolygon( new int[] { res * avcharWidth - avcharHeight / 4, @@ -510,7 +506,6 @@ public class SeqCanvas extends Panel implements ViewportListenerI { ypos - (avcharHeight / 2), ypos - (avcharHeight / 2), ypos - (avcharHeight / 2) + 8 }, 3); - } } diff --git a/src/jalview/datamodel/HiddenColumns.java b/src/jalview/datamodel/HiddenColumns.java index fe2907d..8380e1f 100644 --- a/src/jalview/datamodel/HiddenColumns.java +++ b/src/jalview/datamodel/HiddenColumns.java @@ -31,6 +31,8 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; public class HiddenColumns { + private static final int HASH_MULTIPLIER = 31; + private static final ReentrantReadWriteLock LOCK = new ReentrantReadWriteLock(); /* @@ -338,10 +340,16 @@ public class HiddenColumns /** * Use this method to determine the set of hiddenRegion start positions + * between absolute position and absolute position + * + * @param start + * absolute residue to start from + * @param end + * absolute residue to end at * - * @return list of column number in visible view where hidden regions start + * @return list of column numbers in *visible* view where hidden regions start */ - public List findHiddenRegionPositions() + public List findHiddenRegionPositions(int start, int end) { try { @@ -352,26 +360,26 @@ public class HiddenColumns { positions = new ArrayList<>(hiddenColumns.size()); - positions.add(hiddenColumns.get(0)[0]); - for (int i = 1; i < hiddenColumns.size(); ++i) + // navigate to start, keeping count of hidden columns + int i = 0; + int hiddenSoFar = 0; + while ((i < hiddenColumns.size()) + && (hiddenColumns.get(i)[0] < start)) { + int[] region = hiddenColumns.get(i); + hiddenSoFar += region[1] - region[0] + 1; + i++; + } - int result = 0; - if (hiddenColumns != null) - { - 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; - } - positions.add(result); + // 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 @@ -660,110 +668,6 @@ public class HiddenColumns } /** - * propagate shift in alignment columns to column selection - * - * @param start - * beginning of edit - * @param left - * shift in edit (+ve for removal, or -ve for inserts) - */ - public List compensateForEdit(int start, int change, - ColumnSelection sel) - { - try - { - LOCK.writeLock().lock(); - List deletedHiddenColumns = null; - - if (hiddenColumns != null) - { - deletedHiddenColumns = new ArrayList<>(); - int hSize = hiddenColumns.size(); - for (int i = 0; i < hSize; i++) - { - int[] region = hiddenColumns.get(i); - if (region[0] > start && start + change > region[1]) - { - deletedHiddenColumns.add(region); - - hiddenColumns.remove(i); - i--; - hSize--; - continue; - } - - if (region[0] > start) - { - region[0] -= change; - region[1] -= change; - } - - if (region[0] < 0) - { - region[0] = 0; - } - - } - - this.revealHiddenColumns(0, sel); - } - - return deletedHiddenColumns; - } finally - { - LOCK.writeLock().unlock(); - } - } - - /** - * propagate shift in alignment columns to column selection special version of - * compensateForEdit - allowing for edits within hidden regions - * - * @param start - * beginning of edit - * @param left - * shift in edit (+ve for removal, or -ve for inserts) - */ - public void compensateForDelEdits(int start, int change) - { - try - { - LOCK.writeLock().lock(); - if (hiddenColumns != null) - { - for (int i = 0; i < hiddenColumns.size(); i++) - { - int[] region = hiddenColumns.get(i); - if (region[0] >= start) - { - region[0] -= change; - } - if (region[1] >= start) - { - region[1] -= change; - } - if (region[1] < region[0]) - { - hiddenColumns.remove(i--); - } - - if (region[0] < 0) - { - region[0] = 0; - } - if (region[1] < 0) - { - region[1] = 0; - } - } - } - } finally - { - LOCK.writeLock().unlock(); - } - } - - /** * return all visible segments between the given start and end boundaries * * @param start @@ -780,45 +684,56 @@ public class HiddenColumns LOCK.readLock().lock(); if (hiddenColumns != null && hiddenColumns.size() > 0) { - List visiblecontigs = new ArrayList<>(); - List regions = getHiddenRegions(); - + // 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[] region; int hideStart; int hideEnd; + int i = 0; - for (int j = 0; vstart < end && j < regions.size(); j++) + for (int[] region : hiddenColumns) { - region = regions.get(j); hideStart = region[0]; hideEnd = region[1]; + // navigate to start if (hideEnd < vstart) { continue; } if (hideStart > vstart) { - visiblecontigs.add(new int[] { vstart, hideStart - 1 }); + vcontigs[i * 2] = vstart; + vcontigs[i * 2 + 1] = hideStart - 1; + i++; } vstart = hideEnd + 1; + + // exit if we're past the end + if (vstart >= end) + { + break; + } } if (vstart < end) { - visiblecontigs.add(new int[] { vstart, end - 1 }); - } - int[] vcontigs = new int[visiblecontigs.size() * 2]; - for (int i = 0, j = visiblecontigs.size(); i < j; i++) - { - int[] vc = visiblecontigs.get(i); - visiblecontigs.set(i, null); - vcontigs[i * 2] = vc[0]; - vcontigs[i * 2 + 1] = vc[1]; + vcontigs[i * 2] = vstart; + vcontigs[i * 2 + 1] = end - 1; + i++; } - visiblecontigs.clear(); - return vcontigs; + + // 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 { @@ -843,17 +758,14 @@ public class HiddenColumns for (int i = 0; i < iSize; i++) { StringBuffer visibleSeq = new StringBuffer(); - List regions = getHiddenRegions(); int blockStart = start; int blockEnd = end; - int[] region; int hideStart; int hideEnd; - for (int j = 0; j < regions.size(); j++) + for (int[] region : hiddenColumns) { - region = regions.get(j); hideStart = region[0]; hideEnd = region[1]; @@ -929,7 +841,6 @@ public class HiddenColumns // boundaries List regions = getHiddenRegions(); int spos = fpos; - int lastvispos = -1; int rcount = 0; int hideStart = seq.getLength(); int hideEnd = -1; @@ -972,7 +883,6 @@ public class HiddenColumns start = p; foundStart = true; } - lastvispos = p; lpos = spos; } // look for next sequence position @@ -1033,17 +943,14 @@ public class HiddenColumns // then mangle the alignmentAnnotation annotation array Vector annels = new Vector<>(); Annotation[] els = null; - List regions = getHiddenRegions(); int blockStart = start; int blockEnd = end; - int[] region; int hideStart; int hideEnd; int w = 0; - for (int j = 0; j < regions.size(); j++) + for (int[] region : hiddenColumns) { - region = regions.get(j); hideStart = region[0]; hideEnd = region[1]; @@ -1060,7 +967,8 @@ public class HiddenColumns break; } - annels.addElement(els = new Annotation[blockEnd - blockStart]); + els = new Annotation[blockEnd - blockStart]; + annels.addElement(els); System.arraycopy(alignmentAnnotation.annotations, blockStart, els, 0, els.length); w += els.length; @@ -1070,7 +978,8 @@ public class HiddenColumns if (end > blockStart) { - annels.addElement(els = new Annotation[end - blockStart + 1]); + els = new Annotation[end - blockStart + 1]; + annels.addElement(els); if ((els.length + blockStart) <= alignmentAnnotation.annotations.length) { @@ -1391,8 +1300,8 @@ public class HiddenColumns { for (int[] hidden : hiddenColumns) { - hashCode = 31 * hashCode + hidden[0]; - hashCode = 31 * hashCode + hidden[1]; + hashCode = HASH_MULTIPLIER * hashCode + hidden[0]; + hashCode = HASH_MULTIPLIER * hashCode + hidden[1]; } } return hashCode; @@ -1537,5 +1446,4 @@ public class HiddenColumns LOCK.readLock().unlock(); } } - } diff --git a/src/jalview/gui/ScalePanel.java b/src/jalview/gui/ScalePanel.java index 7c497d1..4e4db23 100755 --- a/src/jalview/gui/ScalePanel.java +++ b/src/jalview/gui/ScalePanel.java @@ -487,16 +487,12 @@ public class ScalePanel extends JPanel if (av.getShowHiddenMarkers()) { - List positions = hidden.findHiddenRegionPositions(); + List positions = hidden.findHiddenRegionPositions(startx, + startx + widthx + 1); for (int pos : positions) { res = pos - startx; - if (res < 0 || res > widthx) - { - continue; - } - gg.fillPolygon( new int[] { -1 + res * avCharWidth - avCharHeight / 4, diff --git a/src/jalview/gui/SeqCanvas.java b/src/jalview/gui/SeqCanvas.java index 4e896a0..8af99b7 100755 --- a/src/jalview/gui/SeqCanvas.java +++ b/src/jalview/gui/SeqCanvas.java @@ -696,16 +696,12 @@ public class SeqCanvas extends JComponent implements ViewportListenerI g.setColor(Color.blue); int res; HiddenColumns hidden = av.getAlignment().getHiddenColumns(); - List positions = hidden.findHiddenRegionPositions(); + List positions = hidden.findHiddenRegionPositions(startRes, + endx + 1); for (int pos : positions) { res = pos - startRes; - if (res < 0 || res > endx - startRes) - { - continue; - } - gg.fillPolygon( new int[] { res * charWidth - charHeight / 4, diff --git a/test/jalview/datamodel/HiddenColumnsTest.java b/test/jalview/datamodel/HiddenColumnsTest.java index fbf565f..af7ace7 100644 --- a/test/jalview/datamodel/HiddenColumnsTest.java +++ b/test/jalview/datamodel/HiddenColumnsTest.java @@ -795,18 +795,42 @@ public class HiddenColumnsTest { HiddenColumns hc = new HiddenColumns(); - List positions = hc.findHiddenRegionPositions(); + List positions = hc.findHiddenRegionPositions(0, 20); assertTrue(positions.isEmpty()); hc.hideColumns(3, 7); hc.hideColumns(10, 10); hc.hideColumns(14, 15); - positions = hc.findHiddenRegionPositions(); + positions = hc.findHiddenRegionPositions(0, 20); assertEquals(3, positions.size()); assertEquals(3, positions.get(0).intValue()); assertEquals(5, positions.get(1).intValue()); assertEquals(8, positions.get(2).intValue()); + + positions = hc.findHiddenRegionPositions(7, 20); + assertEquals(2, positions.size()); + assertEquals(5, positions.get(0).intValue()); + assertEquals(8, positions.get(1).intValue()); + + positions = hc.findHiddenRegionPositions(11, 13); + assertEquals(0, positions.size()); + + positions = hc.findHiddenRegionPositions(7, 20); + assertEquals(2, positions.size()); + assertEquals(5, positions.get(0).intValue()); + assertEquals(8, positions.get(1).intValue()); + + positions = hc.findHiddenRegionPositions(0, 1); + assertEquals(0, positions.size()); + + positions = hc.findHiddenRegionPositions(17, 20); + assertEquals(0, positions.size()); + + positions = hc.findHiddenRegionPositions(10, 15); + assertEquals(2, positions.size()); + assertEquals(5, positions.get(0).intValue()); + assertEquals(8, positions.get(1).intValue()); } @Test(groups = { "Functional" }) -- 1.7.10.2