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

# Source Code for Module nMOLDYN.GUI.TrajectoryConversionDialog

       1  """This modules implements I{File --> Trajectory conversion --> converter} dialog.
       2
       3  Classes:
       4      * AmberNetCDFConverterDialog: sets up I{File-->Trajectory conversion --> Amber NetCDF to MMTK} dialog used to
       5        convert an AMBER trajectory to a MMTK NetCDF trajectory.
       6      * CHARMMConverterDialog: sets up I{File-->Trajectory conversion --> CHARMM/X-PLOR to MMTK} dialog used to
       7        convert a CHARMM or X-PLOR trajectory to a MMTK NetCDF trajectory.
       8      * DL_POLYConverterDialog: sets up I{File-->Trajectory conversion --> DL_POLY to MMTK} dialog used to
       9        convert a DL_POLY trajectory to a MMTK NetCDF trajectory.
      10      * MaterialsStudioConverterDialog: sets up I{File-->Trajectory conversion --> MaterialsStudio --> Discover to MMTK} or
      11        I{File-->Trajectory conversion --> MaterialsStudio --> Forcite to MMTK} dialogs used to convert a Discover or a
      12        Forcite trajectory to a MMTK NetCDF trajectory.
      13      * NAMDConverterDialog: sets up I{File-->Trajectory conversion --> NAMD to MMTK} dialog used to
      14        convert a NAMD trajectory to a MMTK NetCDF trajectory.
      15      * VASPConverterDialog: sets up I{File-->Trajectory conversion --> VASP to MMTK} dialog used to
      16        convert a VASP trajectory to a MMTK NetCDF trajectory.
      17  """
      18
      19  import re
      20
      21  # The Tcl/Tk modules
      22  from tkFileDialog import askopenfilename
      23  from Tkinter import *
      24
      25  # The ScientificPython modules
      26  from Scientific.Geometry import Vector
      27
      28  # The MMTK distribution modules
      29  from MMTK import Atom, AtomCluster, Units
      30  from MMTK.Trajectory import Trajectory, SnapshotGenerator, TrajectoryOutput
      31  from MMTK.Universe import InfiniteUniverse, OrthorhombicPeriodicUniverse, ParallelepipedicPeriodicUniverse
      32
      33  # The nMOLDYN modules
      34  from nMOLDYN.Core.Error import Error
      35  from nMOLDYN.Core.IOFiles import AmberNetCDFConverter, CHARMMConverter, DL_POLYConverter, MaterialsStudioConverter, NAMDConverter, VASPConverter
      36  from nMOLDYN.Core.Logger import LogMessage
      37  from nMOLDYN.GUI.Widgets import *
      38
      39 -class AmberNetCDFConverterDialog(Toplevel):
      40      """Sets up a dialog for the conversion from an Amber NetCDF trajectory to a MMTK NetCDF trajectory.
      41
      42      @note: the conversion requires a AMber NetCDF and PDB file and the time step in ps between two frames.
      43      """
      44
      45 -    def __init__(self, parent):
      46          """The constructor.
      47
      48          @param parent: the parent widget.
      49          """
      50
      51          Toplevel.__init__(self, parent)
      52          self.transient(parent)
      53
      54          self.title('Amber --> MMTK NetCDF converter')
      55
      56          self.parent = parent
      57
      58          body = Frame(self)
      59          self.initial_focus = self.body(body)
      60          body.grid(row = 0, column = 0, sticky = EW)
      61
      62          self.buttonbox()
      63
      64          self.grab_set()
      65
      66          if not self.initial_focus:
      67              self.initial_focus = self
      68
      69          self.protocol("WM_DELETE_WINDOW", self.cancel)
      70
      71          self.resizable(width = NO, height = NO)
      72
      73          self.geometry("+%d+%d" % (parent.winfo_rootx()+50, parent.winfo_rooty()+50))
      74
      75          self.initial_focus.focus_set()
      76
      77          self.wait_window(self)
      78
      79 -    def body(self, master):
      80          """
      81          Create dialog body. Return widget that should have initial focus.
      82          """
      83
      84          settingsFrame = LabelFrame(master, text = 'Settings', bd = 2, relief = GROOVE)
      85          settingsFrame.grid(row = 0, column = 0, sticky = EW, padx = 3, pady = 3)
      86          settingsFrame.grid_columnconfigure(0, weight = 1)
      87
      88          # The combo widget to browse the PDB input file.
      89          self.pdbFileBrowser = ComboFileBrowser(settingsFrame,\
      90                                                 frameLabel = "PDB input file",\
      91                                                 tagName = 'amber_converter_pdb_input_file',\
      92                                                 contents = '',\
      93                                                 filetypes = [('PDB', '*.pdb'), ('All files', '*')],\
      94                                                 save = False)
      95          self.pdbFileBrowser.grid(row = 0, column = 0, padx = 2, pady = 2, sticky = W)
      96
      97          # The combo widget to browse the Amber NetCDF input file.
      98          self.amberNetCDFFileBrowser = ComboFileBrowser(settingsFrame,\
      99                                                         frameLabel = "Amber NetCDF input file",\
     100                                                         tagName = 'amber_converter_netcdf_input_file',\
     101                                                         contents = '',\
     102                                                         filetypes = [('Amber NetCDF', '*.nc'), ('All files', '*')],\
     103                                                         save = False)
     104          self.amberNetCDFFileBrowser.grid(row = 1, column = 0, padx = 2, pady = 2, sticky = EW)
     105          self.amberNetCDFFileBrowser.grid_columnconfigure(0, weight = 1)
     106          self.amberNetCDFFileBrowser.entry.variable.trace('w', self.suggestOutputFilename)
     107
     108          # The combo widget to select the time step in ps between two consecutive frames..
     109          self.timeStepEntry = ComboFloatEntry(settingsFrame,\
     110                                               frameLabel = "Time step (in ps)",\
     111                                               tagName = 'amber_converter_time_step',\
     112                                               contents = 1.0)
     113          self.timeStepEntry.grid(row = 2, column = 0, padx = 2, pady = 2, sticky = EW)
     114          self.timeStepEntry.grid_columnconfigure(0, weight = 1)
     115
     116          # The combo widget to browse the MMTK output file.
     117          self.outputFileBrowser = ComboFileBrowser(settingsFrame,\
     118                                                    frameLabel = "MMTK NetCDF output file",\
     119                                                    tagName = 'amber_converter_mmtk_netcdf_output_file',\
     120                                                    contents = '',\
     121                                                    save = True)
     122          self.outputFileBrowser.grid(row = 3, column = 0, padx = 2, pady = 2, sticky = EW)
     123          self.outputFileBrowser.grid_columnconfigure(0, weight = 1)
     124
     125          return None
     126
     127 -    def buttonbox(self):
     128          """
     129          Add standard button box.
     130          """
     131
     132          # The frame that contains the 'Cancel' and 'OK' buttons.
     133          box = LabelFrame(self, text = 'Actions', bd = 2, relief = GROOVE)
     134          box.grid(row = 1, column = 0, sticky = EW, padx = 3, pady = 3)
     135          box.grid_columnconfigure(0, weight = 1)
     136
     137          w = Button(box, text = "Cancel", width=10, command = self.cancel)
     138          w.grid(row = 0, column = 0, sticky = E)
     139          w = Button(box, text = "OK", width=10, command = self.ok, default=ACTIVE)
     140          w.grid(row = 0, column = 1, sticky = E)
     141
     142          self.bind("<Return>", self.ok)
     143          self.bind("<Escape>", self.cancel)
     144
     145      # Standard button semantics.
     146 -    def ok(self, event = None):
     147
     148          if not self.validate():
     149              self.initial_focus.focus_set()
     150              return
     151
     152          self.update_idletasks()
     153
     154          self.apply()
     155
     156 -    def cancel(self, event=None):
     157
     158          # Put focus back to the parent window
     159          self.parent.focus_set()
     160          self.destroy()
     161
     162      # Command hooks
     163 -    def validate(self):
     164
     165          self.pdbFile = self.pdbFileBrowser.getValue()
     166          # A PDB input file must have been set.
     167          if not self.pdbFile:
     168              raise Error('Please enter a PDB input file.')
     169
     170          # A NetCDF input file must have been set.
     171          self.amberNetCDFFile = self.amberNetCDFFileBrowser.getValue()
     172          if not self.amberNetCDFFile:
     173              raise Error('Please enter an Amber NetCDF input file.')
     174
     175          # The MMTK output file must have been set.
     176          self.outputFile = self.outputFileBrowser.getValue()
     177          if not self.outputFile:
     178              raise Error('Please enter a MMTK NetCDF output file.')
     179
     180          if self.outputFile[-3:] != '.nc':
     181              self.outputFile += '.nc'
     182
     183          self.timeStep = self.timeStepEntry.getValue()
     184          if self.timeStep <= 0.0:
     185              raise Error('Time step must be > 0.')
     186
     187          return True
     188
     189 -    def apply(self):
     190          """
     191          This method starts the conversion.
     192          """
     193
     194          converter = AmberNetCDFConverter(self.pdbFile, self.amberNetCDFFile, self.outputFile, self.timeStep)
     195          LogMessage('info', 'Conversion successful', ['gui'])
     196
     197 -    def suggestOutputFilename(self, *dummy):
     198          """
     199          This method will propose a name for the output file based on the name of the loaded file.
     200          """
     201
     202          if self.amberNetCDFFileBrowser.getValue():
     203              self.outputFileBrowser.setValue(os.path.splitext(self.amberNetCDFFileBrowser.getValue())[0] + '_mmtk.nc')
     204
     205 -class CHARMMConverterDialog(Toplevel):
     206      """Sets up a dialog used for the conversion from a CHARMM/X-PLOR/NAMD trajectory to a MMTK NetCDF trajectory.
     207
     208      @note: the conversion requires CHARMM/X-PLOR DCD and PDB files.
     209      """
     210
     211 -    def __init__(self, parent):
     212          """The constructor.
     213
     214          @param parent: the parent widget.
     215          """
     216
     217          Toplevel.__init__(self, parent)
     218          self.transient(parent)
     219
     220          self.title('CHARMM/X-PLOR --> MMTK NetCDF converter')
     221
     222          self.parent = parent
     223
     224          body = Frame(self)
     225          self.initial_focus = self.body(body)
     226          body.grid(row = 0, column = 0, sticky = EW)
     227
     228          self.buttonbox()
     229
     230          self.grab_set()
     231
     232          if not self.initial_focus:
     233              self.initial_focus = self
     234
     235          self.protocol("WM_DELETE_WINDOW", self.cancel)
     236
     237          self.resizable(width = NO, height = NO)
     238
     239          self.geometry("+%d+%d" % (parent.winfo_rootx()+50, parent.winfo_rooty()+50))
     240
     241          self.initial_focus.focus_set()
     242
     243          self.wait_window(self)
     244
     245 -    def body(self, master):
     246          """
     247          Create dialog body. Return widget that should have initial focus.
     248          """
     249
     250          settingsFrame = LabelFrame(master, text = 'Settings', bd = 2, relief = GROOVE)
     251          settingsFrame.grid(row = 0, column = 0, sticky = EW, padx = 3, pady = 3)
     252          settingsFrame.grid_columnconfigure(0, weight = 1)
     253
     254          # The combo widget to browse the PDB input file.
     255          self.pdbFileBrowser = ComboFileBrowser(settingsFrame,\
     256                                                 frameLabel = "PDB input file",\
     257                                                 tagName = "charmm_converter_pdb_input_file",\
     258                                                 contents = '',\
     259                                                 filetypes = [('PDB', '*.pdb'), ('All files', '*')],\
     260                                                 save = False)
     261          self.pdbFileBrowser.grid(row = 0, column = 0, padx = 2, pady = 2, sticky = EW)
     262          self.pdbFileBrowser.grid_columnconfigure(0, weight = 1)
     263
     264          # The combo widget to browse the DCD input file.
     265          self.dcdFileBrowser = ComboFileBrowser(settingsFrame,\
     266                                                 frameLabel = "DCD input file",\
     267                                                 tagName = "charmm_converter_dcd_input_file",\
     268                                                 contents = '',\
     269                                                 filetypes = [('DCD input file', '*.dcd'), ('All files', '*')],\
     270                                                 save = False)
     271          self.dcdFileBrowser.grid(row = 1, column = 0, padx = 2, pady = 2, sticky = EW)
     272          self.dcdFileBrowser.grid_columnconfigure(0, weight = 1)
     273          self.dcdFileBrowser.entry.variable.trace('w', self.suggestOutputFilename)
     274
     275          # The combo widget to browse the MMTK output file.
     276          self.outputFileBrowser = ComboFileBrowser(settingsFrame,\
     277                                                    frameLabel = "MMTK NetCDF output file",\
     278                                                    tagName = "charmm_converter_mmtk_netcdf_output_file",\
     279                                                    contents = '',\
     280                                                    save = True)
     281          self.outputFileBrowser.grid(row = 3, column = 0, padx = 2, pady = 2, sticky = EW)
     282          self.outputFileBrowser.grid_columnconfigure(0, weight = 1)
     283
     284          return None
     285
     286 -    def buttonbox(self):
     287          """
     288          Add standard button box.
     289          """
     290
     291          # The frame that contains the 'Cancel' and 'OK' buttons.
     292          box = LabelFrame(self, text = 'Actions', bd = 2, relief = GROOVE)
     293          box.grid(row = 1, column = 0, sticky = EW, padx = 3, pady = 3)
     294          box.grid_columnconfigure(0, weight = 1)
     295
     296          w = Button(box, text = "Cancel", width=10, command = self.cancel)
     297          w.grid(row = 0, column = 0, sticky = E)
     298          w = Button(box, text = "OK", width=10, command = self.ok, default=ACTIVE)
     299          w.grid(row = 0, column = 1, sticky = E)
     300
     301          self.bind("<Return>", self.ok)
     302          self.bind("<Escape>", self.cancel)
     303
     304      # Standard button semantics.
     305 -    def ok(self, event = None):
     306
     307          if not self.validate():
     308              self.initial_focus.focus_set()
     309              return
     310
     311          self.update_idletasks()
     312
     313          self.apply()
     314
     315 -    def cancel(self, event=None):
     316
     317          # Put focus back to the parent window
     318          self.parent.focus_set()
     319          self.destroy()
     320
     321      # Command hooks
     322 -    def validate(self):
     323
     324          self.pdbFile = self.pdbFileBrowser.getValue()
     325          # A PDB input file must have been set.
     326          if not self.pdbFile:
     327              raise Error('Please enter a PDB input file.')
     328
     329          # A DCD input file must have been set.
     330          self.dcdFile = self.dcdFileBrowser.getValue()
     331          if not self.dcdFile:
     332              raise Error('Please enter a DCD input file.')
     333
     334          # The MMTK output file must have been set.
     335          self.outputFile = self.outputFileBrowser.getValue()
     336          if not self.outputFile:
     337              raise Error('Please enter a MMTK NetCDF output file.')
     338
     339          if self.outputFile[-3:] != '.nc':
     340              self.outputFile += '.nc'
     341
     342          return True
     343
     344 -    def apply(self):
     345          """
     346          This method starts the conversion.
     347          """
     348
     349          converter = CHARMMConverter(self.pdbFile, self.dcdFile, self.outputFile)
     350          LogMessage('info', 'Conversion successful', ['gui'])
     351
     352 -    def suggestOutputFilename(self, *dummy):
     353          """
     354          This method will propose a name for the output file based on the name of the loaded file.
     355          """
     356
     357          if self.dcdFileBrowser.getValue():
     358              self.outputFileBrowser.setValue(os.path.splitext(self.dcdFileBrowser.getValue())[0] + '.nc')
     359
     360 -class DL_POLYConverterDialog(Toplevel):
     361      """Sets up a dialog used for the conversion from a DL_POLY trajectory to a MMTK NetCDF trajectory.
     362
     363      @note: the conversion requires the DL_POLY FIELD and HISTORY files and additional information to specify
     364      the atoms whose names is not sufficient to determine which element they are.
     365      """
     366
     367 -    def __init__(self, parent):
     368          """The constructor.
     369
     370          @param parent: the parent widget.
     371          """
     372
     373          Toplevel.__init__(self, parent)
     374          self.transient(parent)
     375
     376          self.title('DL_POLY --> MMTK NetCDF converter')
     377
     378          self.parent = parent
     379
     380          body = Frame(self)
     381          self.initial_focus = self.body(body)
     382          body.grid(row = 0, column = 0, sticky = EW)
     383
     384          self.buttonbox()
     385
     386          self.grab_set()
     387
     388          if not self.initial_focus:
     389              self.initial_focus = self
     390
     391          self.protocol("WM_DELETE_WINDOW", self.cancel)
     392
     393          self.resizable(width = NO, height = NO)
     394
     395          self.geometry("+%d+%d" % (parent.winfo_rootx()+50, parent.winfo_rooty()+50))
     396
     397          self.initial_focus.focus_set()
     398
     399          self.wait_window(self)
     400
     401 -    def body(self, master):
     402          """
     403          Create dialog body. Return widget that should have initial focus.
     404          """
     405
     406          settingsFrame = LabelFrame(master, text = 'Settings', bd = 2, relief = GROOVE)
     407          settingsFrame.grid(row = 0, column = 0, sticky = EW, padx = 3, pady = 3)
     408          settingsFrame.grid_columnconfigure(0, weight = 1)
     409
     410          # The combo widget to browse the DL_POLY FIELD file.
     411          self.fieldFileBrowser = ComboFileBrowser(settingsFrame,\
     412                                                   frameLabel = "FIELD input file",\
     413                                                   tagName = "dlpoly_converter_field_input_file",\
     414                                                   contents = '',\
     415                                                   filetypes = [('FIELD files', 'FIELD*'),('All files', '*')],\
     416                                                   save = False)
     417          self.fieldFileBrowser.grid(row = 0, column = 0, padx = 2, pady = 2, sticky = EW)
     418          self.fieldFileBrowser.grid_columnconfigure(0, weight = 1)
     419
     420          # The combo widget to browse the DL_POLY HISTORY file.
     421          self.historyFileBrowser = ComboFileBrowser(settingsFrame,\
     422                                                     frameLabel = "HISTORY input file",\
     423                                                     tagName = "dlpoly_converter_history_input_file",\
     424                                                     contents = '',\
     425                                                     filetypes = [('HISTORY files', 'HISTORY*'),('All files', '*')],\
     426                                                     save = False)
     427          self.historyFileBrowser.grid(row = 1, column = 0, padx = 2, pady = 2, sticky = EW)
     428          self.historyFileBrowser.grid_columnconfigure(0, weight = 1)
     429
     430          # The combo widget to specify the atoms whose names is not sufficient to determine which element they are.
     431          self.specialAtomsEntry = ComboStringEntry(settingsFrame,\
     432                                                    frameLabel = "Special atoms",\
     433                                                    tagName = 'dlpoly_converter_special_atoms',\
     434                                                    contents = '')
     435          self.specialAtomsEntry.grid(row = 2, column = 0, padx = 2, pady = 2, sticky = EW)
     436          self.specialAtomsEntry.grid_columnconfigure(0, weight = 1)
     437
     438          # The combo widget to browse the MMTK output file.
     439          self.outputFileBrowser = ComboFileBrowser(settingsFrame,\
     440                                                    frameLabel = "MMTK NetCDF output file",\
     441                                                    tagName = 'dlpoly_converter_mmtk_netcdf_output_file',\
     442                                                    contents = '',\
     443                                                    save = True)
     444          self.outputFileBrowser.grid(row = 3, column = 0, padx = 2, pady = 2, sticky = EW)
     445          self.outputFileBrowser.grid_columnconfigure(0, weight = 1)
     446
     447          return None
     448
     449 -    def buttonbox(self):
     450          """
     451          Add standard button box.
     452          """
     453
     454          # The frame that contains the 'Cancel' and 'OK' buttons.
     455          box = LabelFrame(self, text = 'Actions', bd = 2, relief = GROOVE)
     456          box.grid(row = 1, column = 0, sticky = EW, padx = 3, pady = 3)
     457          box.grid_columnconfigure(0, weight = 1)
     458
     459          w = Button(box, text = "Cancel", width=10, command = self.cancel)
     460          w.grid(row = 0, column = 0, sticky = E)
     461          w = Button(box, text = "OK", width=10, command = self.ok, default=ACTIVE)
     462          w.grid(row = 0, column = 1, sticky = E)
     463
     464          self.bind("<Return>", self.ok)
     465          self.bind("<Escape>", self.cancel)
     466
     467      # Standard button semantics.
     468 -    def ok(self, event = None):
     469
     470          if not self.validate():
     471              self.initial_focus.focus_set()
     472              return
     473
     474          self.update_idletasks()
     475
     476          self.apply()
     477
     478 -    def cancel(self, event=None):
     479
     480          # Put focus back to the parent window
     481          self.parent.focus_set()
     482          self.destroy()
     483
     484      # Command hooks
     485 -    def validate(self):
     486
     487          # A FIELD input file must have been set.
     488          self.fieldFile = self.fieldFileBrowser.getValue()
     489          if not self.fieldFile:
     490              raise Error('Please enter a FIELD input file.')
     491
     492          # A HISTORY input file must have been set.
     493          self.historyFile = self.historyFileBrowser.getValue()
     494          if not self.historyFile:
     495              raise Error('Please enter a HISTORY input file.')
     496
     497          # The MMTK output file must have been set.
     498          self.outputFile = self.outputFileBrowser.getValue()
     499          if not self.outputFile:
     500              raise Error('Please enter a MMTK NetCDF output file.')
     501
     502          if self.outputFile[-3:] != '.nc':
     503              self.outputFile += '.nc'
     504
     505          self.specialAtoms = self.specialAtomsEntry.getValue()
     506          if not self.specialAtoms:
     507              self.specialAtoms = {}
     508
     509          else:
     510              try:
     511                  self.specialAtoms = dict(re.findall('(\w+):(\w+)',self.specialAtoms))
     512              except:
     513                  raise Error('Wrong format for special atoms declaration. \
     514  Must be of the form special atom name1:corresponding element,...')
     515
     516          return True
     517
     518 -    def apply(self):
     519
     520          converter = DL_POLYConverter(self.fieldFile, self.historyFile, self.outputFile, self.specialAtoms)
     521          LogMessage('info', 'Conversion successful', ['gui'])
     522
     523 -class MaterialsStudioConverterDialog(Toplevel):
     524      """Sets up a dialog used for the conversion from a MaterialsStudio trajectory to a MMTK NetCDF trajectory.
     525
     526      @note: the conversion requires MaterialsStudio XTD or XSD file and HIS or TRJ files according to the MaterialsStudio modules used to
     527      produce the trajectory (HIS for Discover and TRJ for Forcite).
     528      """
     529
     530 -    def __init__(self, parent, module):
     531          """The constructor.
     532
     533          @param parent: the parent widget.
     534          """
     535
     536          Toplevel.__init__(self, parent)
     537          self.transient(parent)
     538
     539          self.title('MaterialsStudio-%s --> MMTK NetCDF converter' % module)
     540
     541          self.parent = parent
     542          self.module = module
     543
     544          body = Frame(self)
     545          self.initial_focus = self.body(body)
     546          body.grid(row = 0, column = 0, sticky = EW)
     547
     548          self.buttonbox()
     549
     550          self.grab_set()
     551
     552          if not self.initial_focus:
     553              self.initial_focus = self
     554
     555          self.protocol("WM_DELETE_WINDOW", self.cancel)
     556
     557          self.resizable(width = NO, height = NO)
     558
     559          self.geometry("+%d+%d" % (parent.winfo_rootx()+50, parent.winfo_rooty()+50))
     560
     561          self.initial_focus.focus_set()
     562
     563          self.wait_window(self)
     564
     565 -    def body(self, master):
     566          """
     567          Create dialog body. Return widget that should have initial focus.
     568          """
     569
     570          module = self.module.lower()
     571
     572          settingsFrame = LabelFrame(master, text = 'Settings', bd = 2, relief = GROOVE)
     573          settingsFrame.grid(row = 0, column = 0, sticky = EW, padx = 3, pady = 3)
     574          settingsFrame.grid_columnconfigure(0, weight = 1)
     575
     576          # The combo widget to browse the XTD or the XSD input file.
     577          self.xtdxsdFileBrowser = ComboFileBrowser(settingsFrame,\
     578                                                    frameLabel = "XTD/XSD input file",\
     579                                                    tagName = '%s_converter_xtd_xsd_input_file' % module,\
     580                                                    contents = '',\
     581                                                    filetypes = [('XTD input file', '*.xtd'), ('XSD input file', '*.xsd'), ('All files', '*')],\
     582                                                    save = False)
     583          self.xtdxsdFileBrowser.grid(row = 0, column = 0, padx = 2, pady = 2, sticky = EW)
     584          self.xtdxsdFileBrowser.grid_columnconfigure(0, weight = 1)
     585
     586          if self.module == 'Discover':
     587              # The combo widget to browse the HIS input file.
     588              self.histrjFileBrowser = ComboFileBrowser(settingsFrame,\
     589                                                        frameLabel = "HIS input file",\
     590                                                        tagName = 'discover_converter_his_input_file',\
     591                                                        contents = '',\
     592                                                        filetypes = [('HIS input file', '*.his'), ('All files', '*')],\
     593                                                        save = False)
     594          elif self.module == 'Forcite':
     595              # The combo widget to browse the TRJ input file.
     596              self.histrjFileBrowser = ComboFileBrowser(settingsFrame,\
     597                                                        frameLabel = "TRJ input file",\
     598                                                        tagName = 'forcite_converter_trj_input_file',\
     599                                                        contents = '',\
     600                                                        filetypes = [('TRJ input file', '*.trj'), ('All files', '*')],\
     601                                                        save = False)
     602
     603          self.histrjFileBrowser.grid(row = 1, column = 0, padx = 2, pady = 2, sticky = EW)
     604          self.histrjFileBrowser.grid_columnconfigure(0, weight = 1)
     605          self.histrjFileBrowser.entry.variable.trace('w', self.suggestOutputFilename)
     606
     607          # The combo widget to extract specific parts of the system.
     608          self.subselectionEntry = ComboStringEntry(settingsFrame,\
     609                                                    frameLabel = "Subselection",\
     610                                                    tagName = '%s_converter_subselection' % module,\
     611                                                    contents = '')
     612          self.subselectionEntry.grid(row = 2, column = 0, padx = 2, pady = 2, sticky = EW)
     613          self.subselectionEntry.grid_columnconfigure(0, weight = 1)
     614
     615          # The combo widget to browse the MMTK output file.
     616          self.outputFileBrowser = ComboFileBrowser(settingsFrame,\
     617                                                    frameLabel = "MMTK NetCDF output file",\
     618                                                    tagName = '%s_converter_mmtk_netcdf_output_file' % module,\
     619                                                    contents = '',\
     620                                                    save = True)
     621          self.outputFileBrowser.grid(row = 3, column = 0, padx = 2, pady = 2, sticky = EW)
     622          self.outputFileBrowser.grid_columnconfigure(0, weight = 1)
     623
     624          return None
     625
     626 -    def buttonbox(self):
     627          """
     628          Add standard button box.
     629          """
     630
     631          # The frame that contains the 'Cancel' and 'OK' buttons.
     632          box = LabelFrame(self, text = 'Actions', bd = 2, relief = GROOVE)
     633          box.grid(row = 1, column = 0, sticky = EW, padx = 3, pady = 3)
     634          box.grid_columnconfigure(0, weight = 1)
     635
     636          w = Button(box, text = "Cancel", width=10, command = self.cancel)
     637          w.grid(row = 0, column = 0, sticky = E)
     638          w = Button(box, text = "OK", width=10, command = self.ok, default=ACTIVE)
     639          w.grid(row = 0, column = 1, sticky = E)
     640
     641          self.bind("<Return>", self.ok)
     642          self.bind("<Escape>", self.cancel)
     643
     644      # Standard button semantics.
     645 -    def ok(self, event = None):
     646
     647          if not self.validate():
     648              self.initial_focus.focus_set()
     649              return
     650
     651          self.update_idletasks()
     652
     653          self.apply()
     654
     655 -    def cancel(self, event=None):
     656
     657          # Put focus back to the parent window
     658          self.parent.focus_set()
     659          self.destroy()
     660
     661      # Command hooks
     662 -    def validate(self):
     663
     664          # A XTD or XSD input file must have been set.
     665          self.xtdxsdFile = self.xtdxsdFileBrowser.getValue()
     666          if not self.xtdxsdFile:
     667              raise Error('Please enter a XTD or XSD input file.')
     668
     669          # A HIS or TRJ input file must have been set.
     670          self.histrjFile = self.histrjFileBrowser.getValue()
     671          if not self.histrjFile:
     672              raise Error('Please enter a HIS or TRJ input file.')
     673
     674          # Case where a subselection has been specified. It must be a python expression that gives
     675          # the index of the atoms to select.
     676          self.subselection = self.subselectionEntry.getValue().strip()
     677          if self.subselection:
     678              try:
     679                  self.subselection = eval(self.subselection)
     680
     681                  if isinstance(self.subselection, int):
     682                      self.subselection = [[self.subselection]]
     683
     684                  elif isinstance(self.subselection, (list,tuple)):
     685                      pass
     686              except:
     687                  try:
     688                      self.subselection = [range(int(v[0]),int(v[1])+1,int(v[2])) for v in re.findall('(\d+):(\d+):(\d+)',subsel)]
     689                  except:
     690                      raise Error('Wrong format for frame selection.')
     691
     692              # Check that the subselection list is valid.
     693              for s in self.subselection:
     694                  if not isinstance(s, (list, tuple)):
     695                      raise Error('The parsed subselection must be a nested list of integers.')
     696
     697                  for ss in s:
     698                      if not isinstance(ss, int):
     699                          raise Error('The parsed subselection must be a nested list of integers.')
     700
     701          # The MMTK output file must have been set.
     702          self.outputFile = self.outputFileBrowser.getValue()
     703          if not self.outputFile:
     704              raise Error('Please enter a MMTK NetCDF output file.')
     705
     706          if self.outputFile[-3:] != '.nc':
     707              self.outputFile += '.nc'
     708
     709          return True
     710
     711 -    def apply(self):
     712
     713          converter = MaterialsStudioConverter(self.module, self.xtdxsdFile, self.histrjFile, self.outputFile, self.subselection)
     714          LogMessage('info', 'Conversion successful', ['gui'])
     715
     716 -    def suggestOutputFilename(self, *dummy):
     717          """
     718          This method will propose a name for the output file based on the name of the loaded file.
     719          """
     720
     721          if self.histrjFileBrowser.getValue():
     722              self.outputFileBrowser.setValue(os.path.splitext(self.histrjFileBrowser.getValue())[0] + '.nc')
     723
     724 -class NAMDConverterDialog(Toplevel):
     725      """Sets up a dialog used for the conversion from a CHARMM/X-PLOR/NAMD trajectory to a MMTK NetCDF trajectory.
     726
     727      @note: the conversion requires CHARMM/X-PLOR/NAMD DCD and PDB files and optionnaly the simulation box dimensions.
     728      """
     729
     730 -    def __init__(self, parent):
     731          """
     732          The constructor.
     733          """
     734
     735          Toplevel.__init__(self, parent)
     736          self.transient(parent)
     737
     738          self.title('NAMD --> MMTK NetCDF converter')
     739
     740          self.parent = parent
     741
     742          body = Frame(self)
     743          self.initial_focus = self.body(body)
     744          body.grid(row = 0, column = 0, sticky = EW)
     745
     746          self.buttonbox()
     747
     748          self.grab_set()
     749
     750          if not self.initial_focus:
     751              self.initial_focus = self
     752
     753          self.protocol("WM_DELETE_WINDOW", self.cancel)
     754
     755          self.resizable(width = NO, height = NO)
     756
     757          self.geometry("+%d+%d" % (parent.winfo_rootx()+50, parent.winfo_rooty()+50))
     758
     759          self.initial_focus.focus_set()
     760
     761          self.wait_window(self)
     762
     763 -    def body(self, master):
     764          """
     765          Create dialog body. Return widget that should have initial focus.
     766          """
     767
     768          settingsFrame = LabelFrame(master, text = 'Settings', bd = 2, relief = GROOVE)
     769          settingsFrame.grid(row = 0, column = 0, sticky = EW, padx = 3, pady = 3)
     770          settingsFrame.grid_columnconfigure(0, weight = 1)
     771
     772          # The combo widget to browse the PDB input file.
     773          self.pdbFileBrowser = ComboFileBrowser(settingsFrame,\
     774                                                 frameLabel = "PDB input file",\
     775                                                 tagName = 'namd_converter_pdb_input_file',\
     776                                                 contents = '',\
     777                                                 filetypes = [('PDB', '*.pdb'), ('All files', '*')],\
     778                                                 save = False)
     779          self.pdbFileBrowser.grid(row = 0, column = 0, padx = 2, pady = 2, sticky = EW)
     780          self.pdbFileBrowser.grid_columnconfigure(0, weight = 1)
     781
     782          # The combo widget to browse the DCD input file.
     783          self.dcdFileBrowser = ComboFileBrowser(settingsFrame,\
     784                                                 frameLabel = "DCD input file",\
     785                                                 tagName = 'namd_converter_dcd_input_file',\
     786                                                 contents = '',\
     787                                                 filetypes = [('DCD input file', '*.dcd'), ('All files', '*')],\
     788                                                 save = False)
     789          self.dcdFileBrowser.grid(row = 1, column = 0, padx = 2, pady = 2, sticky = EW)
     790          self.dcdFileBrowser.grid_columnconfigure(0, weight = 1)
     791          self.dcdFileBrowser.entry.variable.trace('w', self.suggestOutputFilename)
     792
     793          # The combo widget to browse the XST input file.
     794          self.xstFileBrowser = ComboFileBrowser(settingsFrame,\
     795                                                 frameLabel = "XST input file",\
     796                                                 tagName = 'namd_converter_xst_input_file',\
     797                                                 contents = '',\
     798                                                 filetypes = [('XST input file', '*.xst'), ('All files', '*')],\
     799                                                 save = False)
     800          self.xstFileBrowser.grid(row = 2, column = 0, padx = 2, pady = 2, sticky = EW)
     801          self.xstFileBrowser.grid_columnconfigure(0, weight = 1)
     802
     803          # The combo widget to browse the MMTK output file.
     804          self.outputFileBrowser = ComboFileBrowser(settingsFrame,\
     805                                                    frameLabel = "MMTK NetCDF output file",\
     806                                                    tagName = 'namd_converter_mmtk_netcdf_output_file',\
     807                                                    contents = '',\
     808                                                    save = True)
     809          self.outputFileBrowser.grid(row = 3, column = 0, padx = 2, pady = 2, sticky = EW)
     810          self.outputFileBrowser.grid_columnconfigure(0, weight = 1)
     811
     812          return None
     813
     814 -    def buttonbox(self):
     815          """
     816          Add standard button box.
     817          """
     818
     819          # The frame that contains the 'Cancel' and 'OK' buttons.
     820          box = LabelFrame(self, text = 'Actions', bd = 2, relief = GROOVE)
     821          box.grid(row = 1, column = 0, sticky = EW, padx = 3, pady = 3)
     822          box.grid_columnconfigure(0, weight = 1)
     823
     824          w = Button(box, text = "Cancel", width=10, command = self.cancel)
     825          w.grid(row = 0, column = 0, sticky = E)
     826          w = Button(box, text = "OK", width=10, command = self.ok, default=ACTIVE)
     827          w.grid(row = 0, column = 1, sticky = E)
     828
     829          self.bind("<Return>", self.ok)
     830          self.bind("<Escape>", self.cancel)
     831
     832      # Standard button semantics.
     833 -    def ok(self, event = None):
     834
     835          if not self.validate():
     836              self.initial_focus.focus_set()
     837              return
     838
     839          self.update_idletasks()
     840
     841          self.apply()
     842
     843 -    def cancel(self, event=None):
     844
     845          # Put focus back to the parent window
     846          self.parent.focus_set()
     847          self.destroy()
     848
     849      # Command hooks
     850 -    def validate(self):
     851
     852          self.pdbFile = self.pdbFileBrowser.getValue()
     853          # A PDB input file must have been set.
     854          if not self.pdbFile:
     855              raise Error('Please enter a PDB input file.')
     856
     857          # A DCD input file must have been set.
     858          self.dcdFile = self.dcdFileBrowser.getValue()
     859          if not self.dcdFile:
     860              raise Error('Please enter a DCD input file.')
     861
     862          self.xstFile = self.xstFileBrowser.getValue()
     863
     864          # The MMTK output file must have been set.
     865          self.outputFile = self.outputFileBrowser.getValue()
     866          if not self.outputFile:
     867              raise Error('Please enter a MMTK NetCDF output file.')
     868
     869          if self.outputFile[-3:] != '.nc':
     870              self.outputFile += '.nc'
     871
     872          return True
     873
     874 -    def apply(self):
     875          """
     876          This method starts the conversion.
     877          """
     878
     879          converter = NAMDConverter(self.pdbFile, self.dcdFile, self.xstFile, self.outputFile)
     880          LogMessage('info', 'Conversion successful', ['gui'])
     881
     882
     883 -    def suggestOutputFilename(self, *dummy):
     884          """
     885          This method will propose a name for the output file based on the name of the loaded file.
     886          """
     887
     888          if self.dcdFileBrowser.getValue():
     889              self.outputFileBrowser.setValue(os.path.splitext(self.dcdFileBrowser.getValue())[0] + '.nc')
     890
     891 -class VASPConverterDialog(Toplevel):
     892      """Sets up a dialog used for the conversion from a VASP trajectory to a MMTK NetCDF trajectory.
     893
     894      @note: the conversion requires the VASP CONTCAR or POSCAR and XDATCAR files.
     895      """
     896
     897 -    def __init__(self, parent):
     898          """
     899          The constructor.
     900          """
     901
     902          Toplevel.__init__(self, parent)
     903          self.transient(parent)
     904
     905          self.title('VASP --> MMTK NetCDF converter')
     906
     907          self.parent = parent
     908
     909          body = Frame(self)
     910          self.initial_focus = self.body(body)
     911          body.grid(row = 0, column = 0, sticky = EW)
     912
     913          self.buttonbox()
     914
     915          self.grab_set()
     916
     917          if not self.initial_focus:
     918              self.initial_focus = self
     919
     920          self.protocol("WM_DELETE_WINDOW", self.cancel)
     921
     922          self.resizable(width = NO, height = NO)
     923
     924          self.geometry("+%d+%d" % (parent.winfo_rootx()+50, parent.winfo_rooty()+50))
     925
     926          self.initial_focus.focus_set()
     927
     928          self.wait_window(self)
     929
     930 -    def body(self, master):
     931          """
     932          Create dialog body. Return widget that should have initial focus.
     933          """
     934
     935          settingsFrame = LabelFrame(master, text = 'Settings', bd = 2, relief = GROOVE)
     936          settingsFrame.grid(row = 0, column = 0, sticky = EW, padx = 3, pady = 3)
     937          settingsFrame.grid_columnconfigure(0, weight = 1)
     938
     939          # The combo widget to browse the VASP CONTCAR file.
     940          self.contcarFileBrowser = ComboFileBrowser(settingsFrame,\
     941                                                     frameLabel = "POSCAR/CONTCAR input file",\
     942                                                     tagName = 'vasp_converter_poscar_contcar_input_file',\
     943                                                     contents = '',\
     944                                                     filetypes = [('POSCAR files', 'POSCAR*'), ('CONTCAR files', 'CONTCAR*'),('All files', '*')],\
     945                                                     save = False)
     946          self.contcarFileBrowser.grid(row = 0, column = 0, padx = 2, pady = 2, sticky = EW)
     947          self.contcarFileBrowser.grid_columnconfigure(0, weight = 1)
     948
     949          # The combo widget to browse the VASP XDATCAR file.
     950          self.xdatcarFileBrowser = ComboFileBrowser(settingsFrame,\
     951                                                     frameLabel = "XDATCAR input file",\
     952                                                     tagName = 'vasp_converter_xdatcar_input_file',\
     953                                                     contents = '',\
     954                                                     filetypes = [('XDATCAR files', 'XDATCAR*'),('All files', '*')],\
     955                                                     save = False)
     956          self.xdatcarFileBrowser.grid(row = 1, column = 0, padx = 2, pady = 2, sticky = EW)
     957          self.xdatcarFileBrowser.grid_columnconfigure(0, weight = 1)
     958
     959          # The combo widget to the atomic contents of the system..
     960          self.atomContentsEntry = ComboStringEntry(settingsFrame,\
     961                                                    frameLabel = "Atom contents",\
     962                                                    tagName = 'vasp_converter_atom_contents',\
     963                                                    contents = '')
     964          self.atomContentsEntry.grid(row = 2, column = 0, padx = 2, pady = 2, sticky = EW)
     965          self.atomContentsEntry.grid_columnconfigure(0, weight = 1)
     966
     967          # The combo widget to browse the MMTK output file.
     968          self.outputFileBrowser = ComboFileBrowser(settingsFrame,\
     969                                                    frameLabel = "MMTK NetCDF output file",\
     970                                                    tagName = 'vasp_converter_mmtk_netcdf_output_file',\
     971                                                    contents = '',\
     972                                                    save = True)
     973          self.outputFileBrowser.grid(row = 3, column = 0, padx = 2, pady = 2, sticky = EW)
     974          self.outputFileBrowser.grid_columnconfigure(0, weight = 1)
     975
     976          return None
     977
     978 -    def buttonbox(self):
     979          """
     980          Add standard button box.
     981          """
     982
     983          # The frame that contains the 'Cancel' and 'OK' buttons.
     984          box = LabelFrame(self, text = 'Actions', bd = 2, relief = GROOVE)
     985          box.grid(row = 1, column = 0, sticky = EW, padx = 3, pady = 3)
     986          box.grid_columnconfigure(0, weight = 1)
     987
     988          w = Button(box, text = "Cancel", width=10, command = self.cancel)
     989          w.grid(row = 0, column = 0, sticky = E)
     990          w = Button(box, text = "OK", width=10, command = self.ok, default=ACTIVE)
     991          w.grid(row = 0, column = 1, sticky = E)
     992
     993          self.bind("<Return>", self.ok)
     994          self.bind("<Escape>", self.cancel)
     995
     996      # Standard button semantics.
     997 -    def ok(self, event = None):
     998
     999          if not self.validate():
    1000              self.initial_focus.focus_set()
    1001              return
    1002
    1003          self.update_idletasks()
    1004
    1005          self.apply()
    1006
    1007 -    def cancel(self, event=None):
    1008
    1009          # Put focus back to the parent window
    1010          self.parent.focus_set()
    1011          self.destroy()
    1012
    1013      # Command hooks
    1014 -    def validate(self):
    1015
    1016          # A CONTCAR input file must have been set.
    1017          self.contcarFile = self.contcarFileBrowser.getValue()
    1018          if not self.contcarFile:
    1019              raise Error('Please enter a CONTCAR or POSCAR input file.')
    1020
    1021          # A XDATCAR input file must have been set.
    1022          self.xdatcarFile = self.xdatcarFileBrowser.getValue()
    1023          if not self.xdatcarFile:
    1024              raise Error('Please enter a XDATCAR input file.')
    1025
    1026          self.atomContents = self.atomContentsEntry.getValue()
    1027          if not self.atomContents:
    1028              raise Error('You must provide the atomic contents as it appears in the CONTCAR file.')
    1029
    1030          try:
    1031              self.atomContents = re.split('[;,\s]+',self.atomContents)
    1032          except:
    1033              try:
    1034                  self.atomContents = [v.strip() for v in self.atomContents.split()]
    1035              except:
    1036                  raise Error('Wrong format for atomic contents declaration.')
    1037
    1038          # The MMTK output file must have been set.
    1039          self.outputFile = self.outputFileBrowser.getValue()
    1040          if not self.outputFile:
    1041              raise Error('Please enter a MMTK NetCDF output file.')
    1042
    1043          if self.outputFile[-3:] != '.nc':
    1044              self.outputFile += '.nc'
    1045
    1046          return True
    1047
    1048 -    def apply(self):
    1049
    1050          converter = VASPConverter(self.contcarFile, self.xdatcarFile, self.outputFile, self.atomContents)
    1051          LogMessage('info', 'Conversion successful', ['gui'])
    1052