/* * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2) * Copyright (C) 2014 The Jalview Authors * * This file is part of Jalview. * * Jalview is free software: you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation, either version 3 * of the License, or (at your option) any later version. * * Jalview is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Jalview. If not, see . * The Jalview Authors are detailed in the 'AUTHORS' file. */ package jalview.gui; import jalview.datamodel.DBRefEntry; import jalview.datamodel.PDBEntry; import jalview.datamodel.SequenceI; import jalview.jbgui.GStructureChooser; import jalview.jbgui.PDBDocFieldPreferences; import jalview.util.MessageManager; import jalview.ws.dbsources.PDBRestClient; import jalview.ws.dbsources.PDBRestClient.PDBDocField; import jalview.ws.uimodel.PDBRestRequest; import jalview.ws.uimodel.PDBRestResponse; import jalview.ws.uimodel.PDBRestResponse.PDBResponseSummary; import java.awt.event.ItemEvent; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Vector; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JLabel; /** * Provides the behaviors for the Structure chooser Panel * * @author tcnofoegbu * */ @SuppressWarnings("serial") public class StructureChooser extends GStructureChooser { private boolean structuresDiscovered = false; private SequenceI selectedSequence; private SequenceI[] selectedSequences; private IProgressIndicator progressIndicator; private Collection discoveredStructuresSet; private PDBRestRequest lastPdbRequest; private PDBRestClient pdbRestCleint; private String selectedPdbFileName; private boolean isValidPBDEntry; public StructureChooser(SequenceI[] selectedSeqs, SequenceI selectedSeq, AlignmentPanel ap) { this.ap = ap; this.selectedSequence = selectedSeq; this.selectedSequences = selectedSeqs; this.progressIndicator = (ap == null) ? null : ap.alignFrame; init(); } /** * Initializes parameters used by the Structure Chooser Panel */ public void init() { Thread discoverPDBStructuresThread = new Thread(new Runnable() { @Override public void run() { long startTime = System.currentTimeMillis(); String msg = MessageManager.getString("status.fetching_db_refs"); updateProgressIndicator(msg, startTime); fetchStructuresMetaData(); populateFilterComboBox(); updateProgressIndicator(null, startTime); mainFrame.setVisible(true); updateCurrentView(); } }); discoverPDBStructuresThread.start(); } /** * Updates the progress indicator with the specified message * * @param message * displayed message for the operation * @param id * unique handle for this indicator */ public void updateProgressIndicator(String message, long id) { if (progressIndicator != null) { progressIndicator.setProgressBar(message, id); } } /** * Retrieve meta-data for all the structure(s) for a given sequence(s) in a * selection group */ public void fetchStructuresMetaData() { long startTime = System.currentTimeMillis(); Collection wantedFields = PDBDocFieldPreferences .getStructureSummaryFields(); discoveredStructuresSet = new LinkedHashSet(); for (SequenceI seq : selectedSequences) { PDBRestRequest pdbRequest = new PDBRestRequest(); pdbRequest.setAllowEmptySeq(false); pdbRequest.setResponseSize(500); pdbRequest.setFieldToSearchBy("(text:"); pdbRequest.setWantedFields(wantedFields); pdbRequest.setSearchTerm(buildQuery(seq) + ")"); pdbRequest.setAssociatedSequence(seq.getName()); pdbRestCleint = new PDBRestClient(); PDBRestResponse resultList = pdbRestCleint.executeRequest(pdbRequest); lastPdbRequest = pdbRequest; if (resultList.getSearchSummary() != null && !resultList.getSearchSummary().isEmpty()) { discoveredStructuresSet.addAll(resultList.getSearchSummary()); updateSequenceDbRef(seq, resultList.getSearchSummary()); } } int noOfStructuresFound = 0; if (discoveredStructuresSet != null && !discoveredStructuresSet.isEmpty()) { tbl_summary.setModel(PDBRestResponse.getTableModel(lastPdbRequest, discoveredStructuresSet)); structuresDiscovered = true; noOfStructuresFound = discoveredStructuresSet.size(); } String totalTime = (System.currentTimeMillis() - startTime) + " milli secs"; mainFrame.setTitle("Structure Chooser - " + noOfStructuresFound + " Found (" + totalTime + ")"); } /** * Update the DBRef entry for a given sequence with values retrieved from * PDBResponseSummary * * @param seq * the Sequence to update its DBRef entry * @param responseSummaries * a collection of PDBResponseSummary */ public void updateSequenceDbRef(SequenceI seq, Collection responseSummaries) { for (PDBResponseSummary response : responseSummaries) { PDBEntry newEntry = new PDBEntry(); newEntry.setId(response.getPdbId()); newEntry.setType("PDB"); seq.getDatasetSequence().addPDBId(newEntry); } } /** * Builds a query string for a given sequences using its DBRef entries * * @param seq * the sequences to build a query for * @return the built query string */ @SuppressWarnings("unchecked") public static String buildQuery(SequenceI seq) { String query = seq.getName(); StringBuilder queryBuilder = new StringBuilder(); int count = 0; if (seq.getPDBId() != null) { for (PDBEntry entry : (Vector) seq.getPDBId()) { queryBuilder.append("text:").append(entry.getId()).append(" OR "); } } if (seq.getDBRef() != null && seq.getDBRef().length != 0) { for (DBRefEntry dbRef : seq.getDBRef()) { queryBuilder.append("text:") .append(dbRef.getAccessionId().replaceAll("GO:", "")) .append(" OR "); ++count; if (count > 10) { break; } } int endIndex = queryBuilder.lastIndexOf(" OR "); query = queryBuilder.toString().substring(5, endIndex); } return query; } /** * Filters a given list of discovered structures based on supplied argument * * @param fieldToFilterBy * the field to filter by */ public void filterResultSet(final String fieldToFilterBy) { // SwingWorker aWorker = new SwingWorker() // { // long startTime = System.currentTimeMillis(); // // @Override // protected Object doInBackground() throws Exception // { // lbl_loading.setVisible(true); // // Collection wantedFields = PDBDocFieldPreferences // .getStructureSummaryFields(); // Collection filteredResponse = new // HashSet(); // for (SequenceI seq : selectedSequences) // { // PDBRestRequest pdbRequest = new PDBRestRequest(); // pdbRequest.setAllowEmptySeq(false); // pdbRequest.setResponseSize(1); // pdbRequest.setFieldToSearchBy("(text:"); // pdbRequest.setFieldToSortBy(fieldToFilterBy, // !chk_invertFilter.isSelected()); // pdbRequest.setSearchTerm(buildQuery(seq) + ")"); // pdbRequest.setWantedFields(wantedFields); // pdbRequest.setAssociatedSequence(seq.getName()); // pdbRestCleint = new PDBRestClient(); // PDBRestResponse resultList = pdbRestCleint // .executeRequest(pdbRequest); // lastPdbRequest = pdbRequest; // if (resultList.getSearchSummary() != null // && !resultList.getSearchSummary().isEmpty()) // { // filteredResponse.addAll(resultList.getSearchSummary()); // } // } // // if (!filteredResponse.isEmpty()) // { // final int filterResponseCount = filteredResponse.size(); // Collection reorderedStructuresSet = new // LinkedHashSet(); // reorderedStructuresSet.addAll(filteredResponse); // reorderedStructuresSet.addAll(discoveredStructuresSet); // tbl_summary.setModel(PDBRestResponse.getTableModel( // lastPdbRequest, reorderedStructuresSet)); // // // Update the model here // // ListSelectionModel model = tbl_summary.getSelectionModel(); // // model.clearSelection(); // // model.addSelectionInterval(0, filterResponseCount - 1); // // EventQueue.invokeLater(new Runnable() // // { // // public void run() // // { // // tbl_summary.addRowSelectionInterval(0, filterResponseCount - 1); // // // } // // }); // // Discard unwanted objects to make them eligible for garbage // // collection // reorderedStructuresSet = null; // } // return null; // } // // public void done() // { // lbl_loading.setVisible(false); // tbl_summary.addRowSelectionInterval(0, 2); // String totalTime = (System.currentTimeMillis() - startTime) // + " milli secs"; // mainFrame.setTitle("Structure Chooser - Filter time (" + totalTime // + ")"); // validateSelections(); // } // }; // aWorker.execute(); Thread filterThread = new Thread(new Runnable() { @Override public void run() { long startTime = System.currentTimeMillis(); try { lbl_loading.setVisible(true); Collection wantedFields = PDBDocFieldPreferences .getStructureSummaryFields(); Collection filteredResponse = new HashSet(); for (SequenceI seq : selectedSequences) { PDBRestRequest pdbRequest = new PDBRestRequest(); pdbRequest.setAllowEmptySeq(false); pdbRequest.setResponseSize(1); pdbRequest.setFieldToSearchBy("(text:"); pdbRequest.setFieldToSortBy(fieldToFilterBy, !chk_invertFilter.isSelected()); pdbRequest.setSearchTerm(buildQuery(seq) + ")"); pdbRequest.setWantedFields(wantedFields); pdbRequest.setAssociatedSequence(seq.getName()); pdbRestCleint = new PDBRestClient(); PDBRestResponse resultList = pdbRestCleint .executeRequest(pdbRequest); lastPdbRequest = pdbRequest; if (resultList.getSearchSummary() != null && !resultList.getSearchSummary().isEmpty()) { filteredResponse.addAll(resultList.getSearchSummary()); } } if (!filteredResponse.isEmpty()) { final int filterResponseCount = filteredResponse.size(); Collection reorderedStructuresSet = new LinkedHashSet(); reorderedStructuresSet.addAll(filteredResponse); reorderedStructuresSet.addAll(discoveredStructuresSet); tbl_summary.setModel(PDBRestResponse.getTableModel( lastPdbRequest, reorderedStructuresSet)); // Update the model here // ListSelectionModel model = tbl_summary.getSelectionModel(); // model.clearSelection(); // model.addSelectionInterval(0, filterResponseCount - 1); // EventQueue.invokeLater(new Runnable() // { // public void run() // { tbl_summary.addRowSelectionInterval(0, filterResponseCount - 1); // } // }); // Discard unwanted objects to make them eligible for garbage // collection reorderedStructuresSet = null; } lbl_loading.setVisible(false); String totalTime = (System.currentTimeMillis() - startTime) + " milli secs"; mainFrame.setTitle("Structure Chooser - Filter time (" + totalTime + ")"); validateSelections(); } catch (Exception e) { e.printStackTrace(); } } }); filterThread.start(); } /** * Handles action event for btn_pdbFromFile */ 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) { selectedPdbFileName = chooser.getSelectedFile().getPath(); jalview.bin.Cache.setProperty("LAST_DIRECTORY", selectedPdbFileName); validateSelections(); } } /** * Populates the filter combo-box options dynamically depending on discovered * structures */ protected void populateFilterComboBox() { if (isStructuresDiscovered()) { cmb_filterOption.addItem(new FilterOption("Best Quality", PDBDocField.OVERALL_QUALITY.getCode(), VIEWS_FILTER)); cmb_filterOption.addItem(new FilterOption("Best UniProt Coverage", PDBDocField.UNIPROT_COVERAGE.getCode(), VIEWS_FILTER)); cmb_filterOption.addItem(new FilterOption("Highest Resolution", PDBDocField.RESOLUTION.getCode(), VIEWS_FILTER)); cmb_filterOption.addItem(new FilterOption("Highest Protein Chain", PDBDocField.PROTEIN_CHAIN_COUNT.getCode(), VIEWS_FILTER)); cmb_filterOption.addItem(new FilterOption("Highest Bound Molecules", PDBDocField.BOUND_MOLECULE_COUNT.getCode(), VIEWS_FILTER)); cmb_filterOption.addItem(new FilterOption("Highest Polymer Residues", PDBDocField.POLYMER_RESIDUE_COUNT.getCode(), VIEWS_FILTER)); } cmb_filterOption.addItem(new FilterOption("Enter PDB Id", "-", VIEWS_ENTER_ID)); cmb_filterOption.addItem(new FilterOption("From File", "-", VIEWS_FROM_FILE)); } /** * Updates the displayed view based on the selected filter option */ protected void updateCurrentView() { FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption .getSelectedItem()); layout_switchableViews.show(pnl_switchableViews, selectedFilterOpt.getView()); String filterTitle = mainFrame.getTitle(); mainFrame.setTitle(frameTitle); chk_invertFilter.setVisible(false); if (selectedFilterOpt.getView() == VIEWS_FILTER) { mainFrame.setTitle(filterTitle); chk_invertFilter.setVisible(true); filterResultSet(selectedFilterOpt.getValue()); } else { idInputAssSeqPanel.loadCmbAssSeq(); fileChooserAssSeqPanel.loadCmbAssSeq(); } validateSelections(); } /** * Validates user selection and activates the view button if all parameters * are correct */ public void validateSelections() { FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption .getSelectedItem()); btn_view.setEnabled(false); String currentView = selectedFilterOpt.getView(); if (currentView == VIEWS_FILTER) { if (tbl_summary.getSelectedRows().length > 0) { btn_view.setEnabled(true); } } else if (currentView == VIEWS_ENTER_ID) { validateAssociationEnterPdb(); } else if (currentView == VIEWS_FROM_FILE) { validateAssociationFromFile(); } } /** * Validates inputs from the Manual PDB entry panel */ public void validateAssociationEnterPdb() { AssociateSeqOptions assSeqOpt = (AssociateSeqOptions) idInputAssSeqPanel .getCmb_assSeq().getSelectedItem(); lbl_pdbManualFetchStatus.setIcon(errorImage); if (selectedSequences.length == 1 || !assSeqOpt.getName().equalsIgnoreCase( "-Select Associated Seq-")) { txt_search.setEnabled(true); if (isValidPBDEntry) { btn_view.setEnabled(true); lbl_pdbManualFetchStatus.setIcon(goodImage); } } else { txt_search.setEnabled(false); lbl_pdbManualFetchStatus.setIcon(errorImage); } } /** * Validates inputs for the manual PDB file selection options */ public void validateAssociationFromFile() { AssociateSeqOptions assSeqOpt = (AssociateSeqOptions) fileChooserAssSeqPanel .getCmb_assSeq().getSelectedItem(); lbl_fromFileStatus.setIcon(errorImage); if (selectedSequences.length == 1 || (assSeqOpt != null && !assSeqOpt.getName().equalsIgnoreCase( "-Select Associated Seq-"))) { btn_pdbFromFile.setEnabled(true); if (selectedPdbFileName != null && selectedPdbFileName.length() > 0) { btn_view.setEnabled(true); lbl_fromFileStatus.setIcon(goodImage); } } else { btn_pdbFromFile.setEnabled(false); lbl_fromFileStatus.setIcon(errorImage); } } @Override public void cmbAssSeqStateChanged() { validateSelections(); } /** * Handles the state change event for the 'filter' combo-box and 'invert' * check-box */ @Override protected void stateChanged(ItemEvent e) { if (e.getSource() instanceof JCheckBox) { updateCurrentView(); } else { if (e.getStateChange() == ItemEvent.SELECTED) { updateCurrentView(); } } } /** * Handles action event for btn_ok */ @Override public void ok_ActionPerformed() { FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption .getSelectedItem()); String currentView = selectedFilterOpt.getView(); if (currentView == VIEWS_FILTER) { int pdbIdCol = PDBRestClient.getPDBIdColumIndex( lastPdbRequest.getWantedFields(), true); int[] selectedRows = tbl_summary.getSelectedRows(); PDBEntry[] pdbEntriesToView = new PDBEntry[selectedRows.length]; int count = 0; for (int summaryRow : selectedRows) { String pdbIdStr = tbl_summary.getValueAt(summaryRow, pdbIdCol) .toString(); PDBEntry pdbEntry = new PDBEntry(); pdbEntry.setId(pdbIdStr); pdbEntry.setType("PDB"); pdbEntriesToView[count++] = pdbEntry; } new StructureViewer(ap.getStructureSelectionManager()) .viewStructures(ap, pdbEntriesToView, ap.av.collateForPDB(pdbEntriesToView)); } else if (currentView == VIEWS_ENTER_ID) { selectedSequence = ((AssociateSeqOptions) idInputAssSeqPanel .getCmb_assSeq().getSelectedItem()).getSequence(); PDBEntry pdbEntry = new PDBEntry(); pdbEntry.setId(txt_search.getText()); pdbEntry.setType("PDB"); selectedSequence.getDatasetSequence().addPDBId(pdbEntry); PDBEntry[] pdbEntriesToView = new PDBEntry[] { pdbEntry }; new StructureViewer(ap.getStructureSelectionManager()) .viewStructures(ap, pdbEntriesToView, ap.av.collateForPDB(pdbEntriesToView)); } else if (currentView == VIEWS_FROM_FILE) { selectedSequence = ((AssociateSeqOptions) fileChooserAssSeqPanel .getCmb_assSeq().getSelectedItem()).getSequence(); new AssociatePdbFileWithSeq().associatePdbWithSeq( selectedPdbFileName, jalview.io.AppletFormatAdapter.FILE, selectedSequence, true, Desktop.instance); } mainFrame.dispose(); } /** * Populates the combo-box used in associating manually fetched structures to * a unique sequence when more than one sequence selection is made. */ public void populateCmbAssociateSeqOptions( JComboBox cmb_assSeq, JLabel lbl_associateSeq) { cmb_assSeq.removeAllItems(); cmb_assSeq.addItem(new AssociateSeqOptions("-Select Associated Seq-", null)); // cmb_assSeq.addItem(new AssociateSeqOptions("Auto Detect", null)); lbl_associateSeq.setVisible(false); if (selectedSequences.length > 1) { for (SequenceI seq : selectedSequences) { cmb_assSeq.addItem(new AssociateSeqOptions(seq)); } } else { String seqName = selectedSequence.getDisplayId(false); seqName = seqName.length() <= 40 ? seqName : seqName.substring(0, 39); lbl_associateSeq.setText(seqName); lbl_associateSeq.setVisible(true); cmb_assSeq.setVisible(false); } } public boolean isStructuresDiscovered() { return structuresDiscovered; } public void setStructuresDiscovered(boolean structuresDiscovered) { this.structuresDiscovered = structuresDiscovered; } public Collection getDiscoveredStructuresSet() { return discoveredStructuresSet; } @Override protected void txt_search_ActionPerformed() { isValidPBDEntry = false; if (txt_search.getText().length() > 0) { List wantedFields = new ArrayList(); wantedFields.add(PDBDocField.PDB_ID); PDBRestRequest pdbRequest = new PDBRestRequest(); pdbRequest.setAllowEmptySeq(false); pdbRequest.setResponseSize(1); pdbRequest.setFieldToSearchBy("(pdb_id:"); pdbRequest.setWantedFields(wantedFields); pdbRequest.setSearchTerm(txt_search.getText() + ")"); pdbRequest.setAssociatedSequence(selectedSequence.getName()); pdbRestCleint = new PDBRestClient(); PDBRestResponse resultList = pdbRestCleint.executeRequest(pdbRequest); if (resultList.getSearchSummary() != null && resultList.getSearchSummary().size() > 0) { isValidPBDEntry = true; } } validateSelections(); } @Override public void tabRefresh() { if (selectedSequences != null) { Thread refreshThread = new Thread(new Runnable() { @Override public void run() { fetchStructuresMetaData(); filterResultSet(((FilterOption) cmb_filterOption .getSelectedItem()).getValue()); } }); refreshThread.start(); } } }