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

Source Code for Module nMOLDYN.GUI.ViewEffectiveModeDialog

  1  """This modules implements I{View --> Effective Mode} dialog. 
  2   
  3  Classes: 
  4      * ViewEffectiveModeDialog: creates I{View --> Effective Mode} dialog used to  
  5        view an animation of the effective modes resulting from a Quasi Harmonic Analysis. 
  6  """ 
  7   
  8  # The python distribution modules 
  9  import copy 
 10  import os 
 11  import sys 
 12   
 13  # The Tcl/Tk modules 
 14  from tkFileDialog import askopenfilename 
 15  from Tkinter import * 
 16   
 17  # The ScientificPython modules 
 18  from Scientific import N as Num 
 19  from Scientific.IO.NetCDF import NetCDFFile 
 20   
 21  # The MMTK distribution modules 
 22  from MMTK import Configuration 
 23  from MMTK import Skeleton 
 24  from MMTK.ParticleProperties import ParticleVector 
 25  from MMTK.Visualization import definePDBViewer, viewSequenceVMD 
 26   
 27  # The nMOLDYN modules 
 28  from nMOLDYN.Core.Error import Error 
 29  from nMOLDYN.Core.Logger import LogMessage 
 30  from nMOLDYN.Core.Preferences import PREFERENCES 
 31  from nMOLDYN.GUI.Widgets import ComboIntegerEntry, ComboFloatEntry, ComboFileBrowser, ComboListbox, ComboRadiobutton 
 32   
33 -class ViewEffectiveModeDialog(Toplevel):
34 """Sets up a dialog used to visualize the effective modes resulting from a QHA analysis. 35 """ 36
37 - def __init__(self, parent, title = None):
38 """The constructor. 39 40 @param parent: the parent widget. 41 42 @param title: a string specifying the title of the dialog. 43 @type title: string 44 """ 45 46 Toplevel.__init__(self, parent) 47 self.transient(parent) 48 49 if title: 50 self.title(title) 51 52 self.parent = parent 53 54 body = Frame(self) 55 self.initial_focus = self.body(body) 56 body.grid(row = 0, column = 0, sticky = EW) 57 58 self.buttonbox() 59 60 self.grab_set() 61 62 if not self.initial_focus: 63 self.initial_focus = self 64 65 self.protocol("WM_DELETE_WINDOW", self.cancel) 66 67 self.resizable(width = NO, height = NO) 68 69 self.geometry("+%d+%d" % (parent.winfo_rootx()+50, parent.winfo_rooty()+50)) 70 71 self.initial_focus.focus_set() 72 73 self.wait_window(self)
74
75 - def body(self, master):
76 """ 77 Create dialog body. Return widget that should have initial focus. 78 """ 79 80 settingsFrame = LabelFrame(master, text = 'Settings', bd = 2, relief = GROOVE) 81 settingsFrame.grid(row = 0, column = 0, sticky = EW, padx = 3, pady = 3) 82 settingsFrame.grid_columnconfigure(0, weight = 1) 83 84 # The combo widget for the file browser. 85 self.fileBrowser = ComboFileBrowser(settingsFrame,\ 86 frameLabel = "QHA input file",\ 87 tagName = 'view_effective_modes_qha_input_file',\ 88 contents = '',\ 89 save = False,\ 90 command = self.openNetCDFFile,\ 91 filetypes = [("NetCDF file", ".nc"),]) 92 self.fileBrowser.grid(row = 0, column = 0, sticky = EW, padx = 2, pady = 2) 93 self.fileBrowser.grid_columnconfigure(0, weight = 1) 94 self.fileBrowser.entry.bind('<Return>', self.openNetCDFFile) 95 96 # The combo listbox that will contain the X variables. 97 self.selectedModeLb = ComboListbox(settingsFrame,\ 98 frameLabel = 'Quasi-Harmonic mode',\ 99 tagName = 'quasi_harmonic_mode',\ 100 contents = []) 101 self.selectedModeLb.lb.config({'exportselection' : 0, 'width' : 22, 'height' : 8, 'selectmode' : MULTIPLE}) 102 self.selectedModeLb.grid(row = 1, column = 0, sticky = EW, padx = 2, pady = 2) 103 self.selectedModeLb.grid_columnconfigure(0, weight = 1) 104 105 # The combo widget to set the number of frames for the animation. 106 self.nFramesEntry = ComboIntegerEntry(settingsFrame,\ 107 frameLabel = 'Number of frames',\ 108 tagName = 'view_effective_modes_number_of_frames') 109 self.nFramesEntry.grid(row = 2, column = 0, sticky = EW, padx = 2, pady = 2) 110 self.nFramesEntry.grid_columnconfigure(0, weight = 1) 111 112 # The combo widget to set the amplitude of the effective mode to view. 113 self.amplitudeEntry = ComboFloatEntry(settingsFrame,\ 114 frameLabel = 'Amplitude (in nm)',\ 115 tagName = 'view_effective_modes_amplitude') 116 self.amplitudeEntry.grid(row = 3, column = 0, sticky = EW, padx = 2, pady = 2) 117 self.amplitudeEntry.grid_columnconfigure(0, weight = 1) 118 119 return None
120
121 - def buttonbox(self):
122 """ 123 Add standard button box. 124 """ 125 126 # The frame that contains the 'Cancel' and 'OK' buttons. 127 box = LabelFrame(self, text = 'Actions', bd = 2, relief = GROOVE) 128 box.grid(row = 1, column = 0, sticky = EW, padx = 3, pady = 3) 129 box.grid_columnconfigure(0, weight = 1) 130 131 w = Button(box, text = "Cancel", width=10, command = self.cancel) 132 w.grid(row = 0, column = 0, sticky = E) 133 w = Button(box, text = "OK", width=10, command = self.ok, default=ACTIVE) 134 w.grid(row = 0, column = 1, sticky = E) 135 136 self.bind("<Return>", self.ok) 137 self.bind("<Escape>", self.cancel)
138 139 # Standard button semantics.
140 - def ok(self, event = None):
141 142 if not self.validate(): 143 self.initial_focus.focus_set() 144 return 145 146 self.update_idletasks() 147 148 self.apply()
149
150 - def cancel(self, event=None):
151 152 # Put focus back to the parent window 153 self.parent.focus_set() 154 self.destroy()
155 156 # Command hooks
157 - def validate(self):
158 159 try: 160 161 if not self.selectedModeLb.lb.curselection(): 162 LogMessage('warning','Please select a vibration mode.',['gui']) 163 raise 164 165 self.selectedMode = [int(v) - 1 for v in self.selectedModeLb.lb.curselection()] 166 167 self.amplitude = self.amplitudeEntry.getValue() 168 self.nFrames = self.nFramesEntry.getValue() 169 170 if self.amplitude <= 0.0: 171 raise 172 173 if self.nFrames < 0: 174 raise 175 176 except: 177 LogMessage('warning','Bad input. Please try again.',['gui']) 178 return False 179 180 return True
181
182 - def apply(self):
183 184 try: 185 if os.path.exists(PREFERENCES.vmd_path): 186 definePDBViewer('vmd', PREFERENCES.vmd_path) 187 188 else: 189 raise 190 191 except: 192 raise Error('Error when defining the PDB viewer from %s path.' % PREFERENCES.vmd_path) 193 194 try: 195 196 local = {} 197 skeleton = eval(self.description, vars(Skeleton), local) 198 universe = skeleton.make({}, self.avgStruct) 199 universe.setCellParameters(self.cell) 200 201 avg = Configuration(universe, self.avgStruct) 202 pseudoTraj = [avg] 203 204 for frame in range(self.nFrames): 205 vibr = copy.copy(avg) 206 for selMode in self.selectedMode: 207 dx = copy.copy(self.dx[selMode]) 208 dx.shape = (universe.numberOfAtoms(), 3) 209 d = ParticleVector(universe, dx) 210 vibr += self.amplitude*Num.sin(2.0*Num.pi*float(frame)/self.nFrames)*d 211 212 pseudoTraj.append(vibr) 213 214 viewSequenceVMD(universe, pseudoTraj, periodic = 1) 215 216 except: 217 raise Error('Error when animating the selected mode(s).')
218
219 - def openNetCDFFile(self, event = None):
220 """ 221 This method open the NetCDF that contains the effective modes. 222 Arguments: 223 - event: Tkinter event. 224 """ 225 226 # Case where the user enters a file name directly in the entry widget without using the browser. 227 if event is not None: 228 if event.widget == self.fileBrowser.entry: 229 filename = self.fileBrowser.getValue() 230 else: 231 return 232 233 else: 234 # The name of the NetCDF file to load. 235 filename = askopenfilename(parent = self,\ 236 filetypes = [('NetCDF file','*.nc')],\ 237 initialdir = PREFERENCES.trajfile_path) 238 239 # The file must exist. 240 if filename: 241 try: 242 self.netcdf = NetCDFFile(filename, 'r') 243 244 except IOError: 245 LogMessage('warning','Problem when reading the NetCDF file.',['gui']) 246 self.fileBrowser.setValue('') 247 self.selectedModeEntry.setValue('') 248 self.nFramesEntry.setValue('') 249 self.amplitudeEntry.setValue('') 250 251 try: 252 self.description = self.netcdf.variables['description'][:].tostring() 253 254 # The frequencies values. 255 self.omega = self.netcdf.variables['omega'].getValue() 256 257 # The displacements. 258 self.dx = self.netcdf.variables['dx'].getValue() 259 260 # The average structure. 261 self.avgStruct = self.netcdf.variables['avgstruct'].getValue() 262 263 except KeyError: 264 LogMessage('warning','The NetCDF file %s miss some QHA analysis keywords.' % filename,['gui']) 265 266 self.fileBrowser.setValue(filename) 267 268 self.selectedModeLb.lb.delete(0, END) 269 270 for i in range(len(self.omega)): 271 ome = self.omega[i] 272 self.selectedModeLb.lb.insert(END, 'Mode %s (%s cm-1)' % (i+1, ome)) 273 274 self.nFramesEntry.setValue(10) 275 self.amplitudeEntry.setValue(0.1) 276 277 try: 278 self.cell = self.netcdf.variables['box_size'][:] 279 except KeyError: 280 self.cell = None 281 282 self.netcdf.close() 283 284 return 'break'
285