JAL-3829 allow client-side selection of structures for a sequence by passing in disco...
authorJim Procter <j.procter@dundee.ac.uk>
Wed, 8 Sep 2021 12:33:20 +0000 (13:33 +0100)
committerJim Procter <j.procter@dundee.ac.uk>
Wed, 8 Sep 2021 12:33:20 +0000 (13:33 +0100)
src/jalview/gui/StructureChooser.java
src/jalview/gui/structurechooser/PDBStructureChooserQuerySource.java
src/jalview/gui/structurechooser/StructureChooserQuerySource.java
src/jalview/gui/structurechooser/ThreeDBStructureChooserQuerySource.java
test/jalview/gui/structurechooser/StructureChooserQuerySourceTest.java

index a83adcb..55d0ba1 100644 (file)
@@ -352,7 +352,7 @@ public class StructureChooser extends GStructureChooser
           FTSRestResponse resultList;
           try
           {
-            resultList = data.selectFirstRankedQuery(seq, wantedFields,
+            resultList = data.selectFirstRankedQuery(seq, discoveredStructuresSet,wantedFields,
                     fieldToFilterBy, !chk_invertFilter.isSelected());
 
           } catch (Exception e)
index 75e7fc0..1c43bea 100644 (file)
@@ -272,7 +272,7 @@ public class PDBStructureChooserQuerySource
    * @return
    * @throws Exception
    */
-  public FTSRestResponse selectFirstRankedQuery(SequenceI seq,
+  public FTSRestResponse selectFirstRankedQuery(SequenceI seq, Collection<FTSData> collectedResults,
           Collection<FTSDataColumnI> wantedFields, String fieldToFilterBy,
           boolean b) throws Exception
   {
index 96b67e4..6a1c64f 100644 (file)
@@ -167,6 +167,7 @@ public abstract class StructureChooserQuerySource
    * 
    * @param seq
    *          - seq to generate a query for
+   * @param discoveredStructuresSet - existing set of entries - allows client side selection
    * @param wantedFields
    *          - fields to retrieve
    * @param selectedFilterOpt
@@ -177,7 +178,7 @@ public abstract class StructureChooserQuerySource
    * @throws Exception
    */
   public abstract FTSRestResponse selectFirstRankedQuery(SequenceI seq,
-          Collection<FTSDataColumnI> wantedFields, String fieldToFilterBy,
+          Collection<FTSData> discoveredStructuresSet, Collection<FTSDataColumnI> wantedFields, String fieldToFilterBy,
           boolean b) throws Exception;
 
   /**
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;
   }
 
index f492ce6..acedfed 100644 (file)
@@ -24,6 +24,7 @@ package jalview.gui.structurechooser;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertTrue;
 
+import java.util.Collection;
 import java.util.Vector;
 
 import org.junit.Assert;
@@ -38,6 +39,7 @@ import jalview.datamodel.DBRefSource;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceI;
+import jalview.fts.api.FTSData;
 import jalview.fts.core.FTSRestRequest;
 import jalview.fts.core.FTSRestResponse;
 import jalview.fts.service.pdb.PDBFTSRestClient;
@@ -260,6 +262,9 @@ public class StructureChooserQuerySourceTest
     
     try {
       upResponse = tdbquery.fetchStructuresMetaData(upSeq, tdbquery.getDocFieldPrefs().getStructureSummaryFields(),  null, false);
+      // test ranking without additional PDBe data
+      FTSRestResponse firstRanked = tdbquery.selectFirstRankedQuery(upSeq, upResponse.getSearchSummary(), tdbquery.getDocFieldPrefs().getStructureSummaryFields(), "", false);
+      assertTrue(firstRanked.getNumberOfItemsFound()==upResponse.getNumberOfItemsFound());
       // NB Could have race condition here 
       String pdb_Query = tdbquery.buildPDBFTSQueryFor(upResponse);
       assertTrue(pdb_Query.trim().length()>0);
@@ -268,6 +273,7 @@ public class StructureChooserQuerySourceTest
       FTSRestResponse joinedResp = tdbquery.joinResponses(upResponse, pdbResponse);
       assertEquals(upResponse.getNumberOfItemsFound(),joinedResp.getNumberOfItemsFound());
       
+      
     } catch (Exception x)
     {
       x.printStackTrace();