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.JalviewFileChooser;
75 import jalview.io.JalviewFileView;
76 import jalview.jbgui.FilterOption;
77 import jalview.jbgui.GStructureChooser;
78 import jalview.structure.StructureImportSettings.TFType;
79 import jalview.structure.StructureMapping;
80 import jalview.structure.StructureSelectionManager;
81 import jalview.util.MessageManager;
82 import jalview.util.Platform;
83 import jalview.util.StringUtils;
84 import jalview.ws.DBRefFetcher;
85 import jalview.ws.DBRefFetcher.FetchFinishedListenerI;
86 import jalview.ws.datamodel.alphafold.PAEContactMatrix;
87 import jalview.ws.seqfetcher.DbSourceProxy;
88 import jalview.ws.sifts.SiftsSettings;
91 * Provides the behaviors for the Structure chooser Panel
96 @SuppressWarnings("serial")
97 public class StructureChooser extends GStructureChooser
98 implements IProgressIndicator
100 private static final String AUTOSUPERIMPOSE = "AUTOSUPERIMPOSE";
103 * warn user if need to fetch more than this many uniprot records at once
105 private static final int THRESHOLD_WARN_UNIPROT_FETCH_NEEDED = 20;
107 private SequenceI selectedSequence;
109 private SequenceI[] selectedSequences;
111 private IProgressIndicator progressIndicator;
113 private Collection<FTSData> discoveredStructuresSet;
115 private StructureChooserQuerySource data;
118 protected FTSDataColumnPreferences getFTSDocFieldPrefs()
120 return data.getDocFieldPrefs();
123 private String selectedPdbFileName;
125 private TFType localPdbTempfacType;
127 private String localPdbPaeMatrixFileName;
129 private boolean isValidPBDEntry;
131 private boolean cachedPDBExists;
133 private Collection<FTSData> lastDiscoveredStructuresSet;
135 private boolean canQueryTDB = false;
137 private boolean notQueriedTDBYet = true;
139 List<SequenceI> seqsWithoutSourceDBRef = null;
141 private boolean showChooserGUI = true;
143 private static StructureViewer lastTargetedView = null;
145 public StructureChooser(SequenceI[] selectedSeqs, SequenceI selectedSeq,
148 this(selectedSeqs, selectedSeq, ap, true);
151 public StructureChooser(SequenceI[] selectedSeqs, SequenceI selectedSeq,
152 AlignmentPanel ap, boolean showGUI)
154 // which FTS engine to use
155 data = StructureChooserQuerySource.getQuerySourceFor(selectedSeqs);
159 this.selectedSequence = selectedSeq;
160 this.selectedSequences = selectedSeqs;
161 this.progressIndicator = (ap == null) ? null : ap.alignFrame;
162 this.showChooserGUI = showGUI;
168 * sets canQueryTDB if protein sequences without a canonical uniprot ref or at
169 * least one structure are discovered.
171 private void populateSeqsWithoutSourceDBRef()
173 seqsWithoutSourceDBRef = new ArrayList<SequenceI>();
174 boolean needCanonical = false;
175 for (SequenceI seq : selectedSequences)
179 int dbRef = ThreeDBStructureChooserQuerySource
180 .checkUniprotRefs(seq.getDBRefs());
185 // need to retrieve canonicals
186 needCanonical = true;
187 seqsWithoutSourceDBRef.add(seq);
191 // could be a sequence with pdb ref
192 if (seq.getAllPDBEntries() == null
193 || seq.getAllPDBEntries().size() == 0)
195 seqsWithoutSourceDBRef.add(seq);
201 // retrieve database refs for protein sequences
202 if (!seqsWithoutSourceDBRef.isEmpty())
207 // triggers display of the 'Query TDB' button
208 notQueriedTDBYet = true;
214 * Initializes parameters used by the Structure Chooser Panel
216 protected void init()
218 if (!Jalview.isHeadlessMode())
220 progressBar = new ProgressBar(this.statusPanel, this.statusBar);
223 chk_superpose.setSelected(Cache.getDefault(AUTOSUPERIMPOSE, true));
224 btn_queryTDB.addActionListener(new ActionListener()
228 public void actionPerformed(ActionEvent e)
230 promptForTDBFetch(false);
234 Executors.defaultThreadFactory().newThread(new Runnable()
239 populateSeqsWithoutSourceDBRef();
240 initialStructureDiscovery();
248 private void initialStructureDiscovery()
250 // check which FTS engine to use
251 data = StructureChooserQuerySource.getQuerySourceFor(selectedSequences);
253 // ensure a filter option is in force for search
254 populateFilterComboBox(true, cachedPDBExists);
256 // looks for any existing structures already loaded
257 // for the sequences (the cached ones)
258 // then queries the StructureChooserQuerySource to
259 // discover more structures.
261 // Possible optimisation is to only begin querying
262 // the structure chooser if there are no cached structures.
264 long startTime = System.currentTimeMillis();
265 updateProgressIndicator(
266 MessageManager.getString("status.loading_cached_pdb_entries"),
268 loadLocalCachedPDBEntries();
269 updateProgressIndicator(null, startTime);
270 updateProgressIndicator(
271 MessageManager.getString("status.searching_for_pdb_structures"),
273 fetchStructuresMetaData();
274 // revise filter options if no results were found
275 populateFilterComboBox(isStructuresDiscovered(), cachedPDBExists);
276 discoverStructureViews();
277 updateProgressIndicator(null, startTime);
278 mainFrame.setVisible(showChooserGUI);
283 * raises dialog for Uniprot fetch followed by 3D beacons search
286 * - when true, don't ask, just fetch
288 public void promptForTDBFetch(boolean ignoreGui)
290 final long progressId = System.currentTimeMillis();
292 // final action after prompting and discovering db refs
293 final Runnable strucDiscovery = new Runnable()
298 mainFrame.setEnabled(false);
299 cmb_filterOption.setEnabled(false);
300 progressBar.setProgressBar(
301 MessageManager.getString("status.searching_3d_beacons"),
303 btn_queryTDB.setEnabled(false);
304 // TODO: warn if no accessions discovered
305 populateSeqsWithoutSourceDBRef();
306 // redo initial discovery - this time with 3d beacons
308 previousWantedFields = null;
309 lastSelected = (FilterOption) cmb_filterOption.getSelectedItem();
310 cmb_filterOption.setSelectedItem(null);
311 cachedPDBExists = false; // reset to initial
312 initialStructureDiscovery();
313 if (!isStructuresDiscovered())
315 progressBar.setProgressBar(MessageManager.getString(
316 "status.no_structures_discovered_from_3d_beacons"),
318 btn_queryTDB.setToolTipText(MessageManager.getString(
319 "status.no_structures_discovered_from_3d_beacons"));
320 btn_queryTDB.setEnabled(false);
321 pnl_queryTDB.setVisible(false);
325 cmb_filterOption.setSelectedIndex(0); // select 'best'
326 btn_queryTDB.setVisible(false);
327 pnl_queryTDB.setVisible(false);
328 progressBar.setProgressBar(null, progressId);
330 mainFrame.setEnabled(true);
331 cmb_filterOption.setEnabled(true);
335 final FetchFinishedListenerI afterDbRefFetch = new FetchFinishedListenerI()
339 public void finished()
341 // filter has been selected, so we set flag to remove ourselves
342 notQueriedTDBYet = false;
343 // new thread to discover structures - via 3d beacons
344 Executors.defaultThreadFactory().newThread(strucDiscovery).start();
349 // fetch db refs if OK pressed
350 final Runnable discoverCanonicalDBrefs = () -> {
351 btn_queryTDB.setEnabled(false);
352 populateSeqsWithoutSourceDBRef();
354 final int y = seqsWithoutSourceDBRef.size();
357 final SequenceI[] seqWithoutSrcDBRef = seqsWithoutSourceDBRef
358 .toArray(new SequenceI[y]);
359 DBRefFetcher dbRefFetcher = new DBRefFetcher(seqWithoutSrcDBRef,
360 progressBar, new DbSourceProxy[]
361 { new jalview.ws.dbsources.Uniprot() }, null, false);
362 dbRefFetcher.addListener(afterDbRefFetch);
363 // ideally this would also gracefully run with callbacks
365 dbRefFetcher.fetchDBRefs(true);
369 // call finished action directly
370 afterDbRefFetch.finished();
373 final Runnable revertview = () -> {
374 if (lastSelected != null)
376 cmb_filterOption.setSelectedItem(lastSelected);
379 int threshold = Cache.getDefault("UNIPROT_AUTOFETCH_THRESHOLD",
380 THRESHOLD_WARN_UNIPROT_FETCH_NEEDED);
381 Console.debug("Using Uniprot fetch threshold of " + threshold);
382 if (ignoreGui || seqsWithoutSourceDBRef.size() < threshold)
384 Executors.newSingleThreadExecutor().submit(discoverCanonicalDBrefs);
387 // need cancel and no to result in the discoverPDB action - mocked is
388 // 'cancel' TODO: mock should be OK
390 StructureChooser thisSC = this;
391 JvOptionPane.newOptionDialog(thisSC.getFrame())
392 .setResponseHandler(JvOptionPane.OK_OPTION,
393 discoverCanonicalDBrefs)
394 .setResponseHandler(JvOptionPane.CANCEL_OPTION, revertview)
395 .setResponseHandler(JvOptionPane.NO_OPTION, revertview)
397 MessageManager.formatMessage(
398 "label.fetch_references_for_3dbeacons",
399 seqsWithoutSourceDBRef.size()),
400 MessageManager.getString("label.3dbeacons"),
401 JvOptionPane.YES_NO_OPTION, JvOptionPane.PLAIN_MESSAGE,
403 { MessageManager.getString("action.ok"),
404 MessageManager.getString("action.cancel") },
405 MessageManager.getString("action.ok"), false);
409 * Builds a drop-down choice list of existing structure viewers to which new
410 * structures may be added. If this list is empty then it, and the 'Add'
411 * button, are hidden.
413 private void discoverStructureViews()
415 if (Desktop.instance != null)
417 targetView.removeAllItems();
418 if (lastTargetedView != null && !lastTargetedView.isVisible())
420 lastTargetedView = null;
422 int linkedViewsAt = 0;
423 for (StructureViewerBase view : Desktop.instance
424 .getStructureViewers(null, null))
426 StructureViewer viewHandler = (lastTargetedView != null
427 && lastTargetedView.sview == view) ? lastTargetedView
428 : StructureViewer.reconfigure(view);
430 if (view.isLinkedWith(ap))
432 targetView.insertItemAt(viewHandler, linkedViewsAt++);
436 targetView.addItem(viewHandler);
441 * show option to Add to viewer if at least 1 viewer found
443 targetView.setVisible(false);
444 if (targetView.getItemCount() > 0)
446 targetView.setVisible(true);
447 if (lastTargetedView != null)
449 targetView.setSelectedItem(lastTargetedView);
453 targetView.setSelectedIndex(0);
456 btn_add.setVisible(targetView.isVisible());
461 * Updates the progress indicator with the specified message
464 * displayed message for the operation
466 * unique handle for this indicator
468 protected void updateProgressIndicator(String message, long id)
470 if (progressIndicator != null)
472 progressIndicator.setProgressBar(message, id);
477 * Retrieve meta-data for all the structure(s) for a given sequence(s) in a
480 void fetchStructuresMetaData()
482 long startTime = System.currentTimeMillis();
483 Collection<FTSDataColumnI> wantedFields = data.getDocFieldPrefs()
484 .getStructureSummaryFields();
486 discoveredStructuresSet = new LinkedHashSet<>();
487 HashSet<String> errors = new HashSet<>();
489 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
492 for (SequenceI seq : selectedSequences)
495 FTSRestResponse resultList;
498 resultList = data.fetchStructuresMetaData(seq, wantedFields,
499 selectedFilterOpt, !chk_invertFilter.isSelected());
500 // null response means the FTSengine didn't yield a query for this
501 // consider designing a special exception if we really wanted to be
503 if (resultList == null)
507 } catch (Exception e)
510 errors.add(e.getMessage());
513 if (resultList.getSearchSummary() != null
514 && !resultList.getSearchSummary().isEmpty())
516 discoveredStructuresSet.addAll(resultList.getSearchSummary());
520 int noOfStructuresFound = 0;
521 String totalTime = (System.currentTimeMillis() - startTime)
523 if (discoveredStructuresSet != null
524 && !discoveredStructuresSet.isEmpty())
527 .setModel(data.getTableModel(discoveredStructuresSet));
529 noOfStructuresFound = discoveredStructuresSet.size();
530 lastDiscoveredStructuresSet = discoveredStructuresSet;
531 mainFrame.setTitle(MessageManager.formatMessage(
532 "label.structure_chooser_no_of_structures",
533 noOfStructuresFound, totalTime));
537 mainFrame.setTitle(MessageManager
538 .getString("label.structure_chooser_manual_association"));
539 if (errors.size() > 0)
541 StringBuilder errorMsg = new StringBuilder();
542 for (String error : errors)
544 errorMsg.append(error).append("\n");
546 JvOptionPane.showMessageDialog(this, errorMsg.toString(),
547 MessageManager.getString("label.pdb_web-service_error"),
548 JvOptionPane.ERROR_MESSAGE);
553 protected void loadLocalCachedPDBEntries()
555 ArrayList<CachedPDB> entries = new ArrayList<>();
556 for (SequenceI seq : selectedSequences)
558 if (seq.getDatasetSequence() != null
559 && seq.getDatasetSequence().getAllPDBEntries() != null)
561 for (PDBEntry pdbEntry : seq.getDatasetSequence()
564 if (pdbEntry.getFile() != null)
566 entries.add(new CachedPDB(seq, pdbEntry));
571 cachedPDBExists = !entries.isEmpty();
572 PDBEntryTableModel tableModelx = new PDBEntryTableModel(entries);
573 tbl_local_pdb.setModel(tableModelx);
577 * Filters a given list of discovered structures based on supplied argument
579 * @param fieldToFilterBy
580 * the field to filter by
582 void filterResultSet(final String fieldToFilterBy)
584 Thread filterThread = new Thread(new Runnable()
590 long startTime = System.currentTimeMillis();
591 lbl_loading.setVisible(true);
592 Collection<FTSDataColumnI> wantedFields = data.getDocFieldPrefs()
593 .getStructureSummaryFields();
594 Collection<FTSData> filteredResponse = new HashSet<>();
595 HashSet<String> errors = new HashSet<>();
597 for (SequenceI seq : selectedSequences)
600 FTSRestResponse resultList;
603 resultList = data.selectFirstRankedQuery(seq,
604 discoveredStructuresSet, wantedFields, fieldToFilterBy,
605 !chk_invertFilter.isSelected());
607 } catch (Exception e)
610 errors.add(e.getMessage());
613 if (resultList.getSearchSummary() != null
614 && !resultList.getSearchSummary().isEmpty())
616 filteredResponse.addAll(resultList.getSearchSummary());
620 String totalTime = (System.currentTimeMillis() - startTime)
622 if (!filteredResponse.isEmpty())
624 final int filterResponseCount = filteredResponse.size();
625 Collection<FTSData> reorderedStructuresSet = new LinkedHashSet<>();
626 reorderedStructuresSet.addAll(filteredResponse);
627 reorderedStructuresSet.addAll(discoveredStructuresSet);
629 .setModel(data.getTableModel(reorderedStructuresSet));
631 FTSRestResponse.configureTableColumn(getResultTable(),
632 wantedFields, tempUserPrefs);
633 getResultTable().getColumn("Ref Sequence").setPreferredWidth(120);
634 getResultTable().getColumn("Ref Sequence").setMinWidth(100);
635 getResultTable().getColumn("Ref Sequence").setMaxWidth(200);
636 // Update table selection model here
637 getResultTable().addRowSelectionInterval(0,
638 filterResponseCount - 1);
639 mainFrame.setTitle(MessageManager.formatMessage(
640 "label.structure_chooser_filter_time", totalTime));
644 mainFrame.setTitle(MessageManager.formatMessage(
645 "label.structure_chooser_filter_time", totalTime));
646 if (errors.size() > 0)
648 StringBuilder errorMsg = new StringBuilder();
649 for (String error : errors)
651 errorMsg.append(error).append("\n");
653 JvOptionPane.showMessageDialog(null, errorMsg.toString(),
654 MessageManager.getString("label.pdb_web-service_error"),
655 JvOptionPane.ERROR_MESSAGE);
659 lbl_loading.setVisible(false);
661 validateSelections();
664 filterThread.start();
668 * Handles action event for btn_pdbFromFile
671 protected void pdbFromFile_actionPerformed()
673 // TODO: JAL-3048 not needed for Jalview-JS until JSmol dep and
676 JalviewFileChooser chooser = new JalviewFileChooser(
677 Cache.getProperty("LAST_DIRECTORY"));
678 chooser.setFileView(new JalviewFileView());
679 chooser.setDialogTitle(
680 MessageManager.formatMessage("label.select_pdb_file_for",
681 selectedSequence.getDisplayId(false)));
682 chooser.setToolTipText(MessageManager.formatMessage(
683 "label.load_pdb_file_associate_with_sequence",
684 selectedSequence.getDisplayId(false)));
686 int value = chooser.showOpenDialog(null);
687 if (value == JalviewFileChooser.APPROVE_OPTION)
689 selectedPdbFileName = chooser.getSelectedFile().getPath();
690 Cache.setProperty("LAST_DIRECTORY", selectedPdbFileName);
691 boolean guessTFType = localPdbPaeMatrixFileName == null;
692 localPdbPaeMatrixFileName = guessPAEFilename();
693 guessTFType |= localPdbPaeMatrixFileName != null;
694 Regex alphaFold = JmolParser.getNewAlphafoldValidator();
696 && alphaFold.search(new File(selectedPdbFileName).getName())
697 && !tempFacAsChanged)
699 // localPdbPaeMatrixFileName was null and now isn't and filename could
700 // well be AlphaFold and user hasn't adjusted the tempFacType
701 combo_tempFacAs.setSelectedItem(TFType.PLDDT);
703 validateSelections();
708 * Handles action event for btn_paeMatrixFile
711 protected void paeMatrixFile_actionPerformed()
713 File pdbFile = new File(selectedPdbFileName);
714 String setFile = Cache.getProperty("LAST_DIRECTORY");
715 if (localPdbPaeMatrixFileName != null)
717 File paeFile = new File(localPdbPaeMatrixFileName);
718 if (paeFile.exists())
719 setFile = paeFile.getAbsolutePath();
720 else if (paeFile.getParentFile().exists())
721 setFile = paeFile.getParentFile().getAbsolutePath();
725 String guess = guessPAEFilename();
729 JalviewFileChooser chooser = new JalviewFileChooser(setFile);
730 chooser.setFileView(new JalviewFileView());
731 chooser.setDialogTitle(MessageManager.formatMessage(
732 "label.select_pae_matrix_file_for", pdbFile.getName()));
733 chooser.setToolTipText(MessageManager.formatMessage(
734 "label.load_pae_matrix_file_associate_with_structure",
737 // TODO convert to Callable/Promise
738 int value = chooser.showOpenDialog(null);
739 if (value == JalviewFileChooser.APPROVE_OPTION)
741 String fileName = chooser.getSelectedFile().getPath();
744 PAEContactMatrix.validateContactMatrixFile(fileName);
745 } catch (Exception thr)
747 JvOptionPane.showInternalMessageDialog(this, MessageManager
748 .formatMessage("label.couldnt_load_file", new Object[]
749 { fileName }) + "<br>" + thr.getLocalizedMessage(),
750 MessageManager.getString("label.error_loading_file"),
751 JvOptionPane.WARNING_MESSAGE);
752 Console.error("Couldn't import " + fileName + " as a PAE matrix",
756 localPdbPaeMatrixFileName = fileName;
757 Cache.setProperty("LAST_DIRECTORY", localPdbPaeMatrixFileName);
759 validateAssociationFromFile();
762 private String guessPAEFilename()
764 if (selectedPdbFileName.toLowerCase(Locale.ROOT).endsWith(".pdb")
765 || selectedPdbFileName.toLowerCase(Locale.ROOT)
768 String jsonExt = selectedPdbFileName.substring(0,
769 selectedPdbFileName.length() - 4) + ".json";
770 // AlphaFold naming scheme
771 String guessFile1 = StringUtils.replaceLast(jsonExt, "model",
772 "predicted_aligned_error");
773 // nf-core mode naming scheme
774 String guessFile2 = StringUtils.replaceLast(jsonExt, ".json",
776 if (new File(guessFile1).exists())
780 else if (new File(jsonExt).exists())
784 else if (new File(guessFile2).exists())
793 * Populates the filter combo-box options dynamically depending on discovered
796 protected void populateFilterComboBox(boolean haveData,
797 boolean cachedPDBExist)
799 populateFilterComboBox(haveData, cachedPDBExist, null);
803 * Populates the filter combo-box options dynamically depending on discovered
806 protected void populateFilterComboBox(boolean haveData,
807 boolean cachedPDBExist, FilterOption lastSel)
811 * temporarily suspend the change listener behaviour
813 cmb_filterOption.removeItemListener(this);
815 cmb_filterOption.removeAllItems();
818 List<FilterOption> filters = data
819 .getAvailableFilterOptions(VIEWS_FILTER);
820 data.updateAvailableFilterOptions(VIEWS_FILTER, filters,
821 lastDiscoveredStructuresSet);
823 for (FilterOption filter : filters)
825 if (lastSel != null && filter.equals(lastSel))
830 cmb_filterOption.addItem(filter);
834 cmb_filterOption.addItem(
835 new FilterOption(MessageManager.getString("label.enter_pdb_id"),
836 "-", VIEWS_ENTER_ID, false, null));
837 cmb_filterOption.addItem(
838 new FilterOption(MessageManager.getString("label.from_file"),
839 "-", VIEWS_FROM_FILE, false, null));
840 if (canQueryTDB && notQueriedTDBYet)
842 btn_queryTDB.setVisible(true);
843 pnl_queryTDB.setVisible(true);
848 FilterOption cachedOption = new FilterOption(
849 MessageManager.getString("label.cached_structures"), "-",
850 VIEWS_LOCAL_PDB, false, null);
851 cmb_filterOption.addItem(cachedOption);
854 cmb_filterOption.setSelectedItem(cachedOption);
859 cmb_filterOption.setSelectedIndex(selSet);
861 cmb_filterOption.addItemListener(this);
865 * Updates the displayed view based on the selected filter option
867 protected void updateCurrentView()
869 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
872 if (lastSelected == selectedFilterOpt)
874 // don't need to do anything, probably
877 // otherwise, record selection
878 // and update the layout and dialog accordingly
879 lastSelected = selectedFilterOpt;
881 layout_switchableViews.show(pnl_switchableViews,
882 selectedFilterOpt.getView());
883 String filterTitle = mainFrame.getTitle();
884 mainFrame.setTitle(frameTitle);
885 chk_invertFilter.setVisible(false);
887 if (selectedFilterOpt.getView() == VIEWS_FILTER)
889 mainFrame.setTitle(filterTitle);
890 // TDB Query has no invert as yet
891 chk_invertFilter.setVisible(selectedFilterOpt
892 .getQuerySource() instanceof PDBStructureChooserQuerySource);
894 if (data != selectedFilterOpt.getQuerySource()
895 || data.needsRefetch(selectedFilterOpt))
897 data = selectedFilterOpt.getQuerySource();
898 // rebuild the views completely, since prefs will also change
904 filterResultSet(selectedFilterOpt.getValue());
907 else if (selectedFilterOpt.getView() == VIEWS_ENTER_ID
908 || selectedFilterOpt.getView() == VIEWS_FROM_FILE)
910 mainFrame.setTitle(MessageManager
911 .getString("label.structure_chooser_manual_association"));
912 idInputAssSeqPanel.loadCmbAssSeq();
913 fileChooserAssSeqPanel.loadCmbAssSeq();
915 validateSelections();
919 * Validates user selection and enables the 'Add' and 'New View' buttons if
920 * all parameters are correct (the Add button will only be visible if there is
921 * at least one existing structure viewer open). This basically means at least
922 * one structure selected and no error messages.
924 * The 'Superpose Structures' option is enabled if either more than one
925 * structure is selected, or the 'Add' to existing view option is enabled, and
926 * disabled if the only option is to open a new view of a single structure.
929 protected void validateSelections()
931 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
933 btn_add.setEnabled(false);
934 String currentView = selectedFilterOpt.getView();
935 int selectedCount = 0;
936 if (currentView == VIEWS_FILTER)
938 selectedCount = getResultTable().getSelectedRows().length;
939 if (selectedCount > 0)
941 btn_add.setEnabled(true);
944 else if (currentView == VIEWS_LOCAL_PDB)
946 selectedCount = tbl_local_pdb.getSelectedRows().length;
947 if (selectedCount > 0)
949 btn_add.setEnabled(true);
952 else if (currentView == VIEWS_ENTER_ID)
954 validateAssociationEnterPdb();
956 else if (currentView == VIEWS_FROM_FILE)
958 validateAssociationFromFile();
961 btn_newView.setEnabled(btn_add.isEnabled());
964 * enable 'Superpose' option if more than one structure is selected,
965 * or there are view(s) available to add structure(s) to
968 .setEnabled(selectedCount > 1 || targetView.getItemCount() > 0);
972 protected boolean showPopupFor(int selectedRow, int x, int y)
974 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
976 String currentView = selectedFilterOpt.getView();
978 if (currentView == VIEWS_FILTER
979 && data instanceof ThreeDBStructureChooserQuerySource)
982 TDB_FTSData row = ((ThreeDBStructureChooserQuerySource) data)
983 .getFTSDataFor(getResultTable(), selectedRow,
984 discoveredStructuresSet);
985 String pageUrl = row.getModelViewUrl();
986 JPopupMenu popup = new JPopupMenu("3D Beacons");
987 JMenuItem viewUrl = new JMenuItem("View model web page");
988 viewUrl.addActionListener(new ActionListener()
991 public void actionPerformed(ActionEvent e)
993 Desktop.showUrl(pageUrl);
997 SwingUtilities.invokeLater(new Runnable()
1002 popup.show(getResultTable(), x, y);
1007 // event not handled by us
1012 * Validates inputs from the Manual PDB entry panel
1014 protected void validateAssociationEnterPdb()
1016 AssociateSeqOptions assSeqOpt = (AssociateSeqOptions) idInputAssSeqPanel
1017 .getCmb_assSeq().getSelectedItem();
1018 lbl_pdbManualFetchStatus.setIcon(errorImage);
1019 lbl_pdbManualFetchStatus.setToolTipText("");
1020 if (txt_search.getText().length() > 0)
1022 lbl_pdbManualFetchStatus.setToolTipText(JvSwingUtils.wrapTooltip(true,
1023 MessageManager.formatMessage("info.no_pdb_entry_found_for",
1024 txt_search.getText())));
1027 if (errorWarning.length() > 0)
1029 lbl_pdbManualFetchStatus.setIcon(warningImage);
1030 lbl_pdbManualFetchStatus.setToolTipText(
1031 JvSwingUtils.wrapTooltip(true, errorWarning.toString()));
1034 if (selectedSequences.length == 1 || !assSeqOpt.getName()
1035 .equalsIgnoreCase("-Select Associated Seq-"))
1037 txt_search.setEnabled(true);
1038 if (isValidPBDEntry)
1040 btn_add.setEnabled(true);
1041 lbl_pdbManualFetchStatus.setToolTipText("");
1042 lbl_pdbManualFetchStatus.setIcon(goodImage);
1047 txt_search.setEnabled(false);
1048 lbl_pdbManualFetchStatus.setIcon(errorImage);
1053 * Validates inputs for the manual PDB file selection options
1055 protected void validateAssociationFromFile()
1057 AssociateSeqOptions assSeqOpt = (AssociateSeqOptions) fileChooserAssSeqPanel
1058 .getCmb_assSeq().getSelectedItem();
1059 // lbl_fromFileStatus.setIcon(errorImage);
1060 String pdbFileString = "";
1061 String pdbFileTooltip = "";
1062 if (selectedSequences.length == 1 || (assSeqOpt != null && !assSeqOpt
1063 .getName().equalsIgnoreCase("-Select Associated Seq-")))
1065 btn_pdbFromFile.setEnabled(true);
1066 if (selectedPdbFileName != null && selectedPdbFileName.length() > 0)
1068 btn_add.setEnabled(true);
1069 // lbl_fromFileStatus.setIcon(goodImage);
1070 pdbFileString = new File(selectedPdbFileName).getName();
1071 pdbFileTooltip = new File(selectedPdbFileName).getAbsolutePath();
1072 setPdbOptionsEnabled(true);
1076 pdbFileString = MessageManager.getString("label.none");
1077 pdbFileTooltip = MessageManager.getString("label.nothing_selected");
1078 setPdbOptionsEnabled(false);
1083 btn_pdbFromFile.setEnabled(false);
1084 setPdbOptionsEnabled(false);
1085 // lbl_fromFileStatus.setIcon(errorImage);
1086 pdbFileString = MessageManager.getString("label.none");
1087 pdbFileTooltip = MessageManager.getString("label.nothing_selected");
1089 lbl_pdbFile.setText(pdbFileString);
1090 lbl_pdbFile.setToolTipText(pdbFileTooltip);
1093 String paeFileString = "";
1094 String paeFileTooltip = "";
1095 if (localPdbPaeMatrixFileName != null
1096 && localPdbPaeMatrixFileName.length() > 0)
1098 paeFileString = new File(localPdbPaeMatrixFileName).getName();
1099 paeFileTooltip = new File(localPdbPaeMatrixFileName)
1104 paeFileString = MessageManager.getString("label.none");
1105 paeFileTooltip = MessageManager.getString("label.nothing_selected");
1107 lbl_paeFile.setText(paeFileString);
1108 lbl_paeFile.setToolTipText(paeFileTooltip);
1112 protected void cmbAssSeqStateChanged()
1114 validateSelections();
1117 private FilterOption lastSelected = null;
1120 * Handles the state change event for the 'filter' combo-box and 'invert'
1124 protected void stateChanged(ItemEvent e)
1126 if (e.getSource() instanceof JCheckBox)
1128 updateCurrentView();
1132 if (e.getStateChange() == ItemEvent.SELECTED)
1134 updateCurrentView();
1141 * select structures for viewing by their PDB IDs
1144 * @return true if structures were found and marked as selected
1146 public boolean selectStructure(String... pdbids)
1148 boolean found = false;
1150 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
1151 .getSelectedItem());
1152 String currentView = selectedFilterOpt.getView();
1153 JTable restable = (currentView == VIEWS_FILTER) ? getResultTable()
1154 : (currentView == VIEWS_LOCAL_PDB) ? tbl_local_pdb : null;
1156 if (restable == null)
1158 // can't select (enter PDB ID, or load file - need to also select which
1159 // sequence to associate with)
1163 int pdbIdColIndex = restable.getColumn("PDB Id").getModelIndex();
1164 for (int r = 0; r < restable.getRowCount(); r++)
1166 for (int p = 0; p < pdbids.length; p++)
1168 if (String.valueOf(restable.getValueAt(r, pdbIdColIndex))
1169 .equalsIgnoreCase(pdbids[p]))
1171 restable.setRowSelectionInterval(r, r);
1180 * Handles the 'New View' action
1183 protected void newView_ActionPerformed()
1185 targetView.setSelectedItem(null);
1186 showStructures(false);
1190 * Handles the 'Add to existing viewer' action
1193 protected void add_ActionPerformed()
1195 showStructures(false);
1199 * structure viewer opened by this dialog, or null
1201 private StructureViewer sViewer = null;
1203 public void showStructures(boolean waitUntilFinished)
1206 final StructureSelectionManager ssm = ap.getStructureSelectionManager();
1208 final int preferredHeight = pnl_filter.getHeight();
1209 btn_add.setEnabled(false);
1210 btn_newView.setEnabled(false);
1211 btn_cancel.setEnabled(false);
1212 actionsPanel.setEnabled(false);
1214 final String progress = MessageManager
1215 .getString("label.working_ellipsis");
1216 setProgressBar(progress, progress.hashCode());
1217 Runnable viewStruc = new Runnable()
1222 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
1223 .getSelectedItem());
1224 String currentView = selectedFilterOpt.getView();
1225 JTable restable = (currentView == VIEWS_FILTER) ? getResultTable()
1228 if (currentView == VIEWS_FILTER)
1230 int[] selectedRows = restable.getSelectedRows();
1231 PDBEntry[] pdbEntriesToView = new PDBEntry[selectedRows.length];
1232 List<SequenceI> selectedSeqsToView = new ArrayList<>();
1233 pdbEntriesToView = data.collectSelectedRows(restable,
1234 selectedRows, selectedSeqsToView);
1236 SequenceI[] selectedSeqs = selectedSeqsToView
1237 .toArray(new SequenceI[selectedSeqsToView.size()]);
1238 sViewer = launchStructureViewer(ssm, pdbEntriesToView, ap,
1241 else if (currentView == VIEWS_LOCAL_PDB)
1243 int[] selectedRows = tbl_local_pdb.getSelectedRows();
1244 PDBEntry[] pdbEntriesToView = new PDBEntry[selectedRows.length];
1246 int pdbIdColIndex = tbl_local_pdb.getColumn("PDB Id")
1248 int refSeqColIndex = tbl_local_pdb.getColumn("Ref Sequence")
1250 List<SequenceI> selectedSeqsToView = new ArrayList<>();
1251 for (int row : selectedRows)
1253 PDBEntry pdbEntry = ((PDBEntryTableModel) tbl_local_pdb
1254 .getModel()).getPDBEntryAt(row).getPdbEntry();
1256 pdbEntriesToView[count++] = pdbEntry;
1257 SequenceI selectedSeq = (SequenceI) tbl_local_pdb
1258 .getValueAt(row, refSeqColIndex);
1259 selectedSeqsToView.add(selectedSeq);
1261 SequenceI[] selectedSeqs = selectedSeqsToView
1262 .toArray(new SequenceI[selectedSeqsToView.size()]);
1263 sViewer = launchStructureViewer(ssm, pdbEntriesToView, ap,
1266 else if (currentView == VIEWS_ENTER_ID)
1268 SequenceI userSelectedSeq = ((AssociateSeqOptions) idInputAssSeqPanel
1269 .getCmb_assSeq().getSelectedItem()).getSequence();
1270 if (userSelectedSeq != null)
1272 selectedSequence = userSelectedSeq;
1274 String pdbIdStr = txt_search.getText();
1275 PDBEntry pdbEntry = selectedSequence.getPDBEntry(pdbIdStr);
1276 if (pdbEntry == null)
1278 pdbEntry = new PDBEntry();
1279 if (pdbIdStr.split(":").length > 1)
1281 pdbEntry.setId(pdbIdStr.split(":")[0]);
1282 pdbEntry.setChainCode(
1283 pdbIdStr.split(":")[1].toUpperCase(Locale.ROOT));
1287 pdbEntry.setId(pdbIdStr);
1289 pdbEntry.setType(PDBEntry.Type.PDB);
1290 selectedSequence.getDatasetSequence().addPDBId(pdbEntry);
1293 PDBEntry[] pdbEntriesToView = new PDBEntry[] { pdbEntry };
1294 sViewer = launchStructureViewer(ssm, pdbEntriesToView, ap,
1296 { selectedSequence });
1298 else if (currentView == VIEWS_FROM_FILE)
1300 StructureChooser sc = StructureChooser.this;
1301 TFType tft = (TFType) sc.combo_tempFacAs.getSelectedItem();
1302 String paeFilename = sc.localPdbPaeMatrixFileName;
1303 AssociateSeqOptions assSeqOpt = (AssociateSeqOptions) fileChooserAssSeqPanel
1304 .getCmb_assSeq().getSelectedItem();
1305 SequenceI userSelectedSeq = assSeqOpt.getSequence();
1306 if (userSelectedSeq != null)
1308 selectedSequence = userSelectedSeq;
1310 String pdbFilename = selectedPdbFileName;
1312 StructureChooser.openStructureFileForSequence(ssm, sc, ap,
1313 selectedSequence, true, pdbFilename, tft, paeFilename,
1316 SwingUtilities.invokeLater(new Runnable()
1321 setProgressBar("Complete.", progress.hashCode());
1322 closeAction(preferredHeight);
1323 mainFrame.dispose();
1328 Thread runner = new Thread(viewStruc);
1330 if (waitUntilFinished)
1332 while (sViewer == null ? runner.isAlive()
1333 : (sViewer.sview == null ? true
1334 : !sViewer.sview.hasMapping()))
1339 } catch (InterruptedException ie)
1348 * Answers a structure viewer (new or existing) configured to superimpose
1349 * added structures or not according to the user's choice
1354 StructureViewer getTargetedStructureViewer(StructureSelectionManager ssm)
1356 Object sv = targetView.getSelectedItem();
1358 return sv == null ? new StructureViewer(ssm) : (StructureViewer) sv;
1362 * Adds PDB structures to a new or existing structure viewer
1365 * @param pdbEntriesToView
1370 private StructureViewer launchStructureViewer(
1371 StructureSelectionManager ssm, final PDBEntry[] pdbEntriesToView,
1372 final AlignmentPanel alignPanel, SequenceI[] sequences)
1374 return launchStructureViewer(ssm, pdbEntriesToView, alignPanel,
1378 private StructureViewer launchStructureViewer(
1379 StructureSelectionManager ssm, final PDBEntry[] pdbEntriesToView,
1380 final AlignmentPanel alignPanel, SequenceI[] sequences,
1381 ViewerType viewerType)
1383 long progressId = sequences.hashCode();
1384 setProgressBar(MessageManager
1385 .getString("status.launching_3d_structure_viewer"), progressId);
1386 final StructureViewer theViewer = getTargetedStructureViewer(ssm);
1387 boolean superimpose = chk_superpose.isSelected();
1388 theViewer.setSuperpose(superimpose);
1391 * remember user's choice of superimpose or not
1393 Cache.setProperty(AUTOSUPERIMPOSE,
1394 Boolean.valueOf(superimpose).toString());
1396 setProgressBar(null, progressId);
1397 if (SiftsSettings.isMapWithSifts())
1399 List<SequenceI> seqsWithoutSourceDBRef = new ArrayList<>();
1401 // TODO: skip PDBEntry:Sequence pairs where PDBEntry doesn't look like a
1402 // real PDB ID. For moment, we can also safely do this if there is already
1403 // a known mapping between the PDBEntry and the sequence.
1404 for (SequenceI seq : sequences)
1406 PDBEntry pdbe = pdbEntriesToView[p++];
1407 if (pdbe != null && pdbe.getFile() != null)
1409 StructureMapping[] smm = ssm.getMapping(pdbe.getFile());
1410 if (smm != null && smm.length > 0)
1412 for (StructureMapping sm : smm)
1414 if (sm.getSequence() == seq)
1421 if (seq.getPrimaryDBRefs().isEmpty())
1423 seqsWithoutSourceDBRef.add(seq);
1427 if (!seqsWithoutSourceDBRef.isEmpty())
1429 int y = seqsWithoutSourceDBRef.size();
1430 setProgressBar(MessageManager.formatMessage(
1431 "status.fetching_dbrefs_for_sequences_without_valid_refs",
1433 SequenceI[] seqWithoutSrcDBRef = seqsWithoutSourceDBRef
1434 .toArray(new SequenceI[y]);
1435 DBRefFetcher dbRefFetcher = new DBRefFetcher(seqWithoutSrcDBRef);
1436 dbRefFetcher.fetchDBRefs(true);
1438 setProgressBar("Fetch complete.", progressId); // todo i18n
1441 if (pdbEntriesToView.length > 1)
1444 MessageManager.getString(
1445 "status.fetching_3d_structures_for_selected_entries"),
1447 theViewer.viewStructures(pdbEntriesToView, sequences, alignPanel,
1452 setProgressBar(MessageManager.formatMessage(
1453 "status.fetching_3d_structures_for",
1454 pdbEntriesToView[0].getId()), progressId);
1455 // Can we pass a pre-computeMappinged pdbFile?
1456 theViewer.viewStructures(pdbEntriesToView[0], sequences, alignPanel,
1459 setProgressBar(null, progressId);
1460 // remember the last viewer we used...
1461 lastTargetedView = theViewer;
1466 * Populates the combo-box used in associating manually fetched structures to
1467 * a unique sequence when more than one sequence selection is made.
1470 protected void populateCmbAssociateSeqOptions(
1471 JComboBox<AssociateSeqOptions> cmb_assSeq,
1472 JLabel lbl_associateSeq)
1474 cmb_assSeq.removeAllItems();
1476 new AssociateSeqOptions("-Select Associated Seq-", null));
1477 lbl_associateSeq.setVisible(false);
1478 if (selectedSequences.length > 1)
1480 for (SequenceI seq : selectedSequences)
1482 cmb_assSeq.addItem(new AssociateSeqOptions(seq));
1487 String seqName = selectedSequence.getDisplayId(false);
1488 seqName = seqName.length() <= 40 ? seqName : seqName.substring(0, 39);
1489 lbl_associateSeq.setText(seqName);
1490 lbl_associateSeq.setVisible(true);
1491 cmb_assSeq.setVisible(false);
1495 protected boolean isStructuresDiscovered()
1497 return discoveredStructuresSet != null
1498 && !discoveredStructuresSet.isEmpty();
1501 protected int PDB_ID_MIN = 3;// or: (Jalview.isJS() ? 3 : 1); // Bob proposes
1503 // Doing a search for "1" or "1c" is valuable?
1504 // Those work but are enormously slow.
1507 protected void txt_search_ActionPerformed()
1509 String text = txt_search.getText().trim();
1510 if (text.length() >= PDB_ID_MIN)
1517 errorWarning.setLength(0);
1518 isValidPBDEntry = false;
1519 if (text.length() > 0)
1521 // TODO move this pdb id search into the PDB specific
1523 // for moment, it will work fine as is because it is self-contained
1524 String searchTerm = text.toLowerCase(Locale.ROOT);
1525 searchTerm = searchTerm.split(":")[0];
1526 // jalview.bin.Console.outPrintln(">>>>> search term : " + searchTerm);
1527 List<FTSDataColumnI> wantedFields = new ArrayList<>();
1528 FTSRestRequest pdbRequest = new FTSRestRequest();
1529 pdbRequest.setAllowEmptySeq(false);
1530 pdbRequest.setResponseSize(1);
1531 pdbRequest.setFieldToSearchBy("(pdb_id:");
1532 pdbRequest.setWantedFields(wantedFields);
1533 pdbRequest.setSearchTerm(searchTerm + ")");
1534 pdbRequest.setAssociatedSequence(selectedSequence);
1535 FTSRestClientI pdbRestClient = PDBFTSRestClient.getInstance();
1536 wantedFields.add(pdbRestClient.getPrimaryKeyColumn());
1537 FTSRestResponse resultList;
1540 resultList = pdbRestClient.executeRequest(pdbRequest);
1541 } catch (Exception e)
1543 errorWarning.append(e.getMessage());
1547 validateSelections();
1549 if (resultList.getSearchSummary() != null
1550 && resultList.getSearchSummary().size() > 0)
1552 isValidPBDEntry = true;
1555 validateSelections();
1561 protected void tabRefresh()
1563 if (selectedSequences != null)
1565 lbl_loading.setVisible(true);
1566 Thread refreshThread = new Thread(new Runnable()
1571 fetchStructuresMetaData();
1572 // populateFilterComboBox(true, cachedPDBExists);
1575 ((FilterOption) cmb_filterOption.getSelectedItem())
1577 lbl_loading.setVisible(false);
1580 refreshThread.start();
1584 public class PDBEntryTableModel extends AbstractTableModel
1586 String[] columns = { "Ref Sequence", "PDB Id", "Chain", "Type",
1589 private List<CachedPDB> pdbEntries;
1591 public PDBEntryTableModel(List<CachedPDB> pdbEntries)
1593 this.pdbEntries = new ArrayList<>(pdbEntries);
1597 public String getColumnName(int columnIndex)
1599 return columns[columnIndex];
1603 public int getRowCount()
1605 return pdbEntries.size();
1609 public int getColumnCount()
1611 return columns.length;
1615 public boolean isCellEditable(int row, int column)
1621 public Object getValueAt(int rowIndex, int columnIndex)
1623 Object value = "??";
1624 CachedPDB entry = pdbEntries.get(rowIndex);
1625 switch (columnIndex)
1628 value = entry.getSequence();
1631 value = entry.getQualifiedId();
1634 value = entry.getPdbEntry().getChainCode() == null ? "_"
1635 : entry.getPdbEntry().getChainCode();
1638 value = entry.getPdbEntry().getType();
1641 value = entry.getPdbEntry().getFile();
1648 public Class<?> getColumnClass(int columnIndex)
1650 return columnIndex == 0 ? SequenceI.class : PDBEntry.class;
1653 public CachedPDB getPDBEntryAt(int row)
1655 return pdbEntries.get(row);
1660 private class CachedPDB
1662 private SequenceI sequence;
1664 private PDBEntry pdbEntry;
1666 public CachedPDB(SequenceI sequence, PDBEntry pdbEntry)
1668 this.sequence = sequence;
1669 this.pdbEntry = pdbEntry;
1672 public String getQualifiedId()
1674 if (pdbEntry.hasProvider())
1676 return pdbEntry.getProvider() + ":" + pdbEntry.getId();
1678 return pdbEntry.toString();
1681 public SequenceI getSequence()
1686 public PDBEntry getPdbEntry()
1693 private IProgressIndicator progressBar;
1696 public void setProgressBar(String message, long id)
1698 if (!Platform.isHeadless() && progressBar != null)
1699 progressBar.setProgressBar(message, id);
1703 public void registerHandler(long id, IProgressIndicatorHandler handler)
1705 if (progressBar != null)
1706 progressBar.registerHandler(id, handler);
1710 public boolean operationInProgress()
1712 return progressBar == null ? false : progressBar.operationInProgress();
1715 public JalviewStructureDisplayI getOpenedStructureViewer()
1717 return sViewer == null ? null : sViewer.sview;
1721 protected void setFTSDocFieldPrefs(FTSDataColumnPreferences newPrefs)
1723 data.setDocFieldPrefs(newPrefs);
1729 * @return true when all initialisation threads have finished and dialog is
1732 public boolean isDialogVisible()
1734 return mainFrame != null && data != null && cmb_filterOption != null
1735 && mainFrame.isVisible()
1736 && cmb_filterOption.getSelectedItem() != null;
1741 * @return true if the 3D-Beacons query button will/has been displayed
1743 public boolean isCanQueryTDB()
1748 public boolean isNotQueriedTDBYet()
1750 return notQueriedTDBYet;
1754 * Open a single structure file for a given sequence
1756 public static void openStructureFileForSequence(
1757 StructureSelectionManager ssm, StructureChooser sc,
1758 AlignmentPanel ap, SequenceI seq, boolean prompt,
1759 String sFilename, TFType tft, String paeFilename,
1760 boolean doXferSettings)
1762 openStructureFileForSequence(ssm, sc, ap, seq, prompt, sFilename, tft,
1763 paeFilename, false, true, doXferSettings, null);
1766 public static StructureViewer openStructureFileForSequence(
1767 StructureSelectionManager ssm, StructureChooser sc,
1768 AlignmentPanel ap, SequenceI seq, boolean prompt,
1769 String sFilename, TFType tft, String paeFilename,
1770 boolean forceHeadless, boolean showRefAnnotations,
1771 boolean doXferSettings, ViewerType viewerType)
1773 StructureViewer sv = null;
1774 boolean headless = forceHeadless;
1779 sc = new StructureChooser(new SequenceI[] { seq }, seq, ap, false);
1783 ssm = ap.getStructureSelectionManager();
1786 PDBEntry fileEntry = new AssociatePdbFileWithSeq().associatePdbWithSeq(
1787 sFilename, DataSourceType.FILE, seq, prompt, Desktop.instance,
1788 tft, paeFilename, doXferSettings);
1790 // if headless, "false" in the sc constructor above will avoid GUI behaviour
1791 // in sc.launchStructureViewer()
1792 if (!headless && !(viewerType == null))
1794 sv = sc.launchStructureViewer(ssm, new PDBEntry[] { fileEntry }, ap,
1796 { seq }, viewerType);
1799 sc.mainFrame.dispose();
1801 if (showRefAnnotations)
1803 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();