Class |
Line # |
Actions |
|||
---|---|---|---|---|---|
AlignmentView | 35 | 412 | 172 | ||
AlignmentView.ScGroup | 69 | 11 | 6 |
1 | /* | |
2 | * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) | |
3 | * Copyright (C) $$Year-Rel$$ The Jalview Authors | |
4 | * | |
5 | * This file is part of Jalview. | |
6 | * | |
7 | * Jalview is free software: you can redistribute it and/or | |
8 | * modify it under the terms of the GNU General Public License | |
9 | * as published by the Free Software Foundation, either version 3 | |
10 | * of the License, or (at your option) any later version. | |
11 | * | |
12 | * Jalview is distributed in the hope that it will be useful, but | |
13 | * WITHOUT ANY WARRANTY; without even the implied warranty | |
14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR | |
15 | * PURPOSE. See the GNU General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License | |
18 | * along with Jalview. If not, see <http://www.gnu.org/licenses/>. | |
19 | * The Jalview Authors are detailed in the 'AUTHORS' file. | |
20 | */ | |
21 | package jalview.datamodel; | |
22 | ||
23 | import jalview.util.MessageManager; | |
24 | import jalview.util.ShiftList; | |
25 | ||
26 | import java.io.PrintStream; | |
27 | import java.util.ArrayList; | |
28 | import java.util.List; | |
29 | ||
30 | /** | |
31 | * Transient object compactly representing a 'view' of an alignment - with | |
32 | * discontinuities marked. Extended in Jalview 2.7 to optionally record sequence | |
33 | * groups and specific selected regions on the alignment. | |
34 | */ | |
35 | public class AlignmentView | |
36 | { | |
37 | private SeqCigar[] sequences = null; | |
38 | ||
39 | private int[] contigs = null; | |
40 | ||
41 | private int width = 0; | |
42 | ||
43 | private int firstCol = 0; | |
44 | ||
45 | /** | |
46 | * one or more ScGroup objects, which are referenced by each seqCigar's group | |
47 | * membership | |
48 | */ | |
49 | private List<ScGroup> scGroups = null; | |
50 | ||
51 | private boolean isNa = false; | |
52 | ||
53 | /** | |
54 | * false if the view concerns peptides | |
55 | * | |
56 | * @return | |
57 | */ | |
58 | 0 | public boolean isNa() |
59 | { | |
60 | 0 | return isNa; |
61 | } | |
62 | ||
63 | /** | |
64 | * Group defined over SeqCigars. Unlike AlignmentI associated groups, each | |
65 | * SequenceGroup hold just the essential properties for the group, but no | |
66 | * references to the sequences involved. SeqCigars hold references to the | |
67 | * seuqenceGroup entities themselves. | |
68 | */ | |
69 | private class ScGroup | |
70 | { | |
71 | public List<SeqCigar> seqs; | |
72 | ||
73 | public SequenceGroup sg; | |
74 | ||
75 | 11 | ScGroup() |
76 | { | |
77 | 11 | seqs = new ArrayList<>(); |
78 | } | |
79 | ||
80 | /** | |
81 | * @param seq | |
82 | * @return true if seq was not a member before and was added to group | |
83 | */ | |
84 | 33 | public boolean add(SeqCigar seq) |
85 | { | |
86 | 33 | if (!seq.isMemberOf(this)) |
87 | { | |
88 | 33 | seqs.add(seq); |
89 | 33 | seq.setGroupMembership(this); |
90 | 33 | return true; |
91 | } | |
92 | else | |
93 | { | |
94 | 0 | return false; |
95 | } | |
96 | } | |
97 | ||
98 | /** | |
99 | * | |
100 | * @param seq | |
101 | * @return true if seq was a member and was removed from group | |
102 | */ | |
103 | 0 | public boolean remove(SeqCigar seq) |
104 | { | |
105 | 0 | if (seq.removeGroupMembership(this)) |
106 | { | |
107 | 0 | seqs.remove(seq); |
108 | 0 | return true; |
109 | } | |
110 | 0 | return false; |
111 | } | |
112 | ||
113 | 0 | public int size() |
114 | { | |
115 | 0 | return seqs.size(); |
116 | } | |
117 | } | |
118 | ||
119 | /** | |
120 | * vector of selected seqCigars. This vector is also referenced by each | |
121 | * seqCigar contained in it. | |
122 | */ | |
123 | private ScGroup selected; | |
124 | ||
125 | /** | |
126 | * Construct an alignmentView from a live jalview alignment view. Note - | |
127 | * hidden rows will be excluded from alignmentView Note: JAL-1179 | |
128 | * | |
129 | * @param alignment | |
130 | * - alignment as referenced by an AlignViewport | |
131 | * @param columnSelection | |
132 | * - | |
133 | * @param selection | |
134 | * @param hasHiddenColumns | |
135 | * - mark the hidden columns in columnSelection as hidden in the view | |
136 | * @param selectedRegionOnly | |
137 | * - when set, only include the selected region in the view, | |
138 | * otherwise just mark the selected region on the constructed view. | |
139 | * @param recordGroups | |
140 | * - when set, any groups on the given alignment will be marked on | |
141 | * the view | |
142 | */ | |
143 | 24 | public AlignmentView(AlignmentI alignment, HiddenColumns hidden, |
144 | SequenceGroup selection, boolean hasHiddenColumns, | |
145 | boolean selectedRegionOnly, boolean recordGroups) | |
146 | { | |
147 | // refactored from AlignViewport.getAlignmentView(selectedOnly); | |
148 | 24 | this(new jalview.datamodel.CigarArray(alignment, |
149 | 24 | (hasHiddenColumns ? hidden : null), |
150 | 24 | (selectedRegionOnly ? selection : null)), |
151 | 24 | (selectedRegionOnly && selection != null) |
152 | ? selection.getStartRes() | |
153 | : 0); | |
154 | 24 | isNa = alignment.isNucleotide(); |
155 | // walk down SeqCigar array and Alignment Array - optionally restricted by | |
156 | // selected region. | |
157 | // test group membership for each sequence in each group, store membership | |
158 | // and record non-empty groups in group list. | |
159 | // record / sub-select selected region on the alignment view | |
160 | 24 | SequenceI[] selseqs; |
161 | 24 | if (selection != null && selection.getSize() > 0) |
162 | { | |
163 | 6 | this.selected = new ScGroup(); |
164 | 6 | selseqs = selection.getSequencesInOrder(alignment, |
165 | selectedRegionOnly); | |
166 | } | |
167 | else | |
168 | { | |
169 | 18 | selseqs = alignment.getSequencesArray(); |
170 | } | |
171 | ||
172 | 24 | List<List<SequenceI>> seqsets = new ArrayList<>(); |
173 | // get the alignment's group list and make a copy | |
174 | 24 | List<SequenceGroup> grps = new ArrayList<>(); |
175 | 24 | List<SequenceGroup> gg = alignment.getGroups(); |
176 | 24 | grps.addAll(gg); |
177 | 24 | ScGroup[] sgrps = null; |
178 | 24 | boolean addedgps[] = null; |
179 | 24 | if (grps != null) |
180 | { | |
181 | 24 | if (selection != null && selectedRegionOnly) |
182 | { | |
183 | // trim annotation to the region being stored. | |
184 | // strip out any groups that do not actually intersect with the | |
185 | // visible and selected region | |
186 | 6 | int ssel = selection.getStartRes(), esel = selection.getEndRes(); |
187 | 6 | List<SequenceGroup> isg = new ArrayList<>(); |
188 | 6 | for (SequenceGroup sg : grps) |
189 | { | |
190 | 0 | if (!(sg.getStartRes() > esel || sg.getEndRes() < ssel)) |
191 | { | |
192 | // adjust bounds of new group, if necessary. | |
193 | 0 | if (sg.getStartRes() < ssel) |
194 | { | |
195 | 0 | sg.setStartRes(ssel); |
196 | } | |
197 | 0 | if (sg.getEndRes() > esel) |
198 | { | |
199 | 0 | sg.setEndRes(esel); |
200 | } | |
201 | 0 | sg.setStartRes(sg.getStartRes() - ssel + 1); |
202 | 0 | sg.setEndRes(sg.getEndRes() - ssel + 1); |
203 | ||
204 | 0 | isg.add(sg); |
205 | } | |
206 | } | |
207 | 6 | grps = isg; |
208 | } | |
209 | ||
210 | 24 | sgrps = new ScGroup[grps.size()]; |
211 | 24 | addedgps = new boolean[grps.size()]; |
212 | 29 | for (int g = 0; g < sgrps.length; g++) |
213 | { | |
214 | 5 | SequenceGroup sg = grps.get(g); |
215 | 5 | sgrps[g] = new ScGroup(); |
216 | 5 | sgrps[g].sg = new SequenceGroup(sg); |
217 | 5 | addedgps[g] = false; |
218 | // can't set entry 0 in an empty list | |
219 | // seqsets.set(g, sg.getSequences(null)); | |
220 | 5 | seqsets.add(sg.getSequences()); |
221 | } | |
222 | // seqsets now contains vectors (should be sets) for each group, so we can | |
223 | // track when we've done with the group | |
224 | } | |
225 | 24 | int csi = 0; |
226 | 125 | for (int i = 0; i < selseqs.length; i++) |
227 | { | |
228 | 101 | if (selseqs[i] != null) |
229 | { | |
230 | 101 | if (selection != null && selection.getSize() > 0 |
231 | && !selectedRegionOnly) | |
232 | { | |
233 | 0 | selected.add(sequences[csi]); |
234 | } | |
235 | 101 | if (seqsets != null) |
236 | { | |
237 | 266 | for (int sg = 0; sg < sgrps.length; sg++) |
238 | { | |
239 | 165 | if ((seqsets.get(sg)).contains(selseqs[i])) |
240 | { | |
241 | 33 | sgrps[sg].sg.deleteSequence(selseqs[i], false); |
242 | 33 | sgrps[sg].add(sequences[csi]); |
243 | 33 | if (!addedgps[sg]) |
244 | { | |
245 | 5 | if (scGroups == null) |
246 | { | |
247 | 1 | scGroups = new ArrayList<>(); |
248 | } | |
249 | 5 | addedgps[sg] = true; |
250 | 5 | scGroups.add(sgrps[sg]); |
251 | } | |
252 | } | |
253 | } | |
254 | } | |
255 | 101 | csi++; |
256 | } | |
257 | } | |
258 | // finally, delete the remaining sequences (if any) not selected | |
259 | 29 | for (int sg = 0; sg < sgrps.length; sg++) |
260 | { | |
261 | 5 | SequenceI[] sqs = sgrps[sg].sg.getSequencesAsArray(null); |
262 | 5 | for (int si = 0; si < sqs.length; si++) |
263 | { | |
264 | 0 | sgrps[sg].sg.deleteSequence(sqs[si], false); |
265 | } | |
266 | 5 | sgrps[sg] = null; |
267 | } | |
268 | } | |
269 | ||
270 | /** | |
271 | * construct an alignmentView from a SeqCigarArray. Errors are thrown if the | |
272 | * seqcigararray.isSeqCigarArray() flag is not set. | |
273 | */ | |
274 | 25 | public AlignmentView(CigarArray seqcigararray) |
275 | { | |
276 | 25 | if (!seqcigararray.isSeqCigarArray()) |
277 | { | |
278 | 0 | throw new Error( |
279 | "Implementation Error - can only make an alignment view from a CigarArray of sequences."); | |
280 | } | |
281 | // contigs = seqcigararray.applyDeletions(); | |
282 | 25 | contigs = seqcigararray.getDeletedRegions(); |
283 | 25 | sequences = seqcigararray.getSeqCigarArray(); |
284 | 25 | width = seqcigararray.getWidth(); // visible width |
285 | } | |
286 | ||
287 | /** | |
288 | * Create an alignmentView where the first column corresponds with the | |
289 | * 'firstcol' column of some reference alignment | |
290 | * | |
291 | * @param sdata | |
292 | * @param firstcol | |
293 | */ | |
294 | 24 | public AlignmentView(CigarArray sdata, int firstcol) |
295 | { | |
296 | 24 | this(sdata); |
297 | 24 | firstCol = firstcol; |
298 | } | |
299 | ||
300 | 3 | public void setSequences(SeqCigar[] sequences) |
301 | { | |
302 | 3 | this.sequences = sequences; |
303 | } | |
304 | ||
305 | 0 | public void setContigs(int[] contigs) |
306 | { | |
307 | 0 | this.contigs = contigs; |
308 | } | |
309 | ||
310 | 21 | public SeqCigar[] getSequences() |
311 | { | |
312 | 21 | return sequences; |
313 | } | |
314 | ||
315 | /** | |
316 | * @see CigarArray.getDeletedRegions | |
317 | * @return int[] { vis_start, sym_start, length } | |
318 | */ | |
319 | 0 | public int[] getContigs() |
320 | { | |
321 | 0 | return contigs; |
322 | } | |
323 | ||
324 | /** | |
325 | * get the full alignment and a columnselection object marking the hidden | |
326 | * regions | |
327 | * | |
328 | * @param gapCharacter | |
329 | * char | |
330 | * @return Object[] { SequenceI[], ColumnSelection} | |
331 | */ | |
332 | 3 | public Object[] getAlignmentAndHiddenColumns(char gapCharacter) |
333 | { | |
334 | 3 | HiddenColumns hidden = new HiddenColumns(); |
335 | ||
336 | 3 | return new Object[] { SeqCigar.createAlignmentSequences(sequences, |
337 | gapCharacter, hidden, contigs), | |
338 | hidden }; | |
339 | } | |
340 | ||
341 | /** | |
342 | * return the visible alignment corresponding to this view. Sequences in this | |
343 | * alignment are edited versions of the parent sequences - where hidden | |
344 | * regions have been removed. NOTE: the sequence data in this alignment is not | |
345 | * complete! | |
346 | * | |
347 | * @param c | |
348 | * @return | |
349 | */ | |
350 | 2 | public AlignmentI getVisibleAlignment(char c) |
351 | { | |
352 | 2 | SequenceI[] aln = getVisibleSeqs(c); |
353 | ||
354 | 2 | AlignmentI vcal = new Alignment(aln); |
355 | 2 | addPrunedGroupsInOrder(vcal, -1, -1, true); |
356 | 2 | return vcal; |
357 | } | |
358 | ||
359 | /** | |
360 | * add groups from view to the given alignment | |
361 | * | |
362 | * @param vcal | |
363 | * @param gstart | |
364 | * -1 or 0 to width-1 | |
365 | * @param gend | |
366 | * -1 or gstart to width-1 | |
367 | * @param viscontigs | |
368 | * - true if vcal is alignment of the visible regions of the view | |
369 | * (e.g. as returned from getVisibleAlignment) | |
370 | */ | |
371 | 4 | private void addPrunedGroupsInOrder(AlignmentI vcal, int gstart, int gend, |
372 | boolean viscontigs) | |
373 | { | |
374 | 4 | boolean r = false; |
375 | 4 | if (gstart > -1 && gstart <= gend) |
376 | { | |
377 | 2 | r = true; |
378 | } | |
379 | ||
380 | 4 | SequenceI[] aln = vcal.getSequencesArray(); |
381 | { | |
382 | /** | |
383 | * prune any groups to the visible coordinates of the alignment. | |
384 | */ | |
385 | { | |
386 | 4 | int nvg = (scGroups != null) ? scGroups.size() : 0; |
387 | 4 | if (nvg > 0) |
388 | { | |
389 | 2 | SequenceGroup[] nsg = new SequenceGroup[nvg]; |
390 | 12 | for (int g = 0; g < nvg; g++) |
391 | { | |
392 | 10 | SequenceGroup sg = scGroups.get(g).sg; |
393 | 10 | if (r) |
394 | { | |
395 | 10 | if (sg.getStartRes() > gend || sg.getEndRes() < gstart) |
396 | { | |
397 | // Skip this group | |
398 | 0 | nsg[g] = null; |
399 | 0 | continue; |
400 | } | |
401 | } | |
402 | ||
403 | // clone group properties | |
404 | 10 | nsg[g] = new SequenceGroup(sg); |
405 | ||
406 | // may need to shift/trim start and end ? | |
407 | 10 | if (r && !viscontigs) |
408 | { | |
409 | // Not fully tested code - routine not yet called with | |
410 | // viscontigs==false | |
411 | 0 | if (nsg[g].getStartRes() < gstart) |
412 | { | |
413 | 0 | nsg[g].setStartRes(0); |
414 | } | |
415 | else | |
416 | { | |
417 | 0 | nsg[g].setStartRes(nsg[g].getStartRes() - gstart); |
418 | 0 | nsg[g].setEndRes(nsg[g].getEndRes() - gstart); |
419 | } | |
420 | 0 | if (nsg[g].getEndRes() > (gend - gstart)) |
421 | { | |
422 | 0 | nsg[g].setEndRes(gend - gstart); |
423 | } | |
424 | } | |
425 | } | |
426 | 2 | if (viscontigs) |
427 | { | |
428 | // prune groups to cover just the visible positions between | |
429 | // gstart/gend. | |
430 | 2 | if (contigs != null) |
431 | { | |
432 | 0 | int p = 0; |
433 | 0 | ShiftList prune = new ShiftList(); |
434 | 0 | if (r) |
435 | { | |
436 | // adjust for start of alignment within visible window. | |
437 | 0 | prune.addShift(gstart, -gstart); // |
438 | } | |
439 | 0 | for (int h = 0; h < contigs.length; h += 3) |
440 | { | |
441 | { | |
442 | 0 | prune.addShift(p + contigs[h + 1], |
443 | contigs[h + 2] - contigs[h + 1]); | |
444 | } | |
445 | 0 | p = contigs[h + 1] + contigs[h + 2]; |
446 | } | |
447 | 0 | for (int g = 0; g < nsg.length; g++) |
448 | { | |
449 | 0 | if (nsg[g] != null) |
450 | { | |
451 | 0 | int s = nsg[g].getStartRes(), t = nsg[g].getEndRes(); |
452 | 0 | int w = 1 + t - s; |
453 | 0 | if (r) |
454 | { | |
455 | 0 | if (s < gstart) |
456 | { | |
457 | 0 | s = gstart; |
458 | } | |
459 | 0 | if (t > gend) |
460 | { | |
461 | 0 | t = gend; |
462 | } | |
463 | } | |
464 | 0 | s = prune.shift(s); |
465 | 0 | t = prune.shift(t); |
466 | 0 | nsg[g].setStartRes(s); |
467 | 0 | nsg[g].setEndRes(t); |
468 | } | |
469 | } | |
470 | } | |
471 | } | |
472 | ||
473 | 68 | for (int nsq = 0; nsq < aln.length; nsq++) |
474 | { | |
475 | 396 | for (int g = 0; g < nvg; g++) |
476 | { | |
477 | 330 | if (nsg[g] != null |
478 | && sequences[nsq].isMemberOf(scGroups.get(g))) | |
479 | { | |
480 | 66 | nsg[g].addSequence(aln[nsq], false); |
481 | } | |
482 | } | |
483 | } | |
484 | 12 | for (int g = 0; g < nvg; g++) |
485 | { | |
486 | 10 | if (nsg[g] != null && nsg[g].getSize() > 0) |
487 | { | |
488 | 10 | vcal.addGroup(nsg[g]); |
489 | } | |
490 | 10 | nsg[g] = null; |
491 | } | |
492 | } | |
493 | } | |
494 | } | |
495 | } | |
496 | ||
497 | /** | |
498 | * generate sequence array corresponding to the visible parts of the | |
499 | * alignment. | |
500 | * | |
501 | * @param c | |
502 | * gap character to use to recreate the alignment | |
503 | * @return | |
504 | */ | |
505 | 2 | private SequenceI[] getVisibleSeqs(char c) |
506 | { | |
507 | 2 | SequenceI[] aln = new SequenceI[sequences.length]; |
508 | 5 | for (int i = 0, j = sequences.length; i < j; i++) |
509 | { | |
510 | 3 | aln[i] = sequences[i].getSeq(c); |
511 | // Remove hidden regions from sequence | |
512 | 3 | aln[i].setSequence(getASequenceString(c, i)); |
513 | } | |
514 | 2 | return aln; |
515 | } | |
516 | ||
517 | /** | |
518 | * creates new alignment objects for all contiguous visible segments | |
519 | * | |
520 | * @param c | |
521 | * @param start | |
522 | * @param end | |
523 | * @param regionOfInterest | |
524 | * specify which sequences to include (or null to include all | |
525 | * sequences) | |
526 | * @return AlignmentI[] - all alignments where each sequence is a subsequence | |
527 | * constructed from visible contig regions of view | |
528 | */ | |
529 | 2 | public AlignmentI[] getVisibleContigAlignments(char c) |
530 | { | |
531 | 2 | int nvc = 0; |
532 | 2 | int[] vcontigs = getVisibleContigs(); |
533 | 2 | SequenceI[][] contigviews = getVisibleContigs(c); |
534 | 2 | AlignmentI[] vcals = new AlignmentI[contigviews.length]; |
535 | 4 | for (nvc = 0; nvc < contigviews.length; nvc++) |
536 | { | |
537 | 2 | vcals[nvc] = new Alignment(contigviews[nvc]); |
538 | 2 | if (scGroups != null && scGroups.size() > 0) |
539 | { | |
540 | 2 | addPrunedGroupsInOrder(vcals[nvc], vcontigs[nvc * 2], |
541 | vcontigs[nvc * 2 + 1], true); | |
542 | } | |
543 | } | |
544 | 2 | return vcals; |
545 | } | |
546 | ||
547 | /** | |
548 | * build a string excluding hidden regions from a particular sequence in the | |
549 | * view | |
550 | * | |
551 | * @param c | |
552 | * @param n | |
553 | * @return | |
554 | */ | |
555 | 24 | private String getASequenceString(char c, int n) |
556 | { | |
557 | 24 | String sqn; |
558 | 24 | String fullseq = sequences[n].getSequenceString(c); |
559 | 24 | if (contigs != null) |
560 | { | |
561 | 0 | sqn = ""; |
562 | 0 | int p = 0; |
563 | 0 | for (int h = 0; h < contigs.length; h += 3) |
564 | { | |
565 | 0 | sqn += fullseq.substring(p, contigs[h + 1]); |
566 | 0 | p = contigs[h + 1] + contigs[h + 2]; |
567 | } | |
568 | 0 | sqn += fullseq.substring(p); |
569 | } | |
570 | else | |
571 | { | |
572 | 24 | sqn = fullseq; |
573 | } | |
574 | 24 | return sqn; |
575 | } | |
576 | ||
577 | /** | |
578 | * get an array of visible sequence strings for a view on an alignment using | |
579 | * the given gap character uses getASequenceString | |
580 | * | |
581 | * @param c | |
582 | * char | |
583 | * @return String[] | |
584 | */ | |
585 | 5 | public String[] getSequenceStrings(char c) |
586 | { | |
587 | 5 | String[] seqs = new String[sequences.length]; |
588 | 26 | for (int n = 0; n < sequences.length; n++) |
589 | { | |
590 | 21 | seqs[n] = getASequenceString(c, n); |
591 | } | |
592 | 5 | return seqs; |
593 | } | |
594 | ||
595 | /** | |
596 | * | |
597 | * @return visible number of columns in alignment view | |
598 | */ | |
599 | 0 | public int getWidth() |
600 | { | |
601 | 0 | return width; |
602 | } | |
603 | ||
604 | 0 | protected void setWidth(int width) |
605 | { | |
606 | 0 | this.width = width; |
607 | } | |
608 | ||
609 | /** | |
610 | * get the contiguous subalignments in an alignment view. | |
611 | * | |
612 | * @param gapCharacter | |
613 | * char | |
614 | * @return SequenceI[][] | |
615 | */ | |
616 | 2 | public SequenceI[][] getVisibleContigs(char gapCharacter) |
617 | { | |
618 | 2 | SequenceI[][] smsa; |
619 | 2 | int njobs = 1; |
620 | 2 | if (sequences == null || width <= 0) |
621 | { | |
622 | 0 | return null; |
623 | } | |
624 | 2 | if (contigs != null && contigs.length > 0) |
625 | { | |
626 | 0 | int start = 0; |
627 | 0 | njobs = 0; |
628 | 0 | int fwidth = width; |
629 | 0 | for (int contig = 0; contig < contigs.length; contig += 3) |
630 | { | |
631 | 0 | if ((contigs[contig + 1] - start) > 0) |
632 | { | |
633 | 0 | njobs++; |
634 | } | |
635 | 0 | fwidth += contigs[contig + 2]; // end up with full region width |
636 | // (including hidden regions) | |
637 | 0 | start = contigs[contig + 1] + contigs[contig + 2]; |
638 | } | |
639 | 0 | if (start < fwidth) |
640 | { | |
641 | 0 | njobs++; |
642 | } | |
643 | 0 | smsa = new SequenceI[njobs][]; |
644 | 0 | start = 0; |
645 | 0 | int j = 0; |
646 | 0 | for (int contig = 0; contig < contigs.length; contig += 3) |
647 | { | |
648 | 0 | if (contigs[contig + 1] - start > 0) |
649 | { | |
650 | 0 | SequenceI mseq[] = new SequenceI[sequences.length]; |
651 | 0 | for (int s = 0; s < mseq.length; s++) |
652 | { | |
653 | 0 | mseq[s] = sequences[s].getSeq(gapCharacter) |
654 | .getSubSequence(start, contigs[contig + 1]); | |
655 | } | |
656 | 0 | smsa[j] = mseq; |
657 | 0 | j++; |
658 | } | |
659 | 0 | start = contigs[contig + 1] + contigs[contig + 2]; |
660 | } | |
661 | 0 | if (start < fwidth) |
662 | { | |
663 | 0 | SequenceI mseq[] = new SequenceI[sequences.length]; |
664 | 0 | for (int s = 0; s < mseq.length; s++) |
665 | { | |
666 | 0 | mseq[s] = sequences[s].getSeq(gapCharacter).getSubSequence(start, |
667 | fwidth + 1); | |
668 | } | |
669 | 0 | smsa[j] = mseq; |
670 | 0 | j++; |
671 | } | |
672 | } | |
673 | else | |
674 | { | |
675 | 2 | smsa = new SequenceI[1][]; |
676 | 2 | smsa[0] = new SequenceI[sequences.length]; |
677 | 68 | for (int s = 0; s < sequences.length; s++) |
678 | { | |
679 | 66 | smsa[0][s] = sequences[s].getSeq(gapCharacter); |
680 | } | |
681 | } | |
682 | 2 | return smsa; |
683 | } | |
684 | ||
685 | /** | |
686 | * return full msa and hidden regions with visible blocks replaced with new | |
687 | * sub alignments | |
688 | * | |
689 | * @param nvismsa | |
690 | * SequenceI[][] | |
691 | * @param orders | |
692 | * AlignmentOrder[] corresponding to each SequenceI[] block. | |
693 | * @return Object[] | |
694 | */ | |
695 | 0 | public Object[] getUpdatedView(SequenceI[][] nvismsa, |
696 | AlignmentOrder[] orders, char gapCharacter) | |
697 | { | |
698 | 0 | if (sequences == null || width <= 0) |
699 | { | |
700 | 0 | throw new Error(MessageManager |
701 | .getString("error.empty_view_cannot_be_updated")); | |
702 | } | |
703 | 0 | if (nvismsa == null) |
704 | { | |
705 | 0 | throw new Error( |
706 | "nvismsa==null. use getAlignmentAndColumnSelection() instead."); | |
707 | } | |
708 | 0 | if (contigs != null && contigs.length > 0) |
709 | { | |
710 | 0 | SequenceI[] alignment = new SequenceI[sequences.length]; |
711 | // ColumnSelection columnselection = new ColumnSelection(); | |
712 | 0 | HiddenColumns hidden = new HiddenColumns(); |
713 | 0 | if (contigs != null && contigs.length > 0) |
714 | { | |
715 | 0 | int start = 0; |
716 | 0 | int nwidth = 0; |
717 | 0 | int owidth = width; |
718 | 0 | int j = 0; |
719 | 0 | for (int contig = 0; contig < contigs.length; contig += 3) |
720 | { | |
721 | 0 | owidth += contigs[contig + 2]; // recover final column width |
722 | 0 | if (contigs[contig + 1] - start > 0) |
723 | { | |
724 | 0 | int swidth = 0; // subalignment width |
725 | 0 | if (nvismsa[j] != null) |
726 | { | |
727 | 0 | SequenceI mseq[] = nvismsa[j]; |
728 | 0 | AlignmentOrder order = (orders == null) ? null : orders[j]; |
729 | 0 | j++; |
730 | 0 | if (mseq.length != sequences.length) |
731 | { | |
732 | 0 | throw new Error(MessageManager.formatMessage( |
733 | "error.mismatch_between_number_of_sequences_in_block", | |
734 | new String[] | |
735 | { Integer.valueOf(j).toString(), | |
736 | Integer.valueOf(mseq.length).toString(), | |
737 | Integer.valueOf(sequences.length) | |
738 | .toString() })); | |
739 | } | |
740 | 0 | swidth = mseq[0].getLength(); // JBPNote: could ensure padded |
741 | // here. | |
742 | 0 | for (int s = 0; s < mseq.length; s++) |
743 | { | |
744 | 0 | if (alignment[s] == null) |
745 | { | |
746 | 0 | alignment[s] = mseq[s]; |
747 | } | |
748 | else | |
749 | { | |
750 | 0 | alignment[s] |
751 | .setSequence(alignment[s].getSequenceAsString() | |
752 | + mseq[s].getSequenceAsString()); | |
753 | 0 | if (mseq[s].getStart() <= mseq[s].getEnd()) |
754 | { | |
755 | 0 | alignment[s].setEnd(mseq[s].getEnd()); |
756 | } | |
757 | 0 | if (order != null) |
758 | { | |
759 | 0 | order.updateSequence(mseq[s], alignment[s]); |
760 | } | |
761 | } | |
762 | } | |
763 | } | |
764 | else | |
765 | { | |
766 | // recover original alignment block or place gaps | |
767 | 0 | if (true) |
768 | { | |
769 | // recover input data | |
770 | 0 | for (int s = 0; s < sequences.length; s++) |
771 | { | |
772 | 0 | SequenceI oseq = sequences[s].getSeq(gapCharacter) |
773 | .getSubSequence(start, contigs[contig + 1]); | |
774 | 0 | if (swidth < oseq.getLength()) |
775 | { | |
776 | 0 | swidth = oseq.getLength(); |
777 | } | |
778 | 0 | if (alignment[s] == null) |
779 | { | |
780 | 0 | alignment[s] = oseq; |
781 | } | |
782 | else | |
783 | { | |
784 | 0 | alignment[s] |
785 | .setSequence(alignment[s].getSequenceAsString() | |
786 | + oseq.getSequenceAsString()); | |
787 | 0 | if (oseq.getEnd() >= oseq.getStart()) |
788 | { | |
789 | 0 | alignment[s].setEnd(oseq.getEnd()); |
790 | } | |
791 | } | |
792 | } | |
793 | ||
794 | } | |
795 | 0 | j++; |
796 | } | |
797 | 0 | nwidth += swidth; |
798 | } | |
799 | // advance to begining of visible region | |
800 | 0 | start = contigs[contig + 1] + contigs[contig + 2]; |
801 | // add hidden segment to right of next region | |
802 | 0 | for (int s = 0; s < sequences.length; s++) |
803 | { | |
804 | 0 | SequenceI hseq = sequences[s].getSeq(gapCharacter) |
805 | .getSubSequence(contigs[contig + 1], start); | |
806 | 0 | if (alignment[s] == null) |
807 | { | |
808 | 0 | alignment[s] = hseq; |
809 | } | |
810 | else | |
811 | { | |
812 | 0 | alignment[s].setSequence(alignment[s].getSequenceAsString() |
813 | + hseq.getSequenceAsString()); | |
814 | 0 | if (hseq.getEnd() >= hseq.getStart()) |
815 | { | |
816 | 0 | alignment[s].setEnd(hseq.getEnd()); |
817 | } | |
818 | } | |
819 | } | |
820 | // mark hidden segment as hidden in the new alignment | |
821 | 0 | hidden.hideColumns(nwidth, nwidth + contigs[contig + 2] - 1); |
822 | 0 | nwidth += contigs[contig + 2]; |
823 | } | |
824 | // Do final segment - if it exists | |
825 | 0 | if (j < nvismsa.length) |
826 | { | |
827 | 0 | int swidth = 0; |
828 | 0 | if (nvismsa[j] != null) |
829 | { | |
830 | 0 | SequenceI mseq[] = nvismsa[j]; |
831 | 0 | AlignmentOrder order = (orders != null) ? orders[j] : null; |
832 | 0 | swidth = mseq[0].getLength(); |
833 | 0 | for (int s = 0; s < mseq.length; s++) |
834 | { | |
835 | 0 | if (alignment[s] == null) |
836 | { | |
837 | 0 | alignment[s] = mseq[s]; |
838 | } | |
839 | else | |
840 | { | |
841 | 0 | alignment[s].setSequence(alignment[s].getSequenceAsString() |
842 | + mseq[s].getSequenceAsString()); | |
843 | 0 | if (mseq[s].getEnd() >= mseq[s].getStart()) |
844 | { | |
845 | 0 | alignment[s].setEnd(mseq[s].getEnd()); |
846 | } | |
847 | 0 | if (order != null) |
848 | { | |
849 | 0 | order.updateSequence(mseq[s], alignment[s]); |
850 | } | |
851 | } | |
852 | } | |
853 | } | |
854 | else | |
855 | { | |
856 | 0 | if (start < owidth) |
857 | { | |
858 | // recover input data or place gaps | |
859 | 0 | if (true) |
860 | { | |
861 | // recover input data | |
862 | 0 | for (int s = 0; s < sequences.length; s++) |
863 | { | |
864 | 0 | SequenceI oseq = sequences[s].getSeq(gapCharacter) |
865 | .getSubSequence(start, owidth + 1); | |
866 | 0 | if (swidth < oseq.getLength()) |
867 | { | |
868 | 0 | swidth = oseq.getLength(); |
869 | } | |
870 | 0 | if (alignment[s] == null) |
871 | { | |
872 | 0 | alignment[s] = oseq; |
873 | } | |
874 | else | |
875 | { | |
876 | 0 | alignment[s] |
877 | .setSequence(alignment[s].getSequenceAsString() | |
878 | + oseq.getSequenceAsString()); | |
879 | 0 | if (oseq.getEnd() >= oseq.getStart()) |
880 | { | |
881 | 0 | alignment[s].setEnd(oseq.getEnd()); |
882 | } | |
883 | } | |
884 | } | |
885 | 0 | nwidth += swidth; |
886 | } | |
887 | else | |
888 | { | |
889 | // place gaps. | |
890 | 0 | throw new Error(MessageManager |
891 | .getString("error.padding_not_yet_implemented")); | |
892 | } | |
893 | } | |
894 | } | |
895 | } | |
896 | } | |
897 | 0 | return new Object[] { alignment, hidden }; |
898 | } | |
899 | else | |
900 | { | |
901 | 0 | if (nvismsa.length != 1) |
902 | { | |
903 | 0 | throw new Error(MessageManager.formatMessage( |
904 | "error.mismatch_between_visible_blocks_to_update_and_number_of_contigs_in_view", | |
905 | new String[] | |
906 | { Integer.valueOf(nvismsa.length).toString() })); | |
907 | } | |
908 | 0 | if (nvismsa[0] != null) |
909 | { | |
910 | 0 | return new Object[] { nvismsa[0], new HiddenColumns() }; |
911 | } | |
912 | else | |
913 | { | |
914 | 0 | return getAlignmentAndHiddenColumns(gapCharacter); |
915 | } | |
916 | } | |
917 | } | |
918 | ||
919 | /** | |
920 | * returns simple array of start end positions of visible range on alignment. | |
921 | * vis_start and vis_end are inclusive - use | |
922 | * SequenceI.getSubSequence(vis_start, vis_end+1) to recover visible sequence | |
923 | * from underlying alignment. | |
924 | * | |
925 | * @return int[] { start_i, end_i } for 1<i<n visible regions. | |
926 | */ | |
927 | 25 | public int[] getVisibleContigs() |
928 | { | |
929 | 25 | if (contigs != null && contigs.length > 0) |
930 | { | |
931 | 8 | int start = 0; |
932 | 8 | int nvis = 0; |
933 | 8 | int fwidth = width; |
934 | 22 | for (int contig = 0; contig < contigs.length; contig += 3) |
935 | { | |
936 | 14 | if ((contigs[contig + 1] - start) > 0) |
937 | { | |
938 | 7 | nvis++; |
939 | } | |
940 | 14 | fwidth += contigs[contig + 2]; // end up with full region width |
941 | // (including hidden regions) | |
942 | 14 | start = contigs[contig + 1] + contigs[contig + 2]; |
943 | } | |
944 | 8 | if (start < fwidth) |
945 | { | |
946 | 3 | nvis++; |
947 | } | |
948 | 8 | int viscontigs[] = new int[nvis * 2]; |
949 | 8 | nvis = 0; |
950 | 8 | start = 0; |
951 | 22 | for (int contig = 0; contig < contigs.length; contig += 3) |
952 | { | |
953 | 14 | if ((contigs[contig + 1] - start) > 0) |
954 | { | |
955 | 7 | viscontigs[nvis] = start; |
956 | 7 | viscontigs[nvis + 1] = contigs[contig + 1] - 1; // end is inclusive |
957 | 7 | nvis += 2; |
958 | } | |
959 | 14 | start = contigs[contig + 1] + contigs[contig + 2]; |
960 | } | |
961 | 8 | if (start < fwidth) |
962 | { | |
963 | 3 | viscontigs[nvis] = start; |
964 | 3 | viscontigs[nvis + 1] = fwidth - 1; // end is inclusive |
965 | 3 | nvis += 2; |
966 | } | |
967 | 8 | return viscontigs; |
968 | } | |
969 | else | |
970 | { | |
971 | 17 | return new int[] { 0, width - 1 }; |
972 | } | |
973 | } | |
974 | ||
975 | /** | |
976 | * | |
977 | * @return position of first visible column of AlignmentView within its | |
978 | * parent's alignment reference frame | |
979 | */ | |
980 | 0 | public int getAlignmentOrigin() |
981 | { | |
982 | 0 | return firstCol; |
983 | } | |
984 | ||
985 | /** | |
986 | * compute a deletion map for the current view according to the given | |
987 | * gap/match map | |
988 | * | |
989 | * @param gapMap | |
990 | * (as returned from SequenceI.gapMap()) | |
991 | * @return int[] {intersection of visible regions with gapMap) | |
992 | */ | |
993 | 0 | public int[] getVisibleContigMapFor(int[] gapMap) |
994 | { | |
995 | 0 | int[] delMap = null; |
996 | 0 | int[] viscontigs = getVisibleContigs(); |
997 | 0 | int spos = 0; |
998 | 0 | int i = 0; |
999 | 0 | if (viscontigs != null) |
1000 | { | |
1001 | // viscontigs maps from a subset of the gapMap to the gapMap, so it will | |
1002 | // always be equal to or shorter than gapMap | |
1003 | 0 | delMap = new int[gapMap.length]; |
1004 | 0 | for (int contig = 0; contig < viscontigs.length; contig += 2) |
1005 | { | |
1006 | ||
1007 | 0 | while (spos < gapMap.length && gapMap[spos] < viscontigs[contig]) |
1008 | { | |
1009 | 0 | spos++; |
1010 | } | |
1011 | 0 | while (spos < gapMap.length |
1012 | && gapMap[spos] <= viscontigs[contig + 1]) | |
1013 | { | |
1014 | 0 | delMap[i++] = spos++; |
1015 | } | |
1016 | } | |
1017 | 0 | int tmap[] = new int[i]; |
1018 | 0 | System.arraycopy(delMap, 0, tmap, 0, i); |
1019 | 0 | delMap = tmap; |
1020 | } | |
1021 | 0 | return delMap; |
1022 | } | |
1023 | ||
1024 | /** | |
1025 | * apply the getSeq(gc) method to each sequence cigar, and return the array of | |
1026 | * edited sequences, optionally with hidden regions removed. | |
1027 | * | |
1028 | * @param gc | |
1029 | * gap character to use for insertions | |
1030 | * @param delete | |
1031 | * remove hidden regions from sequences. Note: currently implemented | |
1032 | * in a memory inefficient way - space needed is 2*result set for | |
1033 | * deletion | |
1034 | * | |
1035 | * @return SequenceI[] | |
1036 | */ | |
1037 | 0 | public SequenceI[] getEditedSequences(char gc, boolean delete) |
1038 | { | |
1039 | 0 | SeqCigar[] msf = getSequences(); |
1040 | 0 | SequenceI[] aln = new SequenceI[msf.length]; |
1041 | 0 | for (int i = 0, j = msf.length; i < j; i++) |
1042 | { | |
1043 | 0 | aln[i] = msf[i].getSeq(gc); |
1044 | } | |
1045 | 0 | if (delete) |
1046 | { | |
1047 | 0 | String[] sqs = getSequenceStrings(gc); |
1048 | 0 | for (int i = 0; i < sqs.length; i++) |
1049 | { | |
1050 | 0 | aln[i].setSequence(sqs[i]); |
1051 | 0 | sqs[i] = null; |
1052 | } | |
1053 | } | |
1054 | 0 | return aln; |
1055 | } | |
1056 | ||
1057 | 0 | public static void summariseAlignmentView(AlignmentView view, |
1058 | PrintStream os) | |
1059 | { | |
1060 | 0 | os.print("View has " + view.sequences.length + " of which "); |
1061 | 0 | if (view.selected == null) |
1062 | { | |
1063 | 0 | os.print("None"); |
1064 | } | |
1065 | else | |
1066 | { | |
1067 | 0 | os.print(" " + view.selected.size()); |
1068 | } | |
1069 | 0 | os.println(" are selected."); |
1070 | 0 | os.print("View is " + view.getWidth() + " columns wide"); |
1071 | 0 | int viswid = 0; |
1072 | 0 | int[] contigs = view.getContigs(); |
1073 | 0 | if (contigs != null) |
1074 | { | |
1075 | 0 | viswid = view.width; |
1076 | 0 | for (int i = 0; i < contigs.length; i += 3) |
1077 | { | |
1078 | 0 | viswid += contigs[i + 2]; |
1079 | } | |
1080 | 0 | os.println("with " + viswid + " visible columns spread over " |
1081 | + contigs.length / 3 + " regions."); | |
1082 | } | |
1083 | else | |
1084 | { | |
1085 | 0 | viswid = view.width; |
1086 | 0 | os.println("."); |
1087 | } | |
1088 | 0 | if (view.scGroups != null) |
1089 | { | |
1090 | 0 | os.println("There are " + view.scGroups.size() |
1091 | + " groups defined on the view."); | |
1092 | 0 | for (int g = 0; g < view.scGroups.size(); g++) |
1093 | { | |
1094 | 0 | ScGroup sgr = view.scGroups.get(g); |
1095 | 0 | os.println("Group " + g + ": Name = " + sgr.sg.getName() |
1096 | + " Contains " + sgr.seqs.size() + " Seqs."); | |
1097 | 0 | os.println("This group runs from " + sgr.sg.getStartRes() + " to " |
1098 | + sgr.sg.getEndRes()); | |
1099 | 0 | for (int s = 0; s < sgr.seqs.size(); s++) |
1100 | { | |
1101 | // JBPnote this should be a unit test for ScGroup | |
1102 | 0 | if (!sgr.seqs.get(s).isMemberOf(sgr)) |
1103 | { | |
1104 | 0 | os.println("** WARNING: sequence " + sgr.seqs.get(s).toString() |
1105 | + " is not marked as member of group."); | |
1106 | } | |
1107 | } | |
1108 | } | |
1109 | 0 | AlignmentI visal = view.getVisibleAlignment('-'); |
1110 | 0 | if (visal != null) |
1111 | { | |
1112 | 0 | os.println("Vis. alignment is " + visal.getWidth() |
1113 | + " wide and has " + visal.getHeight() + " seqs."); | |
1114 | 0 | if (visal.getGroups() != null && visal.getGroups().size() > 0) |
1115 | { | |
1116 | ||
1117 | 0 | int i = 1; |
1118 | 0 | for (SequenceGroup sg : visal.getGroups()) |
1119 | { | |
1120 | 0 | os.println("Group " + (i++) + " begins at column " |
1121 | + sg.getStartRes() + " and ends at " + sg.getEndRes()); | |
1122 | } | |
1123 | } | |
1124 | } | |
1125 | } | |
1126 | } | |
1127 | ||
1128 | 0 | public static void testSelectionViews(AlignmentI alignment, |
1129 | HiddenColumns hidden, SequenceGroup selection) | |
1130 | { | |
1131 | 0 | jalview.bin.Console.outPrintln("Testing standard view creation:\n"); |
1132 | 0 | AlignmentView view = null; |
1133 | 0 | try |
1134 | { | |
1135 | 0 | jalview.bin.Console.outPrintln( |
1136 | "View with no hidden columns, no limit to selection, no groups to be collected:"); | |
1137 | 0 | view = new AlignmentView(alignment, hidden, selection, false, false, |
1138 | false); | |
1139 | 0 | summariseAlignmentView(view, System.out); |
1140 | ||
1141 | } catch (Exception e) | |
1142 | { | |
1143 | 0 | e.printStackTrace(); |
1144 | 0 | jalview.bin.Console.errPrintln( |
1145 | "Failed to generate alignment with selection but no groups marked."); | |
1146 | } | |
1147 | 0 | try |
1148 | { | |
1149 | 0 | jalview.bin.Console.outPrintln( |
1150 | "View with no hidden columns, no limit to selection, and all groups to be collected:"); | |
1151 | 0 | view = new AlignmentView(alignment, hidden, selection, false, false, |
1152 | true); | |
1153 | 0 | summariseAlignmentView(view, System.out); |
1154 | } catch (Exception e) | |
1155 | { | |
1156 | 0 | e.printStackTrace(); |
1157 | 0 | jalview.bin.Console.errPrintln( |
1158 | "Failed to generate alignment with selection marked but no groups marked."); | |
1159 | } | |
1160 | 0 | try |
1161 | { | |
1162 | 0 | jalview.bin.Console.outPrintln( |
1163 | "View with no hidden columns, limited to selection and no groups to be collected:"); | |
1164 | 0 | view = new AlignmentView(alignment, hidden, selection, false, true, |
1165 | false); | |
1166 | 0 | summariseAlignmentView(view, System.out); |
1167 | } catch (Exception e) | |
1168 | { | |
1169 | 0 | e.printStackTrace(); |
1170 | 0 | jalview.bin.Console.errPrintln( |
1171 | "Failed to generate alignment with selection restricted but no groups marked."); | |
1172 | } | |
1173 | 0 | try |
1174 | { | |
1175 | 0 | jalview.bin.Console.outPrintln( |
1176 | "View with no hidden columns, limited to selection, and all groups to be collected:"); | |
1177 | 0 | view = new AlignmentView(alignment, hidden, selection, false, true, |
1178 | true); | |
1179 | 0 | summariseAlignmentView(view, System.out); |
1180 | } catch (Exception e) | |
1181 | { | |
1182 | 0 | e.printStackTrace(); |
1183 | 0 | jalview.bin.Console.errPrintln( |
1184 | "Failed to generate alignment with selection restricted and groups marked."); | |
1185 | } | |
1186 | 0 | try |
1187 | { | |
1188 | 0 | jalview.bin.Console.outPrintln( |
1189 | "View *with* hidden columns, no limit to selection, no groups to be collected:"); | |
1190 | 0 | view = new AlignmentView(alignment, hidden, selection, true, false, |
1191 | false); | |
1192 | 0 | summariseAlignmentView(view, System.out); |
1193 | } catch (Exception e) | |
1194 | { | |
1195 | 0 | e.printStackTrace(); |
1196 | 0 | jalview.bin.Console.errPrintln( |
1197 | "Failed to generate alignment with selection but no groups marked."); | |
1198 | } | |
1199 | 0 | try |
1200 | { | |
1201 | 0 | jalview.bin.Console.outPrintln( |
1202 | "View *with* hidden columns, no limit to selection, and all groups to be collected:"); | |
1203 | 0 | view = new AlignmentView(alignment, hidden, selection, true, false, |
1204 | true); | |
1205 | 0 | summariseAlignmentView(view, System.out); |
1206 | } catch (Exception e) | |
1207 | { | |
1208 | 0 | e.printStackTrace(); |
1209 | 0 | jalview.bin.Console.errPrintln( |
1210 | "Failed to generate alignment with selection marked but no groups marked."); | |
1211 | } | |
1212 | 0 | try |
1213 | { | |
1214 | 0 | jalview.bin.Console.outPrintln( |
1215 | "View *with* hidden columns, limited to selection and no groups to be collected:"); | |
1216 | 0 | view = new AlignmentView(alignment, hidden, selection, true, true, |
1217 | false); | |
1218 | 0 | summariseAlignmentView(view, System.out); |
1219 | } catch (Exception e) | |
1220 | { | |
1221 | 0 | e.printStackTrace(); |
1222 | 0 | jalview.bin.Console.errPrintln( |
1223 | "Failed to generate alignment with selection restricted but no groups marked."); | |
1224 | } | |
1225 | 0 | try |
1226 | { | |
1227 | 0 | jalview.bin.Console.outPrintln( |
1228 | "View *with* hidden columns, limited to selection, and all groups to be collected:"); | |
1229 | 0 | view = new AlignmentView(alignment, hidden, selection, true, true, |
1230 | true); | |
1231 | 0 | summariseAlignmentView(view, System.out); |
1232 | } catch (Exception e) | |
1233 | { | |
1234 | 0 | e.printStackTrace(); |
1235 | 0 | jalview.bin.Console.errPrintln( |
1236 | "Failed to generate alignment with selection restricted and groups marked."); | |
1237 | } | |
1238 | ||
1239 | } | |
1240 | } |