JAL-2154 don’t synthesise multiple CDS|<Acc> sequences when one is already available...
[jalview.git] / src / jalview / analysis / AlignmentUtils.java
index bed685a..b0a2269 100644 (file)
@@ -1680,15 +1680,20 @@ 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|<dbref>
           // <dbref> 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);
           }
 
@@ -1734,28 +1739,41 @@ 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
@@ -1857,9 +1875,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<int[]> fromRanges = mapping.getMap().getFromRanges();
@@ -1894,6 +1917,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;
@@ -2583,7 +2640,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 +2651,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;
             }