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 = null;
274 if (pe.hasStructureFile())
276 pdb = pe.getStructureFile();
277 Console.debug("(Re)Using StructureFile " + pdb.getId());
281 pdb = binding.getSsm().setMapping(binding.getSequence()[pos],
282 binding.getChains()[pos], pe.getFile(), protocol,
283 getProgressIndicator());
285 binding.stashFoundChains(pdb, pe.getFile());
286 } catch (Exception ex)
288 Console.error("Couldn't open " + pe.getFile() + " in "
289 + getViewerName() + "!", ex);
292 // Cache.debug("File locations are " + files);
297 binding.refreshGUI();
298 binding.setFinishedInit(true);
299 binding.setLoadingFromArchive(false);
302 * ensure that any newly discovered features (e.g. RESNUM)
303 * are added to any open feature settings dialog
305 FeatureRenderer fr = getBinding().getFeatureRenderer(null);
311 // refresh the sequence colours for the new structure(s)
312 for (AlignmentViewPanel ap : _colourwith)
314 binding.updateColours(ap);
316 // do superposition if asked to
317 if (alignAddedStructures)
319 new Thread(new Runnable()
324 alignStructsWithAllAlignPanels();
328 addingStructures = false;
336 * Launch PyMOL. If we have a session file name, send PyMOL the command to
337 * open its saved session file.
341 Desktop.addInternalFrame(this,
342 binding.getViewerTitle(getViewerName(), true),
343 getBounds().width, getBounds().height);
345 if (!binding.launchPymol())
347 JvOptionPane.showMessageDialog(Desktop.desktop,
348 MessageManager.formatMessage("label.open_viewer_failed",
350 MessageManager.getString("label.error_loading_file"),
351 JvOptionPane.ERROR_MESSAGE);
352 binding.closeViewer(true);
357 if (this.pymolSessionFile != null)
359 boolean opened = binding.openSession(pymolSessionFile);
362 Console.error("An error occurred opening PyMOL session file "
366 // binding.startPymolListener();
370 public AAStructureBindingModel getBinding()
376 public ViewerType getViewerType()
378 return ViewerType.PYMOL;
382 protected String getViewerName()
387 JMenuItem writeFeatures = null;
390 protected void initMenus()
394 savemenu.setVisible(false); // not yet implemented
395 viewMenu.add(fitToWindow);
397 writeFeatures = new JMenuItem(
398 MessageManager.getString("label.create_viewer_attributes"));
399 writeFeatures.setToolTipText(
400 MessageManager.getString("label.create_viewer_attributes_tip"));
401 writeFeatures.addActionListener(new ActionListener()
404 public void actionPerformed(ActionEvent e)
406 sendFeaturesToPymol();
409 viewerActionMenu.add(writeFeatures);
413 protected void buildActionMenu()
415 super.buildActionMenu();
416 viewerActionMenu.add(writeFeatures);
419 protected void sendFeaturesToPymol()
421 int count = binding.sendFeaturesToViewer(getAlignmentPanel());
422 statusBar.setText(MessageManager.formatMessage("label.attributes_set",
423 count, getViewerName()));