Skip to content

Commit 78dca67

Browse files
philipc2rajeeja
andauthored
Latitude & Longitude Interval Cross Section, Updated Bounding Box Subset (#1115)
* update bounds subset, add latitude and longitude interval cross section * update notebook and function sig * docstrings, cleanup * update test * update TODO blurbs * update notebook --------- Co-authored-by: Rajeev Jain <[email protected]>
1 parent 17e84a4 commit 78dca67

File tree

12 files changed

+648
-272
lines changed

12 files changed

+648
-272
lines changed

docs/api.rst

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,10 @@ Grid
325325

326326
Grid.cross_section
327327
Grid.cross_section.constant_latitude
328+
Grid.cross_section.constant_longitude
329+
Grid.cross_section.constant_latitude_interval
330+
Grid.cross_section.constant_longitude_interval
331+
328332

329333
UxDataArray
330334
~~~~~~~~~~~
@@ -335,7 +339,9 @@ UxDataArray
335339

336340
UxDataArray.cross_section
337341
UxDataArray.cross_section.constant_latitude
338-
342+
UxDataArray.cross_section.constant_longitude
343+
UxDataArray.cross_section.constant_latitude_interval
344+
UxDataArray.cross_section.constant_longitude_interval
339345
Remapping
340346
---------
341347

docs/user-guide/cross-sections.ipynb

Lines changed: 97 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,14 @@
77
"source": [
88
"# Cross-Sections\n",
99
"\n",
10-
"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"
10+
"This section demonstrates how to extract cross-sections from an unstructured grid using UXarray, which allows the analysis and visualization across slices of grids. Cross-sections can be performed directly on a `ux.Grid` object or on a `ux.UxDataArray`\n"
1111
]
1212
},
1313
{
1414
"cell_type": "code",
1515
"execution_count": null,
1616
"id": "b35ba4a2c30750e4",
17-
"metadata": {
18-
"ExecuteTime": {
19-
"start_time": "2024-10-14T16:39:35.957687Z"
20-
},
21-
"jupyter": {
22-
"is_executing": true
23-
}
24-
},
17+
"metadata": {},
2518
"outputs": [],
2619
"source": [
2720
"import uxarray as ux\n",
@@ -33,24 +26,11 @@
3326
"projection = ccrs.Robinson()"
3427
]
3528
},
36-
{
37-
"cell_type": "markdown",
38-
"id": "395a3db7-495c-4cff-b733-06bbe522a604",
39-
"metadata": {},
40-
"source": [
41-
"## Data"
42-
]
43-
},
4429
{
4530
"cell_type": "code",
4631
"execution_count": null,
4732
"id": "b4160275c09fe6b0",
48-
"metadata": {
49-
"ExecuteTime": {
50-
"end_time": "2024-10-09T17:50:51.217211Z",
51-
"start_time": "2024-10-09T17:50:50.540946Z"
52-
}
53-
},
33+
"metadata": {},
5434
"outputs": [],
5535
"source": [
5636
"base_path = \"../../test/meshfiles/ugrid/outCSne30/\"\n",
@@ -66,44 +46,29 @@
6646
")"
6747
]
6848
},
69-
{
70-
"cell_type": "code",
71-
"execution_count": null,
72-
"id": "c844a3b5-ef71-41c8-a0ae-02ea937801d6",
73-
"metadata": {},
74-
"outputs": [],
75-
"source": [
76-
"uxds.uxgrid.normalize_cartesian_coordinates()"
77-
]
78-
},
7949
{
8050
"cell_type": "markdown",
8151
"id": "a7a40958-0a4d-47e4-9e38-31925261a892",
8252
"metadata": {},
8353
"source": [
8454
"## Constant Latitude\n",
8555
"\n",
86-
"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"
56+
"Cross-sections along constant latitude lines can be obtained by using the ``.cross_section.constant_latitude(lat)`` method. The sliced grid will be made up of the faces that contain at least one edge that intersects with a line of constant latitude.\n"
8757
]
8858
},
8959
{
9060
"cell_type": "markdown",
9161
"id": "2fbe9f6e5bb59a17",
9262
"metadata": {},
9363
"source": [
94-
"For example, we can obtain a cross-section at 30 degrees latitude by doing the following:"
64+
"For example, we can obtain a cross-section at 0 degrees latitude by doing the following:"
9565
]
9666
},
9767
{
9868
"cell_type": "code",
9969
"execution_count": null,
10070
"id": "3775daa1-2f1d-4738-bab5-2b69ebd689d9",
101-
"metadata": {
102-
"ExecuteTime": {
103-
"end_time": "2024-10-09T17:50:53.093314Z",
104-
"start_time": "2024-10-09T17:50:53.077719Z"
105-
}
106-
},
71+
"metadata": {},
10772
"outputs": [],
10873
"source": [
10974
"lat = 0\n",
@@ -167,8 +132,7 @@
167132
"## Constant Longitude\n",
168133
"\n",
169134
"\n",
170-
"\n",
171-
"Cross-sections along constant longitude lines can be obtained using the ``.cross_section.constant_longitude`` method, available for both ``ux.Grid`` and ``ux.DataArray`` objects. \n"
135+
"Cross-sections along constant longitude lines can be obtained using the ``.cross_section.constant_longitude(lon)`` method. The sliced grid will be made up of the faces that contain at least one edge that intersects with a line of constant longitude.\n"
172136
]
173137
},
174138
{
@@ -205,6 +169,94 @@
205169
")"
206170
]
207171
},
172+
{
173+
"cell_type": "markdown",
174+
"id": "5044b8680d514fdc",
175+
"metadata": {},
176+
"source": [
177+
"## Constant Latitude Interval\n",
178+
"\n",
179+
"Cross-sections between two lines of latitudes can be obtained using the ``.cross_section.constant_lats_interval(lats)`` method. The sliced grid will contain faces that are strictly between the latitude interval."
180+
]
181+
},
182+
{
183+
"cell_type": "code",
184+
"execution_count": null,
185+
"id": "fc84e47efe2edf96",
186+
"metadata": {},
187+
"outputs": [],
188+
"source": [
189+
"lats = [-20, 20]\n",
190+
"\n",
191+
"uxda_constant_lat_interval = uxds[\"psi\"].cross_section.constant_latitude_interval(lats)"
192+
]
193+
},
194+
{
195+
"cell_type": "code",
196+
"execution_count": null,
197+
"id": "60232626ba6c74ad",
198+
"metadata": {},
199+
"outputs": [],
200+
"source": [
201+
"(\n",
202+
" uxda_constant_lat_interval.plot(\n",
203+
" rasterize=False,\n",
204+
" backend=\"bokeh\",\n",
205+
" cmap=\"inferno\",\n",
206+
" projection=projection,\n",
207+
" global_extent=True,\n",
208+
" coastline=True,\n",
209+
" title=f\"Cross Section between {lats[0]} and {lats[1]} degrees latitude\",\n",
210+
" periodic_elements=\"split\",\n",
211+
" )\n",
212+
" * gf.grid(projection=projection)\n",
213+
")"
214+
]
215+
},
216+
{
217+
"cell_type": "markdown",
218+
"id": "4afa3d891a80c597",
219+
"metadata": {},
220+
"source": [
221+
"## Constant Longitude Interval\n",
222+
"\n",
223+
"Cross-sections between two lines of longitude can be obtained using the ``.cross_section.constant_lons_interval(lons)`` method. The sliced grid will contain faces that are strictly between the longitude interval.\n"
224+
]
225+
},
226+
{
227+
"cell_type": "code",
228+
"execution_count": null,
229+
"id": "b183d15838aaf6bb",
230+
"metadata": {},
231+
"outputs": [],
232+
"source": [
233+
"lons = [-25, 25]\n",
234+
"\n",
235+
"uxda_constant_lon_interval = uxds[\"psi\"].cross_section.constant_longitude_interval(lats)"
236+
]
237+
},
238+
{
239+
"cell_type": "code",
240+
"execution_count": null,
241+
"id": "22793d56701504ce",
242+
"metadata": {},
243+
"outputs": [],
244+
"source": [
245+
"(\n",
246+
" uxda_constant_lon_interval.plot(\n",
247+
" rasterize=False,\n",
248+
" backend=\"bokeh\",\n",
249+
" cmap=\"inferno\",\n",
250+
" projection=projection,\n",
251+
" global_extent=True,\n",
252+
" coastline=True,\n",
253+
" title=f\"Cross Section between {lons[0]} and {lons[1]} degrees longitude\",\n",
254+
" periodic_elements=\"split\",\n",
255+
" )\n",
256+
" * gf.grid(projection=projection)\n",
257+
")"
258+
]
259+
},
208260
{
209261
"cell_type": "markdown",
210262
"id": "54d9eff1-67f1-4691-a3b0-1ee0c874c98f",
@@ -219,7 +271,7 @@
219271
"metadata": {},
220272
"source": [
221273
"```{warning}\n",
222-
"Arbitrary great circle arc cross sections are not yet supported.\n",
274+
"Arbitrary great circle arc cross sections are not yet implemented.\n",
223275
"```"
224276
]
225277
}
@@ -240,7 +292,7 @@
240292
"name": "python",
241293
"nbconvert_exporter": "python",
242294
"pygments_lexer": "ipython3",
243-
"version": "3.11.8"
295+
"version": "3.12.3"
244296
}
245297
},
246298
"nbformat": 4,

docs/user-guide/subset.ipynb

Lines changed: 2 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -256,20 +256,6 @@
256256
"lat_bounds = (41.8781 - 2, 41.8781 + 2)"
257257
]
258258
},
259-
{
260-
"cell_type": "markdown",
261-
"metadata": {
262-
"collapsed": false,
263-
"jupyter": {
264-
"outputs_hidden": false
265-
}
266-
},
267-
"source": [
268-
"Our bounding box ensures that the coordinates of our select element (`nodes`, `edge_centers`, or `face_centers`) are within the defined bounding box range.\n",
269-
"\n",
270-
"Below is an example using the corner nodes for our subset."
271-
]
272-
},
273259
{
274260
"cell_type": "code",
275261
"execution_count": null,
@@ -282,7 +268,8 @@
282268
"outputs": [],
283269
"source": [
284270
"bbox_subset_nodes = uxds[\"relhum_200hPa\"][0].subset.bounding_box(\n",
285-
" lon_bounds, lat_bounds, element=\"nodes\"\n",
271+
" lon_bounds,\n",
272+
" lat_bounds,\n",
286273
")\n",
287274
"\n",
288275
"bbox_subset_nodes.plot(\n",
@@ -294,58 +281,6 @@
294281
") * features"
295282
]
296283
},
297-
{
298-
"cell_type": "markdown",
299-
"metadata": {
300-
"collapsed": false,
301-
"jupyter": {
302-
"outputs_hidden": false
303-
}
304-
},
305-
"source": [
306-
"And similarly using the face center coordinates."
307-
]
308-
},
309-
{
310-
"cell_type": "code",
311-
"execution_count": null,
312-
"metadata": {
313-
"collapsed": false,
314-
"jupyter": {
315-
"outputs_hidden": false
316-
}
317-
},
318-
"outputs": [],
319-
"source": [
320-
"bbox_subset_faces = uxds[\"relhum_200hPa\"][0].subset.bounding_box(\n",
321-
" lon_bounds, lat_bounds, element=\"face centers\"\n",
322-
")\n",
323-
"\n",
324-
"bbox_subset_faces.plot(\n",
325-
" rasterize=True,\n",
326-
" periodic_elements=\"exclude\",\n",
327-
" clim=clim,\n",
328-
" title=\"Bounding Box Subset (Face Center Query)\",\n",
329-
" **plot_opts,\n",
330-
") * features"
331-
]
332-
},
333-
{
334-
"cell_type": "markdown",
335-
"metadata": {
336-
"collapsed": false,
337-
"jupyter": {
338-
"outputs_hidden": false
339-
}
340-
},
341-
"source": [
342-
"While the bounding box is generally the same, you will notice differences along the border depending on which element is used to query.\n",
343-
"\n",
344-
":::{note}\n",
345-
"Specifying which element to query (i.e. ``nodes``, ``edgecenters``, or ``face centers``) is supported by all subsetting methods.\n",
346-
":::"
347-
]
348-
},
349284
{
350285
"cell_type": "markdown",
351286
"metadata": {

0 commit comments

Comments
 (0)