2 * Jalview - A Sequence Alignment Editor and Viewer
3 * Copyright (C) 2006 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19 package jalview.datamodel;
26 * <p>Description: </p>
28 * <p>Copyright: Copyright (c) 2004</p>
30 * <p>Company: Dundee University</p>
32 * @author not attributable
35 public class AlignmentView
38 * Transient object compactly representing a 'view' of an alignment - with discontinuities marked.
40 private SeqCigar[] sequences = null;
41 private int[] contigs = null;
43 public AlignmentView(CigarArray seqcigararray)
45 if (!seqcigararray.isSeqCigarArray())
46 throw new Error("Implementation Error - can only make an alignment view from a CigarArray of sequences.");
47 //contigs = seqcigararray.applyDeletions();
48 contigs = seqcigararray.getDeletedRegions();
49 sequences = seqcigararray.getSeqCigarArray();
50 width = seqcigararray.getWidth(); // visible width
53 public void setSequences(SeqCigar[] sequences)
55 this.sequences = sequences;
58 public void setContigs(int[] contigs)
60 this.contigs = contigs;
63 public SeqCigar[] getSequences()
68 * @see CigarArray.getDeletedRegions
69 * @return int[] { vis_start, sym_start, length }
71 public int[] getContigs()
76 * get the full alignment and a columnselection object marking the hidden regions
77 * @param gapCharacter char
78 * @return Object[] { SequenceI[], ColumnSelection}
80 public Object[] getAlignmentAndColumnSelection(char gapCharacter) {
81 ColumnSelection colsel = new ColumnSelection();
83 return new Object[] { SeqCigar.createAlignmentSequences(sequences, gapCharacter, colsel, contigs), colsel};
91 public String[] getSequenceStrings(char c)
93 String[] seqs=new String[sequences.length];
94 for (int n=0; n<sequences.length; n++) {
95 String fullseq = sequences[n].getSequenceString(c);
100 for (int h = 0; h < contigs.length; h += 3)
102 seqs[n] += fullseq.substring(p, contigs[h + 1]);
103 p = contigs[h + 1] + contigs[h + 2];
105 seqs[n] += fullseq.substring(p);
113 * @return visible number of columns in alignment view
115 public int getWidth() {
119 protected void setWidth(int width) {
123 * get the contiguous subalignments in an alignment view.
124 * @param gapCharacter char
125 * @return SequenceI[][]
127 public SequenceI[][] getVisibleContigs(char gapCharacter) {
130 if (sequences==null || width<=0)
132 if (contigs != null && contigs.length > 0)
137 for (int contig = 0; contig < contigs.length; contig += 3)
139 if ( (contigs[contig + 1] - start) > 0)
143 fwidth += contigs[contig + 2]; // end up with full region width (including hidden regions)
144 start = contigs[contig + 1] + contigs[contig + 2];
150 smsa = new SequenceI[njobs][];
153 for (int contig = 0; contig < contigs.length; contig += 3)
155 if (contigs[contig + 1] - start > 0)
157 SequenceI mseq[] = new SequenceI[sequences.length];
158 for (int s = 0; s < mseq.length; s++)
160 mseq[s] = sequences[s].getSeq(gapCharacter).getSubSequence(start,
161 contigs[contig + 1]);
166 start = contigs[contig + 1] + contigs[contig + 2];
170 SequenceI mseq[] = new SequenceI[sequences.length];
171 for (int s = 0; s < mseq.length; s++)
173 mseq[s] = sequences[s].getSeq(gapCharacter).getSubSequence(start,
182 smsa = new SequenceI[1][];
183 smsa[0] = new SequenceI[sequences.length];
184 for (int s = 0; s < sequences.length; s++)
186 smsa[0][s] = sequences[s].getSeq(gapCharacter);
192 * return full msa and hidden regions with visible blocks replaced with new sub alignments
193 * @param nvismsa SequenceI[][]
194 * @param orders AlignmentOrder[] corresponding to each SequenceI[] block.
197 public Object[] getUpdatedView(SequenceI[][] nvismsa, AlignmentOrder[] orders, char gapCharacter) {
198 if (sequences == null || width <= 0)
200 throw new Error("empty view cannot be updated.");
204 "nvismsa==null. use getAlignmentAndColumnSelection() instead.");
205 if (contigs != null && contigs.length > 0)
207 SequenceI[] alignment = new SequenceI[sequences.length];
208 ColumnSelection columnselection = new ColumnSelection();
209 if (contigs != null && contigs.length > 0)
215 for (int contig = 0; contig < contigs.length; contig += 3)
217 owidth += contigs[contig + 2]; // recover final column width
218 if (contigs[contig + 1] - start > 0)
220 int swidth = 0; // subalignment width
221 if (nvismsa[j] != null)
223 SequenceI mseq[] = nvismsa[j];
224 AlignmentOrder order=(orders==null) ? null : orders[j];
226 if (mseq.length!=sequences.length)
227 throw new Error("Mismatch between number of sequences in block "+j+" ("+mseq.length+") and the original view ("+sequences.length+")");
228 swidth = mseq[0].getLength(); // JBPNote: could ensure padded here.
229 for (int s = 0; s < mseq.length; s++)
231 if (alignment[s] == null)
233 alignment[s] = mseq[s];
237 alignment[s].setSequence(alignment[s].getSequence() +
238 mseq[s].getSequence());
239 if (mseq[s].getStart() <= mseq[s].getEnd())
241 alignment[s].setEnd(mseq[s].getEnd());
244 order.updateSequence(mseq[s], alignment[s]);
251 // recover original alignment block or place gaps
254 // recover input data
255 for (int s = 0; s < sequences.length; s++)
257 SequenceI oseq = sequences[s].getSeq(gapCharacter).getSubSequence(start,
258 contigs[contig + 1]);
259 if (swidth < oseq.getLength())
261 swidth = oseq.getLength();
263 if (alignment[s] == null)
269 alignment[s].setSequence(alignment[s].getSequence() +
271 if (oseq.getEnd() >= oseq.getStart())
273 alignment[s].setEnd(oseq.getEnd());
283 // advance to begining of visible region
284 start = contigs[contig + 1] + contigs[contig + 2];
285 // add hidden segment to right of next region
286 for (int s = 0; s < sequences.length; s++)
288 SequenceI hseq = sequences[s].getSeq(gapCharacter).getSubSequence(contigs[contig +
290 if (alignment[s] == null)
296 alignment[s].setSequence(alignment[s].getSequence() +
298 if (hseq.getEnd() >= hseq.getStart())
300 alignment[s].setEnd(hseq.getEnd());
304 // mark hidden segment as hidden in the new alignment
305 columnselection.hideColumns(nwidth, nwidth + contigs[contig + 2] - 1);
306 nwidth += contigs[contig + 2];
308 // Do final segment - if it exists
309 if (j < nvismsa.length)
312 if (nvismsa[j] != null)
314 SequenceI mseq[] = nvismsa[j];
315 AlignmentOrder order = (orders!=null) ? orders[j] : null;
316 swidth = mseq[0].getLength();
317 for (int s = 0; s < mseq.length; s++)
319 if (alignment[s] == null)
321 alignment[s] = mseq[s];
325 alignment[s].setSequence(alignment[s].getSequence() +
326 mseq[s].getSequence());
327 if (mseq[s].getEnd() >= mseq[s].getStart())
329 alignment[s].setEnd(mseq[s].getEnd());
332 order.updateSequence(mseq[s], alignment[s]);
341 // recover input data or place gaps
344 // recover input data
345 for (int s = 0; s < sequences.length; s++)
347 SequenceI oseq = sequences[s].getSeq(gapCharacter).getSubSequence(start,
349 if (swidth < oseq.getLength())
351 swidth = oseq.getLength();
353 if (alignment[s] == null)
359 alignment[s].setSequence(alignment[s].getSequence() +
361 if (oseq.getEnd() >= oseq.getStart())
363 alignment[s].setEnd(oseq.getEnd());
372 throw new Error("Padding not yet implemented.");
378 return new Object[] { alignment, columnselection};
380 if (nvismsa.length!=1)
381 throw new Error("Mismatch between visible blocks to update and number of contigs in view (contigs=0,blocks="+nvismsa.length);
382 if (nvismsa[0]!=null)
383 return new Object[] { nvismsa[0], new ColumnSelection()};
385 return getAlignmentAndColumnSelection(gapCharacter);
389 * returns simple array of start end positions of visible range on alignment.
390 * vis_start and vis_end are inclusive - use SequenceI.getSubSequence(vis_start, vis_end+1) to recover visible sequence from underlying alignment.
391 * @return int[] { start_i, end_i } for 1<i<n visible regions.
393 public int[] getVisibleContigs() {
394 if (contigs != null && contigs.length > 0)
399 for (int contig = 0; contig < contigs.length; contig += 3)
401 if ( (contigs[contig + 1] - start) > 0)
405 fwidth += contigs[contig + 2]; // end up with full region width (including hidden regions)
406 start = contigs[contig + 1] + contigs[contig + 2];
412 int viscontigs[] = new int[nvis*2];
415 for (int contig=0; contig<contigs.length; contig+=3) {
416 if ( (contigs[contig + 1] - start) > 0)
418 viscontigs[nvis] = start;
419 viscontigs[nvis+1]=contigs[contig+1]-1; // end is inclusive
422 start = contigs[contig + 1] + contigs[contig + 2];
425 viscontigs[nvis] = start;
426 viscontigs[nvis+1]=fwidth; // end is inclusive
431 return new int[] { 0, width};