Merge branch 'feature/JAL-2664' into feature/JAL-2527
[jalview.git] / src / jalview / analysis / CrossRef.java
index 71b0aa0..1a56393 100644 (file)
@@ -24,6 +24,7 @@ import jalview.datamodel.AlignedCodonFrame;
 import jalview.datamodel.Alignment;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.DBRefEntry;
+import jalview.datamodel.DBRefSource;
 import jalview.datamodel.Mapping;
 import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceFeature;
@@ -106,6 +107,16 @@ public class CrossRef
         findXrefSourcesForSequence(seq, dna, sources);
       }
     }
+    sources.remove(DBRefSource.EMBL); // hack to prevent EMBL xrefs resulting in
+                                      // redundant datasets
+    if (dna)
+    {
+      sources.remove(DBRefSource.ENSEMBL); // hack to prevent Ensembl and
+                                           // EnsemblGenomes xref option shown
+                                           // from cdna panel
+      sources.remove(DBRefSource.ENSEMBLGENOMES);
+    }
+    // redundant datasets
     return sources;
   }
 
@@ -153,8 +164,8 @@ public class CrossRef
        */
       for (SequenceI rs : foundSeqs)
       {
-        DBRefEntry[] xrs = DBRefUtils
-                .selectDbRefs(!fromDna, rs.getDBRefs());
+        DBRefEntry[] xrs = DBRefUtils.selectDbRefs(!fromDna,
+                rs.getDBRefs());
         addXrefsToSources(xrs, sources);
       }
     }
@@ -209,8 +220,7 @@ public class CrossRef
 
     rseqs = new ArrayList<SequenceI>();
     AlignedCodonFrame cf = new AlignedCodonFrame();
-    matcher = new SequenceIdMatcher(
-            dataset.getSequences());
+    matcher = new SequenceIdMatcher(dataset.getSequences());
 
     for (SequenceI seq : fromSeqs)
     {
@@ -220,8 +230,8 @@ public class CrossRef
         dss = dss.getDatasetSequence();
       }
       boolean found = false;
-      DBRefEntry[] xrfs = DBRefUtils
-              .selectDbRefs(!fromDna, dss.getDBRefs());
+      DBRefEntry[] xrfs = DBRefUtils.selectDbRefs(!fromDna,
+              dss.getDBRefs());
       // ENST & ENSP comes in to both Protein and nucleotide, so we need to
       // filter them
       // out later.
@@ -281,13 +291,10 @@ public class CrossRef
             if (matchInDataset != null && xref.getMap().getTo() != null
                     && matchInDataset != xref.getMap().getTo())
             {
-              System.err
-                      .println("Implementation problem (reopen JAL-2154): CrossRef.findInDataset seems to have recovered a different sequence than the one explicitly mapped for xref."
-                              + "Found:"
-                              + matchInDataset
-                              + "\nExpected:"
-                              + xref.getMap().getTo()
-                              + "\nFor xref:"
+              System.err.println(
+                      "Implementation problem (reopen JAL-2154): CrossRef.findInDataset seems to have recovered a different sequence than the one explicitly mapped for xref."
+                              + "Found:" + matchInDataset + "\nExpected:"
+                              + xref.getMap().getTo() + "\nFor xref:"
                               + xref);
             }
             /*matcher.findIdMatch(mappedTo);*/
@@ -313,8 +320,9 @@ public class CrossRef
                 }
                 else
                 {
-                  cf.addMap(matchInDataset, dss, xref.getMap().getMap()
-                          .getInverse(), xref.getMap().getMappedFromId());
+                  cf.addMap(matchInDataset, dss,
+                          xref.getMap().getMap().getInverse(),
+                          xref.getMap().getMappedFromId());
                 }
               }
 
@@ -330,8 +338,8 @@ public class CrossRef
               if (fromDna)
               {
                 // map is from dna seq to a protein product
-                cf.addMap(dss, rsq, xref.getMap().getMap(), xref.getMap()
-                        .getMappedFromId());
+                cf.addMap(dss, rsq, xref.getMap().getMap(),
+                        xref.getMap().getMappedFromId());
               }
               else
               {
@@ -345,8 +353,8 @@ public class CrossRef
 
         if (!found)
         {
-          SequenceI matchedSeq = matcher.findIdMatch(xref.getSource() + "|"
-                  + xref.getAccessionId());
+          SequenceI matchedSeq = matcher.findIdMatch(
+                  xref.getSource() + "|" + xref.getAccessionId());
           // if there was a match, check it's at least the right type of
           // molecule!
           if (matchedSeq != null && matchedSeq.isProtein() == fromDna)
@@ -396,8 +404,8 @@ public class CrossRef
   {
     ASequenceFetcher sftch = SequenceFetcherFactory.getSequenceFetcher();
     SequenceI[] retrieved = null;
-    SequenceI dss = seq.getDatasetSequence() == null ? seq : seq
-            .getDatasetSequence();
+    SequenceI dss = seq.getDatasetSequence() == null ? seq
+            : seq.getDatasetSequence();
     // first filter in case we are retrieving crossrefs that have already been
     // retrieved. this happens for cases where a database record doesn't yield
     // protein products for CDS
@@ -413,8 +421,8 @@ public class CrossRef
       retrieved = sftch.getSequences(sourceRefs, !fromDna);
     } catch (Exception e)
     {
-      System.err
-              .println("Problem whilst retrieving cross references for Sequence : "
+      System.err.println(
+              "Problem whilst retrieving cross references for Sequence : "
                       + seq.getName());
       e.printStackTrace();
     }
@@ -422,13 +430,18 @@ public class CrossRef
     if (retrieved != null)
     {
       boolean addedXref = false;
+      List<SequenceI> newDsSeqs = new ArrayList<SequenceI>(),
+              doNotAdd = new ArrayList<SequenceI>();
+
       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();
-        addedXref |= importCrossRefSeq(cf, dss, retrievedDss);
+        SequenceI retrievedDss = retrievedSequence
+                .getDatasetSequence() == null ? retrievedSequence
+                        : retrievedSequence.getDatasetSequence();
+        addedXref |= importCrossRefSeq(cf, newDsSeqs, doNotAdd, dss,
+                retrievedDss);
       }
       if (!addedXref)
       {
@@ -439,9 +452,20 @@ public class CrossRef
         {
           // dataset gets contaminated ccwith non-ds sequences. why ??!
           // try: Ensembl -> Nuc->Ensembl, Nuc->Uniprot-->Protein->EMBL->
-          SequenceI retrievedDss = retrievedSequence.getDatasetSequence() == null ? retrievedSequence
-                  : retrievedSequence.getDatasetSequence();
-          addedXref |= importCrossRefSeq(cf, dss, retrievedDss);
+          SequenceI retrievedDss = retrievedSequence
+                  .getDatasetSequence() == null ? retrievedSequence
+                          : retrievedSequence.getDatasetSequence();
+          addedXref |= importCrossRefSeq(cf, newDsSeqs, doNotAdd, dss,
+                  retrievedDss);
+        }
+      }
+      for (SequenceI newToSeq : newDsSeqs)
+      {
+        if (!doNotAdd.contains(newToSeq)
+                && dataset.findIndex(newToSeq) == -1)
+        {
+          dataset.addSequence(newToSeq);
+          matcher.add(newToSeq);
         }
       }
     }
@@ -494,6 +518,7 @@ public class CrossRef
    * @return true if retrieveSequence was imported
    */
   private boolean importCrossRefSeq(AlignedCodonFrame cf,
+          List<SequenceI> newDsSeqs, List<SequenceI> doNotAdd,
           SequenceI sourceSequence, SequenceI retrievedSequence)
   {
     /**
@@ -502,7 +527,6 @@ public class CrossRef
      */
     boolean imported = false;
     DBRefEntry[] dbr = retrievedSequence.getDBRefs();
-    List<SequenceI> newDsSeqs = new ArrayList<SequenceI>();
     if (dbr != null)
     {
       for (DBRefEntry dbref : dbr)
@@ -554,9 +578,8 @@ public class CrossRef
               int sf = map.getMap().getToLowest();
               int st = map.getMap().getToHighest();
               SequenceI mappedrg = ms.getSubSequence(sf, st);
-              if (mappedrg.getLength() > 0
-                      && ms.getSequenceAsString().equals(
-                              matched.getSequenceAsString()))
+              if (mappedrg.getLength() > 0 && ms.getSequenceAsString()
+                      .equals(matched.getSequenceAsString()))
               {
                 /*
                  * sequences were a match, 
@@ -574,9 +597,15 @@ public class CrossRef
                    */
                   for (DBRefEntry ref : toRefs)
                   {
+                    if (dbref.getSrcAccString()
+                            .equals(ref.getSrcAccString()))
+                    {
+                      continue; // avoid overwriting the ref on source sequence
+                    }
                     matched.addDBRef(ref); // add or update mapping
                   }
                 }
+                doNotAdd.add(map.getTo());
                 map.setTo(matched);
 
                 /*
@@ -600,8 +629,7 @@ public class CrossRef
                      * attribute in equality test; this avoids creating many
                      * otherwise duplicate exon features on genomic sequence
                      */
-                    SequenceFeature newFeature = new SequenceFeature(
-                            feat)
+                    SequenceFeature newFeature = new SequenceFeature(feat)
                     {
                       @Override
                       public boolean equals(Object o)
@@ -617,8 +645,8 @@ public class CrossRef
               cf.addMap(retrievedSequence, map.getTo(), map.getMap());
             } catch (Exception e)
             {
-              System.err
-                      .println("Exception when consolidating Mapped sequence set...");
+              System.err.println(
+                      "Exception when consolidating Mapped sequence set...");
               e.printStackTrace(System.err);
             }
           }
@@ -634,18 +662,10 @@ public class CrossRef
         dataset.addSequence(retrievedSequence);
         matcher.add(retrievedSequence);
       }
-      for (SequenceI newToSeq : newDsSeqs)
-      {
-
-        if (dataset.findIndex(newToSeq) == -1)
-        {
-          dataset.addSequence(newToSeq);
-          matcher.add(newToSeq);
-        }
-      }
     }
     return imported;
   }
+
   /**
    * Sets the inverse sequence mapping in the corresponding dbref of the mapped
    * to sequence (if any). This is used after fetching a cross-referenced
@@ -705,8 +725,8 @@ public class CrossRef
     SequenceI mapsTo = xref.getMap().getTo();
     String name = xref.getAccessionId();
     String name2 = xref.getSource() + "|" + name;
-    SequenceI dss = mapsTo.getDatasetSequence() == null ? mapsTo : mapsTo
-            .getDatasetSequence();
+    SequenceI dss = mapsTo.getDatasetSequence() == null ? mapsTo
+            : mapsTo.getDatasetSequence();
     // first check ds if ds is directly referenced
     if (dataset.findIndex(dss) > -1)
     {
@@ -721,8 +741,8 @@ public class CrossRef
     for (SequenceI seq : dataset.getSequences())
     {
       // first check primary refs.
-      List<DBRefEntry> match = DBRefUtils.searchRefs(seq.getPrimaryDBRefs()
-              .toArray(new DBRefEntry[0]), template);
+      List<DBRefEntry> match = DBRefUtils.searchRefs(
+              seq.getPrimaryDBRefs().toArray(new DBRefEntry[0]), template);
       if (match != null && match.size() == 1 && sameSequence(seq, dss))
       {
         return seq;
@@ -732,9 +752,8 @@ public class CrossRef
        * returns sequences with a dbref to the matched accession id 
        * which we don't want
        */
-      if (firstIdMatch == null
-              && (name.equals(seq.getName()) || seq.getName().startsWith(
-                      name2)))
+      if (firstIdMatch == null && (name.equals(seq.getName())
+              || seq.getName().startsWith(name2)))
       {
         if (sameSequence(seq, dss))
         {
@@ -930,7 +949,8 @@ public class CrossRef
    * @return true if matches were found.
    */
   private boolean searchDatasetXrefs(boolean fromDna, SequenceI sequenceI,
-          DBRefEntry[] lrfs, List<SequenceI> foundSeqs, AlignedCodonFrame cf)
+          DBRefEntry[] lrfs, List<SequenceI> foundSeqs,
+          AlignedCodonFrame cf)
   {
     boolean found = false;
     if (lrfs == null)
@@ -943,7 +963,8 @@ public class CrossRef
       // add in wildcards
       xref.setVersion(null);
       xref.setMap(null);
-      found |= searchDataset(fromDna, sequenceI, xref, foundSeqs, cf, false);
+      found |= searchDataset(fromDna, sequenceI, xref, foundSeqs, cf,
+              false);
     }
     return found;
   }
@@ -999,10 +1020,9 @@ public class CrossRef
         {
           if (nxt.getDatasetSequence() != null)
           {
-            System.err
-                    .println("Implementation warning: CrossRef initialised with a dataset alignment with non-dataset sequences in it! ("
-                            + nxt.getDisplayId(true)
-                            + " has ds reference "
+            System.err.println(
+                    "Implementation warning: CrossRef initialised with a dataset alignment with non-dataset sequences in it! ("
+                            + nxt.getDisplayId(true) + " has ds reference "
                             + nxt.getDatasetSequence().getDisplayId(true)
                             + ")");
           }