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.
23 import java.awt.event.ActionEvent;
24 import java.awt.event.ActionListener;
26 import java.util.ArrayList;
27 import java.util.List;
30 import javax.swing.JInternalFrame;
31 import javax.swing.JMenuItem;
32 import javax.swing.event.InternalFrameAdapter;
33 import javax.swing.event.InternalFrameEvent;
35 import jalview.api.AlignmentViewPanel;
36 import jalview.api.FeatureRenderer;
37 import jalview.bin.Console;
38 import jalview.datamodel.PDBEntry;
39 import jalview.datamodel.SequenceI;
40 import jalview.datamodel.StructureViewerModel;
41 import jalview.datamodel.StructureViewerModel.StructureData;
42 import jalview.gui.StructureViewer.ViewerType;
43 import jalview.io.DataSourceType;
44 import jalview.io.StructureFile;
45 import jalview.structures.models.AAStructureBindingModel;
46 import jalview.util.MessageManager;
48 public class PymolViewer extends StructureViewerBase
50 private static final int myWidth = 500;
52 private static final int myHeight = 150;
54 private PymolBindingModel binding;
56 private String pymolSessionFile;
63 * closeViewer will decide whether or not to close this frame
64 * depending on whether user chooses to Cancel or not
66 setDefaultCloseOperation(JInternalFrame.DO_NOTHING_ON_CLOSE);
69 public PymolViewer(PDBEntry pdb, SequenceI[] seqs, Object object,
73 openNewPymol(ap, new PDBEntry[] { pdb }, new SequenceI[][] { seqs });
76 public PymolViewer(PDBEntry[] pe, boolean alignAdded, SequenceI[][] seqs,
80 setAlignAddedStructures(alignAdded);
81 openNewPymol(ap, pe, seqs);
85 * Constructor given a session file to be restored
91 * @param colourByPymol
92 * @param colourBySequence
95 public PymolViewer(StructureViewerModel viewerModel,
96 AlignmentPanel alignPanel, String sessionFile, String vid)
98 // TODO convert to base/factory class method
101 this.pymolSessionFile = sessionFile;
102 Map<File, StructureData> pdbData = viewerModel.getFileData();
103 PDBEntry[] pdbArray = new PDBEntry[pdbData.size()];
104 SequenceI[][] seqsArray = new SequenceI[pdbData.size()][];
106 for (StructureData data : pdbData.values())
108 PDBEntry pdbentry = new PDBEntry(data.getPdbId(), null,
109 PDBEntry.Type.PDB, data.getFilePath());
110 pdbArray[i] = pdbentry;
111 List<SequenceI> sequencesForPdb = data.getSeqList();
112 seqsArray[i] = sequencesForPdb
113 .toArray(new SequenceI[sequencesForPdb.size()]);
117 openNewPymol(alignPanel, pdbArray, seqsArray);
118 if (viewerModel.isColourByViewer())
120 binding.setColourBySequence(false);
121 seqColour.setSelected(false);
122 viewerColour.setSelected(true);
124 else if (viewerModel.isColourWithAlignPanel())
126 binding.setColourBySequence(true);
127 seqColour.setSelected(true);
128 viewerColour.setSelected(false);
132 private void openNewPymol(AlignmentPanel ap, PDBEntry[] pe,
136 binding = new PymolBindingModel(this, ap.getStructureSelectionManager(),
138 addAlignmentPanel(ap);
139 useAlignmentPanelForColourbyseq(ap);
143 useAlignmentPanelForSuperposition(ap);
145 binding.setColourBySequence(true);
146 setSize(myWidth, myHeight);
148 viewerActionMenu.setText("PyMOL");
149 updateTitleAndMenus();
151 addingStructures = false;
152 worker = new Thread(this);
155 this.addInternalFrameListener(new InternalFrameAdapter()
158 public void internalFrameClosing(
159 InternalFrameEvent internalFrameEvent)
168 * Create a helper to manage progress bar display
170 protected void createProgressBar()
172 if (getProgressIndicator() == null)
174 setProgressIndicator(new ProgressBar(statusPanel, statusBar));
181 // todo pull up much of this
183 StringBuilder errormsgs = new StringBuilder(128);
184 List<PDBEntry> filePDB = new ArrayList<>();
185 List<Integer> filePDBpos = new ArrayList<>();
186 String[] curfiles = binding.getStructureFiles(); // files currently in
188 for (int pi = 0; pi < binding.getPdbCount(); pi++)
191 PDBEntry thePdbEntry = binding.getPdbEntry(pi);
192 if (thePdbEntry.getFile() == null)
195 * Retrieve PDB data, save to file, attach to PDBEntry
197 file = fetchPdbFile(thePdbEntry);
200 errormsgs.append("'" + thePdbEntry.getId() + "' ");
208 file = new File(thePdbEntry.getFile()).getAbsoluteFile().getPath();
209 // todo - skip if already loaded in PyMOL
213 filePDB.add(thePdbEntry);
214 filePDBpos.add(Integer.valueOf(pi));
218 if (!filePDB.isEmpty())
221 * at least one structure to add to viewer
223 binding.setFinishedInit(false);
224 if (!addingStructures)
229 } catch (Exception ex)
231 Console.error("Couldn't open PyMOL viewer!", ex);
232 // if we couldn't open Pymol, no point continuing
236 if (!binding.isViewerRunning())
239 // TODO: ensure we tidy up JAL-3619
245 for (PDBEntry pe : filePDB)
248 if (pe.getFile() != null)
252 int pos = filePDBpos.get(num).intValue();
253 long startTime = startProgressBar(getViewerName() + " "
254 + MessageManager.getString("status.opening_file_for")
256 binding.openFile(pe);
257 binding.addSequence(pos, binding.getSequence()[pos]);
258 File fl = new File(pe.getFile());
259 DataSourceType protocol = DataSourceType.URL;
264 protocol = DataSourceType.FILE;
266 } catch (Throwable e)
270 stopProgressBar("", startTime);
273 StructureFile pdb = binding.getSsm().setMapping(
274 binding.getSequence()[pos], binding.getChains()[pos],
275 pe.getFile(), protocol, getProgressIndicator());
276 binding.stashFoundChains(pdb, pe.getFile());
277 } catch (Exception ex)
279 Console.error("Couldn't open " + pe.getFile() + " in "
280 + getViewerName() + "!", ex);
283 // Cache.debug("File locations are " + files);
288 binding.refreshGUI();
289 binding.setFinishedInit(true);
290 binding.setLoadingFromArchive(false);
293 * ensure that any newly discovered features (e.g. RESNUM)
294 * are added to any open feature settings dialog
296 FeatureRenderer fr = getBinding().getFeatureRenderer(null);
302 // refresh the sequence colours for the new structure(s)
303 for (AlignmentViewPanel ap : _colourwith)
305 binding.updateColours(ap);
307 // do superposition if asked to
308 if (alignAddedStructures)
310 new Thread(new Runnable()
315 alignStructsWithAllAlignPanels();
319 addingStructures = false;
327 * Launch PyMOL. If we have a session file name, send PyMOL the command to
328 * open its saved session file.
332 Desktop.addInternalFrame(this,
333 binding.getViewerTitle(getViewerName(), true),
334 getBounds().width, getBounds().height);
336 if (!binding.launchPymol())
338 JvOptionPane.showMessageDialog(Desktop.getInstance(),
339 MessageManager.formatMessage("label.open_viewer_failed",
341 MessageManager.getString("label.error_loading_file"),
342 JvOptionPane.ERROR_MESSAGE);
343 binding.closeViewer(true);
348 if (this.pymolSessionFile != null)
350 boolean opened = binding.openSession(pymolSessionFile);
353 Console.error("An error occurred opening PyMOL session file "
357 // binding.startPymolListener();
361 public AAStructureBindingModel getBinding()
367 public ViewerType getViewerType()
369 return ViewerType.PYMOL;
373 protected String getViewerName()
378 JMenuItem writeFeatures = null;
381 protected void initMenus()
385 savemenu.setVisible(false); // not yet implemented
386 viewMenu.add(fitToWindow);
388 writeFeatures = new JMenuItem(
389 MessageManager.getString("label.create_viewer_attributes"));
390 writeFeatures.setToolTipText(
391 MessageManager.getString("label.create_viewer_attributes_tip"));
392 writeFeatures.addActionListener(new ActionListener()
395 public void actionPerformed(ActionEvent e)
397 sendFeaturesToPymol();
400 viewerActionMenu.add(writeFeatures);
404 protected void buildActionMenu()
406 super.buildActionMenu();
407 viewerActionMenu.add(writeFeatures);
410 protected void sendFeaturesToPymol()
412 int count = binding.sendFeaturesToViewer(getAlignmentPanel());
413 statusBar.setText(MessageManager.formatMessage("label.attributes_set",
414 count, getViewerName()));