package jalview.gui;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ItemEvent;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Executors;
+
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JMenuItem;
+import javax.swing.JPopupMenu;
+import javax.swing.JTable;
+import javax.swing.SwingUtilities;
+import javax.swing.table.AbstractTableModel;
+
+import com.stevesoft.pat.Regex;
+
+import jalview.api.structures.JalviewStructureDisplayI;
+import jalview.bin.Cache;
+import jalview.bin.Console;
import jalview.bin.Jalview;
-import jalview.datamodel.DBRefEntry;
-import jalview.datamodel.DBRefSource;
import jalview.datamodel.PDBEntry;
import jalview.datamodel.SequenceI;
+import jalview.ext.jmol.JmolParser;
import jalview.fts.api.FTSData;
import jalview.fts.api.FTSDataColumnI;
import jalview.fts.api.FTSRestClientI;
+import jalview.fts.core.FTSDataColumnPreferences;
import jalview.fts.core.FTSRestRequest;
import jalview.fts.core.FTSRestResponse;
import jalview.fts.service.pdb.PDBFTSRestClient;
+import jalview.fts.service.threedbeacons.TDB_FTSData;
+import jalview.gui.structurechooser.PDBStructureChooserQuerySource;
+import jalview.gui.structurechooser.StructureChooserQuerySource;
+import jalview.gui.structurechooser.ThreeDBStructureChooserQuerySource;
import jalview.io.DataSourceType;
+import jalview.io.JalviewFileChooser;
+import jalview.io.JalviewFileView;
+import jalview.jbgui.FilterOption;
import jalview.jbgui.GStructureChooser;
+import jalview.structure.StructureImportSettings.TFType;
import jalview.structure.StructureMapping;
import jalview.structure.StructureSelectionManager;
import jalview.util.MessageManager;
+import jalview.util.Platform;
+import jalview.util.StringUtils;
import jalview.ws.DBRefFetcher;
+import jalview.ws.DBRefFetcher.FetchFinishedListenerI;
+import jalview.ws.seqfetcher.DbSourceProxy;
import jalview.ws.sifts.SiftsSettings;
-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.Objects;
-import java.util.Set;
-import java.util.Vector;
-
-import javax.swing.JCheckBox;
-import javax.swing.JComboBox;
-import javax.swing.JLabel;
-import javax.swing.table.AbstractTableModel;
-
/**
* Provides the behaviors for the Structure chooser Panel
*
public class StructureChooser extends GStructureChooser
implements IProgressIndicator
{
- private static int MAX_QLENGTH = 7820;
+ private static final String AUTOSUPERIMPOSE = "AUTOSUPERIMPOSE";
+
+ /**
+ * warn user if need to fetch more than this many uniprot records at once
+ */
+ private static final int THRESHOLD_WARN_UNIPROT_FETCH_NEEDED = 20;
private SequenceI selectedSequence;
private Collection<FTSData> discoveredStructuresSet;
- private FTSRestRequest lastPdbRequest;
+ private StructureChooserQuerySource data;
- private FTSRestClientI pdbRestCleint;
+ @Override
+ protected FTSDataColumnPreferences getFTSDocFieldPrefs()
+ {
+ return data.getDocFieldPrefs();
+ }
private String selectedPdbFileName;
+ private TFType localPdbTempfacType;
+
+ private String localPdbPaeMatrixFileName;
+
private boolean isValidPBDEntry;
private boolean cachedPDBExists;
+ private Collection<FTSData> lastDiscoveredStructuresSet;
+
+ private boolean canQueryTDB = false;
+
+ private boolean notQueriedTDBYet = true;
+
+ List<SequenceI> seqsWithoutSourceDBRef = null;
+
+ private boolean showChooserGUI = true;
+
+ private static StructureViewer lastTargetedView = null;
+
public StructureChooser(SequenceI[] selectedSeqs, SequenceI selectedSeq,
AlignmentPanel ap)
{
+ this(selectedSeqs, selectedSeq, ap, true);
+ }
+
+ public StructureChooser(SequenceI[] selectedSeqs, SequenceI selectedSeq,
+ AlignmentPanel ap, boolean showGUI)
+ {
+ // which FTS engine to use
+ data = StructureChooserQuerySource.getQuerySourceFor(selectedSeqs);
+ initDialog();
+
this.ap = ap;
this.selectedSequence = selectedSeq;
this.selectedSequences = selectedSeqs;
this.progressIndicator = (ap == null) ? null : ap.alignFrame;
+ this.showChooserGUI = showGUI;
init();
+
}
/**
+ * sets canQueryTDB if protein sequences without a canonical uniprot ref or at
+ * least one structure are discovered.
+ */
+ private void populateSeqsWithoutSourceDBRef()
+ {
+ seqsWithoutSourceDBRef = new ArrayList<SequenceI>();
+ boolean needCanonical = false;
+ for (SequenceI seq : selectedSequences)
+ {
+ if (seq.isProtein())
+ {
+ int dbRef = ThreeDBStructureChooserQuerySource
+ .checkUniprotRefs(seq.getDBRefs());
+ if (dbRef < 0)
+ {
+ if (dbRef == -1)
+ {
+ // need to retrieve canonicals
+ needCanonical = true;
+ seqsWithoutSourceDBRef.add(seq);
+ }
+ else
+ {
+ // could be a sequence with pdb ref
+ if (seq.getAllPDBEntries() == null
+ || seq.getAllPDBEntries().size() == 0)
+ {
+ seqsWithoutSourceDBRef.add(seq);
+ }
+ }
+ }
+ }
+ }
+ // retrieve database refs for protein sequences
+ if (!seqsWithoutSourceDBRef.isEmpty())
+ {
+ canQueryTDB = true;
+ if (needCanonical)
+ {
+ // triggers display of the 'Query TDB' button
+ notQueriedTDBYet = true;
+ }
+ }
+ };
+
+ /**
* Initializes parameters used by the Structure Chooser Panel
*/
- public void init()
+ protected void init()
{
if (!Jalview.isHeadlessMode())
{
progressBar = new ProgressBar(this.statusPanel, this.statusBar);
}
+ chk_superpose.setSelected(Cache.getDefault(AUTOSUPERIMPOSE, true));
+ btn_queryTDB.addActionListener(new ActionListener()
+ {
+
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ promptForTDBFetch(false);
+ }
+ });
+
+ Executors.defaultThreadFactory().newThread(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ populateSeqsWithoutSourceDBRef();
+ initialStructureDiscovery();
+ }
+
+ }).start();
+
+ }
+
+ // called by init
+ private void initialStructureDiscovery()
+ {
+ // check which FTS engine to use
+ data = StructureChooserQuerySource.getQuerySourceFor(selectedSequences);
+
// ensure a filter option is in force for search
populateFilterComboBox(true, cachedPDBExists);
- Thread discoverPDBStructuresThread = new Thread(new Runnable()
+
+ // looks for any existing structures already loaded
+ // for the sequences (the cached ones)
+ // then queries the StructureChooserQuerySource to
+ // discover more structures.
+ //
+ // Possible optimisation is to only begin querying
+ // the structure chooser if there are no cached structures.
+
+ long startTime = System.currentTimeMillis();
+ updateProgressIndicator(
+ MessageManager.getString("status.loading_cached_pdb_entries"),
+ startTime);
+ loadLocalCachedPDBEntries();
+ updateProgressIndicator(null, startTime);
+ updateProgressIndicator(
+ MessageManager.getString("status.searching_for_pdb_structures"),
+ startTime);
+ fetchStructuresMetaData();
+ // revise filter options if no results were found
+ populateFilterComboBox(isStructuresDiscovered(), cachedPDBExists);
+ discoverStructureViews();
+ updateProgressIndicator(null, startTime);
+ mainFrame.setVisible(showChooserGUI);
+ updateCurrentView();
+ }
+
+ /**
+ * raises dialog for Uniprot fetch followed by 3D beacons search
+ *
+ * @param ignoreGui
+ * - when true, don't ask, just fetch
+ */
+ public void promptForTDBFetch(boolean ignoreGui)
+ {
+ final long progressId = System.currentTimeMillis();
+
+ // final action after prompting and discovering db refs
+ final Runnable strucDiscovery = new Runnable()
{
@Override
public void run()
{
- long startTime = System.currentTimeMillis();
- updateProgressIndicator(MessageManager
- .getString("status.loading_cached_pdb_entries"), startTime);
- loadLocalCachedPDBEntries();
- updateProgressIndicator(null, startTime);
- updateProgressIndicator(MessageManager.getString(
- "status.searching_for_pdb_structures"), startTime);
- fetchStructuresMetaData();
- // revise filter options if no results were found
- populateFilterComboBox(isStructuresDiscovered(), cachedPDBExists);
- updateProgressIndicator(null, startTime);
- mainFrame.setVisible(true);
- updateCurrentView();
+ mainFrame.setEnabled(false);
+ cmb_filterOption.setEnabled(false);
+ progressBar.setProgressBar(
+ MessageManager.getString("status.searching_3d_beacons"),
+ progressId);
+ btn_queryTDB.setEnabled(false);
+ // TODO: warn if no accessions discovered
+ populateSeqsWithoutSourceDBRef();
+ // redo initial discovery - this time with 3d beacons
+ // Executors.
+ previousWantedFields = null;
+ lastSelected = (FilterOption) cmb_filterOption.getSelectedItem();
+ cmb_filterOption.setSelectedItem(null);
+ cachedPDBExists = false; // reset to initial
+ initialStructureDiscovery();
+ if (!isStructuresDiscovered())
+ {
+ progressBar.setProgressBar(MessageManager.getString(
+ "status.no_structures_discovered_from_3d_beacons"),
+ progressId);
+ btn_queryTDB.setToolTipText(MessageManager.getString(
+ "status.no_structures_discovered_from_3d_beacons"));
+ btn_queryTDB.setEnabled(false);
+ pnl_queryTDB.setVisible(false);
+ }
+ else
+ {
+ cmb_filterOption.setSelectedIndex(0); // select 'best'
+ btn_queryTDB.setVisible(false);
+ pnl_queryTDB.setVisible(false);
+ progressBar.setProgressBar(null, progressId);
+ }
+ mainFrame.setEnabled(true);
+ cmb_filterOption.setEnabled(true);
}
- });
- discoverPDBStructuresThread.start();
+ };
+
+ final FetchFinishedListenerI afterDbRefFetch = new FetchFinishedListenerI()
+ {
+
+ @Override
+ public void finished()
+ {
+ // filter has been selected, so we set flag to remove ourselves
+ notQueriedTDBYet = false;
+ // new thread to discover structures - via 3d beacons
+ Executors.defaultThreadFactory().newThread(strucDiscovery).start();
+
+ }
+ };
+
+ // fetch db refs if OK pressed
+ final Callable discoverCanonicalDBrefs = () -> {
+ btn_queryTDB.setEnabled(false);
+ populateSeqsWithoutSourceDBRef();
+
+ final int y = seqsWithoutSourceDBRef.size();
+ if (y > 0)
+ {
+ final SequenceI[] seqWithoutSrcDBRef = seqsWithoutSourceDBRef
+ .toArray(new SequenceI[y]);
+ DBRefFetcher dbRefFetcher = new DBRefFetcher(seqWithoutSrcDBRef,
+ progressBar, new DbSourceProxy[]
+ { new jalview.ws.dbsources.Uniprot() }, null, false);
+ dbRefFetcher.addListener(afterDbRefFetch);
+ // ideally this would also gracefully run with callbacks
+
+ dbRefFetcher.fetchDBRefs(true);
+ }
+ else
+ {
+ // call finished action directly
+ afterDbRefFetch.finished();
+ }
+ return null;
+ };
+ final Callable revertview = () -> {
+ if (lastSelected != null)
+ {
+ cmb_filterOption.setSelectedItem(lastSelected);
+ }
+ return null;
+ };
+ int threshold = Cache.getDefault("UNIPROT_AUTOFETCH_THRESHOLD",
+ THRESHOLD_WARN_UNIPROT_FETCH_NEEDED);
+ Console.debug("Using Uniprot fetch threshold of " + threshold);
+ if (ignoreGui || seqsWithoutSourceDBRef.size() < threshold)
+ {
+ Executors.newSingleThreadExecutor().submit(discoverCanonicalDBrefs);
+ return;
+ }
+ // need cancel and no to result in the discoverPDB action - mocked is
+ // 'cancel' TODO: mock should be OK
+
+ StructureChooser thisSC = this;
+ JvOptionPane.newOptionDialog(thisSC.getFrame())
+ .setResponseHandler(JvOptionPane.OK_OPTION,
+ discoverCanonicalDBrefs)
+ .setResponseHandler(JvOptionPane.CANCEL_OPTION, revertview)
+ .setResponseHandler(JvOptionPane.NO_OPTION, revertview)
+ .showDialog(
+ MessageManager.formatMessage(
+ "label.fetch_references_for_3dbeacons",
+ seqsWithoutSourceDBRef.size()),
+ MessageManager.getString("label.3dbeacons"),
+ JvOptionPane.YES_NO_OPTION, JvOptionPane.PLAIN_MESSAGE,
+ null, new Object[]
+ { MessageManager.getString("action.ok"),
+ MessageManager.getString("action.cancel") },
+ MessageManager.getString("action.ok"), false);
+ }
+
+ /**
+ * Builds a drop-down choice list of existing structure viewers to which new
+ * structures may be added. If this list is empty then it, and the 'Add'
+ * button, are hidden.
+ */
+ private void discoverStructureViews()
+ {
+ if (Desktop.instance != null)
+ {
+ targetView.removeAllItems();
+ if (lastTargetedView != null && !lastTargetedView.isVisible())
+ {
+ lastTargetedView = null;
+ }
+ int linkedViewsAt = 0;
+ for (StructureViewerBase view : Desktop.instance
+ .getStructureViewers(null, null))
+ {
+ StructureViewer viewHandler = (lastTargetedView != null
+ && lastTargetedView.sview == view) ? lastTargetedView
+ : StructureViewer.reconfigure(view);
+
+ if (view.isLinkedWith(ap))
+ {
+ targetView.insertItemAt(viewHandler, linkedViewsAt++);
+ }
+ else
+ {
+ targetView.addItem(viewHandler);
+ }
+ }
+
+ /*
+ * show option to Add to viewer if at least 1 viewer found
+ */
+ targetView.setVisible(false);
+ if (targetView.getItemCount() > 0)
+ {
+ targetView.setVisible(true);
+ if (lastTargetedView != null)
+ {
+ targetView.setSelectedItem(lastTargetedView);
+ }
+ else
+ {
+ targetView.setSelectedIndex(0);
+ }
+ }
+ btn_add.setVisible(targetView.isVisible());
+ }
}
/**
* @param id
* unique handle for this indicator
*/
- public void updateProgressIndicator(String message, long id)
+ protected void updateProgressIndicator(String message, long id)
{
if (progressIndicator != null)
{
* Retrieve meta-data for all the structure(s) for a given sequence(s) in a
* selection group
*/
- public void fetchStructuresMetaData()
+ void fetchStructuresMetaData()
{
long startTime = System.currentTimeMillis();
- pdbRestCleint = PDBFTSRestClient.getInstance();
- Collection<FTSDataColumnI> wantedFields = pdbDocFieldPrefs
+ Collection<FTSDataColumnI> wantedFields = data.getDocFieldPrefs()
.getStructureSummaryFields();
discoveredStructuresSet = new LinkedHashSet<>();
HashSet<String> errors = new HashSet<>();
+
+ FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
+ .getSelectedItem());
+
for (SequenceI seq : selectedSequences)
{
- FTSRestRequest pdbRequest = new FTSRestRequest();
- pdbRequest.setAllowEmptySeq(false);
- pdbRequest.setResponseSize(500);
- pdbRequest.setFieldToSearchBy("(");
- FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
- .getSelectedItem());
- pdbRequest.setFieldToSortBy(selectedFilterOpt.getValue(),
- !chk_invertFilter.isSelected());
- pdbRequest.setWantedFields(wantedFields);
- pdbRequest.setSearchTerm(buildQuery(seq) + ")");
- pdbRequest.setAssociatedSequence(seq);
+
FTSRestResponse resultList;
try
{
- resultList = pdbRestCleint.executeRequest(pdbRequest);
+ resultList = data.fetchStructuresMetaData(seq, wantedFields,
+ selectedFilterOpt, !chk_invertFilter.isSelected());
+ // null response means the FTSengine didn't yield a query for this
+ // consider designing a special exception if we really wanted to be
+ // OOCrazy
+ if (resultList == null)
+ {
+ continue;
+ }
} catch (Exception e)
{
e.printStackTrace();
errors.add(e.getMessage());
continue;
}
- lastPdbRequest = pdbRequest;
if (resultList.getSearchSummary() != null
&& !resultList.getSearchSummary().isEmpty())
{
if (discoveredStructuresSet != null
&& !discoveredStructuresSet.isEmpty())
{
- getResultTable().setModel(FTSRestResponse
- .getTableModel(lastPdbRequest, discoveredStructuresSet));
+ getResultTable()
+ .setModel(data.getTableModel(discoveredStructuresSet));
+
noOfStructuresFound = discoveredStructuresSet.size();
+ lastDiscoveredStructuresSet = discoveredStructuresSet;
mainFrame.setTitle(MessageManager.formatMessage(
"label.structure_chooser_no_of_structures",
noOfStructuresFound, totalTime));
}
}
- public void loadLocalCachedPDBEntries()
+ protected void loadLocalCachedPDBEntries()
{
ArrayList<CachedPDB> entries = new ArrayList<>();
for (SequenceI seq : selectedSequences)
}
/**
- * 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
- */
-
- public static String buildQuery(SequenceI seq)
- {
- boolean isPDBRefsFound = false;
- boolean isUniProtRefsFound = false;
- StringBuilder queryBuilder = new StringBuilder();
- Set<String> seqRefs = new LinkedHashSet<>();
-
- if (seq.getAllPDBEntries() != null
- && queryBuilder.length() < MAX_QLENGTH)
- {
- for (PDBEntry entry : seq.getAllPDBEntries())
- {
- if (isValidSeqName(entry.getId()))
- {
- queryBuilder.append("pdb_id:").append(entry.getId().toLowerCase())
- .append(" OR ");
- isPDBRefsFound = true;
- }
- }
- }
-
- if (seq.getDBRefs() != null && seq.getDBRefs().length != 0)
- {
- for (DBRefEntry dbRef : seq.getDBRefs())
- {
- if (isValidSeqName(getDBRefId(dbRef))
- && queryBuilder.length() < MAX_QLENGTH)
- {
- if (dbRef.getSource().equalsIgnoreCase(DBRefSource.UNIPROT))
- {
- queryBuilder.append("uniprot_accession:")
- .append(getDBRefId(dbRef)).append(" OR ");
- queryBuilder.append("uniprot_id:").append(getDBRefId(dbRef))
- .append(" OR ");
- isUniProtRefsFound = true;
- }
- else if (dbRef.getSource().equalsIgnoreCase(DBRefSource.PDB))
- {
-
- queryBuilder.append("pdb_id:")
- .append(getDBRefId(dbRef).toLowerCase()).append(" OR ");
- isPDBRefsFound = true;
- }
- else
- {
- seqRefs.add(getDBRefId(dbRef));
- }
- }
- }
- }
-
- if (!isPDBRefsFound && !isUniProtRefsFound)
- {
- String seqName = seq.getName();
- seqName = sanitizeSeqName(seqName);
- String[] names = seqName.toLowerCase().split("\\|");
- for (String name : names)
- {
- // System.out.println("Found name : " + name);
- name.trim();
- if (isValidSeqName(name))
- {
- seqRefs.add(name);
- }
- }
-
- for (String seqRef : seqRefs)
- {
- queryBuilder.append("text:").append(seqRef).append(" OR ");
- }
- }
-
- int endIndex = queryBuilder.lastIndexOf(" OR ");
- if (queryBuilder.toString().length() < 6)
- {
- return null;
- }
- String query = queryBuilder.toString().substring(0, endIndex);
- return query;
- }
-
- /**
- * Remove the following special characters from input string +, -, &, !, (, ),
- * {, }, [, ], ^, ", ~, *, ?, :, \
- *
- * @param seqName
- * @return
- */
- static String sanitizeSeqName(String seqName)
- {
- Objects.requireNonNull(seqName);
- return seqName.replaceAll("\\[\\d*\\]", "")
- .replaceAll("[^\\dA-Za-z|_]", "").replaceAll("\\s+", "+");
- }
-
- /**
- * Ensures sequence ref names are not less than 3 characters and does not
- * contain a database name
- *
- * @param seqName
- * @return
- */
- public static boolean isValidSeqName(String seqName)
- {
- // System.out.println("seqName : " + seqName);
- String ignoreList = "pdb,uniprot,swiss-prot";
- if (seqName.length() < 3)
- {
- return false;
- }
- if (seqName.contains(":"))
- {
- return false;
- }
- seqName = seqName.toLowerCase();
- for (String ignoredEntry : ignoreList.split(","))
- {
- if (seqName.contains(ignoredEntry))
- {
- return false;
- }
- }
- return true;
- }
-
- public static String getDBRefId(DBRefEntry dbRef)
- {
- String ref = dbRef.getAccessionId().replaceAll("GO:", "");
- return ref;
- }
-
- /**
* Filters a given list of discovered structures based on supplied argument
*
* @param fieldToFilterBy
* the field to filter by
*/
- public void filterResultSet(final String fieldToFilterBy)
+ void filterResultSet(final String fieldToFilterBy)
{
Thread filterThread = new Thread(new Runnable()
{
+
@Override
public void run()
{
long startTime = System.currentTimeMillis();
- pdbRestCleint = PDBFTSRestClient.getInstance();
lbl_loading.setVisible(true);
- Collection<FTSDataColumnI> wantedFields = pdbDocFieldPrefs
+ Collection<FTSDataColumnI> wantedFields = data.getDocFieldPrefs()
.getStructureSummaryFields();
Collection<FTSData> filteredResponse = new HashSet<>();
HashSet<String> errors = new HashSet<>();
for (SequenceI seq : selectedSequences)
{
- FTSRestRequest pdbRequest = new FTSRestRequest();
- if (fieldToFilterBy.equalsIgnoreCase("uniprot_coverage"))
- {
- pdbRequest.setAllowEmptySeq(false);
- pdbRequest.setResponseSize(1);
- pdbRequest.setFieldToSearchBy("(");
- pdbRequest.setSearchTerm(buildQuery(seq) + ")");
- pdbRequest.setWantedFields(wantedFields);
- pdbRequest.setAssociatedSequence(seq);
- pdbRequest.setFacet(true);
- pdbRequest.setFacetPivot(fieldToFilterBy + ",entry_entity");
- pdbRequest.setFacetPivotMinCount(1);
- }
- else
- {
- pdbRequest.setAllowEmptySeq(false);
- pdbRequest.setResponseSize(1);
- pdbRequest.setFieldToSearchBy("(");
- pdbRequest.setFieldToSortBy(fieldToFilterBy,
- !chk_invertFilter.isSelected());
- pdbRequest.setSearchTerm(buildQuery(seq) + ")");
- pdbRequest.setWantedFields(wantedFields);
- pdbRequest.setAssociatedSequence(seq);
- }
+
FTSRestResponse resultList;
try
{
- resultList = pdbRestCleint.executeRequest(pdbRequest);
+ resultList = data.selectFirstRankedQuery(seq,
+ discoveredStructuresSet, wantedFields, fieldToFilterBy,
+ !chk_invertFilter.isSelected());
+
} catch (Exception e)
{
e.printStackTrace();
errors.add(e.getMessage());
continue;
}
- lastPdbRequest = pdbRequest;
if (resultList.getSearchSummary() != null
&& !resultList.getSearchSummary().isEmpty())
{
Collection<FTSData> reorderedStructuresSet = new LinkedHashSet<>();
reorderedStructuresSet.addAll(filteredResponse);
reorderedStructuresSet.addAll(discoveredStructuresSet);
- getResultTable().setModel(FTSRestResponse
- .getTableModel(lastPdbRequest, reorderedStructuresSet));
+ getResultTable()
+ .setModel(data.getTableModel(reorderedStructuresSet));
FTSRestResponse.configureTableColumn(getResultTable(),
wantedFields, tempUserPrefs);
* Handles action event for btn_pdbFromFile
*/
@Override
- public void pdbFromFile_actionPerformed()
+ protected void pdbFromFile_actionPerformed()
{
- jalview.io.JalviewFileChooser chooser = new jalview.io.JalviewFileChooser(
- jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
- chooser.setFileView(new jalview.io.JalviewFileView());
+ // TODO: JAL-3048 not needed for Jalview-JS until JSmol dep and
+ // StructureChooser
+ // works
+ JalviewFileChooser chooser = new JalviewFileChooser(
+ Cache.getProperty("LAST_DIRECTORY"));
+ chooser.setFileView(new JalviewFileView());
chooser.setDialogTitle(
MessageManager.formatMessage("label.select_pdb_file_for",
selectedSequence.getDisplayId(false)));
selectedSequence.getDisplayId(false)));
int value = chooser.showOpenDialog(null);
- if (value == jalview.io.JalviewFileChooser.APPROVE_OPTION)
+ if (value == JalviewFileChooser.APPROVE_OPTION)
{
selectedPdbFileName = chooser.getSelectedFile().getPath();
- jalview.bin.Cache.setProperty("LAST_DIRECTORY", selectedPdbFileName);
+ Cache.setProperty("LAST_DIRECTORY", selectedPdbFileName);
+ boolean guessTFType = localPdbPaeMatrixFileName == null;
+ localPdbPaeMatrixFileName = guessPAEFilename();
+ guessTFType |= localPdbPaeMatrixFileName != null;
+ Regex alphaFold = JmolParser.getNewAlphafoldValidator();
+ if (guessTFType
+ && alphaFold.search(new File(selectedPdbFileName).getName())
+ && !tempFacAsChanged)
+ {
+ // localPdbPaeMatrixFileName was null and now isn't and filename could
+ // well be AlphaFold and user hasn't adjusted the tempFacType
+ combo_tempFacAs.setSelectedItem(TFType.PLDDT);
+ }
validateSelections();
}
}
/**
+ * Handles action event for btn_pdbFromFile
+ */
+ @Override
+ protected void paeMatrixFile_actionPerformed()
+ {
+ File pdbFile = new File(selectedPdbFileName);
+ String setFile = Cache.getProperty("LAST_DIRECTORY");
+ if (localPdbPaeMatrixFileName != null)
+ {
+ File paeFile = new File(localPdbPaeMatrixFileName);
+ if (paeFile.exists())
+ setFile = paeFile.getAbsolutePath();
+ else if (paeFile.getParentFile().exists())
+ setFile = paeFile.getParentFile().getAbsolutePath();
+ }
+ else
+ {
+ String guess = guessPAEFilename();
+ if (guess != null)
+ setFile = guess;
+ }
+ JalviewFileChooser chooser = new JalviewFileChooser(setFile);
+ chooser.setFileView(new JalviewFileView());
+ chooser.setDialogTitle(MessageManager.formatMessage(
+ "label.select_pae_matrix_file_for", pdbFile.getName()));
+ chooser.setToolTipText(MessageManager.formatMessage(
+ "label.load_pae_matrix_file_associate_with_structure",
+ pdbFile.getName()));
+
+ int value = chooser.showOpenDialog(null);
+ if (value == JalviewFileChooser.APPROVE_OPTION)
+ {
+ localPdbPaeMatrixFileName = chooser.getSelectedFile().getPath();
+ Cache.setProperty("LAST_DIRECTORY", localPdbPaeMatrixFileName);
+ }
+ validateAssociationFromFile();
+ }
+
+ private String guessPAEFilename()
+ {
+ if (selectedPdbFileName.toLowerCase(Locale.ROOT).endsWith(".pdb")
+ || selectedPdbFileName.toLowerCase(Locale.ROOT)
+ .endsWith(".cif"))
+ {
+ String jsonExt = selectedPdbFileName.substring(0,
+ selectedPdbFileName.length() - 4) + ".json";
+ // AlphaFold naming scheme
+ String guessFile1 = StringUtils.replaceLast(jsonExt, "model",
+ "predicted_aligned_error");
+ // nf-core mode naming scheme
+ String guessFile2 = StringUtils.replaceLast(jsonExt, ".json",
+ "_scores.json");
+ if (new File(guessFile1).exists())
+ {
+ return guessFile1;
+ }
+ else if (new File(jsonExt).exists())
+ {
+ return jsonExt;
+ }
+ else if (new File(guessFile2).exists())
+ {
+ return guessFile2;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Populates the filter combo-box options dynamically depending on discovered
+ * structures
+ */
+ protected void populateFilterComboBox(boolean haveData,
+ boolean cachedPDBExist)
+ {
+ populateFilterComboBox(haveData, cachedPDBExist, null);
+ }
+
+ /**
* Populates the filter combo-box options dynamically depending on discovered
* structures
*/
protected void populateFilterComboBox(boolean haveData,
- boolean cachedPDBExists)
+ boolean cachedPDBExist, FilterOption lastSel)
{
+
/*
* temporarily suspend the change listener behaviour
*/
cmb_filterOption.removeItemListener(this);
-
+ int selSet = -1;
cmb_filterOption.removeAllItems();
if (haveData)
{
- cmb_filterOption.addItem(new FilterOption("Best Quality",
- "overall_quality", VIEWS_FILTER, false));
- cmb_filterOption.addItem(new FilterOption("Best Resolution",
- "resolution", VIEWS_FILTER, false));
- cmb_filterOption.addItem(new FilterOption("Most Protein Chain",
- "number_of_protein_chains", VIEWS_FILTER, false));
- cmb_filterOption.addItem(new FilterOption("Most Bound Molecules",
- "number_of_bound_molecules", VIEWS_FILTER, false));
- cmb_filterOption.addItem(new FilterOption("Most Polymer Residues",
- "number_of_polymer_residues", VIEWS_FILTER, true));
+ List<FilterOption> filters = data
+ .getAvailableFilterOptions(VIEWS_FILTER);
+ data.updateAvailableFilterOptions(VIEWS_FILTER, filters,
+ lastDiscoveredStructuresSet);
+ int p = 0;
+ for (FilterOption filter : filters)
+ {
+ if (lastSel != null && filter.equals(lastSel))
+ {
+ selSet = p;
+ }
+ p++;
+ cmb_filterOption.addItem(filter);
+ }
}
+
cmb_filterOption.addItem(
- new FilterOption("Enter PDB Id", "-", VIEWS_ENTER_ID, false));
+ new FilterOption(MessageManager.getString("label.enter_pdb_id"),
+ "-", VIEWS_ENTER_ID, false, null));
cmb_filterOption.addItem(
- new FilterOption("From File", "-", VIEWS_FROM_FILE, false));
+ new FilterOption(MessageManager.getString("label.from_file"),
+ "-", VIEWS_FROM_FILE, false, null));
+ if (canQueryTDB && notQueriedTDBYet)
+ {
+ btn_queryTDB.setVisible(true);
+ pnl_queryTDB.setVisible(true);
+ }
- if (cachedPDBExists)
+ if (cachedPDBExist)
{
- FilterOption cachedOption = new FilterOption("Cached PDB Entries",
- "-", VIEWS_LOCAL_PDB, false);
+ FilterOption cachedOption = new FilterOption(
+ MessageManager.getString("label.cached_structures"), "-",
+ VIEWS_LOCAL_PDB, false, null);
cmb_filterOption.addItem(cachedOption);
- cmb_filterOption.setSelectedItem(cachedOption);
+ if (selSet == -1)
+ {
+ cmb_filterOption.setSelectedItem(cachedOption);
+ }
+ }
+ if (selSet > -1)
+ {
+ cmb_filterOption.setSelectedIndex(selSet);
}
-
cmb_filterOption.addItemListener(this);
}
{
FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
.getSelectedItem());
+
+ if (lastSelected == selectedFilterOpt)
+ {
+ // don't need to do anything, probably
+ return;
+ }
+ // otherwise, record selection
+ // and update the layout and dialog accordingly
+ lastSelected = selectedFilterOpt;
+
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());
+ // TDB Query has no invert as yet
+ chk_invertFilter.setVisible(selectedFilterOpt
+ .getQuerySource() instanceof PDBStructureChooserQuerySource);
+
+ if (data != selectedFilterOpt.getQuerySource()
+ || data.needsRefetch(selectedFilterOpt))
+ {
+ data = selectedFilterOpt.getQuerySource();
+ // rebuild the views completely, since prefs will also change
+ tabRefresh();
+ return;
+ }
+ else
+ {
+ filterResultSet(selectedFilterOpt.getValue());
+ }
}
else if (selectedFilterOpt.getView() == VIEWS_ENTER_ID
|| selectedFilterOpt.getView() == VIEWS_FROM_FILE)
}
/**
- * Validates user selection and activates the view button if all parameters
- * are correct
+ * Validates user selection and enables the 'Add' and 'New View' buttons if
+ * all parameters are correct (the Add button will only be visible if there is
+ * at least one existing structure viewer open). This basically means at least
+ * one structure selected and no error messages.
+ * <p>
+ * The 'Superpose Structures' option is enabled if either more than one
+ * structure is selected, or the 'Add' to existing view option is enabled, and
+ * disabled if the only option is to open a new view of a single structure.
*/
@Override
- public void validateSelections()
+ protected void validateSelections()
{
FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
.getSelectedItem());
- btn_view.setEnabled(false);
+ btn_add.setEnabled(false);
String currentView = selectedFilterOpt.getView();
+ int selectedCount = 0;
if (currentView == VIEWS_FILTER)
{
- if (getResultTable().getSelectedRows().length > 0)
+ selectedCount = getResultTable().getSelectedRows().length;
+ if (selectedCount > 0)
{
- btn_view.setEnabled(true);
+ btn_add.setEnabled(true);
}
}
else if (currentView == VIEWS_LOCAL_PDB)
{
- if (tbl_local_pdb.getSelectedRows().length > 0)
+ selectedCount = tbl_local_pdb.getSelectedRows().length;
+ if (selectedCount > 0)
{
- btn_view.setEnabled(true);
+ btn_add.setEnabled(true);
}
}
else if (currentView == VIEWS_ENTER_ID)
{
validateAssociationFromFile();
}
+
+ btn_newView.setEnabled(btn_add.isEnabled());
+
+ /*
+ * enable 'Superpose' option if more than one structure is selected,
+ * or there are view(s) available to add structure(s) to
+ */
+ chk_superpose
+ .setEnabled(selectedCount > 1 || targetView.getItemCount() > 0);
+ }
+
+ @Override
+ protected boolean showPopupFor(int selectedRow, int x, int y)
+ {
+ FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
+ .getSelectedItem());
+ String currentView = selectedFilterOpt.getView();
+
+ if (currentView == VIEWS_FILTER
+ && data instanceof ThreeDBStructureChooserQuerySource)
+ {
+
+ TDB_FTSData row = ((ThreeDBStructureChooserQuerySource) data)
+ .getFTSDataFor(getResultTable(), selectedRow,
+ discoveredStructuresSet);
+ String pageUrl = row.getModelViewUrl();
+ JPopupMenu popup = new JPopupMenu("3D Beacons");
+ JMenuItem viewUrl = new JMenuItem("View model web page");
+ viewUrl.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ Desktop.showUrl(pageUrl);
+ }
+ });
+ popup.add(viewUrl);
+ SwingUtilities.invokeLater(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ popup.show(getResultTable(), x, y);
+ }
+ });
+ return true;
+ }
+ // event not handled by us
+ return false;
}
/**
* Validates inputs from the Manual PDB entry panel
*/
- public void validateAssociationEnterPdb()
+ protected void validateAssociationEnterPdb()
{
AssociateSeqOptions assSeqOpt = (AssociateSeqOptions) idInputAssSeqPanel
.getCmb_assSeq().getSelectedItem();
txt_search.setEnabled(true);
if (isValidPBDEntry)
{
- btn_view.setEnabled(true);
+ btn_add.setEnabled(true);
lbl_pdbManualFetchStatus.setToolTipText("");
lbl_pdbManualFetchStatus.setIcon(goodImage);
}
/**
* Validates inputs for the manual PDB file selection options
*/
- public void validateAssociationFromFile()
+ protected void validateAssociationFromFile()
{
AssociateSeqOptions assSeqOpt = (AssociateSeqOptions) fileChooserAssSeqPanel
.getCmb_assSeq().getSelectedItem();
- lbl_fromFileStatus.setIcon(errorImage);
+ // lbl_fromFileStatus.setIcon(errorImage);
+ String pdbFileString = "";
+ String pdbFileTooltip = "";
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);
+ btn_add.setEnabled(true);
+ // lbl_fromFileStatus.setIcon(goodImage);
+ pdbFileString = new File(selectedPdbFileName).getName();
+ pdbFileTooltip = new File(selectedPdbFileName).getAbsolutePath();
+ setPdbOptionsEnabled(true);
+ }
+ else
+ {
+ pdbFileString = MessageManager.getString("label.none");
+ pdbFileTooltip = MessageManager.getString("label.nothing_selected");
}
}
else
{
btn_pdbFromFile.setEnabled(false);
- lbl_fromFileStatus.setIcon(errorImage);
+ // lbl_fromFileStatus.setIcon(errorImage);
+ pdbFileString = MessageManager.getString("label.none");
+ pdbFileTooltip = MessageManager.getString("label.nothing_selected");
+ }
+ lbl_pdbFile.setText(pdbFileString);
+ lbl_pdbFile.setToolTipText(pdbFileTooltip);
+
+ // PAE file choice
+ String paeFileString = "";
+ String paeFileTooltip = "";
+ if (localPdbPaeMatrixFileName != null
+ && localPdbPaeMatrixFileName.length() > 0)
+ {
+ paeFileString = new File(localPdbPaeMatrixFileName).getName();
+ paeFileTooltip = new File(localPdbPaeMatrixFileName)
+ .getAbsolutePath();
+ }
+ else
+ {
+ paeFileString = MessageManager.getString("label.none");
+ paeFileTooltip = MessageManager.getString("label.nothing_selected");
}
+ lbl_paeFile.setText(paeFileString);
+ lbl_paeFile.setToolTipText(paeFileTooltip);
}
@Override
- public void cmbAssSeqStateChanged()
+ protected void cmbAssSeqStateChanged()
{
validateSelections();
}
+ private FilterOption lastSelected = null;
+
/**
* Handles the state change event for the 'filter' combo-box and 'invert'
* check-box
}
/**
- * Handles action event for btn_ok
+ * select structures for viewing by their PDB IDs
+ *
+ * @param pdbids
+ * @return true if structures were found and marked as selected
+ */
+ public boolean selectStructure(String... pdbids)
+ {
+ boolean found = false;
+
+ FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
+ .getSelectedItem());
+ String currentView = selectedFilterOpt.getView();
+ JTable restable = (currentView == VIEWS_FILTER) ? getResultTable()
+ : (currentView == VIEWS_LOCAL_PDB) ? tbl_local_pdb : null;
+
+ if (restable == null)
+ {
+ // can't select (enter PDB ID, or load file - need to also select which
+ // sequence to associate with)
+ return false;
+ }
+
+ int pdbIdColIndex = restable.getColumn("PDB Id").getModelIndex();
+ for (int r = 0; r < restable.getRowCount(); r++)
+ {
+ for (int p = 0; p < pdbids.length; p++)
+ {
+ if (String.valueOf(restable.getValueAt(r, pdbIdColIndex))
+ .equalsIgnoreCase(pdbids[p]))
+ {
+ restable.setRowSelectionInterval(r, r);
+ found = true;
+ }
+ }
+ }
+ return found;
+ }
+
+ /**
+ * Handles the 'New View' action
*/
@Override
- public void ok_ActionPerformed()
+ protected void newView_ActionPerformed()
{
+ targetView.setSelectedItem(null);
+ showStructures(false);
+ }
+
+ /**
+ * Handles the 'Add to existing viewer' action
+ */
+ @Override
+ protected void add_ActionPerformed()
+ {
+ showStructures(false);
+ }
+
+ /**
+ * structure viewer opened by this dialog, or null
+ */
+ private StructureViewer sViewer = null;
+
+ public void showStructures(boolean waitUntilFinished)
+ {
+
final StructureSelectionManager ssm = ap.getStructureSelectionManager();
final int preferredHeight = pnl_filter.getHeight();
- new Thread(new Runnable()
+ Runnable viewStruc = new Runnable()
{
@Override
public void run()
FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
.getSelectedItem());
String currentView = selectedFilterOpt.getView();
+ JTable restable = (currentView == VIEWS_FILTER) ? getResultTable()
+ : tbl_local_pdb;
+
if (currentView == VIEWS_FILTER)
{
- int pdbIdColIndex = getResultTable().getColumn("PDB Id")
- .getModelIndex();
- int refSeqColIndex = getResultTable().getColumn("Ref Sequence")
- .getModelIndex();
- int[] selectedRows = getResultTable().getSelectedRows();
+ int[] selectedRows = restable.getSelectedRows();
PDBEntry[] pdbEntriesToView = new PDBEntry[selectedRows.length];
- int count = 0;
List<SequenceI> selectedSeqsToView = new ArrayList<>();
- for (int row : selectedRows)
- {
- String pdbIdStr = getResultTable()
- .getValueAt(row, pdbIdColIndex).toString();
- SequenceI selectedSeq = (SequenceI) getResultTable()
- .getValueAt(row, refSeqColIndex);
- selectedSeqsToView.add(selectedSeq);
- PDBEntry pdbEntry = selectedSeq.getPDBEntry(pdbIdStr);
- if (pdbEntry == null)
- {
- pdbEntry = getFindEntry(pdbIdStr,
- selectedSeq.getAllPDBEntries());
- }
+ pdbEntriesToView = data.collectSelectedRows(restable,
+ selectedRows, selectedSeqsToView);
- if (pdbEntry == null)
- {
- pdbEntry = new PDBEntry();
- pdbEntry.setId(pdbIdStr);
- pdbEntry.setType(PDBEntry.Type.PDB);
- selectedSeq.getDatasetSequence().addPDBId(pdbEntry);
- }
- pdbEntriesToView[count++] = pdbEntry;
- }
SequenceI[] selectedSeqs = selectedSeqsToView
.toArray(new SequenceI[selectedSeqsToView.size()]);
- launchStructureViewer(ssm, pdbEntriesToView, ap, selectedSeqs);
+ sViewer = launchStructureViewer(ssm, pdbEntriesToView, ap,
+ selectedSeqs);
}
else if (currentView == VIEWS_LOCAL_PDB)
{
List<SequenceI> selectedSeqsToView = new ArrayList<>();
for (int row : selectedRows)
{
- PDBEntry pdbEntry = (PDBEntry) tbl_local_pdb.getValueAt(row,
- pdbIdColIndex);
+ PDBEntry pdbEntry = ((PDBEntryTableModel) tbl_local_pdb
+ .getModel()).getPDBEntryAt(row).getPdbEntry();
+
pdbEntriesToView[count++] = pdbEntry;
SequenceI selectedSeq = (SequenceI) tbl_local_pdb
.getValueAt(row, refSeqColIndex);
}
SequenceI[] selectedSeqs = selectedSeqsToView
.toArray(new SequenceI[selectedSeqsToView.size()]);
- launchStructureViewer(ssm, pdbEntriesToView, ap, selectedSeqs);
+ sViewer = launchStructureViewer(ssm, pdbEntriesToView, ap,
+ selectedSeqs);
}
else if (currentView == VIEWS_ENTER_ID)
{
if (pdbIdStr.split(":").length > 1)
{
pdbEntry.setId(pdbIdStr.split(":")[0]);
- pdbEntry.setChainCode(pdbIdStr.split(":")[1].toUpperCase());
+ pdbEntry.setChainCode(
+ pdbIdStr.split(":")[1].toUpperCase(Locale.ROOT));
}
else
{
}
PDBEntry[] pdbEntriesToView = new PDBEntry[] { pdbEntry };
- launchStructureViewer(ssm, pdbEntriesToView, ap,
+ sViewer = launchStructureViewer(ssm, pdbEntriesToView, ap,
new SequenceI[]
{ selectedSequence });
}
else if (currentView == VIEWS_FROM_FILE)
{
- SequenceI userSelectedSeq = ((AssociateSeqOptions) fileChooserAssSeqPanel
- .getCmb_assSeq().getSelectedItem()).getSequence();
+ TFType tft = (TFType) StructureChooser.this.combo_tempFacAs
+ .getSelectedItem();
+ String paeFilename = StructureChooser.this.localPdbPaeMatrixFileName;
+ AssociateSeqOptions assSeqOpt = (AssociateSeqOptions) fileChooserAssSeqPanel
+ .getCmb_assSeq().getSelectedItem();
+ SequenceI userSelectedSeq = assSeqOpt.getSequence();
if (userSelectedSeq != null)
- {
selectedSequence = userSelectedSeq;
- }
- PDBEntry fileEntry = new AssociatePdbFileWithSeq()
- .associatePdbWithSeq(selectedPdbFileName,
- DataSourceType.FILE, selectedSequence, true,
- Desktop.instance);
+ String pdbFilename = selectedPdbFileName;
- launchStructureViewer(ssm, new PDBEntry[] { fileEntry }, ap,
- new SequenceI[]
+ PDBEntry fileEntry = new AssociatePdbFileWithSeq()
+ .associatePdbWithSeq(pdbFilename, DataSourceType.FILE,
+ selectedSequence, true, Desktop.instance, tft,
+ paeFilename);
+
+ /*
+ SequenceI[] seqArray = new SequenceI[] { selectedSequence };
+
+ StructureFile sf = ssm.computeMapping(true, seqArray, null,
+ selectedPdbFileName, DataSourceType.FILE, null, tft,
+ paeFilename);
+ StructureMapping[] sm = ssm.getMapping(fileEntry.getFile());
+ // DO SOMETHING WITH
+ File paeFile = paeFilename == null ? null : new File(paeFilename);
+ if (paeFilename != null && paeFile.exists())
+ {
+ AlignmentI al = StructureChooser.this.ap.getAlignment();
+ try
+ {
+ EBIAlfaFold.importPaeJSONAsContactMatrixToSequence(al,
+ paeFile, selectedSequence);
+ } catch (IOException | ParseException e)
+ {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ */
+ sViewer = launchStructureViewer(ssm, new PDBEntry[] { fileEntry },
+ ap, new SequenceI[]
{ selectedSequence });
}
- closeAction(preferredHeight);
- mainFrame.dispose();
+ SwingUtilities.invokeLater(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ closeAction(preferredHeight);
+ mainFrame.dispose();
+ }
+ });
}
- }).start();
- }
-
- private PDBEntry getFindEntry(String id, Vector<PDBEntry> pdbEntries)
- {
- Objects.requireNonNull(id);
- Objects.requireNonNull(pdbEntries);
- PDBEntry foundEntry = null;
- for (PDBEntry entry : pdbEntries)
+ };
+ Thread runner = new Thread(viewStruc);
+ runner.start();
+ if (waitUntilFinished)
{
- if (entry.getId().equalsIgnoreCase(id))
+ while (sViewer == null ? runner.isAlive()
+ : (sViewer.sview == null ? true
+ : !sViewer.sview.hasMapping()))
{
- return entry;
+ try
+ {
+ Thread.sleep(300);
+ } catch (InterruptedException ie)
+ {
+
+ }
}
}
- return foundEntry;
}
- private void launchStructureViewer(StructureSelectionManager ssm,
- final PDBEntry[] pdbEntriesToView,
+ /**
+ * Answers a structure viewer (new or existing) configured to superimpose
+ * added structures or not according to the user's choice
+ *
+ * @param ssm
+ * @return
+ */
+ StructureViewer getTargetedStructureViewer(StructureSelectionManager ssm)
+ {
+ Object sv = targetView.getSelectedItem();
+
+ return sv == null ? new StructureViewer(ssm) : (StructureViewer) sv;
+ }
+
+ /**
+ * Adds PDB structures to a new or existing structure viewer
+ *
+ * @param ssm
+ * @param pdbEntriesToView
+ * @param alignPanel
+ * @param sequences
+ * @return
+ */
+ private StructureViewer launchStructureViewer(
+ StructureSelectionManager ssm, final PDBEntry[] pdbEntriesToView,
final AlignmentPanel alignPanel, SequenceI[] sequences)
{
long progressId = sequences.hashCode();
setProgressBar(MessageManager
.getString("status.launching_3d_structure_viewer"), progressId);
- final StructureViewer sViewer = new StructureViewer(ssm);
- setProgressBar(null, progressId);
+ final StructureViewer theViewer = getTargetedStructureViewer(ssm);
+ boolean superimpose = chk_superpose.isSelected();
+ theViewer.setSuperpose(superimpose);
+
+ /*
+ * remember user's choice of superimpose or not
+ */
+ Cache.setProperty(AUTOSUPERIMPOSE,
+ Boolean.valueOf(superimpose).toString());
+ setProgressBar(null, progressId);
if (SiftsSettings.isMapWithSifts())
{
List<SequenceI> seqsWithoutSourceDBRef = new ArrayList<>();
for (SequenceI seq : sequences)
{
PDBEntry pdbe = pdbEntriesToView[p++];
+ Console.debug(
+ "##### pdbe=" + pdbe == null ? null : pdbe.toString());
+ Console.debug("##### pdbe.getFile()=" + pdbe == null ? null
+ : pdbe.getFile());
if (pdbe != null && pdbe.getFile() != null)
{
StructureMapping[] smm = ssm.getMapping(pdbe.getFile());
}
}
}
- if (seq.getPrimaryDBRefs().size() == 0)
+ if (seq.getPrimaryDBRefs().isEmpty())
{
seqsWithoutSourceDBRef.add(seq);
continue;
setProgressBar(MessageManager.formatMessage(
"status.fetching_dbrefs_for_sequences_without_valid_refs",
y), progressId);
- SequenceI[] seqWithoutSrcDBRef = new SequenceI[y];
- int x = 0;
- for (SequenceI fSeq : seqsWithoutSourceDBRef)
- {
- seqWithoutSrcDBRef[x++] = fSeq;
- }
-
+ SequenceI[] seqWithoutSrcDBRef = seqsWithoutSourceDBRef
+ .toArray(new SequenceI[y]);
DBRefFetcher dbRefFetcher = new DBRefFetcher(seqWithoutSrcDBRef);
dbRefFetcher.fetchDBRefs(true);
}
if (pdbEntriesToView.length > 1)
{
- ArrayList<SequenceI[]> seqsMap = new ArrayList<>();
- for (SequenceI seq : sequences)
- {
- seqsMap.add(new SequenceI[] { seq });
- }
- SequenceI[][] collatedSeqs = seqsMap.toArray(new SequenceI[0][0]);
-
- setProgressBar(MessageManager
- .getString("status.fetching_3d_structures_for_selected_entries"), progressId);
- sViewer.viewStructures(pdbEntriesToView, collatedSeqs, alignPanel);
+ setProgressBar(
+ MessageManager.getString(
+ "status.fetching_3d_structures_for_selected_entries"),
+ progressId);
+ theViewer.viewStructures(pdbEntriesToView, sequences, alignPanel);
}
else
{
setProgressBar(MessageManager.formatMessage(
"status.fetching_3d_structures_for",
- pdbEntriesToView[0].getId()),progressId);
- sViewer.viewStructures(pdbEntriesToView[0], sequences, alignPanel);
+ pdbEntriesToView[0].getId()), progressId);
+ // Can we pass a pre-computeMappinged pdbFile?
+ theViewer.viewStructures(pdbEntriesToView[0], sequences, alignPanel);
}
setProgressBar(null, progressId);
+ // remember the last viewer we used...
+ lastTargetedView = theViewer;
+ return theViewer;
}
/**
* a unique sequence when more than one sequence selection is made.
*/
@Override
- public void populateCmbAssociateSeqOptions(
+ protected void populateCmbAssociateSeqOptions(
JComboBox<AssociateSeqOptions> cmb_assSeq,
JLabel lbl_associateSeq)
{
}
}
- public boolean isStructuresDiscovered()
+ protected boolean isStructuresDiscovered()
{
return discoveredStructuresSet != null
&& !discoveredStructuresSet.isEmpty();
}
- public Collection<FTSData> getDiscoveredStructuresSet()
- {
- return discoveredStructuresSet;
- }
+ protected int PDB_ID_MIN = 3;// or: (Jalview.isJS() ? 3 : 1); // Bob proposes
+ // this.
+ // Doing a search for "1" or "1c" is valuable?
+ // Those work but are enormously slow.
@Override
protected void txt_search_ActionPerformed()
{
- new Thread()
- {
- @Override
- public void run()
+ String text = txt_search.getText().trim();
+ if (text.length() >= PDB_ID_MIN)
+ new Thread()
{
- errorWarning.setLength(0);
- isValidPBDEntry = false;
- if (txt_search.getText().length() > 0)
+
+ @Override
+ public void run()
{
- String searchTerm = txt_search.getText().toLowerCase();
- searchTerm = searchTerm.split(":")[0];
- // System.out.println(">>>>> search term : " + searchTerm);
- List<FTSDataColumnI> wantedFields = new ArrayList<>();
- FTSRestRequest pdbRequest = new FTSRestRequest();
- pdbRequest.setAllowEmptySeq(false);
- pdbRequest.setResponseSize(1);
- pdbRequest.setFieldToSearchBy("(pdb_id:");
- pdbRequest.setWantedFields(wantedFields);
- pdbRequest.setSearchTerm(searchTerm + ")");
- pdbRequest.setAssociatedSequence(selectedSequence);
- pdbRestCleint = PDBFTSRestClient.getInstance();
- wantedFields.add(pdbRestCleint.getPrimaryKeyColumn());
- FTSRestResponse resultList;
- try
- {
- resultList = pdbRestCleint.executeRequest(pdbRequest);
- } catch (Exception e)
- {
- errorWarning.append(e.getMessage());
- return;
- } finally
- {
- validateSelections();
- }
- if (resultList.getSearchSummary() != null
- && resultList.getSearchSummary().size() > 0)
+ errorWarning.setLength(0);
+ isValidPBDEntry = false;
+ if (text.length() > 0)
{
- isValidPBDEntry = true;
+ // TODO move this pdb id search into the PDB specific
+ // FTSSearchEngine
+ // for moment, it will work fine as is because it is self-contained
+ String searchTerm = text.toLowerCase(Locale.ROOT);
+ searchTerm = searchTerm.split(":")[0];
+ // System.out.println(">>>>> search term : " + searchTerm);
+ List<FTSDataColumnI> wantedFields = new ArrayList<>();
+ FTSRestRequest pdbRequest = new FTSRestRequest();
+ pdbRequest.setAllowEmptySeq(false);
+ pdbRequest.setResponseSize(1);
+ pdbRequest.setFieldToSearchBy("(pdb_id:");
+ pdbRequest.setWantedFields(wantedFields);
+ pdbRequest.setSearchTerm(searchTerm + ")");
+ pdbRequest.setAssociatedSequence(selectedSequence);
+ FTSRestClientI pdbRestClient = PDBFTSRestClient.getInstance();
+ wantedFields.add(pdbRestClient.getPrimaryKeyColumn());
+ FTSRestResponse resultList;
+ try
+ {
+ resultList = pdbRestClient.executeRequest(pdbRequest);
+ } catch (Exception e)
+ {
+ errorWarning.append(e.getMessage());
+ return;
+ } finally
+ {
+ validateSelections();
+ }
+ if (resultList.getSearchSummary() != null
+ && resultList.getSearchSummary().size() > 0)
+ {
+ isValidPBDEntry = true;
+ }
}
+ validateSelections();
}
- validateSelections();
- }
- }.start();
+ }.start();
}
@Override
- public void tabRefresh()
+ protected void tabRefresh()
{
if (selectedSequences != null)
{
+ lbl_loading.setVisible(true);
Thread refreshThread = new Thread(new Runnable()
{
@Override
public void run()
{
fetchStructuresMetaData();
+ // populateFilterComboBox(true, cachedPDBExists);
+
filterResultSet(
((FilterOption) cmb_filterOption.getSelectedItem())
.getValue());
+ lbl_loading.setVisible(false);
}
});
refreshThread.start();
value = entry.getSequence();
break;
case 1:
- value = entry.getPdbEntry();
+ value = entry.getQualifiedId();
break;
case 2:
value = entry.getPdbEntry().getChainCode() == null ? "_"
this.pdbEntry = pdbEntry;
}
+ public String getQualifiedId()
+ {
+ if (pdbEntry.hasProvider())
+ {
+ return pdbEntry.getProvider() + ":" + pdbEntry.getId();
+ }
+ return pdbEntry.toString();
+ }
+
public SequenceI getSequence()
{
return sequence;
@Override
public void setProgressBar(String message, long id)
{
- progressBar.setProgressBar(message, id);
+ if (!Platform.isHeadless())
+ progressBar.setProgressBar(message, id);
}
@Override
{
return progressBar.operationInProgress();
}
+
+ public JalviewStructureDisplayI getOpenedStructureViewer()
+ {
+ return sViewer == null ? null : sViewer.sview;
+ }
+
+ @Override
+ protected void setFTSDocFieldPrefs(FTSDataColumnPreferences newPrefs)
+ {
+ data.setDocFieldPrefs(newPrefs);
+
+ }
+
+ /**
+ *
+ * @return true when all initialisation threads have finished and dialog is
+ * visible
+ */
+ public boolean isDialogVisible()
+ {
+ return mainFrame != null && data != null && cmb_filterOption != null
+ && mainFrame.isVisible()
+ && cmb_filterOption.getSelectedItem() != null;
+ }
+
+ /**
+ *
+ * @return true if the 3D-Beacons query button will/has been displayed
+ */
+ public boolean isCanQueryTDB()
+ {
+ return canQueryTDB;
+ }
+
+ public boolean isNotQueriedTDBYet()
+ {
+ return notQueriedTDBYet;
+ }
+
+ /**
+ * Open a single structure file for a given sequence
+ */
+ public static void openStructureFileForSequence(AlignmentPanel ap,
+ SequenceI seq, File sFile)
+ {
+ // Open the chooser headlessly. Not sure this is actually needed ?
+ StructureChooser sc = new StructureChooser(new SequenceI[] { seq }, seq,
+ ap, false);
+ StructureSelectionManager ssm = ap.getStructureSelectionManager();
+ PDBEntry fileEntry = null;
+ try
+ {
+ fileEntry = new AssociatePdbFileWithSeq().associatePdbWithSeq(
+ sFile.getAbsolutePath(), DataSourceType.FILE, seq, true,
+ Desktop.instance);
+ } catch (Exception e)
+ {
+ Console.error("Could not open structure file '"
+ + sFile.getAbsolutePath() + "'");
+ return;
+ }
+
+ StructureViewer sViewer = sc.launchStructureViewer(ssm,
+ new PDBEntry[]
+ { fileEntry }, ap, new SequenceI[] { seq });
+
+ sc.mainFrame.dispose();
+ }
}