JAL-1668 added filtering and sorting capabilites
[jalview.git] / src / jalview / gui / StructureChooser.java
index 07e36ec..9abf22f 100644 (file)
@@ -6,194 +6,162 @@ import jalview.datamodel.SequenceI;
 import jalview.jbgui.GStructureChooser;
 import jalview.util.MessageManager;
 import jalview.ws.dbsources.PDBRestClient;
+import jalview.ws.dbsources.PDBRestClient.PDBDocField;
 import jalview.ws.uimodel.PDBSearchRequest;
 import jalview.ws.uimodel.PDBSearchResponse;
-import jalview.ws.uimodel.PDBSummaryListModel;
-import jalview.ws.uimodel.PDBSummaryListModel.PDBDocField;
+import jalview.ws.uimodel.PDBSearchResponse.PDBResponseSummary;
 
+import java.awt.Component;
+import java.awt.event.ItemEvent;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
 
+import javax.swing.JCheckBox;
 import javax.swing.JOptionPane;
-import javax.swing.SwingUtilities;
+import javax.swing.JTable;
+import javax.swing.ListSelectionModel;
+import javax.swing.table.TableCellRenderer;
+import javax.swing.table.TableColumnModel;
 
 @SuppressWarnings("serial")
 public class StructureChooser extends GStructureChooser
 {
 
+  private boolean structuresWereFound = false;
 
-  private SequenceI sequence;
+  private SequenceI selectedSequence;
 
+  private SequenceI[] selectedSequences;
 
-  public StructureChooser(AlignmentPanel ap, final SequenceI sequence)
-  {
-    this.ap = ap;
-    this.sequence = sequence;
-    fetchStructures();
-  }
+  IProgressIndicator af;
 
-  @Override
-  public void ok_ActionPerformed()
-  {
-    jListFoundStructures.setSelectedValue("op1x", true);
-  }
+  Collection<PDBResponseSummary> discoveredStructuresSet = new HashSet<PDBResponseSummary>();
 
-  public void pdbFromFile_actionPerformed()
-  {
-    jalview.io.JalviewFileChooser chooser = new jalview.io.JalviewFileChooser(
-            jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
-    chooser.setFileView(new jalview.io.JalviewFileView());
-    chooser.setDialogTitle(MessageManager.formatMessage(
-            "label.select_pdb_file_for", new String[]
-            { sequence.getDisplayId(false) }));
-    chooser.setToolTipText(MessageManager.formatMessage(
-            "label.load_pdb_file_associate_with_sequence", new String[]
-            { sequence.getDisplayId(false) }));
-
-    int value = chooser.showOpenDialog(null);
-
-    if (value == jalview.io.JalviewFileChooser.APPROVE_OPTION)
-    {
-      String choice = chooser.getSelectedFile().getPath();
-      jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice);
-      new AssociatePdbFileWithSeq().associatePdbWithSeq(choice,
-              jalview.io.AppletFormatAdapter.FILE, sequence, true,
-              Desktop.instance);
-    }
-
-  }
-
-  public void discoverPDB_actionPerformed()
+  public StructureChooser(AlignmentPanel ap, final SequenceI sequence)
   {
-
-    final SequenceI[] sequences = ((ap.av.getSelectionGroup() == null) ? new SequenceI[]
+    this.ap = ap;
+    this.af = ap.alignFrame;
+    this.selectedSequence = sequence;
+    this.selectedSequences = ((ap.av.getSelectionGroup() == null) ? new SequenceI[]
     { sequence }
             : ap.av.getSequenceSelection());
-    Thread discpdb = new Thread(new Runnable()
-    {
-      @Override
-      public void run()
-      {
-
-        new jalview.ws.DBRefFetcher(sequences, ap.alignFrame)
-                .fetchDBRefs(false);
-      }
-
-    });
-    discpdb.start();
+    init();
   }
 
-  // rpdbview.addActionListener(new ActionListener()
-  // {
-  //
-  // @Override
-  // public void actionPerformed(ActionEvent e)
-  // {
-  // new StructureViewer(ap.getStructureSelectionManager())
-  // .viewStructures(ap, pr, ap.av.collateForPDB(pr));
-  // }
-  // });
-
-  public void enterPDB_actionPerformed()
-  {
-    String id = JOptionPane.showInternalInputDialog(Desktop.desktop,
-            MessageManager.getString("label.enter_pdb_id"),
-            MessageManager.getString("label.enter_pdb_id"),
-            JOptionPane.QUESTION_MESSAGE);
-    if (id != null && id.length() > 0)
-    {
-      PDBEntry entry = new PDBEntry();
-      entry.setId(id.toUpperCase());
-      sequence.getDatasetSequence().addPDBId(entry);
-    }
-  }
-
-  public static void main(String[] args)
+  private void init()
   {
-    SwingUtilities.invokeLater(new Runnable()
+    Thread discPDBThread = new Thread(new Runnable()
     {
+      @Override
       public void run()
       {
-        new StructureChooser(null, null);
+        long startTime = System.currentTimeMillis();
+        af.setProgressBar(
+                MessageManager.getString("status.fetching_db_refs"),
+                startTime);
+
+        fetchStructures();
+        populateFilterOptions();
+        af.setProgressBar(null, startTime);
+        mainFrame.setVisible(true);
+        updateCurrentView();
       }
     });
-  }
-
-  @SuppressWarnings("unchecked")
-  protected void populateFilterOptions()
-  {
-    filterOptions.addItem(new FilterOptions("- Filter Criteria -", "",
-            VIEWS_AUTO));
-    filterOptions.addItem(new FilterOptions("All", "all", VIEWS_AUTO));
-    filterOptions
-            .addItem(new FilterOptions("Best Coverage", "", VIEWS_AUTO));
-    filterOptions.addItem(new FilterOptions("Best Resolution", "",
-            VIEWS_AUTO));
-    filterOptions
-            .addItem(new FilterOptions("Best Quality", "", VIEWS_AUTO));
-    filterOptions.addItem(new FilterOptions("Enter PDB Id", "", VIEWS_ID));
-    filterOptions.addItem(new FilterOptions("From File", "", VIEWS_FILE));
-  }
-
-  protected void updateCurrentView()
-  {
-    String currentView = ((FilterOptions) filterOptions.getSelectedItem())
-            .getView();
-    switchableViewsLayout.show(switchableViewsPanel, currentView);
+    discPDBThread.start();
   }
 
   private void fetchStructures()
   {
     long startTime = System.currentTimeMillis();
-    final SequenceI[] sequences = ((ap.av.getSelectionGroup() == null) ? new SequenceI[]
-    { sequence }
-            : ap.av.getSequenceSelection());
-    int foundStructures = 0;
-    PDBSearchRequest request = new PDBSearchRequest();
-    request.setAllowEmptySeq(false);
-    request.setResponseSize(500);
-    request.setSearchTarget("(text:");
     List<PDBDocField> wantedFields = new ArrayList<PDBDocField>();
-    wantedFields.add(PDBDocField.MOLECULE_TYPE);
+    // wantedFields.add(PDBDocField.MOLECULE_TYPE);
     wantedFields.add(PDBDocField.PDB_ID);
-    wantedFields.add(PDBDocField.GENUS);
-    wantedFields.add(PDBDocField.GENE_NAME);
+    // wantedFields.add(PDBDocField.GENUS);
+    // wantedFields.add(PDBDocField.GENE_NAME);
     wantedFields.add(PDBDocField.TITLE);
+
+    PDBSearchRequest request = new PDBSearchRequest();
+    request.setAllowEmptySeq(false);
+    request.setResponseSize(500);
+    request.setFieldToSearchBy("(text:");
     request.setWantedFields(wantedFields);
-    
-    Collection<PDBSummaryListModel> searchSummaries = new HashSet<PDBSummaryListModel>();
-    // searchSummaries.
-    for (SequenceI seq : sequences)
+
+    for (SequenceI seq : selectedSequences)
     {
-      // System.out.println("Selected : " + seq.getName());
       request.setSearchTerm(buildQuery(seq) + ")");
-
+      request.setAssociatedSequence(seq.getName());
       PDBRestClient pdbRestCleint = new PDBRestClient();
-
-      PDBSearchResponse resultList = pdbRestCleint
-              .executeRequest(request);
+      PDBSearchResponse resultList = pdbRestCleint.executeRequest(request);
       if (resultList.getSearchSummary() != null
               && !resultList.getSearchSummary().isEmpty())
       {
-        searchSummaries.addAll(resultList.getSearchSummary());
+        discoveredStructuresSet.addAll(resultList.getSearchSummary());
       }
     }
 
-    foundStructures = searchSummaries.size();
-    if (searchSummaries != null)
+    int noOfStructuresFound = 0;
+    if (discoveredStructuresSet != null)
     {
       jListFoundStructures.setModel(PDBSearchResponse
-              .getListModel(searchSummaries));
+              .getListModel(discoveredStructuresSet));
+      summaryTable.setModel(PDBSearchResponse.getTableModel(request,
+              discoveredStructuresSet));
+      // resizeColumnWidth(summaryTable);
+      structuresWereFound = true;
+      noOfStructuresFound = discoveredStructuresSet.size();
     }
-
     String totalTime = (System.currentTimeMillis() - startTime)
             + " milli secs";
-    mainFrame.setTitle("Structure Chooser - " + foundStructures
+    mainFrame.setTitle("Structure Chooser - " + noOfStructuresFound
             + " Found (" + totalTime + ")");
   }
 
+  public void resizeColumnWidth(JTable table)
+  {
+    // table.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
+    final TableColumnModel columnModel = table.getColumnModel();
+    for (int column = 0; column < table.getColumnCount(); column++)
+    {
+      int width = 50; // Min width
+      for (int row = 0; row < table.getRowCount(); row++)
+      {
+        TableCellRenderer renderer = table.getCellRenderer(row, column);
+        Component comp = table.prepareRenderer(renderer, row, column);
+        width = Math.max(comp.getPreferredSize().width, width);
+      }
+      columnModel.getColumn(column).setPreferredWidth(width);
+    }
+  }
+
+  protected void populateFilterOptions()
+  {
+    if (structuresWereFound)
+    {
+      filterOptionsComboBox.addItem(new FilterOptions("Best Quality",
+              PDBDocField.OVERALL_QUALITY.getCode(), VIEWS_FILTER));
+      filterOptionsComboBox.addItem(new FilterOptions(
+              "Best UniProt Coverage", PDBDocField.UNIPROT_COVERAGE
+                      .getCode(), VIEWS_FILTER));
+      filterOptionsComboBox.addItem(new FilterOptions("Highest Resolution",
+              PDBDocField.RESOLUTION.getCode(), VIEWS_FILTER));
+      filterOptionsComboBox.addItem(new FilterOptions(
+              "Highest Protein Chain", PDBDocField.PROTEIN_CHAIN_COUNT
+                      .getCode(), VIEWS_FILTER));
+      filterOptionsComboBox.addItem(new FilterOptions(
+              "Highest Bound Molecules", PDBDocField.BOUND_MOLECULE_COUNT
+                      .getCode(), VIEWS_FILTER));
+      filterOptionsComboBox.addItem(new FilterOptions(
+              "Highest Polymer Residues", PDBDocField.POLYMER_RESIDUE_COUNT
+                      .getCode(), VIEWS_FILTER));
+    }
+    filterOptionsComboBox.addItem(new FilterOptions("Enter PDB Id", "-",
+            VIEWS_ENTER_ID));
+    filterOptionsComboBox.addItem(new FilterOptions("From File", "-",
+            VIEWS_FROM_FILE));
+  }
+
   private String buildQuery(SequenceI seq)
   {
     String query = seq.getName();
@@ -203,7 +171,6 @@ public class StructureChooser extends GStructureChooser
     {
       for (DBRefEntry dbRef : seq.getDBRef())
       {
-        System.out.println("dbref : " + dbRef.getAccessionId());
         queryBuilder.append("text:").append(dbRef.getAccessionId())
                 .append(" OR ");
         ++count;
@@ -212,62 +179,187 @@ public class StructureChooser extends GStructureChooser
           break;
         }
       }
-      // int beginIndex = queryBuilder. firstIndexOf("text");
       int endIndex = queryBuilder.lastIndexOf(" OR ");
       query = queryBuilder.toString().substring(5, endIndex);
     }
-    System.out.println("------------> " + query);
     return query;
   }
 
-  public class FilterOptions
+  protected void updateCurrentView()
   {
-    private String name;
-
-    private String value;
-
-    private String view;
-
-    public FilterOptions(String name, String value, String view)
+    FilterOptions currentOption = ((FilterOptions) filterOptionsComboBox
+            .getSelectedItem());
+    switchableViewsLayout.show(switchableViewsPanel,
+            currentOption.getView());
+    invertFilter.setEnabled(false);
+    if (currentOption.getView() == VIEWS_FILTER)
     {
-      this.name = name;
-      this.value = value;
-      this.view = view;
+      invertFilter.setEnabled(true);
+      filterResultSet(currentOption.getValue());
     }
+  }
 
-    public String getName()
+  public void filterResultSet(final String fieldToFilterBy)
+  {
+    Thread filterThread = new Thread(new Runnable()
     {
-      return name;
-    }
+      @Override
+      public void run()
+      {
+        try
+        {
+        loadingImageLabel.setVisible(true);
+        List<PDBDocField> wantedFields = new ArrayList<PDBDocField>();
+        // wantedFields.add(PDBDocField.MOLECULE_TYPE);
+        wantedFields.add(PDBDocField.PDB_ID);
+        // wantedFields.add(PDBDocField.GENUS);
+        // wantedFields.add(PDBDocField.GENE_NAME);
+        wantedFields.add(PDBDocField.TITLE);
+
+        PDBSearchRequest request = new PDBSearchRequest();
+        request.setAllowEmptySeq(false);
+        request.setResponseSize(1);
+        request.setFieldToSearchBy("(text:");
+        request.setFieldToSortBy(fieldToFilterBy,
+                !invertFilter.isSelected());
+
+        request.setWantedFields(wantedFields);
+
+        Collection<PDBResponseSummary> filteredResponse = new HashSet<PDBResponseSummary>();
+        for (SequenceI seq : selectedSequences)
+        {
+          request.setSearchTerm(buildQuery(seq) + ")");
+          request.setAssociatedSequence(seq.getName());
+          PDBRestClient pdbRestCleint = new PDBRestClient();
+          PDBSearchResponse resultList = pdbRestCleint
+                  .executeRequest(request);
+          if (resultList.getSearchSummary() != null
+                  && !resultList.getSearchSummary().isEmpty())
+          {
+            filteredResponse.addAll(resultList.getSearchSummary());
+          }
+        }
 
-    public void setName(String name)
-    {
-      this.name = name;
-    }
 
-    public String getValue()
-    {
-      return value;
-    }
+        if (filteredResponse != null)
+        {
+            //
+            // for (PDBResponseSummary s : filteredResponse)
+            // {
+            // System.out.println("-----------> " + s.getPdbId());
+            // }
+
+          int filterResponseCount = filteredResponse.size();
+          List<PDBResponseSummary> list = new ArrayList<PDBResponseSummary>(
+                  discoveredStructuresSet);
+          list.removeAll(filteredResponse);
+
+          Collection<PDBResponseSummary> newSet = new ArrayList<PDBResponseSummary>();
+          newSet.addAll(filteredResponse);
+          newSet.addAll(list);
+
+          jListFoundStructures.setModel(PDBSearchResponse
+                  .getListModel(newSet));
+          summaryTable.setModel(PDBSearchResponse.getTableModel(request,
+                  newSet));
+          // resizeColumnWidth(summaryTable);
+          list = null;
+          newSet = null;
+
+          int[] filterIndice = new int[filterResponseCount];
+          ListSelectionModel model = summaryTable.getSelectionModel();
+          model.clearSelection();
+          // int x = 0;
+          for (int x = 0; x < filterResponseCount; x++)
+          {
+            filterIndice[x] = x;
+            model.addSelectionInterval(x, x);
+          }
+          jListFoundStructures.setSelectedIndices(filterIndice);
+        }
+
+        loadingImageLabel.setVisible(false);
+        } catch (Exception e)
+        {
+          e.printStackTrace();
+        }
+      }
+    });
+    filterThread.start();
+
+  }
 
-    public void setValue(String value)
+  @Override
+  protected void stateChanged(ItemEvent e)
+  {
+    if (e.getSource() instanceof JCheckBox)
     {
-      this.value = value;
+      updateCurrentView();
     }
-
-    public String getView()
+    else
     {
-      return view;
+      if (e.getStateChange() == ItemEvent.SELECTED)
+      {
+        updateCurrentView();
+      }
     }
 
-    public void setView(String view)
+  }
+
+  @Override
+  public void ok_ActionPerformed()
+  {
+    // TODO code to load selected structures to jmol or chimera
+  }
+
+  public void pdbFromFile_actionPerformed()
+  {
+    jalview.io.JalviewFileChooser chooser = new jalview.io.JalviewFileChooser(
+            jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
+    chooser.setFileView(new jalview.io.JalviewFileView());
+    chooser.setDialogTitle(MessageManager.formatMessage(
+            "label.select_pdb_file_for", new String[]
+            { selectedSequence.getDisplayId(false) }));
+    chooser.setToolTipText(MessageManager.formatMessage(
+            "label.load_pdb_file_associate_with_sequence", new String[]
+            { selectedSequence.getDisplayId(false) }));
+
+    int value = chooser.showOpenDialog(null);
+
+    if (value == jalview.io.JalviewFileChooser.APPROVE_OPTION)
     {
-      this.view = view;
+      String choice = chooser.getSelectedFile().getPath();
+      jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice);
+      new AssociatePdbFileWithSeq().associatePdbWithSeq(choice,
+              jalview.io.AppletFormatAdapter.FILE, selectedSequence, true,
+              Desktop.instance);
     }
 
-    public String toString()
+  }
+
+  // rpdbview.addActionListener(new ActionListener()
+  // {
+  //
+  // @Override
+  // public void actionPerformed(ActionEvent e)
+  // {
+  // new StructureViewer(ap.getStructureSelectionManager())
+  // .viewStructures(ap, pr, ap.av.collateForPDB(pr));
+  // }
+  // });
+
+  public void enterPDB_actionPerformed()
+  {
+    String id = JOptionPane.showInternalInputDialog(Desktop.desktop,
+            MessageManager.getString("label.enter_pdb_id"),
+            MessageManager.getString("label.enter_pdb_id"),
+            JOptionPane.QUESTION_MESSAGE);
+    if (id != null && id.length() > 0)
     {
-      return this.name;
+      PDBEntry entry = new PDBEntry();
+      entry.setId(id.toUpperCase());
+      selectedSequence.getDatasetSequence().addPDBId(entry);
     }
   }
+
 }