Jalview.isJS() --> Platform.isJS(), DBRefEntry[] --> List<DBRefEntry>
[jalview.git] / src / jalview / analysis / AlignmentUtils.java
index 5e11446..8fd961e 100644 (file)
@@ -1599,11 +1599,12 @@ public class AlignmentUtils
       return false;
     }
     String name = seq2.getName();
-    final DBRefEntry[] xrefs = seq1.getDBRefs();
+    final List<DBRefEntry> xrefs = seq1.getDBRefs();
     if (xrefs != null)
     {
-      for (DBRefEntry xref : xrefs)
+      for (int ix = 0, nx = xrefs.size(); ix < nx; ix++)
       {
+         DBRefEntry xref = xrefs.get(ix);
         String xrefName = xref.getSource() + "|" + xref.getAccessionId();
         // case-insensitive test, consistent with DBRefEntry.equalRef()
         if (xrefName.equalsIgnoreCase(name))
@@ -1799,8 +1800,10 @@ public class AlignmentUtils
           // need to
           // synthesize an xref.
 
-          for (DBRefEntry primRef : dnaDss.getPrimaryDBRefs())
+          List<DBRefEntry> primrefs = dnaDss.getPrimaryDBRefs();
+          for (int ip = 0, np = primrefs.size(); ip < np; ip++)
           {
+                 DBRefEntry primRef = primrefs.get(ip);
             /*
              * create a cross-reference from CDS to the source sequence's
              * primary reference and vice versa
@@ -1814,7 +1817,6 @@ public class AlignmentUtils
 
             dnaSeq.addDBRef(new DBRefEntry(source, version, cdsSeq
                     .getName(), new Mapping(cdsSeqDss, dnaToCdsMap)));
-
             // problem here is that the cross-reference is synthesized -
             // cdsSeq.getName() may be like 'CDS|dnaaccession' or
             // 'CDS|emblcdsacc'
@@ -1827,7 +1829,6 @@ public class AlignmentUtils
                     .getInverse()));
             proteinProduct.addDBRef(proteinToCdsRef);
           }
-
           /*
            * transfer any features on dna that overlap the CDS
            */
@@ -1888,7 +1889,7 @@ public class AlignmentUtils
    * @param seqMappings
    *          the set of mappings involving dnaSeq
    * @param aMapping
-   *          an initial candidate from seqMappings
+   *          a transcript-to-peptide mapping
    * @return
    */
   static SequenceI findCdsForProtein(List<AlignedCodonFrame> mappings,
@@ -1913,7 +1914,15 @@ public class AlignmentUtils
     if (mappedFromLength == dnaLength
             || mappedFromLength == dnaLength - CODON_LENGTH)
     {
-      return seqDss;
+      /*
+       * if sequence has CDS features, this is a transcript with no UTR
+       * - do not take this as the CDS sequence! (JAL-2789)
+       */
+      if (seqDss.getFeatures().getFeaturesByOntology(SequenceOntologyI.CDS)
+              .isEmpty())
+      {
+        return seqDss;
+      }
     }
 
     /*
@@ -1938,10 +1947,12 @@ public class AlignmentUtils
           {
             /*
             * found a 3:1 mapping to the protein product which covers
-            * the whole dna sequence i.e. is from CDS; finally check it
-            * is from the dna start sequence
+            * the whole dna sequence i.e. is from CDS; finally check the CDS
+            * is mapped from the given dna start sequence
             */
             SequenceI cdsSeq = map.getFromSeq();
+            // todo this test is weak if seqMappings contains multiple mappings;
+            // we get away with it if transcript:cds relationship is 1:1
             List<AlignedCodonFrame> dnaToCdsMaps = MappingUtils
                     .findMappingsForSequence(cdsSeq, seqMappings);
             if (!dnaToCdsMaps.isEmpty())
@@ -2056,16 +2067,20 @@ public class AlignmentUtils
   protected static List<DBRefEntry> propagateDBRefsToCDS(SequenceI cdsSeq,
           SequenceI contig, SequenceI proteinProduct, Mapping mapping)
   {
+
     // gather direct refs from contig congruent with mapping
     List<DBRefEntry> direct = new ArrayList<>();
     HashSet<String> directSources = new HashSet<>();
-    if (contig.getDBRefs() != null)
+
+    List<DBRefEntry> refs = contig.getDBRefs();
+    if (refs != null)
     {
-      for (DBRefEntry dbr : contig.getDBRefs())
+      for (int ib = 0, nb = refs.size(); ib < nb; ib++)
       {
-        if (dbr.hasMap() && dbr.getMap().getMap().isTripletMap())
+         DBRefEntry dbr = refs.get(ib);
+         MapList map;
+        if (dbr.hasMap() && (map = dbr.getMap().getMap()).isTripletMap())
         {
-          MapList map = dbr.getMap().getMap();
           // check if map is the CDS mapping
           if (mapping.getMap().equals(map))
           {
@@ -2075,21 +2090,22 @@ public class AlignmentUtils
         }
       }
     }
-    DBRefEntry[] onSource = DBRefUtils.selectRefs(
+    List<DBRefEntry> onSource = DBRefUtils.selectRefs(
             proteinProduct.getDBRefs(),
             directSources.toArray(new String[0]));
     List<DBRefEntry> propagated = new ArrayList<>();
 
     // and generate appropriate mappings
-    for (DBRefEntry cdsref : direct)
+    for (int ic = 0, nc = direct.size(); ic < nc; ic++)
     {
+       DBRefEntry cdsref = direct.get(ic);
+       Mapping m = cdsref.getMap();
       // 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());
+              m.getMap().getToRanges(), 3, 1);
+      Mapping cdsmap = new Mapping(m.getTo(),m.getMap());
 
       // create dbref
       DBRefEntry newref = new DBRefEntry(cdsref.getSource(),
@@ -2235,12 +2251,13 @@ public class AlignmentUtils
     int mappedDnaLength = MappingUtils.getLength(ranges);
 
     /*
-     * if not a whole number of codons, something is wrong,
-     * abort mapping
+     * if not a whole number of codons, truncate mapping
      */
-    if (mappedDnaLength % CODON_LENGTH > 0)
+    int codonRemainder = mappedDnaLength % CODON_LENGTH;
+    if (codonRemainder > 0)
     {
-      return null;
+      mappedDnaLength -= codonRemainder;
+      MappingUtils.removeEndPositions(codonRemainder, ranges);
     }
 
     int proteinLength = proteinSeq.getLength();
@@ -2307,10 +2324,14 @@ public class AlignmentUtils
       int phase = 0;
       try
       {
-        phase = Integer.parseInt(sf.getPhase());
+       String s = sf.getPhase();
+       if (s != null) 
+       {
+               phase = Integer.parseInt(s);
+       }
       } catch (NumberFormatException e)
       {
-        // ignore
+        // SwingJS -- need to avoid these.
       }
       /*
        * phase > 0 on first codon means 5' incomplete - skip to the start
@@ -2421,11 +2442,11 @@ public class AlignmentUtils
     /*
      * variants in first codon base
      */
-    for (DnaVariant var : codonVariants[0])
+    for (DnaVariant dnavar : codonVariants[0])
     {
-      if (var.variant != null)
+      if (dnavar.variant != null)
       {
-        String alleles = (String) var.variant.getValue(Gff3Helper.ALLELES);
+        String alleles = (String) dnavar.variant.getValue(Gff3Helper.ALLELES);
         if (alleles != null)
         {
           for (String base : alleles.split(","))
@@ -2436,7 +2457,7 @@ public class AlignmentUtils
                       + base3.toLowerCase();
               String canonical = base1.toUpperCase() + base2.toLowerCase()
                       + base3.toLowerCase();
-              if (addPeptideVariant(peptide, peptidePos, residue, var,
+              if (addPeptideVariant(peptide, peptidePos, residue, dnavar,
                       codon, canonical))
               {
                 count++;
@@ -2750,19 +2771,25 @@ public class AlignmentUtils
     SequenceIdMatcher matcher = new SequenceIdMatcher(seqs);
     if (xrefs != null)
     {
-      for (SequenceI xref : xrefs)
+       // BH 2019.01.25 streamlined this triply nested loop to remove all iterators
+       
+      for (int ix = 0, nx = xrefs.length; ix < nx; ix++)
       {
-        DBRefEntry[] dbrefs = xref.getDBRefs();
+       SequenceI xref = xrefs[ix];
+        List<DBRefEntry> dbrefs = xref.getDBRefs();
         if (dbrefs != null)
         {
-          for (DBRefEntry dbref : dbrefs)
+          for (int ir = 0, nir = dbrefs.size(); ir < nir; ir++)
           {
-            if (dbref.getMap() == null || dbref.getMap().getTo() == null
-                    || dbref.getMap().getTo().isProtein() != isProtein)
+                 DBRefEntry dbref = dbrefs.get(ir);
+                 Mapping map = dbref.getMap();
+                 SequenceI mto;
+            if (map == null || (mto = map.getTo()) == null
+                    || mto.isProtein() != isProtein)
             {
               continue;
             }
-            SequenceI mappedTo = dbref.getMap().getTo();
+            SequenceI mappedTo = mto;
             SequenceI match = matcher.findIdMatch(mappedTo);
             if (match == null)
             {