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.Callable;
37 import java.util.concurrent.Executors;
39 import javax.swing.JCheckBox;
40 import javax.swing.JComboBox;
41 import javax.swing.JLabel;
42 import javax.swing.JMenuItem;
43 import javax.swing.JPopupMenu;
44 import javax.swing.JTable;
45 import javax.swing.SwingUtilities;
46 import javax.swing.table.AbstractTableModel;
48 import com.stevesoft.pat.Regex;
50 import jalview.analysis.AlignmentUtils;
51 import jalview.api.AlignmentViewPanel;
52 import jalview.api.structures.JalviewStructureDisplayI;
53 import jalview.bin.Cache;
54 import jalview.bin.Console;
55 import jalview.bin.Jalview;
56 import jalview.datamodel.AlignmentAnnotation;
57 import jalview.datamodel.AlignmentI;
58 import jalview.datamodel.PDBEntry;
59 import jalview.datamodel.SequenceGroup;
60 import jalview.datamodel.SequenceI;
61 import jalview.ext.jmol.JmolParser;
62 import jalview.fts.api.FTSData;
63 import jalview.fts.api.FTSDataColumnI;
64 import jalview.fts.api.FTSRestClientI;
65 import jalview.fts.core.FTSDataColumnPreferences;
66 import jalview.fts.core.FTSRestRequest;
67 import jalview.fts.core.FTSRestResponse;
68 import jalview.fts.service.pdb.PDBFTSRestClient;
69 import jalview.fts.service.threedbeacons.TDB_FTSData;
70 import jalview.gui.StructureViewer.ViewerType;
71 import jalview.gui.structurechooser.PDBStructureChooserQuerySource;
72 import jalview.gui.structurechooser.StructureChooserQuerySource;
73 import jalview.gui.structurechooser.ThreeDBStructureChooserQuerySource;
74 import jalview.io.DataSourceType;
75 import jalview.io.FileFormatException;
76 import jalview.io.JalviewFileChooser;
77 import jalview.io.JalviewFileView;
78 import jalview.jbgui.FilterOption;
79 import jalview.jbgui.GStructureChooser;
80 import jalview.structure.StructureImportSettings.TFType;
81 import jalview.structure.StructureMapping;
82 import jalview.structure.StructureSelectionManager;
83 import jalview.util.MessageManager;
84 import jalview.util.Platform;
85 import jalview.util.StringUtils;
86 import jalview.ws.DBRefFetcher;
87 import jalview.ws.DBRefFetcher.FetchFinishedListenerI;
88 import jalview.ws.datamodel.alphafold.PAEContactMatrix;
89 import jalview.ws.dbsources.EBIAlfaFold;
90 import jalview.ws.seqfetcher.DbSourceProxy;
91 import jalview.ws.sifts.SiftsSettings;
94 * Provides the behaviors for the Structure chooser Panel
99 @SuppressWarnings("serial")
100 public class StructureChooser extends GStructureChooser
101 implements IProgressIndicator
103 private static final String AUTOSUPERIMPOSE = "AUTOSUPERIMPOSE";
106 * warn user if need to fetch more than this many uniprot records at once
108 private static final int THRESHOLD_WARN_UNIPROT_FETCH_NEEDED = 20;
110 private SequenceI selectedSequence;
112 private SequenceI[] selectedSequences;
114 private IProgressIndicator progressIndicator;
116 private Collection<FTSData> discoveredStructuresSet;
118 private StructureChooserQuerySource data;
121 protected FTSDataColumnPreferences getFTSDocFieldPrefs()
123 return data.getDocFieldPrefs();
126 private String selectedPdbFileName;
128 private TFType localPdbTempfacType;
130 private String localPdbPaeMatrixFileName;
132 private boolean isValidPBDEntry;
134 private boolean cachedPDBExists;
136 private Collection<FTSData> lastDiscoveredStructuresSet;
138 private boolean canQueryTDB = false;
140 private boolean notQueriedTDBYet = true;
142 List<SequenceI> seqsWithoutSourceDBRef = null;
144 private boolean showChooserGUI = true;
146 private static StructureViewer lastTargetedView = null;
148 public StructureChooser(SequenceI[] selectedSeqs, SequenceI selectedSeq,
151 this(selectedSeqs, selectedSeq, ap, true);
154 public StructureChooser(SequenceI[] selectedSeqs, SequenceI selectedSeq,
155 AlignmentPanel ap, boolean showGUI)
157 // which FTS engine to use
158 data = StructureChooserQuerySource.getQuerySourceFor(selectedSeqs);
162 this.selectedSequence = selectedSeq;
163 this.selectedSequences = selectedSeqs;
164 this.progressIndicator = (ap == null) ? null : ap.alignFrame;
165 this.showChooserGUI = showGUI;
171 * sets canQueryTDB if protein sequences without a canonical uniprot ref or at
172 * least one structure are discovered.
174 private void populateSeqsWithoutSourceDBRef()
176 seqsWithoutSourceDBRef = new ArrayList<SequenceI>();
177 boolean needCanonical = false;
178 for (SequenceI seq : selectedSequences)
182 int dbRef = ThreeDBStructureChooserQuerySource
183 .checkUniprotRefs(seq.getDBRefs());
188 // need to retrieve canonicals
189 needCanonical = true;
190 seqsWithoutSourceDBRef.add(seq);
194 // could be a sequence with pdb ref
195 if (seq.getAllPDBEntries() == null
196 || seq.getAllPDBEntries().size() == 0)
198 seqsWithoutSourceDBRef.add(seq);
204 // retrieve database refs for protein sequences
205 if (!seqsWithoutSourceDBRef.isEmpty())
210 // triggers display of the 'Query TDB' button
211 notQueriedTDBYet = true;
217 * Initializes parameters used by the Structure Chooser Panel
219 protected void init()
221 if (!Jalview.isHeadlessMode())
223 progressBar = new ProgressBar(this.statusPanel, this.statusBar);
226 chk_superpose.setSelected(Cache.getDefault(AUTOSUPERIMPOSE, true));
227 btn_queryTDB.addActionListener(new ActionListener()
231 public void actionPerformed(ActionEvent e)
233 promptForTDBFetch(false);
237 Executors.defaultThreadFactory().newThread(new Runnable()
242 populateSeqsWithoutSourceDBRef();
243 initialStructureDiscovery();
251 private void initialStructureDiscovery()
253 // check which FTS engine to use
254 data = StructureChooserQuerySource.getQuerySourceFor(selectedSequences);
256 // ensure a filter option is in force for search
257 populateFilterComboBox(true, cachedPDBExists);
259 // looks for any existing structures already loaded
260 // for the sequences (the cached ones)
261 // then queries the StructureChooserQuerySource to
262 // discover more structures.
264 // Possible optimisation is to only begin querying
265 // the structure chooser if there are no cached structures.
267 long startTime = System.currentTimeMillis();
268 updateProgressIndicator(
269 MessageManager.getString("status.loading_cached_pdb_entries"),
271 loadLocalCachedPDBEntries();
272 updateProgressIndicator(null, startTime);
273 updateProgressIndicator(
274 MessageManager.getString("status.searching_for_pdb_structures"),
276 fetchStructuresMetaData();
277 // revise filter options if no results were found
278 populateFilterComboBox(isStructuresDiscovered(), cachedPDBExists);
279 discoverStructureViews();
280 updateProgressIndicator(null, startTime);
281 mainFrame.setVisible(showChooserGUI);
286 * raises dialog for Uniprot fetch followed by 3D beacons search
289 * - when true, don't ask, just fetch
291 public void promptForTDBFetch(boolean ignoreGui)
293 final long progressId = System.currentTimeMillis();
295 // final action after prompting and discovering db refs
296 final Runnable strucDiscovery = new Runnable()
301 mainFrame.setEnabled(false);
302 cmb_filterOption.setEnabled(false);
303 progressBar.setProgressBar(
304 MessageManager.getString("status.searching_3d_beacons"),
306 btn_queryTDB.setEnabled(false);
307 // TODO: warn if no accessions discovered
308 populateSeqsWithoutSourceDBRef();
309 // redo initial discovery - this time with 3d beacons
311 previousWantedFields = null;
312 lastSelected = (FilterOption) cmb_filterOption.getSelectedItem();
313 cmb_filterOption.setSelectedItem(null);
314 cachedPDBExists = false; // reset to initial
315 initialStructureDiscovery();
316 if (!isStructuresDiscovered())
318 progressBar.setProgressBar(MessageManager.getString(
319 "status.no_structures_discovered_from_3d_beacons"),
321 btn_queryTDB.setToolTipText(MessageManager.getString(
322 "status.no_structures_discovered_from_3d_beacons"));
323 btn_queryTDB.setEnabled(false);
324 pnl_queryTDB.setVisible(false);
328 cmb_filterOption.setSelectedIndex(0); // select 'best'
329 btn_queryTDB.setVisible(false);
330 pnl_queryTDB.setVisible(false);
331 progressBar.setProgressBar(null, progressId);
333 mainFrame.setEnabled(true);
334 cmb_filterOption.setEnabled(true);
338 final FetchFinishedListenerI afterDbRefFetch = new FetchFinishedListenerI()
342 public void finished()
344 // filter has been selected, so we set flag to remove ourselves
345 notQueriedTDBYet = false;
346 // new thread to discover structures - via 3d beacons
347 Executors.defaultThreadFactory().newThread(strucDiscovery).start();
352 // fetch db refs if OK pressed
353 final Callable discoverCanonicalDBrefs = () -> {
354 btn_queryTDB.setEnabled(false);
355 populateSeqsWithoutSourceDBRef();
357 final int y = seqsWithoutSourceDBRef.size();
360 final SequenceI[] seqWithoutSrcDBRef = seqsWithoutSourceDBRef
361 .toArray(new SequenceI[y]);
362 DBRefFetcher dbRefFetcher = new DBRefFetcher(seqWithoutSrcDBRef,
363 progressBar, new DbSourceProxy[]
364 { new jalview.ws.dbsources.Uniprot() }, null, false);
365 dbRefFetcher.addListener(afterDbRefFetch);
366 // ideally this would also gracefully run with callbacks
368 dbRefFetcher.fetchDBRefs(true);
372 // call finished action directly
373 afterDbRefFetch.finished();
377 final Callable revertview = () -> {
378 if (lastSelected != null)
380 cmb_filterOption.setSelectedItem(lastSelected);
384 int threshold = Cache.getDefault("UNIPROT_AUTOFETCH_THRESHOLD",
385 THRESHOLD_WARN_UNIPROT_FETCH_NEEDED);
386 Console.debug("Using Uniprot fetch threshold of " + threshold);
387 if (ignoreGui || seqsWithoutSourceDBRef.size() < threshold)
389 Executors.newSingleThreadExecutor().submit(discoverCanonicalDBrefs);
392 // need cancel and no to result in the discoverPDB action - mocked is
393 // 'cancel' TODO: mock should be OK
395 StructureChooser thisSC = this;
396 JvOptionPane.newOptionDialog(thisSC.getFrame())
397 .setResponseHandler(JvOptionPane.OK_OPTION,
398 discoverCanonicalDBrefs)
399 .setResponseHandler(JvOptionPane.CANCEL_OPTION, revertview)
400 .setResponseHandler(JvOptionPane.NO_OPTION, revertview)
402 MessageManager.formatMessage(
403 "label.fetch_references_for_3dbeacons",
404 seqsWithoutSourceDBRef.size()),
405 MessageManager.getString("label.3dbeacons"),
406 JvOptionPane.YES_NO_OPTION, JvOptionPane.PLAIN_MESSAGE,
408 { MessageManager.getString("action.ok"),
409 MessageManager.getString("action.cancel") },
410 MessageManager.getString("action.ok"), false);
414 * Builds a drop-down choice list of existing structure viewers to which new
415 * structures may be added. If this list is empty then it, and the 'Add'
416 * button, are hidden.
418 private void discoverStructureViews()
420 if (Desktop.instance != null)
422 targetView.removeAllItems();
423 if (lastTargetedView != null && !lastTargetedView.isVisible())
425 lastTargetedView = null;
427 int linkedViewsAt = 0;
428 for (StructureViewerBase view : Desktop.instance
429 .getStructureViewers(null, null))
431 StructureViewer viewHandler = (lastTargetedView != null
432 && lastTargetedView.sview == view) ? lastTargetedView
433 : StructureViewer.reconfigure(view);
435 if (view.isLinkedWith(ap))
437 targetView.insertItemAt(viewHandler, linkedViewsAt++);
441 targetView.addItem(viewHandler);
446 * show option to Add to viewer if at least 1 viewer found
448 targetView.setVisible(false);
449 if (targetView.getItemCount() > 0)
451 targetView.setVisible(true);
452 if (lastTargetedView != null)
454 targetView.setSelectedItem(lastTargetedView);
458 targetView.setSelectedIndex(0);
461 btn_add.setVisible(targetView.isVisible());
466 * Updates the progress indicator with the specified message
469 * displayed message for the operation
471 * unique handle for this indicator
473 protected void updateProgressIndicator(String message, long id)
475 if (progressIndicator != null)
477 progressIndicator.setProgressBar(message, id);
482 * Retrieve meta-data for all the structure(s) for a given sequence(s) in a
485 void fetchStructuresMetaData()
487 long startTime = System.currentTimeMillis();
488 Collection<FTSDataColumnI> wantedFields = data.getDocFieldPrefs()
489 .getStructureSummaryFields();
491 discoveredStructuresSet = new LinkedHashSet<>();
492 HashSet<String> errors = new HashSet<>();
494 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
497 for (SequenceI seq : selectedSequences)
500 FTSRestResponse resultList;
503 resultList = data.fetchStructuresMetaData(seq, wantedFields,
504 selectedFilterOpt, !chk_invertFilter.isSelected());
505 // null response means the FTSengine didn't yield a query for this
506 // consider designing a special exception if we really wanted to be
508 if (resultList == null)
512 } catch (Exception e)
515 errors.add(e.getMessage());
518 if (resultList.getSearchSummary() != null
519 && !resultList.getSearchSummary().isEmpty())
521 discoveredStructuresSet.addAll(resultList.getSearchSummary());
525 int noOfStructuresFound = 0;
526 String totalTime = (System.currentTimeMillis() - startTime)
528 if (discoveredStructuresSet != null
529 && !discoveredStructuresSet.isEmpty())
532 .setModel(data.getTableModel(discoveredStructuresSet));
534 noOfStructuresFound = discoveredStructuresSet.size();
535 lastDiscoveredStructuresSet = discoveredStructuresSet;
536 mainFrame.setTitle(MessageManager.formatMessage(
537 "label.structure_chooser_no_of_structures",
538 noOfStructuresFound, totalTime));
542 mainFrame.setTitle(MessageManager
543 .getString("label.structure_chooser_manual_association"));
544 if (errors.size() > 0)
546 StringBuilder errorMsg = new StringBuilder();
547 for (String error : errors)
549 errorMsg.append(error).append("\n");
551 JvOptionPane.showMessageDialog(this, errorMsg.toString(),
552 MessageManager.getString("label.pdb_web-service_error"),
553 JvOptionPane.ERROR_MESSAGE);
558 protected void loadLocalCachedPDBEntries()
560 ArrayList<CachedPDB> entries = new ArrayList<>();
561 for (SequenceI seq : selectedSequences)
563 if (seq.getDatasetSequence() != null
564 && seq.getDatasetSequence().getAllPDBEntries() != null)
566 for (PDBEntry pdbEntry : seq.getDatasetSequence()
569 if (pdbEntry.getFile() != null)
571 entries.add(new CachedPDB(seq, pdbEntry));
576 cachedPDBExists = !entries.isEmpty();
577 PDBEntryTableModel tableModelx = new PDBEntryTableModel(entries);
578 tbl_local_pdb.setModel(tableModelx);
582 * Filters a given list of discovered structures based on supplied argument
584 * @param fieldToFilterBy
585 * the field to filter by
587 void filterResultSet(final String fieldToFilterBy)
589 Thread filterThread = new Thread(new Runnable()
595 long startTime = System.currentTimeMillis();
596 lbl_loading.setVisible(true);
597 Collection<FTSDataColumnI> wantedFields = data.getDocFieldPrefs()
598 .getStructureSummaryFields();
599 Collection<FTSData> filteredResponse = new HashSet<>();
600 HashSet<String> errors = new HashSet<>();
602 for (SequenceI seq : selectedSequences)
605 FTSRestResponse resultList;
608 resultList = data.selectFirstRankedQuery(seq,
609 discoveredStructuresSet, wantedFields, fieldToFilterBy,
610 !chk_invertFilter.isSelected());
612 } catch (Exception e)
615 errors.add(e.getMessage());
618 if (resultList.getSearchSummary() != null
619 && !resultList.getSearchSummary().isEmpty())
621 filteredResponse.addAll(resultList.getSearchSummary());
625 String totalTime = (System.currentTimeMillis() - startTime)
627 if (!filteredResponse.isEmpty())
629 final int filterResponseCount = filteredResponse.size();
630 Collection<FTSData> reorderedStructuresSet = new LinkedHashSet<>();
631 reorderedStructuresSet.addAll(filteredResponse);
632 reorderedStructuresSet.addAll(discoveredStructuresSet);
634 .setModel(data.getTableModel(reorderedStructuresSet));
636 FTSRestResponse.configureTableColumn(getResultTable(),
637 wantedFields, tempUserPrefs);
638 getResultTable().getColumn("Ref Sequence").setPreferredWidth(120);
639 getResultTable().getColumn("Ref Sequence").setMinWidth(100);
640 getResultTable().getColumn("Ref Sequence").setMaxWidth(200);
641 // Update table selection model here
642 getResultTable().addRowSelectionInterval(0,
643 filterResponseCount - 1);
644 mainFrame.setTitle(MessageManager.formatMessage(
645 "label.structure_chooser_filter_time", totalTime));
649 mainFrame.setTitle(MessageManager.formatMessage(
650 "label.structure_chooser_filter_time", totalTime));
651 if (errors.size() > 0)
653 StringBuilder errorMsg = new StringBuilder();
654 for (String error : errors)
656 errorMsg.append(error).append("\n");
658 JvOptionPane.showMessageDialog(null, errorMsg.toString(),
659 MessageManager.getString("label.pdb_web-service_error"),
660 JvOptionPane.ERROR_MESSAGE);
664 lbl_loading.setVisible(false);
666 validateSelections();
669 filterThread.start();
673 * Handles action event for btn_pdbFromFile
676 protected void pdbFromFile_actionPerformed()
678 // TODO: JAL-3048 not needed for Jalview-JS until JSmol dep and
681 JalviewFileChooser chooser = new JalviewFileChooser(
682 Cache.getProperty("LAST_DIRECTORY"));
683 chooser.setFileView(new JalviewFileView());
684 chooser.setDialogTitle(
685 MessageManager.formatMessage("label.select_pdb_file_for",
686 selectedSequence.getDisplayId(false)));
687 chooser.setToolTipText(MessageManager.formatMessage(
688 "label.load_pdb_file_associate_with_sequence",
689 selectedSequence.getDisplayId(false)));
691 int value = chooser.showOpenDialog(null);
692 if (value == JalviewFileChooser.APPROVE_OPTION)
694 selectedPdbFileName = chooser.getSelectedFile().getPath();
695 Cache.setProperty("LAST_DIRECTORY", selectedPdbFileName);
696 boolean guessTFType = localPdbPaeMatrixFileName == null;
697 localPdbPaeMatrixFileName = guessPAEFilename();
698 guessTFType |= localPdbPaeMatrixFileName != null;
699 Regex alphaFold = JmolParser.getNewAlphafoldValidator();
701 && alphaFold.search(new File(selectedPdbFileName).getName())
702 && !tempFacAsChanged)
704 // localPdbPaeMatrixFileName was null and now isn't and filename could
705 // well be AlphaFold and user hasn't adjusted the tempFacType
706 combo_tempFacAs.setSelectedItem(TFType.PLDDT);
708 validateSelections();
713 * Handles action event for btn_paeMatrixFile
716 protected void paeMatrixFile_actionPerformed()
718 File pdbFile = new File(selectedPdbFileName);
719 String setFile = Cache.getProperty("LAST_DIRECTORY");
720 if (localPdbPaeMatrixFileName != null)
722 File paeFile = new File(localPdbPaeMatrixFileName);
723 if (paeFile.exists())
724 setFile = paeFile.getAbsolutePath();
725 else if (paeFile.getParentFile().exists())
726 setFile = paeFile.getParentFile().getAbsolutePath();
730 String guess = guessPAEFilename();
734 JalviewFileChooser chooser = new JalviewFileChooser(setFile);
735 chooser.setFileView(new JalviewFileView());
736 chooser.setDialogTitle(MessageManager.formatMessage(
737 "label.select_pae_matrix_file_for", pdbFile.getName()));
738 chooser.setToolTipText(MessageManager.formatMessage(
739 "label.load_pae_matrix_file_associate_with_structure",
742 // TODO convert to Callable/Promise
743 int value = chooser.showOpenDialog(null);
744 if (value == JalviewFileChooser.APPROVE_OPTION)
746 String fileName = chooser.getSelectedFile().getPath();
749 PAEContactMatrix.validateContactMatrixFile(fileName);
750 } catch (Exception thr)
752 JvOptionPane.showInternalMessageDialog(this, MessageManager
753 .formatMessage("label.couldnt_load_file", new Object[]
754 { fileName }) + "<br>" + thr.getLocalizedMessage(),
755 MessageManager.getString("label.error_loading_file"),
756 JvOptionPane.WARNING_MESSAGE);
757 Console.error("Couldn't import " + fileName + " as a PAE matrix",
761 localPdbPaeMatrixFileName = fileName;
762 Cache.setProperty("LAST_DIRECTORY", localPdbPaeMatrixFileName);
764 validateAssociationFromFile();
767 private String guessPAEFilename()
769 if (selectedPdbFileName.toLowerCase(Locale.ROOT).endsWith(".pdb")
770 || selectedPdbFileName.toLowerCase(Locale.ROOT)
773 String jsonExt = selectedPdbFileName.substring(0,
774 selectedPdbFileName.length() - 4) + ".json";
775 // AlphaFold naming scheme
776 String guessFile1 = StringUtils.replaceLast(jsonExt, "model",
777 "predicted_aligned_error");
778 // nf-core mode naming scheme
779 String guessFile2 = StringUtils.replaceLast(jsonExt, ".json",
781 if (new File(guessFile1).exists())
785 else if (new File(jsonExt).exists())
789 else if (new File(guessFile2).exists())
798 * Populates the filter combo-box options dynamically depending on discovered
801 protected void populateFilterComboBox(boolean haveData,
802 boolean cachedPDBExist)
804 populateFilterComboBox(haveData, cachedPDBExist, null);
808 * Populates the filter combo-box options dynamically depending on discovered
811 protected void populateFilterComboBox(boolean haveData,
812 boolean cachedPDBExist, FilterOption lastSel)
816 * temporarily suspend the change listener behaviour
818 cmb_filterOption.removeItemListener(this);
820 cmb_filterOption.removeAllItems();
823 List<FilterOption> filters = data
824 .getAvailableFilterOptions(VIEWS_FILTER);
825 data.updateAvailableFilterOptions(VIEWS_FILTER, filters,
826 lastDiscoveredStructuresSet);
828 for (FilterOption filter : filters)
830 if (lastSel != null && filter.equals(lastSel))
835 cmb_filterOption.addItem(filter);
839 cmb_filterOption.addItem(
840 new FilterOption(MessageManager.getString("label.enter_pdb_id"),
841 "-", VIEWS_ENTER_ID, false, null));
842 cmb_filterOption.addItem(
843 new FilterOption(MessageManager.getString("label.from_file"),
844 "-", VIEWS_FROM_FILE, false, null));
845 if (canQueryTDB && notQueriedTDBYet)
847 btn_queryTDB.setVisible(true);
848 pnl_queryTDB.setVisible(true);
853 FilterOption cachedOption = new FilterOption(
854 MessageManager.getString("label.cached_structures"), "-",
855 VIEWS_LOCAL_PDB, false, null);
856 cmb_filterOption.addItem(cachedOption);
859 cmb_filterOption.setSelectedItem(cachedOption);
864 cmb_filterOption.setSelectedIndex(selSet);
866 cmb_filterOption.addItemListener(this);
870 * Updates the displayed view based on the selected filter option
872 protected void updateCurrentView()
874 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
877 if (lastSelected == selectedFilterOpt)
879 // don't need to do anything, probably
882 // otherwise, record selection
883 // and update the layout and dialog accordingly
884 lastSelected = selectedFilterOpt;
886 layout_switchableViews.show(pnl_switchableViews,
887 selectedFilterOpt.getView());
888 String filterTitle = mainFrame.getTitle();
889 mainFrame.setTitle(frameTitle);
890 chk_invertFilter.setVisible(false);
892 if (selectedFilterOpt.getView() == VIEWS_FILTER)
894 mainFrame.setTitle(filterTitle);
895 // TDB Query has no invert as yet
896 chk_invertFilter.setVisible(selectedFilterOpt
897 .getQuerySource() instanceof PDBStructureChooserQuerySource);
899 if (data != selectedFilterOpt.getQuerySource()
900 || data.needsRefetch(selectedFilterOpt))
902 data = selectedFilterOpt.getQuerySource();
903 // rebuild the views completely, since prefs will also change
909 filterResultSet(selectedFilterOpt.getValue());
912 else if (selectedFilterOpt.getView() == VIEWS_ENTER_ID
913 || selectedFilterOpt.getView() == VIEWS_FROM_FILE)
915 mainFrame.setTitle(MessageManager
916 .getString("label.structure_chooser_manual_association"));
917 idInputAssSeqPanel.loadCmbAssSeq();
918 fileChooserAssSeqPanel.loadCmbAssSeq();
920 validateSelections();
924 * Validates user selection and enables the 'Add' and 'New View' buttons if
925 * all parameters are correct (the Add button will only be visible if there is
926 * at least one existing structure viewer open). This basically means at least
927 * one structure selected and no error messages.
929 * The 'Superpose Structures' option is enabled if either more than one
930 * structure is selected, or the 'Add' to existing view option is enabled, and
931 * disabled if the only option is to open a new view of a single structure.
934 protected void validateSelections()
936 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
938 btn_add.setEnabled(false);
939 String currentView = selectedFilterOpt.getView();
940 int selectedCount = 0;
941 if (currentView == VIEWS_FILTER)
943 selectedCount = getResultTable().getSelectedRows().length;
944 if (selectedCount > 0)
946 btn_add.setEnabled(true);
949 else if (currentView == VIEWS_LOCAL_PDB)
951 selectedCount = tbl_local_pdb.getSelectedRows().length;
952 if (selectedCount > 0)
954 btn_add.setEnabled(true);
957 else if (currentView == VIEWS_ENTER_ID)
959 validateAssociationEnterPdb();
961 else if (currentView == VIEWS_FROM_FILE)
963 validateAssociationFromFile();
966 btn_newView.setEnabled(btn_add.isEnabled());
969 * enable 'Superpose' option if more than one structure is selected,
970 * or there are view(s) available to add structure(s) to
973 .setEnabled(selectedCount > 1 || targetView.getItemCount() > 0);
977 protected boolean showPopupFor(int selectedRow, int x, int y)
979 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
981 String currentView = selectedFilterOpt.getView();
983 if (currentView == VIEWS_FILTER
984 && data instanceof ThreeDBStructureChooserQuerySource)
987 TDB_FTSData row = ((ThreeDBStructureChooserQuerySource) data)
988 .getFTSDataFor(getResultTable(), selectedRow,
989 discoveredStructuresSet);
990 String pageUrl = row.getModelViewUrl();
991 JPopupMenu popup = new JPopupMenu("3D Beacons");
992 JMenuItem viewUrl = new JMenuItem("View model web page");
993 viewUrl.addActionListener(new ActionListener()
996 public void actionPerformed(ActionEvent e)
998 Desktop.showUrl(pageUrl);
1002 SwingUtilities.invokeLater(new Runnable()
1007 popup.show(getResultTable(), x, y);
1012 // event not handled by us
1017 * Validates inputs from the Manual PDB entry panel
1019 protected void validateAssociationEnterPdb()
1021 AssociateSeqOptions assSeqOpt = (AssociateSeqOptions) idInputAssSeqPanel
1022 .getCmb_assSeq().getSelectedItem();
1023 lbl_pdbManualFetchStatus.setIcon(errorImage);
1024 lbl_pdbManualFetchStatus.setToolTipText("");
1025 if (txt_search.getText().length() > 0)
1027 lbl_pdbManualFetchStatus.setToolTipText(JvSwingUtils.wrapTooltip(true,
1028 MessageManager.formatMessage("info.no_pdb_entry_found_for",
1029 txt_search.getText())));
1032 if (errorWarning.length() > 0)
1034 lbl_pdbManualFetchStatus.setIcon(warningImage);
1035 lbl_pdbManualFetchStatus.setToolTipText(
1036 JvSwingUtils.wrapTooltip(true, errorWarning.toString()));
1039 if (selectedSequences.length == 1 || !assSeqOpt.getName()
1040 .equalsIgnoreCase("-Select Associated Seq-"))
1042 txt_search.setEnabled(true);
1043 if (isValidPBDEntry)
1045 btn_add.setEnabled(true);
1046 lbl_pdbManualFetchStatus.setToolTipText("");
1047 lbl_pdbManualFetchStatus.setIcon(goodImage);
1052 txt_search.setEnabled(false);
1053 lbl_pdbManualFetchStatus.setIcon(errorImage);
1058 * Validates inputs for the manual PDB file selection options
1060 protected void validateAssociationFromFile()
1062 AssociateSeqOptions assSeqOpt = (AssociateSeqOptions) fileChooserAssSeqPanel
1063 .getCmb_assSeq().getSelectedItem();
1064 // lbl_fromFileStatus.setIcon(errorImage);
1065 String pdbFileString = "";
1066 String pdbFileTooltip = "";
1067 if (selectedSequences.length == 1 || (assSeqOpt != null && !assSeqOpt
1068 .getName().equalsIgnoreCase("-Select Associated Seq-")))
1070 btn_pdbFromFile.setEnabled(true);
1071 if (selectedPdbFileName != null && selectedPdbFileName.length() > 0)
1073 btn_add.setEnabled(true);
1074 // lbl_fromFileStatus.setIcon(goodImage);
1075 pdbFileString = new File(selectedPdbFileName).getName();
1076 pdbFileTooltip = new File(selectedPdbFileName).getAbsolutePath();
1077 setPdbOptionsEnabled(true);
1081 pdbFileString = MessageManager.getString("label.none");
1082 pdbFileTooltip = MessageManager.getString("label.nothing_selected");
1083 setPdbOptionsEnabled(false);
1088 btn_pdbFromFile.setEnabled(false);
1089 setPdbOptionsEnabled(false);
1090 // lbl_fromFileStatus.setIcon(errorImage);
1091 pdbFileString = MessageManager.getString("label.none");
1092 pdbFileTooltip = MessageManager.getString("label.nothing_selected");
1094 lbl_pdbFile.setText(pdbFileString);
1095 lbl_pdbFile.setToolTipText(pdbFileTooltip);
1098 String paeFileString = "";
1099 String paeFileTooltip = "";
1100 if (localPdbPaeMatrixFileName != null
1101 && localPdbPaeMatrixFileName.length() > 0)
1103 paeFileString = new File(localPdbPaeMatrixFileName).getName();
1104 paeFileTooltip = new File(localPdbPaeMatrixFileName)
1109 paeFileString = MessageManager.getString("label.none");
1110 paeFileTooltip = MessageManager.getString("label.nothing_selected");
1112 lbl_paeFile.setText(paeFileString);
1113 lbl_paeFile.setToolTipText(paeFileTooltip);
1117 protected void cmbAssSeqStateChanged()
1119 validateSelections();
1122 private FilterOption lastSelected = null;
1125 * Handles the state change event for the 'filter' combo-box and 'invert'
1129 protected void stateChanged(ItemEvent e)
1131 if (e.getSource() instanceof JCheckBox)
1133 updateCurrentView();
1137 if (e.getStateChange() == ItemEvent.SELECTED)
1139 updateCurrentView();
1146 * select structures for viewing by their PDB IDs
1149 * @return true if structures were found and marked as selected
1151 public boolean selectStructure(String... pdbids)
1153 boolean found = false;
1155 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
1156 .getSelectedItem());
1157 String currentView = selectedFilterOpt.getView();
1158 JTable restable = (currentView == VIEWS_FILTER) ? getResultTable()
1159 : (currentView == VIEWS_LOCAL_PDB) ? tbl_local_pdb : null;
1161 if (restable == null)
1163 // can't select (enter PDB ID, or load file - need to also select which
1164 // sequence to associate with)
1168 int pdbIdColIndex = restable.getColumn("PDB Id").getModelIndex();
1169 for (int r = 0; r < restable.getRowCount(); r++)
1171 for (int p = 0; p < pdbids.length; p++)
1173 if (String.valueOf(restable.getValueAt(r, pdbIdColIndex))
1174 .equalsIgnoreCase(pdbids[p]))
1176 restable.setRowSelectionInterval(r, r);
1185 * Handles the 'New View' action
1188 protected void newView_ActionPerformed()
1190 targetView.setSelectedItem(null);
1191 showStructures(false);
1195 * Handles the 'Add to existing viewer' action
1198 protected void add_ActionPerformed()
1200 showStructures(false);
1204 * structure viewer opened by this dialog, or null
1206 private StructureViewer sViewer = null;
1208 public void showStructures(boolean waitUntilFinished)
1211 final StructureSelectionManager ssm = ap.getStructureSelectionManager();
1213 final int preferredHeight = pnl_filter.getHeight();
1214 btn_add.setEnabled(false);
1215 btn_newView.setEnabled(false);
1216 btn_cancel.setEnabled(false);
1217 actionsPanel.setEnabled(false);
1219 final String progress = MessageManager
1220 .getString("label.working_ellipsis");
1221 setProgressBar(progress, progress.hashCode());
1222 Runnable viewStruc = new Runnable()
1227 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
1228 .getSelectedItem());
1229 String currentView = selectedFilterOpt.getView();
1230 JTable restable = (currentView == VIEWS_FILTER) ? getResultTable()
1233 if (currentView == VIEWS_FILTER)
1235 int[] selectedRows = restable.getSelectedRows();
1236 PDBEntry[] pdbEntriesToView = new PDBEntry[selectedRows.length];
1237 List<SequenceI> selectedSeqsToView = new ArrayList<>();
1238 pdbEntriesToView = data.collectSelectedRows(restable,
1239 selectedRows, selectedSeqsToView);
1241 SequenceI[] selectedSeqs = selectedSeqsToView
1242 .toArray(new SequenceI[selectedSeqsToView.size()]);
1243 sViewer = launchStructureViewer(ssm, pdbEntriesToView, ap,
1246 else if (currentView == VIEWS_LOCAL_PDB)
1248 int[] selectedRows = tbl_local_pdb.getSelectedRows();
1249 PDBEntry[] pdbEntriesToView = new PDBEntry[selectedRows.length];
1251 int pdbIdColIndex = tbl_local_pdb.getColumn("PDB Id")
1253 int refSeqColIndex = tbl_local_pdb.getColumn("Ref Sequence")
1255 List<SequenceI> selectedSeqsToView = new ArrayList<>();
1256 for (int row : selectedRows)
1258 PDBEntry pdbEntry = ((PDBEntryTableModel) tbl_local_pdb
1259 .getModel()).getPDBEntryAt(row).getPdbEntry();
1261 pdbEntriesToView[count++] = pdbEntry;
1262 SequenceI selectedSeq = (SequenceI) tbl_local_pdb
1263 .getValueAt(row, refSeqColIndex);
1264 selectedSeqsToView.add(selectedSeq);
1266 SequenceI[] selectedSeqs = selectedSeqsToView
1267 .toArray(new SequenceI[selectedSeqsToView.size()]);
1268 sViewer = launchStructureViewer(ssm, pdbEntriesToView, ap,
1271 else if (currentView == VIEWS_ENTER_ID)
1273 SequenceI userSelectedSeq = ((AssociateSeqOptions) idInputAssSeqPanel
1274 .getCmb_assSeq().getSelectedItem()).getSequence();
1275 if (userSelectedSeq != null)
1277 selectedSequence = userSelectedSeq;
1279 String pdbIdStr = txt_search.getText();
1280 PDBEntry pdbEntry = selectedSequence.getPDBEntry(pdbIdStr);
1281 if (pdbEntry == null)
1283 pdbEntry = new PDBEntry();
1284 if (pdbIdStr.split(":").length > 1)
1286 pdbEntry.setId(pdbIdStr.split(":")[0]);
1287 pdbEntry.setChainCode(
1288 pdbIdStr.split(":")[1].toUpperCase(Locale.ROOT));
1292 pdbEntry.setId(pdbIdStr);
1294 pdbEntry.setType(PDBEntry.Type.PDB);
1295 selectedSequence.getDatasetSequence().addPDBId(pdbEntry);
1298 PDBEntry[] pdbEntriesToView = new PDBEntry[] { pdbEntry };
1299 sViewer = launchStructureViewer(ssm, pdbEntriesToView, ap,
1301 { selectedSequence });
1303 else if (currentView == VIEWS_FROM_FILE)
1305 StructureChooser sc = StructureChooser.this;
1306 TFType tft = (TFType) sc.combo_tempFacAs.getSelectedItem();
1307 String paeFilename = sc.localPdbPaeMatrixFileName;
1308 AssociateSeqOptions assSeqOpt = (AssociateSeqOptions) fileChooserAssSeqPanel
1309 .getCmb_assSeq().getSelectedItem();
1310 SequenceI userSelectedSeq = assSeqOpt.getSequence();
1311 if (userSelectedSeq != null)
1313 selectedSequence = userSelectedSeq;
1315 String pdbFilename = selectedPdbFileName;
1317 StructureChooser.openStructureFileForSequence(ssm, sc, ap,
1318 selectedSequence, true, pdbFilename, tft, paeFilename,
1321 SwingUtilities.invokeLater(new Runnable()
1326 setProgressBar("Complete.", progress.hashCode());
1327 closeAction(preferredHeight);
1328 mainFrame.dispose();
1333 Thread runner = new Thread(viewStruc);
1335 if (waitUntilFinished)
1337 while (sViewer == null ? runner.isAlive()
1338 : (sViewer.sview == null ? true
1339 : !sViewer.sview.hasMapping()))
1344 } catch (InterruptedException ie)
1353 * Answers a structure viewer (new or existing) configured to superimpose
1354 * added structures or not according to the user's choice
1359 StructureViewer getTargetedStructureViewer(StructureSelectionManager ssm)
1361 Object sv = targetView.getSelectedItem();
1363 return sv == null ? new StructureViewer(ssm) : (StructureViewer) sv;
1367 * Adds PDB structures to a new or existing structure viewer
1370 * @param pdbEntriesToView
1375 private StructureViewer launchStructureViewer(
1376 StructureSelectionManager ssm, final PDBEntry[] pdbEntriesToView,
1377 final AlignmentPanel alignPanel, SequenceI[] sequences)
1379 return launchStructureViewer(ssm, pdbEntriesToView, alignPanel,
1383 private StructureViewer launchStructureViewer(
1384 StructureSelectionManager ssm, final PDBEntry[] pdbEntriesToView,
1385 final AlignmentPanel alignPanel, SequenceI[] sequences,
1386 ViewerType viewerType)
1388 long progressId = sequences.hashCode();
1389 setProgressBar(MessageManager
1390 .getString("status.launching_3d_structure_viewer"), progressId);
1391 final StructureViewer theViewer = getTargetedStructureViewer(ssm);
1392 boolean superimpose = chk_superpose.isSelected();
1393 theViewer.setSuperpose(superimpose);
1396 * remember user's choice of superimpose or not
1398 Cache.setProperty(AUTOSUPERIMPOSE,
1399 Boolean.valueOf(superimpose).toString());
1401 setProgressBar(null, progressId);
1402 if (SiftsSettings.isMapWithSifts())
1404 List<SequenceI> seqsWithoutSourceDBRef = new ArrayList<>();
1406 // TODO: skip PDBEntry:Sequence pairs where PDBEntry doesn't look like a
1407 // real PDB ID. For moment, we can also safely do this if there is already
1408 // a known mapping between the PDBEntry and the sequence.
1409 for (SequenceI seq : sequences)
1411 PDBEntry pdbe = pdbEntriesToView[p++];
1412 if (pdbe != null && pdbe.getFile() != null)
1414 StructureMapping[] smm = ssm.getMapping(pdbe.getFile());
1415 if (smm != null && smm.length > 0)
1417 for (StructureMapping sm : smm)
1419 if (sm.getSequence() == seq)
1426 if (seq.getPrimaryDBRefs().isEmpty())
1428 seqsWithoutSourceDBRef.add(seq);
1432 if (!seqsWithoutSourceDBRef.isEmpty())
1434 int y = seqsWithoutSourceDBRef.size();
1435 setProgressBar(MessageManager.formatMessage(
1436 "status.fetching_dbrefs_for_sequences_without_valid_refs",
1438 SequenceI[] seqWithoutSrcDBRef = seqsWithoutSourceDBRef
1439 .toArray(new SequenceI[y]);
1440 DBRefFetcher dbRefFetcher = new DBRefFetcher(seqWithoutSrcDBRef);
1441 dbRefFetcher.fetchDBRefs(true);
1443 setProgressBar("Fetch complete.", progressId); // todo i18n
1446 if (pdbEntriesToView.length > 1)
1449 MessageManager.getString(
1450 "status.fetching_3d_structures_for_selected_entries"),
1452 theViewer.viewStructures(pdbEntriesToView, sequences, alignPanel,
1457 setProgressBar(MessageManager.formatMessage(
1458 "status.fetching_3d_structures_for",
1459 pdbEntriesToView[0].getId()), progressId);
1460 // Can we pass a pre-computeMappinged pdbFile?
1461 theViewer.viewStructures(pdbEntriesToView[0], sequences, alignPanel,
1464 setProgressBar(null, progressId);
1465 // remember the last viewer we used...
1466 lastTargetedView = theViewer;
1471 * Populates the combo-box used in associating manually fetched structures to
1472 * a unique sequence when more than one sequence selection is made.
1475 protected void populateCmbAssociateSeqOptions(
1476 JComboBox<AssociateSeqOptions> cmb_assSeq,
1477 JLabel lbl_associateSeq)
1479 cmb_assSeq.removeAllItems();
1481 new AssociateSeqOptions("-Select Associated Seq-", null));
1482 lbl_associateSeq.setVisible(false);
1483 if (selectedSequences.length > 1)
1485 for (SequenceI seq : selectedSequences)
1487 cmb_assSeq.addItem(new AssociateSeqOptions(seq));
1492 String seqName = selectedSequence.getDisplayId(false);
1493 seqName = seqName.length() <= 40 ? seqName : seqName.substring(0, 39);
1494 lbl_associateSeq.setText(seqName);
1495 lbl_associateSeq.setVisible(true);
1496 cmb_assSeq.setVisible(false);
1500 protected boolean isStructuresDiscovered()
1502 return discoveredStructuresSet != null
1503 && !discoveredStructuresSet.isEmpty();
1506 protected int PDB_ID_MIN = 3;// or: (Jalview.isJS() ? 3 : 1); // Bob proposes
1508 // Doing a search for "1" or "1c" is valuable?
1509 // Those work but are enormously slow.
1512 protected void txt_search_ActionPerformed()
1514 String text = txt_search.getText().trim();
1515 if (text.length() >= PDB_ID_MIN)
1522 errorWarning.setLength(0);
1523 isValidPBDEntry = false;
1524 if (text.length() > 0)
1526 // TODO move this pdb id search into the PDB specific
1528 // for moment, it will work fine as is because it is self-contained
1529 String searchTerm = text.toLowerCase(Locale.ROOT);
1530 searchTerm = searchTerm.split(":")[0];
1531 // System.out.println(">>>>> search term : " + searchTerm);
1532 List<FTSDataColumnI> wantedFields = new ArrayList<>();
1533 FTSRestRequest pdbRequest = new FTSRestRequest();
1534 pdbRequest.setAllowEmptySeq(false);
1535 pdbRequest.setResponseSize(1);
1536 pdbRequest.setFieldToSearchBy("(pdb_id:");
1537 pdbRequest.setWantedFields(wantedFields);
1538 pdbRequest.setSearchTerm(searchTerm + ")");
1539 pdbRequest.setAssociatedSequence(selectedSequence);
1540 FTSRestClientI pdbRestClient = PDBFTSRestClient.getInstance();
1541 wantedFields.add(pdbRestClient.getPrimaryKeyColumn());
1542 FTSRestResponse resultList;
1545 resultList = pdbRestClient.executeRequest(pdbRequest);
1546 } catch (Exception e)
1548 errorWarning.append(e.getMessage());
1552 validateSelections();
1554 if (resultList.getSearchSummary() != null
1555 && resultList.getSearchSummary().size() > 0)
1557 isValidPBDEntry = true;
1560 validateSelections();
1566 protected void tabRefresh()
1568 if (selectedSequences != null)
1570 lbl_loading.setVisible(true);
1571 Thread refreshThread = new Thread(new Runnable()
1576 fetchStructuresMetaData();
1577 // populateFilterComboBox(true, cachedPDBExists);
1580 ((FilterOption) cmb_filterOption.getSelectedItem())
1582 lbl_loading.setVisible(false);
1585 refreshThread.start();
1589 public class PDBEntryTableModel extends AbstractTableModel
1591 String[] columns = { "Ref Sequence", "PDB Id", "Chain", "Type",
1594 private List<CachedPDB> pdbEntries;
1596 public PDBEntryTableModel(List<CachedPDB> pdbEntries)
1598 this.pdbEntries = new ArrayList<>(pdbEntries);
1602 public String getColumnName(int columnIndex)
1604 return columns[columnIndex];
1608 public int getRowCount()
1610 return pdbEntries.size();
1614 public int getColumnCount()
1616 return columns.length;
1620 public boolean isCellEditable(int row, int column)
1626 public Object getValueAt(int rowIndex, int columnIndex)
1628 Object value = "??";
1629 CachedPDB entry = pdbEntries.get(rowIndex);
1630 switch (columnIndex)
1633 value = entry.getSequence();
1636 value = entry.getQualifiedId();
1639 value = entry.getPdbEntry().getChainCode() == null ? "_"
1640 : entry.getPdbEntry().getChainCode();
1643 value = entry.getPdbEntry().getType();
1646 value = entry.getPdbEntry().getFile();
1653 public Class<?> getColumnClass(int columnIndex)
1655 return columnIndex == 0 ? SequenceI.class : PDBEntry.class;
1658 public CachedPDB getPDBEntryAt(int row)
1660 return pdbEntries.get(row);
1665 private class CachedPDB
1667 private SequenceI sequence;
1669 private PDBEntry pdbEntry;
1671 public CachedPDB(SequenceI sequence, PDBEntry pdbEntry)
1673 this.sequence = sequence;
1674 this.pdbEntry = pdbEntry;
1677 public String getQualifiedId()
1679 if (pdbEntry.hasProvider())
1681 return pdbEntry.getProvider() + ":" + pdbEntry.getId();
1683 return pdbEntry.toString();
1686 public SequenceI getSequence()
1691 public PDBEntry getPdbEntry()
1698 private IProgressIndicator progressBar;
1701 public void setProgressBar(String message, long id)
1703 if (!Platform.isHeadless())
1704 progressBar.setProgressBar(message, id);
1708 public void registerHandler(long id, IProgressIndicatorHandler handler)
1710 progressBar.registerHandler(id, handler);
1714 public boolean operationInProgress()
1716 return progressBar.operationInProgress();
1719 public JalviewStructureDisplayI getOpenedStructureViewer()
1721 return sViewer == null ? null : sViewer.sview;
1725 protected void setFTSDocFieldPrefs(FTSDataColumnPreferences newPrefs)
1727 data.setDocFieldPrefs(newPrefs);
1733 * @return true when all initialisation threads have finished and dialog is
1736 public boolean isDialogVisible()
1738 return mainFrame != null && data != null && cmb_filterOption != null
1739 && mainFrame.isVisible()
1740 && cmb_filterOption.getSelectedItem() != null;
1745 * @return true if the 3D-Beacons query button will/has been displayed
1747 public boolean isCanQueryTDB()
1752 public boolean isNotQueriedTDBYet()
1754 return notQueriedTDBYet;
1758 * Open a single structure file for a given sequence
1760 public static void openStructureFileForSequence(
1761 StructureSelectionManager ssm, StructureChooser sc,
1762 AlignmentPanel ap, SequenceI seq, boolean prompt,
1763 String sFilename, TFType tft, String paeFilename,
1764 boolean doXferSettings)
1766 openStructureFileForSequence(ssm, sc, ap, seq, prompt, sFilename, tft,
1767 paeFilename, false, true, doXferSettings, null);
1770 public static void openStructureFileForSequence(
1771 StructureSelectionManager ssm, StructureChooser sc,
1772 AlignmentPanel ap, SequenceI seq, boolean prompt,
1773 String sFilename, TFType tft, String paeFilename,
1774 boolean forceHeadless, boolean showRefAnnotations,
1775 boolean doXferSettings, ViewerType viewerType)
1777 boolean headless = forceHeadless;
1782 sc = new StructureChooser(new SequenceI[] { seq }, seq, ap, false);
1785 ssm = ap.getStructureSelectionManager();
1787 PDBEntry fileEntry = new AssociatePdbFileWithSeq().associatePdbWithSeq(
1788 sFilename, DataSourceType.FILE, seq, prompt, Desktop.instance,
1789 tft, paeFilename, doXferSettings);
1791 // if headless, "false" in the sc constructor above will avoid GUI behaviour
1792 // in sc.launchStructureViewer()
1793 if (!headless && !(viewerType == null))
1794 sc.launchStructureViewer(ssm, new PDBEntry[] { fileEntry }, ap,
1796 { seq }, viewerType);
1799 sc.mainFrame.dispose();
1801 if (showRefAnnotations)
1802 showReferenceAnnotationsForSequence(ap.alignFrame, seq);
1805 public static void showReferenceAnnotationsForSequence(AlignFrame af,
1808 AlignViewport av = af.getCurrentView();
1809 AlignmentI al = av.getAlignment();
1811 List<SequenceI> forSequences = new ArrayList<>();
1812 forSequences.add(sequence);
1813 final Map<SequenceI, List<AlignmentAnnotation>> candidates = new LinkedHashMap<>();
1814 AlignmentUtils.findAddableReferenceAnnotations(forSequences, null,
1816 final SequenceGroup selectionGroup = av.getSelectionGroup();
1817 AlignmentUtils.addReferenceAnnotations(candidates, al, selectionGroup);
1818 for (AlignmentViewPanel ap : af.getAlignPanels())
1820 // required to readjust the height and position of the PAE
1822 ap.adjustAnnotationHeight();