-
Notifications
You must be signed in to change notification settings - Fork 34
New Feature: Support plotting native grid data in lat_lon plots #968
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
0d033db to
18771b7
Compare
|
To see that you're working on this makes me so happy! |
Great to hear!! I know you've been a strong advocate for this feature in standard analysis and I was going to reach out to you about the variables and regions we should normally look at, especially with checkerboard issue in mind.. Or maybe we should just support the same set of regular lat-lon variables (i.e. PRECT, PRECC, TREFT and surface fluxes etc.), but add additional regions in addition to global maps? |
I've found that precip and liquid water path (TGCLDLWP) are good variables for visualizing the checkerboard issue. The surface variables like reference temperature and latent/sensible flux usually don't exhibit small scale grid noise, but it wouldn't hurt to include those. Global maps seem fine. Maybe in HR cases we might want regional maps to focus on specific issues like the precip biases around central America, but we can add that as the need arises. |
458b14a to
4605fac
Compare
tomvothecoder
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @chengzhuzhang, I made some initial comments for review. Can you provide update the paths in the scripts so that I can run it? They are currently local paths to your machine.
Once I can run the code, I can do a deeper dive in my review and look at refactoring opportunities.
| "TGCLDLWP": OrderedDict( | ||
| [ | ||
| ( | ||
| ("TGCLDLWP",), | ||
| lambda x: convert_units(x, target_units="g/m^2"), | ||
| ), | ||
| ( | ||
| ("LiqWaterPath",), | ||
| lambda x: convert_units(x, target_units="g/m^2"), | ||
| ), # EAMxx | ||
| ] | ||
| ), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replace with regular dictionary
conda-env/dev.yml
Outdated
| - numpy >=2.0.0,<3.0.0 | ||
| - pywavelets | ||
| - scipy | ||
| - uxarray >=2023.3.0,<2025.6.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason why we're constraining <2025.6.0 here? Also ci.yml doesn't have this constraint.
|
|
||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| contour_levels = [-170, -150, -135, -120, -105, -90, -75, -60, -45, -30, -15, 0, 15, 30, 45] | ||
| diff_levels = [-30, -25, -20, -15, -10, -5, -2, 2, 5, 10, 15, 20, 25, 30] | ||
|
|
||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| contour_levels = [-100, -75, -50, -25, -10, 0, 10, 25, 50, 75, 100, 125, 150] | ||
| diff_levels = [-75, -50, -25, -10, -5, -2, 2, 5, 10, 25, 50, 75] | ||
|
|
||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
@tomvothecoder thank you for starting the initial review. I have a new commit to push the run script and cfg file for testing. |
|
Hey @chengzhuzhang, are you aiming to get this feature in a new version before the upcoming E3SM Unified release? Or does it require more work over a longer timeline? This helps me understand the task priority. I'll review again once Chrysalis is back online. |
|
@tomvothecoder I think this PR is ready, please help review. in the mean time, I will do more testing as well. |
Apologies for not getting back to you sooner about this. We have deprecated the This feature will be released on Tuesday in our September release, in addition to some other Matplotlib/Cartopy plotting improvements UXARRAY/uxarray#1354 |
|
@philipc2 thank you for confirming and for the additional information on new plotting improvement. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR adds support for plotting native grid data in lat_lon plots to address visualization requirements for detecting patterns (e.g., checkerboard) that can only be detected on native grids. The feature provides standard tests for modelers to view lat-lon representations of native grid fields alongside seasonal average lat-lon images.
Key changes:
- New
lat_lon_nativediagnostic set with plotting capabilities for unstructured grid data - Command-line interface and configuration support for native grid visualization
- Model-only and model-vs-model comparison support
Reviewed Changes
Copilot reviewed 24 out of 25 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| e3sm_diags/plot/lat_lon_native_plot.py | Core plotting functionality for native grid visualization using uxarray |
| e3sm_diags/driver/lat_lon_native_driver.py | Driver logic for native grid diagnostics and data processing |
| e3sm_diags/parameter/lat_lon_native_parameter.py | Parameter class with native grid-specific configuration options |
| pyproject.toml | Added uxarray dependency and data file configuration |
| e3sm_diags/viewer/ | Updated viewer components to support lat_lon_native diagnostic set |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
Hi @chengzhuzhang, I am nearly done refactoring and reviewing this PR. I just have the driver and plotter left. I will test my code changes with the full run, push the commit when ready, and tag you for another review + test run on your end. |
add testing script and cfg file Move METRICS_DEFAULT_VALUE to /driver/__init__.py Refactor `default_viewer.py` and `main.py` Move `run_native_grid_test.py` to `debug/968-native-grid-vis` Refactor `lat_lon_native_parameter.py` and `core_parameter.py` - Update type annotations, re-order methods in `LatLonNativeParameter` class Add a comment for granulation in `core_parser.py` Extract code from LatLonNativeDriver into NativeDataset class - Move `TimeSlice` and `TimeSelection` into `type_annotations.py` and update all references Add type annotations and comments Add fixme and todo comments in driver and plotter Update run script to use single run
5c3a5c8 to
0233432
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@chengzhuzhang, here is my PR review. I currently have a full test run going with these changes. I will report back with the status soon.
EDIT: Full run complete here: https://web.lcrc.anl.gov/public/e3sm/diagnostic_output/ac.tvo/tests/lat_lon_native_file/viewer/index.html
I think it is important to refactor lat_lon_native_plot.py to re-use existing utilities, as there is a lot of repeated code from the plotter utilities. I left FIXME comments in that file to section off parts that should be refactored. I currently don't have bandwidth to dive deeper to refactor this file.
Changes:
- Extracted
NativeDatasetclass fromlat_lon_native_driver.pyto store native-grid related functionalities and removed unused functions (e.g., metrics functions, processing test dataset) - Added FIXME comments through
lat_lon_native_driver.pyandlat_lon_native_plot.pyto refactor code and re-use utilities - Refactored methods in
class Datasetwhich now reference new methods inCoreParameter
| test_ds = NativeDataset(parameter, data_type="test") | ||
| ref_ds = NativeDataset(parameter, data_type="ref") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use NativeDataset class instead of Dataset class.
| # ------------------------------------------------------------ | ||
| # FIXME: Metrics extraction for test, ref, and diff datasets are duplicated, | ||
| # extract to a helper function. | ||
| # ------------------------------------------------------------ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FIXME
| # ------------------------------------------------------------ | ||
| # FIXME: Metrics extraction for test, ref, and diff datasets are duplicated, | ||
| # extract to a helper function. | ||
| # ------------------------------------------------------------ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FIXME:
| # ------------------------------------------------------------ | ||
| # FIXME: Metrics extraction for test, ref, and diff datasets are duplicated, | ||
| # extract to a helper function. | ||
| # ------------------------------------------------------------ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FIXME:
| # ------------------------------------------------------------ | ||
| # FIXME: Re-use utils.add_rmse_corr_text here | ||
| # ------------------------------------------------------------ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FIXME:
| # TODO: What is this supposed to do? Just check if the variables | ||
| # can be derived? It returns a bool but the return value is never | ||
| # used downstream. | ||
| test_ds._process_variable_derivations(var_key) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@chengzhuzhang What is this supposed to do?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This explicit call in the driver actually derive variables which is not covered by dataset_native class. The comment is changed to Apply variable derivations if needed.
| # TODO: What is this supposed to do? Just check if the variables | ||
| # can be derived? It returns a bool but the return value is never | ||
| # used downstream. | ||
| ref_ds._process_variable_derivations(var_key) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is this supposed to do?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as above but for reference data.
| class NativeDataset: | ||
| """ | ||
| A class for handling native grid datasets using xarray for raw data | ||
| and uxarray for grid-aware operations. | ||
| NOTE: NativeDataset uses composition instead of inheritance to wrap Dataset | ||
| with additional native-grid specific functionalities. It does not inherit | ||
| from Dataset to avoid confusion with existing Dataset methods and prevent | ||
| tight coupling. If needed, we can refactor to inherit from Dataset or | ||
| create a parent abstract class in the future. | ||
| """ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note about this new class.
| A class for handling native grid datasets using xarray for raw data | ||
| and uxarray for grid-aware operations. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO: Add unit tests for this class.
| def _add_time_series_file_path_attr( | ||
| self, | ||
| data_type: Literal["test", "ref"], | ||
| ds: xr.Dataset, | ||
| ): | ||
| """Add file path attributes to the parameter object. | ||
| Parameters | ||
| ---------- | ||
| data_type : Literal["test", "ref"] | ||
| The type of data, either "test" or "ref". | ||
| ds : xr.Dataset | ||
| The dataset object containing the file path attribute. | ||
| Raises | ||
| ------ | ||
| ValueError | ||
| If `data_type` is not "test" or "ref". | ||
| """ | ||
| if data_type not in {"test", "ref"}: | ||
| raise ValueError("data_type must be either 'test' or 'ref'.") | ||
|
|
||
| file_path_attr = f"{data_type}_data_file_path" | ||
|
|
||
| setattr(self, file_path_attr, getattr(ds, "file_path", "Unknown")) | ||
|
|
||
| def _add_climatology_file_path_attr( | ||
| self, | ||
| data_type: Literal["test", "ref"], | ||
| filepath: str | None = None, | ||
| ): | ||
| """Add file path attributes to the parameter object. | ||
| Parameters | ||
| ---------- | ||
| data_type : Literal["test", "ref"] | ||
| The type of data, either "test" or "ref". | ||
| filepath : str | None, optional | ||
| The file path for climatology data. | ||
| Raises | ||
| ------ | ||
| ValueError | ||
| If `data_type` is not "test" or "ref". | ||
| ValueError | ||
| If `filepath` is not provided for climatology data. | ||
| """ | ||
| if data_type not in {"test", "ref"}: | ||
| raise ValueError("data_type must be either 'test' or 'ref'.") | ||
|
|
||
| file_path_attr = f"{data_type}_data_file_path" | ||
|
|
||
| if not filepath: | ||
| raise ValueError("Filepath must be provided for climatology data.") | ||
|
|
||
| setattr(self, file_path_attr, os.path.abspath(filepath)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New methods in CoreParameter used in class Dataset
|
@tomvothecoder thanks for helping reviewing and refactoring the code! I tested with a couple of configuration and had a minor fix for the case of using season |
| Parameters | ||
| ---------- | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
… into native_grids_viz
|
Merging for a release candidate test of e3sm_unified. |
Description
This feature is to address one of the new feature code review requirement: certain patterns (e.g., checkerboard) can only be detected on native grids. Developers have individual approaches/scripts for this capability. The code review required standard tests to provide a lat-lon view of a subset of these fields for the modeler to view along with standard seasonal average lat-lon images. Details see (internal E3SM doc):
https://acme-climate.atlassian.net/wiki/spaces/EIDMG/pages/3330179146/Native+Grid+Visualization
This PR will start with adding template scripts; and make the capability available through e3sm_diags command-line, as well as run script.
Checklist
If applicable: