1 """This is where the main window of nMOLDYN is defined.
2
3 Classes:
4 * MainDialog: The class that defines the nMOLDYN GUI main window and its associated actions.
5 """
6
7
8 import inspect
9 import os
10 import re
11 import subprocess
12 import sys
13 import webbrowser
14
15 from tkMessageBox import askyesno
16
17
18 from Scientific import N
19 from Scientific.IO.NetCDF import NetCDFFile, _NetCDFFile
20
21
22 from MMTK.Trajectory import Trajectory, trajectoryInfo, TrajectorySet
23
24 from Tkinter import *
25 from tkFileDialog import askopenfilename
26
27
28 from nMOLDYN.Analysis.Analysis import setUniverseContents
29 from nMOLDYN.Analysis.Dynamics import *
30 from nMOLDYN.Analysis.NMR import *
31 from nMOLDYN.Analysis.Scattering import *
32 from nMOLDYN.Analysis.Structure import *
33 from nMOLDYN.Core.Error import Error
34 from nMOLDYN.Core.Logger import LogMessage
35 from nMOLDYN.Core.Preferences import PREFERENCES
36
37 from nMOLDYN.GUI.AnalysisDialog import AnalysisDialog
38 from nMOLDYN.GUI.AnimationDialog import AnimationDialog
39 from nMOLDYN.GUI.AnalysisBenchmarkDialog import AnalysisBenchmarkDialog
40 from nMOLDYN.GUI.ASCIIToNetCDFConversionDialog import ASCIIToNetCDFConversionDialog
41 from nMOLDYN.GUI.PreferencesDialog import PreferencesDialog
42 from nMOLDYN.GUI.GeneralInformationsDialog import GeneralInformationsDialog
43 from nMOLDYN.GUI.NetCDFToASCIIConversionDialog import NetCDFToASCIIConversionDialog
44 from nMOLDYN.GUI.PDBSnapshotGeneratorDialog import PDBSnapshotGeneratorDialog
45 from nMOLDYN.GUI.PlotNetCDFVariableDialog import PlotNetCDFVariableDialog
46 from nMOLDYN.GUI.TrajectoryConversionDialog import *
47 from nMOLDYN.GUI.ViewEffectiveModeDialog import ViewEffectiveModeDialog
48 from nMOLDYN.GUI.Widgets import ComboText
49
50
51 nmoldyn_package_path = os.path.dirname(os.path.split(__file__)[0])
52
53 from Tkinter import *
54
55 -class MainDialog(Tk):
56 """
57 This is the base class for the nMoldyn GUI. It launches the main window of nMoldyn from which
58 different menus can be accessed.
59 """
60
61 - def __init__(self, netcdf_filename = None):
62 """
63 The constructor. Displays the main window.
64
65 @param netcdf_filename: a string specifying a NetCDF file, nMOLDYN should be started with.
66 @rtype: string
67 """
68
69 Tk.__init__(self)
70
71 self.option_add('*Dialog.msg.wrapLength', '30i')
72
73 if netcdf_filename is not None:
74 netcdf_filename = os.path.abspath(netcdf_filename)
75 if os.path.exists(netcdf_filename):
76 self.netcdf_filename = netcdf_filename
77 else:
78 self.netcdf_filename = None
79 LogMessage('warning', 'The NetCDF input file %s does not exist.' % netcdf_filename, ['console'])
80
81 else:
82 self.netcdf_filename = None
83
84 self.netcdf = None
85
86 self.initial_focus = self.body(self)
87
88 self.grab_set()
89
90 self.protocol("WM_DELETE_WINDOW", self.cancel)
91
92
93 if sys.platform == 'darwin':
94 try:
95 self.tk.call('package', 'require', 'tile')
96 self.tk.call('namespace', 'import', '-force', 'ttk::*')
97 self.tk.call('tile::setTheme', 'aqua')
98 except TclError:
99 pass
100
101 self.resizable(width = NO, height = NO)
102
103 self.title('nMOLDYN')
104
105 self.geometry("+20+20")
106
107 self.focus_set()
108
109
110 self.after(1000, self.checkConfiguration)
111
112 self.wait_window(self)
113
114 - def body(self, master):
115
116 mainMenu = Menu(master)
117
118 if sys.platform == 'darwin':
119 accel = 'Cmd-'
120 bindKey = 'Command-'
121 else:
122 accel = 'Ctrl-'
123 bindKey = 'Control-'
124
125
126
127
128 self.fileMenu = Menu(mainMenu, tearoff = 0)
129
130
131 self.fileMenu.add_command(label = 'Load NetCDF file', command = self.loadNetCDF, accelerator = accel + 'O')
132 master.bind('<%s>' % (bindKey+'o',), self.loadNetCDF)
133
134 self.fileMenu.add_separator()
135
136 conversionMenu = Menu(self.fileMenu, tearoff = 0)
137 self.fileMenu.add_cascade(label = 'Trajectory conversion', menu = conversionMenu)
138 conversionMenu.add_command(label = 'Amber NetCDF to MMTK', command = lambda : AmberNetCDFConverterDialog(master))
139 conversionMenu.add_command(label = 'CHARMM/X-PLOR to MMTK', command = lambda : CHARMMConverterDialog(master))
140 conversionMenu.add_command(label = 'DL_POLY to MMTK', command = lambda : DL_POLYConverterDialog(master))
141
142 materialsStudioMenu = Menu(conversionMenu, tearoff = 0)
143 conversionMenu.add_cascade(label = 'MaterialsStudio', menu = materialsStudioMenu)
144 materialsStudioMenu.add_command(label = 'Discover to MMTK', command = lambda : MaterialsStudioConverterDialog(master, 'Discover'))
145 materialsStudioMenu.add_command(label = 'Forcite to MMTK', command = lambda : MaterialsStudioConverterDialog(master, 'Forcite'))
146
147 conversionMenu.add_command(label = 'NAMD to MMTK', command = lambda : NAMDConverterDialog(master))
148 conversionMenu.add_command(label = 'VASP to MMTK', command = lambda : VASPConverterDialog(master))
149
150
151 self.fileMenu.add_command(label = 'Frame snapshot', command = self.extractTrajectoryFrame, accelerator = accel + 'R')
152 master.bind('<%s>' % (bindKey+'r',), self.extractTrajectoryFrame)
153
154 self.fileMenu.add_separator()
155
156
157 self.fileMenu.add_command(label = 'Convert NetCDF to ASCII', command = self.convertNetCDFToASCII, accelerator = accel + 'U')
158 master.bind('<%s>' % (bindKey+'u',), self.convertNetCDFToASCII)
159
160
161 self.fileMenu.add_command(label = 'Convert ASCII to NetCDF', command = self.convertASCIIToNetCDF, accelerator = accel + 'I')
162 master.bind('<%s>' % (bindKey+'i',), self.convertASCIIToNetCDF)
163
164 self.fileMenu.add_separator()
165
166
167 self.fileMenu.add_command(label = 'Preferences', command = self.setPreferences, accelerator = accel + 'E')
168 master.bind('<%s>' % (bindKey+'e',), self.setPreferences)
169
170 self.fileMenu.add_separator()
171
172
173 self.fileMenu.add_command(label = 'Quit', command = self.cancel, accelerator = accel + 'Q')
174 master.bind('<%s>' % (bindKey+'q',), self.cancel)
175
176
177 mainMenu.add_cascade(label = "File", menu = self.fileMenu)
178
179
180
181
182 self.analysisMenu = Menu(mainMenu, tearoff = 0)
183
184
185
186
187 dynamicsMenu = Menu(self.analysisMenu, tearoff = 0)
188
189 self.analysisMenu.add_cascade(label = 'Dynamics', menu = dynamicsMenu)
190
191
192 dynamicsMenu.add_command(label = 'Mean-Square Displacement',
193 command = lambda : self.analysisDialog(MeanSquareDisplacement))
194
195 dynamicsMenu.add_command(label = 'Root Mean-Square Deviation',
196 command = lambda : self.analysisDialog(RootMeanSquareDeviation))
197
198 dynamicsMenu.add_command(label = 'Radius Of Gyration',
199 command = lambda : self.analysisDialog(RadiusOfGyration))
200
201 dynamicsMenu.add_command(label = 'Angular Correlation',
202 command = lambda : self.analysisDialog(AngularCorrelation))
203
204 dynamicsMenu.add_command(label = 'Velocity AutoCorrelation Function',
205 command = lambda : self.analysisDialog(CartesianVelocityAutoCorrelationFunction))
206
207 dynamicsMenu.add_command(label = 'Density Of States',
208 command = lambda : self.analysisDialog(CartesianDensityOfStates))
209
210 dynamicsMenu.add_separator()
211
212 dynamicsMenu.add_command(label = 'Pass-Band Filtered Trajectory',
213 command = lambda : self.analysisDialog(PassBandFilteredTrajectory))
214 dynamicsMenu.add_command(label = 'Global Motion Filtered Trajectory',
215 command = lambda : self.analysisDialog(GlobalMotionFilteredTrajectory))
216
217
218 dynamicsMenu.add_command(label = 'Rigid-Body Trajectory',
219 command = lambda : self.analysisDialog(RigidBodyTrajectory))
220
221
222 dynamicsMenu.add_command(label = 'Center Of Mass Trajectory',
223 command = lambda : self.analysisDialog(CenterOfMassTrajectory))
224
225 dynamicsMenu.add_separator()
226
227
228 dynamicsMenu.add_command(label = 'Auto-Regressive Analysis',
229 command = lambda : self.analysisDialog(AutoRegressiveAnalysis))
230
231 dynamicsMenu.add_separator()
232
233
234 dynamicsMenu.add_command(label = 'Quasi-Harmonic Analysis',
235 command = lambda : self.analysisDialog(QuasiHarmonicAnalysis))
236
237 dynamicsMenu.add_separator()
238
239
240 dynamicsMenu.add_command(label = 'Reorientational Correlation Function',
241 command = lambda : self.analysisDialog(ReorientationalCorrelationFunction))
242
243
244 dynamicsMenu.add_command(label = 'Angular Velocity AutoCorrelation Function',
245 command = lambda : self.analysisDialog(AngularVelocityAutoCorrelationFunction))
246
247
248
249 dynamicsMenu.add_command(label = 'Angular Density Of States',
250 command = lambda : self.analysisDialog(AngularDensityOfStates))
251
252
253
254
255 scatteringMenu = Menu(self.analysisMenu, tearoff = 0)
256
257 self.analysisMenu.add_cascade(label = 'Scattering', menu = scatteringMenu)
258
259
260 scatteringMenu.add_command(label = 'Dynamic Coherent Structure Factor',
261 command = lambda : self.analysisDialog(DynamicCoherentStructureFactor))
262
263
264 scatteringMenu.add_command(label = 'Dynamic Coherent Structure Factor (AR Model)',
265 command = lambda : self.analysisDialog(DynamicCoherentStructureFactorAR))
266
267 scatteringMenu.add_separator()
268
269
270 scatteringMenu.add_command(label = 'Dynamic Incoherent Structure Factor',
271 command = lambda : self.analysisDialog(DynamicIncoherentStructureFactor))
272
273
274 scatteringMenu.add_command(label = 'Dynamic Incoherent Structure Factor (AR Model)',
275 command = lambda : self.analysisDialog(DynamicIncoherentStructureFactorAR))
276
277
278 scatteringMenu.add_command(label = 'Dynamic Incoherent Structure Factor (Gaussian Approximation)',
279 command = lambda : self.analysisDialog(DynamicIncoherentStructureFactorGaussian))
280
281 scatteringMenu.add_separator()
282
283
284 scatteringMenu.add_command(label = 'Elastic Incoherent Structure Factor',
285 command = lambda : self.analysisDialog(ElasticIncoherentStructureFactor))
286
287 scatteringMenu.add_separator()
288
289
290 scatteringMenu.add_command(label = 'Static Coherent Structure Factor',
291 command = lambda : self.analysisDialog(StaticCoherentStructureFactor))
292
293
294 scatteringMenu.add_command(label = 'Smoothed Static Coherent Structure Factor',
295 command = lambda : self.analysisDialog(SmoothedStaticCoherentStructureFactor))
296
297
298
299
300 structureMenu = Menu(self.analysisMenu, tearoff = 0)
301
302 self.analysisMenu.add_cascade(label = 'Structure', menu = structureMenu)
303
304
305 structureMenu.add_command(label = 'Pair Distribution Function',
306 command = lambda : self.analysisDialog(PairDistributionFunction))
307
308
309 structureMenu.add_command(label = 'Coordination Number',
310 command = lambda : self.analysisDialog(CoordinationNumber))
311
312
313 structureMenu.add_command(label = 'Spatial Density',
314 command = lambda : self.analysisDialog(SpatialDensity))
315
316 structureMenu.add_separator()
317
318
319 structureMenu.add_command(label = 'ScrewFit Analysis',
320 command = lambda : self.analysisDialog(ScrewFitAnalysis))
321
322
323
324
325 nmrMenu = Menu(self.analysisMenu, tearoff = 0)
326
327 self.analysisMenu.add_cascade(label = 'NMR', menu = nmrMenu)
328
329
330 nmrMenu.add_command(label = 'Order Parameter', command = lambda : self.analysisDialog(OrderParameter))
331
332
333 nmrMenu.add_command(label = 'Order Parameter (Contact Model)', command = lambda : self.analysisDialog(OrderParameterContactModel))
334
335
336 mainMenu.add_cascade(label = "Analysis", menu = self.analysisMenu)
337
338 self.analysisMenu.entryconfig(0, state = DISABLED)
339 self.analysisMenu.entryconfig(1, state = DISABLED)
340 self.analysisMenu.entryconfig(2, state = DISABLED)
341 self.analysisMenu.entryconfig(3, state = DISABLED)
342
343
344
345
346 self.viewMenu = Menu(mainMenu, tearoff = 0)
347
348
349 self.viewMenu.add_command(label = 'Plot', command = self.plotNetCDF, accelerator = accel + 'L')
350 master.bind('<%s>' % (bindKey+'l',), self.plotNetCDF)
351
352
353 self.viewMenu.add_command(label = 'Animation', command = self.animateTrajectory, accelerator = accel + 'M')
354 master.bind('<%s>' % (bindKey+'m',), self.animateTrajectory)
355
356
357 self.viewMenu.add_command(label = 'Effective mode', command = self.viewEffectiveMode, accelerator = accel + 'K')
358 master.bind('<%s>' % (bindKey+'k',), self.viewEffectiveMode)
359
360
361 mainMenu.add_cascade(label = "View", menu = self.viewMenu)
362
363
364
365
366 self.helpMenu = Menu(mainMenu, tearoff = 0)
367
368
369 self.helpMenu.add_command(label = "Documentation", command = self.displayDocumentation, accelerator = accel + 'H')
370 master.bind('<%s>' % (bindKey+'h',), self.displayDocumentation)
371
372
373 self.helpMenu.add_command(label = "Mailing List", command = self.displayMailingList)
374
375
376 self.helpMenu.add_command(label = 'API', command = self.displayAPI, accelerator = accel + 'T')
377 master.bind('<%s>' % (bindKey+'t',), self.displayAPI)
378
379 self.helpMenu.add_separator()
380
381
382
383
384
385
386
387
388 self.helpMenu.add_command(label = 'Analysis benchmark', command = self.analysisBenchmark)
389
390 self.helpMenu.add_separator()
391
392
393
394 self.helpMenu.add_command(label = 'About nMOLDYN', command = self.aboutNMOLDYN, accelerator = accel + 'B')
395 master.bind('<%s>' % (bindKey+'b',), self.aboutNMOLDYN)
396
397
398 mainMenu.add_cascade(label = "Help", menu = self.helpMenu)
399
400
401 master.config(menu = mainMenu)
402
403 mainPanel = Frame(master)
404 mainPanel.grid(row = 0, column = 0)
405
406
407 self.neutronGIF = PhotoImage(file = os.path.join(nmoldyn_package_path, 'GUI', 'Images', 'Neutron.gif'))
408
409 leftFrame = Frame(mainPanel)
410 leftFrame.grid(row = 0, column = 0)
411 Label(leftFrame, image = self.neutronGIF).grid(row = 0)
412 Label(leftFrame, image = self.neutronGIF).grid(row = 1)
413 Label(leftFrame, image = self.neutronGIF).grid(row = 2)
414 Label(leftFrame, image = self.neutronGIF).grid(row = 3)
415 Label(leftFrame, image = self.neutronGIF).grid(row = 4)
416
417 self.info = ComboText(mainPanel)
418 self.info.config({'width' : 500, 'relief' : SUNKEN})
419 self.info.text.config({'wrap' : WORD, 'width' : 80})
420 self.info.grid(row = 0, column = 1, sticky = "NSEW")
421
422 self.info.text.tag_config('12', font = ('Courier', 12))
423 self.info.text.tag_config('12B', font = ('Courier', 12, 'bold'))
424 self.info.text.tag_config('r12B', foreground = 'red', font = ('Courier', 12, 'bold'))
425 self.info.text.tag_config('12I', font = ('Courier', 12, 'normal', 'italic'))
426
427
428 self.proteinGIF = PhotoImage(file = os.path.join(nmoldyn_package_path, 'GUI', 'Images', 'Protein.gif'))
429 rightFrame = Frame(mainPanel)
430 rightFrame.grid(row = 0, column = 2)
431 Label(rightFrame, image = self.proteinGIF).grid(row = 0)
432 Label(rightFrame, image = self.proteinGIF).grid(row = 1)
433 Label(rightFrame, image = self.proteinGIF).grid(row = 2)
434 Label(rightFrame, image = self.proteinGIF).grid(row = 3)
435 Label(rightFrame, image = self.proteinGIF).grid(row = 4)
436
437 mainPanel.grid_rowconfigure(0, weight = 1)
438 self.info.grid_rowconfigure(0, weight = 1)
439 self.info.text.grid_rowconfigure(0, weight = 1)
440
441 if self.netcdf_filename is not None:
442 self.loadNetCDF(filename = self.netcdf_filename)
443
444 return None
445
446 - def cancel(self, event = None):
447 self.destroy()
448 sys.exit(0)
449
450 - def loadNetCDF(self, event = None, filename = None):
451 """
452 This method is launched when the user clicks on the |Load NetCDF| of the |File| menu.
453 It loads the NetCDF file and displays its main informations in the information window.
454 """
455
456 if filename is None:
457
458
459 filename = askopenfilename(filetypes = [("NetCDF trajectory file", "*.nc"),], title = "Open NetCDF",
460 initialdir = PREFERENCES.trajfile_path)
461
462
463 if not filename:
464 return
465
466
467 self.info.cleanup()
468
469
470 self.info.cleanup()
471
472
473 ext = os.path.splitext(filename)[1]
474
475 try:
476 if ext == '.ncs':
477
478 try:
479
480 trajSetFile = open(filename, 'r')
481 trajSet = [t.strip() for t in trajSetFile.readlines()]
482 trajSetFile.close()
483
484
485 self.netcdf = TrajectorySet(None, trajSet)
486
487
488 setattr(self.netcdf, 'filename', trajSet[0])
489 self.netcdf_filename = os.path.abspath(trajSet[0])
490
491 except IOError:
492 raise
493
494 else:
495
496 try:
497
498 self.netcdf_filename = os.path.abspath(filename)
499 self.netcdf = Trajectory(None, filename, 'r')
500
501 except:
502 try:
503 self.netcdf_filename = os.path.abspath(filename)
504 self.netcdf = NetCDFFile(filename, 'r')
505 except:
506 raise
507
508 except:
509 self.netcdf_filename = None
510 self.netcdf = None
511
512 self.info.cleanup()
513 raise Error('The file %s is not a valid NetCDF file.' % filename)
514
515 if isinstance(self.netcdf,Trajectory):
516
517
518 setUniverseContents(self.netcdf.universe)
519
520 if hasattr(self.netcdf,'time'):
521 if self.netcdf.time[1] == self.netcdf.time[0]:
522 firstStep = 0.0
523 lastStep = float(len(self.netcdf))
524 timeStep = 1.0
525 LogMessage('warning', 'No or uncorrect times found in the trajectory. Will create an arbitrary \
526 one from 0 to %d ps.' % lastStep)
527
528 else:
529 timeStep = self.netcdf.time[1] - self.netcdf.time[0]
530 firstStep = self.netcdf.time[0]
531 lastStep = self.netcdf.time[-1]
532
533 else:
534 firstStep = 0.0
535 lastStep = float(len(self.netcdf))
536 timeStep = 1.0
537
538 self.info.insert(contents = 'FILE TYPE: MMTK NETCDF TRAJECTORY FILE\n\n', tag = '12B')
539
540
541 self.info.insert(contents = trajectoryInfo(self.netcdf_filename), tag = '12B')
542 self.info.insert(contents = '\n\nMMTK objects found in the universe: ', tag = '12')
543
544
545 for k in sorted(self.netcdf.universe.nmoldyncontents.keys()):
546
547 if k == '*':
548 continue
549 self.info.insert(contents = '\n\t- %d %s (%s)' % (self.netcdf.universe.nmoldyncontents[k]['number'],k, self.netcdf.universe.nmoldyncontents[k]['objectclass']), tag = '12')
550
551 self.info.insert(contents = '\n\nNumber of frames: ', tag = '12')
552 self.info.insert(contents = str(len(self.netcdf)), tag = '12B')
553 self.info.insert(contents = '\nStarting at: ', tag = '12')
554 self.info.insert(contents = str(round(firstStep,3)) +' ps', tag = '12B')
555 self.info.insert(contents = '\nEnding at: ', tag = '12')
556 self.info.insert(contents = str(round(lastStep,3)) +' ps', tag = '12B')
557 self.info.insert(contents = '\nTime step: ', tag = '12')
558 self.info.insert(contents = str(round(timeStep,3)) +' ps', tag = '12B')
559 self.info.insert(contents = '\n\nUniverse size: ', tag = '12')
560 self.info.insert(contents = str(len(self.netcdf.universe.atomList())), tag = '12B')
561 self.info.insert(contents = '\n\nUniverse topology: ', tag = '12')
562 self.info.insert(contents = self.netcdf.universe.__class__.__name__, tag = '12B')
563
564 directBasis = self.netcdf.universe.basisVectors()
565 if directBasis is not None:
566 self.info.insert(contents = '\n\nDirect basis:', tag = '12')
567 self.info.insert(contents = '\n%8s\t%8s\t%8s' % tuple(['i','j','k']), tag = '12I')
568 for directVector in directBasis:
569 self.info.insert(contents = '\n%8.3f\t%8.3f\t%8.3f' % tuple(directVector), tag = '12I')
570
571 reciprocalBasis = self.netcdf.universe.reciprocalBasisVectors()
572 if reciprocalBasis is not None:
573 self.info.insert(contents = '\n\nReciprocal basis:', tag = '12')
574 self.info.insert(contents = '\n%8s\t%8s\t%8s' % tuple(['i','j','k']), tag = '12I')
575 for reciprocalVector in reciprocalBasis:
576 self.info.insert(contents = '\n%8.3f\t%8.3f\t%8.3f' % tuple(reciprocalVector), tag = '12I')
577
578
579 self.analysisMenu.entryconfig(0, state = NORMAL)
580 self.analysisMenu.entryconfig(1, state = NORMAL)
581 self.analysisMenu.entryconfig(2, state = NORMAL)
582 self.analysisMenu.entryconfig(3, state = NORMAL)
583
584 elif isinstance(self.netcdf, _NetCDFFile):
585
586 self.analysisMenu.entryconfig(0, state = DISABLED)
587 self.analysisMenu.entryconfig(1, state = DISABLED)
588 self.analysisMenu.entryconfig(2, state = DISABLED)
589 self.analysisMenu.entryconfig(3, state = DISABLED)
590
591 self.info.insert(contents = 'FILE TYPE: NETCDF FILE\n\n', tag = '12B')
592
593
594
595 netCDFStringAttributes = ['title', 'history', 'comment', 'jobinfo', 'jobinput']
596 for attr in inspect.getmembers(self.netcdf):
597 if isinstance(attr[1], str) & (attr[0] not in netCDFStringAttributes):
598 netCDFStringAttributes.append(attr[0])
599
600 self.info.insert(contents = 'Information about NetCDF file:\n', tag = '12B')
601 self.info.insert(contents = '%s.\n\n' % filename, tag = '12')
602
603
604 for h in netCDFStringAttributes:
605
606 if hasattr(self.netcdf,h):
607 self.info.insert(contents = '%s:\n' % h.capitalize(), tag = '12B')
608 self.info.insert(contents = getattr(self.netcdf,h)+ '\n\n', tag = '12')
609
610 if hasattr(self.netcdf, 'dimensions'):
611 self.info.insert(contents = '\n\nNetCDF dimensions found:', tag = '12B')
612 for d in self.netcdf.dimensions.items():
613 self.info.insert(contents = '\n\n\t-%s ----> ' % d[0], tag = '12')
614 self.info.insert(contents = '%s' % d[1], tag = 'r12B')
615
616 if hasattr(self.netcdf, 'variables'):
617 self.info.insert(contents = '\n\nNetCDF variables found:', tag = '12B')
618 for v in self.netcdf.variables.items():
619 self.info.insert(contents = '\n\n\t-%s:' % v[0], tag = '12B')
620 self.info.insert(contents = '\n\t\t+ Dimension(s) ----> ', tag = '12')
621 self.info.insert(contents = str(v[1].shape), tag = 'r12B')
622 if hasattr(v[1], 'typecode'):
623 self.info.insert(contents = '\n\t\t+ Typecode ----> ', tag = '12')
624 self.info.insert(contents = v[1].typecode(), tag = 'r12B')
625 else:
626 self.info.insert(contents = '\n\t\t+ Typecode ----> ', tag = '12')
627 self.info.insert(contents = 'Undefined', tag = 'r12B')
628
629 if hasattr(v[1], 'units'):
630 self.info.insert(contents = '\n\t\t+ Units ----> ', tag = '12')
631 self.info.insert(contents = v[1].units, tag = 'r12B')
632 else:
633 self.info.insert(contents = '\n\t\t+ Units ----> ', tag = '12')
634 self.info.insert(contents = 'Undefined', tag = 'r12B')
635
636 try:
637 if v[1].typecode() == N.Character:
638 continue
639
640 if len(v[1].getValue().shape) > 2:
641 raise
642
643 mini = min(v[1].getValue().ravel())
644 maxi = max(v[1].getValue().ravel())
645
646 except:
647 continue
648
649 else:
650 self.info.insert(contents = '\n\t\t+ Range ----> ', tag = '12')
651 self.info.insert(contents = '%.5f to %.5f' % (mini, maxi), tag = 'r12B')
652
653 else:
654 self.netcdf = None
655
656 - def extractTrajectoryFrame(self, event = None):
657 """
658 This method pops up a dialog from where the user can extract a PDB file from a NetCDF
659 trajectory frame.
660 """
661
662 PDBSnapshotGeneratorDialog(self, 'PDB frame extraction', self.netcdf)
663
664 - def convertNetCDFToASCII(self, event = None):
665 """
666 This method pops up a dialog where the user can proceed to a conversion from a file in NetCDF format
667 to ASCII format.
668 """
669
670 NetCDFToASCIIConversionDialog(self, 'NetCDF to ASCII conversion', self.netcdf)
671
672 - def convertASCIIToNetCDF(self, event = None):
673 """
674 This method pops up a dialog where the user can proceed to a conversion from a file in ASCII format
675 to NetCDF format.
676 """
677
678 ASCIIToNetCDFConversionDialog(self, 'ASCII/CDL to NetCDF conversion')
679
681 """
682 This method checks for missing external programs and display some warning if it found some.
683 """
684
685 if os.path.exists(PREFERENCES.ncdump_path):
686 self.fileMenu.entryconfig(5, state = NORMAL)
687
688 else:
689 self.fileMenu.entryconfig(5, state = DISABLED)
690 if PREFERENCES.warning_ncdump.lower() == 'yes':
691 q = askyesno(title = 'Warning', message = 'The path to "ncdump" program has not been set.\n\n\
692 It will not be possible to convert files in NetCDF format to ASCII/CDL format.\n\
693 You should set that path in the "Preferences"-->"ncdump_path" section.\n\n\
694 Show this warning next time nMOLDYN starts ?')
695 if q:
696 setattr(PREFERENCES, 'warning_ncdump', 'yes')
697 else:
698 setattr(PREFERENCES, 'warning_ncdump', 'no')
699
700 if os.path.exists(PREFERENCES.ncgen_path):
701 self.fileMenu.entryconfig(6, state = NORMAL)
702
703 else:
704 self.fileMenu.entryconfig(6, state = DISABLED)
705 if PREFERENCES.warning_ncgen.lower() == 'yes':
706 q = askyesno(title = 'Warning', message = 'The path to "ncgen" program has not been set.\n\n\
707 It will not be possible to convert files in ASCII/CDL fomat to NetCDF format.\n\
708 You should set that path in the "Preferences"-->"ncgen_path" section.\n\n\
709 Show this warning next time nMOLDYN starts ?')
710 if q:
711 setattr(PREFERENCES, 'warning_ncgen', 'yes')
712 else:
713 setattr(PREFERENCES, 'warning_ncgen', 'no')
714
715 if (sys.platform[:5] == 'linux') & (PREFERENCES.documentation_style.lower() == 'pdf'):
716 if os.path.exists(PREFERENCES.acroread_path):
717 self.helpMenu.entryconfig(0, state = NORMAL)
718
719 else:
720 self.helpMenu.entryconfig(0, state = DISABLED)
721 if PREFERENCES.warning_acroread.lower() == 'yes':
722 q = askyesno(title = 'Warning', message = 'The path to acrobat reader has not been set.\n\n\
723 It will not be possible to read the documentation in PDF format.\n\
724 You should set that path in the "Preferences"-->"acroread_path" section.\n\n\
725 Show this warning next time nMOLDYN starts ?')
726 if q:
727 setattr(PREFERENCES, 'warning_acroread', 'yes')
728 else:
729 setattr(PREFERENCES, 'warning_acroread', 'no')
730
731 if os.path.exists(PREFERENCES.vmd_path):
732 self.viewMenu.entryconfig(1, state = NORMAL)
733 self.viewMenu.entryconfig(2, state = NORMAL)
734
735 else:
736 self.viewMenu.entryconfig(1, state = DISABLED)
737 self.viewMenu.entryconfig(2, state = DISABLED)
738 if PREFERENCES.warning_vmd.lower() == 'yes':
739 q = askyesno(title = 'Warning', message = 'The path to "vmd" program has not been set.\n\n\
740 It will not be possible to visualize any trajectory in nMOLDYN.\n\
741 You should set that path in the "Preferences"-->"vmd_path" section.\n\n\
742 Show this warning next time nMOLDYN starts ?')
743 if q:
744 setattr(PREFERENCES, 'warning_vmd', 'yes')
745 else:
746 setattr(PREFERENCES, 'warning_vmd', 'no')
747
748 - def setPreferences(self, event = None):
749 """
750 This method pops up a dialog from where the user can edit the nMOLDYN configuration file.
751 """
752
753 PreferencesDialog(self, 'Preferences')
754
755 self.checkConfiguration()
756
757 - def analysisDialog(self, analysis):
758 """
759 """
760
761 AnalysisDialog(self, analysis, self.netcdf)
762
763 - def plotNetCDF(self, event = None):
764 """
765 This method pops up a dialog from where the user can display any numeric 2D or 3D NetCDF variables.
766 """
767
768 PlotNetCDFVariableDialog(self, 'Plot NetCDF', self.netcdf)
769
770 - def animateTrajectory(self, event = None):
771 """
772 This method pops up a dialog from where the user can animate a trajectory. If a trajectory has been loaded
773 for analysis this will be the default one. Otherwise the user can still browse one from the dialog.
774 The animation requires VMD.
775 """
776
777 AnimationDialog(self, 'Trajectory animation', self.netcdf)
778
779 - def viewEffectiveMode(self, event = None):
780 """
781 This method pops up a dialog from where the user can animate an effective mode coming from a QHA
782 analysis.
783 The animation require VMD.
784 """
785
786 ViewEffectiveModeDialog(self, 'Effective mode viewer')
787
788 - def traceAnalysis(self, event = None):
789 """
790 This method pops up a dialog from where the user can check the march of the running jobs.
791 The dialog can be updated dynamically by pressing its button 'refresh'.
792 """
793
794 CheckJobsStatusDialog(self, 'Job progress')
795
797 """
798 This method pops up a dialog from where the user can perform some analysis benchmark. The benchmark is
799 done between the current version and a reference version that is the version 2.2.5 the last official release
800 of nMOLDYN.
801 """
802
803 AnalysisBenchmarkDialog(self, 'Analysis benchmark')
804
805 - def displayDocumentation(self, event = None):
806 """
807 This methode opens the nMOLDYN pdf users guide.
808 The users guide was written by E. Pellegrini, V. Calandrini, P. Calligari, K. Hinsen and G.R. Kneller.
809 """
810
811 if PREFERENCES.documentation_style.lower() == 'html':
812 webbrowser.open(os.path.join(nmoldyn_package_path, 'Doc', 'UsersGuide', 'HTML', 'index.html'))
813
814 elif PREFERENCES.documentation_style.lower() == 'pdf':
815
816 pdfFile = os.path.join(nmoldyn_package_path, 'Doc', 'UsersGuide', 'PDF', 'nMOLDYN_ug.pdf')
817
818
819 if sys.platform == 'win32':
820 os.startfile(pdfFile)
821
822
823 elif sys.platform == 'darwin':
824 subprocess.call(['open', pdfFile])
825
826 else:
827
828 try:
829 subprocess.call([PREFERENCES.acroread_path, pdfFile])
830 except:
831 raise Error('Unable to read the file %s\nwith the acrobat reader located in %s.' % (pdfFile, PREFERENCES.acroread_path))
832 else:
833 raise Error('Unknow documentation format: %s.' % PREFERENCES.documentations_style)
834
836 """
837 This methode opens the nMOLDYN mailing list.
838 """
839
840 webbrowser.open('http://sourcesup.cru.fr/forum/?group_id=194')
841
842 - def displayAPI(self, event = None):
843
844 if PREFERENCES.documentation_style.lower() == 'html':
845 webbrowser.open(os.path.join(nmoldyn_package_path, 'Doc', 'API', 'HTML', 'index.html'))
846
847 elif PREFERENCES.documentation_style.lower() == 'pdf':
848
849 pdfFile = os.path.join(nmoldyn_package_path, 'Doc', 'API', 'PDF', 'api.pdf')
850
851
852 if sys.platform == 'win32':
853 os.startfile(pdfFile)
854
855
856 elif sys.platform == 'darwin':
857 subprocess.call(['open', pdfFile])
858
859 else:
860
861 try:
862 subprocess.call([PREFERENCES.acroread_path, pdfFile])
863 except:
864 raise Error('Unable to read the file %s\nwith the acrobat reader located in %s.' % (pdfFile, PREFERENCES.acroread_path))
865
866 else:
867 raise Error('Unknow documentation format: %s.' % PREFERENCES.documentations_style)
868
869 - def aboutNMOLDYN(self, event = None):
870 """
871 This method displays general informations about the program such as the developper, the main versions ...
872 """
873
874 GeneralInformationsDialog(self, 'About nMOLDYN')
875