JAL-3829 provide both PDBe queries and 3D-Beacons queries in the filter combo box
[jalview.git] / src / jalview / gui / structurechooser / ThreeDBStructureChooserQuerySource.java
index 1c04d3a..d64d643 100644 (file)
@@ -36,6 +36,8 @@ public class ThreeDBStructureChooserQuerySource
         extends StructureChooserQuerySource
 {
 
+  private static final String FILTER_TDBEACONS_COVERAGE = "3d_beacons_coverage";
+
   private static int MAX_QLENGTH = 7820;
 
   protected FTSRestRequest lastTdbRequest;
@@ -51,7 +53,7 @@ public class ThreeDBStructureChooserQuerySource
             PreferenceSource.STRUCTURE_CHOOSER,
             TDBeaconsFTSRestClient.getInstance());
 
-  }
+  }  
 
   /**
    * Builds a query string for a given sequences using its DBRef entries 3d
@@ -153,11 +155,34 @@ public class ThreeDBStructureChooserQuerySource
           FilterOption selectedFilterOpt, boolean b) throws Exception
   {
     FTSRestResponse resultList;
+    if (tdBeaconsFilter(selectedFilterOpt.getValue())) {
     FTSRestRequest tdbRequest = getTDBeaconsRequest(seq, wantedFields);
     resultList = tdbRestClient.executeRequest(tdbRequest);
 
     lastTdbRequest = tdbRequest;
+    
+    // Query the PDB and add additional metadata
+    FTSRestResponse pdbResponse = fetchStructuresMetaDataFor(getPDBQuerySource(), resultList);
+    FTSRestResponse joinedResp = joinResponses(resultList,
+            pdbResponse);
     return resultList;
+    } 
+    // use the PDBFTS directly
+    resultList = getPDBQuerySource().fetchStructuresMetaData(seq, wantedFields, selectedFilterOpt, b);
+    lastTdbRequest = getPDBQuerySource().lastPdbRequest;
+    lastPdbRequest = lastTdbRequest; // both queries the same - indicates we rank using PDBe
+    return resultList;
+    
+  }
+
+  PDBStructureChooserQuerySource pdbQuerySource=null;
+  private PDBStructureChooserQuerySource getPDBQuerySource()
+  {
+    if (pdbQuerySource==null)
+    {
+      pdbQuerySource = new PDBStructureChooserQuerySource();
+    }
+    return pdbQuerySource;
   }
 
   private FTSRestRequest getTDBeaconsRequest(SequenceI seq,
@@ -180,36 +205,23 @@ public class ThreeDBStructureChooserQuerySource
   @Override
   public List<FilterOption> getAvailableFilterOptions(String VIEWS_FILTER)
   {
-    List<FilterOption> filters = new ArrayList<FilterOption>();
-    filters.add(
-            new FilterOption(MessageManager.getString("label.best_quality"),
-                    "overall_quality", VIEWS_FILTER, false));
-    filters.add(new FilterOption(
-            MessageManager.getString("label.best_resolution"), "resolution",
-            VIEWS_FILTER, false));
-    filters.add(new FilterOption(
-            MessageManager.getString("label.most_protein_chain"),
-            "number_of_protein_chains", VIEWS_FILTER, false));
-    filters.add(new FilterOption(
-            MessageManager.getString("label.most_bound_molecules"),
-            "number_of_bound_molecules", VIEWS_FILTER, false));
-    filters.add(new FilterOption(
-            MessageManager.getString("label.most_polymer_residues"),
-            "number_of_polymer_residues", VIEWS_FILTER, true));
-
+    List<FilterOption> filters = getPDBQuerySource().getAvailableFilterOptions(VIEWS_FILTER);
+    
+    filters.add(0,
+            new FilterOption("3D-Beacons Coverage",
+                    FILTER_TDBEACONS_COVERAGE, VIEWS_FILTER, true, this));
     return filters;
   }
+  private boolean tdBeaconsFilter(String fieldToFilterBy)
+  {
+    return FILTER_TDBEACONS_COVERAGE.equals(fieldToFilterBy);
+  }
 
-  /**
-   * 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" });
-
+  @Override
+  public boolean needsRefetch(FilterOption selectedFilterOpt)
+  {
+    return tdBeaconsFilter(selectedFilterOpt.getValue()) && lastPdbRequest!=lastTdbRequest;
+  }
   /**
    * FTSRestClient specific query builder to pick top ranked entry from a
    * fetchStructuresMetaData query
@@ -230,103 +242,26 @@ public class ThreeDBStructureChooserQuerySource
           Collection<FTSDataColumnI> wantedFields, String fieldToFilterBy,
           boolean b) throws Exception
   {
-
-    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)
-    {
-      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);
-      }
-    }
-    // sort according to decreasing length,
-    // increasing start
-    Collections.sort(filteredResponse, new Comparator<FTSData>()
+    if (tdBeaconsFilter(fieldToFilterBy))
     {
+      TDBResultAnalyser analyser = new TDBResultAnalyser(seq,
+              collectedResults, lastTdbRequest);
 
-      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;
-      }
+      FTSRestResponse resultList = new FTSRestResponse();
 
-      @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;
-        }
-      }
+      List<FTSData> filteredResponse = analyser.getFilteredResponse();
 
-      @Override
-      public boolean equals(Object obj)
-      {
-        return super.equals(obj);
-      }
-    });
-    FTSRestResponse resultList = new FTSRestResponse();
-    resultList.setNumberOfItemsFound(filteredResponse.size());
-    resultList.setSearchSummary(filteredResponse);
-    return resultList;
+      List<FTSData> selectedStructures = analyser
+              .selectStructures(filteredResponse);
+      resultList.setNumberOfItemsFound(selectedStructures.size());
+      resultList.setSearchSummary(selectedStructures);
+      return resultList;
+    }
+    // Fall back to PDBe rankings
+    return getPDBQuerySource().selectFirstRankedQuery(seq, collectedResults, wantedFields, fieldToFilterBy, b);
   }
 
+
   @Override
   public PDBEntry[] collectSelectedRows(JTable restable, int[] selectedRows,
           List<SequenceI> selectedSeqsToView)
@@ -340,8 +275,30 @@ public class ThreeDBStructureChooserQuerySource
     int typeColumnIndex = restable.getColumn("Provider").getModelIndex();
     int categoryColumnIndex = restable.getColumn("Model Category")
             .getModelIndex();
+    final int up_start_idx = restable.getColumn("Uniprot Start").getModelIndex();
+    final int up_end_idx = restable.getColumn("Uniprot End").getModelIndex();
+    int i=0;
+    
+    // bleugh!
+    Integer[] sellist = new Integer[selectedRows.length];
+    for (Integer row: selectedRows)
+    {
+      sellist[i++] = row;
+    }
+    // Sort rows by coverage
+    Arrays.sort(sellist,new Comparator<Integer>()
+    {
+      @Override
+      public int compare(Integer o1, Integer o2)
+      {
+        int o1_xt = ((Integer)restable.getValueAt(o1, up_end_idx)) - (Integer)restable.getValueAt(o1, up_start_idx);
+        int o2_xt = ((Integer)restable.getValueAt(o2, up_end_idx)) - (Integer)restable.getValueAt(o2, up_start_idx);
+        return o2_xt-o1_xt;
+      }
+    });
 
-    for (int row : selectedRows)
+    
+    for (int row : sellist)
     {
       // unique id - could be a horrible hash
 
@@ -440,27 +397,31 @@ public class ThreeDBStructureChooserQuerySource
     int idx_provider = getLastFTSRequest().getFieldIndex("Provider");
     // join on
     int idx_modelId = getLastFTSRequest().getFieldIndex("Model id");
-    int pdbIdx = lastPdbRequest.getFieldIndex("pdb_id");
-    for (FTSData row : upResponse.getSearchSummary())
+    int pdbIdx = lastPdbRequest.getFieldIndex("PDB Id");
+    int pdbTitle_idx = lastPdbRequest.getFieldIndex("Title");
+    int tdbTitle_idx = getLastFTSRequest().getFieldIndex("Title");
+    
+    List<FTSData> joinedRows = new ArrayList<FTSData>();
+    for (final FTSData row : upResponse.getSearchSummary())
     {
       String id = (String) row.getSummaryData()[idx_modelId];
       String provider = (String) row.getSummaryData()[idx_provider];
       if ("PDBe".equalsIgnoreCase(provider))
       {
-        for (FTSData pdbrow : pdbResponse.getSearchSummary())
+        for (final FTSData pdbrow : pdbResponse.getSearchSummary())
         {
           String pdbid = (String) pdbrow.getSummaryData()[pdbIdx];
           if (id.equalsIgnoreCase(pdbid))
           {
-            // often multiple entries per PDB ID so we bail after first
-            // get wanted fields
-            // append to FTSRestResponse array
+            row.getSummaryData()[tdbTitle_idx] = pdbrow
+                    .getSummaryData()[pdbTitle_idx];
           }
         }
+      } else {
+        row.getSummaryData()[tdbTitle_idx] = "Model from TDB";
       }
     }
-    // TODO Auto-generated method stub
-    return null;
+    return upResponse;
   }
 
 }
\ No newline at end of file