2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2)
3 * Copyright (C) 2014 The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
24 import jalview.datamodel.DBRefEntry;
25 import jalview.datamodel.PDBEntry;
26 import jalview.datamodel.SequenceI;
27 import jalview.jbgui.GStructureChooser;
28 import jalview.jbgui.PDBDocFieldPreferences;
29 import jalview.util.MessageManager;
30 import jalview.ws.dbsources.PDBRestClient;
31 import jalview.ws.dbsources.PDBRestClient.PDBDocField;
32 import jalview.ws.uimodel.PDBRestRequest;
33 import jalview.ws.uimodel.PDBRestResponse;
34 import jalview.ws.uimodel.PDBRestResponse.PDBResponseSummary;
36 import java.awt.event.ItemEvent;
37 import java.util.ArrayList;
38 import java.util.Collection;
39 import java.util.HashSet;
40 import java.util.List;
41 import java.util.Vector;
43 import javax.swing.JCheckBox;
44 import javax.swing.JComboBox;
45 import javax.swing.ListSelectionModel;
48 * Provides the behaviors for the Structure chooser Panel
53 @SuppressWarnings("serial")
54 public class StructureChooser extends GStructureChooser
56 private boolean structuresDiscovered = false;
58 private SequenceI selectedSequence;
60 private SequenceI[] selectedSequences;
62 private IProgressIndicator progressIndicator;
64 private Collection<PDBResponseSummary> discoveredStructuresSet = new HashSet<PDBResponseSummary>();
66 private PDBRestRequest pdbRequest;
68 private PDBRestClient pdbRestCleint;
70 private String selectedPdbFileName;
72 private boolean isValidPBDEntry;
74 public StructureChooser(SequenceI[] selectedSeqs, SequenceI selectedSeq,
78 this.selectedSequence = selectedSeq;
79 this.selectedSequences = selectedSeqs;
80 this.progressIndicator = (ap == null) ? null : ap.alignFrame;
85 * Initializes parameters used by the Structure Chooser Panel
89 Thread discoverPDBStructuresThread = new Thread(new Runnable()
94 long startTime = System.currentTimeMillis();
95 String msg = MessageManager.getString("status.fetching_db_refs");
96 updateProgressIndicator(msg, startTime);
97 fetchStructuresMetaData();
98 populateFilterComboBox();
99 updateProgressIndicator(null, startTime);
100 mainFrame.setVisible(true);
104 discoverPDBStructuresThread.start();
108 * Updates the progress indicator with the specified message
111 * displayed message for the operation
113 * unique handle for this indicator
115 public void updateProgressIndicator(String message, long id)
117 if (progressIndicator != null)
119 progressIndicator.setProgressBar(message, id);
124 * Retrieve meta-data for all the structure(s) for a given sequence(s) in a
127 public void fetchStructuresMetaData()
129 long startTime = System.currentTimeMillis();
130 Collection<PDBDocField> wantedFields = PDBDocFieldPreferences
131 .getStructureSummaryFields();
133 pdbRequest = new PDBRestRequest();
134 pdbRequest.setAllowEmptySeq(false);
135 pdbRequest.setResponseSize(500);
136 pdbRequest.setFieldToSearchBy("(text:");
137 pdbRequest.setWantedFields(wantedFields);
138 for (SequenceI seq : selectedSequences)
140 pdbRequest.setSearchTerm(buildQuery(seq) + ")");
141 pdbRequest.setAssociatedSequence(seq.getName());
142 pdbRestCleint = new PDBRestClient();
143 PDBRestResponse resultList = pdbRestCleint.executeRequest(pdbRequest);
144 if (resultList.getSearchSummary() != null
145 && !resultList.getSearchSummary().isEmpty())
147 discoveredStructuresSet.addAll(resultList.getSearchSummary());
148 updateSequenceDbRef(seq, resultList.getSearchSummary());
152 int noOfStructuresFound = 0;
153 if (discoveredStructuresSet != null
154 && !discoveredStructuresSet.isEmpty())
156 tbl_summary.setModel(PDBRestResponse.getTableModel(pdbRequest,
157 discoveredStructuresSet));
158 structuresDiscovered = true;
159 noOfStructuresFound = discoveredStructuresSet.size();
161 String totalTime = (System.currentTimeMillis() - startTime)
163 mainFrame.setTitle("Structure Chooser - " + noOfStructuresFound
164 + " Found (" + totalTime + ")");
168 * Update the DBRef entry for a given sequence with values retrieved from
172 * the Sequence to update its DBRef entry
173 * @param responseSummaries
174 * a collection of PDBResponseSummary
176 public void updateSequenceDbRef(SequenceI seq,
177 Collection<PDBResponseSummary> responseSummaries)
179 for (PDBResponseSummary response : responseSummaries)
181 PDBEntry newEntry = new PDBEntry();
182 newEntry.setId(response.getPdbId());
183 newEntry.setType("PDB");
184 seq.getDatasetSequence().addPDBId(newEntry);
189 * Builds a query string for a given sequences using its DBRef entries
192 * the sequences to build a query for
193 * @return the built query string
195 @SuppressWarnings("unchecked")
196 public static String buildQuery(SequenceI seq)
198 String query = seq.getName();
199 StringBuilder queryBuilder = new StringBuilder();
202 if (seq.getPDBId() != null)
204 for (PDBEntry entry : (Vector<PDBEntry>) seq.getPDBId())
206 queryBuilder.append("text:").append(entry.getId()).append(" OR ");
210 if (seq.getDBRef() != null && seq.getDBRef().length != 0)
212 for (DBRefEntry dbRef : seq.getDBRef())
214 queryBuilder.append("text:")
215 .append(dbRef.getAccessionId().replaceAll("GO:", ""))
223 int endIndex = queryBuilder.lastIndexOf(" OR ");
224 query = queryBuilder.toString().substring(5, endIndex);
230 * Filters a given list of discovered structures based on supplied argument
232 * @param fieldToFilterBy
233 * the field to filter by
235 public void filterResultSet(final String fieldToFilterBy)
237 Thread filterThread = new Thread(new Runnable()
242 long startTime = System.currentTimeMillis();
245 lbl_loading.setVisible(true);
246 pdbRequest.setResponseSize(1);
247 pdbRequest.setFieldToSearchBy("(text:");
248 pdbRequest.setFieldToSortBy(fieldToFilterBy,
249 !chk_invertFilter.isSelected());
251 Collection<PDBResponseSummary> filteredResponse = new HashSet<PDBResponseSummary>();
252 for (SequenceI seq : selectedSequences)
254 pdbRequest.setSearchTerm(buildQuery(seq) + ")");
255 pdbRequest.setAssociatedSequence(seq.getName());
256 pdbRestCleint = new PDBRestClient();
257 PDBRestResponse resultList = pdbRestCleint
258 .executeRequest(pdbRequest);
259 if (resultList.getSearchSummary() != null
260 && !resultList.getSearchSummary().isEmpty())
262 filteredResponse.addAll(resultList.getSearchSummary());
266 if (filteredResponse != null)
268 int filterResponseCount = filteredResponse.size();
269 List<PDBResponseSummary> originalDiscoveredStructuresList = new ArrayList<PDBResponseSummary>(
270 discoveredStructuresSet);
271 originalDiscoveredStructuresList.removeAll(filteredResponse);
272 Collection<PDBResponseSummary> reorderedStructuresSet = new ArrayList<PDBResponseSummary>();
273 reorderedStructuresSet.addAll(filteredResponse);
274 reorderedStructuresSet.addAll(originalDiscoveredStructuresList);
276 tbl_summary.setModel(PDBRestResponse.getTableModel(pdbRequest,
277 reorderedStructuresSet));
279 ListSelectionModel model = tbl_summary.getSelectionModel();
280 model.clearSelection();
281 for (int x = 0; x < filterResponseCount; x++)
283 model.addSelectionInterval(x, x);
286 // Discard unwanted objects to make them eligible for garbage
288 originalDiscoveredStructuresList = null;
289 reorderedStructuresSet = null;
292 lbl_loading.setVisible(false);
293 } catch (Exception e)
297 String totalTime = (System.currentTimeMillis() - startTime)
299 mainFrame.setTitle("Structure Chooser - Filter time (" + totalTime
302 validateSelections();
305 filterThread.start();
311 * Handles action event for btn_pdbFromFile
313 public void pdbFromFile_actionPerformed()
315 jalview.io.JalviewFileChooser chooser = new jalview.io.JalviewFileChooser(
316 jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
317 chooser.setFileView(new jalview.io.JalviewFileView());
318 chooser.setDialogTitle(MessageManager.formatMessage(
319 "label.select_pdb_file_for", new String[]
320 { selectedSequence.getDisplayId(false) }));
321 chooser.setToolTipText(MessageManager.formatMessage(
322 "label.load_pdb_file_associate_with_sequence", new String[]
323 { selectedSequence.getDisplayId(false) }));
325 int value = chooser.showOpenDialog(null);
326 if (value == jalview.io.JalviewFileChooser.APPROVE_OPTION)
328 selectedPdbFileName = chooser.getSelectedFile().getPath();
329 jalview.bin.Cache.setProperty("LAST_DIRECTORY", selectedPdbFileName);
330 validateSelections();
335 * Populates the filter combo-box options dynamically depending on discovered
338 protected void populateFilterComboBox()
340 if (isStructuresDiscovered())
342 cmb_filterOption.addItem(new FilterOption("Best Quality",
343 PDBDocField.OVERALL_QUALITY.getCode(), VIEWS_FILTER));
344 cmb_filterOption.addItem(new FilterOption("Best UniProt Coverage",
345 PDBDocField.UNIPROT_COVERAGE.getCode(), VIEWS_FILTER));
346 cmb_filterOption.addItem(new FilterOption("Highest Resolution",
347 PDBDocField.RESOLUTION.getCode(), VIEWS_FILTER));
348 cmb_filterOption.addItem(new FilterOption("Highest Protein Chain",
349 PDBDocField.PROTEIN_CHAIN_COUNT.getCode(), VIEWS_FILTER));
350 cmb_filterOption.addItem(new FilterOption("Highest Bound Molecules",
351 PDBDocField.BOUND_MOLECULE_COUNT.getCode(), VIEWS_FILTER));
352 cmb_filterOption.addItem(new FilterOption("Highest Polymer Residues",
353 PDBDocField.POLYMER_RESIDUE_COUNT.getCode(), VIEWS_FILTER));
355 cmb_filterOption.addItem(new FilterOption("Enter PDB Id", "-",
357 cmb_filterOption.addItem(new FilterOption("From File", "-",
362 * Updates the displayed view based on the selected filter option
364 protected void updateCurrentView()
366 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
368 layout_switchableViews.show(pnl_switchableViews,
369 selectedFilterOpt.getView());
370 String filterTitle = mainFrame.getTitle();
371 mainFrame.setTitle(frameTitle);
372 chk_invertFilter.setVisible(false);
373 if (selectedFilterOpt.getView() == VIEWS_FILTER)
375 mainFrame.setTitle(filterTitle);
376 chk_invertFilter.setVisible(true);
377 filterResultSet(selectedFilterOpt.getValue());
381 idInputAssSeqPanel.loadCmbAssSeq();
382 fileChooserAssSeqPanel.loadCmbAssSeq();
384 validateSelections();
388 * Validates user selection and activates the view button if all parameters
391 public void validateSelections()
393 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
395 btn_view.setEnabled(false);
396 String currentView = selectedFilterOpt.getView();
397 if (currentView == VIEWS_FILTER)
399 if (tbl_summary.getSelectedRows().length > 0)
401 btn_view.setEnabled(true);
404 else if (currentView == VIEWS_ENTER_ID)
406 validateAssociationEnterPdb();
408 else if (currentView == VIEWS_FROM_FILE)
410 validateAssociationFromFile();
416 * Validates inputs from the Manual PDB entry panel
418 public void validateAssociationEnterPdb()
420 AssociateSeqOptions assSeqOpt = (AssociateSeqOptions) idInputAssSeqPanel
421 .getCmb_assSeq().getSelectedItem();
422 lbl_pdbManualFetchStatus.setIcon(errorImage);
423 if (selectedSequences.length == 1
424 || !assSeqOpt.getName().equalsIgnoreCase(
425 "-Select Associated Seq-"))
427 txt_search.setEnabled(true);
430 btn_view.setEnabled(true);
431 lbl_pdbManualFetchStatus.setIcon(goodImage);
436 txt_search.setEnabled(false);
437 lbl_pdbManualFetchStatus.setIcon(errorImage);
442 * Validates inputs for the manual PDB file selection options
444 public void validateAssociationFromFile()
446 AssociateSeqOptions assSeqOpt = (AssociateSeqOptions) fileChooserAssSeqPanel
447 .getCmb_assSeq().getSelectedItem();
448 lbl_fromFileStatus.setIcon(errorImage);
449 if (selectedSequences.length == 1
450 || (assSeqOpt != null
451 && !assSeqOpt.getName().equalsIgnoreCase(
452 "-Select Associated Seq-")))
454 btn_pdbFromFile.setEnabled(true);
455 if (selectedPdbFileName != null && selectedPdbFileName.length() > 0)
457 btn_view.setEnabled(true);
458 lbl_fromFileStatus.setIcon(goodImage);
463 btn_pdbFromFile.setEnabled(false);
464 lbl_fromFileStatus.setIcon(errorImage);
469 public void cmbAssSeqStateChanged()
471 validateSelections();
475 * Handles the state change event for the 'filter' combo-box and 'invert'
479 protected void stateChanged(ItemEvent e)
481 if (e.getSource() instanceof JCheckBox)
487 if (e.getStateChange() == ItemEvent.SELECTED)
496 * Handles action event for btn_ok
499 public void ok_ActionPerformed()
501 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
503 String currentView = selectedFilterOpt.getView();
504 if (currentView == VIEWS_FILTER)
506 int pdbIdCol = PDBRestClient.getPDBIdColumIndex(
507 pdbRequest.getWantedFields(), true);
508 int[] selectedRows = tbl_summary.getSelectedRows();
509 PDBEntry[] pdbEntriesToView = new PDBEntry[selectedRows.length];
511 for (int summaryRow : selectedRows)
513 String pdbIdStr = tbl_summary.getValueAt(summaryRow, pdbIdCol)
515 PDBEntry pdbEntry = new PDBEntry();
516 pdbEntry.setId(pdbIdStr);
517 pdbEntry.setType("PDB");
518 pdbEntriesToView[count++] = pdbEntry;
520 new StructureViewer(ap.getStructureSelectionManager())
521 .viewStructures(ap, pdbEntriesToView,
522 ap.av.collateForPDB(pdbEntriesToView));
524 else if (currentView == VIEWS_ENTER_ID)
526 selectedSequence = ((AssociateSeqOptions) idInputAssSeqPanel
527 .getCmb_assSeq().getSelectedItem()).getSequence();
528 PDBEntry pdbEntry = new PDBEntry();
529 pdbEntry.setId(txt_search.getText());
530 pdbEntry.setType("PDB");
531 selectedSequence.getDatasetSequence().addPDBId(pdbEntry);
532 PDBEntry[] pdbEntriesToView = new PDBEntry[]
534 new StructureViewer(ap.getStructureSelectionManager())
535 .viewStructures(ap, pdbEntriesToView,
536 ap.av.collateForPDB(pdbEntriesToView));
538 else if (currentView == VIEWS_FROM_FILE)
540 selectedSequence = ((AssociateSeqOptions) fileChooserAssSeqPanel
541 .getCmb_assSeq().getSelectedItem()).getSequence();
542 new AssociatePdbFileWithSeq().associatePdbWithSeq(
543 selectedPdbFileName, jalview.io.AppletFormatAdapter.FILE,
544 selectedSequence, true, Desktop.instance);
550 * Populates the combo-box used in associating manually fetched structures to
551 * a unique sequence when more than one sequence selection is made.
553 public void populateCmbAssociateSeqOptions(
554 JComboBox<AssociateSeqOptions> cmb_assSeq)
556 cmb_assSeq.removeAllItems();
557 cmb_assSeq.addItem(new AssociateSeqOptions("-Select Associated Seq-",
559 // cmb_assSeq.addItem(new AssociateSeqOptions("Auto Detect", null));
560 if (selectedSequences.length > 1)
562 for (SequenceI seq : selectedSequences)
564 cmb_assSeq.addItem(new AssociateSeqOptions(seq));
569 cmb_assSeq.setVisible(false);
573 public boolean isStructuresDiscovered()
575 return structuresDiscovered;
578 public void setStructuresDiscovered(boolean structuresDiscovered)
580 this.structuresDiscovered = structuresDiscovered;
583 public Collection<PDBResponseSummary> getDiscoveredStructuresSet()
585 return discoveredStructuresSet;
589 protected void txt_search_ActionPerformed()
591 isValidPBDEntry = false;
592 if (txt_search.getText().length() > 0)
594 List<PDBDocField> wantedFields = new ArrayList<PDBDocField>();
595 wantedFields.add(PDBDocField.PDB_ID);
596 pdbRequest = new PDBRestRequest();
597 pdbRequest.setAllowEmptySeq(false);
598 pdbRequest.setResponseSize(1);
599 pdbRequest.setFieldToSearchBy("(pdb_id:");
600 pdbRequest.setWantedFields(wantedFields);
601 pdbRequest.setSearchTerm(txt_search.getText() + ")");
602 pdbRequest.setAssociatedSequence(selectedSequence.getName());
603 pdbRestCleint = new PDBRestClient();
604 PDBRestResponse resultList = pdbRestCleint.executeRequest(pdbRequest);
605 if (resultList.getSearchSummary() != null
606 && resultList.getSearchSummary().size() > 0)
608 isValidPBDEntry = true;
611 validateSelections();