JAL-2023 adjustments to mappings added for split frame to avoid
[jalview.git] / src / jalview / analysis / CrossRef.java
index 2f6076a..7e77fc1 100644 (file)
@@ -30,6 +30,7 @@ import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
 import jalview.util.DBRefUtils;
+import jalview.util.MapList;
 import jalview.ws.SequenceFetcher;
 import jalview.ws.seqfetcher.ASequenceFetcher;
 
@@ -227,13 +228,10 @@ public class CrossRef
    * @param al
    *          alignment to search for cross-referenced sequences (and possibly
    *          add to)
-   * @param addedPeers
-   *          a list of sequences to add to if 'peers' to the original sequences
-   *          are found e.g. alternative protein products for a protein's gene
    * @return products (as dataset sequences)
    */
-  public static Alignment findXrefSequences(SequenceI[] seqs, boolean dna,
-          String source, AlignmentI al, List<SequenceI> addedPeers)
+  public static Alignment findXrefSequences(SequenceI[] seqs,
+          final boolean dna, final String source, AlignmentI al)
   {
     AlignmentI dataset = al.getDataset() == null ? al : al.getDataset();
     List<SequenceI> rseqs = new ArrayList<SequenceI>();
@@ -294,7 +292,8 @@ public class CrossRef
           // xrefs on this sequence.
           if (dataset != null)
           {
-            found |= searchDataset(dss, xref, dataset, rseqs, cf); // ,false,!dna);
+            found |= searchDataset(dss, xref, dataset, rseqs, cf, false,
+                    !dna);
             if (found)
             {
               xrfs[r] = null; // we've recovered seqs for this one.
@@ -328,8 +327,8 @@ public class CrossRef
           }
           if (l > 0)
           {
-            System.out
-                    .println("Attempting to retrieve cross referenced sequences.");
+            // System.out
+            // .println("Attempting to retrieve cross referenced sequences.");
             DBRefEntry[] t = new DBRefEntry[l];
             l = 0;
             for (int r = 0; r < xrfs.length; r++)
@@ -355,6 +354,10 @@ public class CrossRef
 
             if (retrieved != null)
             {
+              updateDbrefMappings(dna, seq, xrfs, retrieved, cf);
+
+              SequenceIdMatcher matcher = new SequenceIdMatcher(
+                      dataset.getSequences());
               List<SequenceFeature> copiedFeatures = new ArrayList<SequenceFeature>();
               CrossRef me = new CrossRef();
               for (int rs = 0; rs < retrieved.length; rs++)
@@ -372,8 +375,25 @@ public class CrossRef
                     {
                       if (map.getTo() != null && map.getMap() != null)
                       {
-                        // should search the local dataset to find any existing
-                        // candidates for To !
+                        SequenceI matched = matcher
+                                .findIdMatch(map.getTo());
+                        if (matched != null)
+                        {
+                          /*
+                           * already got an xref to this sequence; update this
+                           * map to point to the same sequence, and add
+                           * any new dbrefs to it
+                           */
+                          for (DBRefEntry ref : map.getTo().getDBRefs())
+                          {
+                            matched.addDBRef(ref); // add or update mapping
+                          }
+                          map.setTo(matched);
+                        }
+                        else
+                        {
+                          matcher.add(map.getTo());
+                        }
                         try
                         {
                           // compare ms with dss and replace with dss in mapping
@@ -400,7 +420,8 @@ public class CrossRef
                             map.setTo(dss);
                             /*
                              * copy sequence features as well, avoiding
-                             * duplication (e.g. from 2 transcripts)
+                             * duplication (e.g. same variation from 2 
+                             * transcripts)
                              */
                             SequenceFeature[] sfs = ms
                                     .getSequenceFeatures();
@@ -427,7 +448,6 @@ public class CrossRef
                           }
                           else
                           {
-                            addedPeers.add(map.getTo());
                             cf.addMap(retrieved[rs].getDatasetSequence(),
                                     map.getTo(), map.getMap());
                           }
@@ -463,6 +483,69 @@ public class CrossRef
   }
 
   /**
+   * Updates any empty mappings in the cross-references with one to a compatible
+   * retrieved sequence if found, and adds any new mappings to the
+   * AlignedCodonFrame
+   * 
+   * @param dna
+   * @param mapFrom
+   * @param xrefs
+   * @param retrieved
+   * @param acf
+   */
+  static void updateDbrefMappings(boolean dna, SequenceI mapFrom,
+          DBRefEntry[] xrefs, SequenceI[] retrieved, AlignedCodonFrame acf)
+  {
+    SequenceIdMatcher matcher = new SequenceIdMatcher(retrieved);
+    for (DBRefEntry xref : xrefs)
+    {
+      if (!xref.hasMap())
+      {
+        String targetSeqName = xref.getSource() + "|"
+                + xref.getAccessionId();
+        SequenceI[] matches = matcher.findAllIdMatches(targetSeqName);
+        if (matches == null)
+        {
+          return;
+        }
+        for (SequenceI seq : matches)
+        {
+          MapList mapping = null;
+          if (dna)
+          {
+            mapping = AlignmentUtils.mapCdnaToProtein(seq, mapFrom);
+          }
+          else
+          {
+            mapping = AlignmentUtils.mapCdnaToProtein(mapFrom, seq);
+            if (mapping != null)
+            {
+              mapping = mapping.getInverse();
+            }
+          }
+          if (mapping != null)
+          {
+            xref.setMap(new Mapping(seq, mapping));
+            if (dna)
+            {
+              AlignmentUtils.computeProteinFeatures(mapFrom, seq, mapping);
+            }
+            if (dna)
+            {
+              acf.addMap(mapFrom, seq, mapping);
+            }
+            else
+            {
+              acf.addMap(seq, mapFrom, mapping.getInverse());
+            }
+            continue;
+          }
+        }
+      }
+    }
+  }
+
+  /**
    * find references to lrfs in the cross-reference set of each sequence in
    * dataset (that is not equal to sequenceI) Identifies matching DBRefEntry
    * based on source and accession string only - Map and Version are nulled.