From d5b10e2dcf8a4a4d7730925143a9ea597d1e851a Mon Sep 17 00:00:00 2001 From: Xylar Asay-Davis Date: Wed, 4 Feb 2026 08:57:09 -0600 Subject: [PATCH 1/5] Fix spacing in global plots from main vs. control runs Before this fix, there wasn't enough space for the two-line control title. --- mpas_analysis/shared/plot/climatology_map.py | 37 ++++++++++++++++---- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/mpas_analysis/shared/plot/climatology_map.py b/mpas_analysis/shared/plot/climatology_map.py index 0eb1e6092..7b5550da7 100644 --- a/mpas_analysis/shared/plot/climatology_map.py +++ b/mpas_analysis/shared/plot/climatology_map.py @@ -414,6 +414,9 @@ def _plot_panel(ax, title, array, colormap, norm, levels, ticks, contours, plottitle_font = {'size': config.get('plot', 'threePanelPlotTitleFontSize')} + multi_line_ref_title = ( + refArray is not None and refTitle is not None and '\n' in refTitle) + if refArray is None: subplots = [111] else: @@ -427,21 +430,43 @@ def _plot_panel(ax, title, array, colormap, norm, levels, ticks, contours, dictDiff = setup_colormap(config, colorMapSectionName, suffix='Difference') axes = [] - ax = plt.subplot(subplots[0], projection=projection) - _plot_panel(ax, modelTitle, modelArray, **dictModelRef) - axes.append(ax) + if refArray is not None and multi_line_ref_title: + # Use a GridSpec with unequal gaps but equal-sized panels + gs = fig.add_gridspec( + nrows=5, + ncols=1, + height_ratios=[1.0, 0.18, 1.0, 0.08, 1.0]) + + ax = fig.add_subplot(gs[0, 0], projection=projection) + _plot_panel(ax, modelTitle, modelArray, **dictModelRef) + axes.append(ax) - if refArray is not None: - ax = plt.subplot(subplots[1], projection=projection) + ax = fig.add_subplot(gs[2, 0], projection=projection) _plot_panel(ax, refTitle, refArray, **dictModelRef) axes.append(ax) - ax = plt.subplot(subplots[2], projection=projection) + ax = fig.add_subplot(gs[4, 0], projection=projection) _plot_panel(ax, diffTitle, diffArray, **dictDiff) axes.append(ax) + else: + ax = plt.subplot(subplots[0], projection=projection) + _plot_panel(ax, modelTitle, modelArray, **dictModelRef) + axes.append(ax) + + if refArray is not None: + ax = plt.subplot(subplots[1], projection=projection) + _plot_panel(ax, refTitle, refArray, **dictModelRef) + axes.append(ax) + + ax = plt.subplot(subplots[2], projection=projection) + _plot_panel(ax, diffTitle, diffArray, **dictDiff) + axes.append(ax) _add_stats(modelArray, refArray, diffArray, Lats, axes) + # Note: in the multi-line reference-title case, uneven spacing is handled + # via GridSpec so all three panels keep identical sizes. + if fileout is not None: savefig(fileout, config, pad_inches=0.2) From e6211fc97fbb6573b50a9b5e5f4b32faebd7c5fa Mon Sep 17 00:00:00 2001 From: Xylar Asay-Davis Date: Wed, 4 Feb 2026 09:01:28 -0600 Subject: [PATCH 2/5] Give statistic test more room --- mpas_analysis/shared/plot/climatology_map.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mpas_analysis/shared/plot/climatology_map.py b/mpas_analysis/shared/plot/climatology_map.py index 7b5550da7..8be601a78 100644 --- a/mpas_analysis/shared/plot/climatology_map.py +++ b/mpas_analysis/shared/plot/climatology_map.py @@ -800,12 +800,12 @@ def _add_stats(modelArray, refArray, diffArray, Lats, axes): def _add_stats_text(names, values, ax, loc): if loc == 'upper': - text_ax = inset_axes(ax, width='17%', height='20%', loc='upper right', - bbox_to_anchor=(0.2, 0.1, 1., 1.), + text_ax = inset_axes(ax, width='19%', height='20%', loc='upper right', + bbox_to_anchor=(0.22, 0.1, 1., 1.), bbox_transform=ax.transAxes, borderpad=0) else: - text_ax = inset_axes(ax, width='17%', height='20%', loc='lower right', - bbox_to_anchor=(0.2, 0.03, 1., 1.), + text_ax = inset_axes(ax, width='19%', height='20%', loc='lower right', + bbox_to_anchor=(0.22, 0.03, 1., 1.), bbox_transform=ax.transAxes, borderpad=0) text = '\n'.join(names) From b43aca78df20697e015f80e7af87e0ef93a90aec Mon Sep 17 00:00:00 2001 From: Xylar Asay-Davis Date: Wed, 4 Feb 2026 09:12:36 -0600 Subject: [PATCH 3/5] Fix units for mass flux plots --- mpas_analysis/ocean/climatology_map_fluxes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mpas_analysis/ocean/climatology_map_fluxes.py b/mpas_analysis/ocean/climatology_map_fluxes.py index 5e503d8e1..668b33db0 100644 --- a/mpas_analysis/ocean/climatology_map_fluxes.py +++ b/mpas_analysis/ocean/climatology_map_fluxes.py @@ -142,7 +142,7 @@ def __init__(self, config, mpasClimatologyTask, controlConfig=None, unitsLabel = r'W m$^{-2}$' else: groupSubtitle = 'Mass fluxes' - unitsLabel = r'kg m$^{-2}$ s^${-1}$' + unitsLabel = r'kg m$^{-2}$ s$^{-1}$' subtask.set_plot_info( outFileLabel=outFileName, From 83cb0905e21145435b9421b3e1962bb6d64b0868 Mon Sep 17 00:00:00 2001 From: Xylar Asay-Davis Date: Wed, 4 Feb 2026 11:32:55 -0600 Subject: [PATCH 4/5] Update suite to main run to year 8, ctrl to year 10 --- suite/main_vs_ctrl.cfg | 7 ------- suite/run_dev_suite.bash | 1 - suite/run_e3sm_unified_suite.bash | 1 - suite/run_suite.bash | 1 - suite/setup.py | 4 ++++ 5 files changed, 4 insertions(+), 10 deletions(-) diff --git a/suite/main_vs_ctrl.cfg b/suite/main_vs_ctrl.cfg index 2a3d28913..73a21990f 100644 --- a/suite/main_vs_ctrl.cfg +++ b/suite/main_vs_ctrl.cfg @@ -7,10 +7,3 @@ # control run is desired. controlRunConfigFile = ../ctrl.cfg -# config file for a main run on which the analysis was already run to -# completion. The relevant MPAS climatologies already exist and have been -# remapped to the comparison grid and time series have been extracted. -# Leave this option commented out if the analysis for the main run should be -# performed. -mainRunConfigFile = ../main.cfg - diff --git a/suite/run_dev_suite.bash b/suite/run_dev_suite.bash index 6b865c5a4..41cdc814e 100755 --- a/suite/run_dev_suite.bash +++ b/suite/run_dev_suite.bash @@ -25,7 +25,6 @@ py=$(python -c 'import sys; print(f"{sys.version_info[0]}.{sys.version_info[1]}" ./suite/setup.py -p ${py} -r wc_defaults -b ${branch} --no_polar_regions -e ${env_name} ./suite/setup.py -p ${py} -r moc_am -b ${branch} -e ${env_name} ./suite/setup.py -p ${py} -r no_ncclimo -b ${branch} -e ${env_name} -./suite/setup.py -p ${py} -r main -b ${branch} -e ${env_name} ./suite/setup.py -p ${py} -r ctrl -b ${branch} -e ${env_name} ./suite/setup.py -p ${py} -r main_vs_ctrl -b ${branch} -e ${env_name} ./suite/setup.py -p ${py} -r no_polar_regions -b ${branch} --no_polar_regions -e ${env_name} diff --git a/suite/run_e3sm_unified_suite.bash b/suite/run_e3sm_unified_suite.bash index 32648adfb..95266b9c4 100755 --- a/suite/run_e3sm_unified_suite.bash +++ b/suite/run_e3sm_unified_suite.bash @@ -13,7 +13,6 @@ machine=${E3SMU_MACHINE} ./suite/setup.py -p ${py} -r wc_defaults -b ${branch} --no_polar_regions ./suite/setup.py -p ${py} -r moc_am -b ${branch} ./suite/setup.py -p ${py} -r no_ncclimo -b ${branch} -./suite/setup.py -p ${py} -r main -b ${branch} ./suite/setup.py -p ${py} -r ctrl -b ${branch} ./suite/setup.py -p ${py} -r main_vs_ctrl -b ${branch} ./suite/setup.py -p ${py} -r no_polar_regions -b ${branch} --no_polar_regions diff --git a/suite/run_suite.bash b/suite/run_suite.bash index ee8dd0b16..cf3b54807 100755 --- a/suite/run_suite.bash +++ b/suite/run_suite.bash @@ -59,7 +59,6 @@ conda deactivate py=${alt_py} conda activate test_mpas_analysis_py${py} -./suite/setup.py -p ${py} -r main -b ${branch} ./suite/setup.py -p ${py} -r main_py${py} -b ${branch} conda deactivate diff --git a/suite/setup.py b/suite/setup.py index df41ce0e2..29bf8209e 100755 --- a/suite/setup.py +++ b/suite/setup.py @@ -94,12 +94,16 @@ def main(): generate = "['all', 'no_BGC', 'no_icebergs', 'no_index', 'no_eke', " \ "'no_waves']" end_year = '10' + ctrl_end_year = '8' else: raise ValueError(f'Unexpected mesh: {mesh}') if args.run == 'mesh_rename': mesh = f'new_{mesh}' + if args.run == 'main_vs_ctrl': + end_year = ctrl_end_year + sbatch = list() if account is not None: sbatch.append(f'#SBATCH -A {account}') From 4d01e3486db4a5980fa7de4ee5245a2b59fb7492 Mon Sep 17 00:00:00 2001 From: Xylar Asay-Davis Date: Wed, 4 Feb 2026 12:55:51 -0600 Subject: [PATCH 5/5] Skip hovmoller in main_vs_ctrl --- suite/setup.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/suite/setup.py b/suite/setup.py index 29bf8209e..807819695 100755 --- a/suite/setup.py +++ b/suite/setup.py @@ -91,8 +91,9 @@ def main(): shutil.copytree(os.path.join('docs', '_build', 'html'), docs_path) if mesh == 'oQU240wLI': - generate = "['all', 'no_BGC', 'no_icebergs', 'no_index', 'no_eke', " \ - "'no_waves']" + generate = [ + 'all', 'no_BGC', 'no_icebergs', 'no_index', 'no_eke', 'no_waves' + ] end_year = '10' ctrl_end_year = '8' else: @@ -103,6 +104,9 @@ def main(): if args.run == 'main_vs_ctrl': end_year = ctrl_end_year + generate.append('no_hovmoller') + + generate_string = f"['" + "', '".join(generate) + "']" sbatch = list() if account is not None: @@ -140,7 +144,7 @@ def main(): use_e3sm_unified=use_e3sm_unified, run_name=args.run, input_base=input_base, simulation=simulation, mesh=mesh, output_base=output_base, html_base=html_base, out_subdir=out_subdir, - generate=generate, end_year=end_year) + generate=generate_string, end_year=end_year) with open(config, 'w') as config_file: config_file.write(config_text)