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();
1012 JPopupMenu popup = new JPopupMenu("3D Beacons");
1013 JMenuItem viewUrl = new JMenuItem("View model web page");
1014 if (pageUrl == null || "".equals(pageUrl.trim())) {
1015 viewUrl.setEnabled(false);
1016 viewUrl.setText("No model page available.");
1018 viewUrl.addActionListener(new ActionListener()
1021 public void actionPerformed(ActionEvent e)
1023 Desktop.showUrl(pageUrl);
1027 SwingUtilities.invokeLater(new Runnable()
1032 popup.show(getResultTable(), x, y);
1037 // event not handled by us
1042 * Validates inputs from the Manual PDB entry panel
1044 protected void validateAssociationEnterPdb()
1046 AssociateSeqOptions assSeqOpt = (AssociateSeqOptions) idInputAssSeqPanel
1047 .getCmb_assSeq().getSelectedItem();
1048 lbl_pdbManualFetchStatus.setIcon(errorImage);
1049 lbl_pdbManualFetchStatus.setToolTipText("");
1050 if (txt_search.getText().length() > 0)
1052 lbl_pdbManualFetchStatus.setToolTipText(JvSwingUtils.wrapTooltip(true,
1053 MessageManager.formatMessage("info.no_pdb_entry_found_for",
1054 txt_search.getText())));
1057 if (errorWarning.length() > 0)
1059 lbl_pdbManualFetchStatus.setIcon(warningImage);
1060 lbl_pdbManualFetchStatus.setToolTipText(
1061 JvSwingUtils.wrapTooltip(true, errorWarning.toString()));
1064 if (selectedSequences.length == 1 || !assSeqOpt.getName()
1065 .equalsIgnoreCase("-Select Associated Seq-"))
1067 txt_search.setEnabled(true);
1068 if (isValidPBDEntry)
1070 btn_add.setEnabled(true);
1071 lbl_pdbManualFetchStatus.setToolTipText("");
1072 lbl_pdbManualFetchStatus.setIcon(goodImage);
1077 txt_search.setEnabled(false);
1078 lbl_pdbManualFetchStatus.setIcon(errorImage);
1083 * Validates inputs for the manual PDB file selection options
1085 protected void validateAssociationFromFile()
1087 AssociateSeqOptions assSeqOpt = (AssociateSeqOptions) fileChooserAssSeqPanel
1088 .getCmb_assSeq().getSelectedItem();
1089 // lbl_fromFileStatus.setIcon(errorImage);
1090 String pdbFileString = "";
1091 String pdbFileTooltip = "";
1092 if (selectedSequences.length == 1 || (assSeqOpt != null && !assSeqOpt
1093 .getName().equalsIgnoreCase("-Select Associated Seq-")))
1095 btn_pdbFromFile.setEnabled(true);
1096 if (selectedPdbFileName != null && selectedPdbFileName.length() > 0)
1098 btn_add.setEnabled(true);
1099 // lbl_fromFileStatus.setIcon(goodImage);
1100 pdbFileString = new File(selectedPdbFileName).getName();
1101 pdbFileTooltip = new File(selectedPdbFileName).getAbsolutePath();
1102 setPdbOptionsEnabled(true);
1106 pdbFileString = MessageManager.getString("label.none");
1107 pdbFileTooltip = MessageManager.getString("label.nothing_selected");
1108 setPdbOptionsEnabled(false);
1113 btn_pdbFromFile.setEnabled(false);
1114 setPdbOptionsEnabled(false);
1115 // lbl_fromFileStatus.setIcon(errorImage);
1116 pdbFileString = MessageManager.getString("label.none");
1117 pdbFileTooltip = MessageManager.getString("label.nothing_selected");
1119 lbl_pdbFile.setText(pdbFileString);
1120 lbl_pdbFile.setToolTipText(pdbFileTooltip);
1123 String paeFileString = "";
1124 String paeFileTooltip = "";
1125 if (localPdbPaeMatrixFileName != null
1126 && localPdbPaeMatrixFileName.length() > 0)
1128 paeFileString = new File(localPdbPaeMatrixFileName).getName();
1129 paeFileTooltip = new File(localPdbPaeMatrixFileName)
1134 paeFileString = MessageManager.getString("label.none");
1135 paeFileTooltip = MessageManager.getString("label.nothing_selected");
1137 lbl_paeFile.setText(paeFileString);
1138 lbl_paeFile.setToolTipText(paeFileTooltip);
1142 protected void cmbAssSeqStateChanged()
1144 validateSelections();
1147 private FilterOption lastSelected = null;
1150 * Handles the state change event for the 'filter' combo-box and 'invert'
1154 protected void stateChanged(ItemEvent e)
1156 if (e.getSource() instanceof JCheckBox)
1158 updateCurrentView();
1162 if (e.getStateChange() == ItemEvent.SELECTED)
1164 updateCurrentView();
1171 * select structures for viewing by their PDB IDs
1174 * @return true if structures were found and marked as selected
1176 public boolean selectStructure(String... pdbids)
1178 boolean found = false;
1180 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
1181 .getSelectedItem());
1182 String currentView = selectedFilterOpt.getView();
1183 JTable restable = (currentView == VIEWS_FILTER) ? getResultTable()
1184 : (currentView == VIEWS_LOCAL_PDB) ? tbl_local_pdb : null;
1186 if (restable == null)
1188 // can't select (enter PDB ID, or load file - need to also select which
1189 // sequence to associate with)
1193 int pdbIdColIndex = restable.getColumn("PDB Id").getModelIndex();
1194 for (int r = 0; r < restable.getRowCount(); r++)
1196 for (int p = 0; p < pdbids.length; p++)
1198 if (String.valueOf(restable.getValueAt(r, pdbIdColIndex))
1199 .equalsIgnoreCase(pdbids[p]))
1201 restable.setRowSelectionInterval(r, r);
1210 * Handles the 'New View' action
1213 protected void newView_ActionPerformed()
1215 targetView.setSelectedItem(null);
1216 showStructures(false);
1220 * Handles the 'Add to existing viewer' action
1223 protected void add_ActionPerformed()
1225 showStructures(false);
1229 * structure viewer opened by this dialog, or null
1231 private StructureViewer sViewer = null;
1233 public void showStructures(boolean waitUntilFinished)
1236 final StructureSelectionManager ssm = ap.getStructureSelectionManager();
1238 final int preferredHeight = pnl_filter.getHeight();
1239 btn_add.setEnabled(false);
1240 btn_newView.setEnabled(false);
1241 btn_cancel.setEnabled(false);
1242 actionsPanel.setEnabled(false);
1244 final String progress = MessageManager
1245 .getString("label.working_ellipsis");
1246 setProgressBar(progress, progress.hashCode());
1247 Runnable viewStruc = new Runnable()
1252 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
1253 .getSelectedItem());
1254 String currentView = selectedFilterOpt.getView();
1255 JTable restable = (currentView == VIEWS_FILTER) ? getResultTable()
1258 if (currentView == VIEWS_FILTER)
1260 int[] selectedRows = restable.getSelectedRows();
1261 PDBEntry[] pdbEntriesToView = new PDBEntry[selectedRows.length];
1262 List<SequenceI> selectedSeqsToView = new ArrayList<>();
1263 pdbEntriesToView = data.collectSelectedRows(restable,
1264 selectedRows, selectedSeqsToView);
1266 SequenceI[] selectedSeqs = selectedSeqsToView
1267 .toArray(new SequenceI[selectedSeqsToView.size()]);
1268 sViewer = launchStructureViewer(ssm, pdbEntriesToView, ap,
1271 else if (currentView == VIEWS_LOCAL_PDB)
1273 int[] selectedRows = tbl_local_pdb.getSelectedRows();
1274 PDBEntry[] pdbEntriesToView = new PDBEntry[selectedRows.length];
1276 int pdbIdColIndex = tbl_local_pdb.getColumn("PDB Id")
1278 int refSeqColIndex = tbl_local_pdb.getColumn("Ref Sequence")
1280 List<SequenceI> selectedSeqsToView = new ArrayList<>();
1281 for (int row : selectedRows)
1283 PDBEntry pdbEntry = ((PDBEntryTableModel) tbl_local_pdb
1284 .getModel()).getPDBEntryAt(row).getPdbEntry();
1286 pdbEntriesToView[count++] = pdbEntry;
1287 SequenceI selectedSeq = (SequenceI) tbl_local_pdb
1288 .getValueAt(row, refSeqColIndex);
1289 selectedSeqsToView.add(selectedSeq);
1291 SequenceI[] selectedSeqs = selectedSeqsToView
1292 .toArray(new SequenceI[selectedSeqsToView.size()]);
1293 sViewer = launchStructureViewer(ssm, pdbEntriesToView, ap,
1296 else if (currentView == VIEWS_ENTER_ID)
1298 SequenceI userSelectedSeq = ((AssociateSeqOptions) idInputAssSeqPanel
1299 .getCmb_assSeq().getSelectedItem()).getSequence();
1300 if (userSelectedSeq != null)
1302 selectedSequence = userSelectedSeq;
1304 String pdbIdStr = txt_search.getText();
1305 PDBEntry pdbEntry = selectedSequence.getPDBEntry(pdbIdStr);
1306 if (pdbEntry == null)
1308 pdbEntry = new PDBEntry();
1309 if (pdbIdStr.split(":").length > 1)
1311 pdbEntry.setId(pdbIdStr.split(":")[0]);
1312 pdbEntry.setChainCode(
1313 pdbIdStr.split(":")[1].toUpperCase(Locale.ROOT));
1317 pdbEntry.setId(pdbIdStr);
1319 pdbEntry.setType(PDBEntry.Type.PDB);
1320 selectedSequence.getDatasetSequence().addPDBId(pdbEntry);
1323 PDBEntry[] pdbEntriesToView = new PDBEntry[] { pdbEntry };
1324 sViewer = launchStructureViewer(ssm, pdbEntriesToView, ap,
1326 { selectedSequence });
1328 else if (currentView == VIEWS_FROM_FILE)
1330 StructureChooser sc = StructureChooser.this;
1331 TFType tft = (TFType) sc.combo_tempFacAs.getSelectedItem();
1332 String paeFilename = sc.localPdbPaeMatrixFileName;
1333 AssociateSeqOptions assSeqOpt = (AssociateSeqOptions) fileChooserAssSeqPanel
1334 .getCmb_assSeq().getSelectedItem();
1335 SequenceI userSelectedSeq = assSeqOpt.getSequence();
1336 if (userSelectedSeq != null)
1338 selectedSequence = userSelectedSeq;
1340 String pdbFilename = selectedPdbFileName;
1342 StructureChooser.openStructureFileForSequence(ssm, sc, ap,
1343 selectedSequence, true, pdbFilename, tft, paeFilename,
1346 SwingUtilities.invokeLater(new Runnable()
1351 setProgressBar("Complete.", progress.hashCode());
1352 closeAction(preferredHeight);
1353 mainFrame.dispose();
1358 Thread runner = new Thread(viewStruc);
1360 if (waitUntilFinished)
1362 while (sViewer == null ? runner.isAlive()
1363 : (sViewer.sview == null ? true
1364 : !sViewer.sview.hasMapping()))
1369 } catch (InterruptedException ie)
1378 * Answers a structure viewer (new or existing) configured to superimpose
1379 * added structures or not according to the user's choice
1384 StructureViewer getTargetedStructureViewer(StructureSelectionManager ssm)
1386 Object sv = targetView.getSelectedItem();
1388 return sv == null ? new StructureViewer(ssm) : (StructureViewer) sv;
1392 * Adds PDB structures to a new or existing structure viewer
1395 * @param pdbEntriesToView
1400 private StructureViewer launchStructureViewer(
1401 StructureSelectionManager ssm, final PDBEntry[] pdbEntriesToView,
1402 final AlignmentPanel alignPanel, SequenceI[] sequences)
1404 return launchStructureViewer(ssm, pdbEntriesToView, alignPanel,
1408 private StructureViewer launchStructureViewer(
1409 StructureSelectionManager ssm, final PDBEntry[] pdbEntriesToView,
1410 final AlignmentPanel alignPanel, SequenceI[] sequences,
1411 ViewerType viewerType)
1413 long progressId = sequences.hashCode();
1414 setProgressBar(MessageManager
1415 .getString("status.launching_3d_structure_viewer"), progressId);
1416 final StructureViewer theViewer = getTargetedStructureViewer(ssm);
1417 boolean superimpose = chk_superpose.isSelected();
1418 theViewer.setSuperpose(superimpose);
1420 // if we're running in --headless mode make this viewer synchronous
1421 if (Jalview.isHeadlessMode())
1423 theViewer.setAsync(false);
1427 * remember user's choice of superimpose or not
1429 Cache.setProperty(AUTOSUPERIMPOSE,
1430 Boolean.valueOf(superimpose).toString());
1432 setProgressBar(null, progressId);
1433 if (SiftsSettings.isMapWithSifts())
1435 List<SequenceI> seqsWithoutSourceDBRef = new ArrayList<>();
1437 // TODO: skip PDBEntry:Sequence pairs where PDBEntry doesn't look like a
1438 // real PDB ID. For moment, we can also safely do this if there is already
1439 // a known mapping between the PDBEntry and the sequence.
1440 for (SequenceI seq : sequences)
1442 PDBEntry pdbe = pdbEntriesToView[p++];
1443 if (pdbe != null && pdbe.getFile() != null)
1445 StructureMapping[] smm = ssm.getMapping(pdbe.getFile());
1446 if (smm != null && smm.length > 0)
1448 for (StructureMapping sm : smm)
1450 if (sm.getSequence() == seq)
1457 if (seq.getPrimaryDBRefs().isEmpty())
1459 seqsWithoutSourceDBRef.add(seq);
1463 if (!seqsWithoutSourceDBRef.isEmpty())
1465 int y = seqsWithoutSourceDBRef.size();
1466 setProgressBar(MessageManager.formatMessage(
1467 "status.fetching_dbrefs_for_sequences_without_valid_refs",
1469 SequenceI[] seqWithoutSrcDBRef = seqsWithoutSourceDBRef
1470 .toArray(new SequenceI[y]);
1471 DBRefFetcher dbRefFetcher = new DBRefFetcher(seqWithoutSrcDBRef);
1472 dbRefFetcher.fetchDBRefs(true);
1474 setProgressBar("Fetch complete.", progressId); // todo i18n
1477 if (pdbEntriesToView.length > 1)
1480 MessageManager.getString(
1481 "status.fetching_3d_structures_for_selected_entries"),
1483 theViewer.viewStructures(pdbEntriesToView, sequences, alignPanel,
1488 setProgressBar(MessageManager.formatMessage(
1489 "status.fetching_3d_structures_for",
1490 pdbEntriesToView[0].getId()), progressId);
1491 // Can we pass a pre-computeMappinged pdbFile?
1492 theViewer.viewStructures(pdbEntriesToView[0], sequences, alignPanel,
1495 setProgressBar(null, progressId);
1496 // remember the last viewer we used...
1497 lastTargetedView = theViewer;
1502 * Populates the combo-box used in associating manually fetched structures to
1503 * a unique sequence when more than one sequence selection is made.
1506 protected void populateCmbAssociateSeqOptions(
1507 JComboBox<AssociateSeqOptions> cmb_assSeq,
1508 JLabel lbl_associateSeq)
1510 cmb_assSeq.removeAllItems();
1512 new AssociateSeqOptions("-Select Associated Seq-", null));
1513 lbl_associateSeq.setVisible(false);
1514 if (selectedSequences.length > 1)
1516 for (SequenceI seq : selectedSequences)
1518 cmb_assSeq.addItem(new AssociateSeqOptions(seq));
1523 String seqName = selectedSequence.getDisplayId(false);
1524 seqName = seqName.length() <= 40 ? seqName : seqName.substring(0, 39);
1525 lbl_associateSeq.setText(seqName);
1526 lbl_associateSeq.setVisible(true);
1527 cmb_assSeq.setVisible(false);
1531 protected boolean isStructuresDiscovered()
1533 return discoveredStructuresSet != null
1534 && !discoveredStructuresSet.isEmpty();
1537 protected int PDB_ID_MIN = 3;// or: (Jalview.isJS() ? 3 : 1); // Bob proposes
1539 // Doing a search for "1" or "1c" is valuable?
1540 // Those work but are enormously slow.
1543 protected void txt_search_ActionPerformed()
1545 String text = txt_search.getText().trim();
1546 if (text.length() >= PDB_ID_MIN)
1553 errorWarning.setLength(0);
1554 isValidPBDEntry = false;
1555 if (text.length() > 0)
1557 // TODO move this pdb id search into the PDB specific
1559 // for moment, it will work fine as is because it is self-contained
1560 String searchTerm = text.toLowerCase(Locale.ROOT);
1561 searchTerm = searchTerm.split(":")[0];
1562 // jalview.bin.Console.outPrintln(">>>>> search term : " +
1564 List<FTSDataColumnI> wantedFields = new ArrayList<>();
1565 FTSRestRequest pdbRequest = new FTSRestRequest();
1566 pdbRequest.setAllowEmptySeq(false);
1567 pdbRequest.setResponseSize(1);
1568 pdbRequest.setFieldToSearchBy("(pdb_id:");
1569 pdbRequest.setWantedFields(wantedFields);
1570 pdbRequest.setSearchTerm(searchTerm + ")");
1571 pdbRequest.setAssociatedSequence(selectedSequence);
1572 FTSRestClientI pdbRestClient = PDBFTSRestClient.getInstance();
1573 wantedFields.add(pdbRestClient.getPrimaryKeyColumn());
1574 FTSRestResponse resultList;
1577 resultList = pdbRestClient.executeRequest(pdbRequest);
1578 } catch (Exception e)
1580 errorWarning.append(e.getMessage());
1584 validateSelections();
1586 if (resultList.getSearchSummary() != null
1587 && resultList.getSearchSummary().size() > 0)
1589 isValidPBDEntry = true;
1592 validateSelections();
1598 protected void tabRefresh()
1600 if (selectedSequences != null)
1602 lbl_loading.setVisible(true);
1603 Thread refreshThread = new Thread(new Runnable()
1608 fetchStructuresMetaData();
1609 // populateFilterComboBox(true, cachedPDBExists);
1612 ((FilterOption) cmb_filterOption.getSelectedItem())
1614 lbl_loading.setVisible(false);
1617 refreshThread.start();
1621 public class PDBEntryTableModel extends AbstractTableModel
1623 String[] columns = { "Ref Sequence", "PDB Id", "Chain", "Type",
1626 private List<CachedPDB> pdbEntries;
1628 public PDBEntryTableModel(List<CachedPDB> pdbEntries)
1630 this.pdbEntries = new ArrayList<>(pdbEntries);
1634 public String getColumnName(int columnIndex)
1636 return columns[columnIndex];
1640 public int getRowCount()
1642 return pdbEntries.size();
1646 public int getColumnCount()
1648 return columns.length;
1652 public boolean isCellEditable(int row, int column)
1658 public Object getValueAt(int rowIndex, int columnIndex)
1660 Object value = "??";
1661 CachedPDB entry = pdbEntries.get(rowIndex);
1662 switch (columnIndex)
1665 value = entry.getSequence();
1668 value = entry.getQualifiedId();
1671 value = entry.getPdbEntry().getChainCode() == null ? "_"
1672 : entry.getPdbEntry().getChainCode();
1675 value = entry.getPdbEntry().getType();
1678 value = entry.getPdbEntry().getFile();
1685 public Class<?> getColumnClass(int columnIndex)
1687 return columnIndex == 0 ? SequenceI.class : PDBEntry.class;
1690 public CachedPDB getPDBEntryAt(int row)
1692 return pdbEntries.get(row);
1697 private class CachedPDB
1699 private SequenceI sequence;
1701 private PDBEntry pdbEntry;
1703 public CachedPDB(SequenceI sequence, PDBEntry pdbEntry)
1705 this.sequence = sequence;
1706 this.pdbEntry = pdbEntry;
1709 public String getQualifiedId()
1711 if (pdbEntry.hasProvider())
1713 return pdbEntry.getProvider() + ":" + pdbEntry.getId();
1715 return pdbEntry.toString();
1718 public SequenceI getSequence()
1723 public PDBEntry getPdbEntry()
1730 private IProgressIndicator progressBar;
1733 public void setProgressBar(String message, long id)
1735 if (!Platform.isHeadless() && progressBar != null)
1736 progressBar.setProgressBar(message, id);
1740 public void registerHandler(long id, IProgressIndicatorHandler handler)
1742 if (progressBar != null)
1743 progressBar.registerHandler(id, handler);
1747 public boolean operationInProgress()
1749 return progressBar == null ? false : progressBar.operationInProgress();
1752 public JalviewStructureDisplayI getOpenedStructureViewer()
1754 return sViewer == null ? null : sViewer.sview;
1758 protected void setFTSDocFieldPrefs(FTSDataColumnPreferences newPrefs)
1760 data.setDocFieldPrefs(newPrefs);
1766 * @return true when all initialisation threads have finished and dialog is
1769 public boolean isDialogVisible()
1771 return mainFrame != null && data != null && cmb_filterOption != null
1772 && mainFrame.isVisible()
1773 && cmb_filterOption.getSelectedItem() != null;
1778 * @return true if the 3D-Beacons query button will/has been displayed
1780 public boolean isCanQueryTDB()
1785 public boolean isNotQueriedTDBYet()
1787 return notQueriedTDBYet;
1791 * Open a single structure file for a given sequence
1793 public static void openStructureFileForSequence(
1794 StructureSelectionManager ssm, StructureChooser sc,
1795 AlignmentPanel ap, SequenceI seq, boolean prompt,
1796 String sFilename, TFType tft, String paeFilename,
1797 boolean doXferSettings)
1799 openStructureFileForSequence(ssm, sc, ap, seq, prompt, sFilename, tft,
1800 paeFilename, false, true, doXferSettings, null);
1803 public static StructureViewer openStructureFileForSequence(
1804 StructureSelectionManager ssm, StructureChooser sc,
1805 AlignmentPanel ap, SequenceI seq, boolean prompt,
1806 String sFilename, TFType tft, String paeFilename,
1807 boolean forceHeadless, boolean showRefAnnotations,
1808 boolean doXferSettings, ViewerType viewerType)
1810 StructureViewer sv = null;
1811 boolean headless = forceHeadless;
1816 // suppress structure viewer's external service queries
1817 sc = new StructureChooser(new SequenceI[] { seq }, seq, ap, false,true);
1821 ssm = ap.getStructureSelectionManager();
1824 PDBEntry fileEntry = new AssociatePdbFileWithSeq().associatePdbWithSeq(
1825 sFilename, DataSourceType.FILE, seq, prompt, Desktop.instance,
1826 tft, paeFilename, doXferSettings);
1828 // if headless, "false" in the sc constructor above will avoid GUI behaviour
1829 // in sc.launchStructureViewer()
1830 if (!headless && !(viewerType == null))
1832 sv = sc.launchStructureViewer(ssm, new PDBEntry[] { fileEntry }, ap,
1834 { seq }, viewerType);
1837 sc.mainFrame.dispose();
1839 if (showRefAnnotations)
1841 showReferenceAnnotationsForSequence(ap.alignFrame, seq);
1847 public static void showReferenceAnnotationsForSequence(AlignFrame af,
1850 AlignViewport av = af.getCurrentView();
1851 AlignmentI al = av.getAlignment();
1853 List<SequenceI> forSequences = new ArrayList<>();
1854 forSequences.add(sequence);
1855 final Map<SequenceI, List<AlignmentAnnotation>> candidates = new LinkedHashMap<>();
1856 AlignmentUtils.findAddableReferenceAnnotations(forSequences, null,
1858 final SequenceGroup selectionGroup = av.getSelectionGroup();
1859 AlignmentUtils.addReferenceAnnotations(candidates, al, selectionGroup);
1860 for (AlignmentViewPanel ap : af.getAlignPanels())
1862 // required to readjust the height and position of the PAE
1864 ap.adjustAnnotationHeight();