X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fanalysis%2FAlignmentUtils.java;h=1b8f84f6a849c878bfc0228d827ede402717740b;hb=3d0101179759ef157b088ea135423cd909512d9f;hp=bed685ac9eaee2611b5b071f78196019fe76ca12;hpb=46c321b0c0f02adf71fe433c86ab6609e0872871;p=jalview.git diff --git a/src/jalview/analysis/AlignmentUtils.java b/src/jalview/analysis/AlignmentUtils.java index bed685a..1b8f84f 100644 --- a/src/jalview/analysis/AlignmentUtils.java +++ b/src/jalview/analysis/AlignmentUtils.java @@ -42,6 +42,7 @@ import jalview.util.Comparison; import jalview.util.DBRefUtils; import jalview.util.MapList; import jalview.util.MappingUtils; +import jalview.util.RangeComparator; import jalview.util.StringUtils; import java.io.UnsupportedEncodingException; @@ -60,6 +61,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.NoSuchElementException; import java.util.Set; +import java.util.SortedMap; import java.util.TreeMap; /** @@ -72,22 +74,26 @@ import java.util.TreeMap; public class AlignmentUtils { + private static final int CODON_LENGTH = 3; + private static final String SEQUENCE_VARIANT = "sequence_variant:"; + private static final String ID = "ID"; /** * A data model to hold the 'normal' base value at a position, and an optional * sequence variant feature */ - static class DnaVariant + static final class DnaVariant { - String base; + final String base; SequenceFeature variant; DnaVariant(String nuc) { base = nuc; + variant = null; } DnaVariant(String nuc, SequenceFeature var) @@ -95,6 +101,11 @@ public class AlignmentUtils base = nuc; variant = var; } + + public String getSource() + { + return variant == null ? null : variant.getFeatureGroup(); + } } /** @@ -160,10 +171,12 @@ public class AlignmentUtils } } // TODO use Character.toLowerCase to avoid creating String objects? - char[] upstream = new String(ds.getSequence(s.getStart() - 1 - - ustream_ds, s.getStart() - 1)).toLowerCase().toCharArray(); - char[] downstream = new String(ds.getSequence(s_end - 1, s_end - + dstream_ds)).toLowerCase().toCharArray(); + char[] upstream = new String(ds + .getSequence(s.getStart() - 1 - ustream_ds, s.getStart() - 1)) + .toLowerCase().toCharArray(); + char[] downstream = new String( + ds.getSequence(s_end - 1, s_end + dstream_ds)).toLowerCase() + .toCharArray(); char[] coreseq = s.getSequence(); char[] nseq = new char[offset + upstream.length + downstream.length + coreseq.length]; @@ -178,8 +191,8 @@ public class AlignmentUtils System.arraycopy(upstream, 0, nseq, p, upstream.length); System.arraycopy(coreseq, 0, nseq, p + upstream.length, coreseq.length); - System.arraycopy(downstream, 0, nseq, p + coreseq.length - + upstream.length, downstream.length); + System.arraycopy(downstream, 0, nseq, + p + coreseq.length + upstream.length, downstream.length); s.setSequence(new String(nseq)); s.setStart(s.getStart() - ustream_ds); s.setEnd(s_end + downstream.length); @@ -306,9 +319,9 @@ public class AlignmentUtils * @return */ protected static boolean mapProteinToCdna( - final AlignmentI proteinAlignment, - final AlignmentI cdnaAlignment, Set mappedDna, - Set mappedProtein, boolean xrefsOnly) + final AlignmentI proteinAlignment, final AlignmentI cdnaAlignment, + Set mappedDna, Set mappedProtein, + boolean xrefsOnly) { boolean mappingExistsOrAdded = false; List thisSeqs = proteinAlignment.getSequences(); @@ -337,9 +350,8 @@ public class AlignmentUtils * Don't map non-xrefd sequences more than once each. This heuristic * allows us to pair up similar sequences in ordered alignments. */ - if (!xrefsOnly - && (mappedProtein.contains(aaSeq) || mappedDna - .contains(cdnaSeq))) + if (!xrefsOnly && (mappedProtein.contains(aaSeq) + || mappedDna.contains(cdnaSeq))) { continue; } @@ -392,7 +404,8 @@ public class AlignmentUtils /** * Builds a mapping (if possible) of a cDNA to a protein sequence. *
    - *
  • first checks if the cdna translates exactly to the protein sequence
  • + *
  • first checks if the cdna translates exactly to the protein + * sequence
  • *
  • else checks for translation after removing a STOP codon
  • *
  • else checks for translation after removing a START codon
  • *
  • if that fails, inspect CDS features on the cDNA sequence
  • @@ -414,8 +427,9 @@ public class AlignmentUtils * String objects. */ final SequenceI proteinDataset = proteinSeq.getDatasetSequence(); - char[] aaSeqChars = proteinDataset != null ? proteinDataset - .getSequence() : proteinSeq.getSequence(); + char[] aaSeqChars = proteinDataset != null + ? proteinDataset.getSequence() + : proteinSeq.getSequence(); final SequenceI cdnaDataset = cdnaSeq.getDatasetSequence(); char[] cdnaSeqChars = cdnaDataset != null ? cdnaDataset.getSequence() : cdnaSeq.getSequence(); @@ -427,7 +441,7 @@ public class AlignmentUtils /* * cdnaStart/End, proteinStartEnd are base 1 (for dataset sequence mapping) */ - final int mappedLength = 3 * aaSeqChars.length; + final int mappedLength = CODON_LENGTH * aaSeqChars.length; int cdnaLength = cdnaSeqChars.length; int cdnaStart = cdnaSeq.getStart(); int cdnaEnd = cdnaSeq.getEnd(); @@ -439,14 +453,14 @@ public class AlignmentUtils */ if (cdnaLength != mappedLength && cdnaLength > 2) { - String lastCodon = String.valueOf(cdnaSeqChars, cdnaLength - 3, 3) - .toUpperCase(); + String lastCodon = String.valueOf(cdnaSeqChars, + cdnaLength - CODON_LENGTH, CODON_LENGTH).toUpperCase(); for (String stop : ResidueProperties.STOP) { if (lastCodon.equals(stop)) { - cdnaEnd -= 3; - cdnaLength -= 3; + cdnaEnd -= CODON_LENGTH; + cdnaLength -= CODON_LENGTH; break; } } @@ -456,14 +470,13 @@ public class AlignmentUtils * If lengths still don't match, try ignoring start codon. */ int startOffset = 0; - if (cdnaLength != mappedLength - && cdnaLength > 2 - && String.valueOf(cdnaSeqChars, 0, 3).toUpperCase() + if (cdnaLength != mappedLength && cdnaLength > 2 + && String.valueOf(cdnaSeqChars, 0, CODON_LENGTH).toUpperCase() .equals(ResidueProperties.START)) { - startOffset += 3; - cdnaStart += 3; - cdnaLength -= 3; + startOffset += CODON_LENGTH; + cdnaStart += CODON_LENGTH; + cdnaLength -= CODON_LENGTH; } if (translatesAs(cdnaSeqChars, startOffset, aaSeqChars)) @@ -471,8 +484,9 @@ public class AlignmentUtils /* * protein is translation of dna (+/- start/stop codons) */ - MapList map = new MapList(new int[] { cdnaStart, cdnaEnd }, new int[] - { proteinStart, proteinEnd }, 3, 1); + MapList map = new MapList(new int[] { cdnaStart, cdnaEnd }, + new int[] + { proteinStart, proteinEnd }, CODON_LENGTH, 1); return map; } @@ -503,9 +517,9 @@ public class AlignmentUtils int aaPos = 0; int dnaPos = cdnaStart; for (; dnaPos < cdnaSeqChars.length - 2 - && aaPos < aaSeqChars.length; dnaPos += 3, aaPos++) + && aaPos < aaSeqChars.length; dnaPos += CODON_LENGTH, aaPos++) { - String codon = String.valueOf(cdnaSeqChars, dnaPos, 3); + String codon = String.valueOf(cdnaSeqChars, dnaPos, CODON_LENGTH); final String translated = ResidueProperties.codonTranslate(codon); /* @@ -541,9 +555,9 @@ public class AlignmentUtils { return true; } - if (dnaPos == cdnaSeqChars.length - 3) + if (dnaPos == cdnaSeqChars.length - CODON_LENGTH) { - String codon = String.valueOf(cdnaSeqChars, dnaPos, 3); + String codon = String.valueOf(cdnaSeqChars, dnaPos, CODON_LENGTH); if ("STOP".equals(ResidueProperties.codonTranslate(codon))) { return true; @@ -622,10 +636,9 @@ public class AlignmentUtils * @param preserveUnmappedGaps * @param preserveMappedGaps */ - public static void alignSequenceAs(SequenceI alignTo, - SequenceI alignFrom, AlignedCodonFrame mapping, String myGap, - char sourceGap, boolean preserveMappedGaps, - boolean preserveUnmappedGaps) + public static void alignSequenceAs(SequenceI alignTo, SequenceI alignFrom, + AlignedCodonFrame mapping, String myGap, char sourceGap, + boolean preserveMappedGaps, boolean preserveUnmappedGaps) { // TODO generalise to work for Protein-Protein, dna-dna, dna-protein @@ -820,8 +833,9 @@ public class AlignmentUtils } else { - gapsToAdd = Math.min(intronLength + trailingGapLength - - sourceGapMappedLength, trailingGapLength); + gapsToAdd = Math.min( + intronLength + trailingGapLength - sourceGapMappedLength, + trailingGapLength); } } } @@ -894,7 +908,8 @@ public class AlignmentUtils } width = Math.max(dnaSeq.getLength(), width); } - int oldwidth, diff; + int oldwidth; + int diff; for (SequenceI dnaSeq : dna.getSequences()) { oldwidth = dnaSeq.getLength(); @@ -919,7 +934,8 @@ public class AlignmentUtils * @return */ static boolean alignCdsSequenceAsProtein(SequenceI cdsSeq, - AlignmentI protein, List mappings, char gapChar) + AlignmentI protein, List mappings, + char gapChar) { SequenceI cdsDss = cdsSeq.getDatasetSequence(); if (cdsDss == null) @@ -928,15 +944,15 @@ public class AlignmentUtils .println("alignCdsSequenceAsProtein needs aligned sequence!"); return false; } - + List dnaMappings = MappingUtils .findMappingsForSequence(cdsSeq, mappings); for (AlignedCodonFrame mapping : dnaMappings) { SequenceI peptide = mapping.findAlignedSequence(cdsSeq, protein); - int peptideLength = peptide.getLength(); if (peptide != null) { + int peptideLength = peptide.getLength(); Mapping map = mapping.getMappingBetween(cdsSeq, peptide); if (map != null) { @@ -946,26 +962,26 @@ public class AlignmentUtils mapList = mapList.getInverse(); } int cdsLength = cdsDss.getLength(); - int mappedFromLength = MappingUtils.getLength(mapList - .getFromRanges()); + int mappedFromLength = MappingUtils + .getLength(mapList.getFromRanges()); int mappedToLength = MappingUtils .getLength(mapList.getToRanges()); - boolean addStopCodon = (cdsLength == mappedFromLength * 3 + 3) - || (peptide.getDatasetSequence().getLength() == mappedFromLength - 1); + boolean addStopCodon = (cdsLength == mappedFromLength + * CODON_LENGTH + CODON_LENGTH) + || (peptide.getDatasetSequence() + .getLength() == mappedFromLength - 1); if (cdsLength != mappedToLength && !addStopCodon) { - System.err - .println(String - .format("Can't align cds as protein (length mismatch %d/%d): %s", - cdsLength, mappedToLength, - cdsSeq.getName())); + System.err.println(String.format( + "Can't align cds as protein (length mismatch %d/%d): %s", + cdsLength, mappedToLength, cdsSeq.getName())); } /* * pre-fill the aligned cds sequence with gaps */ - char[] alignedCds = new char[peptideLength * 3 - + (addStopCodon ? 3 : 0)]; + char[] alignedCds = new char[peptideLength * CODON_LENGTH + + (addStopCodon ? CODON_LENGTH : 0)]; Arrays.fill(alignedCds, gapChar); /* @@ -982,7 +998,7 @@ public class AlignmentUtils { if (Comparison.isGap(residue)) { - cdsCol += 3; + cdsCol += CODON_LENGTH; } else { @@ -991,7 +1007,7 @@ public class AlignmentUtils if (codon == null) { // e.g. incomplete start codon, X in peptide - cdsCol += 3; + cdsCol += CODON_LENGTH; } else { @@ -1009,7 +1025,7 @@ public class AlignmentUtils * append stop codon if not mapped from protein, * closing it up to the end of the mapped sequence */ - if (copiedBases == nucleotides.length - 3) + if (copiedBases == nucleotides.length - CODON_LENGTH) { for (int i = alignedCds.length - 1; i >= 0; i--) { @@ -1019,7 +1035,8 @@ public class AlignmentUtils break; } } - for (int i = nucleotides.length - 3; i < nucleotides.length; i++) + for (int i = nucleotides.length + - CODON_LENGTH; i < nucleotides.length; i++) { alignedCds[cdsCol++] = nucleotides[i]; } @@ -1075,8 +1092,8 @@ public class AlignmentUtils if (prot != null) { Mapping seqMap = mapping.getMappingForSequence(dnaSeq); - addCodonPositions(dnaSeq, prot, protein.getGapCharacter(), - seqMap, alignedCodons); + addCodonPositions(dnaSeq, prot, protein.getGapCharacter(), seqMap, + alignedCodons); unmappedProtein.remove(prot); } } @@ -1089,7 +1106,7 @@ public class AlignmentUtils // TODO resolve JAL-2022 so this fudge can be removed int mappedSequenceCount = protein.getHeight() - unmappedProtein.size(); addUnmappedPeptideStarts(alignedCodons, mappedSequenceCount); - + return alignedCodons; } @@ -1129,8 +1146,8 @@ public class AlignmentUtils AlignedCodon codon = sequenceCodon.getValue(); if (codon.peptideCol > 1) { - System.err - .println("Problem mapping protein with >1 unmapped start positions: " + System.err.println( + "Problem mapping protein with >1 unmapped start positions: " + seq.getName()); } else if (codon.peptideCol == 1) @@ -1141,8 +1158,8 @@ public class AlignmentUtils if (lastCodon != null) { AlignedCodon firstPeptide = new AlignedCodon(lastCodon.pos1, - lastCodon.pos2, lastCodon.pos3, String.valueOf(seq - .getCharAt(0)), 0); + lastCodon.pos2, lastCodon.pos3, + String.valueOf(seq.getCharAt(0)), 0); toAdd.put(seq, firstPeptide); } else @@ -1291,7 +1308,8 @@ public class AlignmentUtils *
      *
    • One alignment must be nucleotide, and the other protein
    • *
    • At least one pair of sequences must be already mapped, or mappable
    • - *
    • Mappable means the nucleotide translation matches the protein sequence
    • + *
    • Mappable means the nucleotide translation matches the protein + * sequence
    • *
    • The translation may ignore start and stop codons if present in the * nucleotide
    • *
    @@ -1347,9 +1365,10 @@ public class AlignmentUtils return false; } - SequenceI dnaDs = dnaSeq.getDatasetSequence() == null ? dnaSeq : dnaSeq - .getDatasetSequence(); - SequenceI proteinDs = proteinSeq.getDatasetSequence() == null ? proteinSeq + SequenceI dnaDs = dnaSeq.getDatasetSequence() == null ? dnaSeq + : dnaSeq.getDatasetSequence(); + SequenceI proteinDs = proteinSeq.getDatasetSequence() == null + ? proteinSeq : proteinSeq.getDatasetSequence(); for (AlignedCodonFrame mapping : mappings) @@ -1386,8 +1405,7 @@ public class AlignmentUtils * the alignment to check for presence of annotations */ public static void findAddableReferenceAnnotations( - List sequenceScope, - Map labelForCalcId, + List sequenceScope, Map labelForCalcId, final Map> candidates, AlignmentI al) { @@ -1491,8 +1509,8 @@ public class AlignmentUtils /** * Set visibility of alignment annotations of specified types (labels), for - * specified sequences. This supports controls like - * "Show all secondary structure", "Hide all Temp factor", etc. + * specified sequences. This supports controls like "Show all secondary + * structure", "Hide all Temp factor", etc. * * @al the alignment to scan for annotations * @param types @@ -1516,9 +1534,8 @@ public class AlignmentUtils { if (anyType || types.contains(aa.label)) { - if ((aa.sequenceRef != null) - && (forSequences == null || forSequences - .contains(aa.sequenceRef))) + if ((aa.sequenceRef != null) && (forSequences == null + || forSequences.contains(aa.sequenceRef))) { aa.visible = doShow; } @@ -1606,8 +1623,8 @@ public class AlignmentUtils productSeqs = new HashSet(); for (SequenceI seq : products) { - productSeqs.add(seq.getDatasetSequence() == null ? seq : seq - .getDatasetSequence()); + productSeqs.add(seq.getDatasetSequence() == null ? seq + : seq.getDatasetSequence()); } } @@ -1680,25 +1697,32 @@ public class AlignmentUtils * didn't find mapped CDS sequence - construct it and add * its dataset sequence to the dataset */ - cdsSeq = makeCdsSequence(dnaSeq.getDatasetSequence(), aMapping); + cdsSeq = makeCdsSequence(dnaSeq.getDatasetSequence(), aMapping, + dataset).deriveSequence(); // cdsSeq has a name constructed as CDS| // will be either the accession for the coding sequence, // marked in the /via/ dbref to the protein product accession // or it will be the original nucleotide accession. - SequenceI cdsSeqDss = cdsSeq.createDatasetSequence(); + SequenceI cdsSeqDss = cdsSeq.getDatasetSequence(); + cdsSeqs.add(cdsSeq); + if (!dataset.getSequences().contains(cdsSeqDss)) { + // check if this sequence is a newly created one + // so needs adding to the dataset dataset.addSequence(cdsSeqDss); } /* * add a mapping from CDS to the (unchanged) mapped to range */ - List cdsRange = Collections.singletonList(new int[] { 1, - cdsSeq.getLength() }); - MapList cdsToProteinMap = new MapList(cdsRange, mapList.getToRanges(), - mapList.getFromRatio(), mapList.getToRatio()); + List cdsRange = Collections + .singletonList(new int[] + { 1, cdsSeq.getLength() }); + MapList cdsToProteinMap = new MapList(cdsRange, + mapList.getToRanges(), mapList.getFromRatio(), + mapList.getToRatio()); AlignedCodonFrame cdsToProteinMapping = new AlignedCodonFrame(); cdsToProteinMapping.addMap(cdsSeqDss, proteinProduct, cdsToProteinMap); @@ -1718,8 +1742,7 @@ public class AlignmentUtils */ AlignedCodonFrame dnaToCdsMapping = new AlignedCodonFrame(); MapList dnaToCdsMap = new MapList(mapList.getFromRanges(), - cdsRange, 1, - 1); + cdsRange, 1, 1); dnaToCdsMapping.addMap(dnaSeq.getDatasetSequence(), cdsSeqDss, dnaToCdsMap); if (!mappings.contains(dnaToCdsMapping)) @@ -1734,40 +1757,52 @@ public class AlignmentUtils * same source and accession, so need a different accession for * the CDS from the dna sequence */ + // specific use case: // Genomic contig ENSCHR:1, contains coding regions for ENSG01, // ENSG02, ENSG03, with transcripts and products similarly named. // cannot add distinct dbrefs mapping location on ENSCHR:1 to ENSG01 + // JBPNote: ?? can't actually create an example that demonstrates we // need to // synthesize an xref. - // TODO: merge conflicts from JAL-2154 branch and use PrimaryDBRefs() - // for (DBRefEntry primRef:dnaDss.getPrimaryDBRefs()) - // { - // creates a complementary cross-reference to the source sequence's - // primary reference. - - // // problem here is that the cross-reference is synthesized - - // cdsSeq.getName() may be like 'CDS|dnaaccession' or 'CDS|emblcdsacc' - // // assuming cds version same as dna ?!? - // DBRefEntry proteinToCdsRef = new DBRefEntry(dnaRef.getSource(), - // dnaRef.getVersion(), cdsSeq.getName()); - // proteinToCdsRef.setMap(new Mapping(cdsSeqDss, cdsToProteinMap - // .getInverse())); - // proteinProduct.addDBRef(proteinToCdsRef); - // } + + for (DBRefEntry primRef : dnaDss.getPrimaryDBRefs()) + { + // creates a complementary cross-reference to the source sequence's + // primary reference. + + DBRefEntry cdsCrossRef = new DBRefEntry(primRef.getSource(), + primRef.getSource() + ":" + primRef.getVersion(), + primRef.getAccessionId()); + cdsCrossRef + .setMap(new Mapping(dnaDss, new MapList(dnaToCdsMap))); + cdsSeqDss.addDBRef(cdsCrossRef); + + // problem here is that the cross-reference is synthesized - + // cdsSeq.getName() may be like 'CDS|dnaaccession' or + // 'CDS|emblcdsacc' + // assuming cds version same as dna ?!? + + DBRefEntry proteinToCdsRef = new DBRefEntry(primRef.getSource(), + primRef.getVersion(), cdsSeq.getName()); + // + proteinToCdsRef.setMap( + new Mapping(cdsSeqDss, cdsToProteinMap.getInverse())); + proteinProduct.addDBRef(proteinToCdsRef); + } /* * transfer any features on dna that overlap the CDS */ - transferFeatures(dnaSeq, cdsSeq, cdsToProteinMap, null, + transferFeatures(dnaSeq, cdsSeq, dnaToCdsMap, null, SequenceOntologyI.CDS); } } } - AlignmentI cds = new Alignment(cdsSeqs.toArray(new SequenceI[cdsSeqs - .size()])); + AlignmentI cds = new Alignment( + cdsSeqs.toArray(new SequenceI[cdsSeqs.size()])); cds.setDataset(dataset); return cds; @@ -1804,10 +1839,11 @@ public class AlignmentUtils * is this mapping from the whole dna sequence (i.e. CDS)? * allowing for possible stop codon on dna but not peptide */ - int mappedFromLength = MappingUtils.getLength(aMapping.getMap() - .getFromRanges()); + int mappedFromLength = MappingUtils + .getLength(aMapping.getMap().getFromRanges()); int dnaLength = seqDss.getLength(); - if (mappedFromLength == dnaLength || mappedFromLength == dnaLength - 3) + if (mappedFromLength == dnaLength + || mappedFromLength == dnaLength - CODON_LENGTH) { return seqDss; } @@ -1823,12 +1859,13 @@ public class AlignmentUtils for (SequenceToSequenceMapping map : acf.getMappings()) { Mapping mapping = map.getMapping(); - if (mapping != aMapping && mapping.getMap().getFromRatio() == 3 + if (mapping != aMapping + && mapping.getMap().getFromRatio() == CODON_LENGTH && proteinProduct == mapping.getTo() && seqDss != map.getFromSeq()) { - mappedFromLength = MappingUtils.getLength(mapping.getMap() - .getFromRanges()); + mappedFromLength = MappingUtils + .getLength(mapping.getMap().getFromRanges()); if (mappedFromLength == map.getFromSeq().getLength()) { /* @@ -1857,9 +1894,14 @@ public class AlignmentUtils * * @param seq * @param mapping + * @param dataset + * - existing dataset. We check for sequences that look like the CDS + * we are about to construct, if one exists already, then we will + * just return that one. * @return CDS sequence (as a dataset sequence) */ - static SequenceI makeCdsSequence(SequenceI seq, Mapping mapping) + static SequenceI makeCdsSequence(SequenceI seq, Mapping mapping, + AlignmentI dataset) { char[] seqChars = seq.getSequence(); List fromRanges = mapping.getMap().getFromRanges(); @@ -1886,7 +1928,7 @@ public class AlignmentUtils } } } - + /* * assign 'from id' held in the mapping if set (e.g. EMBL protein_id), * else generate a sequence name @@ -1894,6 +1936,40 @@ public class AlignmentUtils String mapFromId = mapping.getMappedFromId(); String seqId = "CDS|" + (mapFromId != null ? mapFromId : seq.getName()); SequenceI newSeq = new Sequence(seqId, newSeqChars, 1, newPos); + if (dataset != null) + { + SequenceI[] matches = dataset.findSequenceMatch(newSeq.getName()); + if (matches != null) + { + boolean matched = false; + for (SequenceI mtch : matches) + { + if (mtch.getStart() != newSeq.getStart()) + { + continue; + } + if (mtch.getEnd() != newSeq.getEnd()) + { + continue; + } + if (!Arrays.equals(mtch.getSequence(), newSeq.getSequence())) + { + continue; + } + if (!matched) + { + matched = true; + newSeq = mtch; + } + else + { + System.err.println( + "JAL-2154 regression: warning - found (and ignnored a duplicate CDS sequence):" + + mtch.toString()); + } + } + } + } // newSeq.setDescription(mapFromId); return newSeq; @@ -1940,16 +2016,17 @@ public class AlignmentUtils for (DBRefEntry cdsref : direct) { // clone maplist and mapping - MapList cdsposmap = new MapList(Arrays.asList(new int[][] { new int[] - { cdsSeq.getStart(), cdsSeq.getEnd() } }), cdsref.getMap().getMap() - .getToRanges(), 3, 1); - Mapping cdsmap = new Mapping(cdsref.getMap().getTo(), cdsref.getMap() - .getMap()); + MapList cdsposmap = new MapList( + Arrays.asList(new int[][] + { new int[] { cdsSeq.getStart(), cdsSeq.getEnd() } }), + cdsref.getMap().getMap().getToRanges(), 3, 1); + Mapping cdsmap = new Mapping(cdsref.getMap().getTo(), + cdsref.getMap().getMap()); // create dbref DBRefEntry newref = new DBRefEntry(cdsref.getSource(), - cdsref.getVersion(), cdsref.getAccessionId(), new Mapping( - cdsmap.getTo(), cdsposmap)); + cdsref.getVersion(), cdsref.getAccessionId(), + new Mapping(cdsmap.getTo(), cdsposmap)); // and see if we can map to the protein product for this mapping. // onSource is the filtered set of accessions on protein that we are @@ -2106,7 +2183,7 @@ public class AlignmentUtils /* * dna length should map to protein (or protein plus stop codon) */ - int codesForResidues = mappedDnaLength / 3; + int codesForResidues = mappedDnaLength / CODON_LENGTH; if (codesForResidues == (proteinLength + 1)) { // assuming extra codon is for STOP and not in peptide @@ -2115,7 +2192,7 @@ public class AlignmentUtils if (codesForResidues == proteinLength) { proteinRange.add(new int[] { proteinStart, proteinEnd }); - return new MapList(ranges, proteinRange, 3, 1); + return new MapList(ranges, proteinRange, CODON_LENGTH, 1); } return null; } @@ -2169,8 +2246,8 @@ public class AlignmentUtils if (begin > end) { // shouldn't happen! - System.err - .println("Error: start phase extends beyond start CDS in " + System.err.println( + "Error: start phase extends beyond start CDS in " + dnaSeq.getName()); } } @@ -2195,14 +2272,7 @@ public class AlignmentUtils * ranges are assembled in order. Other cases should not use this method, * but instead construct an explicit mapping for CDS (e.g. EMBL parsing). */ - Collections.sort(result, new Comparator() - { - @Override - public int compare(int[] o1, int[] o2) - { - return Integer.compare(o1[0], o2[0]); - } - }); + Collections.sort(result, new RangeComparator(true)); return result; } @@ -2391,8 +2461,8 @@ public class AlignmentUtils * are currently ignored here */ String trans = codon.contains("-") ? "-" - : (codon.length() > 3 ? null : ResidueProperties - .codonTranslate(codon)); + : (codon.length() > CODON_LENGTH ? null + : ResidueProperties.codonTranslate(codon)); if (trans != null && !trans.equals(residue)) { String residue3Char = StringUtils @@ -2403,7 +2473,7 @@ public class AlignmentUtils // set score to 0f so 'graduated colour' option is offered! JAL-2060 SequenceFeature sf = new SequenceFeature( SequenceOntologyI.SEQUENCE_VARIANT, desc, peptidePos, - peptidePos, 0f, "Jalview"); + peptidePos, 0f, var.getSource()); StringBuilder attributes = new StringBuilder(32); String id = (String) var.variant.getValue(ID); if (id != null) @@ -2414,12 +2484,12 @@ public class AlignmentUtils } sf.setValue(ID, id); attributes.append(ID).append("=").append(id); - // TODO handle other species variants + // TODO handle other species variants JAL-2064 StringBuilder link = new StringBuilder(32); try { - link.append(desc).append(" ").append(id) - .append("|http://www.ensembl.org/Homo_sapiens/Variation/Summary?v=") + link.append(desc).append(" ").append(id).append( + "|http://www.ensembl.org/Homo_sapiens/Variation/Summary?v=") .append(URLEncoder.encode(id, "UTF-8")); sf.addLink(link.toString()); } catch (UnsupportedEncodingException e) @@ -2427,8 +2497,7 @@ public class AlignmentUtils // as if } } - String clinSig = (String) var.variant - .getValue(CLINICAL_SIGNIFICANCE); + String clinSig = (String) var.variant.getValue(CLINICAL_SIGNIFICANCE); if (clinSig != null) { sf.setValue(CLINICAL_SIGNIFICANCE, clinSig); @@ -2453,6 +2522,7 @@ public class AlignmentUtils * @param dnaToProtein * @return */ + @SuppressWarnings("unchecked") static LinkedHashMap[]> buildDnaVariantsMap( SequenceI dnaSeq, MapList dnaToProtein) { @@ -2496,7 +2566,7 @@ public class AlignmentUtils List[] codonVariants = variants.get(peptidePosition); if (codonVariants == null) { - codonVariants = new ArrayList[3]; + codonVariants = new ArrayList[CODON_LENGTH]; codonVariants[0] = new ArrayList(); codonVariants[1] = new ArrayList(); codonVariants[2] = new ArrayList(); @@ -2522,18 +2592,18 @@ public class AlignmentUtils * get this peptide's codon positions e.g. [3, 4, 5] or [4, 7, 10] */ int[] codon = peptidePosition == lastPeptidePostion ? lastCodon - : MappingUtils.flattenRanges(dnaToProtein.locateInFrom( - peptidePosition, peptidePosition)); + : MappingUtils.flattenRanges(dnaToProtein + .locateInFrom(peptidePosition, peptidePosition)); lastPeptidePostion = peptidePosition; lastCodon = codon; /* * save nucleotide (and any variant) for each codon position */ - for (int codonPos = 0; codonPos < 3; codonPos++) + for (int codonPos = 0; codonPos < CODON_LENGTH; codonPos++) { - String nucleotide = String.valueOf( - dnaSeq.getCharAt(codon[codonPos] - dnaStart)) + String nucleotide = String + .valueOf(dnaSeq.getCharAt(codon[codonPos] - dnaStart)) .toUpperCase(); List codonVariant = codonVariants[codonPos]; if (codon[codonPos] == dnaCol) @@ -2583,7 +2653,7 @@ public class AlignmentUtils { AlignmentI copy = new Alignment(new Alignment(seqs)); copy.setDataset(dataset); - + boolean isProtein = !copy.isNucleotide(); SequenceIdMatcher matcher = new SequenceIdMatcher(seqs); if (xrefs != null) { @@ -2594,7 +2664,8 @@ public class AlignmentUtils { for (DBRefEntry dbref : dbrefs) { - if (dbref.getMap() == null || dbref.getMap().getTo() == null) + if (dbref.getMap() == null || dbref.getMap().getTo() == null + || dbref.getMap().getTo().isProtein() != isProtein) { continue; } @@ -2675,7 +2746,7 @@ public class AlignmentUtils } newCol++; } - + /* * trim trailing gaps */ @@ -2744,8 +2815,8 @@ public class AlignmentUtils */ for (SequenceI seq : unaligned.getSequences()) { - List alignedSequences = alignedDatasets.get(seq - .getDatasetSequence()); + List alignedSequences = alignedDatasets + .get(seq.getDatasetSequence()); // TODO: getSequenceAsString() will be deprecated in the future // TODO: need to leave to SequenceI implementor to update gaps seq.setSequence(alignedSequences.get(0).getSequenceAsString()); @@ -2768,15 +2839,16 @@ public class AlignmentUtils * @param unmapped * @return */ - static Map> buildMappedColumnsMap( - AlignmentI unaligned, AlignmentI aligned, List unmapped) + static SortedMap> buildMappedColumnsMap( + AlignmentI unaligned, AlignmentI aligned, + List unmapped) { /* * Map will hold, for each aligned column position, a map of * {unalignedSequence, characterPerSequence} at that position. * TreeMap keeps the entries in ascending column order. */ - Map> map = new TreeMap>(); + SortedMap> map = new TreeMap>(); /* * record any sequences that have no mapping so can't be realigned @@ -2804,7 +2876,8 @@ public class AlignmentUtils } /** - * Helper method that adds to a map the mapped column positions of a sequence.
    + * Helper method that adds to a map the mapped column positions of a sequence. + *
    * For example if aaTT-Tg-gAAA is mapped to TTTAAA then the map should record * that columns 3,4,6,10,11,12 map to characters T,T,T,A,A,A of the mapped to * sequence. @@ -2833,8 +2906,8 @@ public class AlignmentUtils */ if (seqMap.getTo() == fromSeq.getDatasetSequence()) { - seqMap = new Mapping(seq.getDatasetSequence(), seqMap.getMap() - .getInverse()); + seqMap = new Mapping(seq.getDatasetSequence(), + seqMap.getMap().getInverse()); } char[] fromChars = fromSeq.getSequence();