JAL-3829 allow client-side selection of structures for a sequence by passing in disco...
[jalview.git] / src / jalview / gui / structurechooser / ThreeDBStructureChooserQuerySource.java
index b3242de..1c04d3a 100644 (file)
@@ -1,7 +1,10 @@
 package jalview.gui.structurechooser;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashSet;
 import java.util.LinkedHashSet;
 import java.util.List;
@@ -198,6 +201,16 @@ public class ThreeDBStructureChooserQuerySource
   }
 
   /**
+   * model categories - update as needed. warnings output if unknown types
+   * encountered.
+   * 
+   * Order denotes 'trust'
+   */
+  private static List<String> EXP_CATEGORIES = Arrays
+          .asList(new String[]
+          { "EXPERIMENTALLY DETERMINED", "DEEP LEARNING", "TEMPLATE-BASED" });
+
+  /**
    * FTSRestClient specific query builder to pick top ranked entry from a
    * fetchStructuresMetaData query
    * 
@@ -213,22 +226,104 @@ public class ThreeDBStructureChooserQuerySource
    * @throws Exception
    */
   public FTSRestResponse selectFirstRankedQuery(SequenceI seq,
+          Collection<FTSData> collectedResults,
           Collection<FTSDataColumnI> wantedFields, String fieldToFilterBy,
           boolean b) throws Exception
   {
 
-    FTSRestResponse resultList;
-    FTSRestRequest pdbRequest = getTDBeaconsRequest(seq, wantedFields);
-    if (pdbRequest == null)
+    List<FTSData> filteredResponse = new ArrayList<FTSData>();
+    final int idx_ups = lastTdbRequest.getFieldIndex("Uniprot Start");
+    final int idx_upe = lastTdbRequest.getFieldIndex("Uniprot End");
+    final int idx_mcat = lastTdbRequest.getFieldIndex("Model Category");
+    final int idx_mqual = lastTdbRequest.getFieldIndex("Qmean");
+    final int idx_resol = lastTdbRequest.getFieldIndex("Resolution");
+
+    // ignore anything outside the sequence region
+    for (FTSData row : collectedResults)
     {
-      return null;
+      int up_s = (Integer) row.getSummaryData()[idx_ups];
+      int up_e = (Integer) row.getSummaryData()[idx_upe];
+
+      if (seq == row.getSummaryData()[0] && up_e > seq.getStart()
+              && up_s < seq.getEnd())
+      {
+        filteredResponse.add(row);
+      }
     }
-    pdbRequest.setResponseSize(1);
-    resultList = tdbRestClient.executeRequest(pdbRequest);
+    // sort according to decreasing length,
+    // increasing start
+    Collections.sort(filteredResponse, new Comparator<FTSData>()
+    {
+
+      private final int scoreCategory(String cat)
+      {
+        // TODO: make quicker
+        int idx = EXP_CATEGORIES.indexOf(cat.toUpperCase());
+        if (idx == -1)
+        {
+          System.out.println("Unknown category: '" + cat + "'");
+        }
+        return -EXP_CATEGORIES.size() - idx;
+      }
 
-    // TODO: client side filtering - sort results and pick top one (or N)
+      @Override
+      public int compare(FTSData o1, FTSData o2)
+      {
+        int o1_s = (Integer) o1.getSummaryData()[idx_ups];
+        int o1_e = (Integer) o1.getSummaryData()[idx_upe];
+        int o1_cat = scoreCategory((String) o1.getSummaryData()[idx_mcat]);
+        int o2_s = (Integer) o2.getSummaryData()[idx_ups];
+        int o2_e = (Integer) o2.getSummaryData()[idx_upe];
+        int o2_cat = scoreCategory((String) o2.getSummaryData()[idx_mcat]);
+
+        if (o1_cat == o2_cat)
+        {
+          if (o1_s == o2_s)
+          {
+            int o1_xtent = o1_e - o1_s;
+            int o2_xtent = o2_e - o2_s;
+            if (o1_xtent == o2_xtent)
+            {
+              if (o1_cat == scoreCategory(EXP_CATEGORIES.get(0)))
+              {
+                // experimental structures, so rank on quality
+                double o1_res = (Double) o1.getSummaryData()[idx_resol];
+                double o2_res = (Double) o2.getSummaryData()[idx_resol];
+                return (o2_res < o1_res) ? 1 : (o2_res == o1_res) ? 0 : -1;
+              }
+              else
+              {
+                // models, so rank on qmean
+                float o1_mq = (Float) o1.getSummaryData()[idx_mqual];
+                float o2_mq = (Float) o2.getSummaryData()[idx_mqual];
+                return (o2_mq < o1_mq) ? 1 : (o2_mq == o1_mq) ? 0 : -1;
+              }
+            }
+            else
+            {
+              return o1_xtent - o2_xtent;
+            }
+          }
+          else
+          {
+            return o1_s - o2_s;
+          }
+        }
+        else
+        {
+          return o2_cat - o1_cat;
+        }
+      }
 
-    lastTdbRequest = pdbRequest;
+      @Override
+      public boolean equals(Object obj)
+      {
+        return super.equals(obj);
+      }
+    });
+    FTSRestResponse resultList = new FTSRestResponse();
+    resultList.setNumberOfItemsFound(filteredResponse.size());
+    resultList.setSearchSummary(filteredResponse);
     return resultList;
   }