2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
24 import java.awt.event.ActionEvent;
25 import java.awt.event.ActionListener;
26 import java.awt.event.ItemEvent;
28 import java.util.ArrayList;
29 import java.util.Collection;
30 import java.util.HashSet;
31 import java.util.LinkedHashMap;
32 import java.util.LinkedHashSet;
33 import java.util.List;
34 import java.util.Locale;
36 import java.util.concurrent.Executors;
38 import javax.swing.JCheckBox;
39 import javax.swing.JComboBox;
40 import javax.swing.JLabel;
41 import javax.swing.JMenuItem;
42 import javax.swing.JPopupMenu;
43 import javax.swing.JTable;
44 import javax.swing.SwingUtilities;
45 import javax.swing.table.AbstractTableModel;
47 import com.stevesoft.pat.Regex;
49 import jalview.analysis.AlignmentUtils;
50 import jalview.api.AlignmentViewPanel;
51 import jalview.api.structures.JalviewStructureDisplayI;
52 import jalview.bin.Cache;
53 import jalview.bin.Console;
54 import jalview.bin.Jalview;
55 import jalview.datamodel.AlignmentAnnotation;
56 import jalview.datamodel.AlignmentI;
57 import jalview.datamodel.PDBEntry;
58 import jalview.datamodel.SequenceGroup;
59 import jalview.datamodel.SequenceI;
60 import jalview.ext.jmol.JmolParser;
61 import jalview.fts.api.FTSData;
62 import jalview.fts.api.FTSDataColumnI;
63 import jalview.fts.api.FTSRestClientI;
64 import jalview.fts.core.FTSDataColumnPreferences;
65 import jalview.fts.core.FTSRestRequest;
66 import jalview.fts.core.FTSRestResponse;
67 import jalview.fts.service.pdb.PDBFTSRestClient;
68 import jalview.fts.service.threedbeacons.TDB_FTSData;
69 import jalview.gui.StructureViewer.ViewerType;
70 import jalview.gui.structurechooser.PDBStructureChooserQuerySource;
71 import jalview.gui.structurechooser.StructureChooserQuerySource;
72 import jalview.gui.structurechooser.ThreeDBStructureChooserQuerySource;
73 import jalview.io.DataSourceType;
74 import jalview.io.JalviewFileChooser;
75 import jalview.io.JalviewFileView;
76 import jalview.jbgui.FilterOption;
77 import jalview.jbgui.GStructureChooser;
78 import jalview.structure.StructureImportSettings.TFType;
79 import jalview.structure.StructureMapping;
80 import jalview.structure.StructureSelectionManager;
81 import jalview.util.MessageManager;
82 import jalview.util.Platform;
83 import jalview.util.StringUtils;
84 import jalview.ws.DBRefFetcher;
85 import jalview.ws.DBRefFetcher.FetchFinishedListenerI;
86 import jalview.ws.datamodel.alphafold.PAEContactMatrix;
87 import jalview.ws.seqfetcher.DbSourceProxy;
88 import jalview.ws.sifts.SiftsSettings;
91 * Provides the behaviors for the Structure chooser Panel
96 @SuppressWarnings("serial")
97 public class StructureChooser extends GStructureChooser
98 implements IProgressIndicator
100 private static final String AUTOSUPERIMPOSE = "AUTOSUPERIMPOSE";
103 * warn user if need to fetch more than this many uniprot records at once
105 private static final int THRESHOLD_WARN_UNIPROT_FETCH_NEEDED = 20;
107 private SequenceI selectedSequence;
109 private SequenceI[] selectedSequences;
111 private IProgressIndicator progressIndicator;
113 private Collection<FTSData> discoveredStructuresSet;
115 private StructureChooserQuerySource data;
118 protected FTSDataColumnPreferences getFTSDocFieldPrefs()
120 return data.getDocFieldPrefs();
123 private String selectedPdbFileName;
125 private TFType localPdbTempfacType;
127 private String localPdbPaeMatrixFileName;
129 private boolean isValidPBDEntry;
131 private boolean cachedPDBExists;
133 private Collection<FTSData> lastDiscoveredStructuresSet;
135 private boolean canQueryTDB = false;
137 private boolean notQueriedTDBYet = true;
139 List<SequenceI> seqsWithoutSourceDBRef = null;
141 private boolean showChooserGUI = true;
143 * when true, queries to external services are supressed (no SIFTs, no PDBe, no 3D-Beacons, etc)
145 private boolean dontQueryServices = false;
147 private static StructureViewer lastTargetedView = null;
149 public StructureChooser(SequenceI[] selectedSeqs, SequenceI selectedSeq,
152 this(selectedSeqs, selectedSeq, ap, true);
155 public StructureChooser(SequenceI[] selectedSeqs, SequenceI selectedSeq,
156 AlignmentPanel ap, boolean showGUI)
158 this(selectedSeqs, selectedSeq, ap, showGUI, false);
161 public StructureChooser(SequenceI[] selectedSeqs, SequenceI selectedSeq,
162 AlignmentPanel ap, boolean showGUI, boolean dontQueryServices)
165 // which FTS engine to use
166 data = StructureChooserQuerySource.getQuerySourceFor(selectedSeqs);
170 this.selectedSequence = selectedSeq;
171 this.selectedSequences = selectedSeqs;
172 this.progressIndicator = (ap == null) ? null : ap.alignFrame;
173 this.showChooserGUI = showGUI;
174 this.dontQueryServices = dontQueryServices;
180 * sets canQueryTDB if protein sequences without a canonical uniprot ref or at
181 * least one structure are discovered.
183 private void populateSeqsWithoutSourceDBRef()
185 seqsWithoutSourceDBRef = new ArrayList<SequenceI>();
186 boolean needCanonical = false;
187 for (SequenceI seq : selectedSequences)
191 int dbRef = ThreeDBStructureChooserQuerySource
192 .checkUniprotRefs(seq.getDBRefs());
197 // need to retrieve canonicals
198 needCanonical = true;
199 seqsWithoutSourceDBRef.add(seq);
203 // could be a sequence with pdb ref
204 if (seq.getAllPDBEntries() == null
205 || seq.getAllPDBEntries().size() == 0)
207 seqsWithoutSourceDBRef.add(seq);
213 // retrieve database refs for protein sequences
214 if (!seqsWithoutSourceDBRef.isEmpty())
219 // triggers display of the 'Query TDB' button
220 notQueriedTDBYet = true;
226 * Initializes parameters used by the Structure Chooser Panel
228 protected void init()
230 if (!Jalview.isHeadlessMode())
232 progressBar = new ProgressBar(this.statusPanel, this.statusBar);
235 chk_superpose.setSelected(Cache.getDefault(AUTOSUPERIMPOSE, true));
236 btn_queryTDB.addActionListener(new ActionListener()
240 public void actionPerformed(ActionEvent e)
242 promptForTDBFetch(false);
246 if (!dontQueryServices)
248 Executors.defaultThreadFactory().newThread(new Runnable()
253 populateSeqsWithoutSourceDBRef();
254 initialStructureDiscovery();
259 Console.debug("Structure chooser not querying services to discover metadata.");
264 private void initialStructureDiscovery()
266 // check which FTS engine to use
267 data = StructureChooserQuerySource.getQuerySourceFor(selectedSequences);
269 // ensure a filter option is in force for search
270 populateFilterComboBox(true, cachedPDBExists);
272 // looks for any existing structures already loaded
273 // for the sequences (the cached ones)
274 // then queries the StructureChooserQuerySource to
275 // discover more structures.
277 // Possible optimisation is to only begin querying
278 // the structure chooser if there are no cached structures.
280 long startTime = System.currentTimeMillis();
281 updateProgressIndicator(
282 MessageManager.getString("status.loading_cached_pdb_entries"),
284 loadLocalCachedPDBEntries();
285 updateProgressIndicator(null, startTime);
286 updateProgressIndicator(
287 MessageManager.getString("status.searching_for_pdb_structures"),
289 fetchStructuresMetaData();
290 // revise filter options if no results were found
291 populateFilterComboBox(isStructuresDiscovered(), cachedPDBExists);
292 discoverStructureViews();
293 updateProgressIndicator(null, startTime);
294 mainFrame.setVisible(showChooserGUI);
299 * raises dialog for Uniprot fetch followed by 3D beacons search
302 * - when true, don't ask, just fetch
304 public void promptForTDBFetch(boolean ignoreGui)
306 final long progressId = System.currentTimeMillis();
308 // final action after prompting and discovering db refs
309 final Runnable strucDiscovery = new Runnable()
314 mainFrame.setEnabled(false);
315 cmb_filterOption.setEnabled(false);
316 progressBar.setProgressBar(
317 MessageManager.getString("status.searching_3d_beacons"),
319 btn_queryTDB.setEnabled(false);
320 // TODO: warn if no accessions discovered
321 populateSeqsWithoutSourceDBRef();
322 // redo initial discovery - this time with 3d beacons
324 previousWantedFields = null;
325 lastSelected = (FilterOption) cmb_filterOption.getSelectedItem();
326 cmb_filterOption.setSelectedItem(null);
327 cachedPDBExists = false; // reset to initial
328 initialStructureDiscovery();
329 if (!isStructuresDiscovered())
331 progressBar.setProgressBar(MessageManager.getString(
332 "status.no_structures_discovered_from_3d_beacons"),
334 btn_queryTDB.setToolTipText(MessageManager.getString(
335 "status.no_structures_discovered_from_3d_beacons"));
336 btn_queryTDB.setEnabled(false);
337 pnl_queryTDB.setVisible(false);
341 cmb_filterOption.setSelectedIndex(0); // select 'best'
342 btn_queryTDB.setVisible(false);
343 pnl_queryTDB.setVisible(false);
344 progressBar.setProgressBar(null, progressId);
346 mainFrame.setEnabled(true);
347 cmb_filterOption.setEnabled(true);
351 final FetchFinishedListenerI afterDbRefFetch = new FetchFinishedListenerI()
355 public void finished()
357 // filter has been selected, so we set flag to remove ourselves
358 notQueriedTDBYet = false;
359 // new thread to discover structures - via 3d beacons
360 Executors.defaultThreadFactory().newThread(strucDiscovery).start();
365 // fetch db refs if OK pressed
366 final Runnable discoverCanonicalDBrefs = () -> {
367 btn_queryTDB.setEnabled(false);
368 populateSeqsWithoutSourceDBRef();
370 final int y = seqsWithoutSourceDBRef.size();
373 final SequenceI[] seqWithoutSrcDBRef = seqsWithoutSourceDBRef
374 .toArray(new SequenceI[y]);
375 DBRefFetcher dbRefFetcher = new DBRefFetcher(seqWithoutSrcDBRef,
376 progressBar, new DbSourceProxy[]
377 { new jalview.ws.dbsources.Uniprot() }, null, false);
378 dbRefFetcher.addListener(afterDbRefFetch);
379 // ideally this would also gracefully run with callbacks
381 dbRefFetcher.fetchDBRefs(true);
385 // call finished action directly
386 afterDbRefFetch.finished();
389 final Runnable revertview = () -> {
390 if (lastSelected != null)
392 cmb_filterOption.setSelectedItem(lastSelected);
395 int threshold = Cache.getDefault("UNIPROT_AUTOFETCH_THRESHOLD",
396 THRESHOLD_WARN_UNIPROT_FETCH_NEEDED);
397 Console.debug("Using Uniprot fetch threshold of " + threshold);
398 if (ignoreGui || seqsWithoutSourceDBRef.size() < threshold)
400 Executors.newSingleThreadExecutor().submit(discoverCanonicalDBrefs);
403 // need cancel and no to result in the discoverPDB action - mocked is
404 // 'cancel' TODO: mock should be OK
406 StructureChooser thisSC = this;
407 JvOptionPane.newOptionDialog(thisSC.getFrame())
408 .setResponseHandler(JvOptionPane.OK_OPTION,
409 discoverCanonicalDBrefs)
410 .setResponseHandler(JvOptionPane.CANCEL_OPTION, revertview)
411 .setResponseHandler(JvOptionPane.NO_OPTION, revertview)
413 MessageManager.formatMessage(
414 "label.fetch_references_for_3dbeacons",
415 seqsWithoutSourceDBRef.size()),
416 MessageManager.getString("label.3dbeacons"),
417 JvOptionPane.YES_NO_OPTION, JvOptionPane.PLAIN_MESSAGE,
419 { MessageManager.getString("action.ok"),
420 MessageManager.getString("action.cancel") },
421 MessageManager.getString("action.ok"), false);
425 * Builds a drop-down choice list of existing structure viewers to which new
426 * structures may be added. If this list is empty then it, and the 'Add'
427 * button, are hidden.
429 private void discoverStructureViews()
431 if (Desktop.instance != null)
433 targetView.removeAllItems();
434 if (lastTargetedView != null && !lastTargetedView.isVisible())
436 lastTargetedView = null;
438 int linkedViewsAt = 0;
439 for (StructureViewerBase view : Desktop.instance
440 .getStructureViewers(null, null))
442 StructureViewer viewHandler = (lastTargetedView != null
443 && lastTargetedView.sview == view) ? lastTargetedView
444 : StructureViewer.reconfigure(view);
446 if (view.isLinkedWith(ap))
448 targetView.insertItemAt(viewHandler, linkedViewsAt++);
452 targetView.addItem(viewHandler);
457 * show option to Add to viewer if at least 1 viewer found
459 targetView.setVisible(false);
460 if (targetView.getItemCount() > 0)
462 targetView.setVisible(true);
463 if (lastTargetedView != null)
465 targetView.setSelectedItem(lastTargetedView);
469 targetView.setSelectedIndex(0);
472 btn_add.setVisible(targetView.isVisible());
477 * Updates the progress indicator with the specified message
480 * displayed message for the operation
482 * unique handle for this indicator
484 protected void updateProgressIndicator(String message, long id)
486 if (progressIndicator != null)
488 progressIndicator.setProgressBar(message, id);
493 * Retrieve meta-data for all the structure(s) for a given sequence(s) in a
496 void fetchStructuresMetaData()
498 long startTime = System.currentTimeMillis();
499 Collection<FTSDataColumnI> wantedFields = data.getDocFieldPrefs()
500 .getStructureSummaryFields();
502 discoveredStructuresSet = new LinkedHashSet<>();
503 HashSet<String> errors = new HashSet<>();
505 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
508 for (SequenceI seq : selectedSequences)
511 FTSRestResponse resultList;
514 resultList = data.fetchStructuresMetaData(seq, wantedFields,
515 selectedFilterOpt, !chk_invertFilter.isSelected());
516 // null response means the FTSengine didn't yield a query for this
517 // consider designing a special exception if we really wanted to be
519 if (resultList == null)
523 } catch (Exception e)
525 Console.printStackTrace(e);
526 errors.add(e.getMessage());
529 if (resultList.getSearchSummary() != null
530 && !resultList.getSearchSummary().isEmpty())
532 discoveredStructuresSet.addAll(resultList.getSearchSummary());
536 int noOfStructuresFound = 0;
537 String totalTime = (System.currentTimeMillis() - startTime)
539 if (discoveredStructuresSet != null
540 && !discoveredStructuresSet.isEmpty())
543 .setModel(data.getTableModel(discoveredStructuresSet));
545 noOfStructuresFound = discoveredStructuresSet.size();
546 lastDiscoveredStructuresSet = discoveredStructuresSet;
547 mainFrame.setTitle(MessageManager.formatMessage(
548 "label.structure_chooser_no_of_structures",
549 noOfStructuresFound, totalTime));
553 mainFrame.setTitle(MessageManager
554 .getString("label.structure_chooser_manual_association"));
555 if (errors.size() > 0)
557 StringBuilder errorMsg = new StringBuilder();
558 for (String error : errors)
560 errorMsg.append(error).append("\n");
562 if (!Jalview.isHeadlessMode())
564 JvOptionPane.showMessageDialog(this, errorMsg.toString(),
565 MessageManager.getString("label.pdb_web-service_error"),
566 JvOptionPane.ERROR_MESSAGE);
571 MessageManager.getString("label.pdb_web-service_error"));
572 Console.debug(errorMsg.toString());
578 protected void loadLocalCachedPDBEntries()
580 ArrayList<CachedPDB> entries = new ArrayList<>();
581 for (SequenceI seq : selectedSequences)
583 if (seq.getDatasetSequence() != null
584 && seq.getDatasetSequence().getAllPDBEntries() != null)
586 for (PDBEntry pdbEntry : seq.getDatasetSequence()
589 if (pdbEntry.getFile() != null)
591 entries.add(new CachedPDB(seq, pdbEntry));
596 cachedPDBExists = !entries.isEmpty();
597 PDBEntryTableModel tableModelx = new PDBEntryTableModel(entries);
598 tbl_local_pdb.setModel(tableModelx);
602 * Filters a given list of discovered structures based on supplied argument
604 * @param fieldToFilterBy
605 * the field to filter by
607 void filterResultSet(final String fieldToFilterBy)
609 Thread filterThread = new Thread(new Runnable()
615 long startTime = System.currentTimeMillis();
616 lbl_loading.setVisible(true);
617 Collection<FTSDataColumnI> wantedFields = data.getDocFieldPrefs()
618 .getStructureSummaryFields();
619 Collection<FTSData> filteredResponse = new HashSet<>();
620 HashSet<String> errors = new HashSet<>();
622 for (SequenceI seq : selectedSequences)
625 FTSRestResponse resultList;
628 resultList = data.selectFirstRankedQuery(seq,
629 discoveredStructuresSet, wantedFields, fieldToFilterBy,
630 !chk_invertFilter.isSelected());
632 } catch (Exception e)
634 Console.debugPrintStackTrace(e);
635 errors.add(e.getMessage());
638 if (resultList.getSearchSummary() != null
639 && !resultList.getSearchSummary().isEmpty())
641 filteredResponse.addAll(resultList.getSearchSummary());
645 String totalTime = (System.currentTimeMillis() - startTime)
647 if (!filteredResponse.isEmpty())
649 final int filterResponseCount = filteredResponse.size();
650 Collection<FTSData> reorderedStructuresSet = new LinkedHashSet<>();
651 reorderedStructuresSet.addAll(filteredResponse);
652 reorderedStructuresSet.addAll(discoveredStructuresSet);
654 .setModel(data.getTableModel(reorderedStructuresSet));
656 FTSRestResponse.configureTableColumn(getResultTable(),
657 wantedFields, tempUserPrefs);
658 getResultTable().getColumn("Ref Sequence").setPreferredWidth(120);
659 getResultTable().getColumn("Ref Sequence").setMinWidth(100);
660 getResultTable().getColumn("Ref Sequence").setMaxWidth(200);
661 // Update table selection model here
662 getResultTable().addRowSelectionInterval(0,
663 filterResponseCount - 1);
664 mainFrame.setTitle(MessageManager.formatMessage(
665 "label.structure_chooser_filter_time", totalTime));
669 mainFrame.setTitle(MessageManager.formatMessage(
670 "label.structure_chooser_filter_time", totalTime));
671 if (errors.size() > 0)
673 StringBuilder errorMsg = new StringBuilder();
674 for (String error : errors)
676 errorMsg.append(error).append("\n");
678 JvOptionPane.showMessageDialog(null, errorMsg.toString(),
679 MessageManager.getString("label.pdb_web-service_error"),
680 JvOptionPane.ERROR_MESSAGE);
684 lbl_loading.setVisible(false);
686 validateSelections();
689 filterThread.start();
693 * Handles action event for btn_pdbFromFile
696 protected void pdbFromFile_actionPerformed()
698 // TODO: JAL-3048 not needed for Jalview-JS until JSmol dep and
701 JalviewFileChooser chooser = new JalviewFileChooser(
702 Cache.getProperty("LAST_DIRECTORY"));
703 chooser.setFileView(new JalviewFileView());
704 chooser.setDialogTitle(
705 MessageManager.formatMessage("label.select_pdb_file_for",
706 selectedSequence.getDisplayId(false)));
707 chooser.setToolTipText(MessageManager.formatMessage(
708 "label.load_pdb_file_associate_with_sequence",
709 selectedSequence.getDisplayId(false)));
711 int value = chooser.showOpenDialog(null);
712 if (value == JalviewFileChooser.APPROVE_OPTION)
714 selectedPdbFileName = chooser.getSelectedFile().getPath();
715 Cache.setProperty("LAST_DIRECTORY", selectedPdbFileName);
716 boolean guessTFType = localPdbPaeMatrixFileName == null;
717 localPdbPaeMatrixFileName = guessPAEFilename();
718 guessTFType |= localPdbPaeMatrixFileName != null;
719 Regex alphaFold = JmolParser.getNewAlphafoldValidator();
721 && alphaFold.search(new File(selectedPdbFileName).getName())
722 && !tempFacAsChanged)
724 // localPdbPaeMatrixFileName was null and now isn't and filename could
725 // well be AlphaFold and user hasn't adjusted the tempFacType
726 combo_tempFacAs.setSelectedItem(TFType.PLDDT);
728 validateSelections();
733 * Handles action event for btn_paeMatrixFile
736 protected void paeMatrixFile_actionPerformed()
738 File pdbFile = new File(selectedPdbFileName);
739 String setFile = Cache.getProperty("LAST_DIRECTORY");
740 if (localPdbPaeMatrixFileName != null)
742 File paeFile = new File(localPdbPaeMatrixFileName);
743 if (paeFile.exists())
744 setFile = paeFile.getAbsolutePath();
745 else if (paeFile.getParentFile().exists())
746 setFile = paeFile.getParentFile().getAbsolutePath();
750 String guess = guessPAEFilename();
754 JalviewFileChooser chooser = new JalviewFileChooser(setFile);
755 chooser.setFileView(new JalviewFileView());
756 chooser.setDialogTitle(MessageManager.formatMessage(
757 "label.select_pae_matrix_file_for", pdbFile.getName()));
758 chooser.setToolTipText(MessageManager.formatMessage(
759 "label.load_pae_matrix_file_associate_with_structure",
762 // TODO convert to Callable/Promise
763 int value = chooser.showOpenDialog(null);
764 if (value == JalviewFileChooser.APPROVE_OPTION)
766 String fileName = chooser.getSelectedFile().getPath();
769 PAEContactMatrix.validateContactMatrixFile(fileName);
770 } catch (Exception thr)
772 JvOptionPane.showInternalMessageDialog(this, MessageManager
773 .formatMessage("label.couldnt_load_file", new Object[]
774 { fileName }) + "<br>" + thr.getLocalizedMessage(),
775 MessageManager.getString("label.error_loading_file"),
776 JvOptionPane.WARNING_MESSAGE);
777 Console.error("Couldn't import " + fileName + " as a PAE matrix",
781 localPdbPaeMatrixFileName = fileName;
782 Cache.setProperty("LAST_DIRECTORY", localPdbPaeMatrixFileName);
784 validateAssociationFromFile();
787 private String guessPAEFilename()
789 if (selectedPdbFileName.toLowerCase(Locale.ROOT).endsWith(".pdb")
790 || selectedPdbFileName.toLowerCase(Locale.ROOT)
793 String jsonExt = selectedPdbFileName.substring(0,
794 selectedPdbFileName.length() - 4) + ".json";
795 // AlphaFold naming scheme
796 String guessFile1 = StringUtils.replaceLast(jsonExt, "model",
797 "predicted_aligned_error");
798 // nf-core mode naming scheme
799 String guessFile2 = StringUtils.replaceLast(jsonExt, ".json",
801 if (new File(guessFile1).exists())
805 else if (new File(jsonExt).exists())
809 else if (new File(guessFile2).exists())
818 * Populates the filter combo-box options dynamically depending on discovered
821 protected void populateFilterComboBox(boolean haveData,
822 boolean cachedPDBExist)
824 populateFilterComboBox(haveData, cachedPDBExist, null);
828 * Populates the filter combo-box options dynamically depending on discovered
831 protected void populateFilterComboBox(boolean haveData,
832 boolean cachedPDBExist, FilterOption lastSel)
836 * temporarily suspend the change listener behaviour
838 cmb_filterOption.removeItemListener(this);
840 cmb_filterOption.removeAllItems();
843 List<FilterOption> filters = data
844 .getAvailableFilterOptions(VIEWS_FILTER);
845 data.updateAvailableFilterOptions(VIEWS_FILTER, filters,
846 lastDiscoveredStructuresSet);
848 for (FilterOption filter : filters)
850 if (lastSel != null && filter.equals(lastSel))
855 cmb_filterOption.addItem(filter);
859 cmb_filterOption.addItem(
860 new FilterOption(MessageManager.getString("label.enter_pdb_id"),
861 "-", VIEWS_ENTER_ID, false, null));
862 cmb_filterOption.addItem(
863 new FilterOption(MessageManager.getString("label.from_file"),
864 "-", VIEWS_FROM_FILE, false, null));
865 if (canQueryTDB && notQueriedTDBYet)
867 btn_queryTDB.setVisible(true);
868 pnl_queryTDB.setVisible(true);
873 FilterOption cachedOption = new FilterOption(
874 MessageManager.getString("label.cached_structures"), "-",
875 VIEWS_LOCAL_PDB, false, null);
876 cmb_filterOption.addItem(cachedOption);
879 cmb_filterOption.setSelectedItem(cachedOption);
884 cmb_filterOption.setSelectedIndex(selSet);
886 cmb_filterOption.addItemListener(this);
890 * Updates the displayed view based on the selected filter option
892 protected void updateCurrentView()
894 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
897 if (lastSelected == selectedFilterOpt)
899 // don't need to do anything, probably
902 // otherwise, record selection
903 // and update the layout and dialog accordingly
904 lastSelected = selectedFilterOpt;
906 layout_switchableViews.show(pnl_switchableViews,
907 selectedFilterOpt.getView());
908 String filterTitle = mainFrame.getTitle();
909 mainFrame.setTitle(frameTitle);
910 chk_invertFilter.setVisible(false);
912 if (selectedFilterOpt.getView() == VIEWS_FILTER)
914 mainFrame.setTitle(filterTitle);
915 // TDB Query has no invert as yet
916 chk_invertFilter.setVisible(selectedFilterOpt
917 .getQuerySource() instanceof PDBStructureChooserQuerySource);
919 if (data != selectedFilterOpt.getQuerySource()
920 || data.needsRefetch(selectedFilterOpt))
922 data = selectedFilterOpt.getQuerySource();
923 // rebuild the views completely, since prefs will also change
929 filterResultSet(selectedFilterOpt.getValue());
932 else if (selectedFilterOpt.getView() == VIEWS_ENTER_ID
933 || selectedFilterOpt.getView() == VIEWS_FROM_FILE)
935 mainFrame.setTitle(MessageManager
936 .getString("label.structure_chooser_manual_association"));
937 idInputAssSeqPanel.loadCmbAssSeq();
938 fileChooserAssSeqPanel.loadCmbAssSeq();
940 validateSelections();
944 * Validates user selection and enables the 'Add' and 'New View' buttons if
945 * all parameters are correct (the Add button will only be visible if there is
946 * at least one existing structure viewer open). This basically means at least
947 * one structure selected and no error messages.
949 * The 'Superpose Structures' option is enabled if either more than one
950 * structure is selected, or the 'Add' to existing view option is enabled, and
951 * disabled if the only option is to open a new view of a single structure.
954 protected void validateSelections()
956 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
958 btn_add.setEnabled(false);
959 String currentView = selectedFilterOpt.getView();
960 int selectedCount = 0;
961 if (currentView == VIEWS_FILTER)
963 selectedCount = getResultTable().getSelectedRows().length;
964 if (selectedCount > 0)
966 btn_add.setEnabled(true);
969 else if (currentView == VIEWS_LOCAL_PDB)
971 selectedCount = tbl_local_pdb.getSelectedRows().length;
972 if (selectedCount > 0)
974 btn_add.setEnabled(true);
977 else if (currentView == VIEWS_ENTER_ID)
979 validateAssociationEnterPdb();
981 else if (currentView == VIEWS_FROM_FILE)
983 validateAssociationFromFile();
986 btn_newView.setEnabled(btn_add.isEnabled());
989 * enable 'Superpose' option if more than one structure is selected,
990 * or there are view(s) available to add structure(s) to
993 .setEnabled(selectedCount > 1 || targetView.getItemCount() > 0);
997 protected boolean showPopupFor(int selectedRow, int x, int y)
999 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
1000 .getSelectedItem());
1001 String currentView = selectedFilterOpt.getView();
1003 if (currentView == VIEWS_FILTER
1004 && data instanceof ThreeDBStructureChooserQuerySource)
1007 TDB_FTSData row = ((ThreeDBStructureChooserQuerySource) data)
1008 .getFTSDataFor(getResultTable(), selectedRow,
1009 discoveredStructuresSet);
1010 String pageUrl = row.getModelViewUrl();
1011 JPopupMenu popup = new JPopupMenu("3D Beacons");
1012 JMenuItem viewUrl = new JMenuItem("View model web page");
1013 viewUrl.addActionListener(new ActionListener()
1016 public void actionPerformed(ActionEvent e)
1018 Desktop.showUrl(pageUrl);
1022 SwingUtilities.invokeLater(new Runnable()
1027 popup.show(getResultTable(), x, y);
1032 // event not handled by us
1037 * Validates inputs from the Manual PDB entry panel
1039 protected void validateAssociationEnterPdb()
1041 AssociateSeqOptions assSeqOpt = (AssociateSeqOptions) idInputAssSeqPanel
1042 .getCmb_assSeq().getSelectedItem();
1043 lbl_pdbManualFetchStatus.setIcon(errorImage);
1044 lbl_pdbManualFetchStatus.setToolTipText("");
1045 if (txt_search.getText().length() > 0)
1047 lbl_pdbManualFetchStatus.setToolTipText(JvSwingUtils.wrapTooltip(true,
1048 MessageManager.formatMessage("info.no_pdb_entry_found_for",
1049 txt_search.getText())));
1052 if (errorWarning.length() > 0)
1054 lbl_pdbManualFetchStatus.setIcon(warningImage);
1055 lbl_pdbManualFetchStatus.setToolTipText(
1056 JvSwingUtils.wrapTooltip(true, errorWarning.toString()));
1059 if (selectedSequences.length == 1 || !assSeqOpt.getName()
1060 .equalsIgnoreCase("-Select Associated Seq-"))
1062 txt_search.setEnabled(true);
1063 if (isValidPBDEntry)
1065 btn_add.setEnabled(true);
1066 lbl_pdbManualFetchStatus.setToolTipText("");
1067 lbl_pdbManualFetchStatus.setIcon(goodImage);
1072 txt_search.setEnabled(false);
1073 lbl_pdbManualFetchStatus.setIcon(errorImage);
1078 * Validates inputs for the manual PDB file selection options
1080 protected void validateAssociationFromFile()
1082 AssociateSeqOptions assSeqOpt = (AssociateSeqOptions) fileChooserAssSeqPanel
1083 .getCmb_assSeq().getSelectedItem();
1084 // lbl_fromFileStatus.setIcon(errorImage);
1085 String pdbFileString = "";
1086 String pdbFileTooltip = "";
1087 if (selectedSequences.length == 1 || (assSeqOpt != null && !assSeqOpt
1088 .getName().equalsIgnoreCase("-Select Associated Seq-")))
1090 btn_pdbFromFile.setEnabled(true);
1091 if (selectedPdbFileName != null && selectedPdbFileName.length() > 0)
1093 btn_add.setEnabled(true);
1094 // lbl_fromFileStatus.setIcon(goodImage);
1095 pdbFileString = new File(selectedPdbFileName).getName();
1096 pdbFileTooltip = new File(selectedPdbFileName).getAbsolutePath();
1097 setPdbOptionsEnabled(true);
1101 pdbFileString = MessageManager.getString("label.none");
1102 pdbFileTooltip = MessageManager.getString("label.nothing_selected");
1103 setPdbOptionsEnabled(false);
1108 btn_pdbFromFile.setEnabled(false);
1109 setPdbOptionsEnabled(false);
1110 // lbl_fromFileStatus.setIcon(errorImage);
1111 pdbFileString = MessageManager.getString("label.none");
1112 pdbFileTooltip = MessageManager.getString("label.nothing_selected");
1114 lbl_pdbFile.setText(pdbFileString);
1115 lbl_pdbFile.setToolTipText(pdbFileTooltip);
1118 String paeFileString = "";
1119 String paeFileTooltip = "";
1120 if (localPdbPaeMatrixFileName != null
1121 && localPdbPaeMatrixFileName.length() > 0)
1123 paeFileString = new File(localPdbPaeMatrixFileName).getName();
1124 paeFileTooltip = new File(localPdbPaeMatrixFileName)
1129 paeFileString = MessageManager.getString("label.none");
1130 paeFileTooltip = MessageManager.getString("label.nothing_selected");
1132 lbl_paeFile.setText(paeFileString);
1133 lbl_paeFile.setToolTipText(paeFileTooltip);
1137 protected void cmbAssSeqStateChanged()
1139 validateSelections();
1142 private FilterOption lastSelected = null;
1145 * Handles the state change event for the 'filter' combo-box and 'invert'
1149 protected void stateChanged(ItemEvent e)
1151 if (e.getSource() instanceof JCheckBox)
1153 updateCurrentView();
1157 if (e.getStateChange() == ItemEvent.SELECTED)
1159 updateCurrentView();
1166 * select structures for viewing by their PDB IDs
1169 * @return true if structures were found and marked as selected
1171 public boolean selectStructure(String... pdbids)
1173 boolean found = false;
1175 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
1176 .getSelectedItem());
1177 String currentView = selectedFilterOpt.getView();
1178 JTable restable = (currentView == VIEWS_FILTER) ? getResultTable()
1179 : (currentView == VIEWS_LOCAL_PDB) ? tbl_local_pdb : null;
1181 if (restable == null)
1183 // can't select (enter PDB ID, or load file - need to also select which
1184 // sequence to associate with)
1188 int pdbIdColIndex = restable.getColumn("PDB Id").getModelIndex();
1189 for (int r = 0; r < restable.getRowCount(); r++)
1191 for (int p = 0; p < pdbids.length; p++)
1193 if (String.valueOf(restable.getValueAt(r, pdbIdColIndex))
1194 .equalsIgnoreCase(pdbids[p]))
1196 restable.setRowSelectionInterval(r, r);
1205 * Handles the 'New View' action
1208 protected void newView_ActionPerformed()
1210 targetView.setSelectedItem(null);
1211 showStructures(false);
1215 * Handles the 'Add to existing viewer' action
1218 protected void add_ActionPerformed()
1220 showStructures(false);
1224 * structure viewer opened by this dialog, or null
1226 private StructureViewer sViewer = null;
1228 public void showStructures(boolean waitUntilFinished)
1231 final StructureSelectionManager ssm = ap.getStructureSelectionManager();
1233 final int preferredHeight = pnl_filter.getHeight();
1234 btn_add.setEnabled(false);
1235 btn_newView.setEnabled(false);
1236 btn_cancel.setEnabled(false);
1237 actionsPanel.setEnabled(false);
1239 final String progress = MessageManager
1240 .getString("label.working_ellipsis");
1241 setProgressBar(progress, progress.hashCode());
1242 Runnable viewStruc = new Runnable()
1247 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
1248 .getSelectedItem());
1249 String currentView = selectedFilterOpt.getView();
1250 JTable restable = (currentView == VIEWS_FILTER) ? getResultTable()
1253 if (currentView == VIEWS_FILTER)
1255 int[] selectedRows = restable.getSelectedRows();
1256 PDBEntry[] pdbEntriesToView = new PDBEntry[selectedRows.length];
1257 List<SequenceI> selectedSeqsToView = new ArrayList<>();
1258 pdbEntriesToView = data.collectSelectedRows(restable,
1259 selectedRows, selectedSeqsToView);
1261 SequenceI[] selectedSeqs = selectedSeqsToView
1262 .toArray(new SequenceI[selectedSeqsToView.size()]);
1263 sViewer = launchStructureViewer(ssm, pdbEntriesToView, ap,
1266 else if (currentView == VIEWS_LOCAL_PDB)
1268 int[] selectedRows = tbl_local_pdb.getSelectedRows();
1269 PDBEntry[] pdbEntriesToView = new PDBEntry[selectedRows.length];
1271 int pdbIdColIndex = tbl_local_pdb.getColumn("PDB Id")
1273 int refSeqColIndex = tbl_local_pdb.getColumn("Ref Sequence")
1275 List<SequenceI> selectedSeqsToView = new ArrayList<>();
1276 for (int row : selectedRows)
1278 PDBEntry pdbEntry = ((PDBEntryTableModel) tbl_local_pdb
1279 .getModel()).getPDBEntryAt(row).getPdbEntry();
1281 pdbEntriesToView[count++] = pdbEntry;
1282 SequenceI selectedSeq = (SequenceI) tbl_local_pdb
1283 .getValueAt(row, refSeqColIndex);
1284 selectedSeqsToView.add(selectedSeq);
1286 SequenceI[] selectedSeqs = selectedSeqsToView
1287 .toArray(new SequenceI[selectedSeqsToView.size()]);
1288 sViewer = launchStructureViewer(ssm, pdbEntriesToView, ap,
1291 else if (currentView == VIEWS_ENTER_ID)
1293 SequenceI userSelectedSeq = ((AssociateSeqOptions) idInputAssSeqPanel
1294 .getCmb_assSeq().getSelectedItem()).getSequence();
1295 if (userSelectedSeq != null)
1297 selectedSequence = userSelectedSeq;
1299 String pdbIdStr = txt_search.getText();
1300 PDBEntry pdbEntry = selectedSequence.getPDBEntry(pdbIdStr);
1301 if (pdbEntry == null)
1303 pdbEntry = new PDBEntry();
1304 if (pdbIdStr.split(":").length > 1)
1306 pdbEntry.setId(pdbIdStr.split(":")[0]);
1307 pdbEntry.setChainCode(
1308 pdbIdStr.split(":")[1].toUpperCase(Locale.ROOT));
1312 pdbEntry.setId(pdbIdStr);
1314 pdbEntry.setType(PDBEntry.Type.PDB);
1315 selectedSequence.getDatasetSequence().addPDBId(pdbEntry);
1318 PDBEntry[] pdbEntriesToView = new PDBEntry[] { pdbEntry };
1319 sViewer = launchStructureViewer(ssm, pdbEntriesToView, ap,
1321 { selectedSequence });
1323 else if (currentView == VIEWS_FROM_FILE)
1325 StructureChooser sc = StructureChooser.this;
1326 TFType tft = (TFType) sc.combo_tempFacAs.getSelectedItem();
1327 String paeFilename = sc.localPdbPaeMatrixFileName;
1328 AssociateSeqOptions assSeqOpt = (AssociateSeqOptions) fileChooserAssSeqPanel
1329 .getCmb_assSeq().getSelectedItem();
1330 SequenceI userSelectedSeq = assSeqOpt.getSequence();
1331 if (userSelectedSeq != null)
1333 selectedSequence = userSelectedSeq;
1335 String pdbFilename = selectedPdbFileName;
1337 StructureChooser.openStructureFileForSequence(ssm, sc, ap,
1338 selectedSequence, true, pdbFilename, tft, paeFilename,
1341 SwingUtilities.invokeLater(new Runnable()
1346 setProgressBar("Complete.", progress.hashCode());
1347 closeAction(preferredHeight);
1348 mainFrame.dispose();
1353 Thread runner = new Thread(viewStruc);
1355 if (waitUntilFinished)
1357 while (sViewer == null ? runner.isAlive()
1358 : (sViewer.sview == null ? true
1359 : !sViewer.sview.hasMapping()))
1364 } catch (InterruptedException ie)
1373 * Answers a structure viewer (new or existing) configured to superimpose
1374 * added structures or not according to the user's choice
1379 StructureViewer getTargetedStructureViewer(StructureSelectionManager ssm)
1381 Object sv = targetView.getSelectedItem();
1383 return sv == null ? new StructureViewer(ssm) : (StructureViewer) sv;
1387 * Adds PDB structures to a new or existing structure viewer
1390 * @param pdbEntriesToView
1395 private StructureViewer launchStructureViewer(
1396 StructureSelectionManager ssm, final PDBEntry[] pdbEntriesToView,
1397 final AlignmentPanel alignPanel, SequenceI[] sequences)
1399 return launchStructureViewer(ssm, pdbEntriesToView, alignPanel,
1403 private StructureViewer launchStructureViewer(
1404 StructureSelectionManager ssm, final PDBEntry[] pdbEntriesToView,
1405 final AlignmentPanel alignPanel, SequenceI[] sequences,
1406 ViewerType viewerType)
1408 long progressId = sequences.hashCode();
1409 setProgressBar(MessageManager
1410 .getString("status.launching_3d_structure_viewer"), progressId);
1411 final StructureViewer theViewer = getTargetedStructureViewer(ssm);
1412 boolean superimpose = chk_superpose.isSelected();
1413 theViewer.setSuperpose(superimpose);
1415 // if we're running in --headless mode make this viewer synchronous
1416 if (Jalview.isHeadlessMode())
1418 theViewer.setAsync(false);
1422 * remember user's choice of superimpose or not
1424 Cache.setProperty(AUTOSUPERIMPOSE,
1425 Boolean.valueOf(superimpose).toString());
1427 setProgressBar(null, progressId);
1428 if (SiftsSettings.isMapWithSifts())
1430 List<SequenceI> seqsWithoutSourceDBRef = new ArrayList<>();
1432 // TODO: skip PDBEntry:Sequence pairs where PDBEntry doesn't look like a
1433 // real PDB ID. For moment, we can also safely do this if there is already
1434 // a known mapping between the PDBEntry and the sequence.
1435 for (SequenceI seq : sequences)
1437 PDBEntry pdbe = pdbEntriesToView[p++];
1438 if (pdbe != null && pdbe.getFile() != null)
1440 StructureMapping[] smm = ssm.getMapping(pdbe.getFile());
1441 if (smm != null && smm.length > 0)
1443 for (StructureMapping sm : smm)
1445 if (sm.getSequence() == seq)
1452 if (seq.getPrimaryDBRefs().isEmpty())
1454 seqsWithoutSourceDBRef.add(seq);
1458 if (!seqsWithoutSourceDBRef.isEmpty())
1460 int y = seqsWithoutSourceDBRef.size();
1461 setProgressBar(MessageManager.formatMessage(
1462 "status.fetching_dbrefs_for_sequences_without_valid_refs",
1464 SequenceI[] seqWithoutSrcDBRef = seqsWithoutSourceDBRef
1465 .toArray(new SequenceI[y]);
1466 DBRefFetcher dbRefFetcher = new DBRefFetcher(seqWithoutSrcDBRef);
1467 dbRefFetcher.fetchDBRefs(true);
1469 setProgressBar("Fetch complete.", progressId); // todo i18n
1472 if (pdbEntriesToView.length > 1)
1475 MessageManager.getString(
1476 "status.fetching_3d_structures_for_selected_entries"),
1478 theViewer.viewStructures(pdbEntriesToView, sequences, alignPanel,
1483 setProgressBar(MessageManager.formatMessage(
1484 "status.fetching_3d_structures_for",
1485 pdbEntriesToView[0].getId()), progressId);
1486 // Can we pass a pre-computeMappinged pdbFile?
1487 theViewer.viewStructures(pdbEntriesToView[0], sequences, alignPanel,
1490 setProgressBar(null, progressId);
1491 // remember the last viewer we used...
1492 lastTargetedView = theViewer;
1497 * Populates the combo-box used in associating manually fetched structures to
1498 * a unique sequence when more than one sequence selection is made.
1501 protected void populateCmbAssociateSeqOptions(
1502 JComboBox<AssociateSeqOptions> cmb_assSeq,
1503 JLabel lbl_associateSeq)
1505 cmb_assSeq.removeAllItems();
1507 new AssociateSeqOptions("-Select Associated Seq-", null));
1508 lbl_associateSeq.setVisible(false);
1509 if (selectedSequences.length > 1)
1511 for (SequenceI seq : selectedSequences)
1513 cmb_assSeq.addItem(new AssociateSeqOptions(seq));
1518 String seqName = selectedSequence.getDisplayId(false);
1519 seqName = seqName.length() <= 40 ? seqName : seqName.substring(0, 39);
1520 lbl_associateSeq.setText(seqName);
1521 lbl_associateSeq.setVisible(true);
1522 cmb_assSeq.setVisible(false);
1526 protected boolean isStructuresDiscovered()
1528 return discoveredStructuresSet != null
1529 && !discoveredStructuresSet.isEmpty();
1532 protected int PDB_ID_MIN = 3;// or: (Jalview.isJS() ? 3 : 1); // Bob proposes
1534 // Doing a search for "1" or "1c" is valuable?
1535 // Those work but are enormously slow.
1538 protected void txt_search_ActionPerformed()
1540 String text = txt_search.getText().trim();
1541 if (text.length() >= PDB_ID_MIN)
1548 errorWarning.setLength(0);
1549 isValidPBDEntry = false;
1550 if (text.length() > 0)
1552 // TODO move this pdb id search into the PDB specific
1554 // for moment, it will work fine as is because it is self-contained
1555 String searchTerm = text.toLowerCase(Locale.ROOT);
1556 searchTerm = searchTerm.split(":")[0];
1557 // jalview.bin.Console.outPrintln(">>>>> search term : " +
1559 List<FTSDataColumnI> wantedFields = new ArrayList<>();
1560 FTSRestRequest pdbRequest = new FTSRestRequest();
1561 pdbRequest.setAllowEmptySeq(false);
1562 pdbRequest.setResponseSize(1);
1563 pdbRequest.setFieldToSearchBy("(pdb_id:");
1564 pdbRequest.setWantedFields(wantedFields);
1565 pdbRequest.setSearchTerm(searchTerm + ")");
1566 pdbRequest.setAssociatedSequence(selectedSequence);
1567 FTSRestClientI pdbRestClient = PDBFTSRestClient.getInstance();
1568 wantedFields.add(pdbRestClient.getPrimaryKeyColumn());
1569 FTSRestResponse resultList;
1572 resultList = pdbRestClient.executeRequest(pdbRequest);
1573 } catch (Exception e)
1575 errorWarning.append(e.getMessage());
1579 validateSelections();
1581 if (resultList.getSearchSummary() != null
1582 && resultList.getSearchSummary().size() > 0)
1584 isValidPBDEntry = true;
1587 validateSelections();
1593 protected void tabRefresh()
1595 if (selectedSequences != null)
1597 lbl_loading.setVisible(true);
1598 Thread refreshThread = new Thread(new Runnable()
1603 fetchStructuresMetaData();
1604 // populateFilterComboBox(true, cachedPDBExists);
1607 ((FilterOption) cmb_filterOption.getSelectedItem())
1609 lbl_loading.setVisible(false);
1612 refreshThread.start();
1616 public class PDBEntryTableModel extends AbstractTableModel
1618 String[] columns = { "Ref Sequence", "PDB Id", "Chain", "Type",
1621 private List<CachedPDB> pdbEntries;
1623 public PDBEntryTableModel(List<CachedPDB> pdbEntries)
1625 this.pdbEntries = new ArrayList<>(pdbEntries);
1629 public String getColumnName(int columnIndex)
1631 return columns[columnIndex];
1635 public int getRowCount()
1637 return pdbEntries.size();
1641 public int getColumnCount()
1643 return columns.length;
1647 public boolean isCellEditable(int row, int column)
1653 public Object getValueAt(int rowIndex, int columnIndex)
1655 Object value = "??";
1656 CachedPDB entry = pdbEntries.get(rowIndex);
1657 switch (columnIndex)
1660 value = entry.getSequence();
1663 value = entry.getQualifiedId();
1666 value = entry.getPdbEntry().getChainCode() == null ? "_"
1667 : entry.getPdbEntry().getChainCode();
1670 value = entry.getPdbEntry().getType();
1673 value = entry.getPdbEntry().getFile();
1680 public Class<?> getColumnClass(int columnIndex)
1682 return columnIndex == 0 ? SequenceI.class : PDBEntry.class;
1685 public CachedPDB getPDBEntryAt(int row)
1687 return pdbEntries.get(row);
1692 private class CachedPDB
1694 private SequenceI sequence;
1696 private PDBEntry pdbEntry;
1698 public CachedPDB(SequenceI sequence, PDBEntry pdbEntry)
1700 this.sequence = sequence;
1701 this.pdbEntry = pdbEntry;
1704 public String getQualifiedId()
1706 if (pdbEntry.hasProvider())
1708 return pdbEntry.getProvider() + ":" + pdbEntry.getId();
1710 return pdbEntry.toString();
1713 public SequenceI getSequence()
1718 public PDBEntry getPdbEntry()
1725 private IProgressIndicator progressBar;
1728 public void setProgressBar(String message, long id)
1730 if (!Platform.isHeadless() && progressBar != null)
1731 progressBar.setProgressBar(message, id);
1735 public void registerHandler(long id, IProgressIndicatorHandler handler)
1737 if (progressBar != null)
1738 progressBar.registerHandler(id, handler);
1742 public boolean operationInProgress()
1744 return progressBar == null ? false : progressBar.operationInProgress();
1747 public JalviewStructureDisplayI getOpenedStructureViewer()
1749 return sViewer == null ? null : sViewer.sview;
1753 protected void setFTSDocFieldPrefs(FTSDataColumnPreferences newPrefs)
1755 data.setDocFieldPrefs(newPrefs);
1761 * @return true when all initialisation threads have finished and dialog is
1764 public boolean isDialogVisible()
1766 return mainFrame != null && data != null && cmb_filterOption != null
1767 && mainFrame.isVisible()
1768 && cmb_filterOption.getSelectedItem() != null;
1773 * @return true if the 3D-Beacons query button will/has been displayed
1775 public boolean isCanQueryTDB()
1780 public boolean isNotQueriedTDBYet()
1782 return notQueriedTDBYet;
1786 * Open a single structure file for a given sequence
1788 public static void openStructureFileForSequence(
1789 StructureSelectionManager ssm, StructureChooser sc,
1790 AlignmentPanel ap, SequenceI seq, boolean prompt,
1791 String sFilename, TFType tft, String paeFilename,
1792 boolean doXferSettings)
1794 openStructureFileForSequence(ssm, sc, ap, seq, prompt, sFilename, tft,
1795 paeFilename, false, true, doXferSettings, null);
1798 public static StructureViewer openStructureFileForSequence(
1799 StructureSelectionManager ssm, StructureChooser sc,
1800 AlignmentPanel ap, SequenceI seq, boolean prompt,
1801 String sFilename, TFType tft, String paeFilename,
1802 boolean forceHeadless, boolean showRefAnnotations,
1803 boolean doXferSettings, ViewerType viewerType)
1805 StructureViewer sv = null;
1806 boolean headless = forceHeadless;
1811 // suppress structure viewer's external service queries
1812 sc = new StructureChooser(new SequenceI[] { seq }, seq, ap, false,true);
1816 ssm = ap.getStructureSelectionManager();
1819 PDBEntry fileEntry = new AssociatePdbFileWithSeq().associatePdbWithSeq(
1820 sFilename, DataSourceType.FILE, seq, prompt, Desktop.instance,
1821 tft, paeFilename, doXferSettings);
1823 // if headless, "false" in the sc constructor above will avoid GUI behaviour
1824 // in sc.launchStructureViewer()
1825 if (!headless && !(viewerType == null))
1827 sv = sc.launchStructureViewer(ssm, new PDBEntry[] { fileEntry }, ap,
1829 { seq }, viewerType);
1832 sc.mainFrame.dispose();
1834 if (showRefAnnotations)
1836 showReferenceAnnotationsForSequence(ap.alignFrame, seq);
1842 public static void showReferenceAnnotationsForSequence(AlignFrame af,
1845 AlignViewport av = af.getCurrentView();
1846 AlignmentI al = av.getAlignment();
1848 List<SequenceI> forSequences = new ArrayList<>();
1849 forSequences.add(sequence);
1850 final Map<SequenceI, List<AlignmentAnnotation>> candidates = new LinkedHashMap<>();
1851 AlignmentUtils.findAddableReferenceAnnotations(forSequences, null,
1853 final SequenceGroup selectionGroup = av.getSelectionGroup();
1854 AlignmentUtils.addReferenceAnnotations(candidates, al, selectionGroup);
1855 for (AlignmentViewPanel ap : af.getAlignPanels())
1857 // required to readjust the height and position of the PAE
1859 ap.adjustAnnotationHeight();