2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ 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 java.awt.event.ActionEvent;
25 import java.awt.event.ActionListener;
26 import java.awt.event.ItemEvent;
28 import java.util.ArrayList;
29 import java.util.Collection;
30 import java.util.HashSet;
31 import java.util.LinkedHashMap;
32 import java.util.LinkedHashSet;
33 import java.util.List;
34 import java.util.Locale;
36 import java.util.concurrent.Executors;
38 import javax.swing.JCheckBox;
39 import javax.swing.JComboBox;
40 import javax.swing.JLabel;
41 import javax.swing.JMenuItem;
42 import javax.swing.JPopupMenu;
43 import javax.swing.JTable;
44 import javax.swing.SwingUtilities;
45 import javax.swing.table.AbstractTableModel;
47 import com.stevesoft.pat.Regex;
49 import jalview.analysis.AlignmentUtils;
50 import jalview.api.AlignmentViewPanel;
51 import jalview.api.structures.JalviewStructureDisplayI;
52 import jalview.bin.Cache;
53 import jalview.bin.Console;
54 import jalview.bin.Jalview;
55 import jalview.datamodel.AlignmentAnnotation;
56 import jalview.datamodel.AlignmentI;
57 import jalview.datamodel.PDBEntry;
58 import jalview.datamodel.SequenceGroup;
59 import jalview.datamodel.SequenceI;
60 import jalview.ext.jmol.JmolParser;
61 import jalview.fts.api.FTSData;
62 import jalview.fts.api.FTSDataColumnI;
63 import jalview.fts.api.FTSRestClientI;
64 import jalview.fts.core.FTSDataColumnPreferences;
65 import jalview.fts.core.FTSRestRequest;
66 import jalview.fts.core.FTSRestResponse;
67 import jalview.fts.service.pdb.PDBFTSRestClient;
68 import jalview.fts.service.threedbeacons.TDB_FTSData;
69 import jalview.gui.StructureViewer.ViewerType;
70 import jalview.gui.structurechooser.PDBStructureChooserQuerySource;
71 import jalview.gui.structurechooser.StructureChooserQuerySource;
72 import jalview.gui.structurechooser.ThreeDBStructureChooserQuerySource;
73 import jalview.io.DataSourceType;
74 import jalview.io.FileFormatException;
75 import jalview.io.JalviewFileChooser;
76 import jalview.io.JalviewFileView;
77 import jalview.jbgui.FilterOption;
78 import jalview.jbgui.GStructureChooser;
79 import jalview.structure.StructureImportSettings.TFType;
80 import jalview.structure.StructureMapping;
81 import jalview.structure.StructureSelectionManager;
82 import jalview.util.MessageManager;
83 import jalview.util.Platform;
84 import jalview.util.StringUtils;
85 import jalview.ws.DBRefFetcher;
86 import jalview.ws.DBRefFetcher.FetchFinishedListenerI;
87 import jalview.ws.datamodel.alphafold.PAEContactMatrix;
88 import jalview.ws.dbsources.EBIAlfaFold;
89 import jalview.ws.seqfetcher.DbSourceProxy;
90 import jalview.ws.sifts.SiftsSettings;
93 * Provides the behaviors for the Structure chooser Panel
98 @SuppressWarnings("serial")
99 public class StructureChooser extends GStructureChooser
100 implements IProgressIndicator
102 private static final String AUTOSUPERIMPOSE = "AUTOSUPERIMPOSE";
105 * warn user if need to fetch more than this many uniprot records at once
107 private static final int THRESHOLD_WARN_UNIPROT_FETCH_NEEDED = 20;
109 private SequenceI selectedSequence;
111 private SequenceI[] selectedSequences;
113 private IProgressIndicator progressIndicator;
115 private Collection<FTSData> discoveredStructuresSet;
117 private StructureChooserQuerySource data;
120 protected FTSDataColumnPreferences getFTSDocFieldPrefs()
122 return data.getDocFieldPrefs();
125 private String selectedPdbFileName;
127 private TFType localPdbTempfacType;
129 private String localPdbPaeMatrixFileName;
131 private boolean isValidPBDEntry;
133 private boolean cachedPDBExists;
135 private Collection<FTSData> lastDiscoveredStructuresSet;
137 private boolean canQueryTDB = false;
139 private boolean notQueriedTDBYet = true;
141 List<SequenceI> seqsWithoutSourceDBRef = null;
143 private boolean showChooserGUI = true;
145 private static StructureViewer lastTargetedView = null;
147 public StructureChooser(SequenceI[] selectedSeqs, SequenceI selectedSeq,
150 this(selectedSeqs, selectedSeq, ap, true);
153 public StructureChooser(SequenceI[] selectedSeqs, SequenceI selectedSeq,
154 AlignmentPanel ap, boolean showGUI)
156 // which FTS engine to use
157 data = StructureChooserQuerySource.getQuerySourceFor(selectedSeqs);
161 this.selectedSequence = selectedSeq;
162 this.selectedSequences = selectedSeqs;
163 this.progressIndicator = (ap == null) ? null : ap.alignFrame;
164 this.showChooserGUI = showGUI;
170 * sets canQueryTDB if protein sequences without a canonical uniprot ref or at
171 * least one structure are discovered.
173 private void populateSeqsWithoutSourceDBRef()
175 seqsWithoutSourceDBRef = new ArrayList<SequenceI>();
176 boolean needCanonical = false;
177 for (SequenceI seq : selectedSequences)
181 int dbRef = ThreeDBStructureChooserQuerySource
182 .checkUniprotRefs(seq.getDBRefs());
187 // need to retrieve canonicals
188 needCanonical = true;
189 seqsWithoutSourceDBRef.add(seq);
193 // could be a sequence with pdb ref
194 if (seq.getAllPDBEntries() == null
195 || seq.getAllPDBEntries().size() == 0)
197 seqsWithoutSourceDBRef.add(seq);
203 // retrieve database refs for protein sequences
204 if (!seqsWithoutSourceDBRef.isEmpty())
209 // triggers display of the 'Query TDB' button
210 notQueriedTDBYet = true;
216 * Initializes parameters used by the Structure Chooser Panel
218 protected void init()
220 if (!Jalview.isHeadlessMode())
222 progressBar = new ProgressBar(this.statusPanel, this.statusBar);
225 chk_superpose.setSelected(Cache.getDefault(AUTOSUPERIMPOSE, true));
226 btn_queryTDB.addActionListener(new ActionListener()
230 public void actionPerformed(ActionEvent e)
232 promptForTDBFetch(false);
236 Executors.defaultThreadFactory().newThread(new Runnable()
241 populateSeqsWithoutSourceDBRef();
242 initialStructureDiscovery();
250 private void initialStructureDiscovery()
252 // check which FTS engine to use
253 data = StructureChooserQuerySource.getQuerySourceFor(selectedSequences);
255 // ensure a filter option is in force for search
256 populateFilterComboBox(true, cachedPDBExists);
258 // looks for any existing structures already loaded
259 // for the sequences (the cached ones)
260 // then queries the StructureChooserQuerySource to
261 // discover more structures.
263 // Possible optimisation is to only begin querying
264 // the structure chooser if there are no cached structures.
266 long startTime = System.currentTimeMillis();
267 updateProgressIndicator(
268 MessageManager.getString("status.loading_cached_pdb_entries"),
270 loadLocalCachedPDBEntries();
271 updateProgressIndicator(null, startTime);
272 updateProgressIndicator(
273 MessageManager.getString("status.searching_for_pdb_structures"),
275 fetchStructuresMetaData();
276 // revise filter options if no results were found
277 populateFilterComboBox(isStructuresDiscovered(), cachedPDBExists);
278 discoverStructureViews();
279 updateProgressIndicator(null, startTime);
280 mainFrame.setVisible(showChooserGUI);
285 * raises dialog for Uniprot fetch followed by 3D beacons search
288 * - when true, don't ask, just fetch
290 public void promptForTDBFetch(boolean ignoreGui)
292 final long progressId = System.currentTimeMillis();
294 // final action after prompting and discovering db refs
295 final Runnable strucDiscovery = new Runnable()
300 mainFrame.setEnabled(false);
301 cmb_filterOption.setEnabled(false);
302 progressBar.setProgressBar(
303 MessageManager.getString("status.searching_3d_beacons"),
305 btn_queryTDB.setEnabled(false);
306 // TODO: warn if no accessions discovered
307 populateSeqsWithoutSourceDBRef();
308 // redo initial discovery - this time with 3d beacons
310 previousWantedFields = null;
311 lastSelected = (FilterOption) cmb_filterOption.getSelectedItem();
312 cmb_filterOption.setSelectedItem(null);
313 cachedPDBExists = false; // reset to initial
314 initialStructureDiscovery();
315 if (!isStructuresDiscovered())
317 progressBar.setProgressBar(MessageManager.getString(
318 "status.no_structures_discovered_from_3d_beacons"),
320 btn_queryTDB.setToolTipText(MessageManager.getString(
321 "status.no_structures_discovered_from_3d_beacons"));
322 btn_queryTDB.setEnabled(false);
323 pnl_queryTDB.setVisible(false);
327 cmb_filterOption.setSelectedIndex(0); // select 'best'
328 btn_queryTDB.setVisible(false);
329 pnl_queryTDB.setVisible(false);
330 progressBar.setProgressBar(null, progressId);
332 mainFrame.setEnabled(true);
333 cmb_filterOption.setEnabled(true);
337 final FetchFinishedListenerI afterDbRefFetch = new FetchFinishedListenerI()
341 public void finished()
343 // filter has been selected, so we set flag to remove ourselves
344 notQueriedTDBYet = false;
345 // new thread to discover structures - via 3d beacons
346 Executors.defaultThreadFactory().newThread(strucDiscovery).start();
351 // fetch db refs if OK pressed
352 final Runnable discoverCanonicalDBrefs = () -> {
353 btn_queryTDB.setEnabled(false);
354 populateSeqsWithoutSourceDBRef();
356 final int y = seqsWithoutSourceDBRef.size();
359 final SequenceI[] seqWithoutSrcDBRef = seqsWithoutSourceDBRef
360 .toArray(new SequenceI[y]);
361 DBRefFetcher dbRefFetcher = new DBRefFetcher(seqWithoutSrcDBRef,
362 progressBar, new DbSourceProxy[]
363 { new jalview.ws.dbsources.Uniprot() }, null, false);
364 dbRefFetcher.addListener(afterDbRefFetch);
365 // ideally this would also gracefully run with callbacks
367 dbRefFetcher.fetchDBRefs(true);
371 // call finished action directly
372 afterDbRefFetch.finished();
375 final Runnable revertview = () -> {
376 if (lastSelected != null)
378 cmb_filterOption.setSelectedItem(lastSelected);
381 int threshold = Cache.getDefault("UNIPROT_AUTOFETCH_THRESHOLD",
382 THRESHOLD_WARN_UNIPROT_FETCH_NEEDED);
383 Console.debug("Using Uniprot fetch threshold of " + threshold);
384 if (ignoreGui || seqsWithoutSourceDBRef.size() < threshold)
386 Executors.newSingleThreadExecutor().submit(discoverCanonicalDBrefs);
389 // need cancel and no to result in the discoverPDB action - mocked is
390 // 'cancel' TODO: mock should be OK
392 StructureChooser thisSC = this;
393 JvOptionPane.newOptionDialog(thisSC.getFrame())
394 .setResponseHandler(JvOptionPane.OK_OPTION,
395 discoverCanonicalDBrefs)
396 .setResponseHandler(JvOptionPane.CANCEL_OPTION, revertview)
397 .setResponseHandler(JvOptionPane.NO_OPTION, revertview)
399 MessageManager.formatMessage(
400 "label.fetch_references_for_3dbeacons",
401 seqsWithoutSourceDBRef.size()),
402 MessageManager.getString("label.3dbeacons"),
403 JvOptionPane.YES_NO_OPTION, JvOptionPane.PLAIN_MESSAGE,
405 { MessageManager.getString("action.ok"),
406 MessageManager.getString("action.cancel") },
407 MessageManager.getString("action.ok"), false);
411 * Builds a drop-down choice list of existing structure viewers to which new
412 * structures may be added. If this list is empty then it, and the 'Add'
413 * button, are hidden.
415 private void discoverStructureViews()
417 if (Desktop.instance != null)
419 targetView.removeAllItems();
420 if (lastTargetedView != null && !lastTargetedView.isVisible())
422 lastTargetedView = null;
424 int linkedViewsAt = 0;
425 for (StructureViewerBase view : Desktop.instance
426 .getStructureViewers(null, null))
428 StructureViewer viewHandler = (lastTargetedView != null
429 && lastTargetedView.sview == view) ? lastTargetedView
430 : StructureViewer.reconfigure(view);
432 if (view.isLinkedWith(ap))
434 targetView.insertItemAt(viewHandler, linkedViewsAt++);
438 targetView.addItem(viewHandler);
443 * show option to Add to viewer if at least 1 viewer found
445 targetView.setVisible(false);
446 if (targetView.getItemCount() > 0)
448 targetView.setVisible(true);
449 if (lastTargetedView != null)
451 targetView.setSelectedItem(lastTargetedView);
455 targetView.setSelectedIndex(0);
458 btn_add.setVisible(targetView.isVisible());
463 * Updates the progress indicator with the specified message
466 * displayed message for the operation
468 * unique handle for this indicator
470 protected void updateProgressIndicator(String message, long id)
472 if (progressIndicator != null)
474 progressIndicator.setProgressBar(message, id);
479 * Retrieve meta-data for all the structure(s) for a given sequence(s) in a
482 void fetchStructuresMetaData()
484 long startTime = System.currentTimeMillis();
485 Collection<FTSDataColumnI> wantedFields = data.getDocFieldPrefs()
486 .getStructureSummaryFields();
488 discoveredStructuresSet = new LinkedHashSet<>();
489 HashSet<String> errors = new HashSet<>();
491 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
494 for (SequenceI seq : selectedSequences)
497 FTSRestResponse resultList;
500 resultList = data.fetchStructuresMetaData(seq, wantedFields,
501 selectedFilterOpt, !chk_invertFilter.isSelected());
502 // null response means the FTSengine didn't yield a query for this
503 // consider designing a special exception if we really wanted to be
505 if (resultList == null)
509 } catch (Exception e)
511 Console.debugPrintStackTrace(e);
512 errors.add(e.getMessage());
515 if (resultList.getSearchSummary() != null
516 && !resultList.getSearchSummary().isEmpty())
518 discoveredStructuresSet.addAll(resultList.getSearchSummary());
522 int noOfStructuresFound = 0;
523 String totalTime = (System.currentTimeMillis() - startTime)
525 if (discoveredStructuresSet != null
526 && !discoveredStructuresSet.isEmpty())
529 .setModel(data.getTableModel(discoveredStructuresSet));
531 noOfStructuresFound = discoveredStructuresSet.size();
532 lastDiscoveredStructuresSet = discoveredStructuresSet;
533 mainFrame.setTitle(MessageManager.formatMessage(
534 "label.structure_chooser_no_of_structures",
535 noOfStructuresFound, totalTime));
539 mainFrame.setTitle(MessageManager
540 .getString("label.structure_chooser_manual_association"));
541 if (errors.size() > 0)
543 StringBuilder errorMsg = new StringBuilder();
544 for (String error : errors)
546 errorMsg.append(error).append("\n");
548 if (!Jalview.isHeadlessMode())
550 JvOptionPane.showMessageDialog(this, errorMsg.toString(),
551 MessageManager.getString("label.pdb_web-service_error"),
552 JvOptionPane.ERROR_MESSAGE);
557 MessageManager.getString("label.pdb_web-service_error"));
558 Console.debug(errorMsg.toString());
564 protected void loadLocalCachedPDBEntries()
566 ArrayList<CachedPDB> entries = new ArrayList<>();
567 for (SequenceI seq : selectedSequences)
569 if (seq.getDatasetSequence() != null
570 && seq.getDatasetSequence().getAllPDBEntries() != null)
572 for (PDBEntry pdbEntry : seq.getDatasetSequence()
575 if (pdbEntry.getFile() != null)
577 entries.add(new CachedPDB(seq, pdbEntry));
582 cachedPDBExists = !entries.isEmpty();
583 PDBEntryTableModel tableModelx = new PDBEntryTableModel(entries);
584 tbl_local_pdb.setModel(tableModelx);
588 * Filters a given list of discovered structures based on supplied argument
590 * @param fieldToFilterBy
591 * the field to filter by
593 void filterResultSet(final String fieldToFilterBy)
595 Thread filterThread = new Thread(new Runnable()
601 long startTime = System.currentTimeMillis();
602 lbl_loading.setVisible(true);
603 Collection<FTSDataColumnI> wantedFields = data.getDocFieldPrefs()
604 .getStructureSummaryFields();
605 Collection<FTSData> filteredResponse = new HashSet<>();
606 HashSet<String> errors = new HashSet<>();
608 for (SequenceI seq : selectedSequences)
611 FTSRestResponse resultList;
614 resultList = data.selectFirstRankedQuery(seq,
615 discoveredStructuresSet, wantedFields, fieldToFilterBy,
616 !chk_invertFilter.isSelected());
618 } catch (Exception e)
620 Console.debugPrintStackTrace(e);
621 errors.add(e.getMessage());
624 if (resultList.getSearchSummary() != null
625 && !resultList.getSearchSummary().isEmpty())
627 filteredResponse.addAll(resultList.getSearchSummary());
631 String totalTime = (System.currentTimeMillis() - startTime)
633 if (!filteredResponse.isEmpty())
635 final int filterResponseCount = filteredResponse.size();
636 Collection<FTSData> reorderedStructuresSet = new LinkedHashSet<>();
637 reorderedStructuresSet.addAll(filteredResponse);
638 reorderedStructuresSet.addAll(discoveredStructuresSet);
640 .setModel(data.getTableModel(reorderedStructuresSet));
642 FTSRestResponse.configureTableColumn(getResultTable(),
643 wantedFields, tempUserPrefs);
644 getResultTable().getColumn("Ref Sequence").setPreferredWidth(120);
645 getResultTable().getColumn("Ref Sequence").setMinWidth(100);
646 getResultTable().getColumn("Ref Sequence").setMaxWidth(200);
647 // Update table selection model here
648 getResultTable().addRowSelectionInterval(0,
649 filterResponseCount - 1);
650 mainFrame.setTitle(MessageManager.formatMessage(
651 "label.structure_chooser_filter_time", totalTime));
655 mainFrame.setTitle(MessageManager.formatMessage(
656 "label.structure_chooser_filter_time", totalTime));
657 if (errors.size() > 0)
659 StringBuilder errorMsg = new StringBuilder();
660 for (String error : errors)
662 errorMsg.append(error).append("\n");
664 JvOptionPane.showMessageDialog(null, errorMsg.toString(),
665 MessageManager.getString("label.pdb_web-service_error"),
666 JvOptionPane.ERROR_MESSAGE);
670 lbl_loading.setVisible(false);
672 validateSelections();
675 filterThread.start();
679 * Handles action event for btn_pdbFromFile
682 protected void pdbFromFile_actionPerformed()
684 // TODO: JAL-3048 not needed for Jalview-JS until JSmol dep and
687 JalviewFileChooser chooser = new JalviewFileChooser(
688 Cache.getProperty("LAST_DIRECTORY"));
689 chooser.setFileView(new JalviewFileView());
690 chooser.setDialogTitle(
691 MessageManager.formatMessage("label.select_pdb_file_for",
692 selectedSequence.getDisplayId(false)));
693 chooser.setToolTipText(MessageManager.formatMessage(
694 "label.load_pdb_file_associate_with_sequence",
695 selectedSequence.getDisplayId(false)));
697 int value = chooser.showOpenDialog(null);
698 if (value == JalviewFileChooser.APPROVE_OPTION)
700 selectedPdbFileName = chooser.getSelectedFile().getPath();
701 Cache.setProperty("LAST_DIRECTORY", selectedPdbFileName);
702 boolean guessTFType = localPdbPaeMatrixFileName == null;
703 localPdbPaeMatrixFileName = guessPAEFilename();
704 guessTFType |= localPdbPaeMatrixFileName != null;
705 Regex alphaFold = JmolParser.getNewAlphafoldValidator();
707 && alphaFold.search(new File(selectedPdbFileName).getName())
708 && !tempFacAsChanged)
710 // localPdbPaeMatrixFileName was null and now isn't and filename could
711 // well be AlphaFold and user hasn't adjusted the tempFacType
712 combo_tempFacAs.setSelectedItem(TFType.PLDDT);
714 validateSelections();
719 * Handles action event for btn_paeMatrixFile
722 protected void paeMatrixFile_actionPerformed()
724 File pdbFile = new File(selectedPdbFileName);
725 String setFile = Cache.getProperty("LAST_DIRECTORY");
726 if (localPdbPaeMatrixFileName != null)
728 File paeFile = new File(localPdbPaeMatrixFileName);
729 if (paeFile.exists())
730 setFile = paeFile.getAbsolutePath();
731 else if (paeFile.getParentFile().exists())
732 setFile = paeFile.getParentFile().getAbsolutePath();
736 String guess = guessPAEFilename();
740 JalviewFileChooser chooser = new JalviewFileChooser(setFile);
741 chooser.setFileView(new JalviewFileView());
742 chooser.setDialogTitle(MessageManager.formatMessage(
743 "label.select_pae_matrix_file_for", pdbFile.getName()));
744 chooser.setToolTipText(MessageManager.formatMessage(
745 "label.load_pae_matrix_file_associate_with_structure",
748 // TODO convert to Callable/Promise
749 int value = chooser.showOpenDialog(null);
750 if (value == JalviewFileChooser.APPROVE_OPTION)
752 String fileName = chooser.getSelectedFile().getPath();
755 PAEContactMatrix.validateContactMatrixFile(fileName);
756 } catch (Exception thr)
758 JvOptionPane.showInternalMessageDialog(this, MessageManager
759 .formatMessage("label.couldnt_load_file", new Object[]
760 { fileName }) + "<br>" + thr.getLocalizedMessage(),
761 MessageManager.getString("label.error_loading_file"),
762 JvOptionPane.WARNING_MESSAGE);
763 Console.error("Couldn't import " + fileName + " as a PAE matrix",
767 localPdbPaeMatrixFileName = fileName;
768 Cache.setProperty("LAST_DIRECTORY", localPdbPaeMatrixFileName);
770 validateAssociationFromFile();
773 private String guessPAEFilename()
775 if (selectedPdbFileName.toLowerCase(Locale.ROOT).endsWith(".pdb")
776 || selectedPdbFileName.toLowerCase(Locale.ROOT)
779 String jsonExt = selectedPdbFileName.substring(0,
780 selectedPdbFileName.length() - 4) + ".json";
781 // AlphaFold naming scheme
782 String guessFile1 = StringUtils.replaceLast(jsonExt, "model",
783 "predicted_aligned_error");
784 // nf-core mode naming scheme
785 String guessFile2 = StringUtils.replaceLast(jsonExt, ".json",
787 if (new File(guessFile1).exists())
791 else if (new File(jsonExt).exists())
795 else if (new File(guessFile2).exists())
804 * Populates the filter combo-box options dynamically depending on discovered
807 protected void populateFilterComboBox(boolean haveData,
808 boolean cachedPDBExist)
810 populateFilterComboBox(haveData, cachedPDBExist, null);
814 * Populates the filter combo-box options dynamically depending on discovered
817 protected void populateFilterComboBox(boolean haveData,
818 boolean cachedPDBExist, FilterOption lastSel)
822 * temporarily suspend the change listener behaviour
824 cmb_filterOption.removeItemListener(this);
826 cmb_filterOption.removeAllItems();
829 List<FilterOption> filters = data
830 .getAvailableFilterOptions(VIEWS_FILTER);
831 data.updateAvailableFilterOptions(VIEWS_FILTER, filters,
832 lastDiscoveredStructuresSet);
834 for (FilterOption filter : filters)
836 if (lastSel != null && filter.equals(lastSel))
841 cmb_filterOption.addItem(filter);
845 cmb_filterOption.addItem(
846 new FilterOption(MessageManager.getString("label.enter_pdb_id"),
847 "-", VIEWS_ENTER_ID, false, null));
848 cmb_filterOption.addItem(
849 new FilterOption(MessageManager.getString("label.from_file"),
850 "-", VIEWS_FROM_FILE, false, null));
851 if (canQueryTDB && notQueriedTDBYet)
853 btn_queryTDB.setVisible(true);
854 pnl_queryTDB.setVisible(true);
859 FilterOption cachedOption = new FilterOption(
860 MessageManager.getString("label.cached_structures"), "-",
861 VIEWS_LOCAL_PDB, false, null);
862 cmb_filterOption.addItem(cachedOption);
865 cmb_filterOption.setSelectedItem(cachedOption);
870 cmb_filterOption.setSelectedIndex(selSet);
872 cmb_filterOption.addItemListener(this);
876 * Updates the displayed view based on the selected filter option
878 protected void updateCurrentView()
880 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
883 if (lastSelected == selectedFilterOpt)
885 // don't need to do anything, probably
888 // otherwise, record selection
889 // and update the layout and dialog accordingly
890 lastSelected = selectedFilterOpt;
892 layout_switchableViews.show(pnl_switchableViews,
893 selectedFilterOpt.getView());
894 String filterTitle = mainFrame.getTitle();
895 mainFrame.setTitle(frameTitle);
896 chk_invertFilter.setVisible(false);
898 if (selectedFilterOpt.getView() == VIEWS_FILTER)
900 mainFrame.setTitle(filterTitle);
901 // TDB Query has no invert as yet
902 chk_invertFilter.setVisible(selectedFilterOpt
903 .getQuerySource() instanceof PDBStructureChooserQuerySource);
905 if (data != selectedFilterOpt.getQuerySource()
906 || data.needsRefetch(selectedFilterOpt))
908 data = selectedFilterOpt.getQuerySource();
909 // rebuild the views completely, since prefs will also change
915 filterResultSet(selectedFilterOpt.getValue());
918 else if (selectedFilterOpt.getView() == VIEWS_ENTER_ID
919 || selectedFilterOpt.getView() == VIEWS_FROM_FILE)
921 mainFrame.setTitle(MessageManager
922 .getString("label.structure_chooser_manual_association"));
923 idInputAssSeqPanel.loadCmbAssSeq();
924 fileChooserAssSeqPanel.loadCmbAssSeq();
926 validateSelections();
930 * Validates user selection and enables the 'Add' and 'New View' buttons if
931 * all parameters are correct (the Add button will only be visible if there is
932 * at least one existing structure viewer open). This basically means at least
933 * one structure selected and no error messages.
935 * The 'Superpose Structures' option is enabled if either more than one
936 * structure is selected, or the 'Add' to existing view option is enabled, and
937 * disabled if the only option is to open a new view of a single structure.
940 protected void validateSelections()
942 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
944 btn_add.setEnabled(false);
945 String currentView = selectedFilterOpt.getView();
946 int selectedCount = 0;
947 if (currentView == VIEWS_FILTER)
949 selectedCount = getResultTable().getSelectedRows().length;
950 if (selectedCount > 0)
952 btn_add.setEnabled(true);
955 else if (currentView == VIEWS_LOCAL_PDB)
957 selectedCount = tbl_local_pdb.getSelectedRows().length;
958 if (selectedCount > 0)
960 btn_add.setEnabled(true);
963 else if (currentView == VIEWS_ENTER_ID)
965 validateAssociationEnterPdb();
967 else if (currentView == VIEWS_FROM_FILE)
969 validateAssociationFromFile();
972 btn_newView.setEnabled(btn_add.isEnabled());
975 * enable 'Superpose' option if more than one structure is selected,
976 * or there are view(s) available to add structure(s) to
979 .setEnabled(selectedCount > 1 || targetView.getItemCount() > 0);
983 protected boolean showPopupFor(int selectedRow, int x, int y)
985 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
987 String currentView = selectedFilterOpt.getView();
989 if (currentView == VIEWS_FILTER
990 && data instanceof ThreeDBStructureChooserQuerySource)
993 TDB_FTSData row = ((ThreeDBStructureChooserQuerySource) data)
994 .getFTSDataFor(getResultTable(), selectedRow,
995 discoveredStructuresSet);
996 String pageUrl = row.getModelViewUrl();
997 JPopupMenu popup = new JPopupMenu("3D Beacons");
998 JMenuItem viewUrl = new JMenuItem("View model web page");
999 viewUrl.addActionListener(new ActionListener()
1002 public void actionPerformed(ActionEvent e)
1004 Desktop.showUrl(pageUrl);
1008 SwingUtilities.invokeLater(new Runnable()
1013 popup.show(getResultTable(), x, y);
1018 // event not handled by us
1023 * Validates inputs from the Manual PDB entry panel
1025 protected void validateAssociationEnterPdb()
1027 AssociateSeqOptions assSeqOpt = (AssociateSeqOptions) idInputAssSeqPanel
1028 .getCmb_assSeq().getSelectedItem();
1029 lbl_pdbManualFetchStatus.setIcon(errorImage);
1030 lbl_pdbManualFetchStatus.setToolTipText("");
1031 if (txt_search.getText().length() > 0)
1033 lbl_pdbManualFetchStatus.setToolTipText(JvSwingUtils.wrapTooltip(true,
1034 MessageManager.formatMessage("info.no_pdb_entry_found_for",
1035 txt_search.getText())));
1038 if (errorWarning.length() > 0)
1040 lbl_pdbManualFetchStatus.setIcon(warningImage);
1041 lbl_pdbManualFetchStatus.setToolTipText(
1042 JvSwingUtils.wrapTooltip(true, errorWarning.toString()));
1045 if (selectedSequences.length == 1 || !assSeqOpt.getName()
1046 .equalsIgnoreCase("-Select Associated Seq-"))
1048 txt_search.setEnabled(true);
1049 if (isValidPBDEntry)
1051 btn_add.setEnabled(true);
1052 lbl_pdbManualFetchStatus.setToolTipText("");
1053 lbl_pdbManualFetchStatus.setIcon(goodImage);
1058 txt_search.setEnabled(false);
1059 lbl_pdbManualFetchStatus.setIcon(errorImage);
1064 * Validates inputs for the manual PDB file selection options
1066 protected void validateAssociationFromFile()
1068 AssociateSeqOptions assSeqOpt = (AssociateSeqOptions) fileChooserAssSeqPanel
1069 .getCmb_assSeq().getSelectedItem();
1070 // lbl_fromFileStatus.setIcon(errorImage);
1071 String pdbFileString = "";
1072 String pdbFileTooltip = "";
1073 if (selectedSequences.length == 1 || (assSeqOpt != null && !assSeqOpt
1074 .getName().equalsIgnoreCase("-Select Associated Seq-")))
1076 btn_pdbFromFile.setEnabled(true);
1077 if (selectedPdbFileName != null && selectedPdbFileName.length() > 0)
1079 btn_add.setEnabled(true);
1080 // lbl_fromFileStatus.setIcon(goodImage);
1081 pdbFileString = new File(selectedPdbFileName).getName();
1082 pdbFileTooltip = new File(selectedPdbFileName).getAbsolutePath();
1083 setPdbOptionsEnabled(true);
1087 pdbFileString = MessageManager.getString("label.none");
1088 pdbFileTooltip = MessageManager.getString("label.nothing_selected");
1089 setPdbOptionsEnabled(false);
1094 btn_pdbFromFile.setEnabled(false);
1095 setPdbOptionsEnabled(false);
1096 // lbl_fromFileStatus.setIcon(errorImage);
1097 pdbFileString = MessageManager.getString("label.none");
1098 pdbFileTooltip = MessageManager.getString("label.nothing_selected");
1100 lbl_pdbFile.setText(pdbFileString);
1101 lbl_pdbFile.setToolTipText(pdbFileTooltip);
1104 String paeFileString = "";
1105 String paeFileTooltip = "";
1106 if (localPdbPaeMatrixFileName != null
1107 && localPdbPaeMatrixFileName.length() > 0)
1109 paeFileString = new File(localPdbPaeMatrixFileName).getName();
1110 paeFileTooltip = new File(localPdbPaeMatrixFileName)
1115 paeFileString = MessageManager.getString("label.none");
1116 paeFileTooltip = MessageManager.getString("label.nothing_selected");
1118 lbl_paeFile.setText(paeFileString);
1119 lbl_paeFile.setToolTipText(paeFileTooltip);
1123 protected void cmbAssSeqStateChanged()
1125 validateSelections();
1128 private FilterOption lastSelected = null;
1131 * Handles the state change event for the 'filter' combo-box and 'invert'
1135 protected void stateChanged(ItemEvent e)
1137 if (e.getSource() instanceof JCheckBox)
1139 updateCurrentView();
1143 if (e.getStateChange() == ItemEvent.SELECTED)
1145 updateCurrentView();
1152 * select structures for viewing by their PDB IDs
1155 * @return true if structures were found and marked as selected
1157 public boolean selectStructure(String... pdbids)
1159 boolean found = false;
1161 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
1162 .getSelectedItem());
1163 String currentView = selectedFilterOpt.getView();
1164 JTable restable = (currentView == VIEWS_FILTER) ? getResultTable()
1165 : (currentView == VIEWS_LOCAL_PDB) ? tbl_local_pdb : null;
1167 if (restable == null)
1169 // can't select (enter PDB ID, or load file - need to also select which
1170 // sequence to associate with)
1174 int pdbIdColIndex = restable.getColumn("PDB Id").getModelIndex();
1175 for (int r = 0; r < restable.getRowCount(); r++)
1177 for (int p = 0; p < pdbids.length; p++)
1179 if (String.valueOf(restable.getValueAt(r, pdbIdColIndex))
1180 .equalsIgnoreCase(pdbids[p]))
1182 restable.setRowSelectionInterval(r, r);
1191 * Handles the 'New View' action
1194 protected void newView_ActionPerformed()
1196 targetView.setSelectedItem(null);
1197 showStructures(false);
1201 * Handles the 'Add to existing viewer' action
1204 protected void add_ActionPerformed()
1206 showStructures(false);
1210 * structure viewer opened by this dialog, or null
1212 private StructureViewer sViewer = null;
1214 public void showStructures(boolean waitUntilFinished)
1217 final StructureSelectionManager ssm = ap.getStructureSelectionManager();
1219 final int preferredHeight = pnl_filter.getHeight();
1220 btn_add.setEnabled(false);
1221 btn_newView.setEnabled(false);
1222 btn_cancel.setEnabled(false);
1223 actionsPanel.setEnabled(false);
1225 final String progress = MessageManager
1226 .getString("label.working_ellipsis");
1227 setProgressBar(progress, progress.hashCode());
1228 Runnable viewStruc = new Runnable()
1233 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
1234 .getSelectedItem());
1235 String currentView = selectedFilterOpt.getView();
1236 JTable restable = (currentView == VIEWS_FILTER) ? getResultTable()
1239 if (currentView == VIEWS_FILTER)
1241 int[] selectedRows = restable.getSelectedRows();
1242 PDBEntry[] pdbEntriesToView = new PDBEntry[selectedRows.length];
1243 List<SequenceI> selectedSeqsToView = new ArrayList<>();
1244 pdbEntriesToView = data.collectSelectedRows(restable,
1245 selectedRows, selectedSeqsToView);
1247 SequenceI[] selectedSeqs = selectedSeqsToView
1248 .toArray(new SequenceI[selectedSeqsToView.size()]);
1249 sViewer = launchStructureViewer(ssm, pdbEntriesToView, ap,
1252 else if (currentView == VIEWS_LOCAL_PDB)
1254 int[] selectedRows = tbl_local_pdb.getSelectedRows();
1255 PDBEntry[] pdbEntriesToView = new PDBEntry[selectedRows.length];
1257 int pdbIdColIndex = tbl_local_pdb.getColumn("PDB Id")
1259 int refSeqColIndex = tbl_local_pdb.getColumn("Ref Sequence")
1261 List<SequenceI> selectedSeqsToView = new ArrayList<>();
1262 for (int row : selectedRows)
1264 PDBEntry pdbEntry = ((PDBEntryTableModel) tbl_local_pdb
1265 .getModel()).getPDBEntryAt(row).getPdbEntry();
1267 pdbEntriesToView[count++] = pdbEntry;
1268 SequenceI selectedSeq = (SequenceI) tbl_local_pdb
1269 .getValueAt(row, refSeqColIndex);
1270 selectedSeqsToView.add(selectedSeq);
1272 SequenceI[] selectedSeqs = selectedSeqsToView
1273 .toArray(new SequenceI[selectedSeqsToView.size()]);
1274 sViewer = launchStructureViewer(ssm, pdbEntriesToView, ap,
1277 else if (currentView == VIEWS_ENTER_ID)
1279 SequenceI userSelectedSeq = ((AssociateSeqOptions) idInputAssSeqPanel
1280 .getCmb_assSeq().getSelectedItem()).getSequence();
1281 if (userSelectedSeq != null)
1283 selectedSequence = userSelectedSeq;
1285 String pdbIdStr = txt_search.getText();
1286 PDBEntry pdbEntry = selectedSequence.getPDBEntry(pdbIdStr);
1287 if (pdbEntry == null)
1289 pdbEntry = new PDBEntry();
1290 if (pdbIdStr.split(":").length > 1)
1292 pdbEntry.setId(pdbIdStr.split(":")[0]);
1293 pdbEntry.setChainCode(
1294 pdbIdStr.split(":")[1].toUpperCase(Locale.ROOT));
1298 pdbEntry.setId(pdbIdStr);
1300 pdbEntry.setType(PDBEntry.Type.PDB);
1301 selectedSequence.getDatasetSequence().addPDBId(pdbEntry);
1304 PDBEntry[] pdbEntriesToView = new PDBEntry[] { pdbEntry };
1305 sViewer = launchStructureViewer(ssm, pdbEntriesToView, ap,
1307 { selectedSequence });
1309 else if (currentView == VIEWS_FROM_FILE)
1311 StructureChooser sc = StructureChooser.this;
1312 TFType tft = (TFType) sc.combo_tempFacAs.getSelectedItem();
1313 String paeFilename = sc.localPdbPaeMatrixFileName;
1314 AssociateSeqOptions assSeqOpt = (AssociateSeqOptions) fileChooserAssSeqPanel
1315 .getCmb_assSeq().getSelectedItem();
1316 SequenceI userSelectedSeq = assSeqOpt.getSequence();
1317 if (userSelectedSeq != null)
1319 selectedSequence = userSelectedSeq;
1321 String pdbFilename = selectedPdbFileName;
1323 StructureChooser.openStructureFileForSequence(ssm, sc, ap,
1324 selectedSequence, true, pdbFilename, tft, paeFilename,
1327 SwingUtilities.invokeLater(new Runnable()
1332 setProgressBar("Complete.", progress.hashCode());
1333 closeAction(preferredHeight);
1334 mainFrame.dispose();
1339 Thread runner = new Thread(viewStruc);
1341 if (waitUntilFinished)
1343 while (sViewer == null ? runner.isAlive()
1344 : (sViewer.sview == null ? true
1345 : !sViewer.sview.hasMapping()))
1350 } catch (InterruptedException ie)
1359 * Answers a structure viewer (new or existing) configured to superimpose
1360 * added structures or not according to the user's choice
1365 StructureViewer getTargetedStructureViewer(StructureSelectionManager ssm)
1367 Object sv = targetView.getSelectedItem();
1369 return sv == null ? new StructureViewer(ssm) : (StructureViewer) sv;
1373 * Adds PDB structures to a new or existing structure viewer
1376 * @param pdbEntriesToView
1381 private StructureViewer launchStructureViewer(
1382 StructureSelectionManager ssm, final PDBEntry[] pdbEntriesToView,
1383 final AlignmentPanel alignPanel, SequenceI[] sequences)
1385 return launchStructureViewer(ssm, pdbEntriesToView, alignPanel,
1389 private StructureViewer launchStructureViewer(
1390 StructureSelectionManager ssm, final PDBEntry[] pdbEntriesToView,
1391 final AlignmentPanel alignPanel, SequenceI[] sequences,
1392 ViewerType viewerType)
1394 long progressId = sequences.hashCode();
1395 setProgressBar(MessageManager
1396 .getString("status.launching_3d_structure_viewer"), progressId);
1397 final StructureViewer theViewer = getTargetedStructureViewer(ssm);
1398 boolean superimpose = chk_superpose.isSelected();
1399 theViewer.setSuperpose(superimpose);
1401 // if we're running in --headless mode make this viewer synchronous
1402 if (Jalview.isHeadlessMode())
1404 theViewer.setAsync(false);
1408 * remember user's choice of superimpose or not
1410 Cache.setProperty(AUTOSUPERIMPOSE,
1411 Boolean.valueOf(superimpose).toString());
1413 setProgressBar(null, progressId);
1414 if (SiftsSettings.isMapWithSifts())
1416 List<SequenceI> seqsWithoutSourceDBRef = new ArrayList<>();
1418 // TODO: skip PDBEntry:Sequence pairs where PDBEntry doesn't look like a
1419 // real PDB ID. For moment, we can also safely do this if there is already
1420 // a known mapping between the PDBEntry and the sequence.
1421 for (SequenceI seq : sequences)
1423 PDBEntry pdbe = pdbEntriesToView[p++];
1424 if (pdbe != null && pdbe.getFile() != null)
1426 StructureMapping[] smm = ssm.getMapping(pdbe.getFile());
1427 if (smm != null && smm.length > 0)
1429 for (StructureMapping sm : smm)
1431 if (sm.getSequence() == seq)
1438 if (seq.getPrimaryDBRefs().isEmpty())
1440 seqsWithoutSourceDBRef.add(seq);
1444 if (!seqsWithoutSourceDBRef.isEmpty())
1446 int y = seqsWithoutSourceDBRef.size();
1447 setProgressBar(MessageManager.formatMessage(
1448 "status.fetching_dbrefs_for_sequences_without_valid_refs",
1450 SequenceI[] seqWithoutSrcDBRef = seqsWithoutSourceDBRef
1451 .toArray(new SequenceI[y]);
1452 DBRefFetcher dbRefFetcher = new DBRefFetcher(seqWithoutSrcDBRef);
1453 dbRefFetcher.fetchDBRefs(true);
1455 setProgressBar("Fetch complete.", progressId); // todo i18n
1458 if (pdbEntriesToView.length > 1)
1461 MessageManager.getString(
1462 "status.fetching_3d_structures_for_selected_entries"),
1464 theViewer.viewStructures(pdbEntriesToView, sequences, alignPanel,
1469 setProgressBar(MessageManager.formatMessage(
1470 "status.fetching_3d_structures_for",
1471 pdbEntriesToView[0].getId()), progressId);
1472 // Can we pass a pre-computeMappinged pdbFile?
1473 theViewer.viewStructures(pdbEntriesToView[0], sequences, alignPanel,
1476 setProgressBar(null, progressId);
1477 // remember the last viewer we used...
1478 lastTargetedView = theViewer;
1483 * Populates the combo-box used in associating manually fetched structures to
1484 * a unique sequence when more than one sequence selection is made.
1487 protected void populateCmbAssociateSeqOptions(
1488 JComboBox<AssociateSeqOptions> cmb_assSeq,
1489 JLabel lbl_associateSeq)
1491 cmb_assSeq.removeAllItems();
1493 new AssociateSeqOptions("-Select Associated Seq-", null));
1494 lbl_associateSeq.setVisible(false);
1495 if (selectedSequences.length > 1)
1497 for (SequenceI seq : selectedSequences)
1499 cmb_assSeq.addItem(new AssociateSeqOptions(seq));
1504 String seqName = selectedSequence.getDisplayId(false);
1505 seqName = seqName.length() <= 40 ? seqName : seqName.substring(0, 39);
1506 lbl_associateSeq.setText(seqName);
1507 lbl_associateSeq.setVisible(true);
1508 cmb_assSeq.setVisible(false);
1512 protected boolean isStructuresDiscovered()
1514 return discoveredStructuresSet != null
1515 && !discoveredStructuresSet.isEmpty();
1518 protected int PDB_ID_MIN = 3;// or: (Jalview.isJS() ? 3 : 1); // Bob proposes
1520 // Doing a search for "1" or "1c" is valuable?
1521 // Those work but are enormously slow.
1524 protected void txt_search_ActionPerformed()
1526 String text = txt_search.getText().trim();
1527 if (text.length() >= PDB_ID_MIN)
1534 errorWarning.setLength(0);
1535 isValidPBDEntry = false;
1536 if (text.length() > 0)
1538 // TODO move this pdb id search into the PDB specific
1540 // for moment, it will work fine as is because it is self-contained
1541 String searchTerm = text.toLowerCase(Locale.ROOT);
1542 searchTerm = searchTerm.split(":")[0];
1543 // jalview.bin.Console.outPrintln(">>>>> search term : " +
1545 List<FTSDataColumnI> wantedFields = new ArrayList<>();
1546 FTSRestRequest pdbRequest = new FTSRestRequest();
1547 pdbRequest.setAllowEmptySeq(false);
1548 pdbRequest.setResponseSize(1);
1549 pdbRequest.setFieldToSearchBy("(pdb_id:");
1550 pdbRequest.setWantedFields(wantedFields);
1551 pdbRequest.setSearchTerm(searchTerm + ")");
1552 pdbRequest.setAssociatedSequence(selectedSequence);
1553 FTSRestClientI pdbRestClient = PDBFTSRestClient.getInstance();
1554 wantedFields.add(pdbRestClient.getPrimaryKeyColumn());
1555 FTSRestResponse resultList;
1558 resultList = pdbRestClient.executeRequest(pdbRequest);
1559 } catch (Exception e)
1561 errorWarning.append(e.getMessage());
1565 validateSelections();
1567 if (resultList.getSearchSummary() != null
1568 && resultList.getSearchSummary().size() > 0)
1570 isValidPBDEntry = true;
1573 validateSelections();
1579 protected void tabRefresh()
1581 if (selectedSequences != null)
1583 lbl_loading.setVisible(true);
1584 Thread refreshThread = new Thread(new Runnable()
1589 fetchStructuresMetaData();
1590 // populateFilterComboBox(true, cachedPDBExists);
1593 ((FilterOption) cmb_filterOption.getSelectedItem())
1595 lbl_loading.setVisible(false);
1598 refreshThread.start();
1602 public class PDBEntryTableModel extends AbstractTableModel
1604 String[] columns = { "Ref Sequence", "PDB Id", "Chain", "Type",
1607 private List<CachedPDB> pdbEntries;
1609 public PDBEntryTableModel(List<CachedPDB> pdbEntries)
1611 this.pdbEntries = new ArrayList<>(pdbEntries);
1615 public String getColumnName(int columnIndex)
1617 return columns[columnIndex];
1621 public int getRowCount()
1623 return pdbEntries.size();
1627 public int getColumnCount()
1629 return columns.length;
1633 public boolean isCellEditable(int row, int column)
1639 public Object getValueAt(int rowIndex, int columnIndex)
1641 Object value = "??";
1642 CachedPDB entry = pdbEntries.get(rowIndex);
1643 switch (columnIndex)
1646 value = entry.getSequence();
1649 value = entry.getQualifiedId();
1652 value = entry.getPdbEntry().getChainCode() == null ? "_"
1653 : entry.getPdbEntry().getChainCode();
1656 value = entry.getPdbEntry().getType();
1659 value = entry.getPdbEntry().getFile();
1666 public Class<?> getColumnClass(int columnIndex)
1668 return columnIndex == 0 ? SequenceI.class : PDBEntry.class;
1671 public CachedPDB getPDBEntryAt(int row)
1673 return pdbEntries.get(row);
1678 private class CachedPDB
1680 private SequenceI sequence;
1682 private PDBEntry pdbEntry;
1684 public CachedPDB(SequenceI sequence, PDBEntry pdbEntry)
1686 this.sequence = sequence;
1687 this.pdbEntry = pdbEntry;
1690 public String getQualifiedId()
1692 if (pdbEntry.hasProvider())
1694 return pdbEntry.getProvider() + ":" + pdbEntry.getId();
1696 return pdbEntry.toString();
1699 public SequenceI getSequence()
1704 public PDBEntry getPdbEntry()
1711 private IProgressIndicator progressBar;
1714 public void setProgressBar(String message, long id)
1716 if (!Platform.isHeadless() && progressBar != null)
1717 progressBar.setProgressBar(message, id);
1721 public void registerHandler(long id, IProgressIndicatorHandler handler)
1723 if (progressBar != null)
1724 progressBar.registerHandler(id, handler);
1728 public boolean operationInProgress()
1730 return progressBar == null ? false : progressBar.operationInProgress();
1733 public JalviewStructureDisplayI getOpenedStructureViewer()
1735 return sViewer == null ? null : sViewer.sview;
1739 protected void setFTSDocFieldPrefs(FTSDataColumnPreferences newPrefs)
1741 data.setDocFieldPrefs(newPrefs);
1747 * @return true when all initialisation threads have finished and dialog is
1750 public boolean isDialogVisible()
1752 return mainFrame != null && data != null && cmb_filterOption != null
1753 && mainFrame.isVisible()
1754 && cmb_filterOption.getSelectedItem() != null;
1759 * @return true if the 3D-Beacons query button will/has been displayed
1761 public boolean isCanQueryTDB()
1766 public boolean isNotQueriedTDBYet()
1768 return notQueriedTDBYet;
1772 * Open a single structure file for a given sequence
1774 public static void openStructureFileForSequence(
1775 StructureSelectionManager ssm, StructureChooser sc,
1776 AlignmentPanel ap, SequenceI seq, boolean prompt,
1777 String sFilename, TFType tft, String paeFilename,
1778 boolean doXferSettings)
1780 openStructureFileForSequence(ssm, sc, ap, seq, prompt, sFilename, tft,
1781 paeFilename, false, true, doXferSettings, null);
1784 public static StructureViewer openStructureFileForSequence(
1785 StructureSelectionManager ssm, StructureChooser sc,
1786 AlignmentPanel ap, SequenceI seq, boolean prompt,
1787 String sFilename, TFType tft, String paeFilename,
1788 boolean forceHeadless, boolean showRefAnnotations,
1789 boolean doXferSettings, ViewerType viewerType)
1791 StructureViewer sv = null;
1792 boolean headless = forceHeadless;
1797 sc = new StructureChooser(new SequenceI[] { seq }, seq, ap, false);
1801 ssm = ap.getStructureSelectionManager();
1804 PDBEntry fileEntry = new AssociatePdbFileWithSeq().associatePdbWithSeq(
1805 sFilename, DataSourceType.FILE, seq, prompt, Desktop.instance,
1806 tft, paeFilename, doXferSettings);
1808 // if headless, "false" in the sc constructor above will avoid GUI behaviour
1809 // in sc.launchStructureViewer()
1810 if (!headless && !(viewerType == null))
1812 sv = sc.launchStructureViewer(ssm, new PDBEntry[] { fileEntry }, ap,
1814 { seq }, viewerType);
1817 sc.mainFrame.dispose();
1819 if (showRefAnnotations)
1820 showReferenceAnnotationsForSequence(ap.alignFrame, seq);
1825 public static void showReferenceAnnotationsForSequence(AlignFrame af,
1828 AlignViewport av = af.getCurrentView();
1829 AlignmentI al = av.getAlignment();
1831 List<SequenceI> forSequences = new ArrayList<>();
1832 forSequences.add(sequence);
1833 final Map<SequenceI, List<AlignmentAnnotation>> candidates = new LinkedHashMap<>();
1834 AlignmentUtils.findAddableReferenceAnnotations(forSequences, null,
1836 final SequenceGroup selectionGroup = av.getSelectionGroup();
1837 AlignmentUtils.addReferenceAnnotations(candidates, al, selectionGroup);
1838 for (AlignmentViewPanel ap : af.getAlignPanels())
1840 // required to readjust the height and position of the PAE
1842 ap.adjustAnnotationHeight();