From 70945d3297d98988a8f5e07185c0e8b130e4d483 Mon Sep 17 00:00:00 2001 From: Michael Kelleher Date: Tue, 4 Mar 2025 15:51:07 -0600 Subject: [PATCH 1/6] Make ensemble / ks compatible with MVK for EAMxx --- evv4esm/ensembles/e3sm.py | 5 ++--- evv4esm/extensions/ks.py | 20 ++++++++++++++++---- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/evv4esm/ensembles/e3sm.py b/evv4esm/ensembles/e3sm.py index 33667a3..61ea9f1 100644 --- a/evv4esm/ensembles/e3sm.py +++ b/evv4esm/ensembles/e3sm.py @@ -57,7 +57,6 @@ def file_date_str(case_file, style="short", hist_name="h0"): search_regex = r"{}\.[0-9]+-[0-9]+.nc".format(hist_name) else: search_regex = r"{}\.[0-9]+-[0-9]+.nc".format(hist_name) - result = re.search(search_regex, case_file).group(0) return result.replace("{}.".format(hist_name), "").replace(".nc", "") @@ -103,13 +102,13 @@ def get_variable_meta(dataset, var_name): return {"long_name": _name, "units": _units} -def gather_monthly_averages(ensemble_files, variable_set=None): +def gather_monthly_averages(ensemble_files, variable_set=None, hist_name="h0"): monthly_avgs = [] for case, inst_dict in six.iteritems(ensemble_files): for inst, i_files in six.iteritems(inst_dict): # Get monthly averages from files for file_ in i_files: - date_str = file_date_str(file_) + date_str = file_date_str(file_, hist_name=hist_name) data = None try: diff --git a/evv4esm/extensions/ks.py b/evv4esm/extensions/ks.py index 5e9ae11..1333af6 100755 --- a/evv4esm/extensions/ks.py +++ b/evv4esm/extensions/ks.py @@ -158,6 +158,13 @@ def parse_args(args=None): "--alpha", default=0.05, type=float, help="Alpha threshold for pass / fail" ) + parser.add_argument( + "--hist-name", + default="h0", + help="History file extension [eam: h0, scream: h, mpas: hist], default: h0", + type=str, + ) + args, _ = parser.parse_known_args(args) # use config file arguments, but override with command line arguments @@ -287,10 +294,13 @@ def case_files(args): if args.test_case == args.ref_case: key1 += "1" key2 += "2" - f_sets = { - key1: e3sm.component_monthly_files(args.test_dir, args.component, args.ninst), - key2: e3sm.component_monthly_files(args.ref_dir, args.component, args.ninst), + key1: e3sm.component_monthly_files( + args.test_dir, args.component, args.ninst, hist_name=args.hist_name + ), + key2: e3sm.component_monthly_files( + args.ref_dir, args.component, args.ninst, hist_name=args.hist_name + ), } for key in f_sets: @@ -428,7 +438,9 @@ def main(args): args.test_case = key1 args.ref_case = key2 - monthly_avgs = e3sm.gather_monthly_averages(ens_files, args.var_set) + monthly_avgs = e3sm.gather_monthly_averages( + ens_files, args.var_set, hist_name=args.hist_name + ) annual_avgs = ( monthly_avgs.groupby(["case", "variable", "instance"]) .monthly_mean.aggregate(monthly_to_annual_avg) From 2d0f37ec74576eccd0fe3f6e1d525e6c1deac6e7 Mon Sep 17 00:00:00 2001 From: Michael Kelleher Date: Tue, 4 Mar 2025 15:51:25 -0600 Subject: [PATCH 2/6] Add default EAMxx variables --- evv4esm/extensions/ks_vars.json | 396 +++++++++++++++++++------------- 1 file changed, 237 insertions(+), 159 deletions(-) diff --git a/evv4esm/extensions/ks_vars.json b/evv4esm/extensions/ks_vars.json index 9ed8ff3..fe217ce 100644 --- a/evv4esm/extensions/ks_vars.json +++ b/evv4esm/extensions/ks_vars.json @@ -1,160 +1,238 @@ { - "default": ["ADRAIN", - "ADSNOW", - "AEROD_v", - "ANRAIN", - "ANSNOW", - "AODDUST1", - "AODDUST3", - "AODVIS", - "AQRAIN", - "AQSNOW", - "AREI", - "AREL", - "AWNC", - "AWNI", - "BURDEN1", - "BURDEN2", - "BURDEN3", - "BURDENBC", - "BURDENDUST", - "BURDENPOM", - "BURDENSEASALT", - "BURDENSO4", - "BURDENSOA", - "CCN3", - "CDNUMC", - "CLDHGH", - "CLDICE", - "CLDLIQ", - "CLDLOW", - "CLDMED", - "CLDTOT", - "CLOUD", - "DCQ", - "DMS_SRF", - "DTCOND", - "DTV", - "EMISCLD", - "FICE", - "FLDS", - "FLNS", - "FLNSC", - "FLNT", - "FLNTC", - "FLUT", - "FLUTC", - "FREQI", - "FREQL", - "FREQR", - "FREQS", - "FSDS", - "FSDSC", - "FSNS", - "FSNSC", - "FSNT", - "FSNTC", - "FSNTOA", - "FSNTOAC", - "FSUTOA", - "H2O2_SRF", - "H2SO4_SRF", - "ICEFRAC", - "ICIMR", - "ICWMR", - "IWC", - "LANDFRAC", - "LHFLX", - "LIQCLDF", - "LWCF", - "NUMICE", - "NUMLIQ", - "OCNFRAC", - "OMEGA", - "OMEGAT", - "PBLH", - "PHIS", - "PRECC", - "PRECL", - "PRECSC", - "PRECSL", - "PS", - "PSL", - "Q", - "QFLX", - "QREFHT", - "QRL", - "QRS", - "RELHUM", - "SHFLX", - "SNOWHICE", - "SNOWHLND", - "SO2_SRF", - "SOAG_SRF", - "SOLIN", - "SWCF", - "T", - "TAUGWX", - "TAUGWY", - "TAUX", - "TAUY", - "TGCLDCWP", - "TGCLDIWP", - "TGCLDLWP", - "TMQ", - "TREFHT", - "TS", - "TSMN", - "TSMX", - "U", - "U10", - "UU", - "V", - "VD01", - "VQ", - "VT", - "VU", - "VV", - "Vbc_a1", - "Vdst_a1", - "Vdst_a3", - "Vncl_a1", - "Vncl_a2", - "Vncl_a3", - "Vpom_a1", - "Vso4_a1", - "Vso4_a2", - "Vso4_a3", - "Vsoa_a1", - "Vsoa_a2", - "WGUSTD", - "WSUB", - "Z3", - "bc_a1_2", - "bc_a1_SRF", - "dst_a1_2", - "dst_a1_SRF", - "dst_a3_2", - "dst_a3_SRF", - "ncl_a1_2", - "ncl_a1_SRF", - "ncl_a2_2", - "ncl_a2_SRF", - "ncl_a3_2", - "ncl_a3_SRF", - "num_a1_SRF", - "num_a2_SRF", - "num_a3_SRF", - "pom_a1_2", - "pom_a1_SRF", - "so4_a1_2", - "so4_a1_SRF", - "so4_a2_2", - "so4_a2_SRF", - "so4_a3_2", - "so4_a3_SRF", - "soa_a1_2", - "soa_a1_SRF", - "soa_a2_2", - "soa_a2_SRF"] -} + "default": [ + "ADRAIN", + "ADSNOW", + "AEROD_v", + "ANRAIN", + "ANSNOW", + "AODDUST1", + "AODDUST3", + "AODVIS", + "AQRAIN", + "AQSNOW", + "AREI", + "AREL", + "AWNC", + "AWNI", + "BURDEN1", + "BURDEN2", + "BURDEN3", + "BURDENBC", + "BURDENDUST", + "BURDENPOM", + "BURDENSEASALT", + "BURDENSO4", + "BURDENSOA", + "CCN3", + "CDNUMC", + "CLDHGH", + "CLDICE", + "CLDLIQ", + "CLDLOW", + "CLDMED", + "CLDTOT", + "CLOUD", + "DCQ", + "DMS_SRF", + "DTCOND", + "DTV", + "EMISCLD", + "FICE", + "FLDS", + "FLNS", + "FLNSC", + "FLNT", + "FLNTC", + "FLUT", + "FLUTC", + "FREQI", + "FREQL", + "FREQR", + "FREQS", + "FSDS", + "FSDSC", + "FSNS", + "FSNSC", + "FSNT", + "FSNTC", + "FSNTOA", + "FSNTOAC", + "FSUTOA", + "H2O2_SRF", + "H2SO4_SRF", + "ICEFRAC", + "ICIMR", + "ICWMR", + "IWC", + "LANDFRAC", + "LHFLX", + "LIQCLDF", + "LWCF", + "NUMICE", + "NUMLIQ", + "OCNFRAC", + "OMEGA", + "OMEGAT", + "PBLH", + "PHIS", + "PRECC", + "PRECL", + "PRECSC", + "PRECSL", + "PS", + "PSL", + "Q", + "QFLX", + "QREFHT", + "QRL", + "QRS", + "RELHUM", + "SHFLX", + "SNOWHICE", + "SNOWHLND", + "SO2_SRF", + "SOAG_SRF", + "SOLIN", + "SWCF", + "T", + "TAUGWX", + "TAUGWY", + "TAUX", + "TAUY", + "TGCLDCWP", + "TGCLDIWP", + "TGCLDLWP", + "TMQ", + "TREFHT", + "TS", + "TSMN", + "TSMX", + "U", + "U10", + "UU", + "V", + "VD01", + "VQ", + "VT", + "VU", + "VV", + "Vbc_a1", + "Vdst_a1", + "Vdst_a3", + "Vncl_a1", + "Vncl_a2", + "Vncl_a3", + "Vpom_a1", + "Vso4_a1", + "Vso4_a2", + "Vso4_a3", + "Vsoa_a1", + "Vsoa_a2", + "WGUSTD", + "WSUB", + "Z3", + "bc_a1_2", + "bc_a1_SRF", + "dst_a1_2", + "dst_a1_SRF", + "dst_a3_2", + "dst_a3_SRF", + "ncl_a1_2", + "ncl_a1_SRF", + "ncl_a2_2", + "ncl_a2_SRF", + "ncl_a3_2", + "ncl_a3_SRF", + "num_a1_SRF", + "num_a2_SRF", + "num_a3_SRF", + "pom_a1_2", + "pom_a1_SRF", + "so4_a1_2", + "so4_a1_SRF", + "so4_a2_2", + "so4_a2_SRF", + "so4_a3_2", + "so4_a3_SRF", + "soa_a1_2", + "soa_a1_SRF", + "soa_a2_2", + "soa_a2_SRF" + ], + "scream": [ + "T_mid", + "qv", + "RelativeHumidity", + "qc", + "qi", + "qr", + "qm", + "nc", + "ni", + "nr", + "cldfrac_tot_for_analysis", + "cldfrac_ice_for_analysis", + "cldfrac_liq", + "omega", + "U", + "V", + "z_mid", + "p_mid", + "tke", + "SW_flux_up_at_model_top", + "SW_flux_dn_at_model_top", + "LW_flux_up_at_model_top", + "SW_clrsky_flux_up_at_model_top", + "SW_clrsky_flux_dn_at_model_top", + "LW_clrsky_flux_up_at_model_top", + "SW_flux_up_at_model_bot", + "SW_flux_dn_at_model_bot", + "LW_flux_up_at_model_bot", + "LW_flux_dn_at_model_bot", + "SW_clrsky_flux_up_at_model_bot", + "SW_clrsky_flux_dn_at_model_bot", + "LW_clrsky_flux_dn_at_model_bot", + "ShortwaveCloudForcing", + "LongwaveCloudForcing", + "ps", + "SeaLevelPressure", + "T_2m", + "qv_2m", + "surf_radiative_T", + "VapWaterPath", + "IceWaterPath", + "LiqWaterPath", + "RainWaterPath", + "ZonalVapFlux", + "MeridionalVapFlux", + "surf_evap", + "surf_sens_flux", + "surface_upward_latent_heat_flux", + "precip_liq_surf_mass_flux", + "precip_ice_surf_mass_flux", + "landfrac", + "ocnfrac", + "PotentialTemperature_at_700hPa", + "PotentialTemperature_at_850hPa", + "PotentialTemperature_at_1000hPa", + "PotentialTemperature_at_2m_above_surface", + "omega_at_500hPa", + "omega_at_700hPa", + "omega_at_850hPa", + "RelativeHumidity_at_700hPa", + "RelativeHumidity_at_1000hPa", + "RelativeHumidity_at_2m_above_surface", + "wind_speed_10m", + "z_mid_at_700hPa", + "z_mid_at_1000hPa", + "T_mid_at_850hPa", + "T_mid_at_700hPa", + "U_at_10m_above_surface", + "V_at_10m_above_surface", + "isccp_ctptau", + "modis_ctptau", + "misr_cthtau", + "cosp_sunlit", + "isccp_cldtot" + ] +} \ No newline at end of file From 2c95a6e6ff883e4614c60aae87a63f4502a72e35 Mon Sep 17 00:00:00 2001 From: Michael Kelleher Date: Tue, 4 Mar 2025 15:52:14 -0600 Subject: [PATCH 3/6] Add test and templates for MVKxx and MVKO automated tests --- .github/workflows/python-package.yml | 2 +- test/MVKO_template.json | 16 ++++++++++++++++ test/MVKxx_template.json | 14 ++++++++++++++ test/test_evv.py | 11 ++++++++--- 4 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 test/MVKO_template.json create mode 100644 test/MVKxx_template.json diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index 43501f3..f990ffb 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -16,7 +16,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.9", "3.10", "3.11", "3.12"] + python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] steps: - uses: actions/checkout@v4 diff --git a/test/MVKO_template.json b/test/MVKO_template.json new file mode 100644 index 0000000..42df385 --- /dev/null +++ b/test/MVKO_template.json @@ -0,0 +1,16 @@ +{ + "MVKO": { + "module": "MODULE_LOCATION", + "test-case": "Test", + "test-dir": "TEST_DIRECTORY", + "ref-case": "Baseline", + "ref-dir": "BASELINE_DIRECTORY", + "var-set": "default", + "ninst": 30, + "component": "mpaso", + "img-fmt": "png", + "critical": 0, + "alpha": 0.05, + "hist-name": "hist.am.timeSeriesStatsClimatology" + } +} \ No newline at end of file diff --git a/test/MVKxx_template.json b/test/MVKxx_template.json new file mode 100644 index 0000000..f904a21 --- /dev/null +++ b/test/MVKxx_template.json @@ -0,0 +1,14 @@ +{ + "MVKxx": { + "module": "MODULE_LOCATION", + "test-case": "Test", + "test-dir": "TEST_DIRECTORY", + "ref-case": "Baseline", + "ref-dir": "BASELINE_DIRECTORY", + "var-set": "scream", + "ninst": 30, + "component": "scream", + "img-fmt": "png", + "hist-name": "h" + } +} \ No newline at end of file diff --git a/test/test_evv.py b/test/test_evv.py index 65499aa..74555d7 100644 --- a/test/test_evv.py +++ b/test/test_evv.py @@ -10,7 +10,7 @@ evv_lib_dir = Path(evv4esm.__file__).parent.resolve() mimic_lib_dir = Path(mmc.__file__).parent.resolve() cl_args = namedtuple("Args", ["cfg"]) -evv_tests = {"TSC": "tsc.py", "MVK": "ks.py"} +evv_tests = {"TSC": "tsc.py", "MVK": "ks.py", "MVKxx": "ks.py", "MVKO": "kso.py"} def gen_data_run_evv(evv_test): @@ -39,7 +39,7 @@ def gen_data_run_evv(evv_test): json.dump(evv_cfg, config_file, indent=4) evv_out_dir = Path(f"{evv_test}_test_output") - evv(["-e", str(json_file), "-o", str(evv_out_dir)]) + evv(["-e", str(json_file), "-o", str(evv_out_dir), "-p", 0]) with open(Path(evv_out_dir, "index.json")) as evv_f: evv_status = json.load(evv_f) @@ -57,9 +57,14 @@ def gen_data_run_evv(evv_test): assert not status[_index], f"{_index} SHOULD BE FAIL IS PASS" +def test_evv_mvko(): + gen_data_run_evv("MVKO") + +def test_evv_mvkxx(): + gen_data_run_evv("MVKxx") + def test_evv_tsc(): gen_data_run_evv("TSC") - def test_evv_mvk(): gen_data_run_evv("MVK") From f835137099ac2c1da3c2bbccdb9cc01046c33b6a Mon Sep 17 00:00:00 2001 From: Michael Kelleher Date: Thu, 11 Dec 2025 10:24:44 -0600 Subject: [PATCH 4/6] Update pre-commit, run and fix issues --- .pre-commit-config.yaml | 25 ++++++++++++++----------- evv4esm/ensembles/tools.py | 1 + evv4esm/extensions/ks_vars.json | 2 +- evv4esm/extensions/kso.py | 2 +- evv4esm/extensions/pg.py | 2 +- evv4esm/extensions/tsc.py | 11 +++++------ evv4esm/utils.py | 2 +- test/MVKO_template.json | 2 +- test/MVKxx_template.json | 2 +- test/test_evv.py | 3 +++ 10 files changed, 29 insertions(+), 23 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3798bcf..528d937 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,21 +1,24 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.0.1 + rev: v6.0.0 hooks: - id: end-of-file-fixer - id: trailing-whitespace - id: check-toml - - repo: https://github.com/psf/black - rev: 22.3.0 - hooks: - - id: black - - repo: https://github.com/pycqa/isort - rev: 5.13.2 - hooks: - - id: isort + - id: check-yaml + args: [--unsafe] + - id: debug-statements + - id: destroyed-symlinks + - id: detect-private-key - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. - rev: v0.3.7 + rev: v0.13.0 hooks: # Run the linter. - - id: ruff + - id: ruff-check + # Run the formatter. + - id: ruff-format + - repo: https://github.com/pycqa/isort + rev: 6.0.1 + hooks: + - id: isort diff --git a/evv4esm/ensembles/tools.py b/evv4esm/ensembles/tools.py index 84a344f..4d719a3 100644 --- a/evv4esm/ensembles/tools.py +++ b/evv4esm/ensembles/tools.py @@ -29,6 +29,7 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """General tools for working with ensembles.""" + import os import matplotlib.pyplot as plt diff --git a/evv4esm/extensions/ks_vars.json b/evv4esm/extensions/ks_vars.json index fe217ce..003fe6d 100644 --- a/evv4esm/extensions/ks_vars.json +++ b/evv4esm/extensions/ks_vars.json @@ -235,4 +235,4 @@ "cosp_sunlit", "isccp_cldtot" ] -} \ No newline at end of file +} diff --git a/evv4esm/extensions/kso.py b/evv4esm/extensions/kso.py index 61846d3..65722ac 100644 --- a/evv4esm/extensions/kso.py +++ b/evv4esm/extensions/kso.py @@ -43,6 +43,7 @@ an empirically derived approximate null distribution of t using resampling techniques. """ + import argparse import os from collections import OrderedDict @@ -386,7 +387,6 @@ def main(args): images = {"accept": [], "reject": [], "-": []} details = LIVVDict() for var in sorted(test_vars): - var_1 = e3sm.load_mpas_climatology_ensemble(ens_files[key1], var) var_2 = e3sm.load_mpas_climatology_ensemble(ens_files[key2], var) diff --git a/evv4esm/extensions/pg.py b/evv4esm/extensions/pg.py index 84b1663..b97ce02 100644 --- a/evv4esm/extensions/pg.py +++ b/evv4esm/extensions/pg.py @@ -36,6 +36,7 @@ simulation for many initial conditions, with each initial condition subject to multiple perturbations. """ + import argparse import math import os @@ -220,7 +221,6 @@ def _print_details(details): def main(args): - nvar = len(args.variables) nprt = len(args.perturbations) diff --git a/evv4esm/extensions/tsc.py b/evv4esm/extensions/tsc.py index 17ad111..aa99670 100644 --- a/evv4esm/extensions/tsc.py +++ b/evv4esm/extensions/tsc.py @@ -227,10 +227,11 @@ def main(args): for ff in truth_files ] for tt, time in enumerate(times): - with Dataset(truth_ens[instance][tt]) as truth, Dataset( - ref_ens[instance][tt] - ) as ref, Dataset(test_ens[instance][tt]) as test: - + with ( + Dataset(truth_ens[instance][tt]) as truth, + Dataset(ref_ens[instance][tt]) as ref, + Dataset(test_ens[instance][tt]) as test, + ): truth_plt, truth_ps = pressure_layer_thickness(truth) ref_plt, ref_ps = pressure_layer_thickness(ref) test_plt, test_ps = pressure_layer_thickness(test) @@ -809,7 +810,6 @@ def boxplot_delta_rmsd(args, delta_rmsd, null_hypothesis, img_file_format): list(ax1.get_yticklabels()), list(ax2.get_yticklabels()), ): - land_var_color = pf_color_picker[ null_hypothesis[ (null_hypothesis["seconds"] == time) @@ -996,7 +996,6 @@ def errorbars_delta_rmsd(args, delta_rmsd, null_hypothesis, img_file_format): for ii, var1, var2 in zip( yvals - 1, list(ax1.get_yticklabels()), list(ax2.get_yticklabels()) ): - var1.set_color(land_colors[ii]) var2.set_color(ocean_colors[ii]) diff --git a/evv4esm/utils.py b/evv4esm/utils.py index cb6dc2e..d33849c 100644 --- a/evv4esm/utils.py +++ b/evv4esm/utils.py @@ -53,7 +53,7 @@ def bib2html(bib, style=None, backend=None): return _bib2html_bibdata(bib, style=style, backend=backend) else: raise NotImplementedError( - "I do not now how to convert a {} type to a bibliography".format(type(bib)) + f"I do not now how to convert a {type(bib)} type to a bibliography" ) diff --git a/test/MVKO_template.json b/test/MVKO_template.json index 42df385..7543bc8 100644 --- a/test/MVKO_template.json +++ b/test/MVKO_template.json @@ -13,4 +13,4 @@ "alpha": 0.05, "hist-name": "hist.am.timeSeriesStatsClimatology" } -} \ No newline at end of file +} diff --git a/test/MVKxx_template.json b/test/MVKxx_template.json index f904a21..d2db6fb 100644 --- a/test/MVKxx_template.json +++ b/test/MVKxx_template.json @@ -11,4 +11,4 @@ "img-fmt": "png", "hist-name": "h" } -} \ No newline at end of file +} diff --git a/test/test_evv.py b/test/test_evv.py index 74555d7..6e855b1 100644 --- a/test/test_evv.py +++ b/test/test_evv.py @@ -60,11 +60,14 @@ def gen_data_run_evv(evv_test): def test_evv_mvko(): gen_data_run_evv("MVKO") + def test_evv_mvkxx(): gen_data_run_evv("MVKxx") + def test_evv_tsc(): gen_data_run_evv("TSC") + def test_evv_mvk(): gen_data_run_evv("MVK") From b76190e86255f5488f24fced31d5d22ac2014972 Mon Sep 17 00:00:00 2001 From: Michael Kelleher Date: Thu, 11 Dec 2025 11:15:13 -0600 Subject: [PATCH 5/6] Add verbose flag to pre-commit formatter --- .pre-commit-config.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 528d937..9bc6360 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -18,6 +18,7 @@ repos: - id: ruff-check # Run the formatter. - id: ruff-format + args: [--verbose] - repo: https://github.com/pycqa/isort rev: 6.0.1 hooks: From 62bcbca8c734b13ce9c14a4db341ebe602f03fa4 Mon Sep 17 00:00:00 2001 From: Michael Kelleher Date: Thu, 11 Dec 2025 11:18:09 -0600 Subject: [PATCH 6/6] Fix formatting issue in KS extension --- evv4esm/extensions/ks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evv4esm/extensions/ks.py b/evv4esm/extensions/ks.py index 1333af6..8dfb9c4 100755 --- a/evv4esm/extensions/ks.py +++ b/evv4esm/extensions/ks.py @@ -122,7 +122,7 @@ def parse_args(args=None): "--ninst", default=30, type=int, - help="The number of instances (should be the same for " "both cases).", + help="The number of instances (should be the same for both cases).", ) parser.add_argument(