+
+ }
+ }
+
+ @Override
+ public void validateAnnotation(AlignmentAnnotation alignmentAnnotation)
+ {
+ alignmentAnnotation.validateRangeAndDisplay();
+ if (isNucleotide() && alignmentAnnotation.isValidStruc())
+ {
+ hasRNAStructure = true;
+ }
+ }
+
+ private SequenceI seqrep = null;
+
+ /**
+ *
+ * @return the representative sequence for this group
+ */
+ @Override
+ public SequenceI getSeqrep()
+ {
+ return seqrep;
+ }
+
+ /**
+ * set the representative sequence for this group. Note - this affects the
+ * interpretation of the Hidereps attribute.
+ *
+ * @param seqrep
+ * the seqrep to set (null means no sequence representative)
+ */
+ @Override
+ public void setSeqrep(SequenceI seqrep)
+ {
+ this.seqrep = seqrep;
+ }
+
+ /**
+ *
+ * @return true if group has a sequence representative
+ */
+ @Override
+ public boolean hasSeqrep()
+ {
+ return seqrep != null;
+ }
+
+ @Override
+ public int getEndRes()
+ {
+ return getWidth() - 1;
+ }
+
+ @Override
+ public int getStartRes()
+ {
+ return 0;
+ }
+
+ /*
+ * In the case of AlignmentI - returns the dataset for the alignment, if set
+ * (non-Javadoc)
+ *
+ * @see jalview.datamodel.AnnotatedCollectionI#getContext()
+ */
+ @Override
+ public AnnotatedCollectionI getContext()
+ {
+ return dataset;
+ }
+
+ /**
+ * Align this alignment like the given (mapped) one.
+ */
+ @Override
+ public int alignAs(AlignmentI al)
+ {
+ /*
+ * Currently retains unmapped gaps (in introns), regaps mapped regions
+ * (exons)
+ */
+ return alignAs(al, false, true);
+ }
+
+ /**
+ * Align this alignment 'the same as' the given one. Mapped sequences only are
+ * realigned. If both of the same type (nucleotide/protein) then align both
+ * identically. If this is nucleotide and the other is protein, make 3 gaps
+ * for each gap in the protein sequences. If this is protein and the other is
+ * nucleotide, insert a gap for each 3 gaps (or part thereof) between
+ * nucleotide bases. If this is protein and the other is nucleotide, gaps
+ * protein to match the relative ordering of codons in the nucleotide.
+ *
+ * Parameters control whether gaps in exon (mapped) and intron (unmapped)
+ * regions are preserved. Gaps that connect introns to exons are treated
+ * conservatively, i.e. only preserved if both intron and exon gaps are
+ * preserved. TODO: check caveats below where the implementation fails
+ *
+ * @param al
+ * - must have same dataset, and sequences in al must have equivalent
+ * dataset sequence and start/end bounds under given mapping
+ * @param preserveMappedGaps
+ * if true, gaps within and between mapped codons are preserved
+ * @param preserveUnmappedGaps
+ * if true, gaps within and between unmapped codons are preserved
+ */
+ // @Override
+ public int alignAs(AlignmentI al, boolean preserveMappedGaps,
+ boolean preserveUnmappedGaps)
+ {
+ // TODO should this method signature be the one in the interface?
+ // JBPComment - yes - neither flag is used, so should be deleted.
+ boolean thisIsNucleotide = this.isNucleotide();
+ boolean thatIsProtein = !al.isNucleotide();
+ if (!thatIsProtein && !thisIsNucleotide)
+ {
+ return AlignmentUtils.alignProteinAsDna(this, al);
+ }
+ else if (thatIsProtein && thisIsNucleotide)
+ {
+ return AlignmentUtils.alignCdsAsProtein(this, al);
+ }
+ return AlignmentUtils.alignAs(this, al);
+ }
+
+ /**
+ * Returns the alignment in Fasta format. Behaviour of this method is not
+ * guaranteed between versions.
+ */
+ @Override
+ public String toString()
+ {
+ return new FastaFile().print(getSequencesArray(), true);
+ }
+
+ /**
+ * Returns the set of distinct sequence names. No ordering is guaranteed.
+ */
+ @Override
+ public Set<String> getSequenceNames()
+ {
+ Set<String> names = new HashSet<String>();
+ for (SequenceI seq : getSequences())
+ {
+ names.add(seq.getName());
+ }
+ return names;
+ }
+
+ @Override
+ public boolean hasValidSequence()
+ {
+ boolean hasValidSeq = false;
+ for (SequenceI seq : getSequences())
+ {
+ if ((seq.getEnd() - seq.getStart()) > 0)
+ {
+ hasValidSeq = true;
+ break;
+ }
+ }
+ return hasValidSeq;
+ }
+
+ /**
+ * Update any mappings to 'virtual' sequences to compatible real ones, if
+ * present in the added sequences. Returns a count of mappings updated.
+ *
+ * @param seqs
+ * @return
+ */
+ @Override
+ public int realiseMappings(List<SequenceI> seqs)
+ {
+ int count = 0;
+ for (SequenceI seq : seqs)
+ {
+ for (AlignedCodonFrame mapping : getCodonFrames())
+ {
+ count += mapping.realiseWith(seq);
+ }
+ }
+ return count;
+ }
+
+ /**
+ * Returns the first AlignedCodonFrame that has a mapping between the given
+ * dataset sequences
+ *
+ * @param mapFrom
+ * @param mapTo
+ * @return
+ */
+ @Override
+ public AlignedCodonFrame getMapping(SequenceI mapFrom, SequenceI mapTo)
+ {
+ for (AlignedCodonFrame acf : getCodonFrames())
+ {
+ if (acf.getAaForDnaSeq(mapFrom) == mapTo)
+ {
+ return acf;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public int[] getVisibleStartAndEndIndex(List<int[]> hiddenCols)
+ {
+ int[] alignmentStartEnd = new int[] { 0, getWidth() - 1 };
+ int startPos = alignmentStartEnd[0];
+ int endPos = alignmentStartEnd[1];
+
+ int[] lowestRange = new int[] { -1, -1 };
+ int[] higestRange = new int[] { -1, -1 };
+
+ for (int[] hiddenCol : hiddenCols)
+ {
+ lowestRange = (hiddenCol[0] <= startPos) ? hiddenCol : lowestRange;
+ higestRange = (hiddenCol[1] >= endPos) ? hiddenCol : higestRange;
+ }
+
+ if (lowestRange[0] == -1 && lowestRange[1] == -1)
+ {
+ startPos = alignmentStartEnd[0];
+ }
+ else
+ {
+ startPos = lowestRange[1] + 1;
+ }
+
+ if (higestRange[0] == -1 && higestRange[1] == -1)
+ {
+ endPos = alignmentStartEnd[1];
+ }
+ else
+ {
+ endPos = higestRange[0] - 1;