/* * 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.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.List; import java.util.Vector; import javax.swing.JCheckBox; import javax.swing.JOptionPane; import javax.swing.ListSelectionModel; /** * 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 = new HashSet(); private PDBRestRequest pdbRequest; private PDBRestClient pdbRestCleint; 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(); List wantedFields = new ArrayList(); // wantedFields.add(PDBDocField.MOLECULE_TYPE); wantedFields.add(PDBDocField.PDB_ID); // wantedFields.add(PDBDocField.GENUS); // wantedFields.add(PDBDocField.GENE_NAME); wantedFields.add(PDBDocField.TITLE); pdbRequest = new PDBRestRequest(); pdbRequest.setAllowEmptySeq(false); pdbRequest.setResponseSize(500); pdbRequest.setFieldToSearchBy("(text:"); pdbRequest.setWantedFields(wantedFields); for (SequenceI seq : selectedSequences) { pdbRequest.setSearchTerm(buildQuery(seq) + ")"); pdbRequest.setAssociatedSequence(seq.getName()); pdbRestCleint = new PDBRestClient(); PDBRestResponse resultList = pdbRestCleint.executeRequest(pdbRequest); if (resultList.getSearchSummary() != null && !resultList.getSearchSummary().isEmpty()) { discoveredStructuresSet.addAll(resultList.getSearchSummary()); updateSequenceDbRef(seq, resultList.getSearchSummary()); } } int noOfStructuresFound = 0; if (discoveredStructuresSet != null && !discoveredStructuresSet.isEmpty()) { jList_FoundStructures.setModel(PDBRestResponse .getListModel(discoveredStructuresSet)); tbl_summary.setModel(PDBRestResponse.getTableModel(pdbRequest, discoveredStructuresSet)); // resizeColumnWidth(summaryTable); 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); } // System.out.println("Query -----> " + query); 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) { Thread filterThread = new Thread(new Runnable() { @Override public void run() { try { lbl_loading.setVisible(true); pdbRequest.setResponseSize(1); pdbRequest.setFieldToSearchBy("(text:"); pdbRequest.setFieldToSortBy(fieldToFilterBy, !chk_invertFilter.isSelected()); Collection filteredResponse = new HashSet(); for (SequenceI seq : selectedSequences) { pdbRequest.setSearchTerm(buildQuery(seq) + ")"); pdbRequest.setAssociatedSequence(seq.getName()); pdbRestCleint = new PDBRestClient(); PDBRestResponse resultList = pdbRestCleint .executeRequest(pdbRequest); if (resultList.getSearchSummary() != null && !resultList.getSearchSummary().isEmpty()) { filteredResponse.addAll(resultList.getSearchSummary()); } } if (filteredResponse != null) { int filterResponseCount = filteredResponse.size(); List originalDiscoveredStructuresList = new ArrayList( discoveredStructuresSet); originalDiscoveredStructuresList.removeAll(filteredResponse); Collection reorderedStructuresSet = new ArrayList(); reorderedStructuresSet.addAll(filteredResponse); reorderedStructuresSet.addAll(originalDiscoveredStructuresList); jList_FoundStructures.setModel(PDBRestResponse .getListModel(reorderedStructuresSet)); tbl_summary.setModel(PDBRestResponse.getTableModel(pdbRequest, reorderedStructuresSet)); // int[] filterIndice = new int[filterResponseCount]; ListSelectionModel model = tbl_summary.getSelectionModel(); model.clearSelection(); for (int x = 0; x < filterResponseCount; x++) { // filterIndice[x] = x; model.addSelectionInterval(x, x); } // Discard unwanted objects to make them eligible for garbage // collection originalDiscoveredStructuresList = null; reorderedStructuresSet = null; // jListFoundStructures.setSelectedIndices(filterIndice); } lbl_loading.setVisible(false); } catch (Exception e) { e.printStackTrace(); } } }); filterThread.start(); } /** * Determines the column index for the pdb id in the summary table. The pdb id * serves as a unique identifier for a given row in the summary table * * @param wantedFeilds * the available table columns in no particular order * @return the pdb id field column index */ public static int getPDBIdColumIndex(Collection wantedFeilds) { int pdbFeildIndex = 1; for (PDBDocField feild : wantedFeilds) { if (feild.equals(PDBDocField.PDB_ID)) { break; } ++pdbFeildIndex; } return pdbFeildIndex; } /** * 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) { String choice = chooser.getSelectedFile().getPath(); jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice); new AssociatePdbFileWithSeq().associatePdbWithSeq(choice, jalview.io.AppletFormatAdapter.FILE, selectedSequence, true, Desktop.instance); } } /** * Handles action event for btn_ok */ @Override public void ok_ActionPerformed() { int pdbIdCol = getPDBIdColumIndex(pdbRequest.getWantedFields()); 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)); } /** * Handles action event for manual entry of pdb ids */ 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()); selectedSequence.getDatasetSequence().addPDBId(entry); } } /** * 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 selectedOption = ((FilterOption) cmb_filterOption .getSelectedItem()); layout_switchableViews.show(pnl_switchableViews, selectedOption.getView()); chk_invertFilter.setEnabled(false); if (selectedOption.getView() == VIEWS_FILTER) { chk_invertFilter.setEnabled(true); filterResultSet(selectedOption.getValue()); } } /** * 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(); } } } public boolean isStructuresDiscovered() { return structuresDiscovered; } public void setStructuresDiscovered(boolean structuresDiscovered) { this.structuresDiscovered = structuresDiscovered; } public Collection getDiscoveredStructuresSet() { return discoveredStructuresSet; } }