X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fdatamodel%2FAlignment.java;h=1f0e1c271930da19b7f65cff5fc2a29dd9d1c280;hb=f14071cd4c32feeacdb6d4638ef4e3b52071f2f3;hp=25d770d7264402395888d163a15ccd1a22bad918;hpb=ec141f1e76995494a4caf9fb8a55809d654ab423;p=jalview.git diff --git a/src/jalview/datamodel/Alignment.java b/src/jalview/datamodel/Alignment.java index 25d770d..1f0e1c2 100755 --- a/src/jalview/datamodel/Alignment.java +++ b/src/jalview/datamodel/Alignment.java @@ -28,11 +28,14 @@ import jalview.util.LinkedIdentityHashSet; import jalview.util.MessageManager; import java.util.ArrayList; +import java.util.Arrays; +import java.util.BitSet; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; import java.util.Hashtable; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -45,11 +48,11 @@ import java.util.Vector; * @author JimP * */ -public class Alignment implements AlignmentI +public class Alignment implements AlignmentI, AutoCloseable { private Alignment dataset; - protected List sequences; + private List sequences; protected List groups; @@ -144,9 +147,8 @@ public class Alignment implements AlignmentI */ public static AlignmentI createAlignment(CigarArray compactAlignment) { - throw new Error( - MessageManager - .getString("error.alignment_cigararray_not_implemented")); + throw new Error(MessageManager + .getString("error.alignment_cigararray_not_implemented")); // this(compactAlignment.refCigars); } @@ -189,7 +191,6 @@ public class Alignment implements AlignmentI return AlignmentUtils.getSequencesByName(this); } - @Override public SequenceI getSequenceAt(int i) { @@ -200,6 +201,7 @@ public class Alignment implements AlignmentI return sequences.get(i); } } + return null; } @@ -301,15 +303,20 @@ public class Alignment implements AlignmentI } @Override - public void finalize() throws Throwable + public void close() { if (getDataset() != null) { - getDataset().removeAlignmentRef(); + try + { + getDataset().removeAlignmentRef(); + } catch (Throwable e) + { + e.printStackTrace(); + } } nullReferences(); - super.finalize(); } /** @@ -476,7 +483,9 @@ public class Alignment implements AlignmentI return; } // remove annotation very quickly - AlignmentAnnotation[] t, todelete = new AlignmentAnnotation[annotations.length], tokeep = new AlignmentAnnotation[annotations.length]; + AlignmentAnnotation[] t, + todelete = new AlignmentAnnotation[annotations.length], + tokeep = new AlignmentAnnotation[annotations.length]; int i, p, k; if (gp == null) { @@ -609,7 +618,7 @@ public class Alignment implements AlignmentI sqname = sq.getName(); if (sqname.equals(token) // exact match || (b && // allow imperfect matches - case varies - (sqname.equalsIgnoreCase(token)))) + (sqname.equalsIgnoreCase(token)))) { return getSequenceAt(i); } @@ -690,7 +699,6 @@ public class Alignment implements AlignmentI return -1; } - @Override public int getHeight() { @@ -707,18 +715,25 @@ public class Alignment implements AlignmentI public int getWidth() { int maxLength = -1; - + for (int i = 0; i < sequences.size(); i++) { - if (getSequenceAt(i).getLength() > maxLength) - { - maxLength = getSequenceAt(i).getLength(); - } + maxLength = Math.max(maxLength, getSequenceAt(i).getLength()); } - return maxLength; } + @Override + public int getVisibleWidth() + { + int w = getWidth(); + if (hiddenCols != null) + { + w -= hiddenCols.getSize(); + } + return w; + } + /** * DOCUMENT ME! * @@ -1097,10 +1112,9 @@ public class Alignment implements AlignmentI } if (dbr.getMap().getTo().getDatasetSequence() != null) { - throw new Error( - "Implementation error: Map.getTo() for dbref " + dbr - + " from " + curDs.getName() - + " is not a dataset sequence."); + throw new Error("Implementation error: Map.getTo() for dbref " + + dbr + " from " + curDs.getName() + + " is not a dataset sequence."); } // we recurse to add all forward references to dataset sequences via // DBRefs/etc @@ -1237,8 +1251,8 @@ public class Alignment implements AlignmentI current = getSequenceAt(i); // This should really be a sequence method ends[i * 2] = current.findIndex(current.getStart()); - ends[i * 2 + 1] = current.findIndex(current.getStart() - + current.getLength()); + ends[i * 2 + 1] = current + .findIndex(current.getStart() + current.getLength()); boolean hitres = false; for (int j = 0, rs = 0, ssiz = current.getLength(); j < ssiz; j++) { @@ -1474,13 +1488,15 @@ public class Alignment implements AlignmentI { // TODO JAL-1270 needs test coverage // currently tested for use in jalview.gui.SequenceFetcher - boolean samegap = toappend.getGapCharacter() == getGapCharacter(); char oldc = toappend.getGapCharacter(); + boolean samegap = oldc == getGapCharacter(); boolean hashidden = toappend.getHiddenSequences() != null && toappend.getHiddenSequences().hiddenSequences != null; // get all sequences including any hidden ones - List sqs = (hashidden) ? toappend.getHiddenSequences() - .getFullAlignment().getSequences() : toappend.getSequences(); + List sqs = (hashidden) + ? toappend.getHiddenSequences().getFullAlignment() + .getSequences() + : toappend.getSequences(); if (sqs != null) { // avoid self append deadlock by @@ -1491,14 +1507,7 @@ public class Alignment implements AlignmentI { if (!samegap) { - char[] oldseq = addedsq.getSequence(); - for (int c = 0; c < oldseq.length; c++) - { - if (oldseq[c] == oldc) - { - oldseq[c] = gapCharacter; - } - } + addedsq.replace(oldc, gapCharacter); } toappendsq.add(addedsq); } @@ -1562,8 +1571,8 @@ public class Alignment implements AlignmentI if (ourval instanceof String) { // append strings - this.setProperty(k, ((String) ourval) + "; " - + ((String) toapprop)); + this.setProperty(k, + ((String) ourval) + "; " + ((String) toapprop)); } else { @@ -1610,7 +1619,10 @@ public class Alignment implements AlignmentI AlignmentAnnotation annot = new AlignmentAnnotation(name, name, new Annotation[1], 0f, 0f, AlignmentAnnotation.BAR_GRAPH); annot.hasText = false; - annot.setCalcId(new String(calcId)); + if (calcId != null) + { + annot.setCalcId(new String(calcId)); + } annot.autoCalculated = autoCalc; if (seqRef != null) { @@ -1625,40 +1637,21 @@ public class Alignment implements AlignmentI @Override public Iterable findAnnotation(String calcId) { - List aa = new ArrayList<>(); AlignmentAnnotation[] alignmentAnnotation = getAlignmentAnnotation(); if (alignmentAnnotation != null) { - for (AlignmentAnnotation a : alignmentAnnotation) - { - if (a.getCalcId() == calcId - || (a.getCalcId() != null && calcId != null && a - .getCalcId().equals(calcId))) - { - aa.add(a); - } - } + return AlignmentAnnotation.findAnnotation( + Arrays.asList(getAlignmentAnnotation()), calcId); } - return aa; + return Arrays.asList(new AlignmentAnnotation[] {}); } @Override public Iterable findAnnotations(SequenceI seq, String calcId, String label) { - ArrayList aa = new ArrayList<>(); - for (AlignmentAnnotation ann : getAlignmentAnnotation()) - { - if ((calcId == null || (ann.getCalcId() != null && ann.getCalcId() - .equals(calcId))) - && (seq == null || (ann.sequenceRef != null && ann.sequenceRef == seq)) - && (label == null || (ann.label != null && ann.label - .equals(label)))) - { - aa.add(ann); - } - } - return aa; + return AlignmentAnnotation.findAnnotations( + Arrays.asList(getAlignmentAnnotation()), seq, calcId, label); } @Override @@ -1917,47 +1910,126 @@ public class Alignment implements AlignmentI } @Override - public int[] getVisibleStartAndEndIndex(List hiddenCols) + public boolean setHiddenColumns(HiddenColumns cols) { - int[] alignmentStartEnd = new int[] { 0, getWidth() - 1 }; - int startPos = alignmentStartEnd[0]; - int endPos = alignmentStartEnd[1]; + boolean changed = cols == null ? hiddenCols != null + : !cols.equals(hiddenCols); + hiddenCols = cols; + return changed; + } + @Override + public void setupJPredAlignment() + { + SequenceI repseq = getSequenceAt(0); + setSeqrep(repseq); + HiddenColumns cs = new HiddenColumns(); + cs.hideList(repseq.getInsertions()); + setHiddenColumns(cs); + } - int[] lowestRange = new int[] { -1, -1 }; - int[] higestRange = new int[] { -1, -1 }; + @Override + public HiddenColumns propagateInsertions(SequenceI profileseq, + AlignmentView input) + { + int profsqpos = 0; - for (int[] hiddenCol : hiddenCols) - { - lowestRange = (hiddenCol[0] <= startPos) ? hiddenCol : lowestRange; - higestRange = (hiddenCol[1] >= endPos) ? hiddenCol : higestRange; - } + char gc = getGapCharacter(); + Object[] alandhidden = input.getAlignmentAndHiddenColumns(gc); + HiddenColumns nview = (HiddenColumns) alandhidden[1]; + SequenceI origseq = ((SequenceI[]) alandhidden[0])[profsqpos]; + return propagateInsertions(profileseq, origseq, nview); + } - if (lowestRange[0] == -1 && lowestRange[1] == -1) - { - startPos = alignmentStartEnd[0]; - } - else + /** + * + * @param profileseq + * sequence in al which corresponds to origseq + * @param al + * alignment which is to have gaps inserted into it + * @param origseq + * sequence corresponding to profileseq which defines gap map for + * modifying al + */ + private HiddenColumns propagateInsertions(SequenceI profileseq, + SequenceI origseq, HiddenColumns hc) + { + // take the set of hidden columns, and the set of gaps in origseq, + // and remove all the hidden gaps from hiddenColumns + + // first get the gaps as a Bitset + // then calculate hidden ^ not(gap) + BitSet gaps = origseq.gapBitset(); + hc.andNot(gaps); + + // 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 + HiddenColumns newhidden = new HiddenColumns(); + + int numGapsBefore = 0; + int gapPosition = 0; + Iterator it = hc.iterator(); + while (it.hasNext()) { - startPos = lowestRange[1] + 1; + int[] region = it.next(); + + // get region coordinates accounting for gaps + // we can rely on gaps not being *in* hidden regions because we already + // removed those + while (gapPosition < region[0]) + { + gapPosition++; + if (gaps.get(gapPosition)) + { + numGapsBefore++; + } + } + + int left = region[0] - numGapsBefore; + int right = region[1] - numGapsBefore; + + newhidden.hideColumns(left, right); + padGaps(left, right, profileseq); } + return newhidden; + } + + /** + * Pad gaps in all sequences in alignment except profileseq + * + * @param left + * position of first gap to insert + * @param right + * position of last gap to insert + * @param profileseq + * sequence not to pad + */ + private void padGaps(int left, int right, SequenceI profileseq) + { + char gc = getGapCharacter(); - if (higestRange[0] == -1 && higestRange[1] == -1) + // make a string with number of gaps = length of hidden region + StringBuilder sb = new StringBuilder(); + for (int g = 0; g < right - left + 1; g++) { - endPos = alignmentStartEnd[1]; + sb.append(gc); } - else + + // loop over the sequences and pad with gaps where required + for (int s = 0, ns = getHeight(); s < ns; s++) { - endPos = higestRange[0] - 1; + SequenceI sqobj = getSequenceAt(s); + if ((sqobj != profileseq) && (sqobj.getLength() >= left)) + { + String sq = sqobj.getSequenceAsString(); + sqobj.setSequence( + sq.substring(0, left) + sb.toString() + sq.substring(left)); + } } - return new int[] { startPos, endPos }; - } - @Override - public void setHiddenColumns(HiddenColumns cols) - { - hiddenCols = cols; } - Map contactmaps = new HashMap(); + Map contactmaps = new HashMap<>(); @Override public ContactListI getContactListFor(AlignmentAnnotation _aa, int column)