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
9 import copy
10 import os
11 import sys
12
13
14 from tkFileDialog import askopenfilename
15 from Tkinter import *
16
17
18 from Scientific import N as Num
19 from Scientific.IO.NetCDF import NetCDFFile
20
21
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
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
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
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
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
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
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
138
139
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
153 self.parent.focus_set()
154 self.destroy()
155
156
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
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
220 """
221 This method open the NetCDF that contains the effective modes.
222 Arguments:
223 - event: Tkinter event.
224 """
225
226
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
235 filename = askopenfilename(parent = self,\
236 filetypes = [('NetCDF file','*.nc')],\
237 initialdir = PREFERENCES.trajfile_path)
238
239
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
255 self.omega = self.netcdf.variables['omega'].getValue()
256
257
258 self.dx = self.netcdf.variables['dx'].getValue()
259
260
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