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;
144 * when true, queries to external services are supressed (no SIFTs, no PDBe,
145 * no 3D-Beacons, etc)
147 private boolean dontQueryServices = false;
149 private static StructureViewer lastTargetedView = null;
151 public StructureChooser(SequenceI[] selectedSeqs, SequenceI selectedSeq,
154 this(selectedSeqs, selectedSeq, ap, true);
157 public StructureChooser(SequenceI[] selectedSeqs, SequenceI selectedSeq,
158 AlignmentPanel ap, boolean showGUI)
160 this(selectedSeqs, selectedSeq, ap, showGUI, false);
163 public StructureChooser(SequenceI[] selectedSeqs, SequenceI selectedSeq,
164 AlignmentPanel ap, boolean showGUI, boolean dontQueryServices)
167 // which FTS engine to use
168 data = StructureChooserQuerySource.getQuerySourceFor(selectedSeqs);
172 this.selectedSequence = selectedSeq;
173 this.selectedSequences = selectedSeqs;
174 this.progressIndicator = (ap == null) ? null : ap.alignFrame;
175 this.showChooserGUI = showGUI;
176 this.dontQueryServices = dontQueryServices;
182 * sets canQueryTDB if protein sequences without a canonical uniprot ref or at
183 * least one structure are discovered.
185 private void populateSeqsWithoutSourceDBRef()
187 seqsWithoutSourceDBRef = new ArrayList<SequenceI>();
188 boolean needCanonical = false;
189 for (SequenceI seq : selectedSequences)
193 int dbRef = ThreeDBStructureChooserQuerySource
194 .checkUniprotRefs(seq.getDBRefs());
199 // need to retrieve canonicals
200 needCanonical = true;
201 seqsWithoutSourceDBRef.add(seq);
205 // could be a sequence with pdb ref
206 if (seq.getAllPDBEntries() == null
207 || seq.getAllPDBEntries().size() == 0)
209 seqsWithoutSourceDBRef.add(seq);
215 // retrieve database refs for protein sequences
216 if (!seqsWithoutSourceDBRef.isEmpty())
221 // triggers display of the 'Query TDB' button
222 notQueriedTDBYet = true;
228 * Initializes parameters used by the Structure Chooser Panel
230 protected void init()
232 if (!Jalview.isHeadlessMode())
234 progressBar = new ProgressBar(this.statusPanel, this.statusBar);
237 chk_superpose.setSelected(Cache.getDefault(AUTOSUPERIMPOSE, true));
238 btn_queryTDB.addActionListener(new ActionListener()
242 public void actionPerformed(ActionEvent e)
244 promptForTDBFetch(false);
248 if (!dontQueryServices)
250 Executors.defaultThreadFactory().newThread(new Runnable()
255 populateSeqsWithoutSourceDBRef();
256 initialStructureDiscovery();
264 "Structure chooser not querying services to discover metadata.");
269 private void initialStructureDiscovery()
271 // check which FTS engine to use
272 data = StructureChooserQuerySource.getQuerySourceFor(selectedSequences);
274 // ensure a filter option is in force for search
275 populateFilterComboBox(true, cachedPDBExists);
277 // looks for any existing structures already loaded
278 // for the sequences (the cached ones)
279 // then queries the StructureChooserQuerySource to
280 // discover more structures.
282 // Possible optimisation is to only begin querying
283 // the structure chooser if there are no cached structures.
285 long startTime = System.currentTimeMillis();
286 updateProgressIndicator(
287 MessageManager.getString("status.loading_cached_pdb_entries"),
289 loadLocalCachedPDBEntries();
290 updateProgressIndicator(null, startTime);
291 updateProgressIndicator(
292 MessageManager.getString("status.searching_for_pdb_structures"),
294 fetchStructuresMetaData();
295 // revise filter options if no results were found
296 populateFilterComboBox(isStructuresDiscovered(), cachedPDBExists);
297 discoverStructureViews();
298 updateProgressIndicator(null, startTime);
299 mainFrame.setVisible(showChooserGUI);
304 * raises dialog for Uniprot fetch followed by 3D beacons search
307 * - when true, don't ask, just fetch
309 public void promptForTDBFetch(boolean ignoreGui)
311 final long progressId = System.currentTimeMillis();
313 // final action after prompting and discovering db refs
314 final Runnable strucDiscovery = new Runnable()
319 mainFrame.setEnabled(false);
320 cmb_filterOption.setEnabled(false);
321 progressBar.setProgressBar(
322 MessageManager.getString("status.searching_3d_beacons"),
324 btn_queryTDB.setEnabled(false);
325 // TODO: warn if no accessions discovered
326 populateSeqsWithoutSourceDBRef();
327 // redo initial discovery - this time with 3d beacons
329 previousWantedFields = null;
330 lastSelected = (FilterOption) cmb_filterOption.getSelectedItem();
331 cmb_filterOption.setSelectedItem(null);
332 cachedPDBExists = false; // reset to initial
333 initialStructureDiscovery();
334 if (!isStructuresDiscovered())
336 progressBar.setProgressBar(MessageManager.getString(
337 "status.no_structures_discovered_from_3d_beacons"),
339 btn_queryTDB.setToolTipText(MessageManager.getString(
340 "status.no_structures_discovered_from_3d_beacons"));
341 btn_queryTDB.setEnabled(false);
342 pnl_queryTDB.setVisible(false);
346 cmb_filterOption.setSelectedIndex(0); // select 'best'
347 btn_queryTDB.setVisible(false);
348 pnl_queryTDB.setVisible(false);
349 progressBar.setProgressBar(null, progressId);
351 mainFrame.setEnabled(true);
352 cmb_filterOption.setEnabled(true);
356 final FetchFinishedListenerI afterDbRefFetch = new FetchFinishedListenerI()
360 public void finished()
362 // filter has been selected, so we set flag to remove ourselves
363 notQueriedTDBYet = false;
364 // new thread to discover structures - via 3d beacons
365 Executors.defaultThreadFactory().newThread(strucDiscovery).start();
370 // fetch db refs if OK pressed
371 final Runnable discoverCanonicalDBrefs = () -> {
372 btn_queryTDB.setEnabled(false);
373 populateSeqsWithoutSourceDBRef();
375 final int y = seqsWithoutSourceDBRef.size();
378 final SequenceI[] seqWithoutSrcDBRef = seqsWithoutSourceDBRef
379 .toArray(new SequenceI[y]);
380 DBRefFetcher dbRefFetcher = new DBRefFetcher(seqWithoutSrcDBRef,
381 progressBar, new DbSourceProxy[]
382 { new jalview.ws.dbsources.Uniprot() }, null, false);
383 dbRefFetcher.addListener(afterDbRefFetch);
384 // ideally this would also gracefully run with callbacks
386 dbRefFetcher.fetchDBRefs(true);
390 // call finished action directly
391 afterDbRefFetch.finished();
394 final Runnable revertview = () -> {
395 if (lastSelected != null)
397 cmb_filterOption.setSelectedItem(lastSelected);
400 int threshold = Cache.getDefault("UNIPROT_AUTOFETCH_THRESHOLD",
401 THRESHOLD_WARN_UNIPROT_FETCH_NEEDED);
402 Console.debug("Using Uniprot fetch threshold of " + threshold);
403 if (ignoreGui || seqsWithoutSourceDBRef.size() < threshold)
405 Executors.newSingleThreadExecutor().submit(discoverCanonicalDBrefs);
408 // need cancel and no to result in the discoverPDB action - mocked is
409 // 'cancel' TODO: mock should be OK
411 StructureChooser thisSC = this;
412 JvOptionPane.newOptionDialog(thisSC.getFrame())
413 .setResponseHandler(JvOptionPane.OK_OPTION,
414 discoverCanonicalDBrefs)
415 .setResponseHandler(JvOptionPane.CANCEL_OPTION, revertview)
416 .setResponseHandler(JvOptionPane.NO_OPTION, revertview)
418 MessageManager.formatMessage(
419 "label.fetch_references_for_3dbeacons",
420 seqsWithoutSourceDBRef.size()),
421 MessageManager.getString("label.3dbeacons"),
422 JvOptionPane.YES_NO_OPTION, JvOptionPane.PLAIN_MESSAGE,
424 { MessageManager.getString("action.ok"),
425 MessageManager.getString("action.cancel") },
426 MessageManager.getString("action.ok"), false);
430 * Builds a drop-down choice list of existing structure viewers to which new
431 * structures may be added. If this list is empty then it, and the 'Add'
432 * button, are hidden.
434 private void discoverStructureViews()
436 if (Desktop.instance != null)
438 targetView.removeAllItems();
439 if (lastTargetedView != null && !lastTargetedView.isVisible())
441 lastTargetedView = null;
443 int linkedViewsAt = 0;
444 for (StructureViewerBase view : Desktop.instance
445 .getStructureViewers(null, null))
447 StructureViewer viewHandler = (lastTargetedView != null
448 && lastTargetedView.sview == view) ? lastTargetedView
449 : StructureViewer.reconfigure(view);
451 if (view.isLinkedWith(ap))
453 targetView.insertItemAt(viewHandler, linkedViewsAt++);
457 targetView.addItem(viewHandler);
462 * show option to Add to viewer if at least 1 viewer found
464 targetView.setVisible(false);
465 if (targetView.getItemCount() > 0)
467 targetView.setVisible(true);
468 if (lastTargetedView != null)
470 targetView.setSelectedItem(lastTargetedView);
474 targetView.setSelectedIndex(0);
477 btn_add.setVisible(targetView.isVisible());
482 * Updates the progress indicator with the specified message
485 * displayed message for the operation
487 * unique handle for this indicator
489 protected void updateProgressIndicator(String message, long id)
491 if (progressIndicator != null)
493 progressIndicator.setProgressBar(message, id);
498 * Retrieve meta-data for all the structure(s) for a given sequence(s) in a
501 void fetchStructuresMetaData()
503 long startTime = System.currentTimeMillis();
504 Collection<FTSDataColumnI> wantedFields = data.getDocFieldPrefs()
505 .getStructureSummaryFields();
507 discoveredStructuresSet = new LinkedHashSet<>();
508 HashSet<String> errors = new HashSet<>();
510 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
513 for (SequenceI seq : selectedSequences)
516 FTSRestResponse resultList;
519 resultList = data.fetchStructuresMetaData(seq, wantedFields,
520 selectedFilterOpt, !chk_invertFilter.isSelected());
521 // null response means the FTSengine didn't yield a query for this
522 // consider designing a special exception if we really wanted to be
524 if (resultList == null)
528 } catch (Exception e)
530 Console.printStackTrace(e);
531 errors.add(e.getMessage());
534 if (resultList.getSearchSummary() != null
535 && !resultList.getSearchSummary().isEmpty())
537 discoveredStructuresSet.addAll(resultList.getSearchSummary());
541 int noOfStructuresFound = 0;
542 String totalTime = (System.currentTimeMillis() - startTime)
544 if (discoveredStructuresSet != null
545 && !discoveredStructuresSet.isEmpty())
548 .setModel(data.getTableModel(discoveredStructuresSet));
550 noOfStructuresFound = discoveredStructuresSet.size();
551 lastDiscoveredStructuresSet = discoveredStructuresSet;
552 mainFrame.setTitle(MessageManager.formatMessage(
553 "label.structure_chooser_no_of_structures",
554 noOfStructuresFound, totalTime));
558 mainFrame.setTitle(MessageManager
559 .getString("label.structure_chooser_manual_association"));
560 if (errors.size() > 0)
562 StringBuilder errorMsg = new StringBuilder();
563 for (String error : errors)
565 errorMsg.append(error).append("\n");
567 if (!Jalview.isHeadlessMode())
569 JvOptionPane.showMessageDialog(this, errorMsg.toString(),
570 MessageManager.getString("label.pdb_web-service_error"),
571 JvOptionPane.ERROR_MESSAGE);
576 MessageManager.getString("label.pdb_web-service_error"));
577 Console.debug(errorMsg.toString());
583 protected void loadLocalCachedPDBEntries()
585 ArrayList<CachedPDB> entries = new ArrayList<>();
586 for (SequenceI seq : selectedSequences)
588 if (seq.getDatasetSequence() != null
589 && seq.getDatasetSequence().getAllPDBEntries() != null)
591 for (PDBEntry pdbEntry : seq.getDatasetSequence()
594 if (pdbEntry.getFile() != null)
596 entries.add(new CachedPDB(seq, pdbEntry));
601 cachedPDBExists = !entries.isEmpty();
602 PDBEntryTableModel tableModelx = new PDBEntryTableModel(entries);
603 tbl_local_pdb.setModel(tableModelx);
607 * Filters a given list of discovered structures based on supplied argument
609 * @param fieldToFilterBy
610 * the field to filter by
612 void filterResultSet(final String fieldToFilterBy)
614 Thread filterThread = new Thread(new Runnable()
620 long startTime = System.currentTimeMillis();
621 lbl_loading.setVisible(true);
622 Collection<FTSDataColumnI> wantedFields = data.getDocFieldPrefs()
623 .getStructureSummaryFields();
624 Collection<FTSData> filteredResponse = new HashSet<>();
625 HashSet<String> errors = new HashSet<>();
627 for (SequenceI seq : selectedSequences)
630 FTSRestResponse resultList;
633 resultList = data.selectFirstRankedQuery(seq,
634 discoveredStructuresSet, wantedFields, fieldToFilterBy,
635 !chk_invertFilter.isSelected());
637 } catch (Exception e)
639 Console.debugPrintStackTrace(e);
640 errors.add(e.getMessage());
643 if (resultList.getSearchSummary() != null
644 && !resultList.getSearchSummary().isEmpty())
646 filteredResponse.addAll(resultList.getSearchSummary());
650 String totalTime = (System.currentTimeMillis() - startTime)
652 if (!filteredResponse.isEmpty())
654 final int filterResponseCount = filteredResponse.size();
655 Collection<FTSData> reorderedStructuresSet = new LinkedHashSet<>();
656 reorderedStructuresSet.addAll(filteredResponse);
657 reorderedStructuresSet.addAll(discoveredStructuresSet);
659 .setModel(data.getTableModel(reorderedStructuresSet));
661 FTSRestResponse.configureTableColumn(getResultTable(),
662 wantedFields, tempUserPrefs);
663 getResultTable().getColumn("Ref Sequence").setPreferredWidth(120);
664 getResultTable().getColumn("Ref Sequence").setMinWidth(100);
665 getResultTable().getColumn("Ref Sequence").setMaxWidth(200);
666 // Update table selection model here
667 getResultTable().addRowSelectionInterval(0,
668 filterResponseCount - 1);
669 mainFrame.setTitle(MessageManager.formatMessage(
670 "label.structure_chooser_filter_time", totalTime));
674 mainFrame.setTitle(MessageManager.formatMessage(
675 "label.structure_chooser_filter_time", totalTime));
676 if (errors.size() > 0)
678 StringBuilder errorMsg = new StringBuilder();
679 for (String error : errors)
681 errorMsg.append(error).append("\n");
683 JvOptionPane.showMessageDialog(null, errorMsg.toString(),
684 MessageManager.getString("label.pdb_web-service_error"),
685 JvOptionPane.ERROR_MESSAGE);
689 lbl_loading.setVisible(false);
691 validateSelections();
694 filterThread.start();
698 * Handles action event for btn_pdbFromFile
701 protected void pdbFromFile_actionPerformed()
703 // TODO: JAL-3048 not needed for Jalview-JS until JSmol dep and
706 JalviewFileChooser chooser = new JalviewFileChooser(
707 Cache.getProperty("LAST_DIRECTORY"));
708 chooser.setFileView(new JalviewFileView());
709 chooser.setDialogTitle(
710 MessageManager.formatMessage("label.select_pdb_file_for",
711 selectedSequence.getDisplayId(false)));
712 chooser.setToolTipText(MessageManager.formatMessage(
713 "label.load_pdb_file_associate_with_sequence",
714 selectedSequence.getDisplayId(false)));
716 int value = chooser.showOpenDialog(null);
717 if (value == JalviewFileChooser.APPROVE_OPTION)
719 selectedPdbFileName = chooser.getSelectedFile().getPath();
720 Cache.setProperty("LAST_DIRECTORY", selectedPdbFileName);
721 boolean guessTFType = localPdbPaeMatrixFileName == null;
722 localPdbPaeMatrixFileName = guessPAEFilename();
723 guessTFType |= localPdbPaeMatrixFileName != null;
724 Regex alphaFold = JmolParser.getNewAlphafoldValidator();
726 && alphaFold.search(new File(selectedPdbFileName).getName())
727 && !tempFacAsChanged)
729 // localPdbPaeMatrixFileName was null and now isn't and filename could
730 // well be AlphaFold and user hasn't adjusted the tempFacType
731 combo_tempFacAs.setSelectedItem(TFType.PLDDT);
733 validateSelections();
738 * Handles action event for btn_paeMatrixFile
741 protected void paeMatrixFile_actionPerformed()
743 File pdbFile = new File(selectedPdbFileName);
744 String setFile = Cache.getProperty("LAST_DIRECTORY");
745 if (localPdbPaeMatrixFileName != null)
747 File paeFile = new File(localPdbPaeMatrixFileName);
748 if (paeFile.exists())
749 setFile = paeFile.getAbsolutePath();
750 else if (paeFile.getParentFile().exists())
751 setFile = paeFile.getParentFile().getAbsolutePath();
755 String guess = guessPAEFilename();
759 JalviewFileChooser chooser = new JalviewFileChooser(setFile);
760 chooser.setFileView(new JalviewFileView());
761 chooser.setDialogTitle(MessageManager.formatMessage(
762 "label.select_pae_matrix_file_for", pdbFile.getName()));
763 chooser.setToolTipText(MessageManager.formatMessage(
764 "label.load_pae_matrix_file_associate_with_structure",
767 // TODO convert to Callable/Promise
768 int value = chooser.showOpenDialog(null);
769 if (value == JalviewFileChooser.APPROVE_OPTION)
771 String fileName = chooser.getSelectedFile().getPath();
774 PAEContactMatrix.validateContactMatrixFile(fileName);
775 } catch (Exception thr)
777 JvOptionPane.showInternalMessageDialog(this, MessageManager
778 .formatMessage("label.couldnt_load_file", new Object[]
779 { fileName }) + "<br>" + thr.getLocalizedMessage(),
780 MessageManager.getString("label.error_loading_file"),
781 JvOptionPane.WARNING_MESSAGE);
782 Console.error("Couldn't import " + fileName + " as a PAE matrix",
786 localPdbPaeMatrixFileName = fileName;
787 Cache.setProperty("LAST_DIRECTORY", localPdbPaeMatrixFileName);
789 validateAssociationFromFile();
792 private String guessPAEFilename()
794 if (selectedPdbFileName.toLowerCase(Locale.ROOT).endsWith(".pdb")
795 || selectedPdbFileName.toLowerCase(Locale.ROOT)
798 String jsonExt = selectedPdbFileName.substring(0,
799 selectedPdbFileName.length() - 4) + ".json";
800 // AlphaFold naming scheme
801 String guessFile1 = StringUtils.replaceLast(jsonExt, "model",
802 "predicted_aligned_error");
803 // nf-core mode naming scheme
804 String guessFile2 = StringUtils.replaceLast(jsonExt, ".json",
806 if (new File(guessFile1).exists())
810 else if (new File(jsonExt).exists())
814 else if (new File(guessFile2).exists())
823 * Populates the filter combo-box options dynamically depending on discovered
826 protected void populateFilterComboBox(boolean haveData,
827 boolean cachedPDBExist)
829 populateFilterComboBox(haveData, cachedPDBExist, null);
833 * Populates the filter combo-box options dynamically depending on discovered
836 protected void populateFilterComboBox(boolean haveData,
837 boolean cachedPDBExist, FilterOption lastSel)
841 * temporarily suspend the change listener behaviour
843 cmb_filterOption.removeItemListener(this);
845 cmb_filterOption.removeAllItems();
848 List<FilterOption> filters = data
849 .getAvailableFilterOptions(VIEWS_FILTER);
850 data.updateAvailableFilterOptions(VIEWS_FILTER, filters,
851 lastDiscoveredStructuresSet);
853 for (FilterOption filter : filters)
855 if (lastSel != null && filter.equals(lastSel))
860 cmb_filterOption.addItem(filter);
864 cmb_filterOption.addItem(
865 new FilterOption(MessageManager.getString("label.enter_pdb_id"),
866 "-", VIEWS_ENTER_ID, false, null));
867 cmb_filterOption.addItem(
868 new FilterOption(MessageManager.getString("label.from_file"),
869 "-", VIEWS_FROM_FILE, false, null));
870 if (canQueryTDB && notQueriedTDBYet)
872 btn_queryTDB.setVisible(true);
873 pnl_queryTDB.setVisible(true);
878 FilterOption cachedOption = new FilterOption(
879 MessageManager.getString("label.cached_structures"), "-",
880 VIEWS_LOCAL_PDB, false, null);
881 cmb_filterOption.addItem(cachedOption);
884 cmb_filterOption.setSelectedItem(cachedOption);
889 cmb_filterOption.setSelectedIndex(selSet);
891 cmb_filterOption.addItemListener(this);
895 * Updates the displayed view based on the selected filter option
897 protected void updateCurrentView()
899 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
902 if (lastSelected == selectedFilterOpt)
904 // don't need to do anything, probably
907 // otherwise, record selection
908 // and update the layout and dialog accordingly
909 lastSelected = selectedFilterOpt;
911 layout_switchableViews.show(pnl_switchableViews,
912 selectedFilterOpt.getView());
913 String filterTitle = mainFrame.getTitle();
914 mainFrame.setTitle(frameTitle);
915 chk_invertFilter.setVisible(false);
917 if (selectedFilterOpt.getView() == VIEWS_FILTER)
919 mainFrame.setTitle(filterTitle);
920 // TDB Query has no invert as yet
921 chk_invertFilter.setVisible(selectedFilterOpt
922 .getQuerySource() instanceof PDBStructureChooserQuerySource);
924 if (data != selectedFilterOpt.getQuerySource()
925 || data.needsRefetch(selectedFilterOpt))
927 data = selectedFilterOpt.getQuerySource();
928 // rebuild the views completely, since prefs will also change
934 filterResultSet(selectedFilterOpt.getValue());
937 else if (selectedFilterOpt.getView() == VIEWS_ENTER_ID
938 || selectedFilterOpt.getView() == VIEWS_FROM_FILE)
940 mainFrame.setTitle(MessageManager
941 .getString("label.structure_chooser_manual_association"));
942 idInputAssSeqPanel.loadCmbAssSeq();
943 fileChooserAssSeqPanel.loadCmbAssSeq();
945 validateSelections();
949 * Validates user selection and enables the 'Add' and 'New View' buttons if
950 * all parameters are correct (the Add button will only be visible if there is
951 * at least one existing structure viewer open). This basically means at least
952 * one structure selected and no error messages.
954 * The 'Superpose Structures' option is enabled if either more than one
955 * structure is selected, or the 'Add' to existing view option is enabled, and
956 * disabled if the only option is to open a new view of a single structure.
959 protected void validateSelections()
961 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
963 btn_add.setEnabled(false);
964 String currentView = selectedFilterOpt.getView();
965 int selectedCount = 0;
966 if (currentView == VIEWS_FILTER)
968 selectedCount = getResultTable().getSelectedRows().length;
969 if (selectedCount > 0)
971 btn_add.setEnabled(true);
974 else if (currentView == VIEWS_LOCAL_PDB)
976 selectedCount = tbl_local_pdb.getSelectedRows().length;
977 if (selectedCount > 0)
979 btn_add.setEnabled(true);
982 else if (currentView == VIEWS_ENTER_ID)
984 validateAssociationEnterPdb();
986 else if (currentView == VIEWS_FROM_FILE)
988 validateAssociationFromFile();
991 btn_newView.setEnabled(btn_add.isEnabled());
994 * enable 'Superpose' option if more than one structure is selected,
995 * or there are view(s) available to add structure(s) to
998 .setEnabled(selectedCount > 1 || targetView.getItemCount() > 0);
1002 protected boolean showPopupFor(int selectedRow, int x, int y)
1004 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
1005 .getSelectedItem());
1006 String currentView = selectedFilterOpt.getView();
1008 if (currentView == VIEWS_FILTER
1009 && data instanceof ThreeDBStructureChooserQuerySource)
1012 TDB_FTSData row = ((ThreeDBStructureChooserQuerySource) data)
1013 .getFTSDataFor(getResultTable(), selectedRow,
1014 discoveredStructuresSet);
1015 String pageUrl = row.getModelViewUrl();
1017 JPopupMenu popup = new JPopupMenu("3D Beacons");
1018 JMenuItem viewUrl = new JMenuItem("View model web page");
1019 if (pageUrl == null || "".equals(pageUrl.trim()))
1021 viewUrl.setEnabled(false);
1022 viewUrl.setText("No model page available.");
1024 viewUrl.addActionListener(new ActionListener()
1027 public void actionPerformed(ActionEvent e)
1029 Desktop.showUrl(pageUrl);
1033 SwingUtilities.invokeLater(new Runnable()
1038 popup.show(getResultTable(), x, y);
1043 // event not handled by us
1048 * Validates inputs from the Manual PDB entry panel
1050 protected void validateAssociationEnterPdb()
1052 AssociateSeqOptions assSeqOpt = (AssociateSeqOptions) idInputAssSeqPanel
1053 .getCmb_assSeq().getSelectedItem();
1054 lbl_pdbManualFetchStatus.setIcon(errorImage);
1055 lbl_pdbManualFetchStatus.setToolTipText("");
1056 if (txt_search.getText().length() > 0)
1058 lbl_pdbManualFetchStatus.setToolTipText(JvSwingUtils.wrapTooltip(true,
1059 MessageManager.formatMessage("info.no_pdb_entry_found_for",
1060 txt_search.getText())));
1063 if (errorWarning.length() > 0)
1065 lbl_pdbManualFetchStatus.setIcon(warningImage);
1066 lbl_pdbManualFetchStatus.setToolTipText(
1067 JvSwingUtils.wrapTooltip(true, errorWarning.toString()));
1070 if (selectedSequences.length == 1 || !assSeqOpt.getName()
1071 .equalsIgnoreCase("-Select Associated Seq-"))
1073 txt_search.setEnabled(true);
1074 if (isValidPBDEntry)
1076 btn_add.setEnabled(true);
1077 lbl_pdbManualFetchStatus.setToolTipText("");
1078 lbl_pdbManualFetchStatus.setIcon(goodImage);
1083 txt_search.setEnabled(false);
1084 lbl_pdbManualFetchStatus.setIcon(errorImage);
1089 * Validates inputs for the manual PDB file selection options
1091 protected void validateAssociationFromFile()
1093 AssociateSeqOptions assSeqOpt = (AssociateSeqOptions) fileChooserAssSeqPanel
1094 .getCmb_assSeq().getSelectedItem();
1095 // lbl_fromFileStatus.setIcon(errorImage);
1096 String pdbFileString = "";
1097 String pdbFileTooltip = "";
1098 if (selectedSequences.length == 1 || (assSeqOpt != null && !assSeqOpt
1099 .getName().equalsIgnoreCase("-Select Associated Seq-")))
1101 btn_pdbFromFile.setEnabled(true);
1102 if (selectedPdbFileName != null && selectedPdbFileName.length() > 0)
1104 btn_add.setEnabled(true);
1105 // lbl_fromFileStatus.setIcon(goodImage);
1106 pdbFileString = new File(selectedPdbFileName).getName();
1107 pdbFileTooltip = new File(selectedPdbFileName).getAbsolutePath();
1108 setPdbOptionsEnabled(true);
1112 pdbFileString = MessageManager.getString("label.none");
1113 pdbFileTooltip = MessageManager.getString("label.nothing_selected");
1114 setPdbOptionsEnabled(false);
1119 btn_pdbFromFile.setEnabled(false);
1120 setPdbOptionsEnabled(false);
1121 // lbl_fromFileStatus.setIcon(errorImage);
1122 pdbFileString = MessageManager.getString("label.none");
1123 pdbFileTooltip = MessageManager.getString("label.nothing_selected");
1125 lbl_pdbFile.setText(pdbFileString);
1126 lbl_pdbFile.setToolTipText(pdbFileTooltip);
1129 String paeFileString = "";
1130 String paeFileTooltip = "";
1131 if (localPdbPaeMatrixFileName != null
1132 && localPdbPaeMatrixFileName.length() > 0)
1134 paeFileString = new File(localPdbPaeMatrixFileName).getName();
1135 paeFileTooltip = new File(localPdbPaeMatrixFileName)
1140 paeFileString = MessageManager.getString("label.none");
1141 paeFileTooltip = MessageManager.getString("label.nothing_selected");
1143 lbl_paeFile.setText(paeFileString);
1144 lbl_paeFile.setToolTipText(paeFileTooltip);
1148 protected void cmbAssSeqStateChanged()
1150 validateSelections();
1153 private FilterOption lastSelected = null;
1156 * Handles the state change event for the 'filter' combo-box and 'invert'
1160 protected void stateChanged(ItemEvent e)
1162 if (e.getSource() instanceof JCheckBox)
1164 updateCurrentView();
1168 if (e.getStateChange() == ItemEvent.SELECTED)
1170 updateCurrentView();
1177 * select structures for viewing by their PDB IDs
1180 * @return true if structures were found and marked as selected
1182 public boolean selectStructure(String... pdbids)
1184 boolean found = false;
1186 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
1187 .getSelectedItem());
1188 String currentView = selectedFilterOpt.getView();
1189 JTable restable = (currentView == VIEWS_FILTER) ? getResultTable()
1190 : (currentView == VIEWS_LOCAL_PDB) ? tbl_local_pdb : null;
1192 if (restable == null)
1194 // can't select (enter PDB ID, or load file - need to also select which
1195 // sequence to associate with)
1199 int pdbIdColIndex = restable.getColumn("PDB Id").getModelIndex();
1200 for (int r = 0; r < restable.getRowCount(); r++)
1202 for (int p = 0; p < pdbids.length; p++)
1204 if (String.valueOf(restable.getValueAt(r, pdbIdColIndex))
1205 .equalsIgnoreCase(pdbids[p]))
1207 restable.setRowSelectionInterval(r, r);
1216 * Handles the 'New View' action
1219 protected void newView_ActionPerformed()
1221 targetView.setSelectedItem(null);
1222 showStructures(false);
1226 * Handles the 'Add to existing viewer' action
1229 protected void add_ActionPerformed()
1231 showStructures(false);
1235 * structure viewer opened by this dialog, or null
1237 private StructureViewer sViewer = null;
1239 public void showStructures(boolean waitUntilFinished)
1242 final StructureSelectionManager ssm = ap.getStructureSelectionManager();
1244 final int preferredHeight = pnl_filter.getHeight();
1245 btn_add.setEnabled(false);
1246 btn_newView.setEnabled(false);
1247 btn_cancel.setEnabled(false);
1248 actionsPanel.setEnabled(false);
1250 final String progress = MessageManager
1251 .getString("label.working_ellipsis");
1252 setProgressBar(progress, progress.hashCode());
1253 Runnable viewStruc = new Runnable()
1258 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
1259 .getSelectedItem());
1260 String currentView = selectedFilterOpt.getView();
1261 JTable restable = (currentView == VIEWS_FILTER) ? getResultTable()
1264 if (currentView == VIEWS_FILTER)
1266 int[] selectedRows = restable.getSelectedRows();
1267 PDBEntry[] pdbEntriesToView = new PDBEntry[selectedRows.length];
1268 List<SequenceI> selectedSeqsToView = new ArrayList<>();
1269 pdbEntriesToView = data.collectSelectedRows(restable,
1270 selectedRows, selectedSeqsToView);
1272 SequenceI[] selectedSeqs = selectedSeqsToView
1273 .toArray(new SequenceI[selectedSeqsToView.size()]);
1274 sViewer = launchStructureViewer(ssm, pdbEntriesToView, ap,
1277 else if (currentView == VIEWS_LOCAL_PDB)
1279 int[] selectedRows = tbl_local_pdb.getSelectedRows();
1280 PDBEntry[] pdbEntriesToView = new PDBEntry[selectedRows.length];
1282 int pdbIdColIndex = tbl_local_pdb.getColumn("PDB Id")
1284 int refSeqColIndex = tbl_local_pdb.getColumn("Ref Sequence")
1286 List<SequenceI> selectedSeqsToView = new ArrayList<>();
1287 for (int row : selectedRows)
1289 PDBEntry pdbEntry = ((PDBEntryTableModel) tbl_local_pdb
1290 .getModel()).getPDBEntryAt(row).getPdbEntry();
1292 pdbEntriesToView[count++] = pdbEntry;
1293 SequenceI selectedSeq = (SequenceI) tbl_local_pdb
1294 .getValueAt(row, refSeqColIndex);
1295 selectedSeqsToView.add(selectedSeq);
1297 SequenceI[] selectedSeqs = selectedSeqsToView
1298 .toArray(new SequenceI[selectedSeqsToView.size()]);
1299 sViewer = launchStructureViewer(ssm, pdbEntriesToView, ap,
1302 else if (currentView == VIEWS_ENTER_ID)
1304 SequenceI userSelectedSeq = ((AssociateSeqOptions) idInputAssSeqPanel
1305 .getCmb_assSeq().getSelectedItem()).getSequence();
1306 if (userSelectedSeq != null)
1308 selectedSequence = userSelectedSeq;
1310 String pdbIdStr = txt_search.getText();
1311 PDBEntry pdbEntry = selectedSequence.getPDBEntry(pdbIdStr);
1312 if (pdbEntry == null)
1314 pdbEntry = new PDBEntry();
1315 if (pdbIdStr.split(":").length > 1)
1317 pdbEntry.setId(pdbIdStr.split(":")[0]);
1318 pdbEntry.setChainCode(
1319 pdbIdStr.split(":")[1].toUpperCase(Locale.ROOT));
1323 pdbEntry.setId(pdbIdStr);
1325 pdbEntry.setType(PDBEntry.Type.PDB);
1326 selectedSequence.getDatasetSequence().addPDBId(pdbEntry);
1329 PDBEntry[] pdbEntriesToView = new PDBEntry[] { pdbEntry };
1330 sViewer = launchStructureViewer(ssm, pdbEntriesToView, ap,
1332 { selectedSequence });
1334 else if (currentView == VIEWS_FROM_FILE)
1336 StructureChooser sc = StructureChooser.this;
1337 TFType tft = (TFType) sc.combo_tempFacAs.getSelectedItem();
1338 String paeFilename = sc.localPdbPaeMatrixFileName;
1339 AssociateSeqOptions assSeqOpt = (AssociateSeqOptions) fileChooserAssSeqPanel
1340 .getCmb_assSeq().getSelectedItem();
1341 SequenceI userSelectedSeq = assSeqOpt.getSequence();
1342 if (userSelectedSeq != null)
1344 selectedSequence = userSelectedSeq;
1346 String pdbFilename = selectedPdbFileName;
1348 StructureChooser.openStructureFileForSequence(ssm, sc, ap,
1349 selectedSequence, true, pdbFilename, tft, paeFilename,
1352 SwingUtilities.invokeLater(new Runnable()
1357 setProgressBar("Complete.", progress.hashCode());
1358 closeAction(preferredHeight);
1359 mainFrame.dispose();
1364 Thread runner = new Thread(viewStruc);
1366 if (waitUntilFinished)
1368 while (sViewer == null ? runner.isAlive()
1369 : (sViewer.sview == null ? true
1370 : !sViewer.sview.hasMapping()))
1375 } catch (InterruptedException ie)
1384 * Answers a structure viewer (new or existing) configured to superimpose
1385 * added structures or not according to the user's choice
1390 StructureViewer getTargetedStructureViewer(StructureSelectionManager ssm)
1392 Object sv = targetView.getSelectedItem();
1394 return sv == null ? new StructureViewer(ssm) : (StructureViewer) sv;
1398 * Adds PDB structures to a new or existing structure viewer
1401 * @param pdbEntriesToView
1406 private StructureViewer launchStructureViewer(
1407 StructureSelectionManager ssm, final PDBEntry[] pdbEntriesToView,
1408 final AlignmentPanel alignPanel, SequenceI[] sequences)
1410 return launchStructureViewer(ssm, pdbEntriesToView, alignPanel,
1414 private StructureViewer launchStructureViewer(
1415 StructureSelectionManager ssm, final PDBEntry[] pdbEntriesToView,
1416 final AlignmentPanel alignPanel, SequenceI[] sequences,
1417 ViewerType viewerType)
1419 long progressId = sequences.hashCode();
1420 setProgressBar(MessageManager
1421 .getString("status.launching_3d_structure_viewer"), progressId);
1422 final StructureViewer theViewer = getTargetedStructureViewer(ssm);
1423 boolean superimpose = chk_superpose.isSelected();
1424 theViewer.setSuperpose(superimpose);
1426 // if we're running in --headless mode make this viewer synchronous
1427 if (Jalview.isHeadlessMode())
1429 theViewer.setAsync(false);
1433 * remember user's choice of superimpose or not
1435 Cache.setProperty(AUTOSUPERIMPOSE,
1436 Boolean.valueOf(superimpose).toString());
1438 setProgressBar(null, progressId);
1439 if (SiftsSettings.isMapWithSifts())
1441 List<SequenceI> seqsWithoutSourceDBRef = new ArrayList<>();
1443 // TODO: skip PDBEntry:Sequence pairs where PDBEntry doesn't look like a
1444 // real PDB ID. For moment, we can also safely do this if there is already
1445 // a known mapping between the PDBEntry and the sequence.
1446 for (SequenceI seq : sequences)
1448 PDBEntry pdbe = pdbEntriesToView[p++];
1449 if (pdbe != null && pdbe.getFile() != null)
1451 StructureMapping[] smm = ssm.getMapping(pdbe.getFile());
1452 if (smm != null && smm.length > 0)
1454 for (StructureMapping sm : smm)
1456 if (sm.getSequence() == seq)
1463 if (seq.getPrimaryDBRefs().isEmpty())
1465 seqsWithoutSourceDBRef.add(seq);
1469 if (!seqsWithoutSourceDBRef.isEmpty())
1471 int y = seqsWithoutSourceDBRef.size();
1472 setProgressBar(MessageManager.formatMessage(
1473 "status.fetching_dbrefs_for_sequences_without_valid_refs",
1475 SequenceI[] seqWithoutSrcDBRef = seqsWithoutSourceDBRef
1476 .toArray(new SequenceI[y]);
1477 DBRefFetcher dbRefFetcher = new DBRefFetcher(seqWithoutSrcDBRef);
1478 dbRefFetcher.fetchDBRefs(true);
1480 setProgressBar("Fetch complete.", progressId); // todo i18n
1483 if (pdbEntriesToView.length > 1)
1486 MessageManager.getString(
1487 "status.fetching_3d_structures_for_selected_entries"),
1489 theViewer.viewStructures(pdbEntriesToView, sequences, alignPanel,
1494 setProgressBar(MessageManager.formatMessage(
1495 "status.fetching_3d_structures_for",
1496 pdbEntriesToView[0].getId()), progressId);
1497 // Can we pass a pre-computeMappinged pdbFile?
1498 theViewer.viewStructures(pdbEntriesToView[0], sequences, alignPanel,
1501 setProgressBar(null, progressId);
1502 // remember the last viewer we used...
1503 lastTargetedView = theViewer;
1508 * Populates the combo-box used in associating manually fetched structures to
1509 * a unique sequence when more than one sequence selection is made.
1512 protected void populateCmbAssociateSeqOptions(
1513 JComboBox<AssociateSeqOptions> cmb_assSeq,
1514 JLabel lbl_associateSeq)
1516 cmb_assSeq.removeAllItems();
1518 new AssociateSeqOptions("-Select Associated Seq-", null));
1519 lbl_associateSeq.setVisible(false);
1520 if (selectedSequences.length > 1)
1522 for (SequenceI seq : selectedSequences)
1524 cmb_assSeq.addItem(new AssociateSeqOptions(seq));
1529 String seqName = selectedSequence.getDisplayId(false);
1530 seqName = seqName.length() <= 40 ? seqName : seqName.substring(0, 39);
1531 lbl_associateSeq.setText(seqName);
1532 lbl_associateSeq.setVisible(true);
1533 cmb_assSeq.setVisible(false);
1537 protected boolean isStructuresDiscovered()
1539 return discoveredStructuresSet != null
1540 && !discoveredStructuresSet.isEmpty();
1543 protected int PDB_ID_MIN = 3;// or: (Jalview.isJS() ? 3 : 1); // Bob proposes
1545 // Doing a search for "1" or "1c" is valuable?
1546 // Those work but are enormously slow.
1549 protected void txt_search_ActionPerformed()
1551 String text = txt_search.getText().trim();
1552 if (text.length() >= PDB_ID_MIN)
1559 errorWarning.setLength(0);
1560 isValidPBDEntry = false;
1561 if (text.length() > 0)
1563 // TODO move this pdb id search into the PDB specific
1565 // for moment, it will work fine as is because it is self-contained
1566 String searchTerm = text.toLowerCase(Locale.ROOT);
1567 searchTerm = searchTerm.split(":")[0];
1568 // jalview.bin.Console.outPrintln(">>>>> search term : " +
1570 List<FTSDataColumnI> wantedFields = new ArrayList<>();
1571 FTSRestRequest pdbRequest = new FTSRestRequest();
1572 pdbRequest.setAllowEmptySeq(false);
1573 pdbRequest.setResponseSize(1);
1574 pdbRequest.setFieldToSearchBy("(pdb_id:");
1575 pdbRequest.setWantedFields(wantedFields);
1576 pdbRequest.setSearchTerm(searchTerm + ")");
1577 pdbRequest.setAssociatedSequence(selectedSequence);
1578 FTSRestClientI pdbRestClient = PDBFTSRestClient.getInstance();
1579 wantedFields.add(pdbRestClient.getPrimaryKeyColumn());
1580 FTSRestResponse resultList;
1583 resultList = pdbRestClient.executeRequest(pdbRequest);
1584 } catch (Exception e)
1586 errorWarning.append(e.getMessage());
1590 validateSelections();
1592 if (resultList.getSearchSummary() != null
1593 && resultList.getSearchSummary().size() > 0)
1595 isValidPBDEntry = true;
1598 validateSelections();
1604 protected void tabRefresh()
1606 if (selectedSequences != null)
1608 lbl_loading.setVisible(true);
1609 Thread refreshThread = new Thread(new Runnable()
1614 fetchStructuresMetaData();
1615 // populateFilterComboBox(true, cachedPDBExists);
1618 ((FilterOption) cmb_filterOption.getSelectedItem())
1620 lbl_loading.setVisible(false);
1623 refreshThread.start();
1627 public class PDBEntryTableModel extends AbstractTableModel
1629 String[] columns = { "Ref Sequence", "PDB Id", "Chain", "Type",
1632 private List<CachedPDB> pdbEntries;
1634 public PDBEntryTableModel(List<CachedPDB> pdbEntries)
1636 this.pdbEntries = new ArrayList<>(pdbEntries);
1640 public String getColumnName(int columnIndex)
1642 return columns[columnIndex];
1646 public int getRowCount()
1648 return pdbEntries.size();
1652 public int getColumnCount()
1654 return columns.length;
1658 public boolean isCellEditable(int row, int column)
1664 public Object getValueAt(int rowIndex, int columnIndex)
1666 Object value = "??";
1667 CachedPDB entry = pdbEntries.get(rowIndex);
1668 switch (columnIndex)
1671 value = entry.getSequence();
1674 value = entry.getQualifiedId();
1677 value = entry.getPdbEntry().getChainCode() == null ? "_"
1678 : entry.getPdbEntry().getChainCode();
1681 value = entry.getPdbEntry().getType();
1684 value = entry.getPdbEntry().getFile();
1691 public Class<?> getColumnClass(int columnIndex)
1693 return columnIndex == 0 ? SequenceI.class : PDBEntry.class;
1696 public CachedPDB getPDBEntryAt(int row)
1698 return pdbEntries.get(row);
1703 private class CachedPDB
1705 private SequenceI sequence;
1707 private PDBEntry pdbEntry;
1709 public CachedPDB(SequenceI sequence, PDBEntry pdbEntry)
1711 this.sequence = sequence;
1712 this.pdbEntry = pdbEntry;
1715 public String getQualifiedId()
1717 if (pdbEntry.hasProvider())
1719 return pdbEntry.getProvider() + ":" + pdbEntry.getId();
1721 return pdbEntry.toString();
1724 public SequenceI getSequence()
1729 public PDBEntry getPdbEntry()
1736 private IProgressIndicator progressBar;
1739 public void setProgressBar(String message, long id)
1741 if (!Platform.isHeadless() && progressBar != null)
1742 progressBar.setProgressBar(message, id);
1746 public void registerHandler(long id, IProgressIndicatorHandler handler)
1748 if (progressBar != null)
1749 progressBar.registerHandler(id, handler);
1753 public boolean operationInProgress()
1755 return progressBar == null ? false : progressBar.operationInProgress();
1758 public JalviewStructureDisplayI getOpenedStructureViewer()
1760 return sViewer == null ? null : sViewer.sview;
1764 protected void setFTSDocFieldPrefs(FTSDataColumnPreferences newPrefs)
1766 data.setDocFieldPrefs(newPrefs);
1772 * @return true when all initialisation threads have finished and dialog is
1775 public boolean isDialogVisible()
1777 return mainFrame != null && data != null && cmb_filterOption != null
1778 && mainFrame.isVisible()
1779 && cmb_filterOption.getSelectedItem() != null;
1784 * @return true if the 3D-Beacons query button will/has been displayed
1786 public boolean isCanQueryTDB()
1791 public boolean isNotQueriedTDBYet()
1793 return notQueriedTDBYet;
1797 * Open a single structure file for a given sequence
1799 public static void openStructureFileForSequence(
1800 StructureSelectionManager ssm, StructureChooser sc,
1801 AlignmentPanel ap, SequenceI seq, boolean prompt,
1802 String sFilename, TFType tft, String paeFilename,
1803 boolean doXferSettings)
1805 openStructureFileForSequence(ssm, sc, ap, seq, prompt, sFilename, tft,
1806 paeFilename, false, true, doXferSettings, null);
1809 public static StructureViewer openStructureFileForSequence(
1810 StructureSelectionManager ssm, StructureChooser sc,
1811 AlignmentPanel ap, SequenceI seq, boolean prompt,
1812 String sFilename, TFType tft, String paeFilename,
1813 boolean forceHeadless, boolean showRefAnnotations,
1814 boolean doXferSettings, ViewerType viewerType)
1816 StructureViewer sv = null;
1817 boolean headless = forceHeadless;
1822 // suppress structure viewer's external service queries
1823 sc = new StructureChooser(new SequenceI[] { seq }, seq, ap, false,
1828 ssm = ap.getStructureSelectionManager();
1831 PDBEntry fileEntry = new AssociatePdbFileWithSeq().associatePdbWithSeq(
1832 sFilename, DataSourceType.FILE, seq, prompt, Desktop.instance,
1833 tft, paeFilename, doXferSettings);
1835 // if headless, "false" in the sc constructor above will avoid GUI behaviour
1836 // in sc.launchStructureViewer()
1837 if (!headless && !(viewerType == null))
1839 sv = sc.launchStructureViewer(ssm, new PDBEntry[] { fileEntry }, ap,
1841 { seq }, viewerType);
1844 sc.mainFrame.dispose();
1846 if (showRefAnnotations)
1848 showReferenceAnnotationsForSequence(ap.alignFrame, seq);
1854 public static void showReferenceAnnotationsForSequence(AlignFrame af,
1857 AlignViewport av = af.getCurrentView();
1858 AlignmentI al = av.getAlignment();
1860 List<SequenceI> forSequences = new ArrayList<>();
1861 forSequences.add(sequence);
1862 final Map<SequenceI, List<AlignmentAnnotation>> candidates = new LinkedHashMap<>();
1863 AlignmentUtils.findAddableReferenceAnnotations(forSequences, null,
1865 final SequenceGroup selectionGroup = av.getSelectionGroup();
1866 AlignmentUtils.addReferenceAnnotations(candidates, al, selectionGroup);
1867 for (AlignmentViewPanel ap : af.getAlignPanels())
1869 // required to readjust the height and position of the PAE
1871 ap.adjustAnnotationHeight();