Package nMOLDYN :: Package GUI :: Module AnimationDialog
[hide private]
[frames] | no frames]

Source Code for Module nMOLDYN.GUI.AnimationDialog

  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  # The python distribution modules 
  8  import os 
  9  import sys 
 10   
 11  # The Tcl/Tk modules 
 12  from tkFileDialog import askopenfilename 
 13  from Tkinter import * 
 14   
 15  # The ScientificPython modules 
 16   
 17  # The MMTK distribution modules 
 18  from MMTK.Trajectory import Trajectory 
 19  from MMTK.Visualization import definePDBViewer, viewTrajectory 
 20   
 21  # The nMOLDYN modules 
 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   
27 -class AnimationDialog(Toplevel):
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 # If a trajectory has been loaded in nMOLDYN for simulation purposes (e.g. MSD ...) then it is proposed by default for 56 # visualization. 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 # The combo widget for the file browser. 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 # The combo widget for the first step setting. 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 # The combo widget for the last step setting. 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 # The combo widget for the skip step setting. 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 # The control variables are updated with the informations coming from the loaded trajectory. 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
134 - def buttonbox(self):
135 """ 136 Add standard button box. 137 """ 138 139 # The frame that contains the 'Cancel' and 'OK' buttons. 140 box = LabelFrame(self, text = 'Actions', bd = 2, relief = GROOVE) 141 box.grid(row = 1, column = 0, sticky = EW, padx = 3, pady = 3) 142 box.grid_columnconfigure(0, weight = 1) 143 144 w = Button(box, text = "Cancel", width=10, command = self.cancel) 145 w.grid(row = 0, column = 0, sticky = E) 146 w = Button(box, text = "OK", width=10, command = self.ok, default=ACTIVE) 147 w.grid(row = 0, column = 1, sticky = E) 148 149 self.bind("<Return>", self.ok) 150 self.bind("<Escape>", self.cancel)
151 152 # Standard button semantics.
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 # Put focus back to the parent window 169 self.parent.focus_set() 170 self.destroy()
171 172 # Command hooks
173 - def validate(self):
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
213 - def apply(self):
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 # This MMTK function calls VMD to visualize the trajectory. 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
230 - def openTrajectory(self, event = None):
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 # Case where the user enters a file name directly in the entry widget without using the browser. 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 # The name of the NetCDF file to load. 249 filename = askopenfilename(parent = self,\ 250 filetypes = [('NetCDF file','*.nc')],\ 251 initialdir = PREFERENCES.trajfile_path) 252 253 # The file must exist. 254 if filename: 255 try: 256 # The trajectory is loaded. 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 # The control variables are updated with the informations about the loaded trajectory. 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