JAL-3210 Improvements to eclipse detection. New src tree and SwingJS updated from...
[jalview.git] / src / jalview / ext / ensembl / EnsemblSeqProxy.java
index 7a37c8a..bdaef0b 100644 (file)
@@ -40,8 +40,8 @@ import jalview.util.Comparison;
 import jalview.util.DBRefUtils;
 import jalview.util.IntRangeComparator;
 import jalview.util.MapList;
+import jalview.util.Platform;
 
-import java.io.BufferedReader;
 import java.io.IOException;
 import java.net.MalformedURLException;
 import java.net.URL;
@@ -49,9 +49,8 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 
-import org.json.simple.JSONObject;
-import org.json.simple.parser.JSONParser;
 import org.json.simple.parser.ParseException;
 
 /**
@@ -172,14 +171,15 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
      * fetch and transfer genomic sequence features,
      * fetch protein product and add as cross-reference
      */
-    for (String accId : allIds)
+    for (int i = 0, n = allIds.size(); i < n; i++) 
     {
-      addFeaturesAndProduct(accId, alignment);
+      addFeaturesAndProduct(allIds.get(i), alignment);
     }
 
-    for (SequenceI seq : alignment.getSequences())
+    List<SequenceI> seqs = alignment.getSequences();
+    for (int i = 0, n = seqs.size(); i < n; i++)
     {
-      getCrossReferences(seq);
+      getCrossReferences(seqs.get(i));
     }
 
     return alignment;
@@ -209,13 +209,20 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
        */
       SequenceI genomicSequence = null;
       EnsemblFeatures gffFetcher = new EnsemblFeatures(getDomain());
-      EnsemblFeatureType[] features = getFeaturesToFetch();
+      EnsemblFeatureType[] features = getFeaturesToFetch();      
+      
+      Platform.timeCheck("ESP.getsequencerec1", Platform.TIME_MARK);     
+
+      
       AlignmentI geneFeatures = gffFetcher.getSequenceRecords(accId,
               features);
       if (geneFeatures != null && geneFeatures.getHeight() > 0)
       {
         genomicSequence = geneFeatures.getSequenceAt(0);
       }
+      
+      Platform.timeCheck("ESP.getsequencerec2", Platform.TIME_MARK);     
+      
       if (genomicSequence != null)
       {
         /*
@@ -229,6 +236,7 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
            * fetch and map protein product, and add it as a cross-reference
            * of the retrieved sequence
            */
+            Platform.timeCheck("ESP.transferFeatures", Platform.TIME_MARK);      
           addProteinProduct(querySeq);
         }
       }
@@ -237,6 +245,7 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
       System.err.println(
               "Error transferring Ensembl features: " + e.getMessage());
     }
+    Platform.timeCheck("ESP.addfeat done", Platform.TIME_MARK);          
   }
 
   /**
@@ -258,6 +267,7 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
     String accId = querySeq.getName();
     try
     {
+      System.out.println("Adding protein product for " + accId);
       AlignmentI protein = new EnsemblProtein(getDomain())
               .getSequenceRecords(accId);
       if (protein == null || protein.getHeight() == 0)
@@ -284,10 +294,10 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
         DBRefEntry dbr = new DBRefEntry(getDbSource(),
                 getEnsemblDataVersion(), proteinSeq.getName(), map);
         querySeq.getDatasetSequence().addDBRef(dbr);
-        DBRefEntry[] uprots = DBRefUtils.selectRefs(ds.getDBRefs(),
+        List<DBRefEntry> uprots = DBRefUtils.selectRefs(ds.getDBRefs(),
                 new String[]
                 { DBRefSource.UNIPROT });
-        DBRefEntry[] upxrefs = DBRefUtils.selectRefs(querySeq.getDBRefs(),
+        List<DBRefEntry> upxrefs = DBRefUtils.selectRefs(querySeq.getDBRefs(),
                 new String[]
                 { DBRefSource.UNIPROT });
         if (uprots != null)
@@ -348,25 +358,47 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
    */
   protected void getCrossReferences(SequenceI seq)
   {
+         
+      Platform.timeCheck("ESP. getdataseq ", Platform.TIME_MARK);        
+
+         
     while (seq.getDatasetSequence() != null)
     {
       seq = seq.getDatasetSequence();
     }
 
+    Platform.timeCheck("ESP. getxref ", Platform.TIME_MARK);     
+
     EnsemblXref xrefFetcher = new EnsemblXref(getDomain(), getDbSource(),
             getEnsemblDataVersion());
     List<DBRefEntry> xrefs = xrefFetcher.getCrossReferences(seq.getName());
-    for (DBRefEntry xref : xrefs)
+    
+    for (int i = 0, n = xrefs.size(); i < n; i++)
     {
-      seq.addDBRef(xref);
+//        Platform.timeCheck("ESP. getxref + " + (i) + "/" + n, Platform.TIME_MARK);     
+        // BH 2019.01.25 this next method was taking 174 ms PER addition for a 266-reference example.
+        //    DBRefUtils.ensurePrimaries(seq) 
+        //        was at the end of seq.addDBRef, so executed after ever addition!
+        //        This method was moved to     seq.getPrimaryDBRefs()
+      seq.addDBRef(xrefs.get(i));
     }
 
+//    System.out.println("primaries are " + seq.getPrimaryDBRefs().toString());
     /*
      * and add a reference to itself
      */
+    
+//    Platform.timeCheck("ESP. getxref self ", Platform.TIME_MARK);      
+
     DBRefEntry self = new DBRefEntry(getDbSource(), getEnsemblDataVersion(),
-            seq.getName());
+    seq.getName());
+
+//    Platform.timeCheck("ESP. getxref self add ", Platform.TIME_MARK);          
+
     seq.addDBRef(self);
+    
+    Platform.timeCheck("ESP. seqprox done ", Platform.TIME_MARK);        
+
   }
 
   /**
@@ -387,14 +419,14 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
       inProgress = false;
       throw new JalviewException("ENSEMBL Rest API not available.");
     }
-    BufferedReader br = getSequenceReader(ids);
-    if (br == null)
+       Platform.timeCheck("EnsemblSeqProx.fetchSeq ", Platform.TIME_MARK);
+
+    List<SequenceI> seqs = parseSequenceJson(ids);
+    if (seqs == null)
     {
       return alignment;
     }
 
-    List<SequenceI> seqs = parseSequenceJson(br);
-
     if (seqs.isEmpty())
     {
       throw new IOException("No data returned for " + ids);
@@ -446,9 +478,9 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
    * @return a single jalview.datamodel.Sequence
    * @see http://rest.ensembl.org/documentation/info/sequence_id
    */
-  protected List<SequenceI> parseSequenceJson(BufferedReader br)
+  @SuppressWarnings("unchecked")
+  protected List<SequenceI> parseSequenceJson(List<String> ids)
   {
-    JSONParser jp = new JSONParser();
     List<SequenceI> result = new ArrayList<>();
     try
     {
@@ -456,7 +488,13 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
        * for now, assumes only one sequence returned; refactor if needed
        * in future to handle a JSONArray with more than one
        */
-      final JSONObject val = (JSONObject) jp.parse(br);
+       
+       Platform.timeCheck("ENS seqproxy", Platform.TIME_MARK);
+      Map<String, Object> val = (Map<String, Object>) getJSON(null, ids, -1, MODE_MAP, null);
+      if (val == null)
+      {
+        return null;
+      }
       Object s = val.get("desc");
       String desc = s == null ? null : s.toString();
       s = val.get("id");
@@ -479,6 +517,7 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
       System.err.println("Error processing JSON response: " + e.toString());
       // ignore
     }
+       Platform.timeCheck("ENS seqproxy2", Platform.TIME_MARK);
     return result;
   }
 
@@ -504,7 +543,7 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
     // @see https://github.com/Ensembl/ensembl-rest/wiki/Output-formats
     urlstring.append("?type=").append(getSourceEnsemblType().getType());
     urlstring.append(("&Accept=application/json"));
-    urlstring.append(("&Content-Type=application/json"));
+    urlstring.append(("&content-type=application/json"));
 
     String objectType = getObjectType();
     if (objectType != null)
@@ -658,7 +697,9 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
    */
   protected abstract List<SequenceFeature> getIdentifyingFeatures(
           SequenceI seq, String accId);
-
+  
+  int bhtest = 0;
+  
   /**
    * Transfers the sequence feature to the target sequence, locating its start
    * and end range based on the mapping. Features which do not overlap the
@@ -680,6 +721,7 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
 
     if (mappedRange != null)
     {
+//      Platform.timeCheck(null, Platform.TIME_SET);
       String group = sf.getFeatureGroup();
       if (".".equals(group))
       {
@@ -687,15 +729,18 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
       }
       int newBegin = Math.min(mappedRange[0], mappedRange[1]);
       int newEnd = Math.max(mappedRange[0], mappedRange[1]);
-      SequenceFeature copy = new SequenceFeature(sf, newBegin, newEnd,
-              group, sf.getScore());
+//      Platform.timeCheck(null, Platform.TIME_MARK);
+      bhtest++;
+      // 280 ms/1000 here:
+      SequenceFeature copy = new SequenceFeature(sf, newBegin, newEnd, group, sf.getScore());
+      // 0.175 ms here:
       targetSequence.addSequenceFeature(copy);
 
       /*
        * for sequence_variant on reverse strand, have to convert the allele
        * values to their complements
        */
-      if (!forwardStrand && SequenceOntologyFactory.getInstance()
+      if (!forwardStrand && SequenceOntologyFactory.getSequenceOntology()
               .isA(sf.getType(), SequenceOntologyI.SEQUENCE_VARIANT))
       {
         reverseComplementAlleles(copy);
@@ -793,10 +838,14 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
     MapList mapping = getGenomicRangesFromFeatures(sourceSequence,
             accessionId, targetSequence.getStart());
     if (mapping == null)
-    {
+    { 
       return false;
     }
 
+
+    Platform.timeCheck("ESP. xfer " + sfs.size(), Platform.TIME_MARK);   
+
+
     boolean result = transferFeatures(sfs, targetSequence, mapping,
             accessionId);
 //    System.out.println("transferFeatures (" + (sfs.size()) + " --> "
@@ -830,14 +879,23 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
     SequenceFeatures.sortFeatures(sfs, forwardStrand);
 
     boolean transferred = false;
-    for (SequenceFeature sf : sfs)
+    
+    for (int i = 0, n = sfs.size(); i < n; i++)
     {
+
+//     if ((i%1000) == 0) {
+////               Platform.timeCheck("Feature " + bhtest, Platform.TIME_GET);
+//     Platform.timeCheck("ESP. xferFeature + " + (i) + "/" + n, Platform.TIME_MARK);    
+//     }
+
+      SequenceFeature sf = sfs.get(i);
       if (retainFeature(sf, parentId))
       {
         transferFeature(sf, targetSequence, mapping, forwardStrand);
         transferred = true;
       }
     }
+
     return transferred;
   }
 
@@ -915,10 +973,14 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
 
   /**
    * Answers true if the feature type is either 'NMD_transcript_variant' or
-   * 'transcript' or one of its sub-types in the Sequence Ontology. This is
-   * needed because NMD_transcript_variant behaves like 'transcript' in Ensembl
+   * 'transcript' (or one of its sub-types in the Sequence Ontology). This is
+   * because NMD_transcript_variant behaves like 'transcript' in Ensembl
    * although strictly speaking it is not (it is a sub-type of
    * sequence_variant).
+   * <p>
+   * (This test was needed when fetching transcript features as GFF. As we are
+   * now fetching as JSON, all features have type 'transcript' so the check for
+   * NMD_transcript_variant is redundant. Left in for any future case arising.)
    * 
    * @param featureType
    * @return
@@ -926,7 +988,7 @@ public abstract class EnsemblSeqProxy extends EnsemblRestClient
   public static boolean isTranscript(String featureType)
   {
     return SequenceOntologyI.NMD_TRANSCRIPT_VARIANT.equals(featureType)
-            || SequenceOntologyFactory.getInstance().isA(featureType,
+            || SequenceOntologyFactory.getSequenceOntology().isA(featureType,
                     SequenceOntologyI.TRANSCRIPT);
   }
 }