JAL-1668 added filtering and sorting capabilites
[jalview.git] / src / jalview / gui / StructureChooser.java
1 package jalview.gui;
2
3 import jalview.datamodel.DBRefEntry;
4 import jalview.datamodel.PDBEntry;
5 import jalview.datamodel.SequenceI;
6 import jalview.jbgui.GStructureChooser;
7 import jalview.util.MessageManager;
8 import jalview.ws.dbsources.PDBRestClient;
9 import jalview.ws.dbsources.PDBRestClient.PDBDocField;
10 import jalview.ws.uimodel.PDBSearchRequest;
11 import jalview.ws.uimodel.PDBSearchResponse;
12 import jalview.ws.uimodel.PDBSearchResponse.PDBResponseSummary;
13
14 import java.awt.Component;
15 import java.awt.event.ItemEvent;
16 import java.util.ArrayList;
17 import java.util.Collection;
18 import java.util.HashSet;
19 import java.util.List;
20
21 import javax.swing.JCheckBox;
22 import javax.swing.JOptionPane;
23 import javax.swing.JTable;
24 import javax.swing.ListSelectionModel;
25 import javax.swing.table.TableCellRenderer;
26 import javax.swing.table.TableColumnModel;
27
28 @SuppressWarnings("serial")
29 public class StructureChooser extends GStructureChooser
30 {
31
32   private boolean structuresWereFound = false;
33
34   private SequenceI selectedSequence;
35
36   private SequenceI[] selectedSequences;
37
38   IProgressIndicator af;
39
40   Collection<PDBResponseSummary> discoveredStructuresSet = new HashSet<PDBResponseSummary>();
41
42   public StructureChooser(AlignmentPanel ap, final SequenceI sequence)
43   {
44     this.ap = ap;
45     this.af = ap.alignFrame;
46     this.selectedSequence = sequence;
47     this.selectedSequences = ((ap.av.getSelectionGroup() == null) ? new SequenceI[]
48     { sequence }
49             : ap.av.getSequenceSelection());
50     init();
51   }
52
53   private void init()
54   {
55     Thread discPDBThread = new Thread(new Runnable()
56     {
57       @Override
58       public void run()
59       {
60         long startTime = System.currentTimeMillis();
61         af.setProgressBar(
62                 MessageManager.getString("status.fetching_db_refs"),
63                 startTime);
64
65         fetchStructures();
66         populateFilterOptions();
67         af.setProgressBar(null, startTime);
68         mainFrame.setVisible(true);
69         updateCurrentView();
70       }
71     });
72     discPDBThread.start();
73   }
74
75   private void fetchStructures()
76   {
77     long startTime = System.currentTimeMillis();
78     List<PDBDocField> wantedFields = new ArrayList<PDBDocField>();
79     // wantedFields.add(PDBDocField.MOLECULE_TYPE);
80     wantedFields.add(PDBDocField.PDB_ID);
81     // wantedFields.add(PDBDocField.GENUS);
82     // wantedFields.add(PDBDocField.GENE_NAME);
83     wantedFields.add(PDBDocField.TITLE);
84
85     PDBSearchRequest request = new PDBSearchRequest();
86     request.setAllowEmptySeq(false);
87     request.setResponseSize(500);
88     request.setFieldToSearchBy("(text:");
89     request.setWantedFields(wantedFields);
90
91     for (SequenceI seq : selectedSequences)
92     {
93       request.setSearchTerm(buildQuery(seq) + ")");
94       request.setAssociatedSequence(seq.getName());
95       PDBRestClient pdbRestCleint = new PDBRestClient();
96       PDBSearchResponse resultList = pdbRestCleint.executeRequest(request);
97       if (resultList.getSearchSummary() != null
98               && !resultList.getSearchSummary().isEmpty())
99       {
100         discoveredStructuresSet.addAll(resultList.getSearchSummary());
101       }
102     }
103
104     int noOfStructuresFound = 0;
105     if (discoveredStructuresSet != null)
106     {
107       jListFoundStructures.setModel(PDBSearchResponse
108               .getListModel(discoveredStructuresSet));
109       summaryTable.setModel(PDBSearchResponse.getTableModel(request,
110               discoveredStructuresSet));
111       // resizeColumnWidth(summaryTable);
112       structuresWereFound = true;
113       noOfStructuresFound = discoveredStructuresSet.size();
114     }
115     String totalTime = (System.currentTimeMillis() - startTime)
116             + " milli secs";
117     mainFrame.setTitle("Structure Chooser - " + noOfStructuresFound
118             + " Found (" + totalTime + ")");
119   }
120
121   public void resizeColumnWidth(JTable table)
122   {
123     // table.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
124     final TableColumnModel columnModel = table.getColumnModel();
125     for (int column = 0; column < table.getColumnCount(); column++)
126     {
127       int width = 50; // Min width
128       for (int row = 0; row < table.getRowCount(); row++)
129       {
130         TableCellRenderer renderer = table.getCellRenderer(row, column);
131         Component comp = table.prepareRenderer(renderer, row, column);
132         width = Math.max(comp.getPreferredSize().width, width);
133       }
134       columnModel.getColumn(column).setPreferredWidth(width);
135     }
136   }
137
138   protected void populateFilterOptions()
139   {
140     if (structuresWereFound)
141     {
142       filterOptionsComboBox.addItem(new FilterOptions("Best Quality",
143               PDBDocField.OVERALL_QUALITY.getCode(), VIEWS_FILTER));
144       filterOptionsComboBox.addItem(new FilterOptions(
145               "Best UniProt Coverage", PDBDocField.UNIPROT_COVERAGE
146                       .getCode(), VIEWS_FILTER));
147       filterOptionsComboBox.addItem(new FilterOptions("Highest Resolution",
148               PDBDocField.RESOLUTION.getCode(), VIEWS_FILTER));
149       filterOptionsComboBox.addItem(new FilterOptions(
150               "Highest Protein Chain", PDBDocField.PROTEIN_CHAIN_COUNT
151                       .getCode(), VIEWS_FILTER));
152       filterOptionsComboBox.addItem(new FilterOptions(
153               "Highest Bound Molecules", PDBDocField.BOUND_MOLECULE_COUNT
154                       .getCode(), VIEWS_FILTER));
155       filterOptionsComboBox.addItem(new FilterOptions(
156               "Highest Polymer Residues", PDBDocField.POLYMER_RESIDUE_COUNT
157                       .getCode(), VIEWS_FILTER));
158     }
159     filterOptionsComboBox.addItem(new FilterOptions("Enter PDB Id", "-",
160             VIEWS_ENTER_ID));
161     filterOptionsComboBox.addItem(new FilterOptions("From File", "-",
162             VIEWS_FROM_FILE));
163   }
164
165   private String buildQuery(SequenceI seq)
166   {
167     String query = seq.getName();
168     StringBuilder queryBuilder = new StringBuilder();
169     int count = 0;
170     if (seq.getDBRef() != null && seq.getDBRef().length != 0)
171     {
172       for (DBRefEntry dbRef : seq.getDBRef())
173       {
174         queryBuilder.append("text:").append(dbRef.getAccessionId())
175                 .append(" OR ");
176         ++count;
177         if (count > 10)
178         {
179           break;
180         }
181       }
182       int endIndex = queryBuilder.lastIndexOf(" OR ");
183       query = queryBuilder.toString().substring(5, endIndex);
184     }
185     return query;
186   }
187
188   protected void updateCurrentView()
189   {
190     FilterOptions currentOption = ((FilterOptions) filterOptionsComboBox
191             .getSelectedItem());
192     switchableViewsLayout.show(switchableViewsPanel,
193             currentOption.getView());
194     invertFilter.setEnabled(false);
195     if (currentOption.getView() == VIEWS_FILTER)
196     {
197       invertFilter.setEnabled(true);
198       filterResultSet(currentOption.getValue());
199     }
200   }
201
202   public void filterResultSet(final String fieldToFilterBy)
203   {
204     Thread filterThread = new Thread(new Runnable()
205     {
206       @Override
207       public void run()
208       {
209         try
210         {
211         loadingImageLabel.setVisible(true);
212         List<PDBDocField> wantedFields = new ArrayList<PDBDocField>();
213         // wantedFields.add(PDBDocField.MOLECULE_TYPE);
214         wantedFields.add(PDBDocField.PDB_ID);
215         // wantedFields.add(PDBDocField.GENUS);
216         // wantedFields.add(PDBDocField.GENE_NAME);
217         wantedFields.add(PDBDocField.TITLE);
218
219         PDBSearchRequest request = new PDBSearchRequest();
220         request.setAllowEmptySeq(false);
221         request.setResponseSize(1);
222         request.setFieldToSearchBy("(text:");
223         request.setFieldToSortBy(fieldToFilterBy,
224                 !invertFilter.isSelected());
225
226         request.setWantedFields(wantedFields);
227
228         Collection<PDBResponseSummary> filteredResponse = new HashSet<PDBResponseSummary>();
229         for (SequenceI seq : selectedSequences)
230         {
231           request.setSearchTerm(buildQuery(seq) + ")");
232           request.setAssociatedSequence(seq.getName());
233           PDBRestClient pdbRestCleint = new PDBRestClient();
234           PDBSearchResponse resultList = pdbRestCleint
235                   .executeRequest(request);
236           if (resultList.getSearchSummary() != null
237                   && !resultList.getSearchSummary().isEmpty())
238           {
239             filteredResponse.addAll(resultList.getSearchSummary());
240           }
241         }
242
243
244         if (filteredResponse != null)
245         {
246             //
247             // for (PDBResponseSummary s : filteredResponse)
248             // {
249             // System.out.println("-----------> " + s.getPdbId());
250             // }
251
252           int filterResponseCount = filteredResponse.size();
253           List<PDBResponseSummary> list = new ArrayList<PDBResponseSummary>(
254                   discoveredStructuresSet);
255           list.removeAll(filteredResponse);
256
257           Collection<PDBResponseSummary> newSet = new ArrayList<PDBResponseSummary>();
258           newSet.addAll(filteredResponse);
259           newSet.addAll(list);
260
261           jListFoundStructures.setModel(PDBSearchResponse
262                   .getListModel(newSet));
263           summaryTable.setModel(PDBSearchResponse.getTableModel(request,
264                   newSet));
265           // resizeColumnWidth(summaryTable);
266           list = null;
267           newSet = null;
268
269           int[] filterIndice = new int[filterResponseCount];
270           ListSelectionModel model = summaryTable.getSelectionModel();
271           model.clearSelection();
272           // int x = 0;
273           for (int x = 0; x < filterResponseCount; x++)
274           {
275             filterIndice[x] = x;
276             model.addSelectionInterval(x, x);
277           }
278           jListFoundStructures.setSelectedIndices(filterIndice);
279         }
280
281         loadingImageLabel.setVisible(false);
282         } catch (Exception e)
283         {
284           e.printStackTrace();
285         }
286       }
287     });
288     filterThread.start();
289
290   }
291
292   @Override
293   protected void stateChanged(ItemEvent e)
294   {
295     if (e.getSource() instanceof JCheckBox)
296     {
297       updateCurrentView();
298     }
299     else
300     {
301       if (e.getStateChange() == ItemEvent.SELECTED)
302       {
303         updateCurrentView();
304       }
305     }
306
307   }
308
309   @Override
310   public void ok_ActionPerformed()
311   {
312     // TODO code to load selected structures to jmol or chimera
313   }
314
315   public void pdbFromFile_actionPerformed()
316   {
317     jalview.io.JalviewFileChooser chooser = new jalview.io.JalviewFileChooser(
318             jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
319     chooser.setFileView(new jalview.io.JalviewFileView());
320     chooser.setDialogTitle(MessageManager.formatMessage(
321             "label.select_pdb_file_for", new String[]
322             { selectedSequence.getDisplayId(false) }));
323     chooser.setToolTipText(MessageManager.formatMessage(
324             "label.load_pdb_file_associate_with_sequence", new String[]
325             { selectedSequence.getDisplayId(false) }));
326
327     int value = chooser.showOpenDialog(null);
328
329     if (value == jalview.io.JalviewFileChooser.APPROVE_OPTION)
330     {
331       String choice = chooser.getSelectedFile().getPath();
332       jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice);
333       new AssociatePdbFileWithSeq().associatePdbWithSeq(choice,
334               jalview.io.AppletFormatAdapter.FILE, selectedSequence, true,
335               Desktop.instance);
336     }
337
338   }
339
340   // rpdbview.addActionListener(new ActionListener()
341   // {
342   //
343   // @Override
344   // public void actionPerformed(ActionEvent e)
345   // {
346   // new StructureViewer(ap.getStructureSelectionManager())
347   // .viewStructures(ap, pr, ap.av.collateForPDB(pr));
348   // }
349   // });
350
351   public void enterPDB_actionPerformed()
352   {
353     String id = JOptionPane.showInternalInputDialog(Desktop.desktop,
354             MessageManager.getString("label.enter_pdb_id"),
355             MessageManager.getString("label.enter_pdb_id"),
356             JOptionPane.QUESTION_MESSAGE);
357     if (id != null && id.length() > 0)
358     {
359       PDBEntry entry = new PDBEntry();
360       entry.setId(id.toUpperCase());
361       selectedSequence.getDatasetSequence().addPDBId(entry);
362     }
363   }
364
365 }