+
+ /**
+ * get the contiguous subalignments in an alignment view.
+ *
+ * @param gapCharacter
+ * char
+ * @return SequenceI[][]
+ */
+ public SequenceI[][] getVisibleContigs(char gapCharacter)
+ {
+ SequenceI[][] smsa;
+ int njobs = 1;
+ if (sequences == null || width <= 0)
+ {
+ return null;
+ }
+ if (contigs != null && contigs.length > 0)
+ {
+ int start = 0;
+ njobs = 0;
+ int fwidth = width;
+ for (int contig = 0; contig < contigs.length; contig += 3)
+ {
+ if ((contigs[contig + 1] - start) > 0)
+ {
+ njobs++;
+ }
+ fwidth += contigs[contig + 2]; // end up with full region width
+ // (including hidden regions)
+ start = contigs[contig + 1] + contigs[contig + 2];
+ }
+ if (start < fwidth)
+ {
+ njobs++;
+ }
+ smsa = new SequenceI[njobs][];
+ start = 0;
+ int j = 0;
+ for (int contig = 0; contig < contigs.length; contig += 3)
+ {
+ if (contigs[contig + 1] - start > 0)
+ {
+ SequenceI mseq[] = new SequenceI[sequences.length];
+ for (int s = 0; s < mseq.length; s++)
+ {
+ mseq[s] = sequences[s].getSeq(gapCharacter).getSubSequence(
+ start, contigs[contig + 1]);
+ }
+ smsa[j] = mseq;
+ j++;
+ }
+ start = contigs[contig + 1] + contigs[contig + 2];
+ }
+ if (start < fwidth)
+ {
+ SequenceI mseq[] = new SequenceI[sequences.length];
+ for (int s = 0; s < mseq.length; s++)
+ {
+ mseq[s] = sequences[s].getSeq(gapCharacter).getSubSequence(start,
+ fwidth + 1);
+ }
+ smsa[j] = mseq;
+ j++;
+ }
+ }
+ else
+ {
+ smsa = new SequenceI[1][];
+ smsa[0] = new SequenceI[sequences.length];
+ for (int s = 0; s < sequences.length; s++)
+ {
+ smsa[0][s] = sequences[s].getSeq(gapCharacter);
+ }
+ }
+ return smsa;
+ }
+
+ /**
+ * return full msa and hidden regions with visible blocks replaced with new
+ * sub alignments
+ *
+ * @param nvismsa
+ * SequenceI[][]
+ * @param orders
+ * AlignmentOrder[] corresponding to each SequenceI[] block.
+ * @return Object[]
+ */
+ public Object[] getUpdatedView(SequenceI[][] nvismsa,
+ AlignmentOrder[] orders, char gapCharacter)
+ {
+ if (sequences == null || width <= 0)
+ {
+ throw new Error(MessageManager.getString("error.empty_view_cannot_be_updated"));
+ }
+ if (nvismsa == null)
+ {
+ throw new Error(
+ "nvismsa==null. use getAlignmentAndColumnSelection() instead.");
+ }
+ if (contigs != null && contigs.length > 0)
+ {
+ SequenceI[] alignment = new SequenceI[sequences.length];
+ ColumnSelection columnselection = new ColumnSelection();
+ if (contigs != null && contigs.length > 0)
+ {
+ int start = 0;
+ int nwidth = 0;
+ int owidth = width;
+ int j = 0;
+ for (int contig = 0; contig < contigs.length; contig += 3)
+ {
+ owidth += contigs[contig + 2]; // recover final column width
+ if (contigs[contig + 1] - start > 0)
+ {
+ int swidth = 0; // subalignment width
+ if (nvismsa[j] != null)
+ {
+ SequenceI mseq[] = nvismsa[j];
+ AlignmentOrder order = (orders == null) ? null : orders[j];
+ j++;
+ if (mseq.length != sequences.length)
+ {
+ throw new Error(MessageManager.formatMessage("error.mismatch_between_number_of_sequences_in_block", new String[]{Integer.valueOf(j).toString(),Integer.valueOf(mseq.length).toString(),Integer.valueOf(sequences.length).toString() }));
+ }
+ swidth = mseq[0].getLength(); // JBPNote: could ensure padded
+ // here.
+ for (int s = 0; s < mseq.length; s++)
+ {
+ if (alignment[s] == null)
+ {
+ alignment[s] = mseq[s];
+ }
+ else
+ {
+ alignment[s].setSequence(alignment[s]
+ .getSequenceAsString()
+ + mseq[s].getSequenceAsString());
+ if (mseq[s].getStart() <= mseq[s].getEnd())
+ {
+ alignment[s].setEnd(mseq[s].getEnd());
+ }
+ if (order != null)
+ {
+ order.updateSequence(mseq[s], alignment[s]);
+ }
+ }
+ }
+ }
+ else
+ {
+ // recover original alignment block or place gaps
+ if (true)
+ {
+ // recover input data
+ for (int s = 0; s < sequences.length; s++)
+ {
+ SequenceI oseq = sequences[s].getSeq(gapCharacter)
+ .getSubSequence(start, contigs[contig + 1]);
+ if (swidth < oseq.getLength())
+ {
+ swidth = oseq.getLength();
+ }
+ if (alignment[s] == null)
+ {
+ alignment[s] = oseq;
+ }
+ else
+ {
+ alignment[s].setSequence(alignment[s]
+ .getSequenceAsString()
+ + oseq.getSequenceAsString());
+ if (oseq.getEnd() >= oseq.getStart())
+ {
+ alignment[s].setEnd(oseq.getEnd());
+ }
+ }
+ }
+
+ }
+ j++;
+ }
+ nwidth += swidth;
+ }
+ // advance to begining of visible region
+ start = contigs[contig + 1] + contigs[contig + 2];
+ // add hidden segment to right of next region
+ for (int s = 0; s < sequences.length; s++)
+ {
+ SequenceI hseq = sequences[s].getSeq(gapCharacter)
+ .getSubSequence(contigs[contig + 1], start);
+ if (alignment[s] == null)
+ {
+ alignment[s] = hseq;
+ }
+ else
+ {
+ alignment[s].setSequence(alignment[s].getSequenceAsString()
+ + hseq.getSequenceAsString());
+ if (hseq.getEnd() >= hseq.getStart())
+ {
+ alignment[s].setEnd(hseq.getEnd());
+ }
+ }
+ }
+ // mark hidden segment as hidden in the new alignment
+ columnselection.hideColumns(nwidth, nwidth + contigs[contig + 2]
+ - 1);
+ nwidth += contigs[contig + 2];
+ }
+ // Do final segment - if it exists
+ if (j < nvismsa.length)
+ {
+ int swidth = 0;
+ if (nvismsa[j] != null)
+ {
+ SequenceI mseq[] = nvismsa[j];
+ AlignmentOrder order = (orders != null) ? orders[j] : null;
+ swidth = mseq[0].getLength();
+ for (int s = 0; s < mseq.length; s++)
+ {
+ if (alignment[s] == null)
+ {
+ alignment[s] = mseq[s];
+ }
+ else
+ {
+ alignment[s].setSequence(alignment[s].getSequenceAsString()
+ + mseq[s].getSequenceAsString());
+ if (mseq[s].getEnd() >= mseq[s].getStart())
+ {
+ alignment[s].setEnd(mseq[s].getEnd());
+ }
+ if (order != null)
+ {
+ order.updateSequence(mseq[s], alignment[s]);
+ }
+ }
+ }
+ }
+ else
+ {
+ if (start < owidth)
+ {
+ // recover input data or place gaps
+ if (true)
+ {
+ // recover input data
+ for (int s = 0; s < sequences.length; s++)
+ {
+ SequenceI oseq = sequences[s].getSeq(gapCharacter)
+ .getSubSequence(start, owidth + 1);
+ if (swidth < oseq.getLength())
+ {
+ swidth = oseq.getLength();
+ }
+ if (alignment[s] == null)
+ {
+ alignment[s] = oseq;
+ }
+ else
+ {
+ alignment[s].setSequence(alignment[s]
+ .getSequenceAsString()
+ + oseq.getSequenceAsString());
+ if (oseq.getEnd() >= oseq.getStart())
+ {
+ alignment[s].setEnd(oseq.getEnd());
+ }
+ }
+ }
+ nwidth += swidth;
+ }
+ else
+ {
+ // place gaps.
+ throw new Error(MessageManager.getString("error.padding_not_yet_implemented"));
+ }
+ }
+ }
+ }
+ }
+ return new Object[]
+ { alignment, columnselection };
+ }
+ else
+ {
+ if (nvismsa.length != 1)
+ {
+ throw new Error(MessageManager.formatMessage("error.mismatch_between_visible_blocks_to_update_and_number_of_contigs_in_view", new String[]{Integer.valueOf(nvismsa.length).toString()}));
+ }
+ if (nvismsa[0] != null)
+ {
+ return new Object[]
+ { nvismsa[0], new ColumnSelection() };
+ }
+ else
+ {
+ return getAlignmentAndColumnSelection(gapCharacter);
+ }
+ }
+ }
+
+ /**
+ * returns simple array of start end positions of visible range on alignment.
+ * vis_start and vis_end are inclusive - use
+ * SequenceI.getSubSequence(vis_start, vis_end+1) to recover visible sequence
+ * from underlying alignment.
+ *
+ * @return int[] { start_i, end_i } for 1<i<n visible regions.
+ */
+ public int[] getVisibleContigs()
+ {
+ if (contigs != null && contigs.length > 0)
+ {
+ int start = 0;
+ int nvis = 0;
+ int fwidth = width;
+ for (int contig = 0; contig < contigs.length; contig += 3)
+ {
+ if ((contigs[contig + 1] - start) > 0)
+ {
+ nvis++;
+ }
+ fwidth += contigs[contig + 2]; // end up with full region width
+ // (including hidden regions)
+ start = contigs[contig + 1] + contigs[contig + 2];
+ }
+ if (start < fwidth)
+ {
+ nvis++;
+ }
+ int viscontigs[] = new int[nvis * 2];
+ nvis = 0;
+ start = 0;
+ for (int contig = 0; contig < contigs.length; contig += 3)
+ {
+ if ((contigs[contig + 1] - start) > 0)
+ {
+ viscontigs[nvis] = start;
+ viscontigs[nvis + 1] = contigs[contig + 1] - 1; // end is inclusive
+ nvis += 2;
+ }
+ start = contigs[contig + 1] + contigs[contig + 2];
+ }
+ if (start < fwidth)
+ {
+ viscontigs[nvis] = start;
+ viscontigs[nvis + 1] = fwidth; // end is inclusive
+ nvis += 2;
+ }
+ return viscontigs;
+ }
+ else
+ {
+ return new int[]
+ { 0, width };
+ }
+ }
+
+ /**
+ *
+ * @return position of first visible column of AlignmentView within its
+ * parent's alignment reference frame
+ */
+ public int getAlignmentOrigin()
+ {
+ return firstCol;
+ }
+
+ /**
+ * compute a deletion map for the current view according to the given
+ * gap/match map
+ *
+ * @param gapMap
+ * (as returned from SequenceI.gapMap())
+ * @return int[] {intersection of visible regions with gapMap)
+ */
+ public int[] getVisibleContigMapFor(int[] gapMap)
+ {
+ int[] delMap = null;
+ int[] viscontigs = getVisibleContigs();
+ int spos = 0;
+ int i = 0;
+ if (viscontigs != null)
+ {
+ // viscontigs maps from a subset of the gapMap to the gapMap, so it will
+ // always be equal to or shorter than gapMap
+ delMap = new int[gapMap.length];
+ for (int contig = 0; contig < viscontigs.length; contig += 2)
+ {
+
+ while (spos < gapMap.length && gapMap[spos] < viscontigs[contig])
+ {
+ spos++;
+ }
+ while (spos < gapMap.length
+ && gapMap[spos] <= viscontigs[contig + 1])
+ {
+ delMap[i++] = spos++;
+ }
+ }
+ int tmap[] = new int[i];
+ System.arraycopy(delMap, 0, tmap, 0, i);
+ delMap = tmap;
+ }
+ return delMap;
+ }
+
+ /**
+ * apply the getSeq(gc) method to each sequence cigar, and return the array of
+ * edited sequences, optionally with hidden regions removed.
+ *
+ * @param gc
+ * gap character to use for insertions
+ * @param delete
+ * remove hidden regions from sequences. Note: currently implemented
+ * in a memory inefficient way - space needed is 2*result set for
+ * deletion
+ *
+ * @return SequenceI[]
+ */
+ public SequenceI[] getEditedSequences(char gc, boolean delete)
+ {
+ SeqCigar[] msf = getSequences();
+ SequenceI[] aln = new SequenceI[msf.length];
+ for (int i = 0, j = msf.length; i < j; i++)
+ {
+ aln[i] = msf[i].getSeq(gc);
+ }
+ if (delete)
+ {
+ String[] sqs = getSequenceStrings(gc);
+ for (int i = 0; i < sqs.length; i++)
+ {
+ aln[i].setSequence(sqs[i]);
+ sqs[i] = null;
+ }
+ }
+ return aln;
+ }
+
+ public static void summariseAlignmentView(AlignmentView view,
+ PrintStream os)
+ {
+ os.print("View has " + view.sequences.length + " of which ");
+ if (view.selected == null)
+ {
+ os.print("None");
+ }
+ else
+ {
+ os.print(" " + view.selected.size());
+ }
+ os.println(" are selected.");
+ os.print("View is " + view.getWidth() + " columns wide");
+ int viswid = 0;
+ int[] contigs = view.getContigs();
+ if (contigs != null)
+ {
+ viswid = view.width;
+ for (int i = 0; i < contigs.length; i += 3)
+ {
+ viswid += contigs[i + 2];
+ }
+ os.println("with " + viswid + " visible columns spread over "
+ + contigs.length / 3 + " regions.");
+ }
+ else
+ {
+ viswid = view.width;
+ os.println(".");
+ }
+ if (view.scGroups != null)
+ {
+ os.println("There are " + view.scGroups.size()
+ + " groups defined on the view.");
+ for (int g = 0; g < view.scGroups.size(); g++)
+ {
+ ScGroup sgr = view.scGroups.get(g);
+ os.println("Group " + g + ": Name = " + sgr.sg.getName()
+ + " Contains " + sgr.seqs.size() + " Seqs.");
+ os.println("This group runs from " + sgr.sg.getStartRes() + " to "
+ + sgr.sg.getEndRes());
+ for (int s = 0; s < sgr.seqs.size(); s++)
+ {
+ if (!((SeqCigar) sgr.seqs.elementAt(s)).isMemberOf(sgr))
+ {
+ os.println("** WARNING: sequence "
+ + ((SeqCigar) sgr.seqs.elementAt(s)).toString()
+ + " is not marked as member of group.");
+ }
+ }
+ }
+ AlignmentI visal = view.getVisibleAlignment('-');
+ if (visal != null)
+ {
+ os.println("Vis. alignment is " + visal.getWidth()
+ + " wide and has " + visal.getHeight() + " seqs.");
+ if (visal.getGroups() != null && visal.getGroups().size() > 0)
+ {
+
+ int i = 1;
+ for (SequenceGroup sg : visal.getGroups())
+ {
+ os.println("Group " + (i++) + " begins at column "
+ + sg.getStartRes() + " and ends at " + sg.getEndRes());
+ }
+ }
+ }
+ }
+ }
+
+ public static void testSelectionViews(AlignmentI alignment,
+ ColumnSelection csel, SequenceGroup selection)
+ {
+ System.out.println("Testing standard view creation:\n");
+ AlignmentView view = null;
+ try
+ {
+ System.out
+ .println("View with no hidden columns, no limit to selection, no groups to be collected:");
+ view = new AlignmentView(alignment, csel, selection, false, false,
+ false);
+ summariseAlignmentView(view, System.out);
+
+ } catch (Exception e)
+ {
+ e.printStackTrace();
+ System.err
+ .println("Failed to generate alignment with selection but no groups marked.");
+ }
+ try
+ {
+ System.out
+ .println("View with no hidden columns, no limit to selection, and all groups to be collected:");
+ view = new AlignmentView(alignment, csel, selection, false, false,
+ true);
+ summariseAlignmentView(view, System.out);
+ } catch (Exception e)
+ {
+ e.printStackTrace();
+ System.err
+ .println("Failed to generate alignment with selection marked but no groups marked.");
+ }
+ try
+ {
+ System.out
+ .println("View with no hidden columns, limited to selection and no groups to be collected:");
+ view = new AlignmentView(alignment, csel, selection, false, true,
+ false);
+ summariseAlignmentView(view, System.out);
+ } catch (Exception e)
+ {
+ e.printStackTrace();
+ System.err
+ .println("Failed to generate alignment with selection restricted but no groups marked.");
+ }
+ try
+ {
+ System.out
+ .println("View with no hidden columns, limited to selection, and all groups to be collected:");
+ view = new AlignmentView(alignment, csel, selection, false, true,
+ true);
+ summariseAlignmentView(view, System.out);
+ } catch (Exception e)
+ {
+ e.printStackTrace();
+ System.err
+ .println("Failed to generate alignment with selection restricted and groups marked.");
+ }
+ try
+ {
+ System.out
+ .println("View *with* hidden columns, no limit to selection, no groups to be collected:");
+ view = new AlignmentView(alignment, csel, selection, true, false,
+ false);
+ summariseAlignmentView(view, System.out);
+ } catch (Exception e)
+ {
+ e.printStackTrace();
+ System.err
+ .println("Failed to generate alignment with selection but no groups marked.");
+ }
+ try
+ {
+ System.out
+ .println("View *with* hidden columns, no limit to selection, and all groups to be collected:");
+ view = new AlignmentView(alignment, csel, selection, true, false,
+ true);
+ summariseAlignmentView(view, System.out);
+ } catch (Exception e)
+ {
+ e.printStackTrace();
+ System.err
+ .println("Failed to generate alignment with selection marked but no groups marked.");
+ }
+ try
+ {
+ System.out
+ .println("View *with* hidden columns, limited to selection and no groups to be collected:");
+ view = new AlignmentView(alignment, csel, selection, true, true,
+ false);
+ summariseAlignmentView(view, System.out);
+ } catch (Exception e)
+ {
+ e.printStackTrace();
+ System.err
+ .println("Failed to generate alignment with selection restricted but no groups marked.");
+ }
+ try
+ {
+ System.out
+ .println("View *with* hidden columns, limited to selection, and all groups to be collected:");
+ view = new AlignmentView(alignment, csel, selection, true, true, true);
+ summariseAlignmentView(view, System.out);
+ } catch (Exception e)
+ {
+ e.printStackTrace();
+ System.err
+ .println("Failed to generate alignment with selection restricted and groups marked.");
+ }
+
+ }