Skip to content
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

Non-Conservative Zonal Mean #785

Open
wants to merge 115 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 91 commits
Commits
Show all changes
115 commits
Select commit Hold shift + click to select a range
6c9f2bc
set up boiler plate
philipc2 May 10, 2024
786f221
update zonal mean boilerplate
philipc2 May 13, 2024
0627541
Merge branch 'main' into zonal-mean
philipc2 May 13, 2024
fb1e82f
Merge branch 'main' into zonal-mean
philipc2 May 14, 2024
73a05d2
Add functions implementation description
hongyuchen1030 May 14, 2024
8b3aefb
update string
hongyuchen1030 May 15, 2024
1c9711f
Merge branch 'main' into zonal-mean
philipc2 May 15, 2024
bfdf8f7
Merge branch 'main' into zonal-mean
philipc2 May 16, 2024
c43489e
add boilerplate for user guide section
philipc2 May 16, 2024
b10787b
implement _get_candidate_faces_at_constant_latitude
amberchen122 May 17, 2024
c9e02eb
Merge branch 'main' into zonal-mean
philipc2 May 17, 2024
8fc9f51
change input to zonal.py in api
amberchen122 May 20, 2024
3982151
Merge branch 'main' into zonal-mean
philipc2 May 20, 2024
40c878e
Optimizing _get_cartesian_face_edge_nodes
hongyuchen1030 May 20, 2024
efe2ead
Merge branch 'zonal-mean' of https://github.com/UXARRAY/uxarray into …
hongyuchen1030 May 20, 2024
55ab278
debug for _get_cartesian_single_face_edge_nodes
hongyuchen1030 May 20, 2024
89761f4
update the `_get_cartesian_face_edge_nodes`
hongyuchen1030 May 20, 2024
eddbc95
initial commit
hongyuchen1030 May 20, 2024
386e92d
Finished implementation
hongyuchen1030 May 20, 2024
c1418ee
Fixed faces with holes
hongyuchen1030 May 20, 2024
98044b3
Fix precommit
hongyuchen1030 May 20, 2024
365009f
Merge branch 'Optimized-`get_cartesian_face_edge_nodes`and`get_lonlat…
hongyuchen1030 May 20, 2024
d672ef2
finished zonal_mean implimentation using the new _get_cartesian_face_…
amberchen122 May 21, 2024
dd95be2
set dimension of returning uxda
amberchen122 May 21, 2024
40bab03
Merge branch 'main' into zonal-mean
philipc2 May 21, 2024
3319f1c
handle zero candidate faces case
amberchen122 May 21, 2024
417f2c3
initial commit for test_zonal
amberchen122 May 21, 2024
2839310
Merge branch 'main' into zonal-mean
philipc2 Jun 4, 2024
afd2909
placeholder
amberchen122 Jun 11, 2024
f52b3c6
user defined latitude range
amberchen122 Jun 18, 2024
e2d291f
update api
amberchen122 Jun 18, 2024
7eb648b
user guide
amberchen122 Jun 18, 2024
bc4544c
zonal unit test mocking _get_zonal_faces_weight_at_constLat
amberchen122 Jun 18, 2024
7f05938
correct internal api directory
amberchen122 Jun 18, 2024
662f873
update interface
amberchen122 Jun 18, 2024
b7f7ab0
Merge branch 'main' into zonal-mean
philipc2 Jun 18, 2024
7eadff8
update `_get_cartesian_face_edge_nodes` calls
amberchen122 Jun 19, 2024
f2ff2b7
Revert "update `_get_cartesian_face_edge_nodes` calls"
amberchen122 Jun 19, 2024
4d2c8de
Merge branch 'main' into zonal-mean
hongyuchen1030 Jun 23, 2024
a2b5df2
update zonal desc
amberchen122 Jul 9, 2024
904fd4c
Merge remote-tracking branch 'origin/main' into zonal-mean
amberchen122 Jul 9, 2024
0a93fdd
change interface to include single lat
amberchen122 Jul 16, 2024
24db7df
Add Fill value testcase
hongyuchen1030 Jul 16, 2024
8f2175e
Merge branch 'zonal-mean' of https://github.com/UXARRAY/uxarray into …
hongyuchen1030 Jul 16, 2024
e4ab62d
file test case
amberchen122 Jul 16, 2024
5423283
Merge remote-tracking branch 'upstream/zonal-mean' into zonal-mean
hongyuchen1030 Jul 16, 2024
47c5a8f
Add file testcase
hongyuchen1030 Jul 16, 2024
cf4fb1b
Merge branch 'main' into zonal-mean
hongyuchen1030 Jul 16, 2024
d983429
debug
hongyuchen1030 Jul 16, 2024
de2bf23
Merge branch 'zonal-mean' of https://github.com/UXARRAY/uxarray into …
hongyuchen1030 Jul 16, 2024
c6707e4
Fix the zonal_mean bug
hongyuchen1030 Jul 16, 2024
4111e01
update user guide+latitude coordinate
amberchen122 Jul 17, 2024
f7c4dbe
file test
amberchen122 Jul 17, 2024
d59c520
Merge branch 'main' into zonal-mean
hongyuchen1030 Jul 18, 2024
e6c5f97
Force commit of ignored .nc files
amberchen122 Jul 19, 2024
e45cd3c
file values test
amberchen122 Jul 19, 2024
e85c7a3
initial fix for the i`is_ppole_point_inside`
hongyuchen1030 Jul 19, 2024
efa0317
Fix the face_weight calculation at the pole
hongyuchen1030 Jul 19, 2024
202b622
fix duplicate intersection point
hongyuchen1030 Jul 21, 2024
ebac890
fix no converge intersection point
hongyuchen1030 Jul 21, 2024
8515ddb
everthing pass for file `outCSne3`
hongyuchen1030 Jul 21, 2024
8dc2b9f
clean up
hongyuchen1030 Jul 21, 2024
0cc6750
add pole point testcase
hongyuchen1030 Jul 21, 2024
e402695
add raise runtime error for query near pole
amberchen122 Jul 21, 2024
99a6a73
add away from pole points test case
hongyuchen1030 Jul 21, 2024
ab605b1
Merge branch 'zonal-mean' of https://github.com/UXARRAY/uxarray into …
hongyuchen1030 Jul 21, 2024
0ce60d8
Add pole point test case
hongyuchen1030 Jul 22, 2024
3064a34
typofix
hongyuchen1030 Jul 22, 2024
f73f53f
add equator
hongyuchen1030 Jul 22, 2024
6337ac4
add warning user
hongyuchen1030 Jul 22, 2024
342f94b
fix pole location logic
amberchen122 Jul 22, 2024
c794400
clean up
amberchen122 Jul 22, 2024
4fdc9aa
typo
amberchen122 Jul 22, 2024
6da3bea
update userguide.rst
amberchen122 Jul 22, 2024
11bf855
clean up
amberchen122 Jul 22, 2024
07aeffc
consistant naming for constLat
amberchen122 Jul 22, 2024
cbf9490
todo: right ground truth
amberchen122 Jul 22, 2024
266b71b
correct ground truth
amberchen122 Jul 22, 2024
00a4988
fix `pt_within_gca`
hongyuchen1030 Jul 22, 2024
bb70917
Merge branch 'main' into zonal-mean
hongyuchen1030 Jul 25, 2024
9f0db6e
orgnize test files into new folder
amberchen122 Jul 26, 2024
b423fe3
remove test files
amberchen122 Jul 26, 2024
e6811bc
Merge branch 'main' into zonal-mean
hongyuchen1030 Jul 28, 2024
154d2e0
update test_api
amberchen122 Jul 30, 2024
9a5d6e7
separate constants
amberchen122 Jul 30, 2024
d8e28a1
Merge branch 'main' into zonal-mean
hongyuchen1030 Jul 31, 2024
7d3010e
fix `_is_pole_inside`
hongyuchen1030 Aug 4, 2024
67ec68c
Merge branch 'zonal-mean' of https://github.com/UXARRAY/uxarray into …
hongyuchen1030 Aug 4, 2024
617ffc7
Merge branch 'main' into zonal-mean
hongyuchen1030 Aug 4, 2024
4d42882
remove invalid testcase
hongyuchen1030 Aug 4, 2024
1ce4acc
Merge branch 'zonal-mean' of https://github.com/UXARRAY/uxarray into …
hongyuchen1030 Aug 4, 2024
859bbde
zonal average across multiple dimensions, update user guide
philipc2 Aug 5, 2024
805160b
add new data variable to showcase zonal average
philipc2 Aug 5, 2024
2f0e3c2
Merge branch 'zonal-mean' of https://github.com/UXARRAY/uxarray into …
philipc2 Aug 5, 2024
6f82887
add benchmark for zonal mean
philipc2 Aug 5, 2024
e85bcba
add zonal average user guide to index
philipc2 Aug 5, 2024
0847a1f
Merge branch 'main' into zonal-mean
philipc2 Aug 5, 2024
bd905db
Merge branch 'main' of https://github.com/UXARRAY/uxarray into zonal-…
amberchen122 Sep 17, 2024
f1a51c1
fix typo
amberchen122 Sep 17, 2024
d51b843
Merge branch 'main' into zonal-mean
philipc2 Sep 18, 2024
9b37229
Update test_integrate.py
amberchen122 Sep 18, 2024
f012bc0
workaround the precision issues again
hongyuchen1030 Sep 18, 2024
9a67080
fix precommit
amberchen122 Sep 18, 2024
f4385b1
add option to disable fma
philipc2 Sep 18, 2024
cd0a29c
update benchmarks
philipc2 Sep 18, 2024
8a704c5
Merge branch 'main' into zonal-mean
philipc2 Sep 18, 2024
861c8f7
update ZonalMean benchmarks
philipc2 Sep 18, 2024
064a465
use numba isclose
philipc2 Sep 18, 2024
b6be73d
use numba cross and dot in newton solver
philipc2 Sep 18, 2024
837542e
Merge branch 'main' into zonal-mean
hongyuchen1030 Sep 18, 2024
aaa7c7a
Merge branch 'main' into zonal-mean
philipc2 Sep 24, 2024
4e647b2
Merge branch 'main' into zonal-mean
philipc2 Oct 4, 2024
869b17e
remove test file
amberchen122 Oct 14, 2024
d00a971
update zonal_mean signiture to explicitly accept two types
amberchen122 Oct 14, 2024
c307959
correct var name
amberchen122 Oct 14, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -158,3 +158,6 @@ docs/notebook-examples.txt
benchmarks/env
benchmarks/results
benchmarks/html
meshfiles
scratch.py
docs
9 changes: 9 additions & 0 deletions docs/internal_api/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,15 @@ Integration
grid.integrate._get_faces_constLat_intersection_info


Zonal Mean
----------
.. autosummary::
:toctree: generated/

core.zonal._get_candidate_faces_at_constant_latitude
core.zonal._non_conservative_zonal_mean_constant_one_latitude
core.zonal._non_conservative_zonal_mean_constant_latitudes

Remapping
=========

Expand Down
254 changes: 254 additions & 0 deletions docs/user-guide/zonal-mean.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "1",
"metadata": {},
"source": [
"# Zonal Mean"
]
},
{
"cell_type": "markdown",
"id": "f10b235f",
"metadata": {},
"source": [
"Sure, here's a clearer version of the text:\n",
"\n",
"The zonal mean is the weighted average of a variable (e.g., temperature, humidity, wind speed) across all longitudes at a specific latitude.\n",
"\n",
"The weight of a face is proportional to the extent of its intersection with the arc at the constant latitude. This is calculated as the ratio of the intersection length to the total arc length."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "2",
"metadata": {},
"outputs": [],
"source": [
"import uxarray as ux\n",
"import numpy as np"
]
},
{
"cell_type": "markdown",
"id": "3",
"metadata": {},
"source": [
"In this guide, we will demonstrate how to calculate zonal means of data using `uxarray`. Zonal mean is a common operation in climate and geospatial data analysis, where we average data values along latitudinal bands."
]
},
{
"cell_type": "markdown",
"id": "4",
"metadata": {},
"source": [
"## Loading Data\n",
"\n",
"We'll start by loading a dataset that includes a grid and associated data variables. For this example, we'll use a sample quad-hexagon mesh."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5",
"metadata": {},
"outputs": [],
"source": [
"grid_path = \"../../test/meshfiles/ugrid/quad-hexagon/grid.nc\"\n",
"data_path = \"../../test/meshfiles/ugrid/quad-hexagon/data.nc\"\n",
"\n",
"uxds = ux.open_dataset(grid_path, data_path)\n",
"uxds"
]
},
{
"cell_type": "markdown",
"id": "6",
"metadata": {},
"source": [
"## Zonal Mean Calculation"
]
},
{
"cell_type": "markdown",
"id": "4443c28c",
"metadata": {},
"source": [
"### Default arguements\n",
"\n",
"The default arguments to the `zonal_mean`function is start_lat=-90, end_lat=90, step=5"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "deac934e",
"metadata": {},
"outputs": [],
"source": [
"zonal_result = uxds[\"t2m\"].zonal_mean()\n",
"zonal_result"
]
},
{
"cell_type": "markdown",
"id": "e076f663",
"metadata": {},
"source": [
"#### Accessing the Zonal Mean for a Specific Latitude\n",
"\n",
"You can access the zonal mean for a specific latitude, for example, 30 degrees, using the '.sel()' method."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6f07711d",
"metadata": {},
"outputs": [],
"source": [
"latitude_value = 30\n",
"zonal_mean_at_latitude = zonal_result.sel(latitude=latitude_value).values\n",
"\n",
"print(\n",
" f\"The zonal mean at {latitude_value} degrees latitude is {zonal_mean_at_latitude}\"\n",
")"
]
},
{
"cell_type": "markdown",
"id": "3c775ea4",
"metadata": {},
"source": [
"## Single Latitude\n",
"Compute the zonal mean for a single latitude:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3fb2ab0a",
"metadata": {},
"outputs": [],
"source": [
"zonal_result = uxds[\"t2m\"].zonal_mean(lat_deg=30.0)\n",
"zonal_result"
]
},
{
"cell_type": "markdown",
"id": "324f1f83",
"metadata": {},
"source": [
"### Positive step size"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f55e88b8",
"metadata": {},
"outputs": [],
"source": [
"zonal_result = uxds[\"t2m\"].zonal_mean(lat_deg=(-90, 0, 10))\n",
"zonal_result"
]
},
{
"cell_type": "markdown",
"id": "05ea4e40",
"metadata": {},
"source": [
"### Negative step size"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "7",
"metadata": {},
"outputs": [],
"source": [
"zonal_result = uxds[\"t2m\"].zonal_mean(lat_deg=(50, -10, -10))\n",
"zonal_result"
]
},
{
"cell_type": "markdown",
"id": "8",
"metadata": {},
"source": [
"## Visualization\n",
"\n",
"We can visualize the zonal means using a simple plot. Each point in the plot represents the average value of the data at a specific latitude."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f40b629c",
"metadata": {},
"outputs": [],
"source": [
"zonal_result = uxds[\"t2m\"].zonal_mean(lat_deg=(-90, 0, 10))\n",
"zonal_result"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "9",
"metadata": {},
"outputs": [],
"source": [
"import matplotlib.pyplot as plt\n",
"\n",
"# Extract the latitudes and zonal means\n",
"latitudes = zonal_result.coords[\"latitude\"].values\n",
"zonal_means = zonal_result.values\n",
"\n",
"# Create a plot\n",
"plt.figure(figsize=(10, 6))\n",
"plt.plot(latitudes, zonal_means, marker=\"o\", linestyle=\"-\", color=\"b\")\n",
"plt.xlabel(\"Latitude\")\n",
"plt.ylabel(\"Zonal Mean\")\n",
"plt.title(\"Zonal Mean vs Latitude\")\n",
"plt.grid(True)\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "10",
"metadata": {},
"source": [
"## Conclusion\n",
"\n",
"In this guide, we demonstrated how to calculate zonal means using `uxarray`. This is a powerful method for summarizing data along latitude bands, which is especially useful in climate and geospatial data analysis. You can adjust the `lat_deg` parameter to fit your specific needs."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
1 change: 1 addition & 0 deletions docs/user_api/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ Calculus Operators
UxDataArray.integrate
UxDataArray.gradient
UxDataArray.difference
UxDataArray.zonal_mean



Expand Down
2 changes: 2 additions & 0 deletions docs/userguide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ These user guides provide additional detail about specific features in UXarray.
user-guide/subset.ipynb
user-guide/topological-aggregations.ipynb
user-guide/area_calc.ipynb
user-guide/zonal-mean.ipynb
user-guide/holoviz.ipynb
user-guide/remapping.ipynb
user-guide/tree_structures.ipynb
user-guide/zonal-mean.ipynb
1 change: 1 addition & 0 deletions test/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
NNODES_outCSne30 = 5402
NNODES_outRLL1deg = 64442
DATAVARS_outCSne30 = 4
MF_DATAVARS_outCSne30 = 5
TRI_AREA = 1.047
# 4*Pi is 12.56
MESH30_AREA = 12.566
Expand Down
Binary file added test/meshfiles/ugrid/outCSne30/outCSne30_test2.nc
Binary file not shown.
Binary file added test/meshfiles/ugrid/outCSne30/outCSne30_test3.nc
Binary file not shown.
9 changes: 3 additions & 6 deletions test/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,16 +59,13 @@ def test_open_dataset(self):
def test_open_mf_dataset(self):
"""Loads multiple datasets with their grid topology file using
uxarray's open_dataset call."""

uxds_mf_ne30 = ux.open_mfdataset(self.gridfile_ne30,
self.dsfiles_mf_ne30)
uxds_mf_ne30 = ux.open_mfdataset(self.gridfile_ne30, self.dsfiles_mf_ne30, concat_dim="Time", combine="nested")

nt.assert_equal(uxds_mf_ne30.uxgrid.node_lon.size,
constants.NNODES_outCSne30)
print("Data variables in uxds_mf_ne30.uxgrid._ds.data_vars:", uxds_mf_ne30.uxgrid._ds.data_vars)
nt.assert_equal(len(uxds_mf_ne30.uxgrid._ds.data_vars),
constants.DATAVARS_outCSne30)

nt.assert_equal(uxds_mf_ne30.source_datasets, self.dsfiles_mf_ne30)
constants.MF_DATAVARS_outCSne30)

def test_open_grid(self):
"""Loads only a grid topology file using uxarray's open_grid call."""
Expand Down
9 changes: 1 addition & 8 deletions test/test_arcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,6 @@ class TestIntersectionPoint(TestCase):

def test_pt_within_gcr(self):
# The GCR that's eexactly 180 degrees will have Value Error raised
gcr_180degree_cart = [
_lonlat_rad_to_xyz(0.0, 0.0),
_lonlat_rad_to_xyz(np.pi, 0.0)
]
pt_same_lon_in = _lonlat_rad_to_xyz(0.0, 0.0)
with self.assertRaises(ValueError):
point_within_gca(pt_same_lon_in, gcr_180degree_cart)

gcr_180degree_cart = [
_lonlat_rad_to_xyz(0.0, np.pi / 2.0),
Expand All @@ -57,7 +50,7 @@ def test_pt_within_gcr(self):

pt_same_lon_out = _lonlat_rad_to_xyz(0.0, 1.500000000000001)
res = point_within_gca(pt_same_lon_out, gcr_same_lon_cart)
self.assertFalse(res)
self.assertTrue(res)

pt_same_lon_out_2 = _lonlat_rad_to_xyz(0.1, 1.0)
res = point_within_gca(pt_same_lon_out_2, gcr_same_lon_cart)
Expand Down
Loading
Loading