|
7 | 7 | In the `GBR4` tutorial dataset |
8 | 8 | the u and v variables contain the x and y components of the vector |
9 | 9 | for each cell in the dataset. |
10 | | -Plotting every cell is straight forward for small areas: |
11 | 10 | """ |
12 | 11 |
|
13 | 12 | import matplotlib.pyplot as plt |
|
20 | 19 | from emsarray import plot |
21 | 20 | from emsarray.operations import point_extraction |
22 | 21 |
|
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') |
25 | 23 |
|
26 | 24 | 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: |
27 | 30 |
|
28 | | -# Plot the points |
29 | 31 | figure = plt.figure(figsize=(8, 8), layout="constrained") |
30 | 32 | 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") |
32 | 34 |
|
33 | 35 | 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)) |
36 | 39 |
|
37 | 40 | current_artist = dataset.ems.make_artist( |
38 | 41 | axes, (surface_currents["u"], surface_currents["v"]), |
|
43 | 46 |
|
44 | 47 | # Just show a small area over the Whitsundays |
45 | 48 | view_box = box(148.7, -20.4, 149.6, -19.8) |
46 | | -axes.set_extent(plot.bounds_to_extent(view_box.bounds)) |
47 | 49 | axes.set_aspect("equal", adjustable="datalim") |
| 50 | +axes.set_extent(plot.bounds_to_extent(view_box.bounds)) |
48 | 51 |
|
49 | 52 | # %% |
| 53 | +# |
50 | 54 | # Plotting the entire dataset this way leads to the current vectors becoming a confusing mess however: |
51 | 55 |
|
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") |
58 | 57 | 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") |
60 | 59 |
|
61 | 60 | temp = surface_currents["temp"] |
62 | | -temp.attrs['units'] = '°C' |
63 | 61 | temp_artist = dataset.ems.make_artist(axes, temp, cmap="coolwarm") |
64 | 62 |
|
65 | 63 | current_artist = dataset.ems.make_artist( |
|
70 | 68 | plot.add_gridlines(axes) |
71 | 69 |
|
72 | 70 | # Show the entire model domain |
73 | | -axes.autoscale() |
74 | 71 | axes.set_aspect("equal", adjustable="datalim") |
| 72 | +axes.autoscale() |
75 | 73 |
|
76 | 74 | # %% |
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) |
84 | 89 | samples[::10, ::10] = True |
85 | 90 | samples = dataset.ems.ravel(samples) |
86 | 91 |
|
87 | 92 | # 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 |
90 | 94 | u = dataset.ems.ravel(surface_currents["u"]).values[samples] |
91 | 95 | v = dataset.ems.ravel(surface_currents["v"]).values[samples] |
92 | 96 |
|
93 | 97 | # Plot the points |
94 | | -figure = plt.figure(figsize=(8, 10), layout="constrained") |
| 98 | +figure = plt.figure(figsize=(7, 10), layout="constrained") |
95 | 99 | 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") |
97 | 101 |
|
98 | 102 | temp = surface_currents["temp"] |
99 | | -temp.attrs['units'] = '°C' |
100 | 103 | temp_artist = dataset.ems.make_artist(axes, temp, cmap="coolwarm") |
101 | 104 |
|
102 | 105 | quiver = plt.quiver( |
|
108 | 111 | plot.add_gridlines(axes) |
109 | 112 |
|
110 | 113 | # Show the entire model domain |
111 | | -axes.autoscale() |
112 | 114 | axes.set_aspect("equal", adjustable="datalim") |
| 115 | +axes.autoscale() |
113 | 116 |
|
114 | 117 | # %% |
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 |
120 | 129 | domain = box(*dataset.ems.bounds) |
121 | 130 | x = numpy.arange(domain.bounds[0], domain.bounds[2], 0.4) |
122 | 131 | y = numpy.arange(domain.bounds[1], domain.bounds[3], 0.4) |
|
127 | 136 | }) |
128 | 137 |
|
129 | 138 | # 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() |
132 | 139 | components = point_extraction.extract_dataframe( |
133 | 140 | surface_currents, points, ('x', 'y'), missing_points='drop') |
134 | 141 |
|
135 | 142 | # Plot the points |
136 | | -figure = plt.figure(figsize=(8, 10), layout="constrained") |
| 143 | +figure = plt.figure(figsize=(7, 10), layout="constrained") |
137 | 144 | 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") |
139 | 146 |
|
140 | 147 | temp = surface_currents["temp"] |
141 | | -temp.attrs['units'] = '°C' |
142 | 148 | temp_artist = dataset.ems.make_artist(axes, temp, cmap="coolwarm") |
143 | 149 |
|
144 | 150 | quiver = plt.quiver( |
|
149 | 155 | plot.add_coast(axes) |
150 | 156 | plot.add_gridlines(axes) |
151 | 157 |
|
152 | | -axes.autoscale() |
153 | 158 | axes.set_aspect("equal", adjustable="datalim") |
154 | | - |
| 159 | +axes.autoscale() |
0 commit comments