1 """This modules implements I{View-->Animation} dialog.
2
3 Classes:
4 * AnimationDialog: creates I{View-->Animation} dialog used to view an animation of a trajectory.
5 """
6
7
8 import os
9 import sys
10
11
12 from tkFileDialog import askopenfilename
13 from Tkinter import *
14
15
16
17
18 from MMTK.Trajectory import Trajectory
19 from MMTK.Visualization import definePDBViewer, viewTrajectory
20
21
22 from nMOLDYN.Core.Error import Error
23 from nMOLDYN.Core.Logger import LogMessage
24 from nMOLDYN.Core.Preferences import PREFERENCES
25 from nMOLDYN.GUI.Widgets import ComboFileBrowser, ComboIntegerEntry, ComboRadiobutton
26
28 """Sets up a dialog used to visualize a loaded trajectory.
29
30 @note: if a trajectory has been previously loaded in nMOLDYN for simulation purposes this will be the one
31 proposed for visualization by default. Otherwise, the user can still choose a trajectory to visualize from
32 the dialog.
33 """
34
35 - def __init__(self, parent, title = None, trajectory = None):
36 """The constructor.
37
38 @param parent: the parent widget.
39
40 @param title: a string specifying the title of the dialog.
41 @type title: string
42
43 @param trajectory: an opened MMTK trajectory.
44 @type trajectory: an instance of MMTK.Trajectory.Trajectory class.
45 """
46
47 Toplevel.__init__(self, parent)
48 self.transient(parent)
49
50 if title:
51 self.title(title)
52
53 self.parent = parent
54
55
56
57 if isinstance(trajectory, Trajectory):
58 self.trajectory = trajectory
59
60 else:
61 self.trajectory = None
62
63 body = Frame(self)
64 self.initial_focus = self.body(body)
65 body.grid(row = 0, column = 0, sticky = EW)
66
67 self.buttonbox()
68
69 self.grab_set()
70
71 if not self.initial_focus:
72 self.initial_focus = self
73
74 self.protocol("WM_DELETE_WINDOW", self.cancel)
75
76 self.resizable(width = NO, height = NO)
77
78 self.geometry("+%d+%d" % (parent.winfo_rootx()+50, parent.winfo_rooty()+50))
79
80 self.initial_focus.focus_set()
81
82 self.wait_window(self)
83
84 - def body(self, master):
85 """
86 Create dialog body. Return widget that should have initial focus.
87 """
88
89 settingsFrame = LabelFrame(master, text = 'Settings', bd = 2, relief = GROOVE)
90 settingsFrame.grid(row = 0, column = 0, sticky = EW, padx = 3, pady = 3)
91 settingsFrame.grid_columnconfigure(0, weight = 1)
92
93
94 self.fileBrowser = ComboFileBrowser(settingsFrame,\
95 frameLabel = "MMTK Trajectory file",\
96 tagName = 'animation_mmtk_trajectory_file',\
97 contents = '',\
98 save = False,\
99 command = self.openTrajectory)
100 self.fileBrowser.grid(row = 0, column = 0, padx = 2, pady = 2, sticky = EW)
101 self.fileBrowser.grid_columnconfigure(0, weight = 1)
102 self.fileBrowser.entry.bind('<Return>', self.openTrajectory)
103
104
105 self.firstStepEntry = ComboIntegerEntry(settingsFrame,\
106 frameLabel = 'First step',\
107 tagName = 'animation_first_step')
108 self.firstStepEntry.grid(row = 1, column = 0, sticky = EW, padx = 2, pady = 2)
109 self.firstStepEntry.grid_columnconfigure(0, weight = 1)
110
111
112 self.lastStepEntry = ComboIntegerEntry(settingsFrame,\
113 frameLabel = 'Last step',\
114 tagName = 'animation_last_step')
115 self.lastStepEntry.grid(row = 2, column = 0, sticky = EW, padx = 2, pady = 2)
116 self.lastStepEntry.grid_columnconfigure(0, weight = 1)
117
118
119 self.skipStepEntry = ComboIntegerEntry(settingsFrame,\
120 frameLabel = 'Skip step',\
121 tagName = 'animation_skip_test')
122 self.skipStepEntry.grid(row = 3, column = 0, sticky = EW, padx = 2, pady = 2)
123 self.skipStepEntry.grid_columnconfigure(0, weight = 1)
124
125 if self.trajectory is not None:
126
127 self.fileBrowser.setValue(self.trajectory.filename)
128 self.firstStepEntry.setValue(1)
129 self.lastStepEntry.setValue(1)
130 self.skipStepEntry.setValue(1)
131
132 return None
133
151
152
153 - def ok(self, event = None):
154
155 if not self.validate():
156 self.initial_focus.focus_set()
157 return
158
159 self.withdraw()
160 self.update_idletasks()
161
162 self.apply()
163
164 self.cancel()
165
166 - def cancel(self, event=None):
167
168
169 self.parent.focus_set()
170 self.destroy()
171
172
174
175 if not self.trajectory:
176 raise Error('No MMTK trajectory file loaded for animation.')
177
178 if self.trajectory.filename != self.fileBrowser.getValue():
179 raise Error('Mismatch between the loaded trajectory and the displayed MMTK trajectory file name.\
180 You should validate that file by pressing Return on its corresponding entry.')
181
182 self.viewableAtoms = self.trajectory.universe.atomsWithDefinedPositions()
183
184 if not self.firstStepEntry.getValue():
185 self.first = 0
186 LogMessage('warning', 'First frame undefined. Frame 1 will be taken by default.', ['gui'])
187 else:
188 self.first = self.firstStepEntry.getValue() - 1
189
190 if self.first < 0:
191 raise Error('First frame not within [1,%d].' % len(self.trajectory))
192
193 if not self.lastStepEntry.getValue():
194 self.last = 1
195 LogMessage('warning', 'Last frame undefined. Frame 1 will be taken by default.', ['gui'])
196 else:
197 self.last = self.lastStepEntry.getValue()
198
199 if self.last > len(self.trajectory):
200 raise Error('Last frame not within [1,%d].' % len(self.trajectory))
201
202 if not self.skipStepEntry.getValue():
203 self.skip = 1
204 LogMessage('warning', 'Frame skip undefined. 1 will be taken by default.', ['gui'])
205 else:
206 self.skip = self.skipStepEntry.getValue()
207
208 if (self.skip < 1) or (self.skip >= len(self.trajectory)):
209 raise Error('Last frame not within [1,%d[.' % len(self.trajectory))
210
211 return True
212
214
215 try:
216 if os.path.exists(PREFERENCES.vmd_path):
217 definePDBViewer('vmd', PREFERENCES.vmd_path)
218 else:
219 raise
220 except:
221 raise Error('Error when defining VMD molecular viewer from %s path.' % PREFERENCES.vmd_path)
222
223 try:
224
225 viewTrajectory(trajectory = self.trajectory, first = self.first, last = self.last, skip = self.skip,\
226 subset = self.viewableAtoms)
227 except:
228 raise Error('Error when animating the trajectory.')
229
231 """
232 The method is called when the user clicks on the 'Browse' button of the trajectory visualization dialog.
233 It opens a file browser. After the file selection some of the dialog widgets are updated with the informations
234 coming from the loaded trajectory.
235
236 Arguments:
237 - event: Tkinter event.
238 """
239
240
241 if event is not None:
242 if event.widget == self.fileBrowser.entry:
243 filename = self.fileBrowser.getValue()
244 else:
245 return
246
247 else:
248
249 filename = askopenfilename(parent = self,\
250 filetypes = [('NetCDF file','*.nc')],\
251 initialdir = PREFERENCES.trajfile_path)
252
253
254 if filename:
255 try:
256
257 self.trajectory = Trajectory(None, filename, 'r')
258
259 except IOError:
260 LogMessage('warning', 'Problem when reading the trajectory.',['gui'])
261 self.fileBrowser.setValue('')
262 self.firstStepEntry.setValue('')
263 self.lastStepEntry.setValue('')
264 self.skipStepEntry.setValue('')
265
266 else:
267
268 self.fileBrowser.setValue(filename)
269 self.firstStepEntry.setValue(1)
270 self.lastStepEntry.setValue(1)
271 self.skipStepEntry.setValue(1)
272
273 return 'break'
274