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.JProgressBar;
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 Runnable 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();
376 final Runnable revertview = () -> {
377 if (lastSelected != null)
379 cmb_filterOption.setSelectedItem(lastSelected);
382 int threshold = Cache.getDefault("UNIPROT_AUTOFETCH_THRESHOLD",
383 THRESHOLD_WARN_UNIPROT_FETCH_NEEDED);
384 Console.debug("Using Uniprot fetch threshold of " + threshold);
385 if (ignoreGui || seqsWithoutSourceDBRef.size() < threshold)
387 Executors.newSingleThreadExecutor().submit(discoverCanonicalDBrefs);
390 // need cancel and no to result in the discoverPDB action - mocked is
391 // 'cancel' TODO: mock should be OK
393 StructureChooser thisSC = this;
394 JvOptionPane.newOptionDialog(thisSC.getFrame())
395 .setResponseHandler(JvOptionPane.OK_OPTION,
396 discoverCanonicalDBrefs)
397 .setResponseHandler(JvOptionPane.CANCEL_OPTION, revertview)
398 .setResponseHandler(JvOptionPane.NO_OPTION, revertview)
400 MessageManager.formatMessage(
401 "label.fetch_references_for_3dbeacons",
402 seqsWithoutSourceDBRef.size()),
403 MessageManager.getString("label.3dbeacons"),
404 JvOptionPane.YES_NO_OPTION, JvOptionPane.PLAIN_MESSAGE,
406 { MessageManager.getString("action.ok"),
407 MessageManager.getString("action.cancel") },
408 MessageManager.getString("action.ok"), false);
412 * Builds a drop-down choice list of existing structure viewers to which new
413 * structures may be added. If this list is empty then it, and the 'Add'
414 * button, are hidden.
416 private void discoverStructureViews()
418 if (Desktop.instance != null)
420 targetView.removeAllItems();
421 if (lastTargetedView != null && !lastTargetedView.isVisible())
423 lastTargetedView = null;
425 int linkedViewsAt = 0;
426 for (StructureViewerBase view : Desktop.instance
427 .getStructureViewers(null, null))
429 StructureViewer viewHandler = (lastTargetedView != null
430 && lastTargetedView.sview == view) ? lastTargetedView
431 : StructureViewer.reconfigure(view);
433 if (view.isLinkedWith(ap))
435 targetView.insertItemAt(viewHandler, linkedViewsAt++);
439 targetView.addItem(viewHandler);
444 * show option to Add to viewer if at least 1 viewer found
446 targetView.setVisible(false);
447 if (targetView.getItemCount() > 0)
449 targetView.setVisible(true);
450 if (lastTargetedView != null)
452 targetView.setSelectedItem(lastTargetedView);
456 targetView.setSelectedIndex(0);
459 btn_add.setVisible(targetView.isVisible());
464 * Updates the progress indicator with the specified message
467 * displayed message for the operation
469 * unique handle for this indicator
471 protected void updateProgressIndicator(String message, long id)
473 if (progressIndicator != null)
475 progressIndicator.setProgressBar(message, id);
480 * Retrieve meta-data for all the structure(s) for a given sequence(s) in a
483 void fetchStructuresMetaData()
485 long startTime = System.currentTimeMillis();
486 Collection<FTSDataColumnI> wantedFields = data.getDocFieldPrefs()
487 .getStructureSummaryFields();
489 discoveredStructuresSet = new LinkedHashSet<>();
490 HashSet<String> errors = new HashSet<>();
492 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
495 for (SequenceI seq : selectedSequences)
498 FTSRestResponse resultList;
501 resultList = data.fetchStructuresMetaData(seq, wantedFields,
502 selectedFilterOpt, !chk_invertFilter.isSelected());
503 // null response means the FTSengine didn't yield a query for this
504 // consider designing a special exception if we really wanted to be
506 if (resultList == null)
510 } catch (Exception e)
513 errors.add(e.getMessage());
516 if (resultList.getSearchSummary() != null
517 && !resultList.getSearchSummary().isEmpty())
519 discoveredStructuresSet.addAll(resultList.getSearchSummary());
523 int noOfStructuresFound = 0;
524 String totalTime = (System.currentTimeMillis() - startTime)
526 if (discoveredStructuresSet != null
527 && !discoveredStructuresSet.isEmpty())
530 .setModel(data.getTableModel(discoveredStructuresSet));
532 noOfStructuresFound = discoveredStructuresSet.size();
533 lastDiscoveredStructuresSet = discoveredStructuresSet;
534 mainFrame.setTitle(MessageManager.formatMessage(
535 "label.structure_chooser_no_of_structures",
536 noOfStructuresFound, totalTime));
540 mainFrame.setTitle(MessageManager
541 .getString("label.structure_chooser_manual_association"));
542 if (errors.size() > 0)
544 StringBuilder errorMsg = new StringBuilder();
545 for (String error : errors)
547 errorMsg.append(error).append("\n");
549 JvOptionPane.showMessageDialog(this, errorMsg.toString(),
550 MessageManager.getString("label.pdb_web-service_error"),
551 JvOptionPane.ERROR_MESSAGE);
556 protected void loadLocalCachedPDBEntries()
558 ArrayList<CachedPDB> entries = new ArrayList<>();
559 for (SequenceI seq : selectedSequences)
561 if (seq.getDatasetSequence() != null
562 && seq.getDatasetSequence().getAllPDBEntries() != null)
564 for (PDBEntry pdbEntry : seq.getDatasetSequence()
567 if (pdbEntry.getFile() != null)
569 entries.add(new CachedPDB(seq, pdbEntry));
574 cachedPDBExists = !entries.isEmpty();
575 PDBEntryTableModel tableModelx = new PDBEntryTableModel(entries);
576 tbl_local_pdb.setModel(tableModelx);
580 * Filters a given list of discovered structures based on supplied argument
582 * @param fieldToFilterBy
583 * the field to filter by
585 void filterResultSet(final String fieldToFilterBy)
587 Thread filterThread = new Thread(new Runnable()
593 long startTime = System.currentTimeMillis();
594 lbl_loading.setVisible(true);
595 Collection<FTSDataColumnI> wantedFields = data.getDocFieldPrefs()
596 .getStructureSummaryFields();
597 Collection<FTSData> filteredResponse = new HashSet<>();
598 HashSet<String> errors = new HashSet<>();
600 for (SequenceI seq : selectedSequences)
603 FTSRestResponse resultList;
606 resultList = data.selectFirstRankedQuery(seq,
607 discoveredStructuresSet, wantedFields, fieldToFilterBy,
608 !chk_invertFilter.isSelected());
610 } catch (Exception e)
613 errors.add(e.getMessage());
616 if (resultList.getSearchSummary() != null
617 && !resultList.getSearchSummary().isEmpty())
619 filteredResponse.addAll(resultList.getSearchSummary());
623 String totalTime = (System.currentTimeMillis() - startTime)
625 if (!filteredResponse.isEmpty())
627 final int filterResponseCount = filteredResponse.size();
628 Collection<FTSData> reorderedStructuresSet = new LinkedHashSet<>();
629 reorderedStructuresSet.addAll(filteredResponse);
630 reorderedStructuresSet.addAll(discoveredStructuresSet);
632 .setModel(data.getTableModel(reorderedStructuresSet));
634 FTSRestResponse.configureTableColumn(getResultTable(),
635 wantedFields, tempUserPrefs);
636 getResultTable().getColumn("Ref Sequence").setPreferredWidth(120);
637 getResultTable().getColumn("Ref Sequence").setMinWidth(100);
638 getResultTable().getColumn("Ref Sequence").setMaxWidth(200);
639 // Update table selection model here
640 getResultTable().addRowSelectionInterval(0,
641 filterResponseCount - 1);
642 mainFrame.setTitle(MessageManager.formatMessage(
643 "label.structure_chooser_filter_time", totalTime));
647 mainFrame.setTitle(MessageManager.formatMessage(
648 "label.structure_chooser_filter_time", totalTime));
649 if (errors.size() > 0)
651 StringBuilder errorMsg = new StringBuilder();
652 for (String error : errors)
654 errorMsg.append(error).append("\n");
656 JvOptionPane.showMessageDialog(null, errorMsg.toString(),
657 MessageManager.getString("label.pdb_web-service_error"),
658 JvOptionPane.ERROR_MESSAGE);
662 lbl_loading.setVisible(false);
664 validateSelections();
667 filterThread.start();
671 * Handles action event for btn_pdbFromFile
674 protected void pdbFromFile_actionPerformed()
676 // TODO: JAL-3048 not needed for Jalview-JS until JSmol dep and
679 JalviewFileChooser chooser = new JalviewFileChooser(
680 Cache.getProperty("LAST_DIRECTORY"));
681 chooser.setFileView(new JalviewFileView());
682 chooser.setDialogTitle(
683 MessageManager.formatMessage("label.select_pdb_file_for",
684 selectedSequence.getDisplayId(false)));
685 chooser.setToolTipText(MessageManager.formatMessage(
686 "label.load_pdb_file_associate_with_sequence",
687 selectedSequence.getDisplayId(false)));
689 int value = chooser.showOpenDialog(null);
690 if (value == JalviewFileChooser.APPROVE_OPTION)
692 selectedPdbFileName = chooser.getSelectedFile().getPath();
693 Cache.setProperty("LAST_DIRECTORY", selectedPdbFileName);
694 boolean guessTFType = localPdbPaeMatrixFileName == null;
695 localPdbPaeMatrixFileName = guessPAEFilename();
696 guessTFType |= localPdbPaeMatrixFileName != null;
697 Regex alphaFold = JmolParser.getNewAlphafoldValidator();
699 && alphaFold.search(new File(selectedPdbFileName).getName())
700 && !tempFacAsChanged)
702 // localPdbPaeMatrixFileName was null and now isn't and filename could
703 // well be AlphaFold and user hasn't adjusted the tempFacType
704 combo_tempFacAs.setSelectedItem(TFType.PLDDT);
706 validateSelections();
711 * Handles action event for btn_paeMatrixFile
714 protected void paeMatrixFile_actionPerformed()
716 File pdbFile = new File(selectedPdbFileName);
717 String setFile = Cache.getProperty("LAST_DIRECTORY");
718 if (localPdbPaeMatrixFileName != null)
720 File paeFile = new File(localPdbPaeMatrixFileName);
721 if (paeFile.exists())
722 setFile = paeFile.getAbsolutePath();
723 else if (paeFile.getParentFile().exists())
724 setFile = paeFile.getParentFile().getAbsolutePath();
728 String guess = guessPAEFilename();
732 JalviewFileChooser chooser = new JalviewFileChooser(setFile);
733 chooser.setFileView(new JalviewFileView());
734 chooser.setDialogTitle(MessageManager.formatMessage(
735 "label.select_pae_matrix_file_for", pdbFile.getName()));
736 chooser.setToolTipText(MessageManager.formatMessage(
737 "label.load_pae_matrix_file_associate_with_structure",
740 // TODO convert to Callable/Promise
741 int value = chooser.showOpenDialog(null);
742 if (value == JalviewFileChooser.APPROVE_OPTION)
744 String fileName = chooser.getSelectedFile().getPath();
747 PAEContactMatrix.validateContactMatrixFile(fileName);
748 } catch (Exception thr)
750 JvOptionPane.showInternalMessageDialog(this, MessageManager
751 .formatMessage("label.couldnt_load_file", new Object[]
752 { fileName }) + "<br>" + thr.getLocalizedMessage(),
753 MessageManager.getString("label.error_loading_file"),
754 JvOptionPane.WARNING_MESSAGE);
755 Console.error("Couldn't import " + fileName + " as a PAE matrix",
759 localPdbPaeMatrixFileName = fileName;
760 Cache.setProperty("LAST_DIRECTORY", localPdbPaeMatrixFileName);
762 validateAssociationFromFile();
765 private String guessPAEFilename()
767 if (selectedPdbFileName.toLowerCase(Locale.ROOT).endsWith(".pdb")
768 || selectedPdbFileName.toLowerCase(Locale.ROOT)
771 String jsonExt = selectedPdbFileName.substring(0,
772 selectedPdbFileName.length() - 4) + ".json";
773 // AlphaFold naming scheme
774 String guessFile1 = StringUtils.replaceLast(jsonExt, "model",
775 "predicted_aligned_error");
776 // nf-core mode naming scheme
777 String guessFile2 = StringUtils.replaceLast(jsonExt, ".json",
779 if (new File(guessFile1).exists())
783 else if (new File(jsonExt).exists())
787 else if (new File(guessFile2).exists())
796 * Populates the filter combo-box options dynamically depending on discovered
799 protected void populateFilterComboBox(boolean haveData,
800 boolean cachedPDBExist)
802 populateFilterComboBox(haveData, cachedPDBExist, null);
806 * Populates the filter combo-box options dynamically depending on discovered
809 protected void populateFilterComboBox(boolean haveData,
810 boolean cachedPDBExist, FilterOption lastSel)
814 * temporarily suspend the change listener behaviour
816 cmb_filterOption.removeItemListener(this);
818 cmb_filterOption.removeAllItems();
821 List<FilterOption> filters = data
822 .getAvailableFilterOptions(VIEWS_FILTER);
823 data.updateAvailableFilterOptions(VIEWS_FILTER, filters,
824 lastDiscoveredStructuresSet);
826 for (FilterOption filter : filters)
828 if (lastSel != null && filter.equals(lastSel))
833 cmb_filterOption.addItem(filter);
837 cmb_filterOption.addItem(
838 new FilterOption(MessageManager.getString("label.enter_pdb_id"),
839 "-", VIEWS_ENTER_ID, false, null));
840 cmb_filterOption.addItem(
841 new FilterOption(MessageManager.getString("label.from_file"),
842 "-", VIEWS_FROM_FILE, false, null));
843 if (canQueryTDB && notQueriedTDBYet)
845 btn_queryTDB.setVisible(true);
846 pnl_queryTDB.setVisible(true);
851 FilterOption cachedOption = new FilterOption(
852 MessageManager.getString("label.cached_structures"), "-",
853 VIEWS_LOCAL_PDB, false, null);
854 cmb_filterOption.addItem(cachedOption);
857 cmb_filterOption.setSelectedItem(cachedOption);
862 cmb_filterOption.setSelectedIndex(selSet);
864 cmb_filterOption.addItemListener(this);
868 * Updates the displayed view based on the selected filter option
870 protected void updateCurrentView()
872 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
875 if (lastSelected == selectedFilterOpt)
877 // don't need to do anything, probably
880 // otherwise, record selection
881 // and update the layout and dialog accordingly
882 lastSelected = selectedFilterOpt;
884 layout_switchableViews.show(pnl_switchableViews,
885 selectedFilterOpt.getView());
886 String filterTitle = mainFrame.getTitle();
887 mainFrame.setTitle(frameTitle);
888 chk_invertFilter.setVisible(false);
890 if (selectedFilterOpt.getView() == VIEWS_FILTER)
892 mainFrame.setTitle(filterTitle);
893 // TDB Query has no invert as yet
894 chk_invertFilter.setVisible(selectedFilterOpt
895 .getQuerySource() instanceof PDBStructureChooserQuerySource);
897 if (data != selectedFilterOpt.getQuerySource()
898 || data.needsRefetch(selectedFilterOpt))
900 data = selectedFilterOpt.getQuerySource();
901 // rebuild the views completely, since prefs will also change
907 filterResultSet(selectedFilterOpt.getValue());
910 else if (selectedFilterOpt.getView() == VIEWS_ENTER_ID
911 || selectedFilterOpt.getView() == VIEWS_FROM_FILE)
913 mainFrame.setTitle(MessageManager
914 .getString("label.structure_chooser_manual_association"));
915 idInputAssSeqPanel.loadCmbAssSeq();
916 fileChooserAssSeqPanel.loadCmbAssSeq();
918 validateSelections();
922 * Validates user selection and enables the 'Add' and 'New View' buttons if
923 * all parameters are correct (the Add button will only be visible if there is
924 * at least one existing structure viewer open). This basically means at least
925 * one structure selected and no error messages.
927 * The 'Superpose Structures' option is enabled if either more than one
928 * structure is selected, or the 'Add' to existing view option is enabled, and
929 * disabled if the only option is to open a new view of a single structure.
932 protected void validateSelections()
934 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
936 btn_add.setEnabled(false);
937 String currentView = selectedFilterOpt.getView();
938 int selectedCount = 0;
939 if (currentView == VIEWS_FILTER)
941 selectedCount = getResultTable().getSelectedRows().length;
942 if (selectedCount > 0)
944 btn_add.setEnabled(true);
947 else if (currentView == VIEWS_LOCAL_PDB)
949 selectedCount = tbl_local_pdb.getSelectedRows().length;
950 if (selectedCount > 0)
952 btn_add.setEnabled(true);
955 else if (currentView == VIEWS_ENTER_ID)
957 validateAssociationEnterPdb();
959 else if (currentView == VIEWS_FROM_FILE)
961 validateAssociationFromFile();
964 btn_newView.setEnabled(btn_add.isEnabled());
967 * enable 'Superpose' option if more than one structure is selected,
968 * or there are view(s) available to add structure(s) to
971 .setEnabled(selectedCount > 1 || targetView.getItemCount() > 0);
975 protected boolean showPopupFor(int selectedRow, int x, int y)
977 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
979 String currentView = selectedFilterOpt.getView();
981 if (currentView == VIEWS_FILTER
982 && data instanceof ThreeDBStructureChooserQuerySource)
985 TDB_FTSData row = ((ThreeDBStructureChooserQuerySource) data)
986 .getFTSDataFor(getResultTable(), selectedRow,
987 discoveredStructuresSet);
988 String pageUrl = row.getModelViewUrl();
989 JPopupMenu popup = new JPopupMenu("3D Beacons");
990 JMenuItem viewUrl = new JMenuItem("View model web page");
991 viewUrl.addActionListener(new ActionListener()
994 public void actionPerformed(ActionEvent e)
996 Desktop.showUrl(pageUrl);
1000 SwingUtilities.invokeLater(new Runnable()
1005 popup.show(getResultTable(), x, y);
1010 // event not handled by us
1015 * Validates inputs from the Manual PDB entry panel
1017 protected void validateAssociationEnterPdb()
1019 AssociateSeqOptions assSeqOpt = (AssociateSeqOptions) idInputAssSeqPanel
1020 .getCmb_assSeq().getSelectedItem();
1021 lbl_pdbManualFetchStatus.setIcon(errorImage);
1022 lbl_pdbManualFetchStatus.setToolTipText("");
1023 if (txt_search.getText().length() > 0)
1025 lbl_pdbManualFetchStatus.setToolTipText(JvSwingUtils.wrapTooltip(true,
1026 MessageManager.formatMessage("info.no_pdb_entry_found_for",
1027 txt_search.getText())));
1030 if (errorWarning.length() > 0)
1032 lbl_pdbManualFetchStatus.setIcon(warningImage);
1033 lbl_pdbManualFetchStatus.setToolTipText(
1034 JvSwingUtils.wrapTooltip(true, errorWarning.toString()));
1037 if (selectedSequences.length == 1 || !assSeqOpt.getName()
1038 .equalsIgnoreCase("-Select Associated Seq-"))
1040 txt_search.setEnabled(true);
1041 if (isValidPBDEntry)
1043 btn_add.setEnabled(true);
1044 lbl_pdbManualFetchStatus.setToolTipText("");
1045 lbl_pdbManualFetchStatus.setIcon(goodImage);
1050 txt_search.setEnabled(false);
1051 lbl_pdbManualFetchStatus.setIcon(errorImage);
1056 * Validates inputs for the manual PDB file selection options
1058 protected void validateAssociationFromFile()
1060 AssociateSeqOptions assSeqOpt = (AssociateSeqOptions) fileChooserAssSeqPanel
1061 .getCmb_assSeq().getSelectedItem();
1062 // lbl_fromFileStatus.setIcon(errorImage);
1063 String pdbFileString = "";
1064 String pdbFileTooltip = "";
1065 if (selectedSequences.length == 1 || (assSeqOpt != null && !assSeqOpt
1066 .getName().equalsIgnoreCase("-Select Associated Seq-")))
1068 btn_pdbFromFile.setEnabled(true);
1069 if (selectedPdbFileName != null && selectedPdbFileName.length() > 0)
1071 btn_add.setEnabled(true);
1072 // lbl_fromFileStatus.setIcon(goodImage);
1073 pdbFileString = new File(selectedPdbFileName).getName();
1074 pdbFileTooltip = new File(selectedPdbFileName).getAbsolutePath();
1075 setPdbOptionsEnabled(true);
1079 pdbFileString = MessageManager.getString("label.none");
1080 pdbFileTooltip = MessageManager.getString("label.nothing_selected");
1081 setPdbOptionsEnabled(false);
1086 btn_pdbFromFile.setEnabled(false);
1087 setPdbOptionsEnabled(false);
1088 // lbl_fromFileStatus.setIcon(errorImage);
1089 pdbFileString = MessageManager.getString("label.none");
1090 pdbFileTooltip = MessageManager.getString("label.nothing_selected");
1092 lbl_pdbFile.setText(pdbFileString);
1093 lbl_pdbFile.setToolTipText(pdbFileTooltip);
1096 String paeFileString = "";
1097 String paeFileTooltip = "";
1098 if (localPdbPaeMatrixFileName != null
1099 && localPdbPaeMatrixFileName.length() > 0)
1101 paeFileString = new File(localPdbPaeMatrixFileName).getName();
1102 paeFileTooltip = new File(localPdbPaeMatrixFileName)
1107 paeFileString = MessageManager.getString("label.none");
1108 paeFileTooltip = MessageManager.getString("label.nothing_selected");
1110 lbl_paeFile.setText(paeFileString);
1111 lbl_paeFile.setToolTipText(paeFileTooltip);
1115 protected void cmbAssSeqStateChanged()
1117 validateSelections();
1120 private FilterOption lastSelected = null;
1123 * Handles the state change event for the 'filter' combo-box and 'invert'
1127 protected void stateChanged(ItemEvent e)
1129 if (e.getSource() instanceof JCheckBox)
1131 updateCurrentView();
1135 if (e.getStateChange() == ItemEvent.SELECTED)
1137 updateCurrentView();
1144 * select structures for viewing by their PDB IDs
1147 * @return true if structures were found and marked as selected
1149 public boolean selectStructure(String... pdbids)
1151 boolean found = false;
1153 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
1154 .getSelectedItem());
1155 String currentView = selectedFilterOpt.getView();
1156 JTable restable = (currentView == VIEWS_FILTER) ? getResultTable()
1157 : (currentView == VIEWS_LOCAL_PDB) ? tbl_local_pdb : null;
1159 if (restable == null)
1161 // can't select (enter PDB ID, or load file - need to also select which
1162 // sequence to associate with)
1166 int pdbIdColIndex = restable.getColumn("PDB Id").getModelIndex();
1167 for (int r = 0; r < restable.getRowCount(); r++)
1169 for (int p = 0; p < pdbids.length; p++)
1171 if (String.valueOf(restable.getValueAt(r, pdbIdColIndex))
1172 .equalsIgnoreCase(pdbids[p]))
1174 restable.setRowSelectionInterval(r, r);
1183 * Handles the 'New View' action
1186 protected void newView_ActionPerformed()
1188 targetView.setSelectedItem(null);
1189 showStructures(false);
1193 * Handles the 'Add to existing viewer' action
1196 protected void add_ActionPerformed()
1198 showStructures(false);
1202 * structure viewer opened by this dialog, or null
1204 private StructureViewer sViewer = null;
1206 public void showStructures(boolean waitUntilFinished)
1209 final StructureSelectionManager ssm = ap.getStructureSelectionManager();
1211 final int preferredHeight = pnl_filter.getHeight();
1212 btn_add.setEnabled(false);
1213 btn_newView.setEnabled(false);
1214 btn_cancel.setEnabled(false);
1215 actionsPanel.setEnabled(false);
1217 final String progress = MessageManager
1218 .getString("label.working_ellipsis");
1219 setProgressBar(progress, progress.hashCode());
1220 Runnable viewStruc = new Runnable()
1225 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
1226 .getSelectedItem());
1227 String currentView = selectedFilterOpt.getView();
1228 JTable restable = (currentView == VIEWS_FILTER) ? getResultTable()
1231 if (currentView == VIEWS_FILTER)
1233 int[] selectedRows = restable.getSelectedRows();
1234 PDBEntry[] pdbEntriesToView = new PDBEntry[selectedRows.length];
1235 List<SequenceI> selectedSeqsToView = new ArrayList<>();
1236 pdbEntriesToView = data.collectSelectedRows(restable,
1237 selectedRows, selectedSeqsToView);
1239 SequenceI[] selectedSeqs = selectedSeqsToView
1240 .toArray(new SequenceI[selectedSeqsToView.size()]);
1241 sViewer = launchStructureViewer(ssm, pdbEntriesToView, ap,
1244 else if (currentView == VIEWS_LOCAL_PDB)
1246 int[] selectedRows = tbl_local_pdb.getSelectedRows();
1247 PDBEntry[] pdbEntriesToView = new PDBEntry[selectedRows.length];
1249 int pdbIdColIndex = tbl_local_pdb.getColumn("PDB Id")
1251 int refSeqColIndex = tbl_local_pdb.getColumn("Ref Sequence")
1253 List<SequenceI> selectedSeqsToView = new ArrayList<>();
1254 for (int row : selectedRows)
1256 PDBEntry pdbEntry = ((PDBEntryTableModel) tbl_local_pdb
1257 .getModel()).getPDBEntryAt(row).getPdbEntry();
1259 pdbEntriesToView[count++] = pdbEntry;
1260 SequenceI selectedSeq = (SequenceI) tbl_local_pdb
1261 .getValueAt(row, refSeqColIndex);
1262 selectedSeqsToView.add(selectedSeq);
1264 SequenceI[] selectedSeqs = selectedSeqsToView
1265 .toArray(new SequenceI[selectedSeqsToView.size()]);
1266 sViewer = launchStructureViewer(ssm, pdbEntriesToView, ap,
1269 else if (currentView == VIEWS_ENTER_ID)
1271 SequenceI userSelectedSeq = ((AssociateSeqOptions) idInputAssSeqPanel
1272 .getCmb_assSeq().getSelectedItem()).getSequence();
1273 if (userSelectedSeq != null)
1275 selectedSequence = userSelectedSeq;
1277 String pdbIdStr = txt_search.getText();
1278 PDBEntry pdbEntry = selectedSequence.getPDBEntry(pdbIdStr);
1279 if (pdbEntry == null)
1281 pdbEntry = new PDBEntry();
1282 if (pdbIdStr.split(":").length > 1)
1284 pdbEntry.setId(pdbIdStr.split(":")[0]);
1285 pdbEntry.setChainCode(
1286 pdbIdStr.split(":")[1].toUpperCase(Locale.ROOT));
1290 pdbEntry.setId(pdbIdStr);
1292 pdbEntry.setType(PDBEntry.Type.PDB);
1293 selectedSequence.getDatasetSequence().addPDBId(pdbEntry);
1296 PDBEntry[] pdbEntriesToView = new PDBEntry[] { pdbEntry };
1297 sViewer = launchStructureViewer(ssm, pdbEntriesToView, ap,
1299 { selectedSequence });
1301 else if (currentView == VIEWS_FROM_FILE)
1303 StructureChooser sc = StructureChooser.this;
1304 TFType tft = (TFType) sc.combo_tempFacAs.getSelectedItem();
1305 String paeFilename = sc.localPdbPaeMatrixFileName;
1306 AssociateSeqOptions assSeqOpt = (AssociateSeqOptions) fileChooserAssSeqPanel
1307 .getCmb_assSeq().getSelectedItem();
1308 SequenceI userSelectedSeq = assSeqOpt.getSequence();
1309 if (userSelectedSeq != null)
1311 selectedSequence = userSelectedSeq;
1313 String pdbFilename = selectedPdbFileName;
1315 StructureChooser.openStructureFileForSequence(ssm, sc, ap,
1316 selectedSequence, true, pdbFilename, tft, paeFilename,
1319 SwingUtilities.invokeLater(new Runnable()
1324 setProgressBar("Complete.", progress.hashCode());
1325 closeAction(preferredHeight);
1326 mainFrame.dispose();
1331 Thread runner = new Thread(viewStruc);
1333 if (waitUntilFinished)
1335 while (sViewer == null ? runner.isAlive()
1336 : (sViewer.sview == null ? true
1337 : !sViewer.sview.hasMapping()))
1342 } catch (InterruptedException ie)
1351 * Answers a structure viewer (new or existing) configured to superimpose
1352 * added structures or not according to the user's choice
1357 StructureViewer getTargetedStructureViewer(StructureSelectionManager ssm)
1359 Object sv = targetView.getSelectedItem();
1361 return sv == null ? new StructureViewer(ssm) : (StructureViewer) sv;
1365 * Adds PDB structures to a new or existing structure viewer
1368 * @param pdbEntriesToView
1373 private StructureViewer launchStructureViewer(
1374 StructureSelectionManager ssm, final PDBEntry[] pdbEntriesToView,
1375 final AlignmentPanel alignPanel, SequenceI[] sequences)
1377 return launchStructureViewer(ssm, pdbEntriesToView, alignPanel,
1381 private StructureViewer launchStructureViewer(
1382 StructureSelectionManager ssm, final PDBEntry[] pdbEntriesToView,
1383 final AlignmentPanel alignPanel, SequenceI[] sequences,
1384 ViewerType viewerType)
1386 long progressId = sequences.hashCode();
1387 setProgressBar(MessageManager
1388 .getString("status.launching_3d_structure_viewer"), progressId);
1389 final StructureViewer theViewer = getTargetedStructureViewer(ssm);
1390 boolean superimpose = chk_superpose.isSelected();
1391 theViewer.setSuperpose(superimpose);
1394 * remember user's choice of superimpose or not
1396 Cache.setProperty(AUTOSUPERIMPOSE,
1397 Boolean.valueOf(superimpose).toString());
1399 setProgressBar(null, progressId);
1400 if (SiftsSettings.isMapWithSifts())
1402 List<SequenceI> seqsWithoutSourceDBRef = new ArrayList<>();
1404 // TODO: skip PDBEntry:Sequence pairs where PDBEntry doesn't look like a
1405 // real PDB ID. For moment, we can also safely do this if there is already
1406 // a known mapping between the PDBEntry and the sequence.
1407 for (SequenceI seq : sequences)
1409 PDBEntry pdbe = pdbEntriesToView[p++];
1410 if (pdbe != null && pdbe.getFile() != null)
1412 StructureMapping[] smm = ssm.getMapping(pdbe.getFile());
1413 if (smm != null && smm.length > 0)
1415 for (StructureMapping sm : smm)
1417 if (sm.getSequence() == seq)
1424 if (seq.getPrimaryDBRefs().isEmpty())
1426 seqsWithoutSourceDBRef.add(seq);
1430 if (!seqsWithoutSourceDBRef.isEmpty())
1432 int y = seqsWithoutSourceDBRef.size();
1433 setProgressBar(MessageManager.formatMessage(
1434 "status.fetching_dbrefs_for_sequences_without_valid_refs",
1436 SequenceI[] seqWithoutSrcDBRef = seqsWithoutSourceDBRef
1437 .toArray(new SequenceI[y]);
1438 DBRefFetcher dbRefFetcher = new DBRefFetcher(seqWithoutSrcDBRef);
1439 dbRefFetcher.fetchDBRefs(true);
1441 setProgressBar("Fetch complete.", progressId); // todo i18n
1444 if (pdbEntriesToView.length > 1)
1447 MessageManager.getString(
1448 "status.fetching_3d_structures_for_selected_entries"),
1450 theViewer.viewStructures(pdbEntriesToView, sequences, alignPanel,
1455 setProgressBar(MessageManager.formatMessage(
1456 "status.fetching_3d_structures_for",
1457 pdbEntriesToView[0].getId()), progressId);
1458 // Can we pass a pre-computeMappinged pdbFile?
1459 theViewer.viewStructures(pdbEntriesToView[0], sequences, alignPanel,
1462 setProgressBar(null, progressId);
1463 // remember the last viewer we used...
1464 lastTargetedView = theViewer;
1469 * Populates the combo-box used in associating manually fetched structures to
1470 * a unique sequence when more than one sequence selection is made.
1473 protected void populateCmbAssociateSeqOptions(
1474 JComboBox<AssociateSeqOptions> cmb_assSeq,
1475 JLabel lbl_associateSeq)
1477 cmb_assSeq.removeAllItems();
1479 new AssociateSeqOptions("-Select Associated Seq-", null));
1480 lbl_associateSeq.setVisible(false);
1481 if (selectedSequences.length > 1)
1483 for (SequenceI seq : selectedSequences)
1485 cmb_assSeq.addItem(new AssociateSeqOptions(seq));
1490 String seqName = selectedSequence.getDisplayId(false);
1491 seqName = seqName.length() <= 40 ? seqName : seqName.substring(0, 39);
1492 lbl_associateSeq.setText(seqName);
1493 lbl_associateSeq.setVisible(true);
1494 cmb_assSeq.setVisible(false);
1498 protected boolean isStructuresDiscovered()
1500 return discoveredStructuresSet != null
1501 && !discoveredStructuresSet.isEmpty();
1504 protected int PDB_ID_MIN = 3;// or: (Jalview.isJS() ? 3 : 1); // Bob proposes
1506 // Doing a search for "1" or "1c" is valuable?
1507 // Those work but are enormously slow.
1510 protected void txt_search_ActionPerformed()
1512 String text = txt_search.getText().trim();
1513 if (text.length() >= PDB_ID_MIN)
1520 errorWarning.setLength(0);
1521 isValidPBDEntry = false;
1522 if (text.length() > 0)
1524 // TODO move this pdb id search into the PDB specific
1526 // for moment, it will work fine as is because it is self-contained
1527 String searchTerm = text.toLowerCase(Locale.ROOT);
1528 searchTerm = searchTerm.split(":")[0];
1529 // System.out.println(">>>>> search term : " + searchTerm);
1530 List<FTSDataColumnI> wantedFields = new ArrayList<>();
1531 FTSRestRequest pdbRequest = new FTSRestRequest();
1532 pdbRequest.setAllowEmptySeq(false);
1533 pdbRequest.setResponseSize(1);
1534 pdbRequest.setFieldToSearchBy("(pdb_id:");
1535 pdbRequest.setWantedFields(wantedFields);
1536 pdbRequest.setSearchTerm(searchTerm + ")");
1537 pdbRequest.setAssociatedSequence(selectedSequence);
1538 FTSRestClientI pdbRestClient = PDBFTSRestClient.getInstance();
1539 wantedFields.add(pdbRestClient.getPrimaryKeyColumn());
1540 FTSRestResponse resultList;
1543 resultList = pdbRestClient.executeRequest(pdbRequest);
1544 } catch (Exception e)
1546 errorWarning.append(e.getMessage());
1550 validateSelections();
1552 if (resultList.getSearchSummary() != null
1553 && resultList.getSearchSummary().size() > 0)
1555 isValidPBDEntry = true;
1558 validateSelections();
1564 protected void tabRefresh()
1566 if (selectedSequences != null)
1568 lbl_loading.setVisible(true);
1569 Thread refreshThread = new Thread(new Runnable()
1574 fetchStructuresMetaData();
1575 // populateFilterComboBox(true, cachedPDBExists);
1578 ((FilterOption) cmb_filterOption.getSelectedItem())
1580 lbl_loading.setVisible(false);
1583 refreshThread.start();
1587 public class PDBEntryTableModel extends AbstractTableModel
1589 String[] columns = { "Ref Sequence", "PDB Id", "Chain", "Type",
1592 private List<CachedPDB> pdbEntries;
1594 public PDBEntryTableModel(List<CachedPDB> pdbEntries)
1596 this.pdbEntries = new ArrayList<>(pdbEntries);
1600 public String getColumnName(int columnIndex)
1602 return columns[columnIndex];
1606 public int getRowCount()
1608 return pdbEntries.size();
1612 public int getColumnCount()
1614 return columns.length;
1618 public boolean isCellEditable(int row, int column)
1624 public Object getValueAt(int rowIndex, int columnIndex)
1626 Object value = "??";
1627 CachedPDB entry = pdbEntries.get(rowIndex);
1628 switch (columnIndex)
1631 value = entry.getSequence();
1634 value = entry.getQualifiedId();
1637 value = entry.getPdbEntry().getChainCode() == null ? "_"
1638 : entry.getPdbEntry().getChainCode();
1641 value = entry.getPdbEntry().getType();
1644 value = entry.getPdbEntry().getFile();
1651 public Class<?> getColumnClass(int columnIndex)
1653 return columnIndex == 0 ? SequenceI.class : PDBEntry.class;
1656 public CachedPDB getPDBEntryAt(int row)
1658 return pdbEntries.get(row);
1663 private class CachedPDB
1665 private SequenceI sequence;
1667 private PDBEntry pdbEntry;
1669 public CachedPDB(SequenceI sequence, PDBEntry pdbEntry)
1671 this.sequence = sequence;
1672 this.pdbEntry = pdbEntry;
1675 public String getQualifiedId()
1677 if (pdbEntry.hasProvider())
1679 return pdbEntry.getProvider() + ":" + pdbEntry.getId();
1681 return pdbEntry.toString();
1684 public SequenceI getSequence()
1689 public PDBEntry getPdbEntry()
1696 private IProgressIndicator progressBar;
1699 public void setProgressBar(String message, long id)
1701 if (!Platform.isHeadless() && progressBar != null)
1702 progressBar.setProgressBar(message, id);
1706 public void registerHandler(long id, IProgressIndicatorHandler handler)
1708 if (progressBar != null)
1709 progressBar.registerHandler(id, handler);
1713 public boolean operationInProgress()
1715 return progressBar == null ? false : progressBar.operationInProgress();
1718 public JalviewStructureDisplayI getOpenedStructureViewer()
1720 return sViewer == null ? null : sViewer.sview;
1724 protected void setFTSDocFieldPrefs(FTSDataColumnPreferences newPrefs)
1726 data.setDocFieldPrefs(newPrefs);
1732 * @return true when all initialisation threads have finished and dialog is
1735 public boolean isDialogVisible()
1737 return mainFrame != null && data != null && cmb_filterOption != null
1738 && mainFrame.isVisible()
1739 && cmb_filterOption.getSelectedItem() != null;
1744 * @return true if the 3D-Beacons query button will/has been displayed
1746 public boolean isCanQueryTDB()
1751 public boolean isNotQueriedTDBYet()
1753 return notQueriedTDBYet;
1757 * Open a single structure file for a given sequence
1759 public static void openStructureFileForSequence(
1760 StructureSelectionManager ssm, StructureChooser sc,
1761 AlignmentPanel ap, SequenceI seq, boolean prompt,
1762 String sFilename, TFType tft, String paeFilename,
1763 boolean doXferSettings)
1765 openStructureFileForSequence(ssm, sc, ap, seq, prompt, sFilename, tft,
1766 paeFilename, false, true, doXferSettings, null);
1769 public static StructureViewer openStructureFileForSequence(
1770 StructureSelectionManager ssm, StructureChooser sc,
1771 AlignmentPanel ap, SequenceI seq, boolean prompt,
1772 String sFilename, TFType tft, String paeFilename,
1773 boolean forceHeadless, boolean showRefAnnotations,
1774 boolean doXferSettings, ViewerType viewerType)
1776 StructureViewer sv = null;
1777 boolean headless = forceHeadless;
1782 sc = new StructureChooser(new SequenceI[] { seq }, seq, ap, false);
1786 ssm = ap.getStructureSelectionManager();
1789 PDBEntry fileEntry = new AssociatePdbFileWithSeq().associatePdbWithSeq(
1790 sFilename, DataSourceType.FILE, seq, prompt, Desktop.instance,
1791 tft, paeFilename, doXferSettings);
1793 // if headless, "false" in the sc constructor above will avoid GUI behaviour
1794 // in sc.launchStructureViewer()
1795 if (!headless && !(viewerType == null))
1797 sv = sc.launchStructureViewer(ssm, new PDBEntry[] { fileEntry }, ap,
1799 { seq }, viewerType);
1802 sc.mainFrame.dispose();
1804 if (showRefAnnotations)
1805 showReferenceAnnotationsForSequence(ap.alignFrame, seq);
1810 public static void showReferenceAnnotationsForSequence(AlignFrame af,
1813 AlignViewport av = af.getCurrentView();
1814 AlignmentI al = av.getAlignment();
1816 List<SequenceI> forSequences = new ArrayList<>();
1817 forSequences.add(sequence);
1818 final Map<SequenceI, List<AlignmentAnnotation>> candidates = new LinkedHashMap<>();
1819 AlignmentUtils.findAddableReferenceAnnotations(forSequences, null,
1821 final SequenceGroup selectionGroup = av.getSelectionGroup();
1822 AlignmentUtils.addReferenceAnnotations(candidates, al, selectionGroup);
1823 for (AlignmentViewPanel ap : af.getAlignPanels())
1825 // required to readjust the height and position of the PAE
1827 ap.adjustAnnotationHeight();
1833 public JProgressBar getProgressBar(long id)
1835 return progressBar.getProgressBar(id);