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.util.MessageManager;
29 import jalview.ws.dbsources.PDBRestClient;
30 import jalview.ws.dbsources.PDBRestClient.PDBDocField;
31 import jalview.ws.uimodel.PDBRestRequest;
32 import jalview.ws.uimodel.PDBRestResponse;
33 import jalview.ws.uimodel.PDBRestResponse.PDBResponseSummary;
35 import java.awt.event.ItemEvent;
36 import java.util.ArrayList;
37 import java.util.Collection;
38 import java.util.HashSet;
39 import java.util.List;
40 import java.util.Vector;
42 import javax.swing.JCheckBox;
43 import javax.swing.JComboBox;
44 import javax.swing.ListSelectionModel;
47 * Provides the behaviors for the Structure chooser Panel
52 @SuppressWarnings("serial")
53 public class StructureChooser extends GStructureChooser
55 private boolean structuresDiscovered = false;
57 private SequenceI selectedSequence;
59 private SequenceI[] selectedSequences;
61 private IProgressIndicator progressIndicator;
63 private Collection<PDBResponseSummary> discoveredStructuresSet = new HashSet<PDBResponseSummary>();
65 private PDBRestRequest pdbRequest;
67 private PDBRestClient pdbRestCleint;
69 private String selectedPdbFileName;
71 private boolean isValidPBDEntry;
73 public StructureChooser(SequenceI[] selectedSeqs, SequenceI selectedSeq,
77 this.selectedSequence = selectedSeq;
78 this.selectedSequences = selectedSeqs;
79 this.progressIndicator = (ap == null) ? null : ap.alignFrame;
84 * Initializes parameters used by the Structure Chooser Panel
88 Thread discoverPDBStructuresThread = new Thread(new Runnable()
93 long startTime = System.currentTimeMillis();
94 String msg = MessageManager.getString("status.fetching_db_refs");
95 updateProgressIndicator(msg, startTime);
96 fetchStructuresMetaData();
97 populateFilterComboBox();
98 updateProgressIndicator(null, startTime);
99 mainFrame.setVisible(true);
103 discoverPDBStructuresThread.start();
107 * Updates the progress indicator with the specified message
110 * displayed message for the operation
112 * unique handle for this indicator
114 public void updateProgressIndicator(String message, long id)
116 if (progressIndicator != null)
118 progressIndicator.setProgressBar(message, id);
123 * Retrieve meta-data for all the structure(s) for a given sequence(s) in a
126 public void fetchStructuresMetaData()
128 long startTime = System.currentTimeMillis();
129 List<PDBDocField> wantedFields = new ArrayList<PDBDocField>();
130 // wantedFields.add(PDBDocField.MOLECULE_TYPE);
131 wantedFields.add(PDBDocField.PDB_ID);
132 // wantedFields.add(PDBDocField.GENUS);
133 // wantedFields.add(PDBDocField.GENE_NAME);
134 wantedFields.add(PDBDocField.TITLE);
135 pdbRequest = new PDBRestRequest();
136 pdbRequest.setAllowEmptySeq(false);
137 pdbRequest.setResponseSize(500);
138 pdbRequest.setFieldToSearchBy("(text:");
139 pdbRequest.setWantedFields(wantedFields);
140 for (SequenceI seq : selectedSequences)
142 pdbRequest.setSearchTerm(buildQuery(seq) + ")");
143 pdbRequest.setAssociatedSequence(seq.getName());
144 pdbRestCleint = new PDBRestClient();
145 PDBRestResponse resultList = pdbRestCleint.executeRequest(pdbRequest);
146 if (resultList.getSearchSummary() != null
147 && !resultList.getSearchSummary().isEmpty())
149 discoveredStructuresSet.addAll(resultList.getSearchSummary());
150 updateSequenceDbRef(seq, resultList.getSearchSummary());
154 int noOfStructuresFound = 0;
155 if (discoveredStructuresSet != null
156 && !discoveredStructuresSet.isEmpty())
158 tbl_summary.setModel(PDBRestResponse.getTableModel(pdbRequest,
159 discoveredStructuresSet));
160 structuresDiscovered = true;
161 noOfStructuresFound = discoveredStructuresSet.size();
163 String totalTime = (System.currentTimeMillis() - startTime)
165 mainFrame.setTitle("Structure Chooser - " + noOfStructuresFound
166 + " Found (" + totalTime + ")");
170 * Update the DBRef entry for a given sequence with values retrieved from
174 * the Sequence to update its DBRef entry
175 * @param responseSummaries
176 * a collection of PDBResponseSummary
178 public void updateSequenceDbRef(SequenceI seq,
179 Collection<PDBResponseSummary> responseSummaries)
181 for (PDBResponseSummary response : responseSummaries)
183 PDBEntry newEntry = new PDBEntry();
184 newEntry.setId(response.getPdbId());
185 newEntry.setType("PDB");
186 seq.getDatasetSequence().addPDBId(newEntry);
191 * Builds a query string for a given sequences using its DBRef entries
194 * the sequences to build a query for
195 * @return the built query string
197 @SuppressWarnings("unchecked")
198 public static String buildQuery(SequenceI seq)
200 String query = seq.getName();
201 StringBuilder queryBuilder = new StringBuilder();
204 if (seq.getPDBId() != null)
206 for (PDBEntry entry : (Vector<PDBEntry>) seq.getPDBId())
208 queryBuilder.append("text:").append(entry.getId()).append(" OR ");
212 if (seq.getDBRef() != null && seq.getDBRef().length != 0)
214 for (DBRefEntry dbRef : seq.getDBRef())
216 queryBuilder.append("text:")
217 .append(dbRef.getAccessionId().replaceAll("GO:", ""))
225 int endIndex = queryBuilder.lastIndexOf(" OR ");
226 query = queryBuilder.toString().substring(5, endIndex);
232 * Filters a given list of discovered structures based on supplied argument
234 * @param fieldToFilterBy
235 * the field to filter by
237 public void filterResultSet(final String fieldToFilterBy)
239 Thread filterThread = new Thread(new Runnable()
244 long startTime = System.currentTimeMillis();
247 lbl_loading.setVisible(true);
248 pdbRequest.setResponseSize(1);
249 pdbRequest.setFieldToSearchBy("(text:");
250 pdbRequest.setFieldToSortBy(fieldToFilterBy,
251 !chk_invertFilter.isSelected());
253 Collection<PDBResponseSummary> filteredResponse = new HashSet<PDBResponseSummary>();
254 for (SequenceI seq : selectedSequences)
256 pdbRequest.setSearchTerm(buildQuery(seq) + ")");
257 pdbRequest.setAssociatedSequence(seq.getName());
258 pdbRestCleint = new PDBRestClient();
259 PDBRestResponse resultList = pdbRestCleint
260 .executeRequest(pdbRequest);
261 if (resultList.getSearchSummary() != null
262 && !resultList.getSearchSummary().isEmpty())
264 filteredResponse.addAll(resultList.getSearchSummary());
268 if (filteredResponse != null)
270 int filterResponseCount = filteredResponse.size();
271 List<PDBResponseSummary> originalDiscoveredStructuresList = new ArrayList<PDBResponseSummary>(
272 discoveredStructuresSet);
273 originalDiscoveredStructuresList.removeAll(filteredResponse);
274 Collection<PDBResponseSummary> reorderedStructuresSet = new ArrayList<PDBResponseSummary>();
275 reorderedStructuresSet.addAll(filteredResponse);
276 reorderedStructuresSet.addAll(originalDiscoveredStructuresList);
278 tbl_summary.setModel(PDBRestResponse.getTableModel(pdbRequest,
279 reorderedStructuresSet));
281 ListSelectionModel model = tbl_summary.getSelectionModel();
282 model.clearSelection();
283 for (int x = 0; x < filterResponseCount; x++)
285 model.addSelectionInterval(x, x);
288 // Discard unwanted objects to make them eligible for garbage
290 originalDiscoveredStructuresList = null;
291 reorderedStructuresSet = null;
294 lbl_loading.setVisible(false);
295 } catch (Exception e)
299 String totalTime = (System.currentTimeMillis() - startTime)
301 mainFrame.setTitle("Structure Chooser - Filter time (" + totalTime
304 validateSelections();
307 filterThread.start();
311 * Determines the column index for the pdb id in the summary table. The pdb id
312 * serves as a unique identifier for a given row in the summary table
314 * @param wantedFeilds
315 * the available table columns in no particular order
316 * @return the pdb id field column index
318 public static int getPDBIdColumIndex(Collection<PDBDocField> wantedFeilds)
320 int pdbFeildIndex = 1;
321 for (PDBDocField feild : wantedFeilds)
323 if (feild.equals(PDBDocField.PDB_ID))
329 return pdbFeildIndex;
333 * Handles action event for btn_pdbFromFile
335 public void pdbFromFile_actionPerformed()
337 jalview.io.JalviewFileChooser chooser = new jalview.io.JalviewFileChooser(
338 jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
339 chooser.setFileView(new jalview.io.JalviewFileView());
340 chooser.setDialogTitle(MessageManager.formatMessage(
341 "label.select_pdb_file_for", new String[]
342 { selectedSequence.getDisplayId(false) }));
343 chooser.setToolTipText(MessageManager.formatMessage(
344 "label.load_pdb_file_associate_with_sequence", new String[]
345 { selectedSequence.getDisplayId(false) }));
347 int value = chooser.showOpenDialog(null);
348 if (value == jalview.io.JalviewFileChooser.APPROVE_OPTION)
350 selectedPdbFileName = chooser.getSelectedFile().getPath();
351 jalview.bin.Cache.setProperty("LAST_DIRECTORY", selectedPdbFileName);
352 validateSelections();
357 * Populates the filter combo-box options dynamically depending on discovered
360 protected void populateFilterComboBox()
362 if (isStructuresDiscovered())
364 cmb_filterOption.addItem(new FilterOption("Best Quality",
365 PDBDocField.OVERALL_QUALITY.getCode(), VIEWS_FILTER));
366 cmb_filterOption.addItem(new FilterOption("Best UniProt Coverage",
367 PDBDocField.UNIPROT_COVERAGE.getCode(), VIEWS_FILTER));
368 cmb_filterOption.addItem(new FilterOption("Highest Resolution",
369 PDBDocField.RESOLUTION.getCode(), VIEWS_FILTER));
370 cmb_filterOption.addItem(new FilterOption("Highest Protein Chain",
371 PDBDocField.PROTEIN_CHAIN_COUNT.getCode(), VIEWS_FILTER));
372 cmb_filterOption.addItem(new FilterOption("Highest Bound Molecules",
373 PDBDocField.BOUND_MOLECULE_COUNT.getCode(), VIEWS_FILTER));
374 cmb_filterOption.addItem(new FilterOption("Highest Polymer Residues",
375 PDBDocField.POLYMER_RESIDUE_COUNT.getCode(), VIEWS_FILTER));
377 cmb_filterOption.addItem(new FilterOption("Enter PDB Id", "-",
379 cmb_filterOption.addItem(new FilterOption("From File", "-",
384 * Updates the displayed view based on the selected filter option
386 protected void updateCurrentView()
388 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
390 layout_switchableViews.show(pnl_switchableViews,
391 selectedFilterOpt.getView());
392 String filterTitle = mainFrame.getTitle();
393 mainFrame.setTitle(frameTitle);
394 chk_invertFilter.setVisible(false);
395 if (selectedFilterOpt.getView() == VIEWS_FILTER)
397 mainFrame.setTitle(filterTitle);
398 chk_invertFilter.setVisible(true);
399 filterResultSet(selectedFilterOpt.getValue());
403 idInputAssSeqPanel.loadCmbAssSeq();
404 fileChooserAssSeqPanel.loadCmbAssSeq();
406 validateSelections();
410 * Validates user selection and activates the view button if all parameters
413 public void validateSelections()
415 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
417 btn_view.setEnabled(false);
418 String currentView = selectedFilterOpt.getView();
419 if (currentView == VIEWS_FILTER)
421 if (tbl_summary.getSelectedRows().length > 0)
423 btn_view.setEnabled(true);
426 else if (currentView == VIEWS_ENTER_ID)
428 validateAssociationEnterPdb();
430 else if (currentView == VIEWS_FROM_FILE)
432 validateAssociationFromFile();
438 * Validates inputs from the Manual PDB entry panel
440 public void validateAssociationEnterPdb()
442 AssociateSeqOptions assSeqOpt = (AssociateSeqOptions) idInputAssSeqPanel
443 .getCmb_assSeq().getSelectedItem();
444 lbl_pdbManualFetchStatus.setIcon(errorImage);
445 if (selectedSequences.length == 1
446 || !assSeqOpt.getName().equalsIgnoreCase(
447 "-Select Associated Seq-"))
449 txt_search.setEnabled(true);
452 btn_view.setEnabled(true);
453 lbl_pdbManualFetchStatus.setIcon(goodImage);
458 txt_search.setEnabled(false);
459 lbl_pdbManualFetchStatus.setIcon(errorImage);
464 * Validates inputs for the manual PDB file selection options
466 public void validateAssociationFromFile()
468 AssociateSeqOptions assSeqOpt = (AssociateSeqOptions) fileChooserAssSeqPanel
469 .getCmb_assSeq().getSelectedItem();
470 lbl_fromFileStatus.setIcon(errorImage);
471 if (selectedSequences.length == 1
472 || (assSeqOpt != null
473 && !assSeqOpt.getName().equalsIgnoreCase(
474 "-Select Associated Seq-")))
476 btn_pdbFromFile.setEnabled(true);
477 if (selectedPdbFileName != null && selectedPdbFileName.length() > 0)
479 btn_view.setEnabled(true);
480 lbl_fromFileStatus.setIcon(goodImage);
485 btn_pdbFromFile.setEnabled(false);
486 lbl_fromFileStatus.setIcon(errorImage);
491 public void cmbAssSeqStateChanged()
493 validateSelections();
497 * Handles the state change event for the 'filter' combo-box and 'invert'
501 protected void stateChanged(ItemEvent e)
503 if (e.getSource() instanceof JCheckBox)
509 if (e.getStateChange() == ItemEvent.SELECTED)
518 * Handles action event for btn_ok
521 public void ok_ActionPerformed()
523 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
525 String currentView = selectedFilterOpt.getView();
526 if (currentView == VIEWS_FILTER)
528 int pdbIdCol = getPDBIdColumIndex(pdbRequest.getWantedFields());
529 int[] selectedRows = tbl_summary.getSelectedRows();
530 PDBEntry[] pdbEntriesToView = new PDBEntry[selectedRows.length];
532 for (int summaryRow : selectedRows)
534 String pdbIdStr = tbl_summary.getValueAt(summaryRow, pdbIdCol)
536 PDBEntry pdbEntry = new PDBEntry();
537 pdbEntry.setId(pdbIdStr);
538 pdbEntry.setType("PDB");
539 pdbEntriesToView[count++] = pdbEntry;
541 new StructureViewer(ap.getStructureSelectionManager())
542 .viewStructures(ap, pdbEntriesToView,
543 ap.av.collateForPDB(pdbEntriesToView));
545 else if (currentView == VIEWS_ENTER_ID)
547 selectedSequence = ((AssociateSeqOptions) idInputAssSeqPanel
548 .getCmb_assSeq().getSelectedItem()).getSequence();
549 PDBEntry pdbEntry = new PDBEntry();
550 pdbEntry.setId(txt_search.getText());
551 pdbEntry.setType("PDB");
552 selectedSequence.getDatasetSequence().addPDBId(pdbEntry);
553 PDBEntry[] pdbEntriesToView = new PDBEntry[]
555 new StructureViewer(ap.getStructureSelectionManager())
556 .viewStructures(ap, pdbEntriesToView,
557 ap.av.collateForPDB(pdbEntriesToView));
559 else if (currentView == VIEWS_FROM_FILE)
561 selectedSequence = ((AssociateSeqOptions) fileChooserAssSeqPanel
562 .getCmb_assSeq().getSelectedItem()).getSequence();
563 new AssociatePdbFileWithSeq().associatePdbWithSeq(
564 selectedPdbFileName, jalview.io.AppletFormatAdapter.FILE,
565 selectedSequence, true, Desktop.instance);
571 * Populates the combo-box used in associating manually fetched structures to
572 * a unique sequence when more than one sequence selection is made.
574 public void populateCmbAssociateSeqOptions(
575 JComboBox<AssociateSeqOptions> cmb_assSeq)
577 cmb_assSeq.removeAllItems();
578 cmb_assSeq.addItem(new AssociateSeqOptions("-Select Associated Seq-",
580 // cmb_assSeq.addItem(new AssociateSeqOptions("Auto Detect", null));
581 if (selectedSequences.length > 1)
583 for (SequenceI seq : selectedSequences)
585 cmb_assSeq.addItem(new AssociateSeqOptions(seq));
590 cmb_assSeq.setVisible(false);
594 public boolean isStructuresDiscovered()
596 return structuresDiscovered;
599 public void setStructuresDiscovered(boolean structuresDiscovered)
601 this.structuresDiscovered = structuresDiscovered;
604 public Collection<PDBResponseSummary> getDiscoveredStructuresSet()
606 return discoveredStructuresSet;
610 protected void txt_search_ActionPerformed()
612 isValidPBDEntry = false;
613 if (txt_search.getText().length() > 0)
615 List<PDBDocField> wantedFields = new ArrayList<PDBDocField>();
616 wantedFields.add(PDBDocField.PDB_ID);
617 pdbRequest = new PDBRestRequest();
618 pdbRequest.setAllowEmptySeq(false);
619 pdbRequest.setResponseSize(1);
620 pdbRequest.setFieldToSearchBy("(pdb_id:");
621 pdbRequest.setWantedFields(wantedFields);
622 pdbRequest.setSearchTerm(txt_search.getText() + ")");
623 pdbRequest.setAssociatedSequence(selectedSequence.getName());
624 pdbRestCleint = new PDBRestClient();
625 PDBRestResponse resultList = pdbRestCleint.executeRequest(pdbRequest);
626 if (resultList.getSearchSummary() != null
627 && resultList.getSearchSummary().size() > 0)
629 isValidPBDEntry = true;
632 validateSelections();