X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fdatamodel%2FAlignment.java;h=f389ad89da1396deb194eceb8f281712ae2c7b44;hb=refs%2Fheads%2Ffeatures%2FJAL-3417_sdppred_calcs;hp=17dfb4c4f2ed05cee557260b399fb504a944c8a3;hpb=57ac5900f8f2d031f09ca563d3406283aa8a0d58;p=jalview.git diff --git a/src/jalview/datamodel/Alignment.java b/src/jalview/datamodel/Alignment.java index 17dfb4c..f389ad8 100755 --- a/src/jalview/datamodel/Alignment.java +++ b/src/jalview/datamodel/Alignment.java @@ -21,6 +21,7 @@ package jalview.datamodel; import jalview.analysis.AlignmentUtils; +import jalview.analysis.Conservation; import jalview.datamodel.AlignedCodonFrame.SequenceToSequenceMapping; import jalview.io.FastaFile; import jalview.util.Comparison; @@ -28,10 +29,13 @@ 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.HashSet; import java.util.Hashtable; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -44,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; @@ -62,15 +66,24 @@ public class Alignment implements AlignmentI HiddenSequences hiddenSequences; + HiddenColumns hiddenCols; + public Hashtable alignmentProperties; private List codonFrameList; + private Conservation conservation; + + private ProfilesI consensus; + + private Hashtable[] codonConsensus, rnaStructureConsensus; + private void initAlignment(SequenceI[] seqs) { groups = Collections.synchronizedList(new ArrayList()); hiddenSequences = new HiddenSequences(this); - codonFrameList = new ArrayList(); + hiddenCols = new HiddenColumns(); + codonFrameList = new ArrayList<>(); nucleotide = Comparison.isNucleotide(seqs); @@ -125,7 +138,7 @@ public class Alignment implements AlignmentI public Alignment(SeqCigar[] alseqs) { SequenceI[] seqs = SeqCigar.createAlignmentSequences(alseqs, - gapCharacter, new ColumnSelection(), null); + gapCharacter, new HiddenColumns(), null); initAlignment(seqs); } @@ -140,9 +153,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); } @@ -185,17 +197,18 @@ public class Alignment implements AlignmentI return AlignmentUtils.getSequencesByName(this); } - @Override public SequenceI getSequenceAt(int i) { synchronized (sequences) { + if (i > -1 && i < sequences.size()) { return sequences.get(i); } } + return null; } @@ -297,15 +310,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(); } /** @@ -402,7 +420,7 @@ public class Alignment implements AlignmentI @Override public SequenceGroup[] findAllGroups(SequenceI s) { - ArrayList temp = new ArrayList(); + ArrayList temp = new ArrayList<>(); synchronized (groups) { @@ -453,7 +471,7 @@ public class Alignment implements AlignmentI return; } } - sg.setContext(this); + sg.setContext(this, true); groups.add(sg); } } @@ -472,7 +490,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) { @@ -530,7 +550,7 @@ public class Alignment implements AlignmentI } for (SequenceGroup sg : groups) { - sg.setContext(null); + sg.setContext(null, false); } groups.clear(); } @@ -546,7 +566,7 @@ public class Alignment implements AlignmentI { removeAnnotationForGroup(g); groups.remove(g); - g.setContext(null); + g.setContext(null, false); } } } @@ -582,11 +602,12 @@ public class Alignment implements AlignmentI int i = 0; SequenceI sq = null; String sqname = null; + int nseq = sequences.size(); if (startAfter != null) { // try to find the sequence in the alignment boolean matched = false; - while (i < sequences.size()) + while (i < nseq) { if (getSequenceAt(i++) == startAfter) { @@ -599,13 +620,13 @@ public class Alignment implements AlignmentI i = 0; } } - while (i < sequences.size()) + while (i < nseq) { sq = getSequenceAt(i); sqname = sq.getName(); if (sqname.equals(token) // exact match || (b && // allow imperfect matches - case varies - (sqname.equalsIgnoreCase(token)))) + (sqname.equalsIgnoreCase(token)))) { return getSequenceAt(i); } @@ -686,7 +707,6 @@ public class Alignment implements AlignmentI return -1; } - @Override public int getHeight() { @@ -706,15 +726,22 @@ public class Alignment implements AlignmentI 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! * @@ -1064,21 +1091,18 @@ public class Alignment implements AlignmentI currentSeq = currentSeq.createDatasetSequence(); } } - if (seqs.contains(currentSeq)) - { - return; - } - List toProcess = new ArrayList(); + + List toProcess = new ArrayList<>(); toProcess.add(currentSeq); while (toProcess.size() > 0) { // use a queue ? SequenceI curDs = toProcess.remove(0); - if (seqs.contains(curDs)) + + if (!seqs.add(curDs)) { continue; } - seqs.add(curDs); // iterate over database references, making sure we add forward referenced // sequences if (curDs.getDBRefs() != null) @@ -1096,10 +1120,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 @@ -1121,7 +1144,7 @@ public class Alignment implements AlignmentI return; } // try to avoid using SequenceI.equals at this stage, it will be expensive - Set seqs = new LinkedIdentityHashSet(); + Set seqs = new LinkedIdentityHashSet<>(); for (int i = 0; i < getHeight(); i++) { @@ -1179,7 +1202,8 @@ public class Alignment implements AlignmentI int maxLength = -1; SequenceI current; - for (int i = 0; i < sequences.size(); i++) + int nseq = sequences.size(); + for (int i = 0; i < nseq; i++) { current = getSequenceAt(i); for (int j = current.getLength(); j > maxLength; j--) @@ -1196,7 +1220,7 @@ public class Alignment implements AlignmentI maxLength++; int cLength; - for (int i = 0; i < sequences.size(); i++) + for (int i = 0; i < nseq; i++) { current = getSequenceAt(i); cLength = current.getLength(); @@ -1236,8 +1260,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++) { @@ -1327,6 +1351,12 @@ public class Alignment implements AlignmentI } @Override + public HiddenColumns getHiddenColumns() + { + return hiddenCols; + } + + @Override public CigarArray getCompactAlignment() { synchronized (sequences) @@ -1400,7 +1430,7 @@ public class Alignment implements AlignmentI { return null; } - List cframes = new ArrayList(); + List cframes = new ArrayList<>(); for (AlignedCodonFrame acf : getCodonFrames()) { if (acf.involvesSequence(seq)) @@ -1467,31 +1497,26 @@ 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 - List toappendsq = new ArrayList(); + List toappendsq = new ArrayList<>(); synchronized (sqs) { for (SequenceI addedsq : sqs) { 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); } @@ -1555,8 +1580,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 { @@ -1603,7 +1628,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) { @@ -1618,38 +1646,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 (ann.getCalcId() != null && ann.getCalcId().equals(calcId) - && ann.sequenceRef != null && ann.sequenceRef == seq - && ann.label != null && ann.label.equals(label)) - { - aa.add(ann); - } - } - return aa; + return AlignmentAnnotation.findAnnotations( + Arrays.asList(getAlignmentAnnotation()), seq, calcId, label); } @Override @@ -1842,7 +1853,7 @@ public class Alignment implements AlignmentI @Override public Set getSequenceNames() { - Set names = new HashSet(); + Set names = new HashSet<>(); for (SequenceI seq : getSequences()) { names.add(seq.getName()); @@ -1908,38 +1919,175 @@ 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; + } - int[] lowestRange = new int[] { -1, -1 }; - int[] higestRange = new int[] { -1, -1 }; + @Override + public void setupJPredAlignment() + { + SequenceI repseq = getSequenceAt(0); + setSeqrep(repseq); + HiddenColumns cs = new HiddenColumns(); + cs.hideList(repseq.getInsertions()); + setHiddenColumns(cs); + } - for (int[] hiddenCol : hiddenCols) - { - lowestRange = (hiddenCol[0] <= startPos) ? hiddenCol : lowestRange; - higestRange = (hiddenCol[1] >= endPos) ? hiddenCol : higestRange; - } + @Override + public HiddenColumns propagateInsertions(SequenceI profileseq, + AlignmentView input) + { + int profsqpos = 0; - if (lowestRange[0] == -1 && lowestRange[1] == -1) - { - startPos = alignmentStartEnd[0]; - } - else + char gc = getGapCharacter(); + Object[] alandhidden = input.getAlignmentAndHiddenColumns(gc); + HiddenColumns nview = (HiddenColumns) alandhidden[1]; + SequenceI origseq = ((SequenceI[]) alandhidden[0])[profsqpos]; + return propagateInsertions(profileseq, origseq, nview); + } + + /** + * + * @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 Hashtable[] getComplementConsensusHash() + { + return codonConsensus; + } + + @Override + public Conservation getConservation() + { + return conservation; + } + + @Override + public Hashtable[] getRnaStructureConsensusHash() + { + return rnaStructureConsensus; + } + + @Override + public ProfilesI getSequenceConsensusHash() + { + return consensus; + } + + @Override + public void setComplementConsensusHash(Hashtable[] hconsensus) + { + codonConsensus = hconsensus; + + } + + @Override + public void setConservation(Conservation cons) + { + conservation = cons; + + } + + @Override + public void setRnaStructureConsensusHash(Hashtable[] hStrucConsensus) + { + rnaStructureConsensus = hStrucConsensus; + + } + + @Override + public void setSequenceConsensusHash(ProfilesI hconsensus) + { + consensus = hconsensus; + } }