+
+ /*
+ * Finally add any unmapped peptide start residues (e.g. for incomplete
+ * codons) as if at the codon position before the second residue
+ */
+ int mappedSequenceCount = protein.getHeight() - unmappedProtein.size();
+ addUnmappedPeptideStarts(alignedCodons, mappedSequenceCount);
+
+ return alignedCodons;
+ }
+
+ /**
+ * Scans for any protein mapped from position 2 (meaning unmapped start
+ * position e.g. an incomplete codon), and synthesizes a 'codon' for it at the
+ * preceding position in the alignment
+ *
+ * @param alignedCodons
+ * the codon-to-peptide map
+ * @param mappedSequenceCount
+ * the number of distinct sequences in the map
+ */
+ protected static void addUnmappedPeptideStarts(
+ Map<AlignedCodon, Map<SequenceI, AlignedCodon>> alignedCodons,
+ int mappedSequenceCount)
+ {
+ // TODO there must be an easier way! root problem is that our mapping data
+ // model does not include phase so can't map part of a codon to a peptide
+ List<SequenceI> sequencesChecked = new ArrayList<SequenceI>();
+ AlignedCodon lastCodon = null;
+ Map<SequenceI, AlignedCodon> toAdd = new HashMap<SequenceI, AlignedCodon>();
+
+ for (Entry<AlignedCodon, Map<SequenceI, AlignedCodon>> entry : alignedCodons
+ .entrySet())
+ {
+ for (Entry<SequenceI, AlignedCodon> sequenceCodon : entry.getValue()
+ .entrySet())
+ {
+ SequenceI seq = sequenceCodon.getKey();
+ if (sequencesChecked.contains(seq))
+ {
+ continue;
+ }
+ sequencesChecked.add(seq);
+ AlignedCodon codon = sequenceCodon.getValue();
+ if (codon.peptideCol > 1)
+ {
+ System.err
+ .println("Problem mapping protein with >1 unmapped start positions: "
+ + seq.getName());
+ }
+ else if (codon.peptideCol == 1)
+ {
+ /*
+ * first position (peptideCol == 0) was unmapped - add it
+ */
+ if (lastCodon != null)
+ {
+ AlignedCodon firstPeptide = new AlignedCodon(lastCodon.pos1,
+ lastCodon.pos2, lastCodon.pos3, String.valueOf(seq
+ .getCharAt(0)), 0);
+ toAdd.put(seq, firstPeptide);
+ }
+ else
+ {
+ /*
+ * unmapped residue at start of alignment (no prior column) -
+ * 'insert' at nominal codon [0, 0, 0]
+ */
+ AlignedCodon firstPeptide = new AlignedCodon(0, 0, 0,
+ String.valueOf(seq.getCharAt(0)), 0);
+ toAdd.put(seq, firstPeptide);
+ }
+ }
+ if (sequencesChecked.size() == mappedSequenceCount)
+ {
+ // no need to check past first mapped position in all sequences
+ break;
+ }
+ }
+ lastCodon = entry.getKey();
+ }
+
+ /*
+ * add any new codons safely after iterating over the map
+ */
+ for (Entry<SequenceI, AlignedCodon> startCodon : toAdd.entrySet())
+ {
+ addCodonToMap(alignedCodons, startCodon.getValue(),
+ startCodon.getKey());
+ }