From da8b4d3aa49a9e1de3186bd255c8931f2c07144c Mon Sep 17 00:00:00 2001 From: Ian Laflotte Date: Mon, 13 Jan 2025 11:35:45 -0500 Subject: [PATCH] ok got a format and a conditional pytest.xfail approach i am OK with. push to make sure this xfails in the pipeline appropriately --- fre/cmor/cmor_helpers.py | 1 + fre/cmor/tests/test_cmor_run_subtool.py | 6 +- .../tests/test_cmor_run_subtool_ppan_only.py | 379 +++++++++--------- 3 files changed, 196 insertions(+), 190 deletions(-) diff --git a/fre/cmor/cmor_helpers.py b/fre/cmor/cmor_helpers.py index c4707c6d..bab9899e 100644 --- a/fre/cmor/cmor_helpers.py +++ b/fre/cmor/cmor_helpers.py @@ -83,6 +83,7 @@ def get_var_filenames(indir, var_filenames = None, local_var = None): var_filenames = [] filename_pattern = '.nc' if local_var is None else f'.{local_var}.nc' print(f'(get_var_filenames) filename_pattern = {filename_pattern}\n') + print(f'(get_var_filenames) indir = {indir}\n') var_filenames_all = glob.glob(f'{indir}/*{filename_pattern}') #print(f'(get_var_filenames) var_filenames_all = {var_filenames_all}') for var_file in var_filenames_all: diff --git a/fre/cmor/tests/test_cmor_run_subtool.py b/fre/cmor/tests/test_cmor_run_subtool.py index a896f250..59cf1ac0 100644 --- a/fre/cmor/tests/test_cmor_run_subtool.py +++ b/fre/cmor/tests/test_cmor_run_subtool.py @@ -14,14 +14,14 @@ ROOTDIR = 'fre/tests/test_files' # setup- cmip/cmor variable table(s) -CLONE_REPO_PATH = \ +CMIP6_TABLE_REPO_PATH = \ f'{ROOTDIR}/cmip6-cmor-tables' TABLE_CONFIG = \ - f'{CLONE_REPO_PATH}/Tables/CMIP6_Omon.json' + f'{CMIP6_TABLE_REPO_PATH}/Tables/CMIP6_Omon.json' def test_setup_cmor_cmip_table_repo(): ''' setup routine, make sure the recursively cloned tables exist ''' - assert all( [ Path(CLONE_REPO_PATH).exists(), + assert all( [ Path(CMIP6_TABLE_REPO_PATH).exists(), Path(TABLE_CONFIG).exists() ] ) diff --git a/fre/cmor/tests/test_cmor_run_subtool_ppan_only.py b/fre/cmor/tests/test_cmor_run_subtool_ppan_only.py index f74e8dcf..b7be5cc2 100644 --- a/fre/cmor/tests/test_cmor_run_subtool_ppan_only.py +++ b/fre/cmor/tests/test_cmor_run_subtool_ppan_only.py @@ -1,16 +1,19 @@ -#!/usr/bin/env python ''' -this is a quick and dirty script. -it will not be maintained. it will not be supported. -it is for a very context-dependent set of tests for a very specific point in time. +expanded set of tests for fre cmor run +focus on ''' -import sys +from datetime import date import os from pathlib import Path +import sys +import shutil + +import pytest from fre.cmor import cmor_run_subtool +# helper functions, not tests def print_cwd(): print(f'os.getcwd() = {os.getcwd()}') print(f'\n\n\n\n') @@ -30,195 +33,197 @@ def print_the_outcome(some_return,case_str): ROOTDIR='fre/tests/test_files' CMORBITE_VARLIST=f'{ROOTDIR}/CMORbite_var_list.json' +# cmip6 variable table(s) +CMIP6_TABLE_REPO_PATH = \ + f'{ROOTDIR}/cmip6-cmor-tables' + +# outputs +OUTDIR = f'{ROOTDIR}/outdir' +TMPDIR = f'{OUTDIR}/tmp' +# determined by cmor_run_subtool +YYYYMMDD = date.today().strftime('%Y%m%d') +CMOR_CREATES_DIR_BASE = \ + 'CMIP6/CMIP6/ISMIP6/PCMDI/PCMDI-test-1-0/piControl-withism/r3i1p1f1'#Omon/sos/gn' +#FULL_OUTPUTDIR = \ +# f"{OUTDIR}/{CMOR_CREATES_DIR}/v{YYYYMMDD}" + # this file exists basically for users to specify their own information to append to the netcdf file # i.e., it fills in FOO/BAR/BAZ style values, and what they are currently is totally irrelevant EXP_CONFIG_DEFAULT=f'{ROOTDIR}/CMOR_input_example.json' # this likely is not sufficient -def run_cmor_RUN(filename, table, opt_var_name): - func_debug1 = False - if func_debug1: - print('cmor_run_subtool(\n' - f' indir = \"{str(Path(filename).parent)}\",\n' - f' json_var_list = \"{CMORBITE_VARLIST}\",\n' - f' json_table_config = \"{ROOTDIR}/cmip6-cmor-tables/Tables/CMIP6_{table}.json\",\n' - f' json_exp_config = \"{EXP_CONFIG_DEFAULT}\",\n' - f' outdir = \"{os.getcwd()}\",\n' - f' opt_var_name = \"{opt_var_name}\"\n' - ')\n' - ) - func_debug2 = True - if func_debug2: - print('fre cmor run ' - f'-d {str(Path(filename).parent)} ' - f'-l {CMORBITE_VARLIST} ' - f'-r {ROOTDIR}/cmip6-cmor-tables/Tables/CMIP6_{table}.json ' - f'-p {EXP_CONFIG_DEFAULT} ' - f'-o {os.getcwd()} ' - f'-v {opt_var_name} ' - ) - FOO_return = cmor_run_subtool( - indir = str(Path(filename).parent), - json_var_list = CMORBITE_VARLIST, - json_table_config = f'{ROOTDIR}/cmip6-cmor-tables/Tables/CMIP6_{table}.json', - json_exp_config = EXP_CONFIG_DEFAULT, - outdir = os.getcwd(), # dont keep it this way... - opt_var_name = opt_var_name - ) - return FOO_return - - - -if True: - #### THIS CASE MAY WORK if i rewrite the ocean file correctly, effectively appending the lat/lon data from a statics file. - #### for this case, that file is: - #### '/archive/ejs/CMIP7/ESM4/DEV/ESM4.5v01_om5b04_piC/gfdl.ncrc5-intel23-prod-openmp/' + \ - #### 'pp/ocean_monthly/' + \ - #### 'ocean_monthly.static.nc' - #### and that data is stored under "geolon" and "geolat" consuming dims "x" and "y". - # 6) FAIL - # ocean, Omon / sos - # Result - error, it wants lat/lon, but only xh, yh coordinates are available - testfile_ocean_monthly_gn = \ - '/archive/ejs/CMIP7/ESM4/DEV/ESM4.5v01_om5b04_piC/gfdl.ncrc5-intel23-prod-openmp/' + \ - 'pp/ocean_monthly/ts/monthly/5yr/' + \ - 'ocean_monthly.002101-002512.sos.nc' - try: - some_return = run_cmor_RUN(testfile_ocean_monthly_gn, 'Omon', opt_var_name = 'sos') - except Exception as exc: - print(f'exception caught: exc=\n{exc}') - some_return=-1 - - print_the_outcome(some_return,'ocean_monthly_gn / sos') - - #sys.exit() - - -if True: - # 1) SUCCEEDs - # land, Lmon, gr1 - testfile_land_gr1_Lmon = \ + +def test_case_land_Lmon_gr1(): + + # clean up from previous tests + if Path(f'{OUTDIR}/CMIP6').exists(): + shutil.rmtree(f'{OUTDIR}/CMIP6') + + # define inputs to the cmor run tool + testfile = \ '/archive/Eric.Stofferahn/CMIP7/ESM4/DEV/ESM4.5v01_om5b04_piC/gfdl.ncrc5-intel23-prod-openmp/' + \ 'pp/land/ts/monthly/5yr/' + \ 'land.005101-005512.lai.nc' + indir = Path(testfile).parent + table = 'Lmon' + table_file = f'{CMIP6_TABLE_REPO_PATH}/Tables/CMIP6_{table}.json' + opt_var_name = 'lai' + + # if we can't find the input test file, do an xfail. most likely, you're not at PPAN. + if not Path(testfile).exists(): + pytest.xfail('land, Lmon, gr1 - SUCCEEDs on PP/AN at GFDL only! OR testfile does not exist!') + + # execute the test try: - some_return = run_cmor_RUN(testfile_land_gr1_Lmon, 'Lmon', opt_var_name = 'lai') - except: - print(f'exception caught: exc=\n{exc}') - some_return=-1 - - print_the_outcome(some_return,'land_gr1_Lmon / lai') - - - # 2) SUCCEEDs - # atmos, Amon / cl - testfile_atmos_level_cmip_gr1_Amon_complex_vert = \ - '/arch0/cm6/ESM4/DECK/ESM4_historical_D1/gfdl.ncrc4-intel16-prod-openmp/' + \ - 'pp/atmos_level_cmip/ts/monthly/5yr/' + \ - 'atmos_level_cmip.196001-196412.cl.nc' - try: - some_return = run_cmor_RUN(testfile_atmos_level_cmip_gr1_Amon_complex_vert, 'Amon', opt_var_name = 'cl') - except Exception as exc: - print(f'exception caught: exc=\n{exc}') - some_return=-1 - - print_the_outcome(some_return,'atmos_level_cmip_gr1_Amon_complex_vert / cl') - - - # 3) SUCCEEDs - # atmos, Amon / mc - testfile_atmos_level_cmip_gr1_Amon_fullL = \ - '/arch0/cm6/ESM4/DECK/ESM4_historical_D1/gfdl.ncrc4-intel16-prod-openmp/' + \ - 'pp/atmos_level_cmip/ts/monthly/5yr/' + \ - 'atmos_level_cmip.195501-195912.mc.nc' - try: - some_return = run_cmor_RUN(testfile_atmos_level_cmip_gr1_Amon_fullL, 'Amon', opt_var_name = 'mc') - except Exception as exc: - print(f'exception caught: exc=\n{exc}') - some_return=-1 - - print_the_outcome(some_return,'atmos_level_cmip_gr1_Amon_fullL / mc') - - - # 4) SUCCEEDs (no longitude coordinate case) - # atmos, AERmonZ / ta - # just like #1, but lack longitude - testfile_atmos_gr1_AERmonZ_nolons = \ - '/arch0/cm6/ESM4/DECK/ESM4_historical_D1/gfdl.ncrc4-intel16-prod-openmp/' + \ - 'pp/atmos_plev39_cmip/ts/monthly/5yr/zonavg/' + \ - 'atmos_plev39_cmip.201001-201412.ta.nc' - try: - some_return = run_cmor_RUN(testfile_atmos_gr1_AERmonZ_nolons, 'AERmonZ', opt_var_name = 'ta') - except Exception as exc: - print(f'exception caught: exc=\n{exc}') - some_return=-1 - - print_the_outcome(some_return,'atmos_gr1_AERmonZ_nolons / ta') - - - # 5) SUCCEEDs - # ocean, Omon / sos - testfile_ocean_monthly_1x1deg_gr = \ - '/arch0/cm6/ESM4/DECK/ESM4_historical_D1/gfdl.ncrc4-intel16-prod-openmp/' + \ - 'pp/ocean_monthly_1x1deg/ts/monthly/5yr/' + \ - 'ocean_monthly_1x1deg.190001-190412.sos.nc' - try: - some_return = run_cmor_RUN(testfile_ocean_monthly_1x1deg_gr, 'Omon', opt_var_name = 'sos') - except Exception as exc: - print(f'exception caught: exc=\n{exc}') - some_return=-1 - - print_the_outcome(some_return,'ocean_monthly_1x1deg_gr / sos') - - - # 7) SUCCEEDs - # ocean, Omon / so - testfile_ocean_monthly_z_1x1deg_gr = \ - '/archive/ejs/CMIP7/ESM4/DEV/ESM4.5v01_om5b04_piC/gfdl.ncrc5-intel23-prod-openmp/' + \ - 'pp/ocean_monthly_z_1x1deg/ts/monthly/5yr/' + \ - 'ocean_monthly_z_1x1deg.000101-000512.so.nc' - try: - some_return = run_cmor_RUN(testfile_ocean_monthly_z_1x1deg_gr, 'Omon', opt_var_name = 'so') - except Exception as exc: - print(f'exception caught: exc=\n{exc}') - some_return=-1 - - print_the_outcome(some_return,'ocean_monthly_z_1x1deg_gr / so') - - - # 8) SUCCEEDs (no latitude, nor longitude, nor vertical coordinates cases) - # atmos, Amon / ch4global - testfile_atmos_scalar_gn_Amon_nolon_nolat = \ - '/arch0/cm6/ESM4/DECK/ESM4_historical_D1/gfdl.ncrc4-intel16-prod-openmp/' + \ - 'pp/atmos_scalar/ts/monthly/5yr/' + \ - 'atmos_scalar.197001-197412.ch4global.nc' - try: - some_return = run_cmor_RUN(testfile_atmos_scalar_gn_Amon_nolon_nolat, 'Amon', opt_var_name = 'ch4global') - except Exception as exc: - print(f'exception caught: exc=\n{exc}') - some_return=-1 - - print_the_outcome(some_return,'atmos_scalar_gn_Amon_nolon_nolat / ch4global') - - - - # 9) SUCCEEDs (needs coordinate variable axis with character string values) - # land, Emon / gppLut - testfile_LUmip_refined_gr1_Emon_landusedim = \ - '/arch0/cm6/ESM4/DECK/ESM4_historical_D1/gfdl.ncrc4-intel16-prod-openmp/' + \ - 'pp/LUmip_refined/ts/monthly/5yr/' + \ - 'LUmip_refined.185001-185412.gppLut.nc' - try: - some_return = run_cmor_RUN(testfile_LUmip_refined_gr1_Emon_landusedim, 'Emon', opt_var_name = 'gppLut') + cmor_run_subtool( + indir = indir, + json_var_list = CMORBITE_VARLIST, + json_table_config = table_file, + json_exp_config = EXP_CONFIG_DEFAULT, + outdir = OUTDIR, + opt_var_name = opt_var_name + ) + some_return = 0 except Exception as exc: - print(f'exception caught: exc=\n{exc}') - some_return=-1 - - print_the_outcome(some_return,'LUmip_refined_gr1_Emon_landusedim / gppLut') - - - - - - - + raise Exception(f'exception caught: exc=\n{exc}') from exc + + # outputs that should be created + cmor_output_dir = f'{OUTDIR}/{CMOR_CREATES_DIR_BASE}/{table}/{opt_var_name}/gn/v{YYYYMMDD}' + cmor_output_file = f'{cmor_output_dir}/{opt_var_name}_{table}_PCMDI-test-1-0_piControl-withism_r3i1p1f1_gn_000101-000601.nc' + + # success criteria + assert all( [ some_return == 0, + Path(cmor_output_dir).exists(), + Path(cmor_output_file).exists() ] ) + + +# +## 2) SUCCEEDs +## atmos, Amon / cl +#testfile_atmos_level_cmip_gr1_Amon_complex_vert = \ +# '/arch0/cm6/ESM4/DECK/ESM4_historical_D1/gfdl.ncrc4-intel16-prod-openmp/' + \ +# 'pp/atmos_level_cmip/ts/monthly/5yr/' + \ +# 'atmos_level_cmip.196001-196412.cl.nc' +#try: +# some_return = run_cmor_RUN(testfile_atmos_level_cmip_gr1_Amon_complex_vert, 'Amon', opt_var_name = 'cl') +#except Exception as exc: +# print(f'exception caught: exc=\n{exc}') +# some_return=-1 +# +#print_the_outcome(some_return,'atmos_level_cmip_gr1_Amon_complex_vert / cl') +# +# +## 3) SUCCEEDs +## atmos, Amon / mc +#testfile_atmos_level_cmip_gr1_Amon_fullL = \ +# '/arch0/cm6/ESM4/DECK/ESM4_historical_D1/gfdl.ncrc4-intel16-prod-openmp/' + \ +# 'pp/atmos_level_cmip/ts/monthly/5yr/' + \ +# 'atmos_level_cmip.195501-195912.mc.nc' +#try: +# some_return = run_cmor_RUN(testfile_atmos_level_cmip_gr1_Amon_fullL, 'Amon', opt_var_name = 'mc') +#except Exception as exc: +# print(f'exception caught: exc=\n{exc}') +# some_return=-1 +# +#print_the_outcome(some_return,'atmos_level_cmip_gr1_Amon_fullL / mc') +# +# +## 4) SUCCEEDs (no longitude coordinate case) +## atmos, AERmonZ / ta +## just like #1, but lack longitude +#testfile_atmos_gr1_AERmonZ_nolons = \ +# '/arch0/cm6/ESM4/DECK/ESM4_historical_D1/gfdl.ncrc4-intel16-prod-openmp/' + \ +# 'pp/atmos_plev39_cmip/ts/monthly/5yr/zonavg/' + \ +# 'atmos_plev39_cmip.201001-201412.ta.nc' +#try: +# some_return = run_cmor_RUN(testfile_atmos_gr1_AERmonZ_nolons, 'AERmonZ', opt_var_name = 'ta') +#except Exception as exc: +# print(f'exception caught: exc=\n{exc}') +# some_return=-1 +# +#print_the_outcome(some_return,'atmos_gr1_AERmonZ_nolons / ta') +# +# +## 5) SUCCEEDs +## ocean, Omon / sos, gr +#testfile_ocean_monthly_1x1deg_gr = \ +# '/arch0/cm6/ESM4/DECK/ESM4_historical_D1/gfdl.ncrc4-intel16-prod-openmp/' + \ +# 'pp/ocean_monthly_1x1deg/ts/monthly/5yr/' + \ +# 'ocean_monthly_1x1deg.190001-190412.sos.nc' +#try: +# some_return = run_cmor_RUN(testfile_ocean_monthly_1x1deg_gr, 'Omon', opt_var_name = 'sos') +#except Exception as exc: +# print(f'exception caught: exc=\n{exc}') +# some_return=-1 +# +#print_the_outcome(some_return,'ocean_monthly_1x1deg_gr / sos') +# +# +## 6) SUCCEEDs +## ocean, Omon / sos, gn +#testfile_ocean_monthly_gn = \ +# '/archive/ejs/CMIP7/ESM4/DEV/ESM4.5v01_om5b04_piC/gfdl.ncrc5-intel23-prod-openmp/' + \ +# 'pp/ocean_monthly/ts/monthly/5yr/' + \ +# 'ocean_monthly.002101-002512.sos.nc' +#try: +# some_return = run_cmor_RUN(testfile_ocean_monthly_gn, 'Omon', opt_var_name = 'sos') +#except Exception as exc: +# print(f'exception caught: exc=\n{exc}') +# some_return=-1 +# +# print_the_outcome(some_return,'ocean_monthly_gn / sos') +# +# +# +## 7) SUCCEEDs +## ocean, Omon / so +#testfile_ocean_monthly_z_1x1deg_gr = \ +# '/archive/ejs/CMIP7/ESM4/DEV/ESM4.5v01_om5b04_piC/gfdl.ncrc5-intel23-prod-openmp/' + \ +# 'pp/ocean_monthly_z_1x1deg/ts/monthly/5yr/' + \ +# 'ocean_monthly_z_1x1deg.000101-000512.so.nc' +#try: +# some_return = run_cmor_RUN(testfile_ocean_monthly_z_1x1deg_gr, 'Omon', opt_var_name = 'so') +#except Exception as exc: +# print(f'exception caught: exc=\n{exc}') +# some_return=-1 +# +#print_the_outcome(some_return,'ocean_monthly_z_1x1deg_gr / so') +# +# +## 8) SUCCEEDs (no latitude, nor longitude, nor vertical coordinates cases) +## atmos, Amon / ch4global +#testfile_atmos_scalar_gn_Amon_nolon_nolat = \ +# '/arch0/cm6/ESM4/DECK/ESM4_historical_D1/gfdl.ncrc4-intel16-prod-openmp/' + \ +# 'pp/atmos_scalar/ts/monthly/5yr/' + \ +# 'atmos_scalar.197001-197412.ch4global.nc' +#try: +# some_return = run_cmor_RUN(testfile_atmos_scalar_gn_Amon_nolon_nolat, 'Amon', opt_var_name = 'ch4global') +#except Exception as exc: +# print(f'exception caught: exc=\n{exc}') +# some_return=-1 +# +#print_the_outcome(some_return,'atmos_scalar_gn_Amon_nolon_nolat / ch4global') +# +# +# +## 9) SUCCEEDs (needs coordinate variable axis with character string values) +## land, Emon / gppLut +#testfile_LUmip_refined_gr1_Emon_landusedim = \ +# '/arch0/cm6/ESM4/DECK/ESM4_historical_D1/gfdl.ncrc4-intel16-prod-openmp/' + \ +# 'pp/LUmip_refined/ts/monthly/5yr/' + \ +# 'LUmip_refined.185001-185412.gppLut.nc' +#try: +# some_return = run_cmor_RUN(testfile_LUmip_refined_gr1_Emon_landusedim, 'Emon', opt_var_name = 'gppLut') +#except Exception as exc: +# print(f'exception caught: exc=\n{exc}') +# some_return=-1 +# +#print_the_outcome(some_return,'LUmip_refined_gr1_Emon_landusedim / gppLut') +# +# +# +# +# +# +# +#