Skip to content

Commit 9aacf05

Browse files
committed
Update the vector plotting example to use newer functionality
It was based on some examples written before the geometry update and had not been fully adapted to the new API.
1 parent 9b5da2f commit 9aacf05

2 files changed

Lines changed: 48 additions & 43 deletions

File tree

docs/releases/development.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ Next release (in development)
1010
(:pr:`212`).
1111
* Add example showing
1212
:ref:`multiple ways of plotting vector data <sphx_glr_examples_plot-vector-methods.py>`
13-
(:pr:`213`).
13+
(:pr:`213`, :pr:`215`).
1414
* Add :attr:`.Grid.centroid_coordinates` attribute
1515
(:pr:`214`).

examples/plot-vector-methods.py

Lines changed: 47 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
In the `GBR4` tutorial dataset
88
the u and v variables contain the x and y components of the vector
99
for each cell in the dataset.
10-
Plotting every cell is straight forward for small areas:
1110
"""
1211

1312
import matplotlib.pyplot as plt
@@ -20,19 +19,23 @@
2019
from emsarray import plot
2120
from emsarray.operations import point_extraction
2221

23-
dataset_url = "https://thredds.nci.org.au/thredds/dodsC/fx3/gbr4_bgc_GBR4_H2p0_B3p1_Cfur_Dnrt/gbr4_bgc_simple_2024-01-16.nc"
24-
dataset = emsarray.open_dataset(dataset_url, decode_timedelta=False)
22+
dataset = emsarray.tutorial.open_dataset('gbr4')
2523

2624
surface_currents = dataset.ems.select_variables(["temp", "u", "v"]).isel(time=0, k=-1)
25+
surface_currents.load()
26+
27+
# %%
28+
#
29+
# Plotting every cell is straight forward for small areas:
2730

28-
# Plot the points
2931
figure = plt.figure(figsize=(8, 8), layout="constrained")
3032
axes = figure.add_subplot(projection=dataset.ems.data_crs)
31-
axes.set_title("Surface water temperature and currents near the Whitsundays")
33+
figure.suptitle("Surface water temperature and currents near the Whitsundays")
3234

3335
temp = surface_currents["temp"]
34-
temp.attrs['units'] = '°C'
35-
temp_artist = dataset.ems.make_artist(axes, temp, cmap="coolwarm", clim=(27, 30), edgecolor="face")
36+
temp_artist = dataset.ems.make_artist(
37+
axes, temp,
38+
cmap="coolwarm", clim=(24, 27))
3639

3740
current_artist = dataset.ems.make_artist(
3841
axes, (surface_currents["u"], surface_currents["v"]),
@@ -43,23 +46,18 @@
4346

4447
# Just show a small area over the Whitsundays
4548
view_box = box(148.7, -20.4, 149.6, -19.8)
46-
axes.set_extent(plot.bounds_to_extent(view_box.bounds))
4749
axes.set_aspect("equal", adjustable="datalim")
50+
axes.set_extent(plot.bounds_to_extent(view_box.bounds))
4851

4952
# %%
53+
#
5054
# Plotting the entire dataset this way leads to the current vectors becoming a confusing mess however:
5155

52-
dataset = emsarray.tutorial.open_dataset('gbr4')
53-
54-
surface_currents = dataset.ems.select_variables(["temp", "u", "v"]).isel(time=0, k=-1)
55-
56-
# Plot the points
57-
figure = plt.figure(figsize=(8, 10), layout="constrained")
56+
figure = plt.figure(figsize=(7, 10), layout="constrained")
5857
axes = figure.add_subplot(projection=dataset.ems.data_crs)
59-
axes.set_title("A bad plot of surface water temperature and currents over the entire reef")
58+
figure.suptitle("A bad plot of surface water temperature and currents over the entire reef")
6059

6160
temp = surface_currents["temp"]
62-
temp.attrs['units'] = '°C'
6361
temp_artist = dataset.ems.make_artist(axes, temp, cmap="coolwarm")
6462

6563
current_artist = dataset.ems.make_artist(
@@ -70,33 +68,38 @@
7068
plot.add_gridlines(axes)
7169

7270
# Show the entire model domain
73-
axes.autoscale()
7471
axes.set_aspect("equal", adjustable="datalim")
72+
axes.autoscale()
7573

7674
# %%
77-
# For gridded datasets like this we can sample the current data at regular intervals to display only a subset of the vectors:
78-
79-
dataset = emsarray.tutorial.open_dataset('gbr4')
80-
81-
# Make an empty array of the same shape as the data, then select every nth cell in there
82-
samples = xarray.DataArray(numpy.full(dataset.ems.grid_size[dataset.ems.default_grid_kind], False))
83-
samples = dataset.ems.wind(samples)
75+
#
76+
# Sampling gridded datasets
77+
# =========================
78+
#
79+
# For datasets on a two dimensional grid like this
80+
# we can sample the current data at regular intervals
81+
# to display only a subset of the vectors.
82+
# The sampled points will follow the geometry of the dataset.
83+
# For curvilinear datasets such as `GBR4` the vectors will follow the curves of the dataset shape:
84+
85+
# Make an empty array of the same shape as the data, then select every 10th cell in there.
86+
face_grid = dataset.ems.get_grid(surface_currents["u"])
87+
samples = xarray.DataArray(numpy.full(face_grid.size, False))
88+
samples = face_grid.wind(samples)
8489
samples[::10, ::10] = True
8590
samples = dataset.ems.ravel(samples)
8691

8792
# Select the (x, y) coordinates and the (u, v) components of the sampled cells
88-
surface_currents = dataset.ems.select_variables(["temp", "u", "v"]).isel(time=0, k=-1)
89-
x, y = dataset.ems.face_centres[samples].T
93+
x, y = face_grid.centroid_coordinates[samples].T
9094
u = dataset.ems.ravel(surface_currents["u"]).values[samples]
9195
v = dataset.ems.ravel(surface_currents["v"]).values[samples]
9296

9397
# Plot the points
94-
figure = plt.figure(figsize=(8, 10), layout="constrained")
98+
figure = plt.figure(figsize=(7, 10), layout="constrained")
9599
axes = figure.add_subplot(projection=dataset.ems.data_crs)
96-
axes.set_title("Surface water temperature and currents across the entire model domain")
100+
figure.suptitle("Surface water temperature and currents across the entire dataset domain")
97101

98102
temp = surface_currents["temp"]
99-
temp.attrs['units'] = '°C'
100103
temp_artist = dataset.ems.make_artist(axes, temp, cmap="coolwarm")
101104

102105
quiver = plt.quiver(
@@ -108,15 +111,21 @@
108111
plot.add_gridlines(axes)
109112

110113
# Show the entire model domain
111-
axes.autoscale()
112114
axes.set_aspect("equal", adjustable="datalim")
115+
axes.autoscale()
113116

114117
# %%
115-
# Another approach is to plot vectors at regular points across the domain. This means that the vector locations are not tied to the grid geometry.
116-
117-
dataset = emsarray.tutorial.open_dataset('gbr4')
118-
119-
# Generate a mesh of points across the model domain
118+
#
119+
# Sampling the dataset domain
120+
# ===========================
121+
#
122+
# Another approach is to plot vectors at regular points across the dataset domain
123+
# by sampling at regular intervals.
124+
# The vector locations are not tied to the grid geometry.
125+
# This approach will work with unstructured grids unlike the previous method.
126+
# :func:`.point_extraction.extract_dataframe` can be used for this:
127+
128+
# Generate a mesh of points across the dataset domain
120129
domain = box(*dataset.ems.bounds)
121130
x = numpy.arange(domain.bounds[0], domain.bounds[2], 0.4)
122131
y = numpy.arange(domain.bounds[1], domain.bounds[3], 0.4)
@@ -127,18 +136,15 @@
127136
})
128137

129138
# Extract the surface current components at these locations
130-
surface_currents = dataset.ems.select_variables(["temp", "u", "v"]).isel(time=0, k=-1)
131-
surface_currents.load()
132139
components = point_extraction.extract_dataframe(
133140
surface_currents, points, ('x', 'y'), missing_points='drop')
134141

135142
# Plot the points
136-
figure = plt.figure(figsize=(8, 10), layout="constrained")
143+
figure = plt.figure(figsize=(7, 10), layout="constrained")
137144
axes = figure.add_subplot(projection=dataset.ems.data_crs)
138-
axes.set_title("Surface water temperature and currents across the entire model domain")
145+
figure.suptitle("Surface water temperature and currents across the entire dataset domain")
139146

140147
temp = surface_currents["temp"]
141-
temp.attrs['units'] = '°C'
142148
temp_artist = dataset.ems.make_artist(axes, temp, cmap="coolwarm")
143149

144150
quiver = plt.quiver(
@@ -149,6 +155,5 @@
149155
plot.add_coast(axes)
150156
plot.add_gridlines(axes)
151157

152-
axes.autoscale()
153158
axes.set_aspect("equal", adjustable="datalim")
154-
159+
axes.autoscale()

0 commit comments

Comments
 (0)