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.seqfetcher.DbSourceProxy;
87 import jalview.ws.sifts.SiftsSettings;
90 * Provides the behaviors for the Structure chooser Panel
95 @SuppressWarnings("serial")
96 public class StructureChooser extends GStructureChooser
97 implements IProgressIndicator
99 private static final String AUTOSUPERIMPOSE = "AUTOSUPERIMPOSE";
102 * warn user if need to fetch more than this many uniprot records at once
104 private static final int THRESHOLD_WARN_UNIPROT_FETCH_NEEDED = 20;
106 private SequenceI selectedSequence;
108 private SequenceI[] selectedSequences;
110 private IProgressIndicator progressIndicator;
112 private Collection<FTSData> discoveredStructuresSet;
114 private StructureChooserQuerySource data;
117 protected FTSDataColumnPreferences getFTSDocFieldPrefs()
119 return data.getDocFieldPrefs();
122 private String selectedPdbFileName;
124 private TFType localPdbTempfacType;
126 private String localPdbPaeMatrixFileName;
128 private boolean isValidPBDEntry;
130 private boolean cachedPDBExists;
132 private Collection<FTSData> lastDiscoveredStructuresSet;
134 private boolean canQueryTDB = false;
136 private boolean notQueriedTDBYet = true;
138 List<SequenceI> seqsWithoutSourceDBRef = null;
140 private boolean showChooserGUI = true;
142 private static StructureViewer lastTargetedView = null;
144 public StructureChooser(SequenceI[] selectedSeqs, SequenceI selectedSeq,
147 this(selectedSeqs, selectedSeq, ap, true);
150 public StructureChooser(SequenceI[] selectedSeqs, SequenceI selectedSeq,
151 AlignmentPanel ap, boolean showGUI)
153 // which FTS engine to use
154 data = StructureChooserQuerySource.getQuerySourceFor(selectedSeqs);
158 this.selectedSequence = selectedSeq;
159 this.selectedSequences = selectedSeqs;
160 this.progressIndicator = (ap == null) ? null : ap.alignFrame;
161 this.showChooserGUI = showGUI;
167 * sets canQueryTDB if protein sequences without a canonical uniprot ref or at
168 * least one structure are discovered.
170 private void populateSeqsWithoutSourceDBRef()
172 seqsWithoutSourceDBRef = new ArrayList<SequenceI>();
173 boolean needCanonical = false;
174 for (SequenceI seq : selectedSequences)
178 int dbRef = ThreeDBStructureChooserQuerySource
179 .checkUniprotRefs(seq.getDBRefs());
184 // need to retrieve canonicals
185 needCanonical = true;
186 seqsWithoutSourceDBRef.add(seq);
190 // could be a sequence with pdb ref
191 if (seq.getAllPDBEntries() == null
192 || seq.getAllPDBEntries().size() == 0)
194 seqsWithoutSourceDBRef.add(seq);
200 // retrieve database refs for protein sequences
201 if (!seqsWithoutSourceDBRef.isEmpty())
206 // triggers display of the 'Query TDB' button
207 notQueriedTDBYet = true;
213 * Initializes parameters used by the Structure Chooser Panel
215 protected void init()
217 if (!Jalview.isHeadlessMode())
219 progressBar = new ProgressBar(this.statusPanel, this.statusBar);
222 chk_superpose.setSelected(Cache.getDefault(AUTOSUPERIMPOSE, true));
223 btn_queryTDB.addActionListener(new ActionListener()
227 public void actionPerformed(ActionEvent e)
229 promptForTDBFetch(false);
233 Executors.defaultThreadFactory().newThread(new Runnable()
238 populateSeqsWithoutSourceDBRef();
239 initialStructureDiscovery();
247 private void initialStructureDiscovery()
249 // check which FTS engine to use
250 data = StructureChooserQuerySource.getQuerySourceFor(selectedSequences);
252 // ensure a filter option is in force for search
253 populateFilterComboBox(true, cachedPDBExists);
255 // looks for any existing structures already loaded
256 // for the sequences (the cached ones)
257 // then queries the StructureChooserQuerySource to
258 // discover more structures.
260 // Possible optimisation is to only begin querying
261 // the structure chooser if there are no cached structures.
263 long startTime = System.currentTimeMillis();
264 updateProgressIndicator(
265 MessageManager.getString("status.loading_cached_pdb_entries"),
267 loadLocalCachedPDBEntries();
268 updateProgressIndicator(null, startTime);
269 updateProgressIndicator(
270 MessageManager.getString("status.searching_for_pdb_structures"),
272 fetchStructuresMetaData();
273 // revise filter options if no results were found
274 populateFilterComboBox(isStructuresDiscovered(), cachedPDBExists);
275 discoverStructureViews();
276 updateProgressIndicator(null, startTime);
277 mainFrame.setVisible(showChooserGUI);
282 * raises dialog for Uniprot fetch followed by 3D beacons search
285 * - when true, don't ask, just fetch
287 public void promptForTDBFetch(boolean ignoreGui)
289 final long progressId = System.currentTimeMillis();
291 // final action after prompting and discovering db refs
292 final Runnable strucDiscovery = new Runnable()
297 mainFrame.setEnabled(false);
298 cmb_filterOption.setEnabled(false);
299 progressBar.setProgressBar(
300 MessageManager.getString("status.searching_3d_beacons"),
302 btn_queryTDB.setEnabled(false);
303 // TODO: warn if no accessions discovered
304 populateSeqsWithoutSourceDBRef();
305 // redo initial discovery - this time with 3d beacons
307 previousWantedFields = null;
308 lastSelected = (FilterOption) cmb_filterOption.getSelectedItem();
309 cmb_filterOption.setSelectedItem(null);
310 cachedPDBExists = false; // reset to initial
311 initialStructureDiscovery();
312 if (!isStructuresDiscovered())
314 progressBar.setProgressBar(MessageManager.getString(
315 "status.no_structures_discovered_from_3d_beacons"),
317 btn_queryTDB.setToolTipText(MessageManager.getString(
318 "status.no_structures_discovered_from_3d_beacons"));
319 btn_queryTDB.setEnabled(false);
320 pnl_queryTDB.setVisible(false);
324 cmb_filterOption.setSelectedIndex(0); // select 'best'
325 btn_queryTDB.setVisible(false);
326 pnl_queryTDB.setVisible(false);
327 progressBar.setProgressBar(null, progressId);
329 mainFrame.setEnabled(true);
330 cmb_filterOption.setEnabled(true);
334 final FetchFinishedListenerI afterDbRefFetch = new FetchFinishedListenerI()
338 public void finished()
340 // filter has been selected, so we set flag to remove ourselves
341 notQueriedTDBYet = false;
342 // new thread to discover structures - via 3d beacons
343 Executors.defaultThreadFactory().newThread(strucDiscovery).start();
348 // fetch db refs if OK pressed
349 final Runnable discoverCanonicalDBrefs = () -> {
350 btn_queryTDB.setEnabled(false);
351 populateSeqsWithoutSourceDBRef();
353 final int y = seqsWithoutSourceDBRef.size();
356 final SequenceI[] seqWithoutSrcDBRef = seqsWithoutSourceDBRef
357 .toArray(new SequenceI[y]);
358 DBRefFetcher dbRefFetcher = new DBRefFetcher(seqWithoutSrcDBRef,
359 progressBar, new DbSourceProxy[]
360 { new jalview.ws.dbsources.Uniprot() }, null, false);
361 dbRefFetcher.addListener(afterDbRefFetch);
362 // ideally this would also gracefully run with callbacks
364 dbRefFetcher.fetchDBRefs(true);
368 // call finished action directly
369 afterDbRefFetch.finished();
372 final Runnable revertview = () -> {
373 if (lastSelected != null)
375 cmb_filterOption.setSelectedItem(lastSelected);
378 int threshold = Cache.getDefault("UNIPROT_AUTOFETCH_THRESHOLD",
379 THRESHOLD_WARN_UNIPROT_FETCH_NEEDED);
380 Console.debug("Using Uniprot fetch threshold of " + threshold);
381 if (ignoreGui || seqsWithoutSourceDBRef.size() < threshold)
383 Executors.newSingleThreadExecutor().submit(discoverCanonicalDBrefs);
386 // need cancel and no to result in the discoverPDB action - mocked is
387 // 'cancel' TODO: mock should be OK
389 StructureChooser thisSC = this;
390 JvOptionPane.newOptionDialog(thisSC.getFrame())
391 .setResponseHandler(JvOptionPane.OK_OPTION,
392 discoverCanonicalDBrefs)
393 .setResponseHandler(JvOptionPane.CANCEL_OPTION, revertview)
394 .setResponseHandler(JvOptionPane.NO_OPTION, revertview)
396 MessageManager.formatMessage(
397 "label.fetch_references_for_3dbeacons",
398 seqsWithoutSourceDBRef.size()),
399 MessageManager.getString("label.3dbeacons"),
400 JvOptionPane.YES_NO_OPTION, JvOptionPane.PLAIN_MESSAGE,
402 { MessageManager.getString("action.ok"),
403 MessageManager.getString("action.cancel") },
404 MessageManager.getString("action.ok"), false);
408 * Builds a drop-down choice list of existing structure viewers to which new
409 * structures may be added. If this list is empty then it, and the 'Add'
410 * button, are hidden.
412 private void discoverStructureViews()
414 if (Desktop.instance != null)
416 targetView.removeAllItems();
417 if (lastTargetedView != null && !lastTargetedView.isVisible())
419 lastTargetedView = null;
421 int linkedViewsAt = 0;
422 for (StructureViewerBase view : Desktop.instance
423 .getStructureViewers(null, null))
425 StructureViewer viewHandler = (lastTargetedView != null
426 && lastTargetedView.sview == view) ? lastTargetedView
427 : StructureViewer.reconfigure(view);
429 if (view.isLinkedWith(ap))
431 targetView.insertItemAt(viewHandler, linkedViewsAt++);
435 targetView.addItem(viewHandler);
440 * show option to Add to viewer if at least 1 viewer found
442 targetView.setVisible(false);
443 if (targetView.getItemCount() > 0)
445 targetView.setVisible(true);
446 if (lastTargetedView != null)
448 targetView.setSelectedItem(lastTargetedView);
452 targetView.setSelectedIndex(0);
455 btn_add.setVisible(targetView.isVisible());
460 * Updates the progress indicator with the specified message
463 * displayed message for the operation
465 * unique handle for this indicator
467 protected void updateProgressIndicator(String message, long id)
469 if (progressIndicator != null)
471 progressIndicator.setProgressBar(message, id);
476 * Retrieve meta-data for all the structure(s) for a given sequence(s) in a
479 void fetchStructuresMetaData()
481 long startTime = System.currentTimeMillis();
482 Collection<FTSDataColumnI> wantedFields = data.getDocFieldPrefs()
483 .getStructureSummaryFields();
485 discoveredStructuresSet = new LinkedHashSet<>();
486 HashSet<String> errors = new HashSet<>();
488 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
491 for (SequenceI seq : selectedSequences)
494 FTSRestResponse resultList;
497 resultList = data.fetchStructuresMetaData(seq, wantedFields,
498 selectedFilterOpt, !chk_invertFilter.isSelected());
499 // null response means the FTSengine didn't yield a query for this
500 // consider designing a special exception if we really wanted to be
502 if (resultList == null)
506 } catch (Exception e)
509 errors.add(e.getMessage());
512 if (resultList.getSearchSummary() != null
513 && !resultList.getSearchSummary().isEmpty())
515 discoveredStructuresSet.addAll(resultList.getSearchSummary());
519 int noOfStructuresFound = 0;
520 String totalTime = (System.currentTimeMillis() - startTime)
522 if (discoveredStructuresSet != null
523 && !discoveredStructuresSet.isEmpty())
526 .setModel(data.getTableModel(discoveredStructuresSet));
528 noOfStructuresFound = discoveredStructuresSet.size();
529 lastDiscoveredStructuresSet = discoveredStructuresSet;
530 mainFrame.setTitle(MessageManager.formatMessage(
531 "label.structure_chooser_no_of_structures",
532 noOfStructuresFound, totalTime));
536 mainFrame.setTitle(MessageManager
537 .getString("label.structure_chooser_manual_association"));
538 if (errors.size() > 0)
540 StringBuilder errorMsg = new StringBuilder();
541 for (String error : errors)
543 errorMsg.append(error).append("\n");
545 JvOptionPane.showMessageDialog(this, errorMsg.toString(),
546 MessageManager.getString("label.pdb_web-service_error"),
547 JvOptionPane.ERROR_MESSAGE);
552 protected void loadLocalCachedPDBEntries()
554 ArrayList<CachedPDB> entries = new ArrayList<>();
555 for (SequenceI seq : selectedSequences)
557 if (seq.getDatasetSequence() != null
558 && seq.getDatasetSequence().getAllPDBEntries() != null)
560 for (PDBEntry pdbEntry : seq.getDatasetSequence()
563 if (pdbEntry.getFile() != null)
565 entries.add(new CachedPDB(seq, pdbEntry));
570 cachedPDBExists = !entries.isEmpty();
571 PDBEntryTableModel tableModelx = new PDBEntryTableModel(entries);
572 tbl_local_pdb.setModel(tableModelx);
576 * Filters a given list of discovered structures based on supplied argument
578 * @param fieldToFilterBy
579 * the field to filter by
581 void filterResultSet(final String fieldToFilterBy)
583 Thread filterThread = new Thread(new Runnable()
589 long startTime = System.currentTimeMillis();
590 lbl_loading.setVisible(true);
591 Collection<FTSDataColumnI> wantedFields = data.getDocFieldPrefs()
592 .getStructureSummaryFields();
593 Collection<FTSData> filteredResponse = new HashSet<>();
594 HashSet<String> errors = new HashSet<>();
596 for (SequenceI seq : selectedSequences)
599 FTSRestResponse resultList;
602 resultList = data.selectFirstRankedQuery(seq,
603 discoveredStructuresSet, wantedFields, fieldToFilterBy,
604 !chk_invertFilter.isSelected());
606 } catch (Exception e)
609 errors.add(e.getMessage());
612 if (resultList.getSearchSummary() != null
613 && !resultList.getSearchSummary().isEmpty())
615 filteredResponse.addAll(resultList.getSearchSummary());
619 String totalTime = (System.currentTimeMillis() - startTime)
621 if (!filteredResponse.isEmpty())
623 final int filterResponseCount = filteredResponse.size();
624 Collection<FTSData> reorderedStructuresSet = new LinkedHashSet<>();
625 reorderedStructuresSet.addAll(filteredResponse);
626 reorderedStructuresSet.addAll(discoveredStructuresSet);
628 .setModel(data.getTableModel(reorderedStructuresSet));
630 FTSRestResponse.configureTableColumn(getResultTable(),
631 wantedFields, tempUserPrefs);
632 getResultTable().getColumn("Ref Sequence").setPreferredWidth(120);
633 getResultTable().getColumn("Ref Sequence").setMinWidth(100);
634 getResultTable().getColumn("Ref Sequence").setMaxWidth(200);
635 // Update table selection model here
636 getResultTable().addRowSelectionInterval(0,
637 filterResponseCount - 1);
638 mainFrame.setTitle(MessageManager.formatMessage(
639 "label.structure_chooser_filter_time", totalTime));
643 mainFrame.setTitle(MessageManager.formatMessage(
644 "label.structure_chooser_filter_time", totalTime));
645 if (errors.size() > 0)
647 StringBuilder errorMsg = new StringBuilder();
648 for (String error : errors)
650 errorMsg.append(error).append("\n");
652 JvOptionPane.showMessageDialog(null, errorMsg.toString(),
653 MessageManager.getString("label.pdb_web-service_error"),
654 JvOptionPane.ERROR_MESSAGE);
658 lbl_loading.setVisible(false);
660 validateSelections();
663 filterThread.start();
667 * Handles action event for btn_pdbFromFile
670 protected void pdbFromFile_actionPerformed()
672 // TODO: JAL-3048 not needed for Jalview-JS until JSmol dep and
675 JalviewFileChooser chooser = new JalviewFileChooser(
676 Cache.getProperty("LAST_DIRECTORY"));
677 chooser.setFileView(new JalviewFileView());
678 chooser.setDialogTitle(
679 MessageManager.formatMessage("label.select_pdb_file_for",
680 selectedSequence.getDisplayId(false)));
681 chooser.setToolTipText(MessageManager.formatMessage(
682 "label.load_pdb_file_associate_with_sequence",
683 selectedSequence.getDisplayId(false)));
685 int value = chooser.showOpenDialog(null);
686 if (value == JalviewFileChooser.APPROVE_OPTION)
688 selectedPdbFileName = chooser.getSelectedFile().getPath();
689 Cache.setProperty("LAST_DIRECTORY", selectedPdbFileName);
690 boolean guessTFType = localPdbPaeMatrixFileName == null;
691 localPdbPaeMatrixFileName = guessPAEFilename();
692 guessTFType |= localPdbPaeMatrixFileName != null;
693 Regex alphaFold = JmolParser.getNewAlphafoldValidator();
695 && alphaFold.search(new File(selectedPdbFileName).getName())
696 && !tempFacAsChanged)
698 // localPdbPaeMatrixFileName was null and now isn't and filename could
699 // well be AlphaFold and user hasn't adjusted the tempFacType
700 combo_tempFacAs.setSelectedItem(TFType.PLDDT);
702 validateSelections();
707 * Handles action event for btn_pdbFromFile
710 protected void paeMatrixFile_actionPerformed()
712 File pdbFile = new File(selectedPdbFileName);
713 String setFile = Cache.getProperty("LAST_DIRECTORY");
714 if (localPdbPaeMatrixFileName != null)
716 File paeFile = new File(localPdbPaeMatrixFileName);
717 if (paeFile.exists())
718 setFile = paeFile.getAbsolutePath();
719 else if (paeFile.getParentFile().exists())
720 setFile = paeFile.getParentFile().getAbsolutePath();
724 String guess = guessPAEFilename();
728 JalviewFileChooser chooser = new JalviewFileChooser(setFile);
729 chooser.setFileView(new JalviewFileView());
730 chooser.setDialogTitle(MessageManager.formatMessage(
731 "label.select_pae_matrix_file_for", pdbFile.getName()));
732 chooser.setToolTipText(MessageManager.formatMessage(
733 "label.load_pae_matrix_file_associate_with_structure",
736 int value = chooser.showOpenDialog(null);
737 if (value == JalviewFileChooser.APPROVE_OPTION)
739 localPdbPaeMatrixFileName = chooser.getSelectedFile().getPath();
740 Cache.setProperty("LAST_DIRECTORY", localPdbPaeMatrixFileName);
742 validateAssociationFromFile();
745 private String guessPAEFilename()
747 if (selectedPdbFileName.toLowerCase(Locale.ROOT).endsWith(".pdb")
748 || selectedPdbFileName.toLowerCase(Locale.ROOT)
751 String jsonExt = selectedPdbFileName.substring(0,
752 selectedPdbFileName.length() - 4) + ".json";
753 // AlphaFold naming scheme
754 String guessFile1 = StringUtils.replaceLast(jsonExt, "model",
755 "predicted_aligned_error");
756 // nf-core mode naming scheme
757 String guessFile2 = StringUtils.replaceLast(jsonExt, ".json",
759 if (new File(guessFile1).exists())
763 else if (new File(jsonExt).exists())
767 else if (new File(guessFile2).exists())
776 * Populates the filter combo-box options dynamically depending on discovered
779 protected void populateFilterComboBox(boolean haveData,
780 boolean cachedPDBExist)
782 populateFilterComboBox(haveData, cachedPDBExist, null);
786 * Populates the filter combo-box options dynamically depending on discovered
789 protected void populateFilterComboBox(boolean haveData,
790 boolean cachedPDBExist, FilterOption lastSel)
794 * temporarily suspend the change listener behaviour
796 cmb_filterOption.removeItemListener(this);
798 cmb_filterOption.removeAllItems();
801 List<FilterOption> filters = data
802 .getAvailableFilterOptions(VIEWS_FILTER);
803 data.updateAvailableFilterOptions(VIEWS_FILTER, filters,
804 lastDiscoveredStructuresSet);
806 for (FilterOption filter : filters)
808 if (lastSel != null && filter.equals(lastSel))
813 cmb_filterOption.addItem(filter);
817 cmb_filterOption.addItem(
818 new FilterOption(MessageManager.getString("label.enter_pdb_id"),
819 "-", VIEWS_ENTER_ID, false, null));
820 cmb_filterOption.addItem(
821 new FilterOption(MessageManager.getString("label.from_file"),
822 "-", VIEWS_FROM_FILE, false, null));
823 if (canQueryTDB && notQueriedTDBYet)
825 btn_queryTDB.setVisible(true);
826 pnl_queryTDB.setVisible(true);
831 FilterOption cachedOption = new FilterOption(
832 MessageManager.getString("label.cached_structures"), "-",
833 VIEWS_LOCAL_PDB, false, null);
834 cmb_filterOption.addItem(cachedOption);
837 cmb_filterOption.setSelectedItem(cachedOption);
842 cmb_filterOption.setSelectedIndex(selSet);
844 cmb_filterOption.addItemListener(this);
848 * Updates the displayed view based on the selected filter option
850 protected void updateCurrentView()
852 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
855 if (lastSelected == selectedFilterOpt)
857 // don't need to do anything, probably
860 // otherwise, record selection
861 // and update the layout and dialog accordingly
862 lastSelected = selectedFilterOpt;
864 layout_switchableViews.show(pnl_switchableViews,
865 selectedFilterOpt.getView());
866 String filterTitle = mainFrame.getTitle();
867 mainFrame.setTitle(frameTitle);
868 chk_invertFilter.setVisible(false);
870 if (selectedFilterOpt.getView() == VIEWS_FILTER)
872 mainFrame.setTitle(filterTitle);
873 // TDB Query has no invert as yet
874 chk_invertFilter.setVisible(selectedFilterOpt
875 .getQuerySource() instanceof PDBStructureChooserQuerySource);
877 if (data != selectedFilterOpt.getQuerySource()
878 || data.needsRefetch(selectedFilterOpt))
880 data = selectedFilterOpt.getQuerySource();
881 // rebuild the views completely, since prefs will also change
887 filterResultSet(selectedFilterOpt.getValue());
890 else if (selectedFilterOpt.getView() == VIEWS_ENTER_ID
891 || selectedFilterOpt.getView() == VIEWS_FROM_FILE)
893 mainFrame.setTitle(MessageManager
894 .getString("label.structure_chooser_manual_association"));
895 idInputAssSeqPanel.loadCmbAssSeq();
896 fileChooserAssSeqPanel.loadCmbAssSeq();
898 validateSelections();
902 * Validates user selection and enables the 'Add' and 'New View' buttons if
903 * all parameters are correct (the Add button will only be visible if there is
904 * at least one existing structure viewer open). This basically means at least
905 * one structure selected and no error messages.
907 * The 'Superpose Structures' option is enabled if either more than one
908 * structure is selected, or the 'Add' to existing view option is enabled, and
909 * disabled if the only option is to open a new view of a single structure.
912 protected void validateSelections()
914 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
916 btn_add.setEnabled(false);
917 String currentView = selectedFilterOpt.getView();
918 int selectedCount = 0;
919 if (currentView == VIEWS_FILTER)
921 selectedCount = getResultTable().getSelectedRows().length;
922 if (selectedCount > 0)
924 btn_add.setEnabled(true);
927 else if (currentView == VIEWS_LOCAL_PDB)
929 selectedCount = tbl_local_pdb.getSelectedRows().length;
930 if (selectedCount > 0)
932 btn_add.setEnabled(true);
935 else if (currentView == VIEWS_ENTER_ID)
937 validateAssociationEnterPdb();
939 else if (currentView == VIEWS_FROM_FILE)
941 validateAssociationFromFile();
944 btn_newView.setEnabled(btn_add.isEnabled());
947 * enable 'Superpose' option if more than one structure is selected,
948 * or there are view(s) available to add structure(s) to
951 .setEnabled(selectedCount > 1 || targetView.getItemCount() > 0);
955 protected boolean showPopupFor(int selectedRow, int x, int y)
957 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
959 String currentView = selectedFilterOpt.getView();
961 if (currentView == VIEWS_FILTER
962 && data instanceof ThreeDBStructureChooserQuerySource)
965 TDB_FTSData row = ((ThreeDBStructureChooserQuerySource) data)
966 .getFTSDataFor(getResultTable(), selectedRow,
967 discoveredStructuresSet);
968 String pageUrl = row.getModelViewUrl();
969 JPopupMenu popup = new JPopupMenu("3D Beacons");
970 JMenuItem viewUrl = new JMenuItem("View model web page");
971 viewUrl.addActionListener(new ActionListener()
974 public void actionPerformed(ActionEvent e)
976 Desktop.showUrl(pageUrl);
980 SwingUtilities.invokeLater(new Runnable()
985 popup.show(getResultTable(), x, y);
990 // event not handled by us
995 * Validates inputs from the Manual PDB entry panel
997 protected void validateAssociationEnterPdb()
999 AssociateSeqOptions assSeqOpt = (AssociateSeqOptions) idInputAssSeqPanel
1000 .getCmb_assSeq().getSelectedItem();
1001 lbl_pdbManualFetchStatus.setIcon(errorImage);
1002 lbl_pdbManualFetchStatus.setToolTipText("");
1003 if (txt_search.getText().length() > 0)
1005 lbl_pdbManualFetchStatus.setToolTipText(JvSwingUtils.wrapTooltip(true,
1006 MessageManager.formatMessage("info.no_pdb_entry_found_for",
1007 txt_search.getText())));
1010 if (errorWarning.length() > 0)
1012 lbl_pdbManualFetchStatus.setIcon(warningImage);
1013 lbl_pdbManualFetchStatus.setToolTipText(
1014 JvSwingUtils.wrapTooltip(true, errorWarning.toString()));
1017 if (selectedSequences.length == 1 || !assSeqOpt.getName()
1018 .equalsIgnoreCase("-Select Associated Seq-"))
1020 txt_search.setEnabled(true);
1021 if (isValidPBDEntry)
1023 btn_add.setEnabled(true);
1024 lbl_pdbManualFetchStatus.setToolTipText("");
1025 lbl_pdbManualFetchStatus.setIcon(goodImage);
1030 txt_search.setEnabled(false);
1031 lbl_pdbManualFetchStatus.setIcon(errorImage);
1036 * Validates inputs for the manual PDB file selection options
1038 protected void validateAssociationFromFile()
1040 AssociateSeqOptions assSeqOpt = (AssociateSeqOptions) fileChooserAssSeqPanel
1041 .getCmb_assSeq().getSelectedItem();
1042 // lbl_fromFileStatus.setIcon(errorImage);
1043 String pdbFileString = "";
1044 String pdbFileTooltip = "";
1045 if (selectedSequences.length == 1 || (assSeqOpt != null && !assSeqOpt
1046 .getName().equalsIgnoreCase("-Select Associated Seq-")))
1048 btn_pdbFromFile.setEnabled(true);
1049 if (selectedPdbFileName != null && selectedPdbFileName.length() > 0)
1051 btn_add.setEnabled(true);
1052 // lbl_fromFileStatus.setIcon(goodImage);
1053 pdbFileString = new File(selectedPdbFileName).getName();
1054 pdbFileTooltip = new File(selectedPdbFileName).getAbsolutePath();
1055 setPdbOptionsEnabled(true);
1059 pdbFileString = MessageManager.getString("label.none");
1060 pdbFileTooltip = MessageManager.getString("label.nothing_selected");
1065 btn_pdbFromFile.setEnabled(false);
1066 // lbl_fromFileStatus.setIcon(errorImage);
1067 pdbFileString = MessageManager.getString("label.none");
1068 pdbFileTooltip = MessageManager.getString("label.nothing_selected");
1070 lbl_pdbFile.setText(pdbFileString);
1071 lbl_pdbFile.setToolTipText(pdbFileTooltip);
1074 String paeFileString = "";
1075 String paeFileTooltip = "";
1076 if (localPdbPaeMatrixFileName != null
1077 && localPdbPaeMatrixFileName.length() > 0)
1079 paeFileString = new File(localPdbPaeMatrixFileName).getName();
1080 paeFileTooltip = new File(localPdbPaeMatrixFileName)
1085 paeFileString = MessageManager.getString("label.none");
1086 paeFileTooltip = MessageManager.getString("label.nothing_selected");
1088 lbl_paeFile.setText(paeFileString);
1089 lbl_paeFile.setToolTipText(paeFileTooltip);
1093 protected void cmbAssSeqStateChanged()
1095 validateSelections();
1098 private FilterOption lastSelected = null;
1101 * Handles the state change event for the 'filter' combo-box and 'invert'
1105 protected void stateChanged(ItemEvent e)
1107 if (e.getSource() instanceof JCheckBox)
1109 updateCurrentView();
1113 if (e.getStateChange() == ItemEvent.SELECTED)
1115 updateCurrentView();
1122 * select structures for viewing by their PDB IDs
1125 * @return true if structures were found and marked as selected
1127 public boolean selectStructure(String... pdbids)
1129 boolean found = false;
1131 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
1132 .getSelectedItem());
1133 String currentView = selectedFilterOpt.getView();
1134 JTable restable = (currentView == VIEWS_FILTER) ? getResultTable()
1135 : (currentView == VIEWS_LOCAL_PDB) ? tbl_local_pdb : null;
1137 if (restable == null)
1139 // can't select (enter PDB ID, or load file - need to also select which
1140 // sequence to associate with)
1144 int pdbIdColIndex = restable.getColumn("PDB Id").getModelIndex();
1145 for (int r = 0; r < restable.getRowCount(); r++)
1147 for (int p = 0; p < pdbids.length; p++)
1149 if (String.valueOf(restable.getValueAt(r, pdbIdColIndex))
1150 .equalsIgnoreCase(pdbids[p]))
1152 restable.setRowSelectionInterval(r, r);
1161 * Handles the 'New View' action
1164 protected void newView_ActionPerformed()
1166 targetView.setSelectedItem(null);
1167 showStructures(false);
1171 * Handles the 'Add to existing viewer' action
1174 protected void add_ActionPerformed()
1176 showStructures(false);
1180 * structure viewer opened by this dialog, or null
1182 private StructureViewer sViewer = null;
1184 public void showStructures(boolean waitUntilFinished)
1187 final StructureSelectionManager ssm = ap.getStructureSelectionManager();
1189 final int preferredHeight = pnl_filter.getHeight();
1191 Runnable viewStruc = new Runnable()
1196 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
1197 .getSelectedItem());
1198 String currentView = selectedFilterOpt.getView();
1199 JTable restable = (currentView == VIEWS_FILTER) ? getResultTable()
1202 if (currentView == VIEWS_FILTER)
1204 int[] selectedRows = restable.getSelectedRows();
1205 PDBEntry[] pdbEntriesToView = new PDBEntry[selectedRows.length];
1206 List<SequenceI> selectedSeqsToView = new ArrayList<>();
1207 pdbEntriesToView = data.collectSelectedRows(restable,
1208 selectedRows, selectedSeqsToView);
1210 SequenceI[] selectedSeqs = selectedSeqsToView
1211 .toArray(new SequenceI[selectedSeqsToView.size()]);
1212 sViewer = launchStructureViewer(ssm, pdbEntriesToView, ap,
1215 else if (currentView == VIEWS_LOCAL_PDB)
1217 int[] selectedRows = tbl_local_pdb.getSelectedRows();
1218 PDBEntry[] pdbEntriesToView = new PDBEntry[selectedRows.length];
1220 int pdbIdColIndex = tbl_local_pdb.getColumn("PDB Id")
1222 int refSeqColIndex = tbl_local_pdb.getColumn("Ref Sequence")
1224 List<SequenceI> selectedSeqsToView = new ArrayList<>();
1225 for (int row : selectedRows)
1227 PDBEntry pdbEntry = ((PDBEntryTableModel) tbl_local_pdb
1228 .getModel()).getPDBEntryAt(row).getPdbEntry();
1230 pdbEntriesToView[count++] = pdbEntry;
1231 SequenceI selectedSeq = (SequenceI) tbl_local_pdb
1232 .getValueAt(row, refSeqColIndex);
1233 selectedSeqsToView.add(selectedSeq);
1235 SequenceI[] selectedSeqs = selectedSeqsToView
1236 .toArray(new SequenceI[selectedSeqsToView.size()]);
1237 sViewer = launchStructureViewer(ssm, pdbEntriesToView, ap,
1240 else if (currentView == VIEWS_ENTER_ID)
1242 SequenceI userSelectedSeq = ((AssociateSeqOptions) idInputAssSeqPanel
1243 .getCmb_assSeq().getSelectedItem()).getSequence();
1244 if (userSelectedSeq != null)
1246 selectedSequence = userSelectedSeq;
1248 String pdbIdStr = txt_search.getText();
1249 PDBEntry pdbEntry = selectedSequence.getPDBEntry(pdbIdStr);
1250 if (pdbEntry == null)
1252 pdbEntry = new PDBEntry();
1253 if (pdbIdStr.split(":").length > 1)
1255 pdbEntry.setId(pdbIdStr.split(":")[0]);
1256 pdbEntry.setChainCode(
1257 pdbIdStr.split(":")[1].toUpperCase(Locale.ROOT));
1261 pdbEntry.setId(pdbIdStr);
1263 pdbEntry.setType(PDBEntry.Type.PDB);
1264 selectedSequence.getDatasetSequence().addPDBId(pdbEntry);
1267 PDBEntry[] pdbEntriesToView = new PDBEntry[] { pdbEntry };
1268 sViewer = launchStructureViewer(ssm, pdbEntriesToView, ap,
1270 { selectedSequence });
1272 else if (currentView == VIEWS_FROM_FILE)
1274 StructureChooser sc = StructureChooser.this;
1275 TFType tft = (TFType) sc.combo_tempFacAs.getSelectedItem();
1276 String paeFilename = sc.localPdbPaeMatrixFileName;
1277 AssociateSeqOptions assSeqOpt = (AssociateSeqOptions) fileChooserAssSeqPanel
1278 .getCmb_assSeq().getSelectedItem();
1279 SequenceI userSelectedSeq = assSeqOpt.getSequence();
1280 if (userSelectedSeq != null)
1281 selectedSequence = userSelectedSeq;
1282 String pdbFilename = selectedPdbFileName;
1284 StructureChooser.openStructureFileForSequence(ssm, sc, ap,
1285 selectedSequence, true, pdbFilename, tft, paeFilename,
1288 SwingUtilities.invokeLater(new Runnable()
1293 closeAction(preferredHeight);
1294 mainFrame.dispose();
1299 Thread runner = new Thread(viewStruc);
1301 if (waitUntilFinished)
1303 while (sViewer == null ? runner.isAlive()
1304 : (sViewer.sview == null ? true
1305 : !sViewer.sview.hasMapping()))
1310 } catch (InterruptedException ie)
1319 * Answers a structure viewer (new or existing) configured to superimpose
1320 * added structures or not according to the user's choice
1325 StructureViewer getTargetedStructureViewer(StructureSelectionManager ssm)
1327 Object sv = targetView.getSelectedItem();
1329 return sv == null ? new StructureViewer(ssm) : (StructureViewer) sv;
1333 * Adds PDB structures to a new or existing structure viewer
1336 * @param pdbEntriesToView
1341 private StructureViewer launchStructureViewer(
1342 StructureSelectionManager ssm, final PDBEntry[] pdbEntriesToView,
1343 final AlignmentPanel alignPanel, SequenceI[] sequences)
1345 return launchStructureViewer(ssm, pdbEntriesToView, alignPanel,
1349 private StructureViewer launchStructureViewer(
1350 StructureSelectionManager ssm, final PDBEntry[] pdbEntriesToView,
1351 final AlignmentPanel alignPanel, SequenceI[] sequences,
1352 ViewerType viewerType)
1354 long progressId = sequences.hashCode();
1355 setProgressBar(MessageManager
1356 .getString("status.launching_3d_structure_viewer"), progressId);
1357 final StructureViewer theViewer = getTargetedStructureViewer(ssm);
1358 boolean superimpose = chk_superpose.isSelected();
1359 theViewer.setSuperpose(superimpose);
1362 * remember user's choice of superimpose or not
1364 Cache.setProperty(AUTOSUPERIMPOSE,
1365 Boolean.valueOf(superimpose).toString());
1367 setProgressBar(null, progressId);
1368 if (SiftsSettings.isMapWithSifts())
1370 List<SequenceI> seqsWithoutSourceDBRef = new ArrayList<>();
1372 // TODO: skip PDBEntry:Sequence pairs where PDBEntry doesn't look like a
1373 // real PDB ID. For moment, we can also safely do this if there is already
1374 // a known mapping between the PDBEntry and the sequence.
1375 for (SequenceI seq : sequences)
1377 PDBEntry pdbe = pdbEntriesToView[p++];
1378 if (pdbe != null && pdbe.getFile() != null)
1380 StructureMapping[] smm = ssm.getMapping(pdbe.getFile());
1381 if (smm != null && smm.length > 0)
1383 for (StructureMapping sm : smm)
1385 if (sm.getSequence() == seq)
1392 if (seq.getPrimaryDBRefs().isEmpty())
1394 seqsWithoutSourceDBRef.add(seq);
1398 if (!seqsWithoutSourceDBRef.isEmpty())
1400 int y = seqsWithoutSourceDBRef.size();
1401 setProgressBar(MessageManager.formatMessage(
1402 "status.fetching_dbrefs_for_sequences_without_valid_refs",
1404 SequenceI[] seqWithoutSrcDBRef = seqsWithoutSourceDBRef
1405 .toArray(new SequenceI[y]);
1406 DBRefFetcher dbRefFetcher = new DBRefFetcher(seqWithoutSrcDBRef);
1407 dbRefFetcher.fetchDBRefs(true);
1409 setProgressBar("Fetch complete.", progressId); // todo i18n
1412 if (pdbEntriesToView.length > 1)
1415 MessageManager.getString(
1416 "status.fetching_3d_structures_for_selected_entries"),
1418 theViewer.viewStructures(pdbEntriesToView, sequences, alignPanel,
1423 setProgressBar(MessageManager.formatMessage(
1424 "status.fetching_3d_structures_for",
1425 pdbEntriesToView[0].getId()), progressId);
1426 // Can we pass a pre-computeMappinged pdbFile?
1427 theViewer.viewStructures(pdbEntriesToView[0], sequences, alignPanel,
1430 setProgressBar(null, progressId);
1431 // remember the last viewer we used...
1432 lastTargetedView = theViewer;
1437 * Populates the combo-box used in associating manually fetched structures to
1438 * a unique sequence when more than one sequence selection is made.
1441 protected void populateCmbAssociateSeqOptions(
1442 JComboBox<AssociateSeqOptions> cmb_assSeq,
1443 JLabel lbl_associateSeq)
1445 cmb_assSeq.removeAllItems();
1447 new AssociateSeqOptions("-Select Associated Seq-", null));
1448 lbl_associateSeq.setVisible(false);
1449 if (selectedSequences.length > 1)
1451 for (SequenceI seq : selectedSequences)
1453 cmb_assSeq.addItem(new AssociateSeqOptions(seq));
1458 String seqName = selectedSequence.getDisplayId(false);
1459 seqName = seqName.length() <= 40 ? seqName : seqName.substring(0, 39);
1460 lbl_associateSeq.setText(seqName);
1461 lbl_associateSeq.setVisible(true);
1462 cmb_assSeq.setVisible(false);
1466 protected boolean isStructuresDiscovered()
1468 return discoveredStructuresSet != null
1469 && !discoveredStructuresSet.isEmpty();
1472 protected int PDB_ID_MIN = 3;// or: (Jalview.isJS() ? 3 : 1); // Bob proposes
1474 // Doing a search for "1" or "1c" is valuable?
1475 // Those work but are enormously slow.
1478 protected void txt_search_ActionPerformed()
1480 String text = txt_search.getText().trim();
1481 if (text.length() >= PDB_ID_MIN)
1488 errorWarning.setLength(0);
1489 isValidPBDEntry = false;
1490 if (text.length() > 0)
1492 // TODO move this pdb id search into the PDB specific
1494 // for moment, it will work fine as is because it is self-contained
1495 String searchTerm = text.toLowerCase(Locale.ROOT);
1496 searchTerm = searchTerm.split(":")[0];
1497 // System.out.println(">>>>> search term : " + searchTerm);
1498 List<FTSDataColumnI> wantedFields = new ArrayList<>();
1499 FTSRestRequest pdbRequest = new FTSRestRequest();
1500 pdbRequest.setAllowEmptySeq(false);
1501 pdbRequest.setResponseSize(1);
1502 pdbRequest.setFieldToSearchBy("(pdb_id:");
1503 pdbRequest.setWantedFields(wantedFields);
1504 pdbRequest.setSearchTerm(searchTerm + ")");
1505 pdbRequest.setAssociatedSequence(selectedSequence);
1506 FTSRestClientI pdbRestClient = PDBFTSRestClient.getInstance();
1507 wantedFields.add(pdbRestClient.getPrimaryKeyColumn());
1508 FTSRestResponse resultList;
1511 resultList = pdbRestClient.executeRequest(pdbRequest);
1512 } catch (Exception e)
1514 errorWarning.append(e.getMessage());
1518 validateSelections();
1520 if (resultList.getSearchSummary() != null
1521 && resultList.getSearchSummary().size() > 0)
1523 isValidPBDEntry = true;
1526 validateSelections();
1532 protected void tabRefresh()
1534 if (selectedSequences != null)
1536 lbl_loading.setVisible(true);
1537 Thread refreshThread = new Thread(new Runnable()
1542 fetchStructuresMetaData();
1543 // populateFilterComboBox(true, cachedPDBExists);
1546 ((FilterOption) cmb_filterOption.getSelectedItem())
1548 lbl_loading.setVisible(false);
1551 refreshThread.start();
1555 public class PDBEntryTableModel extends AbstractTableModel
1557 String[] columns = { "Ref Sequence", "PDB Id", "Chain", "Type",
1560 private List<CachedPDB> pdbEntries;
1562 public PDBEntryTableModel(List<CachedPDB> pdbEntries)
1564 this.pdbEntries = new ArrayList<>(pdbEntries);
1568 public String getColumnName(int columnIndex)
1570 return columns[columnIndex];
1574 public int getRowCount()
1576 return pdbEntries.size();
1580 public int getColumnCount()
1582 return columns.length;
1586 public boolean isCellEditable(int row, int column)
1592 public Object getValueAt(int rowIndex, int columnIndex)
1594 Object value = "??";
1595 CachedPDB entry = pdbEntries.get(rowIndex);
1596 switch (columnIndex)
1599 value = entry.getSequence();
1602 value = entry.getQualifiedId();
1605 value = entry.getPdbEntry().getChainCode() == null ? "_"
1606 : entry.getPdbEntry().getChainCode();
1609 value = entry.getPdbEntry().getType();
1612 value = entry.getPdbEntry().getFile();
1619 public Class<?> getColumnClass(int columnIndex)
1621 return columnIndex == 0 ? SequenceI.class : PDBEntry.class;
1624 public CachedPDB getPDBEntryAt(int row)
1626 return pdbEntries.get(row);
1631 private class CachedPDB
1633 private SequenceI sequence;
1635 private PDBEntry pdbEntry;
1637 public CachedPDB(SequenceI sequence, PDBEntry pdbEntry)
1639 this.sequence = sequence;
1640 this.pdbEntry = pdbEntry;
1643 public String getQualifiedId()
1645 if (pdbEntry.hasProvider())
1647 return pdbEntry.getProvider() + ":" + pdbEntry.getId();
1649 return pdbEntry.toString();
1652 public SequenceI getSequence()
1657 public PDBEntry getPdbEntry()
1664 private IProgressIndicator progressBar;
1667 public void setProgressBar(String message, long id)
1669 if (!Platform.isHeadless() && progressBar != null)
1670 progressBar.setProgressBar(message, id);
1674 public void registerHandler(long id, IProgressIndicatorHandler handler)
1676 if (progressBar != null)
1677 progressBar.registerHandler(id, handler);
1681 public boolean operationInProgress()
1683 return progressBar == null ? false : progressBar.operationInProgress();
1686 public JalviewStructureDisplayI getOpenedStructureViewer()
1688 return sViewer == null ? null : sViewer.sview;
1692 protected void setFTSDocFieldPrefs(FTSDataColumnPreferences newPrefs)
1694 data.setDocFieldPrefs(newPrefs);
1700 * @return true when all initialisation threads have finished and dialog is
1703 public boolean isDialogVisible()
1705 return mainFrame != null && data != null && cmb_filterOption != null
1706 && mainFrame.isVisible()
1707 && cmb_filterOption.getSelectedItem() != null;
1712 * @return true if the 3D-Beacons query button will/has been displayed
1714 public boolean isCanQueryTDB()
1719 public boolean isNotQueriedTDBYet()
1721 return notQueriedTDBYet;
1725 * Open a single structure file for a given sequence
1727 public static void openStructureFileForSequence(
1728 StructureSelectionManager ssm, StructureChooser sc,
1729 AlignmentPanel ap, SequenceI seq, boolean prompt,
1730 String sFilename, TFType tft, String paeFilename,
1731 boolean doXferSettings)
1733 openStructureFileForSequence(ssm, sc, ap, seq, prompt, sFilename, tft,
1734 paeFilename, false, true, doXferSettings, null);
1737 public static StructureViewer openStructureFileForSequence(
1738 StructureSelectionManager ssm, StructureChooser sc,
1739 AlignmentPanel ap, SequenceI seq, boolean prompt,
1740 String sFilename, TFType tft, String paeFilename,
1741 boolean forceHeadless, boolean showRefAnnotations,
1742 boolean doXferSettings, ViewerType viewerType)
1744 StructureViewer sv = null;
1745 boolean headless = forceHeadless;
1750 sc = new StructureChooser(new SequenceI[] { seq }, seq, ap, false);
1754 ssm = ap.getStructureSelectionManager();
1757 PDBEntry fileEntry = new AssociatePdbFileWithSeq().associatePdbWithSeq(
1758 sFilename, DataSourceType.FILE, seq, prompt, Desktop.instance,
1759 tft, paeFilename, doXferSettings);
1761 // if headless, "false" in the sc constructor above will avoid GUI behaviour
1762 // in sc.launchStructureViewer()
1763 if (!headless && !(viewerType == null))
1765 sv = sc.launchStructureViewer(ssm, new PDBEntry[] { fileEntry }, ap,
1767 { seq }, viewerType);
1770 sc.mainFrame.dispose();
1772 if (showRefAnnotations)
1773 showReferenceAnnotationsForSequence(ap.alignFrame, seq);
1778 public static void showReferenceAnnotationsForSequence(AlignFrame af,
1781 AlignViewport av = af.getCurrentView();
1782 AlignmentI al = av.getAlignment();
1784 List<SequenceI> forSequences = new ArrayList<>();
1785 forSequences.add(sequence);
1786 final Map<SequenceI, List<AlignmentAnnotation>> candidates = new LinkedHashMap<>();
1787 AlignmentUtils.findAddableReferenceAnnotations(forSequences, null,
1789 final SequenceGroup selectionGroup = av.getSelectionGroup();
1790 AlignmentUtils.addReferenceAnnotations(candidates, al, selectionGroup);
1791 for (AlignmentViewPanel ap : af.getAlignPanels())
1793 // required to readjust the height and position of the PAE
1795 ap.adjustAnnotationHeight();