JAL-2110 refactor to split SequenceFetcher from x-ref resolution routine
authorJim Procter <jprocter@issues.jalview.org>
Thu, 23 Jun 2016 13:11:10 +0000 (14:11 +0100)
committerJim Procter <jprocter@issues.jalview.org>
Thu, 23 Jun 2016 13:11:10 +0000 (14:11 +0100)
src/jalview/analysis/CrossRef.java

index 3862edf..7dcaa17 100644 (file)
@@ -28,7 +28,6 @@ import jalview.datamodel.Mapping;
 import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
-import jalview.util.Comparison;
 import jalview.util.DBRefUtils;
 import jalview.util.MapList;
 import jalview.ws.SequenceFetcherFactory;
@@ -59,6 +58,21 @@ public class CrossRef
   private SequenceI[] fromSeqs;
 
   /**
+   * matcher built from dataset
+   */
+  SequenceIdMatcher matcher;
+
+  /**
+   * sequences found by cross-ref searches to fromSeqs
+   */
+  List<SequenceI> rseqs;
+
+  /**
+   * mappings constructed
+   */
+  AlignedCodonFrame cf;
+
+  /**
    * Constructor
    * 
    * @param seqs
@@ -195,9 +209,9 @@ public class CrossRef
   public Alignment findXrefSequences(String source, boolean fromDna)
   {
 
-    List<SequenceI> rseqs = new ArrayList<SequenceI>();
-    AlignedCodonFrame cf = new AlignedCodonFrame();
-    SequenceIdMatcher matcher = new SequenceIdMatcher(
+    rseqs = new ArrayList<SequenceI>();
+    cf = new AlignedCodonFrame();
+    matcher = new SequenceIdMatcher(
             dataset.getSequences());
 
     for (SequenceI seq : fromSeqs)
@@ -319,153 +333,160 @@ public class CrossRef
        */
       if (!sourceRefs.isEmpty())
       {
-        ASequenceFetcher sftch = SequenceFetcherFactory
-                .getSequenceFetcher();
-        SequenceI[] retrieved = null;
-        try
-        {
-          retrieved = sftch.getSequences(sourceRefs, !fromDna);
-        } catch (Exception e)
-        {
-          System.err
-                  .println("Problem whilst retrieving cross references for Sequence : "
-                          + seq.getName());
-          e.printStackTrace();
-        }
+        retrieveCrossRef(sourceRefs, seq, xrfs, fromDna);
+      }
+    }
+
+    Alignment ral = null;
+    if (rseqs.size() > 0)
+    {
+      ral = new Alignment(rseqs.toArray(new SequenceI[rseqs.size()]));
+      if (!cf.isEmpty())
+      {
+        dataset.addCodonFrame(cf);
+      }
+    }
+    return ral;
+  }
+
+  private void retrieveCrossRef(List<DBRefEntry> sourceRefs, SequenceI seq,
+          DBRefEntry[] xrfs, boolean fromDna)
+  {
+    ASequenceFetcher sftch = SequenceFetcherFactory.getSequenceFetcher();
+    SequenceI[] retrieved = null;
+    SequenceI dss = null;
+    try
+    {
+      retrieved = sftch.getSequences(sourceRefs, !fromDna);
+    } catch (Exception e)
+    {
+      System.err
+              .println("Problem whilst retrieving cross references for Sequence : "
+                      + seq.getName());
+      e.printStackTrace();
+    }
 
-        if (retrieved != null)
+    if (retrieved != null)
+    {
+      updateDbrefMappings(seq, xrfs, retrieved, cf, fromDna);
+      for (SequenceI retrievedSequence : retrieved)
+      {
+        // dataset gets contaminated ccwith non-ds sequences. why ??!
+        // try: Ensembl -> Nuc->Ensembl, Nuc->Uniprot-->Protein->EMBL->
+        SequenceI retrievedDss = retrievedSequence.getDatasetSequence() == null ? retrievedSequence
+                : retrievedSequence.getDatasetSequence();
+        DBRefEntry[] dbr = retrievedSequence.getDBRefs();
+        if (dbr != null)
         {
-          updateDbrefMappings(seq, xrfs, retrieved, cf, fromDna);
-          for (SequenceI retrievedSequence : retrieved)
+          for (DBRefEntry dbref : dbr)
           {
-            SequenceI retrievedDss = retrievedSequence.getDatasetSequence() == null ? retrievedSequence
-                    : retrievedSequence.getDatasetSequence();
-            DBRefEntry[] dbr = retrievedSequence.getDBRefs();
-            if (dbr != null)
+            // find any entry where we should put in the sequence being
+            // cross-referenced into the map
+            Mapping map = dbref.getMap();
+            if (map != null)
             {
-              for (DBRefEntry dbref : dbr)
+              if (map.getTo() != null && map.getMap() != null)
               {
-                // find any entry where we should put in the sequence being
-                // cross-referenced into the map
-                Mapping map = dbref.getMap();
-                if (map != null)
+                // TODO findInDataset requires exact sequence match but
+                // 'congruent' test is only for the mapped part
+                // maybe not a problem in practice since only ENA provide a
+                // mapping and it is to the full protein translation of CDS
+                SequenceI matched = findInDataset(dbref);
+                // matcher.findIdMatch(map.getTo());
+                if (matched != null)
                 {
-                  if (map.getTo() != null && map.getMap() != null)
+                  /*
+                   * already got an xref to this sequence; update this
+                   * map to point to the same sequence, and add
+                   * any new dbrefs to it
+                   */
+                  DBRefEntry[] toRefs = map.getTo().getDBRefs();
+                  if (toRefs != null)
                   {
-                    // TODO findInDataset requires exact sequence match but
-                    // 'congruent' test is only for the mapped part
-                    // maybe not a problem in practice since only ENA provide a
-                    // mapping and it is to the full protein translation of CDS
-                    SequenceI matched = findInDataset(dbref);
-                    // 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
-                       */
-                      DBRefEntry[] toRefs = map.getTo().getDBRefs();
-                      if (toRefs != null)
-                      {
-                        for (DBRefEntry ref : toRefs)
-                        {
-                          matched.addDBRef(ref); // add or update mapping
-                        }
-                      }
-                      map.setTo(matched);
-                    }
-                    else
+                    for (DBRefEntry ref : toRefs)
                     {
-                      matcher.add(map.getTo());
+                      matched.addDBRef(ref); // add or update mapping
                     }
-                    try
+                  }
+                  map.setTo(matched);
+                }
+                else
+                {
+                  matcher.add(map.getTo());
+                }
+                try
+                {
+                  // compare ms with dss and replace with dss in mapping
+                  // if map is congruent
+                  SequenceI ms = map.getTo();
+                  int sf = map.getMap().getToLowest();
+                  int st = map.getMap().getToHighest();
+                  SequenceI mappedrg = ms.getSubSequence(sf, st);
+                  // SequenceI loc = dss.getSubSequence(sf, st);
+                  if (mappedrg.getLength() > 0
+                          && ms.getSequenceAsString().equals(
+                                  dss.getSequenceAsString()))
+                  // && mappedrg.getSequenceAsString().equals(
+                  // loc.getSequenceAsString()))
+                  {
+                    String msg = "Mapping updated from " + ms.getName()
+                            + " to retrieved crossreference "
+                            + dss.getName();
+                    System.out.println(msg);
+                    map.setTo(dss);
+
+                    /*
+                     * give the reverse reference the inverse mapping 
+                     * (if it doesn't have one already)
+                     */
+                    setReverseMapping(dss, dbref, cf);
+
+                    /*
+                     * copy sequence features as well, avoiding
+                     * duplication (e.g. same variation from two 
+                     * transcripts)
+                     */
+                    SequenceFeature[] sfs = ms.getSequenceFeatures();
+                    if (sfs != null)
                     {
-                      // compare ms with dss and replace with dss in mapping
-                      // if map is congruent
-                      SequenceI ms = map.getTo();
-                      int sf = map.getMap().getToLowest();
-                      int st = map.getMap().getToHighest();
-                      SequenceI mappedrg = ms.getSubSequence(sf, st);
-                      // SequenceI loc = dss.getSubSequence(sf, st);
-                      if (mappedrg.getLength() > 0
-                              && ms.getSequenceAsString().equals(
-                                      dss.getSequenceAsString()))
-                      // && mappedrg.getSequenceAsString().equals(
-                      // loc.getSequenceAsString()))
+                      for (SequenceFeature feat : sfs)
                       {
-                        String msg = "Mapping updated from " + ms.getName()
-                                + " to retrieved crossreference "
-                                + dss.getName();
-                        System.out.println(msg);
-                        map.setTo(dss);
-
                         /*
-                         * give the reverse reference the inverse mapping 
-                         * (if it doesn't have one already)
+                         * make a flyweight feature object which ignores Parent
+                         * attribute in equality test; this avoids creating many
+                         * otherwise duplicate exon features on genomic sequence
                          */
-                        setReverseMapping(dss, dbref, cf);
-
-                        /*
-                         * copy sequence features as well, avoiding
-                         * duplication (e.g. same variation from two 
-                         * transcripts)
-                         */
-                        SequenceFeature[] sfs = ms.getSequenceFeatures();
-                        if (sfs != null)
+                        SequenceFeature newFeature = new SequenceFeature(
+                                feat)
                         {
-                          for (SequenceFeature feat : sfs)
+                          @Override
+                          public boolean equals(Object o)
                           {
-                            /*
-                             * make a flyweight feature object which ignores Parent
-                             * attribute in equality test; this avoids creating many
-                             * otherwise duplicate exon features on genomic sequence
-                             */
-                            SequenceFeature newFeature = new SequenceFeature(
-                                    feat)
-                            {
-                              @Override
-                              public boolean equals(Object o)
-                              {
-                                return super.equals(o, true);
-                              }
-                            };
-                            dss.addSequenceFeature(newFeature);
+                            return super.equals(o, true);
                           }
-                        }
+                        };
+                        dss.addSequenceFeature(newFeature);
                       }
-                      cf.addMap(retrievedDss, map.getTo(), map.getMap());
-                    } catch (Exception e)
-                    {
-                      System.err
-                              .println("Exception when consolidating Mapped sequence set...");
-                      e.printStackTrace(System.err);
                     }
                   }
+                  cf.addMap(retrievedDss, map.getTo(), map.getMap());
+                } catch (Exception e)
+                {
+                  System.err
+                          .println("Exception when consolidating Mapped sequence set...");
+                  e.printStackTrace(System.err);
                 }
               }
             }
-            retrievedSequence.updatePDBIds();
-            rseqs.add(retrievedDss);
-            dataset.addSequence(retrievedDss);
-            matcher.add(retrievedDss);
           }
         }
+        retrievedSequence.updatePDBIds();
+        rseqs.add(retrievedDss);
+        dataset.addSequence(retrievedDss);
+        matcher.add(retrievedDss);
       }
     }
-
-    Alignment ral = null;
-    if (rseqs.size() > 0)
-    {
-      ral = new Alignment(rseqs.toArray(new SequenceI[rseqs.size()]));
-      if (!cf.isEmpty())
-      {
-        dataset.addCodonFrame(cf);
-      }
-    }
-    return ral;
   }
-
   /**
    * Sets the inverse sequence mapping in the corresponding dbref of the mapped
    * to sequence (if any). This is used after fetching a cross-referenced