Skip to content

Commit c0dd708

Browse files
authored
Merge pull request #215 from csiro-coasts/update-vector-examples
Update the vector plotting example to use newer functionality
2 parents 9b5da2f + 7b7d425 commit c0dd708

2 files changed

Lines changed: 49 additions & 44 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: 48 additions & 43 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()
2726

28-
# Plot the points
29-
figure = plt.figure(figsize=(8, 8), layout="constrained")
27+
# %%
28+
#
29+
# Plotting every cell is straight forward for small areas:
30+
31+
figure = plt.figure(figsize=(7, 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)