Development Guide
Testing changes and debugging in Python
In older versions of e3sm_to_cmip
, the only way to test changes was to run e3sm_to_cmip
directly on the command line. This debugging process often involves adding print
or ipdb
statements throughout the codebase, which generally isn’t good practice because it is inefficient and developers might forget to delete those statements.
As of e3sm_to_cmip > 1.91
, e3sm_to_cmip
can now be executed through a Python script. Advantages of using this approach include:
Testing and debugging changes are significantly more efficient, which shortens the debugging cycle.
Leverage IDEs to set breakpoints in IDEs and step through the call stack at runtime.
Gain a better sense of how functions are manipulating variables and whether the correct behaviors are being produced.
Prototype code in the debugger and implement those changes, then test if it behaves as expected.
Example 1 (CMORizing serially)
CLI Execution
e3sm_to_cmip --output-path ../qa/tmp --var-list 'pfull, phalf, tas, ts, psl, ps, sfcWind, huss, pr, prc, prsn, evspsbl, tauu, tauv, hfls, clt, rlds, rlus, rsds, rsus, hfss, cl, clw, cli, clivi, clwvi, prw, rldscs, rlut, rlutcs, rsdt, rsuscs, rsut, rsutcs, rtmt, abs550aer, od550aer, rsdscs, hur' --input-path /lcrc/group/e3sm/e3sm_to_cmip/input/atm-unified-eam-ncclimo --user-metadata /home/ac.tvo/E3SM-Project/CMIP6-Metadata/template.json --tables-path /home/ac.tvo/PCMDI/cmip6-cmor-tables/Tables/ --serial
Python Execution
from e3sm_to_cmip.__main__ import main
args = [
"--var-list",
'pfull, phalf, tas, ts, psl, ps, sfcWind, huss, pr, prc, prsn, evspsbl, tauu, tauv, hfls, clt, rlds, rlus, rsds, rsus, hfss, cl, clw, cli, clivi, clwvi, prw, rldscs, rlut, rlutcs, rsdt, rsuscs, rsut, rsutcs, rtmt, abs550aer, od550aer, rsdscs, hur',
"--input",
"/lcrc/group/e3sm/e3sm_to_cmip/input/atm-unified-eam-ncclimo",
"--output",
"../qa/tmp",
"--tables-path",
"/lcrc/group/e3sm/e3sm_to_cmip/cmip6-cmor-tables/Tables/",
"--user-metadata",
"/lcrc/group/e3sm/e3sm_to_cmip/template.json",
"--serial"
]
# `main()` creates an `E3SMtoCMIP` object and passes `args` to it, which sets the object parameters to execute a run.
main(args)
Example 2 (info mode)
CLI Execution
e3sm_to_cmip --info -v prw, pr --input /p/user_pub/work/E3SM/1_0/historical/1deg_atm_60-30km_ocean/atmos/native/model-output/day/ens1/v1/ --tables /home/vo13/PCMDI/cmip6-cmor-tables/Tables/
Python Execution
from e3sm_to_cmip.__main__ import main
args = [
"--info",
"-v",
"prw, pr",
"--input",
"/p/user_pub/work/E3SM/1_0/historical/1deg_atm_60-30km_ocean/atmos/native/model-output/day/ens1/v1/",
"--output",
"../qa/tmp",
"--tables-path",
"/home/vo13/PCMDI/cmip6-cmor-tables/Tables/",
]
# `main()` creates an `E3SMtoCMIP` object and passes `args` to it, which sets object parameters to execute a run.
main(args)
Example 3 (E3SMtoCMIP class inspection)
This process is useful for checking how e3sm_to_cmip
interprets the CLI arguments, and which handlers are derived based on --var-list
.
from e3sm_to_cmip.__main__ import E3SMtoCMIP
args = [
"--var-list",
'pfull, phalf, tas, ts, psl, ps, sfcWind, huss, pr, prc, prsn, evspsbl, tauu, tauv, hfls, clt, rlds, rlus, rsds, rsus, hfss, cl, clw, cli, clivi, clwvi, prw, rldscs, rlut, rlutcs, rsdt, rsuscs, rsut, rsutcs, rtmt, abs550aer, od550aer, rsdscs, hur',
"--input",
"/lcrc/group/e3sm/e3sm_to_cmip/input/atm-unified-eam-ncclimo",
"--output",
"../qa/tmp",
"--tables-path",
"/lcrc/group/e3sm/e3sm_to_cmip/cmip6-cmor-tables/Tables/",
"--user-metadata",
"/lcrc/group/e3sm/e3sm_to_cmip/template.json",
"--serial"
]
run = E3SMtoCMIP(args)
# Now we can check the `E3SMtoCMIP` object attributes for the `run` variable.
print(run.handlers)