X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fdatamodel%2FColumnSelection.java;h=6fb584ca4774b3ec6a2ab2996d101d567d642af0;hb=f41f5deaf0c8c1bbfb3fe4ca8be208d27b8e11d7;hp=0655660e4ad9da84136ec807586e075da0c36e95;hpb=a8f483d04205bb8273ee311c12968b7e86d205fa;p=jalview.git diff --git a/src/jalview/datamodel/ColumnSelection.java b/src/jalview/datamodel/ColumnSelection.java index 0655660..6fb584c 100644 --- a/src/jalview/datamodel/ColumnSelection.java +++ b/src/jalview/datamodel/ColumnSelection.java @@ -1,36 +1,49 @@ /* - * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2) - * Copyright (C) 2014 The Jalview Authors + * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) + * Copyright (C) $$Year-Rel$$ The Jalview Authors * * This file is part of Jalview. * * Jalview is free software: you can redistribute it and/or * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. * * Jalview is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License along with Jalview. If not, see . + * You should have received a copy of the GNU General Public License + * along with Jalview. If not, see . * The Jalview Authors are detailed in the 'AUTHORS' file. */ package jalview.datamodel; -import java.util.*; +import jalview.util.ShiftList; +import jalview.viewmodel.annotationfilter.AnnotationFilterParameter; +import jalview.viewmodel.annotationfilter.AnnotationFilterParameter.SearchableAnnotationField; -import jalview.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Vector; /** * NOTE: Columns are zero based. */ public class ColumnSelection { - Vector selected = new Vector(); + /* + * list of selected columns (not ordered) + */ + Vector selected = new Vector(); - // Vector of int [] {startCol, endCol} - Vector hiddenColumns; + /* + * list of hidden column [start, end] ranges; the list is maintained in + * ascending start column order + */ + Vector hiddenColumns; /** * Add a column to the selection @@ -56,7 +69,7 @@ public class ColumnSelection } /** - * removes col from selection + * Removes value 'col' from the selection (not the col'th item) * * @param col * index of column to be removed @@ -67,6 +80,8 @@ public class ColumnSelection if (selected.contains(colInt)) { + // if this ever changes to List.remove(), ensure Integer not int argument + // as List.remove(int i) removes the i'th item which is wrong selected.removeElement(colInt); } } @@ -93,10 +108,10 @@ public class ColumnSelection } /** - * - * @return Vector containing selected columns as Integers + * Returns a list of selected columns. The list contains no duplicates but is + * not necessarily ordered. */ - public Vector getSelected() + public List getSelected() { return selected; } @@ -114,26 +129,11 @@ public class ColumnSelection } /** - * Column number at position i in selection - * - * @param i - * index into selected columns - * - * @return column number in alignment - */ - public int columnAt(int i) - { - return ((Integer) selected.elementAt(i)).intValue(); - } - - /** - * DOCUMENT ME! - * - * @return DOCUMENT ME! + * Answers true if no columns are selected, else false */ - public int size() + public boolean isEmpty() { - return selected.size(); + return selected == null || selected.isEmpty(); } /** @@ -145,11 +145,11 @@ public class ColumnSelection { int max = -1; - for (int i = 0; i < selected.size(); i++) + for (int sel : getSelected()) { - if (columnAt(i) > max) + if (sel > max) { - max = columnAt(i); + max = sel; } } @@ -165,11 +165,11 @@ public class ColumnSelection { int min = 1000000000; - for (int i = 0; i < selected.size(); i++) + for (int sel : getSelected()) { - if (columnAt(i) < min) + if (sel < min) { - min = columnAt(i); + min = sel; } } @@ -184,29 +184,30 @@ public class ColumnSelection * @param left * shift in edit (+ve for removal, or -ve for inserts) */ - public Vector compensateForEdit(int start, int change) + public List compensateForEdit(int start, int change) { - Vector deletedHiddenColumns = null; - for (int i = 0; i < size(); i++) + List deletedHiddenColumns = null; + for (int i = 0; i < selected.size(); i++) { - int temp = columnAt(i); + int temp = selected.get(i); if (temp >= start) { + // if this ever changes to List.set(), swap parameter order!! selected.setElementAt(new Integer(temp - change), i); } } if (hiddenColumns != null) { - deletedHiddenColumns = new Vector(); + deletedHiddenColumns = new ArrayList(); int hSize = hiddenColumns.size(); for (int i = 0; i < hSize; i++) { - int[] region = (int[]) hiddenColumns.elementAt(i); + int[] region = hiddenColumns.elementAt(i); if (region[0] > start && start + change > region[1]) { - deletedHiddenColumns.addElement(hiddenColumns.elementAt(i)); + deletedHiddenColumns.add(region); hiddenColumns.removeElementAt(i); i--; @@ -244,12 +245,13 @@ public class ColumnSelection */ private void compensateForDelEdits(int start, int change) { - for (int i = 0; i < size(); i++) + for (int i = 0; i < selected.size(); i++) { - int temp = columnAt(i); + int temp = selected.get(i); if (temp >= start) { + // if this ever changes to List.set(), must swap parameter order!!! selected.setElementAt(new Integer(temp - change), i); } } @@ -258,7 +260,7 @@ public class ColumnSelection { for (int i = 0; i < hiddenColumns.size(); i++) { - int[] region = (int[]) hiddenColumns.elementAt(i); + int[] region = hiddenColumns.elementAt(i); if (region[0] >= start) { region[0] -= change; @@ -295,13 +297,13 @@ public class ColumnSelection { if (shiftrecord != null) { - Vector shifts = shiftrecord.shifts; + final List shifts = shiftrecord.getShifts(); if (shifts != null && shifts.size() > 0) { int shifted = 0; for (int i = 0, j = shifts.size(); i < j; i++) { - int[] sh = (int[]) shifts.elementAt(i); + int[] sh = shifts.get(i); // compensateForEdit(shifted+sh[0], sh[1]); compensateForDelEdits(shifted + sh[0], sh[1]); shifted -= sh[1]; @@ -316,16 +318,17 @@ public class ColumnSelection * removes intersection of position,length ranges in deletions from the * start,end regions marked in intervals. * - * @param deletions + * @param shifts * @param intervals * @return */ - private boolean pruneIntervalVector(Vector deletions, Vector intervals) + private boolean pruneIntervalVector(final List shifts, + Vector intervals) { boolean pruned = false; - int i = 0, j = intervals.size() - 1, s = 0, t = deletions.size() - 1; - int hr[] = (int[]) intervals.elementAt(i); - int sr[] = (int[]) deletions.elementAt(s); + int i = 0, j = intervals.size() - 1, s = 0, t = shifts.size() - 1; + int hr[] = intervals.elementAt(i); + int sr[] = shifts.get(s); while (i <= j && s <= t) { boolean trailinghn = hr[1] >= sr[0]; @@ -333,7 +336,7 @@ public class ColumnSelection { if (i < j) { - hr = (int[]) intervals.elementAt(++i); + hr = intervals.elementAt(++i); } else { @@ -346,7 +349,7 @@ public class ColumnSelection { // leadinghc disjoint or not a deletion if (s < t) { - sr = (int[]) deletions.elementAt(++s); + sr = shifts.get(++s); } else { @@ -366,7 +369,7 @@ public class ColumnSelection j--; if (i <= j) { - hr = (int[]) intervals.elementAt(i); + hr = intervals.elementAt(i); } continue; } @@ -392,7 +395,7 @@ public class ColumnSelection // sr contained in hr if (s < t) { - sr = (int[]) deletions.elementAt(++s); + sr = shifts.get(++s); } else { @@ -406,15 +409,16 @@ public class ColumnSelection // operations. } - private boolean pruneColumnList(Vector deletion, Vector list) + private boolean pruneColumnList(final List shifts, + Vector list) { - int s = 0, t = deletion.size(); - int[] sr = (int[]) list.elementAt(s++); + int s = 0, t = shifts.size(); + int[] sr = shifts.get(s++); boolean pruned = false; int i = 0, j = list.size(); while (i < j && s <= t) { - int c = ((Integer) list.elementAt(i++)).intValue(); + int c = list.elementAt(i++).intValue(); if (sr[0] <= c) { if (sr[1] + sr[0] >= c) @@ -426,7 +430,7 @@ public class ColumnSelection { if (s < t) { - sr = (int[]) deletion.elementAt(s); + sr = shifts.get(s); } s++; } @@ -445,7 +449,7 @@ public class ColumnSelection { if (deletions != null) { - Vector shifts = deletions.shifts; + final List shifts = deletions.getShifts(); if (shifts != null && shifts.size() > 0) { // delete any intervals intersecting. @@ -472,16 +476,14 @@ public class ColumnSelection } /** - * This Method is used to return all the HiddenColumn regions less than the - * given index. + * This Method is used to return all the HiddenColumn regions * - * @param end - * int - * @return Vector + * @return empty list or List of hidden column intervals */ - public Vector getHiddenColumns() + public List getHiddenColumns() { - return hiddenColumns; + return hiddenColumns == null ? Collections. emptyList() + : hiddenColumns; } /** @@ -498,7 +500,7 @@ public class ColumnSelection { for (int i = 0; i < hiddenColumns.size(); i++) { - int[] region = (int[]) hiddenColumns.elementAt(i); + int[] region = hiddenColumns.elementAt(i); if (result >= region[0]) { result += region[1] - region[0] + 1; @@ -526,7 +528,7 @@ public class ColumnSelection int[] region; do { - region = (int[]) hiddenColumns.elementAt(index++); + region = hiddenColumns.elementAt(index++); if (hiddenColumn > region[1]) { result -= region[1] + 1 - region[0]; @@ -552,7 +554,7 @@ public class ColumnSelection int gaps = 0; do { - int[] region = (int[]) hiddenColumns.elementAt(index); + int[] region = hiddenColumns.elementAt(index); if (hiddenRegion == 0) { return region[0]; @@ -583,7 +585,7 @@ public class ColumnSelection int index = 0; do { - int[] region = (int[]) hiddenColumns.elementAt(index); + int[] region = hiddenColumns.elementAt(index); if (alPos < region[0]) { return region[0]; @@ -611,7 +613,7 @@ public class ColumnSelection int index = hiddenColumns.size() - 1; do { - int[] region = (int[]) hiddenColumns.elementAt(index); + int[] region = hiddenColumns.elementAt(index); if (alPos > region[1]) { return region[1]; @@ -627,65 +629,89 @@ public class ColumnSelection public void hideSelectedColumns() { - while (size() > 0) + while (!selected.isEmpty()) { - int column = ((Integer) getSelected().firstElement()).intValue(); + int column = selected.get(0).intValue(); hideColumns(column); } } + /** + * Adds the specified column range to the hidden columns + * + * @param start + * @param end + */ public void hideColumns(int start, int end) { if (hiddenColumns == null) { - hiddenColumns = new Vector(); + hiddenColumns = new Vector(); } - boolean added = false; - boolean overlap = false; - + /* + * traverse existing hidden ranges and insert / amend / append as + * appropriate + */ for (int i = 0; i < hiddenColumns.size(); i++) { - int[] region = (int[]) hiddenColumns.elementAt(i); - if (start <= region[1] && end >= region[0]) + int[] region = hiddenColumns.elementAt(i); + + if (end < region[0] - 1) { - hiddenColumns.removeElementAt(i); - overlap = true; - break; + /* + * insert discontiguous preceding range + */ + hiddenColumns.insertElementAt(new int[] { start, end }, i); + return; } - else if (end < region[0] && start < region[0]) + + if (end <= region[1]) { - hiddenColumns.insertElementAt(new int[] - { start, end }, i); - added = true; - break; + /* + * new range overlaps existing, or is contiguous preceding it - adjust + * start column + */ + region[0] = Math.min(region[0], start); + return; } - } - if (overlap) - { - hideColumns(start, end); - } - else if (!added) - { - hiddenColumns.addElement(new int[] - { start, end }); + if (start <= region[1] + 1) + { + /* + * new range overlaps existing, or is contiguous following it - adjust + * start and end columns + */ + region[0] = Math.min(region[0], start); + region[1] = Math.max(region[1], end); + return; + } } + /* + * remaining case is that the new range follows everything else + */ + hiddenColumns.addElement(new int[] { start, end }); } /** - * This method will find a range of selected columns around the column - * specified + * Hides the specified column and any adjacent selected columns * * @param res * int */ public void hideColumns(int col) { - // First find out range of columns to hide - int min = col, max = col + 1; + /* + * deselect column (whether selected or not!) + */ + removeElement(col); + + /* + * find adjacent selected columns + */ + int min = col - 1, max = col + 1; while (contains(min)) { removeElement(min); @@ -698,6 +724,9 @@ public class ColumnSelection max++; } + /* + * min, max are now the closest unselected columns + */ min++; max--; if (min > max) @@ -708,13 +737,16 @@ public class ColumnSelection hideColumns(min, max); } + /** + * Unhides, and adds to the selection list, all hidden columns + */ public void revealAllHiddenColumns() { if (hiddenColumns != null) { for (int i = 0; i < hiddenColumns.size(); i++) { - int[] region = (int[]) hiddenColumns.elementAt(i); + int[] region = hiddenColumns.elementAt(i); for (int j = region[0]; j < region[1] + 1; j++) { addElement(j); @@ -725,12 +757,18 @@ public class ColumnSelection hiddenColumns = null; } - public void revealHiddenColumns(int res) + /** + * Reveals, and marks as selected, the hidden column range with the given + * start column + * + * @param start + */ + public void revealHiddenColumns(int start) { for (int i = 0; i < hiddenColumns.size(); i++) { - int[] region = (int[]) hiddenColumns.elementAt(i); - if (res == region[0]) + int[] region = hiddenColumns.elementAt(i); + if (start == region[0]) { for (int j = region[0]; j < region[1] + 1; j++) { @@ -750,14 +788,15 @@ public class ColumnSelection public boolean isVisible(int column) { if (hiddenColumns != null) - for (int i = 0; i < hiddenColumns.size(); i++) + { + for (int[] region : hiddenColumns) { - int[] region = (int[]) hiddenColumns.elementAt(i); if (column >= region[0] && column <= region[1]) { return false; } } + } return true; } @@ -773,7 +812,7 @@ public class ColumnSelection { if (copy.selected != null) { - selected = new Vector(); + selected = new Vector(); for (int i = 0, j = copy.selected.size(); i < j; i++) { selected.addElement(copy.selected.elementAt(i)); @@ -781,11 +820,11 @@ public class ColumnSelection } if (copy.hiddenColumns != null) { - hiddenColumns = new Vector(copy.hiddenColumns.size()); + hiddenColumns = new Vector(copy.hiddenColumns.size()); for (int i = 0, j = copy.hiddenColumns.size(); i < j; i++) { int[] rh, cp; - rh = (int[]) copy.hiddenColumns.elementAt(i); + rh = copy.hiddenColumns.elementAt(i); if (rh != null) { cp = new int[rh.length]; @@ -814,7 +853,7 @@ public class ColumnSelection for (i = 0; i < iSize; i++) { StringBuffer visibleSeq = new StringBuffer(); - Vector regions = getHiddenColumns(); + List regions = getHiddenColumns(); int blockStart = start, blockEnd = end; int[] region; @@ -822,7 +861,7 @@ public class ColumnSelection for (int j = 0; j < regions.size(); j++) { - region = (int[]) regions.elementAt(j); + region = regions.get(j); hideStart = region[0]; hideEnd = region[1]; @@ -878,8 +917,8 @@ public class ColumnSelection { if (hiddenColumns != null && hiddenColumns.size() > 0) { - Vector visiblecontigs = new Vector(); - Vector regions = getHiddenColumns(); + List visiblecontigs = new ArrayList(); + List regions = getHiddenColumns(); int vstart = start; int[] region; @@ -887,7 +926,7 @@ public class ColumnSelection for (int j = 0; vstart < end && j < regions.size(); j++) { - region = (int[]) regions.elementAt(j); + region = regions.get(j); hideStart = region[0]; hideEnd = region[1]; @@ -897,32 +936,29 @@ public class ColumnSelection } if (hideStart > vstart) { - visiblecontigs.addElement(new int[] - { vstart, hideStart - 1 }); + visiblecontigs.add(new int[] { vstart, hideStart - 1 }); } vstart = hideEnd + 1; } if (vstart < end) { - visiblecontigs.addElement(new int[] - { vstart, end - 1 }); + 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 = (int[]) visiblecontigs.elementAt(i); - visiblecontigs.setElementAt(null, i); + int[] vc = visiblecontigs.get(i); + visiblecontigs.set(i, null); vcontigs[i * 2] = vc[0]; vcontigs[i * 2 + 1] = vc[1]; } - visiblecontigs.removeAllElements(); + visiblecontigs.clear(); return vcontigs; } else { - return new int[] - { start, end - 1 }; + return new int[] { start, end - 1 }; } } @@ -963,16 +999,16 @@ public class ColumnSelection if (hiddenColumns != null && hiddenColumns.size() > 0) { // then mangle the alignmentAnnotation annotation array - Vector annels = new Vector(); + Vector annels = new Vector(); Annotation[] els = null; - Vector regions = getHiddenColumns(); + List regions = getHiddenColumns(); int blockStart = start, blockEnd = end; int[] region; int hideStart, hideEnd, w = 0; for (int j = 0; j < regions.size(); j++) { - region = (int[]) regions.elementAt(j); + region = regions.get(j); hideStart = region[0]; hideEnd = region[1]; @@ -1016,13 +1052,15 @@ public class ColumnSelection w += els.length; } if (w == 0) + { return; - Enumeration e = annels.elements(); + } + alignmentAnnotation.annotations = new Annotation[w]; w = 0; - while (e.hasMoreElements()) + + for (Annotation[] chnk : annels) { - Annotation[] chnk = (Annotation[]) e.nextElement(); System.arraycopy(chnk, 0, alignmentAnnotation.annotations, w, chnk.length); w += chnk.length; @@ -1068,17 +1106,15 @@ public class ColumnSelection */ public void addElementsFrom(ColumnSelection colsel) { - if (colsel != null && colsel.size() > 0) + if (colsel != null && !colsel.isEmpty()) { - Enumeration e = colsel.getSelected().elements(); - while (e.hasMoreElements()) + for (Integer col : colsel.getSelected()) { - Object eo = e.nextElement(); - if (hiddenColumns != null && isVisible(((Integer) eo).intValue())) + if (hiddenColumns != null && isVisible(col.intValue())) { - if (!selected.contains(eo)) + if (!selected.contains(col)) { - selected.addElement(eo); + selected.addElement(col); } } } @@ -1093,22 +1129,20 @@ public class ColumnSelection */ public void setElementsFrom(ColumnSelection colsel) { - selected = new Vector(); + selected = new Vector(); if (colsel.selected != null && colsel.selected.size() > 0) { if (hiddenColumns != null && hiddenColumns.size() > 0) { // only select visible columns in this columns selection - selected = new Vector(); addElementsFrom(colsel); } else { // add everything regardless - Enumeration en = colsel.selected.elements(); - while (en.hasMoreElements()) + for (Integer col : colsel.getSelected()) { - selected.addElement(en.nextElement()); + addElement(col); } } } @@ -1128,7 +1162,7 @@ public class ColumnSelection * profileseq marked as hidden. */ public static ColumnSelection propagateInsertions(SequenceI profileseq, - Alignment al, AlignmentView input) + AlignmentI al, AlignmentView input) { int profsqpos = 0; @@ -1256,4 +1290,131 @@ public class ColumnSelection } } } + + /** + * + * @return true if there are columns marked + */ + public boolean hasSelectedColumns() + { + return (selected != null && selected.size() > 0); + } + + /** + * + * @return true if there are columns hidden + */ + public boolean hasHiddenColumns() + { + return hiddenColumns != null && hiddenColumns.size() > 0; + } + + /** + * + * @return true if there are more than one set of columns hidden + */ + public boolean hasManyHiddenColumns() + { + return hiddenColumns != null && hiddenColumns.size() > 1; + } + + /** + * mark the columns corresponding to gap characters as hidden in the column + * selection + * + * @param sr + */ + public void hideInsertionsFor(SequenceI sr) + { + List inserts = sr.getInsertions(); + for (int[] r : inserts) + { + hideColumns(r[0], r[1]); + } + } + + public boolean filterAnnotations(Annotation[] annotations, + AnnotationFilterParameter filterParams) + { + this.revealAllHiddenColumns(); + this.clear(); + int count = 0; + do + { + if (annotations[count] != null) + { + + boolean itemMatched = false; + + if (filterParams.getThresholdType() == AnnotationFilterParameter.ThresholdType.ABOVE_THRESHOLD + && annotations[count].value >= filterParams + .getThresholdValue()) + { + itemMatched = true; + } + if (filterParams.getThresholdType() == AnnotationFilterParameter.ThresholdType.BELOW_THRESHOLD + && annotations[count].value <= filterParams + .getThresholdValue()) + { + itemMatched = true; + } + + if (filterParams.isFilterAlphaHelix() + && annotations[count].secondaryStructure == 'H') + { + itemMatched = true; + } + + if (filterParams.isFilterBetaSheet() + && annotations[count].secondaryStructure == 'E') + { + itemMatched = true; + } + + if (filterParams.isFilterTurn() + && annotations[count].secondaryStructure == 'S') + { + itemMatched = true; + } + + String regexSearchString = filterParams.getRegexString(); + if (regexSearchString != null + && !filterParams.getRegexSearchFields().isEmpty()) + { + List fields = filterParams + .getRegexSearchFields(); + try + { + if (fields.contains(SearchableAnnotationField.DISPLAY_STRING) + && annotations[count].displayCharacter + .matches(regexSearchString)) + { + itemMatched = true; + } + } catch (java.util.regex.PatternSyntaxException pse) + { + if (annotations[count].displayCharacter + .equals(regexSearchString)) + { + itemMatched = true; + } + } + if (fields.contains(SearchableAnnotationField.DESCRIPTION) + && annotations[count].description != null + && annotations[count].description + .matches(regexSearchString)) + { + itemMatched = true; + } + } + + if (itemMatched) + { + this.addElement(count); + } + } + count++; + } while (count < annotations.length); + return false; + } }