99# progress bar
1010from tqdm import tqdm
1111
12+ ### Version :
13+ version = '0.1' #05.08.2022 (Major version).(Minor version)
14+
1215#######################################
1316#### specify your source path
1417#######################################
2124
2225try :
2326 # load csv :
24- ismip = pd .read_csv (workdir + '/ismip6_criteria_v0 .csv' ,delimiter = ';' ,decimal = "," )
27+ ismip = pd .read_csv (workdir + '/ismip6_criteria .csv' ,delimiter = ';' ,decimal = "," )
2528except IOError :
2629 print ('ERROR: Unable to open the compliance criteria file (.csv required with ; as delimiter and , for decimal.). Is the path to the file correct ? ' + workdir + 'ismip6_criteria_v0.csv' )
2730else :
@@ -68,6 +71,11 @@ def files_and_subdirectories(path):
6871 directories .append (f )
6972 return directories , files
7073
74+ # check motonocity of a list (used to check time serie)
75+
76+ def strictly_increasing (L ):
77+ return all (x < y for x , y in zip (L , L [1 :]))
78+
7179###############################################
7280# create the compliance_checker_log.txt file
7381###############################################
@@ -84,7 +92,7 @@ def files_and_subdirectories(path):
8492 f .write ('************************************************************************************\n ' )
8593 f .write ('************* Ice Sheet Model Simulations - Compliance Checker *************\n ' )
8694 f .write ('************************************************************************************\n ' )
87- f .write ('version: 0 \n ' )
95+ f .write (f 'version: { version } \n ' )
8896 f .write ('verification criteria: ismip6_criteria_v0.csv \n ' )
8997 f .write ('date: ' + today .strftime ("%Y/%m/%d" ) + '\n ' )
9098 f .write ('source: https://github.com/jbbarre/ISM_SimulationChecker \n ' )
@@ -128,7 +136,6 @@ def files_and_subdirectories(path):
128136 file_counter = 0
129137 #initialize files checked counter
130138 exp_counter = 0
131-
132139 for xp in experiment_directories :
133140
134141 exp_counter += 1
@@ -166,15 +173,17 @@ def files_and_subdirectories(path):
166173 temp_mandatory_var = mandatory_variables
167174 if variable in mandatory_variables :
168175 temp_mandatory_var .remove (variable )
176+ #split the experiment directory name
177+ experiment_chain = xp .split ('_' )
169178 #get the experiment name (example: exp05)
170- experiment_name = xp . split ( '_' )[ 0 ]
179+ experiment_name = '_' . join ( experiment_chain [: - 1 ])
171180 #get the resolution as integer
172- grid_resolution = int (xp . split ( '_' )[ 1 ])
181+ grid_resolution = int (experiment_chain [ - 1 ])
173182
174183 if experiment_name in [dic ['experiment' ] for dic in experiments ]:
175184 f .write ('\n ' )
176185 f .write ('**********************************************************\n ' )
177- f .write ('** Experiment: ' + experiment_name + ' \n ' )
186+ f .write (' ** Experiment: ' + experiment_name + ' \n ' )
178187 f .write ('**********************************************************\n ' )
179188 f .write ('\n ' )
180189 if not temp_mandatory_var :
@@ -342,47 +351,59 @@ def files_and_subdirectories(path):
342351 f .write ('TIME Tests \n ' )
343352 #check if time dimension is not missing
344353 if set (['t' ]).issubset (dim ) or set (['time' ]).issubset (dim ):
354+ iteration = len (ds .coords ['time' ])
345355 start_exp = pd .to_datetime (min (ds ['time' ]).values .astype ("datetime64[ns]" ))
346356 end_exp = pd .to_datetime (max (ds ['time' ]).values .astype ("datetime64[ns]" ))
347357 avgyear = 365.2425 # pedants definition of a year length with leap years
348- duration_days = (end_exp - start_exp )
349- duration_years = round (pd .to_numeric (duration_days .days / avgyear ))
350-
358+
351359 index_exp = [dic ['experiment' ] for dic in experiments ].index (experiment_name )
352360 #test if start_exp and end_exp are datetime format
353361 if isinstance (start_exp , datetime .datetime ) & isinstance (end_exp , datetime .datetime ):
354- # test Starting date
355- if experiments [index_exp ]['startinf' ] <= start_exp <= experiments [index_exp ]['startsup' ]:
356- f .write (' - Experiment starts correctly on ' + start_exp .strftime ('%Y-%m-%d' ) + '.\n ' )
357- else :
358- f .write (' - ERROR: the experiment starts the ' + start_exp .strftime ('%Y-%m-%d' ) + '. The date should be comprised between ' + experiments [index_exp ]['startinf' ].strftime ('%Y-%m-%d' ) + ' and ' + experiments [index_exp ]['startsup' ].strftime ('%Y-%m-%d' )+ '\n ' )
359- var_time_errors += 1
360- # test Ending date
361- if experiments [index_exp ]['endinf' ] <= end_exp <= experiments [index_exp ]['endsup' ]:
362- f .write (' - Experiment ends correctly on ' + end_exp .strftime ('%Y-%m-%d' ) + '.\n ' )
363- else :
364- f .write (' - ERROR: the experiment ends on ' + end_exp .strftime ('%Y-%m-%d' ) + '. The date should be comprised between ' + experiments [index_exp ]['endinf' ].strftime ('%Y-%m-%d' ) + ' and ' + experiments [index_exp ]['endsup' ].strftime ('%Y-%m-%d' )+ '\n ' )
365- var_time_errors += 1
366- # test Duration
367- if experiments [index_exp ]['duration' ]- 1 <= duration_years <= experiments [index_exp ]['duration' ]:
368- f .write (" - Experiment lasts " + str (duration_years ) + ' years.\n ' )
369- else :
370- f .write (' - ERROR: the experiment lasts ' + str (duration_years ) + ' years. The duration should be ' + str (experiments [index_exp ]['duration' ]) + ' years\n ' )
371- var_time_errors += 1
372- # test Time step
373- if isinstance ((ds ['time' ].values [1 ]- ds ['time' ].values [0 ]),datetime .timedelta ):
374- time_step = (ds ['time' ].values [1 ]- ds ['time' ].values [0 ]).days
375- else :
376- if isinstance ((ds ['time' ].values [1 ]- ds ['time' ].values [0 ]),np .timedelta64 ):
377- time_step = np .timedelta64 (ds ['time' ].values [1 ]- ds ['time' ].values [0 ], 'D' )/ np .timedelta64 (1 , 'D' )
378- else :
379- time_step = ds ['time' ].values [1 ]- ds ['time' ].values [10 ]
380-
381- if 360 <= time_step <= 367 :
382- f .write (' - Time step: ' + str (time_step ) + ' days' + '\n ' )
383- else :
384- f .write (' - ERROR: the time step(' + str (time_step ) + ') should be comprised between [360,367].\n ' )
362+ #check Monotonicity of the time serie
363+ if strictly_increasing (ds .coords ['time' ]):
364+ # test Time step : should be 360<timestep<367
365+ if isinstance ((ds ['time' ].values [1 ]- ds ['time' ].values [0 ]),datetime .timedelta ):
366+ time_step = (ds ['time' ].values [1 ]- ds ['time' ].values [0 ]).days
367+ else :
368+ if isinstance ((ds ['time' ].values [1 ]- ds ['time' ].values [0 ]),np .timedelta64 ):
369+ time_step = np .timedelta64 (ds ['time' ].values [1 ]- ds ['time' ].values [0 ], 'D' )/ np .timedelta64 (1 , 'D' )
370+ else :
371+ time_step = ds ['time' ].values [1 ]- ds ['time' ].values [10 ]
372+
373+ if 360 <= time_step <= 367 :
374+ f .write (' - Time step: ' + str (time_step ) + ' days' + '\n ' )
375+ else :
376+ f .write (' - ERROR: the time step(' + str (time_step ) + ') should be comprised between [360,367].\n ' )
377+ var_time_errors += 1
378+
379+ # test duration (iteration = length of the coords 'time')
380+ duration_days = pd .to_timedelta (time_step * iteration ,'D' )
381+ duration_years = round (pd .to_numeric (duration_days .days / avgyear ))
382+ if duration_years == experiments [index_exp ]['duration' ]:
383+ f .write (" - Experiment lasts " + str (duration_years ) + ' years.\n ' )
384+ # test Starting date
385+ if experiments [index_exp ]['startinf' ] <= start_exp <= experiments [index_exp ]['startsup' ]:
386+ f .write (' - Experiment starts correctly on ' + start_exp .strftime ('%Y-%m-%d' ) + '.\n ' )
387+ else :
388+ f .write (' - ERROR: the experiment starts the ' + start_exp .strftime ('%Y-%m-%d' ) + '. The date should be comprised between ' + experiments [index_exp ]['startinf' ].strftime ('%Y-%m-%d' ) + ' and ' + experiments [index_exp ]['startsup' ].strftime ('%Y-%m-%d' )+ '\n ' )
389+ var_time_errors += 1
390+ # test Ending date
391+ if experiments [index_exp ]['endinf' ] <= end_exp <= experiments [index_exp ]['endsup' ]:
392+ f .write (' - Experiment ends correctly on ' + end_exp .strftime ('%Y-%m-%d' ) + '.\n ' )
393+ else :
394+ f .write (' - ERROR: the experiment ends on ' + end_exp .strftime ('%Y-%m-%d' ) + '. The date should be comprised between ' + experiments [index_exp ]['endinf' ].strftime ('%Y-%m-%d' ) + ' and ' + experiments [index_exp ]['endsup' ].strftime ('%Y-%m-%d' )+ '\n ' )
395+ var_time_errors += 1
396+ else :
397+ end_date = start_exp + datetime .timedelta (days = experiments [index_exp ]['duration' ]* avgyear )
398+ f .write (' - ERROR: the experiment lasts ' + str (duration_years ) + ' years. The duration should be ' + str (experiments [index_exp ]['duration' ]) + ' years\n ' )
399+ f .write (' - As the experiment started on ' + start_exp .strftime ('%Y-%m-%d' ) + ' , it should end on ' + end_date .strftime ('%Y-%m-%d' )+ '\n ' )
400+ var_time_errors += 1
401+
402+
403+ else : #time serie not monotonous
404+ f .write (' - ERROR: the time serie is not monotonous. Time segments have probably been concatenate in a wrong order.\n ' )
385405 var_time_errors += 1
406+
386407 else :
387408 #not a datetime format
388409 f .write (' - ERROR: the time format of the Netcdf file is not recognized.Time Tests have been ignored.\n ' )
@@ -449,7 +470,7 @@ def files_and_subdirectories(path):
449470 else :
450471 f .write ('\n ' )
451472 f .write ('**********************************************************\n ' )
452- f .write ('** Experiment: ' + experiment_name + ' \n ' )
473+ f .write (' ** Experiment: ' + experiment_name + ' \n ' )
453474 f .write ('**********************************************************\n ' )
454475 f .write ('\n ' )
455476 f .write ('ERROR: The compliance check is ignored for experiment ' + experiment_name + ' as it is not in [hist, ctrl, ctrl_proj, exp01, exp02, exp03, exp04, exp05, exp06, exp07, exp08, exp09, exp10, exp11, exp12, exp13]. \n ' )
0 commit comments