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

# Source Code for Module nMOLDYN.GUI.AnalysisBenchmarkDialog

      1  """This modules implements I{Help-->nMOLDYN benchmark} dialog.
      2
      3  Classes:
      4      * AnalysisBenchmarkDialog: creates I{Help-->nMOLDYN benchmark} dialog used to run the stability tests
      5        between nMOLDYN v2.2.5 and the current version of nMOLDYN.
      6  """
      7
      8  # The python distribution modules
      9  import copy
     10  import os
     11  import re
     12
     13  # The Tcl/Tk modules
     14  from Tkinter import *
     15  from tkMessageBox import showinfo
     16
     17  # The nMOLDYN modules
     18  import nMOLDYN
     19  from nMOLDYN.Core.Error import Error
     20  from nMOLDYN.GUI.Widgets import *
     21  from nMOLDYN.Tests.StabilityTests import *
     22
     23 -class AnalysisBenchmarkDialog(Toplevel):
     24      """Builds the dialog for nMOLDYN analysis benchmarks.
     25
     26      These benchmarks will guarantee the stability of the current version with a reference one that is the
     27      version 2.2.5 the last official release of nMOLDYN.
     28
     29      @note: these benchmarks should be performed every time the code source of nMOLDYN has been touched for
     30          any reason.
     31      """
     32
     33 -    def __init__(self, parent, title = None):
     34          """The constructor.
     35
     36          @param parent: the parent widget.
     37
     38          @param title: a string specifying the title of the dialog.
     39          @type title: string
     40          """
     41
     42          Toplevel.__init__(self, parent)
     43          self.transient(parent)
     44
     45          if title:
     46              self.title(title)
     47
     48          self.parent = parent
     49
     50          # List of the test sets available.
     51          self.availableTestSets = sorted(availableTests + ['ALL'])
     52
     53          # This is the tag counter to allow the user to click on each failing test id to get more informations.
     54          self.tagCounter = 1
     55
     56          body = Frame(self)
     57          self.initial_focus = self.body(body)
     58          body.grid(row = 0, column = 0, sticky = EW)
     59
     60          self.buttonbox()
     61
     62          self.grab_set()
     63
     64          if not self.initial_focus:
     65              self.initial_focus = self
     66
     67          self.protocol("WM_DELETE_WINDOW", self.cancel)
     68
     69          self.resizable(width = NO, height = NO)
     70
     71          self.geometry("+%d+%d" % (parent.winfo_rootx()+50, parent.winfo_rooty()+50))
     72
     73          self.initial_focus.focus_set()
     74
     75          self.wait_window(self)
     76
     77 -    def body(self, master):
     78          """Creates dialog body. Returns widget that should have initial focus.
     79          """
     80
     81          settingsFrame = LabelFrame(master, text = 'Settings', bd = 2, relief = GROOVE)
     82          settingsFrame.grid(row = 0, column = 0, sticky = EW, padx = 3, pady = 3)
     83          settingsFrame.grid_columnconfigure(0, weight = 1)
     84          settingsFrame.grid_rowconfigure(0, weight = 1)
     85
     86          # The combo listbox that will contain the list of the available tests.
     87          self.testListLb = ComboListbox(settingsFrame,'Available tests',[])
     88          self.testListLb.grid(row = 0, column = 0, padx = 2, pady = 2, sticky = 'NS')
     89          self.testListLb.grid_rowconfigure(0, weight = 1)
     90          self.testListLb.lb.config({'selectmode' : MULTIPLE})
     91          self.testListLb.lb.bind('<Button-3>',self.infoAboutTest)
     92
     93          # The available test sets are inserted in the listboxes.
     94          for testSet in self.availableTestSets:
     95              self.testListLb.lb.insert(END, testSet)
     96
     97          self.testResultsText = ComboText(settingsFrame,\
     98                                           frameLabel = 'Results for the selected benchmark(s)')
     99          self.testResultsText.grid(row = 0, column = 1, padx = 2, pady = 2, sticky = 'NS')
    100          self.testResultsText.config({'relief' : SUNKEN, 'bd' : 2})
    101          self.testResultsText.grid_rowconfigure(0, weight = 1)
    102          self.testResultsText.text.config({'wrap' : WORD})
    103
    104          self.testResultsText.text.tag_config('12', foreground = 'black', font = ('Courier','12'))
    105          self.testResultsText.text.tag_config('g12', foreground = 'green', font = ('Courier','12'))
    106          self.testResultsText.text.tag_config('12B', foreground = 'black', font = ('Courier','12','bold'))
    107
    108          return None
    109
    110 -    def buttonbox(self):
    111          """Adds standard button box."""
    112
    113          # The frame that contains the 'Cancel' and 'OK' buttons.
    114          box = LabelFrame(self, text = 'Actions', bd = 2, relief = GROOVE)
    115          box.grid(row = 1, column = 0, sticky = EW, padx = 3, pady = 3)
    116          box.grid_columnconfigure(0, weight = 1)
    117
    118          w = Button(box, text = "Cancel", width=10, command = self.cancel)
    119          w.grid(row = 0, column = 0, sticky = E)
    120          w = Button(box, text = "Clear", width=10, command = self.clearResults)
    121          w.grid(row = 0, column = 1, sticky = E)
    122          w = Button(box, text = "OK", width=10, command = self.ok, default=ACTIVE)
    123          w.grid(row = 0, column = 2, sticky = E)
    124
    125          self.bind("<Return>", self.ok)
    126          self.bind("<Escape>", self.cancel)
    127
    128      # Standard button semantics.
    129 -    def ok(self, event = None):
    130          if not self.validate():
    131              self.initial_focus.focus_set()
    132              return
    133
    134          self.update_idletasks()
    135
    136          self.apply()
    137
    138 -    def cancel(self, event = None):
    139
    140          # Put focus back to the parent window
    141          self.parent.focus_set()
    142          self.destroy()
    143
    144      # Command hooks
    145 -    def validate(self):
    146
    147          # This is the list of the test sets selected by the |checkSimulationsDialog| dialog.
    148          self.selectedTestSets = [self.testListLb.lb.get(int(testSet)) for testSet in self.testListLb.lb.curselection()]
    149
    150          if not self.selectedTestSets:
    151              raise Error('No Test selected.')
    152
    153          return True
    154
    155 -    def apply(self):
    156
    157          # The tests results is switched to NORMAL state. Some informations can be written in.
    158          self.testResultsText.text.config(state = NORMAL)
    159
    160          try:
    161
    162              if 'ALL' in self.selectedTestSets:
    163                  self.selectedTestSets = availableTests
    164
    165              comp = 1
    166              # Loop over each selected set of test (e.g. MSD, AT ...).
    167              for test in self.selectedTestSets:
    168
    169                  t = eval(test+'Tests()')
    170                  t.run()
    171
    172                  self.testResultsText.insert(END, t.summary)
    173
    174                  self.testResultsText.tag('#', 'g12')
    175
    176                  [self.testResultsText.tag(p, '12B') for p in re.findall('Summary.*\n', t.summary)]
    177
    178                  [self.testResultsText.tag(p, '12B') for p in re.findall('Number of.*\n', t.summary)]
    179
    180                  [self.testResultsText.tag(p, 'success%s' % comp) for p in re.findall('Successful tests:.*\n', t.summary)]
    181
    182                  [self.testResultsText.tag(p, 'failure%s' % comp) for p in re.findall('Failing tests:.*\n', t.summary)]
    183
    184                  self.testResultsText.text.tag_config('success%s' % comp, foreground = 'blue', font = ('Courier','10','bold'))
    185
    186                  self.testResultsText.text.tag_config('failure%s' % comp, foreground = 'red', font = ('Courier','10','bold'))
    187
    188                  [self.testResultsText.tag(p, '12B') for p in re.findall('Percentage.*\n', t.summary)]
    189
    190                  [self.testResultsText.tag(p, '12B') for p in re.findall('Time to run.*\n', t.summary)]
    191
    192                  # This binding displays the contents of the successful tests when the user click on it with the mouse left button.
    193                  self.testResultsText.text.tag_bind('success%s' % comp,\
    194                                                     '<Button-1>',\
    195                                                     lambda event, p = t.successes : self.displayTest(event, p))
    196
    197                  # This binding changes the mouse icon to a question when the user passes over a failing test.
    198                  self.testResultsText.text.tag_bind('success%s' % comp, '<Motion>', lambda event : changeMouseCursor(event,'question_arrow'), '+')
    199
    200                  # This binding returns the mouse icon to its default value when the user passes out a failing test.
    201                  self.testResultsText.text.tag_bind('success%s' % comp, '<Leave>', lambda event : changeMouseCursor(event,'arrow'), '+')
    202
    203                  # Some tag bindings for the failing tests.
    204                  # This binding displays the contents of the failing tests when the user click on it with the mouse left button.
    205                  self.testResultsText.text.tag_bind('failure%s' % comp,\
    206                                                     '<Button-1>',\
    207                                                     lambda event, p = t.failures : self.displayTest(event, p))
    208
    209                  # This binding changes the mouse icon to a question when the user passes over a failing test.
    210                  self.testResultsText.text.tag_bind('failure%s' % comp,'<Motion>', lambda event : changeMouseCursor(event,'question_arrow'), '+')
    211
    212                  # This binding returns the mouse icon to its default value when the user passes out a failing test.
    213                  self.testResultsText.text.tag_bind('failure%s' % comp,'<Leave>', lambda event : changeMouseCursor(event,'arrow'), '+')
    214
    215                  comp += 1
    216
    217          except:
    218              raise Error('Error when running test benchmark.')
    219
    220          finally:
    221              # The tests results is switched to DISABLED state. Nothing can be written in.
    222              self.testResultsText.text.config(state = DISABLED)
    223
    224 -    def infoAboutTest(self, event):
    225          """This callback displays basic information about a selected test before running it by clicking on
    226          the right mouse button.
    227          """
    228
    229          selectedInd = self.testListLb.lb.nearest(event.y)
    230          selectedTest = self.testListLb.lb.get(selectedInd)
    231          t = eval(selectedTest+'Tests()')
    232          showinfo('Information',t.info)
    233          del(t)
    234
    235 -    def displayTest(self, event, parameters):
    236          """Displays in a text widget the nMOLDYN v2.2.5 input file of a selected failing test.
    237
    238          Arguments:
    239              - event: the mouse left button click Tkinter event that will trigger the opening of the window.
    240              - testSet: the test set to which belong the failing test.
    241          """
    242
    243          # The text index of the event.
    244          first = event.widget.index('@%d,%d' % (event.x, event.y))
    245          c = self.testResultsText.text.get(first)
    246
    247          try:
    248              i = int(c)
    249
    250              while c not in  [' ','\n']:
    251                  first = first + '-1c'
    252                  c = self.testResultsText.text.get(first)
    253                  if c == '\n':
    254                      break
    255
    256              first = first + '+1c'
    257              c = self.testResultsText.text.get(first)
    258
    259              last = first
    260              while c not in  [' ','\n']:
    261                  last = last + '+1c'
    262                  c = self.testResultsText.text.get(last)
    263                  if c == '\n':
    264                      break
    265
    266              selectedTest =  int(self.testResultsText.text.get(first, last).strip())
    267
    268          except:
    269              return
    270
    271          # Creation of a toplevel window that will display the reference and current
    272          # nMOLDYN input files of the failing test.
    273          self.detailsDialog = Toplevel(self)
    274          self.detailsDialog.transient(self.parent)
    275
    276          # The text combo widget that will display the contents of the reference version of the input file.
    277          referenceContents = ComboText(self.detailsDialog,\
    278                                        frameLabel = 'nMOLDYN reference version parameters')
    279          referenceContents.grid(row = 0, column = 0)
    280
    281          referenceContents.config({'width' : 100,\
    282                                    'height' : 20,\
    283                                    'relief' : SUNKEN,\
    284                                    'bd' : 2})
    285          referenceContents.text.config({'wrap' : WORD,\
    286                                         'font' : ('Courier', 10, 'normal'),\
    287                                         'width' : 80,\
    288                                         'height' : 10,\
    289                                         'bg' : 'salmon'})
    290
    291          for k, v in parameters[selectedTest]['REF'].items():
    292              referenceContents.insert(END, '%s = %s\n' % (repr(k), repr(v)))
    293          referenceContents.text.config(state = DISABLED)
    294
    295          # The text combo widget that will display the contents of the current version of the input file.
    296          currentContents = ComboText(self.detailsDialog,\
    297                                      frameLabel = 'nMOLDYN version %s parameters' % nMOLDYN.__version__)
    298          currentContents.grid(row = 1, column = 0)
    299
    300          currentContents.config({'width' : 100,\
    301                                  'height' : 20,\
    302                                  'relief' : SUNKEN,\
    303                                  'bd' : 2})
    304          currentContents.text.config({'wrap' : WORD,\
    305                                       'width' : 80,\
    306                                       'height' : 10,\
    307                                       'bg' : '#ffff80',\
    308                                       'font' : ('Arial', 10, 'normal')})
    309
    310          for k, v in parameters[selectedTest]['NEW'].items():
    311              currentContents.insert(END, '%s = %s\n' % (repr(k), repr(v)))
    312          currentContents.text.config(state = DISABLED)
    313
    314          self.detailsDialog.grab_set()
    315
    316          self.detailsDialog.bind("<Escape>", self.cancel1)
    317          self.detailsDialog.protocol("WM_DELETE_WINDOW", self.cancel1)
    318
    319          self.detailsDialog.resizable(width = NO, height = NO)
    320
    321          self.detailsDialog.geometry("+%d+%d" % (self.winfo_rootx()+50, self.winfo_rooty()+50))
    322
    323          self.detailsDialog.title('Details about the test %s.' % selectedTest)
    324
    325          self.detailsDialog.focus_set()
    326
    327          self.detailsDialog.wait_window(self.detailsDialog)
    328
    329 -    def cancel1(self, event = None):
    330
    331          # Put focus back to the parent window
    332          self.grab_set()
    333
    334          # Put focus back to the parent window
    335          self.focus_set()
    336
    337          self.detailsDialog.destroy()
    338
    339 -    def clearResults(self):
    340          """
    341          This methods clears up all the results about the evaluated test sets.
    342          """
    343
    344          self.testResultsText.cleanup()
    345