-
Notifications
You must be signed in to change notification settings - Fork 31
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
Fast Constant Latitude Cross Sections #989
Merged
Merged
Changes from all commits
Commits
Show all changes
33 commits
Select commit
Hold shift + click to select a range
42e3036
initial work on fast cross-sections
philipc2 5c8d9d5
add API
philipc2 aeb544b
add section for cross sections
philipc2 a2b247f
parallel numba
philipc2 82e49ea
update notebook
philipc2 79958f6
Merge branch 'main' into philipc2/vectorized-cross-sections
philipc2 b5965e6
add docstrings
philipc2 46b72f9
Merge branch 'philipc2/vectorized-cross-sections' of https://github.c…
philipc2 d2f0a86
add benchmark
philipc2 995bc97
update benchmark
philipc2 ac64eeb
update quad hex grid
philipc2 8376f17
add tests
philipc2 d539dee
update tests
philipc2 0174977
update quad hex grid
philipc2 f35b999
update name of intersection func
philipc2 2adbcde
update value error
philipc2 b769d67
update user guide
philipc2 b974436
add docstring for uxda
philipc2 c1d0538
update docstring of intersections
philipc2 d2ab10f
fix benchmark
philipc2 884139e
Merge branch 'main' into philipc2/vectorized-cross-sections
philipc2 32dde5f
add tests for north and south pole
philipc2 0362afe
Merge branch 'main' into philipc2/vectorized-cross-sections
philipc2 d7c9714
Update intersections.py
philipc2 9178f0f
Merge branch 'main' into philipc2/vectorized-cross-sections
philipc2 67f19d9
Merge branch 'main' into philipc2/vectorized-cross-sections
philipc2 07db497
update user guide
philipc2 4d4d167
Merge branch 'main' into philipc2/vectorized-cross-sections
philipc2 61f6383
Delete docs/user-guide/grid.nc
philipc2 5dbb557
use accessor
philipc2 7b78daa
update notebook
philipc2 abf2ba1
merge main
philipc2 9f862e5
fix docs
philipc2 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,208 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "markdown", | ||
"id": "4a432a8bf95d9cdb", | ||
"metadata": {}, | ||
"source": [ | ||
"# Cross-Sections\n", | ||
"\n", | ||
"This section demonstrates how to extract cross-sections from an unstructured grid using UXarray, which allows the analysis and visualization across slices of grids.\n" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "b35ba4a2c30750e4", | ||
"metadata": { | ||
"ExecuteTime": { | ||
"end_time": "2024-10-09T17:50:50.244285Z", | ||
"start_time": "2024-10-09T17:50:50.239653Z" | ||
} | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"import uxarray as ux\n", | ||
"import geoviews.feature as gf\n", | ||
"\n", | ||
"import cartopy.crs as ccrs\n", | ||
"import geoviews as gv\n", | ||
"\n", | ||
"projection = ccrs.Robinson()" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "395a3db7-495c-4cff-b733-06bbe522a604", | ||
"metadata": {}, | ||
"source": [ | ||
"## Data" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "b4160275c09fe6b0", | ||
"metadata": { | ||
"ExecuteTime": { | ||
"end_time": "2024-10-09T17:50:51.217211Z", | ||
"start_time": "2024-10-09T17:50:50.540946Z" | ||
} | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"base_path = \"../../test/meshfiles/ugrid/outCSne30/\"\n", | ||
"grid_path = base_path + \"outCSne30.ug\"\n", | ||
"data_path = base_path + \"outCSne30_vortex.nc\"\n", | ||
"\n", | ||
"uxds = ux.open_dataset(grid_path, data_path)\n", | ||
"uxds[\"psi\"].plot(\n", | ||
" cmap=\"inferno\",\n", | ||
" periodic_elements=\"split\",\n", | ||
" projection=projection,\n", | ||
" title=\"Global Plot\",\n", | ||
")" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "a7a40958-0a4d-47e4-9e38-31925261a892", | ||
"metadata": {}, | ||
"source": [ | ||
"## Constant Latitude\n", | ||
"\n", | ||
"Cross-sections along constant latitude lines can be obtained using the ``.cross_section.constant_latitude`` method, available for both ``ux.Grid`` and ``ux.DataArray`` objects. This functionality allows users to extract and analyze slices of data at specified latitudes, providing insights into variations along horizontal sections of the grid.\n" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "2fbe9f6e5bb59a17", | ||
"metadata": {}, | ||
"source": [ | ||
"For example, we can obtain a cross-section at 30 degrees latitude by doing the following:" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "3775daa1-2f1d-4738-bab5-2b69ebd689d9", | ||
"metadata": { | ||
"ExecuteTime": { | ||
"end_time": "2024-10-09T17:50:53.093314Z", | ||
"start_time": "2024-10-09T17:50:53.077719Z" | ||
} | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"lat = 30\n", | ||
"\n", | ||
"uxda_constant_lat = uxds[\"psi\"].cross_section.constant_latitude(lat)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "dcec0b96b92e7f4", | ||
"metadata": {}, | ||
"source": [ | ||
"Since the result is a new ``UxDataArray``, we can directly plot the result to see the cross-section." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "484b77a6-86da-4395-9e63-f5ac56e37deb", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"(\n", | ||
" uxda_constant_lat.plot(\n", | ||
" rasterize=False,\n", | ||
" backend=\"bokeh\",\n", | ||
" cmap=\"inferno\",\n", | ||
" projection=projection,\n", | ||
" global_extent=True,\n", | ||
" coastline=True,\n", | ||
" title=f\"Cross Section at {lat} degrees latitude\",\n", | ||
" )\n", | ||
" * gf.grid(projection=projection)\n", | ||
")" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "c7cca7de4722c121", | ||
"metadata": {}, | ||
"source": [ | ||
"You can also perform operations on the cross-section, such as taking the mean." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "1cbee722-34a4-4e67-8e22-f393d7d36c99", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"print(f\"Global Mean: {uxds['psi'].data.mean()}\")\n", | ||
"print(f\"Mean at {lat} degrees lat: {uxda_constant_lat.data.mean()}\")" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "c4a7ee25-0b60-470f-bab7-92ff70563076", | ||
"metadata": {}, | ||
"source": [ | ||
"## Constant Longitude" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "9fcc8ec5-c6a8-4bde-a33d-7f37f9116ee2", | ||
"metadata": {}, | ||
"source": [ | ||
"```{warning}\n", | ||
"Constant longitude cross sections are not yet supported.\n", | ||
"```" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "54d9eff1-67f1-4691-a3b0-1ee0c874c98f", | ||
"metadata": {}, | ||
"source": [ | ||
"## Arbitrary Great Circle Arc (GCA)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "ea94ff9f-fe86-470d-813b-45f32a633ffc", | ||
"metadata": {}, | ||
"source": [ | ||
"```{warning}\n", | ||
"Arbitrary great circle arc cross sections are not yet supported.\n", | ||
"```" | ||
] | ||
} | ||
], | ||
"metadata": { | ||
"kernelspec": { | ||
"display_name": "Python 3 (ipykernel)", | ||
"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.8" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 5 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import uxarray as ux | ||
import pytest | ||
from pathlib import Path | ||
import os | ||
|
||
import numpy.testing as nt | ||
|
||
# Define the current path and file paths for grid and data | ||
current_path = Path(os.path.dirname(os.path.realpath(__file__))) | ||
quad_hex_grid_path = current_path / 'meshfiles' / "ugrid" / "quad-hexagon" / 'grid.nc' | ||
quad_hex_data_path = current_path / 'meshfiles' / "ugrid" / "quad-hexagon" / 'data.nc' | ||
|
||
cube_sphere_grid = current_path / "meshfiles" / "geos-cs" / "c12" / "test-c12.native.nc4" | ||
|
||
|
||
|
||
class TestQuadHex: | ||
"""The quad hexagon grid contains four faces. | ||
|
||
Top Left Face: Index 1 | ||
|
||
Top Right Face: Index 2 | ||
|
||
Bottom Left Face: Index 0 | ||
|
||
Bottom Right Face: Index 3 | ||
|
||
The top two faces intersect a constant latitude of 0.1 | ||
|
||
The bottom two faces intersect a constant latitude of -0.1 | ||
|
||
All four faces intersect a constant latitude of 0.0 | ||
""" | ||
|
||
def test_constant_lat_cross_section_grid(self): | ||
uxgrid = ux.open_grid(quad_hex_grid_path) | ||
|
||
grid_top_two = uxgrid.cross_section.constant_latitude(lat=0.1) | ||
|
||
assert grid_top_two.n_face == 2 | ||
|
||
grid_bottom_two = uxgrid.cross_section.constant_latitude(lat=-0.1) | ||
|
||
assert grid_bottom_two.n_face == 2 | ||
|
||
grid_all_four = uxgrid.cross_section.constant_latitude(lat=0.0) | ||
|
||
assert grid_all_four.n_face == 4 | ||
|
||
with pytest.raises(ValueError): | ||
# no intersections found at this line | ||
uxgrid.cross_section.constant_latitude(lat=10.0) | ||
|
||
|
||
def test_constant_lat_cross_section_uxds(self): | ||
uxds = ux.open_dataset(quad_hex_grid_path, quad_hex_data_path) | ||
|
||
da_top_two = uxds['t2m'].cross_section.constant_latitude(lat=0.1) | ||
|
||
nt.assert_array_equal(da_top_two.data, uxds['t2m'].isel(n_face=[1, 2]).data) | ||
|
||
da_bottom_two = uxds['t2m'].cross_section.constant_latitude(lat=-0.1) | ||
|
||
nt.assert_array_equal(da_bottom_two.data, uxds['t2m'].isel(n_face=[0, 3]).data) | ||
|
||
da_all_four = uxds['t2m'].cross_section.constant_latitude(lat=0.0) | ||
|
||
nt.assert_array_equal(da_all_four.data , uxds['t2m'].data) | ||
|
||
with pytest.raises(ValueError): | ||
# no intersections found at this line | ||
uxds['t2m'].cross_section.constant_latitude(lat=10.0) | ||
|
||
|
||
class TestGeosCubeSphere: | ||
def test_north_pole(self): | ||
uxgrid = ux.open_grid(cube_sphere_grid) | ||
|
||
lats = [89.85, 89.9, 89.95, 89.99] | ||
|
||
for lat in lats: | ||
cross_grid = uxgrid.cross_section.constant_latitude(lat=lat) | ||
# Cube sphere grid should have 4 faces centered around the pole | ||
assert cross_grid.n_face == 4 | ||
|
||
def test_south_pole(self): | ||
uxgrid = ux.open_grid(cube_sphere_grid) | ||
|
||
lats = [-89.85, -89.9, -89.95, -89.99] | ||
|
||
for lat in lats: | ||
cross_grid = uxgrid.cross_section.constant_latitude(lat=lat) | ||
# Cube sphere grid should have 4 faces centered around the pole | ||
assert cross_grid.n_face == 4 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
from .dataarray_accessor import UxDataArrayCrossSectionAccessor | ||
from .grid_accessor import GridCrossSectionAccessor | ||
|
||
__all__ = ( | ||
"GridCrossSectionAccessor", | ||
"UxDataArrayCrossSectionAccessor", | ||
) |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Please add some test case when lattitude is around pole area,
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.
I've added tests for both poles for a cube-sphere grid.