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)
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 JvOptionPane.showMessageDialog(this, errorMsg.toString(),
549 MessageManager.getString("label.pdb_web-service_error"),
550 JvOptionPane.ERROR_MESSAGE);
555 protected void loadLocalCachedPDBEntries()
557 ArrayList<CachedPDB> entries = new ArrayList<>();
558 for (SequenceI seq : selectedSequences)
560 if (seq.getDatasetSequence() != null
561 && seq.getDatasetSequence().getAllPDBEntries() != null)
563 for (PDBEntry pdbEntry : seq.getDatasetSequence()
566 if (pdbEntry.getFile() != null)
568 entries.add(new CachedPDB(seq, pdbEntry));
573 cachedPDBExists = !entries.isEmpty();
574 PDBEntryTableModel tableModelx = new PDBEntryTableModel(entries);
575 tbl_local_pdb.setModel(tableModelx);
579 * Filters a given list of discovered structures based on supplied argument
581 * @param fieldToFilterBy
582 * the field to filter by
584 void filterResultSet(final String fieldToFilterBy)
586 Thread filterThread = new Thread(new Runnable()
592 long startTime = System.currentTimeMillis();
593 lbl_loading.setVisible(true);
594 Collection<FTSDataColumnI> wantedFields = data.getDocFieldPrefs()
595 .getStructureSummaryFields();
596 Collection<FTSData> filteredResponse = new HashSet<>();
597 HashSet<String> errors = new HashSet<>();
599 for (SequenceI seq : selectedSequences)
602 FTSRestResponse resultList;
605 resultList = data.selectFirstRankedQuery(seq,
606 discoveredStructuresSet, wantedFields, fieldToFilterBy,
607 !chk_invertFilter.isSelected());
609 } catch (Exception e)
612 errors.add(e.getMessage());
615 if (resultList.getSearchSummary() != null
616 && !resultList.getSearchSummary().isEmpty())
618 filteredResponse.addAll(resultList.getSearchSummary());
622 String totalTime = (System.currentTimeMillis() - startTime)
624 if (!filteredResponse.isEmpty())
626 final int filterResponseCount = filteredResponse.size();
627 Collection<FTSData> reorderedStructuresSet = new LinkedHashSet<>();
628 reorderedStructuresSet.addAll(filteredResponse);
629 reorderedStructuresSet.addAll(discoveredStructuresSet);
631 .setModel(data.getTableModel(reorderedStructuresSet));
633 FTSRestResponse.configureTableColumn(getResultTable(),
634 wantedFields, tempUserPrefs);
635 getResultTable().getColumn("Ref Sequence").setPreferredWidth(120);
636 getResultTable().getColumn("Ref Sequence").setMinWidth(100);
637 getResultTable().getColumn("Ref Sequence").setMaxWidth(200);
638 // Update table selection model here
639 getResultTable().addRowSelectionInterval(0,
640 filterResponseCount - 1);
641 mainFrame.setTitle(MessageManager.formatMessage(
642 "label.structure_chooser_filter_time", totalTime));
646 mainFrame.setTitle(MessageManager.formatMessage(
647 "label.structure_chooser_filter_time", totalTime));
648 if (errors.size() > 0)
650 StringBuilder errorMsg = new StringBuilder();
651 for (String error : errors)
653 errorMsg.append(error).append("\n");
655 JvOptionPane.showMessageDialog(null, errorMsg.toString(),
656 MessageManager.getString("label.pdb_web-service_error"),
657 JvOptionPane.ERROR_MESSAGE);
661 lbl_loading.setVisible(false);
663 validateSelections();
666 filterThread.start();
670 * Handles action event for btn_pdbFromFile
673 protected void pdbFromFile_actionPerformed()
675 // TODO: JAL-3048 not needed for Jalview-JS until JSmol dep and
678 JalviewFileChooser chooser = new JalviewFileChooser(
679 Cache.getProperty("LAST_DIRECTORY"));
680 chooser.setFileView(new JalviewFileView());
681 chooser.setDialogTitle(
682 MessageManager.formatMessage("label.select_pdb_file_for",
683 selectedSequence.getDisplayId(false)));
684 chooser.setToolTipText(MessageManager.formatMessage(
685 "label.load_pdb_file_associate_with_sequence",
686 selectedSequence.getDisplayId(false)));
688 int value = chooser.showOpenDialog(null);
689 if (value == JalviewFileChooser.APPROVE_OPTION)
691 selectedPdbFileName = chooser.getSelectedFile().getPath();
692 Cache.setProperty("LAST_DIRECTORY", selectedPdbFileName);
693 boolean guessTFType = localPdbPaeMatrixFileName == null;
694 localPdbPaeMatrixFileName = guessPAEFilename();
695 guessTFType |= localPdbPaeMatrixFileName != null;
696 Regex alphaFold = JmolParser.getNewAlphafoldValidator();
698 && alphaFold.search(new File(selectedPdbFileName).getName())
699 && !tempFacAsChanged)
701 // localPdbPaeMatrixFileName was null and now isn't and filename could
702 // well be AlphaFold and user hasn't adjusted the tempFacType
703 combo_tempFacAs.setSelectedItem(TFType.PLDDT);
705 validateSelections();
710 * Handles action event for btn_paeMatrixFile
713 protected void paeMatrixFile_actionPerformed()
715 File pdbFile = new File(selectedPdbFileName);
716 String setFile = Cache.getProperty("LAST_DIRECTORY");
717 if (localPdbPaeMatrixFileName != null)
719 File paeFile = new File(localPdbPaeMatrixFileName);
720 if (paeFile.exists())
721 setFile = paeFile.getAbsolutePath();
722 else if (paeFile.getParentFile().exists())
723 setFile = paeFile.getParentFile().getAbsolutePath();
727 String guess = guessPAEFilename();
731 JalviewFileChooser chooser = new JalviewFileChooser(setFile);
732 chooser.setFileView(new JalviewFileView());
733 chooser.setDialogTitle(MessageManager.formatMessage(
734 "label.select_pae_matrix_file_for", pdbFile.getName()));
735 chooser.setToolTipText(MessageManager.formatMessage(
736 "label.load_pae_matrix_file_associate_with_structure",
739 // TODO convert to Callable/Promise
740 int value = chooser.showOpenDialog(null);
741 if (value == JalviewFileChooser.APPROVE_OPTION)
743 String fileName = chooser.getSelectedFile().getPath();
746 PAEContactMatrix.validateContactMatrixFile(fileName);
747 } catch (Exception thr)
749 JvOptionPane.showInternalMessageDialog(this, MessageManager
750 .formatMessage("label.couldnt_load_file", new Object[]
751 { fileName }) + "<br>" + thr.getLocalizedMessage(),
752 MessageManager.getString("label.error_loading_file"),
753 JvOptionPane.WARNING_MESSAGE);
754 Console.error("Couldn't import " + fileName + " as a PAE matrix",
758 localPdbPaeMatrixFileName = fileName;
759 Cache.setProperty("LAST_DIRECTORY", localPdbPaeMatrixFileName);
761 validateAssociationFromFile();
764 private String guessPAEFilename()
766 if (selectedPdbFileName.toLowerCase(Locale.ROOT).endsWith(".pdb")
767 || selectedPdbFileName.toLowerCase(Locale.ROOT)
770 String jsonExt = selectedPdbFileName.substring(0,
771 selectedPdbFileName.length() - 4) + ".json";
772 // AlphaFold naming scheme
773 String guessFile1 = StringUtils.replaceLast(jsonExt, "model",
774 "predicted_aligned_error");
775 // nf-core mode naming scheme
776 String guessFile2 = StringUtils.replaceLast(jsonExt, ".json",
778 if (new File(guessFile1).exists())
782 else if (new File(jsonExt).exists())
786 else if (new File(guessFile2).exists())
795 * Populates the filter combo-box options dynamically depending on discovered
798 protected void populateFilterComboBox(boolean haveData,
799 boolean cachedPDBExist)
801 populateFilterComboBox(haveData, cachedPDBExist, null);
805 * Populates the filter combo-box options dynamically depending on discovered
808 protected void populateFilterComboBox(boolean haveData,
809 boolean cachedPDBExist, FilterOption lastSel)
813 * temporarily suspend the change listener behaviour
815 cmb_filterOption.removeItemListener(this);
817 cmb_filterOption.removeAllItems();
820 List<FilterOption> filters = data
821 .getAvailableFilterOptions(VIEWS_FILTER);
822 data.updateAvailableFilterOptions(VIEWS_FILTER, filters,
823 lastDiscoveredStructuresSet);
825 for (FilterOption filter : filters)
827 if (lastSel != null && filter.equals(lastSel))
832 cmb_filterOption.addItem(filter);
836 cmb_filterOption.addItem(
837 new FilterOption(MessageManager.getString("label.enter_pdb_id"),
838 "-", VIEWS_ENTER_ID, false, null));
839 cmb_filterOption.addItem(
840 new FilterOption(MessageManager.getString("label.from_file"),
841 "-", VIEWS_FROM_FILE, false, null));
842 if (canQueryTDB && notQueriedTDBYet)
844 btn_queryTDB.setVisible(true);
845 pnl_queryTDB.setVisible(true);
850 FilterOption cachedOption = new FilterOption(
851 MessageManager.getString("label.cached_structures"), "-",
852 VIEWS_LOCAL_PDB, false, null);
853 cmb_filterOption.addItem(cachedOption);
856 cmb_filterOption.setSelectedItem(cachedOption);
861 cmb_filterOption.setSelectedIndex(selSet);
863 cmb_filterOption.addItemListener(this);
867 * Updates the displayed view based on the selected filter option
869 protected void updateCurrentView()
871 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
874 if (lastSelected == selectedFilterOpt)
876 // don't need to do anything, probably
879 // otherwise, record selection
880 // and update the layout and dialog accordingly
881 lastSelected = selectedFilterOpt;
883 layout_switchableViews.show(pnl_switchableViews,
884 selectedFilterOpt.getView());
885 String filterTitle = mainFrame.getTitle();
886 mainFrame.setTitle(frameTitle);
887 chk_invertFilter.setVisible(false);
889 if (selectedFilterOpt.getView() == VIEWS_FILTER)
891 mainFrame.setTitle(filterTitle);
892 // TDB Query has no invert as yet
893 chk_invertFilter.setVisible(selectedFilterOpt
894 .getQuerySource() instanceof PDBStructureChooserQuerySource);
896 if (data != selectedFilterOpt.getQuerySource()
897 || data.needsRefetch(selectedFilterOpt))
899 data = selectedFilterOpt.getQuerySource();
900 // rebuild the views completely, since prefs will also change
906 filterResultSet(selectedFilterOpt.getValue());
909 else if (selectedFilterOpt.getView() == VIEWS_ENTER_ID
910 || selectedFilterOpt.getView() == VIEWS_FROM_FILE)
912 mainFrame.setTitle(MessageManager
913 .getString("label.structure_chooser_manual_association"));
914 idInputAssSeqPanel.loadCmbAssSeq();
915 fileChooserAssSeqPanel.loadCmbAssSeq();
917 validateSelections();
921 * Validates user selection and enables the 'Add' and 'New View' buttons if
922 * all parameters are correct (the Add button will only be visible if there is
923 * at least one existing structure viewer open). This basically means at least
924 * one structure selected and no error messages.
926 * The 'Superpose Structures' option is enabled if either more than one
927 * structure is selected, or the 'Add' to existing view option is enabled, and
928 * disabled if the only option is to open a new view of a single structure.
931 protected void validateSelections()
933 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
935 btn_add.setEnabled(false);
936 String currentView = selectedFilterOpt.getView();
937 int selectedCount = 0;
938 if (currentView == VIEWS_FILTER)
940 selectedCount = getResultTable().getSelectedRows().length;
941 if (selectedCount > 0)
943 btn_add.setEnabled(true);
946 else if (currentView == VIEWS_LOCAL_PDB)
948 selectedCount = tbl_local_pdb.getSelectedRows().length;
949 if (selectedCount > 0)
951 btn_add.setEnabled(true);
954 else if (currentView == VIEWS_ENTER_ID)
956 validateAssociationEnterPdb();
958 else if (currentView == VIEWS_FROM_FILE)
960 validateAssociationFromFile();
963 btn_newView.setEnabled(btn_add.isEnabled());
966 * enable 'Superpose' option if more than one structure is selected,
967 * or there are view(s) available to add structure(s) to
970 .setEnabled(selectedCount > 1 || targetView.getItemCount() > 0);
974 protected boolean showPopupFor(int selectedRow, int x, int y)
976 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
978 String currentView = selectedFilterOpt.getView();
980 if (currentView == VIEWS_FILTER
981 && data instanceof ThreeDBStructureChooserQuerySource)
984 TDB_FTSData row = ((ThreeDBStructureChooserQuerySource) data)
985 .getFTSDataFor(getResultTable(), selectedRow,
986 discoveredStructuresSet);
987 String pageUrl = row.getModelViewUrl();
988 JPopupMenu popup = new JPopupMenu("3D Beacons");
989 JMenuItem viewUrl = new JMenuItem("View model web page");
990 viewUrl.addActionListener(new ActionListener()
993 public void actionPerformed(ActionEvent e)
995 Desktop.showUrl(pageUrl);
999 SwingUtilities.invokeLater(new Runnable()
1004 popup.show(getResultTable(), x, y);
1009 // event not handled by us
1014 * Validates inputs from the Manual PDB entry panel
1016 protected void validateAssociationEnterPdb()
1018 AssociateSeqOptions assSeqOpt = (AssociateSeqOptions) idInputAssSeqPanel
1019 .getCmb_assSeq().getSelectedItem();
1020 lbl_pdbManualFetchStatus.setIcon(errorImage);
1021 lbl_pdbManualFetchStatus.setToolTipText("");
1022 if (txt_search.getText().length() > 0)
1024 lbl_pdbManualFetchStatus.setToolTipText(JvSwingUtils.wrapTooltip(true,
1025 MessageManager.formatMessage("info.no_pdb_entry_found_for",
1026 txt_search.getText())));
1029 if (errorWarning.length() > 0)
1031 lbl_pdbManualFetchStatus.setIcon(warningImage);
1032 lbl_pdbManualFetchStatus.setToolTipText(
1033 JvSwingUtils.wrapTooltip(true, errorWarning.toString()));
1036 if (selectedSequences.length == 1 || !assSeqOpt.getName()
1037 .equalsIgnoreCase("-Select Associated Seq-"))
1039 txt_search.setEnabled(true);
1040 if (isValidPBDEntry)
1042 btn_add.setEnabled(true);
1043 lbl_pdbManualFetchStatus.setToolTipText("");
1044 lbl_pdbManualFetchStatus.setIcon(goodImage);
1049 txt_search.setEnabled(false);
1050 lbl_pdbManualFetchStatus.setIcon(errorImage);
1055 * Validates inputs for the manual PDB file selection options
1057 protected void validateAssociationFromFile()
1059 AssociateSeqOptions assSeqOpt = (AssociateSeqOptions) fileChooserAssSeqPanel
1060 .getCmb_assSeq().getSelectedItem();
1061 // lbl_fromFileStatus.setIcon(errorImage);
1062 String pdbFileString = "";
1063 String pdbFileTooltip = "";
1064 if (selectedSequences.length == 1 || (assSeqOpt != null && !assSeqOpt
1065 .getName().equalsIgnoreCase("-Select Associated Seq-")))
1067 btn_pdbFromFile.setEnabled(true);
1068 if (selectedPdbFileName != null && selectedPdbFileName.length() > 0)
1070 btn_add.setEnabled(true);
1071 // lbl_fromFileStatus.setIcon(goodImage);
1072 pdbFileString = new File(selectedPdbFileName).getName();
1073 pdbFileTooltip = new File(selectedPdbFileName).getAbsolutePath();
1074 setPdbOptionsEnabled(true);
1078 pdbFileString = MessageManager.getString("label.none");
1079 pdbFileTooltip = MessageManager.getString("label.nothing_selected");
1080 setPdbOptionsEnabled(false);
1085 btn_pdbFromFile.setEnabled(false);
1086 setPdbOptionsEnabled(false);
1087 // lbl_fromFileStatus.setIcon(errorImage);
1088 pdbFileString = MessageManager.getString("label.none");
1089 pdbFileTooltip = MessageManager.getString("label.nothing_selected");
1091 lbl_pdbFile.setText(pdbFileString);
1092 lbl_pdbFile.setToolTipText(pdbFileTooltip);
1095 String paeFileString = "";
1096 String paeFileTooltip = "";
1097 if (localPdbPaeMatrixFileName != null
1098 && localPdbPaeMatrixFileName.length() > 0)
1100 paeFileString = new File(localPdbPaeMatrixFileName).getName();
1101 paeFileTooltip = new File(localPdbPaeMatrixFileName)
1106 paeFileString = MessageManager.getString("label.none");
1107 paeFileTooltip = MessageManager.getString("label.nothing_selected");
1109 lbl_paeFile.setText(paeFileString);
1110 lbl_paeFile.setToolTipText(paeFileTooltip);
1114 protected void cmbAssSeqStateChanged()
1116 validateSelections();
1119 private FilterOption lastSelected = null;
1122 * Handles the state change event for the 'filter' combo-box and 'invert'
1126 protected void stateChanged(ItemEvent e)
1128 if (e.getSource() instanceof JCheckBox)
1130 updateCurrentView();
1134 if (e.getStateChange() == ItemEvent.SELECTED)
1136 updateCurrentView();
1143 * select structures for viewing by their PDB IDs
1146 * @return true if structures were found and marked as selected
1148 public boolean selectStructure(String... pdbids)
1150 boolean found = false;
1152 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
1153 .getSelectedItem());
1154 String currentView = selectedFilterOpt.getView();
1155 JTable restable = (currentView == VIEWS_FILTER) ? getResultTable()
1156 : (currentView == VIEWS_LOCAL_PDB) ? tbl_local_pdb : null;
1158 if (restable == null)
1160 // can't select (enter PDB ID, or load file - need to also select which
1161 // sequence to associate with)
1165 int pdbIdColIndex = restable.getColumn("PDB Id").getModelIndex();
1166 for (int r = 0; r < restable.getRowCount(); r++)
1168 for (int p = 0; p < pdbids.length; p++)
1170 if (String.valueOf(restable.getValueAt(r, pdbIdColIndex))
1171 .equalsIgnoreCase(pdbids[p]))
1173 restable.setRowSelectionInterval(r, r);
1182 * Handles the 'New View' action
1185 protected void newView_ActionPerformed()
1187 targetView.setSelectedItem(null);
1188 showStructures(false);
1192 * Handles the 'Add to existing viewer' action
1195 protected void add_ActionPerformed()
1197 showStructures(false);
1201 * structure viewer opened by this dialog, or null
1203 private StructureViewer sViewer = null;
1205 public void showStructures(boolean waitUntilFinished)
1208 final StructureSelectionManager ssm = ap.getStructureSelectionManager();
1210 final int preferredHeight = pnl_filter.getHeight();
1211 btn_add.setEnabled(false);
1212 btn_newView.setEnabled(false);
1213 btn_cancel.setEnabled(false);
1214 actionsPanel.setEnabled(false);
1216 final String progress = MessageManager
1217 .getString("label.working_ellipsis");
1218 setProgressBar(progress, progress.hashCode());
1219 Runnable viewStruc = new Runnable()
1224 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
1225 .getSelectedItem());
1226 String currentView = selectedFilterOpt.getView();
1227 JTable restable = (currentView == VIEWS_FILTER) ? getResultTable()
1230 if (currentView == VIEWS_FILTER)
1232 int[] selectedRows = restable.getSelectedRows();
1233 PDBEntry[] pdbEntriesToView = new PDBEntry[selectedRows.length];
1234 List<SequenceI> selectedSeqsToView = new ArrayList<>();
1235 pdbEntriesToView = data.collectSelectedRows(restable,
1236 selectedRows, selectedSeqsToView);
1238 SequenceI[] selectedSeqs = selectedSeqsToView
1239 .toArray(new SequenceI[selectedSeqsToView.size()]);
1240 sViewer = launchStructureViewer(ssm, pdbEntriesToView, ap,
1243 else if (currentView == VIEWS_LOCAL_PDB)
1245 int[] selectedRows = tbl_local_pdb.getSelectedRows();
1246 PDBEntry[] pdbEntriesToView = new PDBEntry[selectedRows.length];
1248 int pdbIdColIndex = tbl_local_pdb.getColumn("PDB Id")
1250 int refSeqColIndex = tbl_local_pdb.getColumn("Ref Sequence")
1252 List<SequenceI> selectedSeqsToView = new ArrayList<>();
1253 for (int row : selectedRows)
1255 PDBEntry pdbEntry = ((PDBEntryTableModel) tbl_local_pdb
1256 .getModel()).getPDBEntryAt(row).getPdbEntry();
1258 pdbEntriesToView[count++] = pdbEntry;
1259 SequenceI selectedSeq = (SequenceI) tbl_local_pdb
1260 .getValueAt(row, refSeqColIndex);
1261 selectedSeqsToView.add(selectedSeq);
1263 SequenceI[] selectedSeqs = selectedSeqsToView
1264 .toArray(new SequenceI[selectedSeqsToView.size()]);
1265 sViewer = launchStructureViewer(ssm, pdbEntriesToView, ap,
1268 else if (currentView == VIEWS_ENTER_ID)
1270 SequenceI userSelectedSeq = ((AssociateSeqOptions) idInputAssSeqPanel
1271 .getCmb_assSeq().getSelectedItem()).getSequence();
1272 if (userSelectedSeq != null)
1274 selectedSequence = userSelectedSeq;
1276 String pdbIdStr = txt_search.getText();
1277 PDBEntry pdbEntry = selectedSequence.getPDBEntry(pdbIdStr);
1278 if (pdbEntry == null)
1280 pdbEntry = new PDBEntry();
1281 if (pdbIdStr.split(":").length > 1)
1283 pdbEntry.setId(pdbIdStr.split(":")[0]);
1284 pdbEntry.setChainCode(
1285 pdbIdStr.split(":")[1].toUpperCase(Locale.ROOT));
1289 pdbEntry.setId(pdbIdStr);
1291 pdbEntry.setType(PDBEntry.Type.PDB);
1292 selectedSequence.getDatasetSequence().addPDBId(pdbEntry);
1295 PDBEntry[] pdbEntriesToView = new PDBEntry[] { pdbEntry };
1296 sViewer = launchStructureViewer(ssm, pdbEntriesToView, ap,
1298 { selectedSequence });
1300 else if (currentView == VIEWS_FROM_FILE)
1302 StructureChooser sc = StructureChooser.this;
1303 TFType tft = (TFType) sc.combo_tempFacAs.getSelectedItem();
1304 String paeFilename = sc.localPdbPaeMatrixFileName;
1305 AssociateSeqOptions assSeqOpt = (AssociateSeqOptions) fileChooserAssSeqPanel
1306 .getCmb_assSeq().getSelectedItem();
1307 SequenceI userSelectedSeq = assSeqOpt.getSequence();
1308 if (userSelectedSeq != null)
1310 selectedSequence = userSelectedSeq;
1312 String pdbFilename = selectedPdbFileName;
1314 StructureChooser.openStructureFileForSequence(ssm, sc, ap,
1315 selectedSequence, true, pdbFilename, tft, paeFilename,
1318 SwingUtilities.invokeLater(new Runnable()
1323 setProgressBar("Complete.", progress.hashCode());
1324 closeAction(preferredHeight);
1325 mainFrame.dispose();
1330 Thread runner = new Thread(viewStruc);
1332 if (waitUntilFinished)
1334 while (sViewer == null ? runner.isAlive()
1335 : (sViewer.sview == null ? true
1336 : !sViewer.sview.hasMapping()))
1341 } catch (InterruptedException ie)
1350 * Answers a structure viewer (new or existing) configured to superimpose
1351 * added structures or not according to the user's choice
1356 StructureViewer getTargetedStructureViewer(StructureSelectionManager ssm)
1358 Object sv = targetView.getSelectedItem();
1360 return sv == null ? new StructureViewer(ssm) : (StructureViewer) sv;
1364 * Adds PDB structures to a new or existing structure viewer
1367 * @param pdbEntriesToView
1372 private StructureViewer launchStructureViewer(
1373 StructureSelectionManager ssm, final PDBEntry[] pdbEntriesToView,
1374 final AlignmentPanel alignPanel, SequenceI[] sequences)
1376 return launchStructureViewer(ssm, pdbEntriesToView, alignPanel,
1380 private StructureViewer launchStructureViewer(
1381 StructureSelectionManager ssm, final PDBEntry[] pdbEntriesToView,
1382 final AlignmentPanel alignPanel, SequenceI[] sequences,
1383 ViewerType viewerType)
1385 long progressId = sequences.hashCode();
1386 setProgressBar(MessageManager
1387 .getString("status.launching_3d_structure_viewer"), progressId);
1388 final StructureViewer theViewer = getTargetedStructureViewer(ssm);
1389 boolean superimpose = chk_superpose.isSelected();
1390 theViewer.setSuperpose(superimpose);
1393 * remember user's choice of superimpose or not
1395 Cache.setProperty(AUTOSUPERIMPOSE,
1396 Boolean.valueOf(superimpose).toString());
1398 setProgressBar(null, progressId);
1399 if (SiftsSettings.isMapWithSifts())
1401 List<SequenceI> seqsWithoutSourceDBRef = new ArrayList<>();
1403 // TODO: skip PDBEntry:Sequence pairs where PDBEntry doesn't look like a
1404 // real PDB ID. For moment, we can also safely do this if there is already
1405 // a known mapping between the PDBEntry and the sequence.
1406 for (SequenceI seq : sequences)
1408 PDBEntry pdbe = pdbEntriesToView[p++];
1409 if (pdbe != null && pdbe.getFile() != null)
1411 StructureMapping[] smm = ssm.getMapping(pdbe.getFile());
1412 if (smm != null && smm.length > 0)
1414 for (StructureMapping sm : smm)
1416 if (sm.getSequence() == seq)
1423 if (seq.getPrimaryDBRefs().isEmpty())
1425 seqsWithoutSourceDBRef.add(seq);
1429 if (!seqsWithoutSourceDBRef.isEmpty())
1431 int y = seqsWithoutSourceDBRef.size();
1432 setProgressBar(MessageManager.formatMessage(
1433 "status.fetching_dbrefs_for_sequences_without_valid_refs",
1435 SequenceI[] seqWithoutSrcDBRef = seqsWithoutSourceDBRef
1436 .toArray(new SequenceI[y]);
1437 DBRefFetcher dbRefFetcher = new DBRefFetcher(seqWithoutSrcDBRef);
1438 dbRefFetcher.fetchDBRefs(true);
1440 setProgressBar("Fetch complete.", progressId); // todo i18n
1443 if (pdbEntriesToView.length > 1)
1446 MessageManager.getString(
1447 "status.fetching_3d_structures_for_selected_entries"),
1449 theViewer.viewStructures(pdbEntriesToView, sequences, alignPanel,
1454 setProgressBar(MessageManager.formatMessage(
1455 "status.fetching_3d_structures_for",
1456 pdbEntriesToView[0].getId()), progressId);
1457 // Can we pass a pre-computeMappinged pdbFile?
1458 theViewer.viewStructures(pdbEntriesToView[0], sequences, alignPanel,
1461 setProgressBar(null, progressId);
1462 // remember the last viewer we used...
1463 lastTargetedView = theViewer;
1468 * Populates the combo-box used in associating manually fetched structures to
1469 * a unique sequence when more than one sequence selection is made.
1472 protected void populateCmbAssociateSeqOptions(
1473 JComboBox<AssociateSeqOptions> cmb_assSeq,
1474 JLabel lbl_associateSeq)
1476 cmb_assSeq.removeAllItems();
1478 new AssociateSeqOptions("-Select Associated Seq-", null));
1479 lbl_associateSeq.setVisible(false);
1480 if (selectedSequences.length > 1)
1482 for (SequenceI seq : selectedSequences)
1484 cmb_assSeq.addItem(new AssociateSeqOptions(seq));
1489 String seqName = selectedSequence.getDisplayId(false);
1490 seqName = seqName.length() <= 40 ? seqName : seqName.substring(0, 39);
1491 lbl_associateSeq.setText(seqName);
1492 lbl_associateSeq.setVisible(true);
1493 cmb_assSeq.setVisible(false);
1497 protected boolean isStructuresDiscovered()
1499 return discoveredStructuresSet != null
1500 && !discoveredStructuresSet.isEmpty();
1503 protected int PDB_ID_MIN = 3;// or: (Jalview.isJS() ? 3 : 1); // Bob proposes
1505 // Doing a search for "1" or "1c" is valuable?
1506 // Those work but are enormously slow.
1509 protected void txt_search_ActionPerformed()
1511 String text = txt_search.getText().trim();
1512 if (text.length() >= PDB_ID_MIN)
1519 errorWarning.setLength(0);
1520 isValidPBDEntry = false;
1521 if (text.length() > 0)
1523 // TODO move this pdb id search into the PDB specific
1525 // for moment, it will work fine as is because it is self-contained
1526 String searchTerm = text.toLowerCase(Locale.ROOT);
1527 searchTerm = searchTerm.split(":")[0];
1528 // System.out.println(">>>>> search term : " + searchTerm);
1529 List<FTSDataColumnI> wantedFields = new ArrayList<>();
1530 FTSRestRequest pdbRequest = new FTSRestRequest();
1531 pdbRequest.setAllowEmptySeq(false);
1532 pdbRequest.setResponseSize(1);
1533 pdbRequest.setFieldToSearchBy("(pdb_id:");
1534 pdbRequest.setWantedFields(wantedFields);
1535 pdbRequest.setSearchTerm(searchTerm + ")");
1536 pdbRequest.setAssociatedSequence(selectedSequence);
1537 FTSRestClientI pdbRestClient = PDBFTSRestClient.getInstance();
1538 wantedFields.add(pdbRestClient.getPrimaryKeyColumn());
1539 FTSRestResponse resultList;
1542 resultList = pdbRestClient.executeRequest(pdbRequest);
1543 } catch (Exception e)
1545 errorWarning.append(e.getMessage());
1549 validateSelections();
1551 if (resultList.getSearchSummary() != null
1552 && resultList.getSearchSummary().size() > 0)
1554 isValidPBDEntry = true;
1557 validateSelections();
1563 protected void tabRefresh()
1565 if (selectedSequences != null)
1567 lbl_loading.setVisible(true);
1568 Thread refreshThread = new Thread(new Runnable()
1573 fetchStructuresMetaData();
1574 // populateFilterComboBox(true, cachedPDBExists);
1577 ((FilterOption) cmb_filterOption.getSelectedItem())
1579 lbl_loading.setVisible(false);
1582 refreshThread.start();
1586 public class PDBEntryTableModel extends AbstractTableModel
1588 String[] columns = { "Ref Sequence", "PDB Id", "Chain", "Type",
1591 private List<CachedPDB> pdbEntries;
1593 public PDBEntryTableModel(List<CachedPDB> pdbEntries)
1595 this.pdbEntries = new ArrayList<>(pdbEntries);
1599 public String getColumnName(int columnIndex)
1601 return columns[columnIndex];
1605 public int getRowCount()
1607 return pdbEntries.size();
1611 public int getColumnCount()
1613 return columns.length;
1617 public boolean isCellEditable(int row, int column)
1623 public Object getValueAt(int rowIndex, int columnIndex)
1625 Object value = "??";
1626 CachedPDB entry = pdbEntries.get(rowIndex);
1627 switch (columnIndex)
1630 value = entry.getSequence();
1633 value = entry.getQualifiedId();
1636 value = entry.getPdbEntry().getChainCode() == null ? "_"
1637 : entry.getPdbEntry().getChainCode();
1640 value = entry.getPdbEntry().getType();
1643 value = entry.getPdbEntry().getFile();
1650 public Class<?> getColumnClass(int columnIndex)
1652 return columnIndex == 0 ? SequenceI.class : PDBEntry.class;
1655 public CachedPDB getPDBEntryAt(int row)
1657 return pdbEntries.get(row);
1662 private class CachedPDB
1664 private SequenceI sequence;
1666 private PDBEntry pdbEntry;
1668 public CachedPDB(SequenceI sequence, PDBEntry pdbEntry)
1670 this.sequence = sequence;
1671 this.pdbEntry = pdbEntry;
1674 public String getQualifiedId()
1676 if (pdbEntry.hasProvider())
1678 return pdbEntry.getProvider() + ":" + pdbEntry.getId();
1680 return pdbEntry.toString();
1683 public SequenceI getSequence()
1688 public PDBEntry getPdbEntry()
1695 private IProgressIndicator progressBar;
1698 public void setProgressBar(String message, long id)
1700 if (!Platform.isHeadless() && progressBar != null)
1701 progressBar.setProgressBar(message, id);
1705 public void registerHandler(long id, IProgressIndicatorHandler handler)
1707 if (progressBar != null)
1708 progressBar.registerHandler(id, handler);
1712 public boolean operationInProgress()
1714 return progressBar == null ? false : progressBar.operationInProgress();
1717 public JalviewStructureDisplayI getOpenedStructureViewer()
1719 return sViewer == null ? null : sViewer.sview;
1723 protected void setFTSDocFieldPrefs(FTSDataColumnPreferences newPrefs)
1725 data.setDocFieldPrefs(newPrefs);
1731 * @return true when all initialisation threads have finished and dialog is
1734 public boolean isDialogVisible()
1736 return mainFrame != null && data != null && cmb_filterOption != null
1737 && mainFrame.isVisible()
1738 && cmb_filterOption.getSelectedItem() != null;
1743 * @return true if the 3D-Beacons query button will/has been displayed
1745 public boolean isCanQueryTDB()
1750 public boolean isNotQueriedTDBYet()
1752 return notQueriedTDBYet;
1756 * Open a single structure file for a given sequence
1758 public static void openStructureFileForSequence(
1759 StructureSelectionManager ssm, StructureChooser sc,
1760 AlignmentPanel ap, SequenceI seq, boolean prompt,
1761 String sFilename, TFType tft, String paeFilename,
1762 boolean doXferSettings)
1764 openStructureFileForSequence(ssm, sc, ap, seq, prompt, sFilename, tft,
1765 paeFilename, false, true, doXferSettings, null);
1768 public static StructureViewer openStructureFileForSequence(
1769 StructureSelectionManager ssm, StructureChooser sc,
1770 AlignmentPanel ap, SequenceI seq, boolean prompt,
1771 String sFilename, TFType tft, String paeFilename,
1772 boolean forceHeadless, boolean showRefAnnotations,
1773 boolean doXferSettings, ViewerType viewerType)
1775 StructureViewer sv = null;
1776 boolean headless = forceHeadless;
1781 sc = new StructureChooser(new SequenceI[] { seq }, seq, ap, false);
1785 ssm = ap.getStructureSelectionManager();
1788 PDBEntry fileEntry = new AssociatePdbFileWithSeq().associatePdbWithSeq(
1789 sFilename, DataSourceType.FILE, seq, prompt, Desktop.instance,
1790 tft, paeFilename, doXferSettings);
1792 // if headless, "false" in the sc constructor above will avoid GUI behaviour
1793 // in sc.launchStructureViewer()
1794 if (!headless && !(viewerType == null))
1796 sv = sc.launchStructureViewer(ssm, new PDBEntry[] { fileEntry }, ap,
1798 { seq }, viewerType);
1801 sc.mainFrame.dispose();
1803 if (showRefAnnotations)
1804 showReferenceAnnotationsForSequence(ap.alignFrame, seq);
1809 public static void showReferenceAnnotationsForSequence(AlignFrame af,
1812 AlignViewport av = af.getCurrentView();
1813 AlignmentI al = av.getAlignment();
1815 List<SequenceI> forSequences = new ArrayList<>();
1816 forSequences.add(sequence);
1817 final Map<SequenceI, List<AlignmentAnnotation>> candidates = new LinkedHashMap<>();
1818 AlignmentUtils.findAddableReferenceAnnotations(forSequences, null,
1820 final SequenceGroup selectionGroup = av.getSelectionGroup();
1821 AlignmentUtils.addReferenceAnnotations(candidates, al, selectionGroup);
1822 for (AlignmentViewPanel ap : af.getAlignPanels())
1824 // required to readjust the height and position of the PAE
1826 ap.adjustAnnotationHeight();