Package nMOLDYN :: Package Tests :: Module StabilityTests |
[hide private]
[frames] | no frames]

# Source Code for Module nMOLDYN.Tests.StabilityTests

      1  """
      2  Test cases for stability of the current version of nMOLDYN versus nMoldyn v2.1.0, the last stable release
      3  of nMoldyn.
      4  Each test case is made of a benchmark of $n small tests corresponding to various input values.
      5  For all of these small tests, the output of the tests with the reference version of nMOLDYN are
      6  stored into files with the name:
      7      * $PREFIX$TESTID_Reference.nc where $PREFIX is the prefix for the analysis to test and $TESTID the test number.
      8        When running a stability test, the output of the current version are created on the fly with the name:
      9      * $PREFIX$TESTID_Current.nc where $PREFIX is the prefix for the analysis to test and $TESTID the test number.
     10        and each of the numeric variables of the reference and current NetCDF output file are checked to be equal within
     11        a tolerance set to 1E-06.
     12  """
     13
     14  # The python distribution modules
     15  import os
     16  import sys
     17  from timeit import default_timer
     18  import unittest
     19
     20  # The ScientificPython modules
     21  from Scientific import N
     22  from Scientific.IO.NetCDF import NetCDFFile
     23
     24  # The nMOLDYN modules
     25  from nMOLDYN.Analysis.Template import *
     26  from nMOLDYN.Core.Logger import LogMessage
     27
     28  nmoldyn_tests_path = os.path.abspath(os.path.split(__file__)[0])
     29
     30  availableTests = ['ARA','AVACF','DCSF','DISF','DISFG','EISF','MSD','VACF']
     31
     32 -class AnalysisTest(unittest.TestCase):
     33
     34 -    def setUp(self):
     35          """Overides the TestCase.setUp method. Initialization of the test variables.
     36          """
     37
     38          self.testPath = os.path.join(nmoldyn_tests_path,self.shortName)
     39
     40          self.details = ''
     41
     42          self.failures = {}
     43
     44          self.successes = {}
     45
     46 -    def runTest(self):
     47
     48          # The time at whic the test starts.
     49          self.start = default_timer()
     50
     51          test = []
     52
     53          testContents = open(os.path.join(self.testPath, 'TestsContents.py'),'r')
     54          exec testContents
     55          testContents.close()
     56
     57          # Loop over the tests available for the selected test.
     58          for testNumber in range(len(test)):
     59
     60              LogMessage('info', 'ANALYSIS: %s --- TEST No: %s' % (self.longName, testNumber+1),['console', 'file'])
     61
     62              self.details += '\nTest %s\n' % (testNumber + 1)
     63
     64              refParameters = {}
     65              for key, val in template['REF'].items() + test[testNumber]['REF'].items():
     66                  refParameters[key] = val
     67
     68              self.testParameters = {}
     69              for key, val in template['NEW'].items() + test[testNumber]['NEW'].items():
     70                  if key.lower() == 'analysis':
     71                      continue
     72                  self.testParameters[key] = val
     73
     74              analysis = eval(template['NEW']['analysis'])
     75              analysis.runAnalysis()
     76
     77              for refVersionPrefix, refVersionVar, newVersionPrefix, newVersionVar in self.variables:
     78                  refVersionFile =  os.path.join(self.testPath, refVersionPrefix + str(testNumber+1) + '_Reference.nc')
     79                  newVersionFile = template['NEW'][newVersionPrefix.lower()]
     80
     81                  # Opens the NetCDF files coming from nMOLDYN reference and current versions.
     82                  ref = NetCDFFile(refVersionFile, 'r')
     83                  new = NetCDFFile(newVersionFile, 'r')
     84                  try:
     85                      if ref.variables[refVersionVar].typecode() in [N.Float, N.Float0, N.Int, N.Int32,N.Character]:
     86                          refVersionVals = ref.variables[refVersionVar].getValue()
     87                          newVersionVals = new.variables[newVersionVar].getValue()
     88                          errorMax = max(abs(N.ravel(refVersionVals - newVersionVals)))
     89                          self.details += '\tError for %s variable = %e\n' % (newVersionVar, errorMax)
     90                          self.assertAlmostEqual(errorMax, 0.0, 6)
     91
     92                      if not self.failures.has_key(testNumber+1):
     93                          self.successes[testNumber+1] = {'REF' : refParameters, 'NEW' : self.testParameters}
     94
     95                  except:
     96
     97                      if self.successes.has_key(testNumber+1):
     98                          del self.successes[testNumber+1]
     99                      self.failures[testNumber+1] = {'REF' : refParameters, 'NEW' : self.testParameters}
    100
    101                  finally:
    102
    103                      ref.close()
    104                      new.close()
    105
    106          # The time at which the test ends.
    107          self.end = default_timer()
    108
    109 -    def tearDown(self):
    110          """Overides the TestCase.tearDown method. Finalization of the test.
    111          """
    112
    113          # The number of successful tests.
    114          nSuccesses = len(self.successes.keys())
    115
    116          # The number of successful tests.
    117          nFailures = len(self.failures.keys())
    118
    119          # The number of tests performed.
    120          nTests = nSuccesses + nFailures
    121
    122          # The percentages of successful tests.
    123          rate = 100.0*(float(nSuccesses)/float(nTests))
    124
    125          # The summary of the performed tests.
    126          self.summary = '\n'
    127          self.summary += '#########################################################'
    128          self.summary += '\nSummary of tests run for %s analysis\n' % self.longName
    129          self.summary += '\nNumber of tests run: %3d' % nTests
    130          self.summary += '\n\nNumber of successes: %3d' % nSuccesses
    131          self.summary += '\nSuccessful tests: '
    132          if not self.successes:
    133              self.summary += ' None'
    134          else:
    135              for t in self.successes:
    136                  self.summary += '%s   ' % t
    137
    138          self.summary += '\n\nNumber of failures: %3d' % nFailures
    139          self.summary += '\nFailing tests:'
    140          if not self.failures:
    141              self.summary += ' -'
    142          else:
    143              for t in self.failures:
    144                  self.summary += '      '
    145                  self.summary += '%s' % t
    146          self.summary += '\n\nPercentage of success: %4.1f %%' % rate
    147          self.summary += '\n\nTime to run all the tests: %5d seconds' % int(self.end - self.start)
    148          self.summary += '\n\nDetails:'
    149          self.summary += self.details
    150
    151 -class MSDTests(AnalysisTest):
    152      # The test shortname.
    153      shortName = 'MSD'
    154
    155      # The test longname.
    156      longName = 'Mean-Square Displacement'
    157
    158      # The number of test.
    159      numberOfTests = 14
    160
    161      info = '%d tests about %s analysis.' % (numberOfTests,longName)
    162
    163      # The nested list of the correspondance between the old and new names of the variables to compare between the old
    164      # and new version of nMOLDYN. For each list,
    165      # element 0 is the prefix of the old version netcdf filename.
    166      # element 1 is the name of the variable to test within the old version netcdf filename.
    167      # element 2 is the prefix of the new version netcdf filename.
    168      # element 3 is the name of the variable to test within the new version netcdf filename.
    169      variables  = [['MSD','column1','MSD','time'], ['MSD','column2','MSD','msd']]
    170
    171 -    def runTest(self):
    172          AnalysisTest.runTest(self)
    173
    174 -class VACFTests(AnalysisTest):
    175      # The test shortname.
    176      shortName = 'VACF'
    177
    178      # The test longname.
    179      longName = 'Velocity AutoCorrelation Function'
    180
    181      # The number of test.
    182      numberOfTests = 14
    183
    184      info = '%d tests about %s analysis.' % (numberOfTests,longName)
    185
    186      # The nested list of the correspondance between the old and new names of the variables to compare between the old
    187      # and new version of nMOLDYN. For each list,
    188      # element 0 is the prefix of the old version netcdf filename.
    189      # element 1 is the name of the variable to test within the old version netcdf filename.
    190      # element 2 is the prefix of the new version netcdf filename.
    191      # element 3 is the name of the variable to test within the new version netcdf filename.
    192      variables = [['VACF','column1','VACF','time'], ['VACF','column2','VACF','vacf']]
    193
    194 -    def runTest(self):
    195          AnalysisTest.runTest(self)
    196
    197 -class ARATests(AnalysisTest):
    198      # The test shortname.
    199      shortName = 'ARA'
    200
    201      # The test longname.
    202      longName = 'Auto-Regressive Analysis'
    203
    204      # The number of test.
    205      numberOfTests = 12
    206
    207      info = '%d tests about %s analysis.' % (numberOfTests,longName)
    208
    209      # The nested list of the correspondance between the old and new names of the variables to compare between the old
    210      # and new version of nMOLDYN. For each list,
    211      # element 0 is the prefix of the old version netcdf filename.
    212      # element 1 is the name of the variable to test within the old version netcdf filename.
    213      # element 2 is the prefix of the new version netcdf filename.
    214      # element 3 is the name of the variable to test within the new version netcdf filename.
    215      variables  = [['MSD','column1','ARA','time_msd'], ['MSD','column2','ARA','msd'],\
    216                    ['VACF','column1','ARA','time_vacf'], ['VACF','column2','ARA','vacf'],\
    217                    ['DOS','column1','ARA','frequency'], ['DOS','column2','ARA','dos'],\
    218                    ['MEMORY','column1','ARA','time_memory'], ['MEMORY','column2','ARA','memory_function']]
    219
    220 -    def runTest(self):
    221          AnalysisTest.runTest(self)
    222
    223 -class AVACFTests(AnalysisTest):
    224      # The test shortname.
    225      shortName = 'AVACF'
    226
    227      # The test longname.
    228      longName = 'Angular Velocity AutoCorrelation Function'
    229
    230      # The number of test.
    231      numberOfTests = 14
    232
    233      info = '%d tests about %s analysis.' % (numberOfTests,longName)
    234
    235      # The nested list of the correspondance between the old and new names of the variables to compare between the old
    236      # and new version of nMOLDYN. For each list,
    237      # element 0 is the prefix of the old version netcdf filename.
    238      # element 1 is the name of the variable to test within the old version netcdf filename.
    239      # element 2 is the prefix of the new version netcdf filename.
    240      # element 3 is the name of the variable to test within the new version netcdf filename.
    241      variables = [['AVACF','column1','AVACF','time'], ['AVACF','column2','AVACF','avacf-total']]
    242
    243 -    def runTest(self):
    244          AnalysisTest.runTest(self)
    245
    246 -class DOSTests(AnalysisTest):
    247      # The test shortname.
    248      shortName = 'DOS'
    249
    250      # The test longname.
    251      longName = 'Density Of States'
    252
    253      # The number of test.
    254      numberOfTests = 14
    255
    256      info = '%d tests about %s analysis.' % (numberOfTests,longName)
    257
    258      # The nested list of the correspondance between the old and new names of the variables to compare between the old
    259      # and new version of nMOLDYN. For each list,
    260      # element 0 is the prefix of the old version netcdf filename.
    261      # element 1 is the name of the variable to test within the old version netcdf filename.
    262      # element 2 is the prefix of the new version netcdf filename.
    263      # element 3 is the name of the variable to test within the new version netcdf filename.    variables = [['AVACF','column1','AVACF','time'], ['AVACF','column2','AVACF','avacf-total']]
    264      variables  = [['DOS','column1','DOS','frequency'], ['DOS','column2','DOS','dos']]
    265
    266 -    def runTest(self):
    267          AnalysisTest.runTest(self)
    268
    269 -class DCSFTests(AnalysisTest):
    270      # The test shortname.
    271      shortName = 'DCSF'
    272
    273      # The test longname.
    274      longName = 'Dynamic Coherent Structure Factor'
    275
    276      # The number of test.
    277      numberOfTests = 12
    278
    279      info = '%d tests about %s analysis.' % (numberOfTests,longName)
    280
    281      # The nested list of the correspondance between the old and new names of the variables to compare between the old
    282      # and new version of nMOLDYN. For each list,
    283      # element 0 is the prefix of the old version netcdf filename.
    284      # element 1 is the name of the variable to test within the old version netcdf filename.
    285      # element 2 is the prefix of the new version netcdf filename.
    286      # element 3 is the name of the variable to test within the new version netcdf filename.    variables = [['AVACF','column1','AVACF','time'], ['AVACF','column2','AVACF','avacf-total']]
    287      variables  = [['Fqt','q','DCSF','q'], ['Fqt','time','DCSF','time'], ['Fqt','sf','DCSF','Fqt-total'],\
    288                    ['Sqw','q','DCSF','q'], ['Sqw','frequency','DCSF','frequency'],['Sqw','dsf','DCSF','Sqw-total']]
    289
    290 -    def runTest(self):
    291          AnalysisTest.runTest(self)
    292
    293 -class DISFTests(AnalysisTest):
    294      # The test shortname.
    295      shortName = 'DISF'
    296
    297      # The test longname.
    298      longName = 'Dynamic Incoherent Structure Factor'
    299
    300      # The number of test.
    301      numberOfTests = 12
    302
    303      info = '%d tests about %s analysis.' % (numberOfTests,longName)
    304      # The nested list of the correspondance between the old and new names of the variables to compare between the old
    305      # and new version of nMOLDYN. For each list,
    306      # element 0 is the prefix of the old version netcdf filename.
    307      # element 1 is the name of the variable to test within the old version netcdf filename.
    308      # element 2 is the prefix of the new version netcdf filename.
    309      # element 3 is the name of the variable to test within the new version netcdf filename.    variables = [['AVACF','column1','AVACF','time'], ['AVACF','column2','AVACF','avacf-total']]
    310      variables  = [['Fqt','q','DISF','q'], ['Fqt','time','DISF','time'], ['Fqt','sf','DISF','Fqt-total'],\
    311                    ['Sqw','q','DISF','q'], ['Sqw','frequency','DISF','frequency'],['Sqw','dsf','DISF','Sqw-total']]
    312
    313 -    def runTest(self):
    314          AnalysisTest.runTest(self)
    315
    316 -class DISFGTests(AnalysisTest):
    317
    318      # The test shortname.
    319      shortName = 'DISFG'
    320
    321      # The test longname.
    322      longName = 'Dynamic Incoherent Structure Factor'
    323
    324      # The number of test.
    325      numberOfTests = 12
    326
    327      info = '%d tests about %s analysis.' % (numberOfTests,longName)
    328
    329      # The nested list of the correspondance between the old and new names of the variables to compare between the old
    330      # and new version of nMOLDYN. For each list,
    331      # element 0 is the prefix of the old version netcdf filename.
    332      # element 1 is the name of the variable to test within the old version netcdf filename.
    333      # element 2 is the prefix of the new version netcdf filename.
    334      # element 3 is the name of the variable to test within the new version netcdf filename.    variables = [['AVACF','column1','AVACF','time'], ['AVACF','column2','AVACF','avacf-total']]
    335      variables = [['Fqt','q','DISFG','q'], ['Fqt','time','DISFG','time'], ['Fqt','sf','DISFG','Fqt-total'],\
    336                   ['Sqw','q','DISFG','q'], ['Sqw','frequency','DISFG','frequency'],['Sqw','dsf','DISFG','Sqw-total']]
    337
    338 -    def runTest(self):
    339          AnalysisTest.runTest(self)
    340
    341 -class EISFTests(AnalysisTest):
    342      # The test shortname.
    343      shortName = 'EISF'
    344
    345      # The test longname.
    346      longName = 'Elastic Incoherent Structure Factor'
    347
    348      # The number of test.
    349      numberOfTests = 12
    350
    351      info = '%d tests about %s analysis.' % (numberOfTests,longName)
    352
    353      # The nested list of the correspondance between the old and new names of the variables to compare between the old
    354      # and new version of nMOLDYN. For each list,
    355      # element 0 is the prefix of the old version netcdf filename.
    356      # element 1 is the name of the variable to test within the old version netcdf filename.
    357      # element 2 is the prefix of the new version netcdf filename.
    358      # element 3 is the name of the variable to test within the new version netcdf filename.    variables = [['AVACF','column1','AVACF','time'], ['AVACF','column2','AVACF','avacf-total']]
    359      variables = [['EISF','column1','EISF','q'], ['EISF','column2','EISF','eisf-total']]
    360
    361 -    def runTest(self):
    362          AnalysisTest.runTest(self)
    363
    364 -class ALLTests(AnalysisTest):
    365      # The test shortname.
    366      shortName = 'ALL'
    367
    368      # The test longname.
    369      longName = 'All available tests'
    370
    371      # The number of test.
    372      numberOfTests = 12
    373
    374      variables = None
    375
    376      info = ''
    377      for n in availableTests:
    378          t = eval(n+'Tests()')
    379          info += '%d tests about %s analysis.\n' % (t.numberOfTests,t.longName)
    380          del t
    381
    382 -    def runTest(self):
    383          self.summary = ''
    384          for n in availableTests:
    385              t = eval(n+'Tests()')
    386              t.run()
    387              self.summary += t.summary
    388
    389  if __name__ == '__main__':
    390
    391      selectedTests = [n.upper() for n in sys.argv[1:]]
    392
    393      if 'ALL' in selectedTests:
    394          selectedTests =  availableTests
    395
    396      try:
    397          globalSummary = ''
    398          for n in selectedTests:
    399              t = eval(n.strip().upper()+'Tests()')
    400              t.run()
    401              globalSummary += t.summary
    402          print globalSummary
    403
    404      except:
    405          print 'One or several unknown tests'
    406