Skip to content

Commit 813bc41

Browse files
chengzhuzhangclaudetomvothecoderCopilot
authored
Extend snapshot support for other core sets and doc updates (#1013)
* Extend snapshot support for other core sets * add new util module * fix tests * fix mean_2d_viewer * add testing scripts * clean up; clarify on input format for time_slices * update testing scripts * update README.md for 3.1.0 new feature * Update documentation for v3.1.0 features and parameters This commit updates the documentation to reflect new features and parameters added in v3.1.0: 1. Updated available-parameters.rst: - Added time_slices parameter for snapshot analysis - Added lat_lon_native set-specific parameters (test_grid_file, ref_grid_file, antialiased) - Added test_file and ref_file parameters - Updated regrid_tool default from 'esmf' to 'xesmf' - Updated granulate default to include 'time_slices' - Updated sets default list to include all current diagnostic sets - Added notes about mutual exclusivity of time_slices and seasons 2. Updated examples.rst: - Added Example 8: Native Grid Visualization - Added Example 9: Snapshot Analysis for Core Sets - Updated running instructions to include new examples - Updated batch script example with ex8 and ex9 3. Created example files: - examples/ex8-native-grid-visualization/ (ex8.py, diags.cfg, README.md) - examples/ex9-snapshot-analysis/ (ex9.py, diags.cfg, README.md) These changes document the two major features introduced in v3.1.0: - Native grid visualization using UXarray - Snapshot analysis for core diagnostic sets using time_slices 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * fix examples; update default set for lat_lon_native * Refactor implementation of I/O for retrieving time-sliced datasets - Refactor drivers for polar, meriodional_mean_2d, zonal_mean_2d, zonal_mean_xy to use `driver.utils.io._get_xarray_datasets()` - Add `driver.io._get_xarray_datasets()` utility to simplify fetching of xarray datasets based on time selection - Update references to `season` to `time_selection` with `TimeSelection` annotation - Move `_set_time_slice_name_yrs_attrs()` back to `LatLonNativeParameter` because it is only used there -- consider refactoring later - Remove `time_slice.py` as this functions were converted to `CoreParameter` methods * Add unit tests - Test coverage for get_time_sliced_dataset(), _add_time_series_filepath_attr(), check_values(), and get_xarray_datasets()` * Fix method reference in lat_lon_native_driver.py * Update e3sm_diags/driver/lat_lon_driver.py Co-authored-by: Copilot <[email protected]> * Apply Copilot review suggestions * minor doc change --------- Co-authored-by: Claude <[email protected]> Co-authored-by: tomvothecoder <[email protected]> Co-authored-by: Copilot <[email protected]>
1 parent 6fec517 commit 813bc41

34 files changed

+1692
-290
lines changed

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,15 @@ The modernization improves performance, usability, and maintainability, paving t
5757
for future enhancements to E3SM development. The refactored codebase is now more robust
5858
and extensively covered by unit tests, setting a solid foundation for ongoing testing and development.
5959

60+
### New Features in v3.1.0
61+
62+
v3.1.0 introduces significant enhancements to support advanced grid analysis and temporal snapshot capabilities:
63+
64+
| Feature name <br />(set name) | Brief Introduction | Developers Contributors\* | Released version |
65+
| ------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------- | ---------------- |
66+
| Native grid visualization (lat_lon_native) | Support for plotting data on native grids (e.g., cubed-sphere, unstructured grids) using UXarray, enabling visualization without regridding to preserve native grid features | Jill Zhang, Tom Vo | 3.1.0 |
67+
| Snapshot analysis for core sets | Index-based time selection for snapshot analysis on core diagnostic sets (lat_lon, lat_lon_native, polar, zonal_mean_2d, meridional_mean_2d, zonal_mean_2d_stratosphere), allowing analysis of individual time steps instead of climatological means | Jill Zhang, Tom Vo | 3.1.0 |
68+
6069
### New Feature added during v2 development
6170

6271
| Feature name <br />(set name) | Brief Introduction | Developers Contributors\* | Released version |
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
[#]
2+
sets = ["lat_lon"]
3+
case_id = "model_vs_model"
4+
variables = ["T"]
5+
seasons = ["ANN", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "DJF", "MAM", "JJA", "SON"]
6+
plevs = [850.0]
7+
contour_levels = [240, 245, 250, 255, 260, 265, 270, 275, 280, 285, 290, 295]
8+
diff_levels = [-5, -4, -3, -2, -1, -0.5, -0.25, 0.25, 0.5, 1, 2, 3, 4, 5]
9+
regrid_method = "bilinear"
10+
11+
[#]
12+
sets = ["polar"]
13+
case_id = "model_vs_model"
14+
variables = ["T"]
15+
seasons = ["DJF", "MAM", "JJA", "SON"]
16+
regions = ["polar_S", "polar_N"]
17+
plevs = [850.0]
18+
contour_levels = [230, 240, 250, 260, 270, 280, 290, 300, 310]
19+
diff_levels = [-15, -10, -7.5, -5, -2.5, -1, 1, 2.5, 5, 7.5, 10, 15]
20+
21+
[#]
22+
sets = ["zonal_mean_2d"]
23+
case_id = "model_vs_model"
24+
variables = ["T"]
25+
seasons = ["ANN", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "DJF", "MAM", "JJA", "SON"]
26+
contour_levels = [180,185,190,200,210,220,230,240,250,260,270,280,290,295,300]
27+
diff_levels = [-3.0, -2.5, -2, -1.5, -1, -0.5, -0.25, 0.25, 0.5, 1, 1.5, 2, 2.5, 3.0]
28+
29+
[#]
30+
sets = ["zonal_mean_2d_stratosphere"]
31+
case_id = "model_vs_model"
32+
variables = ["T"]
33+
seasons = ["ANN", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "DJF", "MAM", "JJA", "SON"]
34+
contour_levels = [180,185,190,200,210,220,230,240,250,260,270,280,290,295,300]
35+
diff_levels = [-8, -6,-4,-2, -1, -0.5, 0.5, 1, 2, 4,6, 8]
36+
37+
[#]
38+
sets = ["zonal_mean_xy"]
39+
case_id = "model_vs_model"
40+
variables = ["T"]
41+
seasons = ["ANN", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "DJF", "MAM", "JJA", "SON"]
42+
plevs = [850.0]
43+
44+
[#]
45+
sets = ["meridional_mean_2d"]
46+
case_id = "model_vs_model"
47+
variables = ["T"]
48+
seasons = ["ANN", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "DJF", "MAM", "JJA", "SON"]
49+
contour_levels = [180,185,190,200,210,220,230,240,250,260,270,280,290,295,300]
50+
diff_levels = [-7,-6,-5,-4,-3,-2,-1,1,2,3,4,5,6,7]
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
#!/usr/bin/env python3
2+
"""
3+
This script runs e3sm_diags with the core sets to visualize snap-shot data.
4+
"""
5+
6+
import os
7+
import sys
8+
9+
from e3sm_diags.parameter.core_parameter import CoreParameter
10+
from e3sm_diags.run import runner
11+
12+
# Auto-detect username
13+
username = os.environ.get('USER', 'unknown_user')
14+
15+
# Create parameter objects for 3 different runs
16+
params = []
17+
18+
## (1) First test configuration
19+
#param1 = LatLonNativeParameter()
20+
#param1.results_dir = f"/lcrc/group/e3sm/public_html/diagnostic_output/{username}/tests/lat_lon_native_test_1"
21+
#param1.test_data_path = "/lcrc/group/e3sm/public_html/e3sm_diags_test_data/native_grid"
22+
#param1.test_name = "v3.LR.amip_0101"
23+
#param1.short_test_name = "v3.LR.amip_0101"
24+
#param1.reference_data_path = "/lcrc/group/e3sm/public_html/e3sm_diags_test_data/native_grid"
25+
#param1.ref_name = "v3.HR.test4"
26+
#param1.short_ref_name = "v3.HR.test4"
27+
#param1.seasons = ["DJF"]
28+
#param1.test_grid_file = "/lcrc/group/e3sm/diagnostics/grids/ne30pg2.nc"
29+
#param1.ref_grid_file = "/lcrc/group/e3sm/diagnostics/grids/ne120pg2.nc"
30+
#param1.case_id = "model_vs_model"
31+
#param1.run_type = "model_vs_model"
32+
#params.append(param1)
33+
#
34+
## (2) Second test configuration
35+
#param2 = LatLonNativeParameter()
36+
#param2.results_dir = f"/lcrc/group/e3sm/public_html/diagnostic_output/{username}/tests/lat_lon_native_test_2"
37+
#param2.test_data_path = "/lcrc/group/e3sm/public_html/e3sm_diags_test_data/native_grid"
38+
#param2.test_file = "v3.LR.amip_0101_DJF_climo.nc"
39+
#param2.short_test_name = "v3.LR.amip_0101"
40+
#param2.reference_data_path = "/lcrc/group/e3sm/public_html/e3sm_diags_test_data/native_grid"
41+
#param2.ref_file = "v3.HR.test4_DJF_climo.nc"
42+
#param2.short_ref_name = "v3.HR.test4"
43+
#param2.seasons = ["DJF"]
44+
#param2.test_grid_file = "/lcrc/group/e3sm/diagnostics/grids/ne30pg2.nc"
45+
#param2.ref_grid_file = "/lcrc/group/e3sm/diagnostics/grids/ne120pg2.nc"
46+
#param2.case_id = "model_vs_model"
47+
#param2.run_type = "model_vs_model"
48+
#params.append(param2)
49+
50+
# (3) Third test configuration
51+
param3 = CoreParameter()
52+
param3.results_dir = f"/lcrc/group/e3sm/public_html/diagnostic_output/{username}/tests/1013-snapshot-analysis-core-sets"
53+
param3.test_data_path = "/lcrc/group/e3sm/public_html/e3sm_diags_test_data/postprocessed_e3sm_v2_data_for_e3sm_diags/20210528.v2rc3e.piControl.ne30pg2_EC30to60E2r2.chrysalis/time-series/rgr"
54+
param3.test_file = "T_005101_006012.nc"
55+
param3.reference_data_path = "/lcrc/group/e3sm/public_html/e3sm_diags_test_data/postprocessed_e3sm_v2_data_for_e3sm_diags/20210528.v2rc3e.piControl.ne30pg2_EC30to60E2r2.chrysalis/time-series/rgr"
56+
param3.ref_file = "T_005101_006012.nc"
57+
param3.short_test_name = "v2 test"
58+
param3.short_ref_name = "v2 test"
59+
param3.time_slices = ["0","1"]
60+
param3.case_id = "model_vs_model"
61+
param3.run_type = "model_vs_model"
62+
params.append(param3)
63+
64+
# Run the single diagnostic, comment out for complete diagnostics.
65+
cfg_path = "auxiliary_tools/debug/1013-snapshot-analysis-core-sets/T.cfg"
66+
sys.argv.extend(["--diags", cfg_path])
67+
68+
runner.sets_to_run = ["lat_lon",
69+
"zonal_mean_xy",
70+
"zonal_mean_2d",
71+
"zonal_mean_2d_stratosphere",
72+
"polar",
73+
"meridional_mean_2d",]
74+
75+
# Run each test sequentially
76+
for i, param in enumerate(params, 1):
77+
print(f"\n{'='*60}")
78+
print(f"Running Test {i}: {param.results_dir}")
79+
print(f"{'='*60}")
80+
81+
# Create results directory
82+
if not os.path.exists(param.results_dir):
83+
os.makedirs(param.results_dir)
84+
85+
# Run the diagnostic
86+
runner.run_diags([param])
87+
print(f"Test {i} completed!")
88+
89+
print(f"\n{'='*60}")
90+
print("All tests completed!")
91+
print(f"{'='*60}")
92+
93+

docs/source/available-parameters.rst

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,18 @@ functionality of the diagnostics.
7070
- **regrid_method**: What regrid method of the regrid tool to use.
7171
Possible values are ``'linear'`` or ``'conservative'``. Default is ``'conservative'``.
7272
Read the xCDAT documentation on `regridding`_ for more information.
73-
- **regrid_tool**: The regrid tool to use. Default is ``'esmf'``.
73+
- **regrid_tool**: The regrid tool to use. Default is ``'xesmf'``.
7474
Read the xCDAT documentation on `regridding`_ for more information.
75+
**Note:** The ``lat_lon_native`` set does not use regridding, so this parameter is ignored for that set.
7576
- **seasons**: A list of season to use. Default is annual and all seasons: ``['ANN', 'DJF', 'MAM', 'JJA', 'SON']``.
77+
**Note:** This parameter is mutually exclusive with ``time_slices``. When using ``time_slices``, do not set ``seasons``.
78+
- **time_slices**: *(v3.1.0+)* A list of time indices for snapshot analysis. Examples: ``['0']``, ``['5']``, ``['0', '1', '2']``.
79+
Time slices are zero-based indices into the time dimension of the input dataset.
80+
This enables analysis of individual time steps instead of climatological means.
81+
**Note:** This parameter is mutually exclusive with ``seasons``. When using ``time_slices``, do not set ``seasons``.
82+
Supported sets: ``lat_lon``, ``lat_lon_native``, ``polar``, ``zonal_mean_xy``, ``zonal_mean_2d``, ``meridional_mean_2d``, ``zonal_mean_2d_stratosphere``.
7683
- **sets**: A list of the sets to be run. Default is all sets:
77-
``['zonal_mean_xy', 'zonal_mean_2d', 'meridional_mean_2d', 'lat_lon', 'polar', 'area_mean_time_series', 'cosp_histogram', 'enso_diags', 'qbo', 'streamflow','diurnal_cycle']``.
84+
``['zonal_mean_xy', 'zonal_mean_2d', 'zonal_mean_2d_stratosphere', 'meridional_mean_2d', 'lat_lon', 'lat_lon_native', 'polar', 'area_mean_time_series', 'cosp_histogram', 'enso_diags', 'qbo', 'streamflow', 'diurnal_cycle', 'arm_diags', 'tc_analysis', 'annual_cycle_zonal_mean', 'lat_lon_land', 'lat_lon_river', 'aerosol_aeronet', 'aerosol_budget']``.
7885
- **variables**: What variable(s) to use for this run. Ex: ``variables=["T", "PRECT"]``.
7986

8087
.. _regridding: https://xcdat.readthedocs.io/en/latest/getting-started-guide/faqs.html#regridding
@@ -262,12 +269,30 @@ You can specify both ``test_end_yr`` and ``ref_end_yr`` or just ``end_yr``.
262269
- **plot_log_plevs**: Log-scale the y-axis. Default ``False``.
263270
- **plot_plevs**: Plot the pressure levels. Default ``False``.
264271

272+
``'lat_lon_native'`` *(v3.1.0+)*:
273+
274+
- **test_grid_file**: *(Required)* Path to the grid file for test data in UGRID format (e.g., ``'/path/to/ne30pg2.nc'``).
275+
The grid file defines the native grid structure used by UXarray for visualization.
276+
- **ref_grid_file**: Path to the grid file for reference data in UGRID format (e.g., ``'/path/to/ne30pg2.nc'``).
277+
Required for model vs model comparisons. Can be omitted for model-only runs.
278+
- **antialiased**: Apply antialiasing to the plot. Default ``False``. Setting to ``True`` may improve visual quality but can impact performance.
279+
- **time_slices**: Time indices for snapshot analysis (same as in core parameters). See ``time_slices`` description above.
280+
281+
**Notes for lat_lon_native:**
282+
283+
- Native grid visualization requires UXarray (included in E3SM Unified environment)
284+
- Grid files must be in UGRID format
285+
- Regridding parameters (``regrid_tool``, ``regrid_method``) are ignored for this set
286+
- Can use either ``seasons`` for climatology or ``time_slices`` for snapshot analysis (mutually exclusive)
265287

266288
Other parameters
267289
~~~~~~~~~~~~~~~~
268290

269291
- **dataset**: Default is ``''``.
270-
- **granulate**: Default is ``['variables', 'seasons', 'plevs', 'regions']``.
292+
- **granulate**: Default is ``['variables', 'seasons', 'plevs', 'regions', 'time_slices']``.
293+
This parameter controls how diagnostics are split into separate runs.
271294
- **selectors**: Default is ``['sets', 'seasons']``. See :ref:`Using the selectors parameter <selector-ex>`.
272295
- **viewer_descr**: Used to specify values in the viewer. Default ``{}``.
273296
- **fail_on_incomplete**: Exit status will reflect failure if any parameter fails to complete. Default is ``False`` (e.g., a failing parameter will not create a failing exit code).
297+
- **test_file**: *(v3.1.0+)* Specify the exact file name for test data. Useful for snapshot analysis with ``time_slices`` or when using specific data files.
298+
- **ref_file**: *(v3.1.0+)* Specify the exact file name for reference data. Useful for snapshot analysis with ``time_slices`` or when using specific data files.

docs/source/examples.rst

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,38 @@ on two different sets: ``zonal_mean_2d`` an ``lat_lon``.
9393
so you can compare different version of the data, or the same variable from different datasets.
9494
We are comparing CERES EBAF TOA version 2.8 and 4.0.
9595

96+
8. Native Grid Visualization (v3.1.0)
97+
--------------------------------------
98+
`This example <https://github.com/E3SM-Project/e3sm_diags/tree/master/examples/ex8-native-grid-visualization>`__ demonstrates how to visualize model data on its native grid
99+
(e.g., cubed-sphere, unstructured grids) without regridding to a regular lat-lon grid.
100+
This feature uses UXarray to preserve native grid features and is particularly useful for high-resolution models with complex grid structures.
101+
The example shows model vs model comparison using snapshot analysis on native grids.
102+
103+
**Key features:**
104+
105+
- Visualize data on native grids without regridding
106+
- Preserve native grid features and characteristics
107+
- Support for cubed-sphere and unstructured grids
108+
- Uses UXarray for grid-aware operations
109+
110+
9. Snapshot Analysis for Core Sets (v3.1.0)
111+
--------------------------------------------
112+
`This example <https://github.com/E3SM-Project/e3sm_diags/tree/master/examples/ex9-snapshot-analysis>`__ demonstrates time slice analysis on core diagnostic sets.
113+
Instead of computing climatological seasonal means, this analyzes individual time steps from model output using index-based time selection.
114+
115+
This is useful for analyzing specific events, comparing model states at particular time points,
116+
or understanding temporal evolution without time averaging. The example shows how to use the ``time_slices`` parameter
117+
on multiple diagnostic sets (lat_lon, zonal_mean_2d, polar, meridional_mean_2d, zonal_mean_2d_stratosphere).
118+
119+
**Key features:**
120+
121+
- Index-based time selection (e.g., time_slices = ["0", "1", "2"])
122+
- Analyze individual time steps without temporal averaging
123+
- Event-based or process-oriented diagnostics
124+
- Works across multiple core diagnostic sets
125+
126+
**Note:** ``time_slices`` and ``seasons`` parameters are mutually exclusive.
127+
96128
Running the Examples
97129
====================
98130

@@ -117,7 +149,7 @@ The parameters file contains information related to the location
117149
of the data, what years to run the diagnostics on, what plots to create, and more.
118150

119151
The configuration file provides information about the diagnostics you are running.
120-
This is used in Ex.4,5,7.
152+
This is used in Ex.4, 5, 7, 8, 9.
121153

122154
Parameters for each example can be found in
123155
`this directory <https://github.com/E3SM-Project/e3sm_diags/tree/master/examples>`__.
@@ -134,7 +166,7 @@ Use the code below to run the diagnostics.
134166
salloc --nodes 1 --qos interactive --time 01:00:00 --constraint cpu --account=e3sm
135167
# Enter the E3SM Unified environment. For Perlmutter CPU, the command to do this is:
136168
source /global/common/software/e3sm/anaconda_envs/load_latest_e3sm_unified_pm-cpu.sh
137-
# Running Ex.1. For examples 4,5,7 append ``-d diags.cfg``.
169+
# Running Ex.1. For examples 4, 5, 7, 8, 9 append ``-d diags.cfg``.
138170
python ex1.py --multiprocessing --num_workers=32
139171
# You may need to change permissions on your web directory to see the example output.
140172
chmod -R 755 <your web directory>
@@ -174,6 +206,8 @@ These were generated with the following script:
174206
# emacs ex5-model-vs-obs/ex5.py
175207
# emacs ex6-model-vs-obs-custom/ex6.py
176208
# emacs ex7-obs-vs-obs/ex7.py
209+
# emacs ex8-native-grid-visualization/ex8.py
210+
# emacs ex9-snapshot-analysis/ex9.py
177211
178212
source /global/common/software/e3sm/anaconda_envs/load_latest_e3sm_unified_pm-cpu.sh
179213
cd ex1-model_ts-vs-model_ts
@@ -187,9 +221,13 @@ These were generated with the following script:
187221
cd ../ex5-model-vs-obs
188222
python ex5.py --multiprocessing --num_workers=32 -d diags.cfg
189223
cd ../ex6-model-vs-obs-custom
190-
python ex6.py --multiprocessing --num_workers=32
224+
python ex6.py
191225
cd ../ex7-obs-vs-obs
192-
python ex7.py --multiprocessing --num_workers=32 -d diags.cfg
226+
python ex7.py -d diags.cfg
227+
cd ../ex8-native-grid-visualization
228+
python ex8.py -d diags.cfg
229+
cd ../ex9-snapshot-analysis
230+
python ex9.py -d diags.cfg
193231
cd ../
194232
195233
chmod -R 755 /global/cfs/cdirs/e3sm/www/forsyth/examples

0 commit comments

Comments
 (0)