3 import java.awt.event.ActionEvent;
4 import java.awt.event.ActionListener;
6 import java.util.ArrayList;
10 import javax.swing.JInternalFrame;
11 import javax.swing.JMenuItem;
12 import javax.swing.event.InternalFrameAdapter;
13 import javax.swing.event.InternalFrameEvent;
15 import jalview.api.AlignmentViewPanel;
16 import jalview.api.FeatureRenderer;
17 import jalview.bin.Console;
18 import jalview.datamodel.PDBEntry;
19 import jalview.datamodel.SequenceI;
20 import jalview.datamodel.StructureViewerModel;
21 import jalview.datamodel.StructureViewerModel.StructureData;
22 import jalview.gui.StructureViewer.ViewerType;
23 import jalview.io.DataSourceType;
24 import jalview.io.StructureFile;
25 import jalview.structures.models.AAStructureBindingModel;
26 import jalview.util.MessageManager;
28 public class PymolViewer extends StructureViewerBase
30 private static final int myWidth = 500;
32 private static final int myHeight = 150;
34 private PymolBindingModel binding;
36 private String pymolSessionFile;
43 * closeViewer will decide whether or not to close this frame
44 * depending on whether user chooses to Cancel or not
46 setDefaultCloseOperation(JInternalFrame.DO_NOTHING_ON_CLOSE);
49 public PymolViewer(PDBEntry pdb, SequenceI[] seqs, Object object,
53 openNewPymol(ap, new PDBEntry[] { pdb },
58 public PymolViewer(PDBEntry[] pe, boolean alignAdded, SequenceI[][] seqs,
62 setAlignAddedStructures(alignAdded);
63 openNewPymol(ap, pe, seqs);
67 * Constructor given a session file to be restored
73 * @param colourByPymol
74 * @param colourBySequence
77 public PymolViewer(StructureViewerModel viewerModel,
78 AlignmentPanel alignPanel, String sessionFile, String vid)
80 // TODO convert to base/factory class method
83 this.pymolSessionFile = sessionFile;
84 Map<File, StructureData> pdbData = viewerModel.getFileData();
85 PDBEntry[] pdbArray = new PDBEntry[pdbData.size()];
86 SequenceI[][] seqsArray = new SequenceI[pdbData.size()][];
88 for (StructureData data : pdbData.values())
90 PDBEntry pdbentry = new PDBEntry(data.getPdbId(), null,
91 PDBEntry.Type.PDB, data.getFilePath());
92 pdbArray[i] = pdbentry;
93 List<SequenceI> sequencesForPdb = data.getSeqList();
94 seqsArray[i] = sequencesForPdb
95 .toArray(new SequenceI[sequencesForPdb.size()]);
99 openNewPymol(alignPanel, pdbArray, seqsArray);
100 if (viewerModel.isColourByViewer())
102 binding.setColourBySequence(false);
103 seqColour.setSelected(false);
104 viewerColour.setSelected(true);
106 else if (viewerModel.isColourWithAlignPanel())
108 binding.setColourBySequence(true);
109 seqColour.setSelected(true);
110 viewerColour.setSelected(false);
114 private void openNewPymol(AlignmentPanel ap, PDBEntry[] pe,
118 binding = new PymolBindingModel(this, ap.getStructureSelectionManager(),
120 addAlignmentPanel(ap);
121 useAlignmentPanelForColourbyseq(ap);
125 useAlignmentPanelForSuperposition(ap);
127 binding.setColourBySequence(true);
128 setSize(myWidth, myHeight);
130 viewerActionMenu.setText("PyMOL");
131 updateTitleAndMenus();
133 addingStructures = false;
134 worker = new Thread(this);
137 this.addInternalFrameListener(new InternalFrameAdapter()
140 public void internalFrameClosing(
141 InternalFrameEvent internalFrameEvent)
150 * Create a helper to manage progress bar display
152 protected void createProgressBar()
154 if (getProgressIndicator() == null)
156 setProgressIndicator(new ProgressBar(statusPanel, statusBar));
163 // todo pull up much of this
165 StringBuilder errormsgs = new StringBuilder(128);
166 List<PDBEntry> filePDB = new ArrayList<>();
167 List<Integer> filePDBpos = new ArrayList<>();
168 String[] curfiles = binding.getStructureFiles(); // files currently in viewer
169 for (int pi = 0; pi < binding.getPdbCount(); pi++)
172 PDBEntry thePdbEntry = binding.getPdbEntry(pi);
173 if (thePdbEntry.getFile() == null)
176 * Retrieve PDB data, save to file, attach to PDBEntry
178 file = fetchPdbFile(thePdbEntry);
181 errormsgs.append("'" + thePdbEntry.getId() + "' ");
189 file = new File(thePdbEntry.getFile()).getAbsoluteFile()
191 // todo - skip if already loaded in PyMOL
195 filePDB.add(thePdbEntry);
196 filePDBpos.add(Integer.valueOf(pi));
200 if (!filePDB.isEmpty())
203 * at least one structure to add to viewer
205 binding.setFinishedInit(false);
206 if (!addingStructures)
211 } catch (Exception ex)
213 Console.error("Couldn't open PyMOL viewer!", ex);
214 // if we couldn't open Pymol, no point continuing
218 if (!binding.isViewerRunning())
221 // TODO: ensure we tidy up JAL-3619
227 for (PDBEntry pe : filePDB)
230 if (pe.getFile() != null)
234 int pos = filePDBpos.get(num).intValue();
235 long startTime = startProgressBar(getViewerName() + " "
236 + MessageManager.getString("status.opening_file_for")
238 binding.openFile(pe);
239 binding.addSequence(pos, binding.getSequence()[pos]);
240 File fl = new File(pe.getFile());
241 DataSourceType protocol = DataSourceType.URL;
246 protocol = DataSourceType.FILE;
248 } catch (Throwable e)
252 stopProgressBar("", startTime);
255 StructureFile pdb = binding.getSsm().setMapping(
256 binding.getSequence()[pos], binding.getChains()[pos],
257 pe.getFile(), protocol,
258 getProgressIndicator());
259 binding.stashFoundChains(pdb, pe.getFile());
260 } catch (Exception ex)
263 "Couldn't open " + pe.getFile() + " in "+getViewerName()+"!",
267 // Cache.debug("File locations are " + files);
272 binding.refreshGUI();
273 binding.setFinishedInit(true);
274 binding.setLoadingFromArchive(false);
277 * ensure that any newly discovered features (e.g. RESNUM)
278 * are added to any open feature settings dialog
280 FeatureRenderer fr = getBinding().getFeatureRenderer(null);
286 // refresh the sequence colours for the new structure(s)
287 for (AlignmentViewPanel ap : _colourwith)
289 binding.updateColours(ap);
291 // do superposition if asked to
292 if (alignAddedStructures)
294 new Thread(new Runnable()
299 alignStructsWithAllAlignPanels();
303 addingStructures = false;
311 * Launch PyMOL. If we have a session file name, send PyMOL the command to
312 * open its saved session file.
316 Desktop.addInternalFrame(this,
317 binding.getViewerTitle(getViewerName(), true),
318 getBounds().width, getBounds().height);
320 if (!binding.launchPymol())
322 JvOptionPane.showMessageDialog(Desktop.desktop,
323 MessageManager.formatMessage("label.open_viewer_failed",
325 MessageManager.getString("label.error_loading_file"),
326 JvOptionPane.ERROR_MESSAGE);
327 binding.closeViewer(true);
332 if (this.pymolSessionFile != null)
334 boolean opened = binding.openSession(pymolSessionFile);
338 "An error occurred opening PyMOL session file "
342 // binding.startPymolListener();
346 public AAStructureBindingModel getBinding()
352 public ViewerType getViewerType()
354 return ViewerType.PYMOL;
358 protected String getViewerName()
362 JMenuItem writeFeatures = null;
364 protected void initMenus()
368 savemenu.setVisible(false); // not yet implemented
369 viewMenu.add(fitToWindow);
371 writeFeatures = new JMenuItem(
372 MessageManager.getString("label.create_viewer_attributes"));
373 writeFeatures.setToolTipText(MessageManager
374 .getString("label.create_viewer_attributes_tip"));
375 writeFeatures.addActionListener(new ActionListener()
378 public void actionPerformed(ActionEvent e)
380 sendFeaturesToPymol();
383 viewerActionMenu.add(writeFeatures);
387 protected void buildActionMenu()
389 super.buildActionMenu();
390 viewerActionMenu.add(writeFeatures);
393 protected void sendFeaturesToPymol()
395 int count = binding.sendFeaturesToViewer(getAlignmentPanel());
397 MessageManager.formatMessage("label.attributes_set", count, getViewerName()));