|
1 | 1 | """ |
2 | | -Calculating and plotting the divergence of sea current vectors |
3 | | -============================================================== |
| 2 | +Calculating and plotting the divergence of sea currents |
| 3 | +======================================================= |
4 | 4 |
|
5 | 5 | In this recipe, we will calculate the divergence of depth-averaged |
6 | 6 | currents in the Irish Sea, then plot the divergence as a contour |
7 | | -fill plot underneath the vectors themselves in a vector plot. |
| 7 | +fill plot underneath the vectors themselves in the form of a vector plot. |
8 | 8 | """ |
9 | 9 |
|
| 10 | +# %% |
| 11 | +# 1. Import cf-python and cf-plot: |
10 | 12 | import cfplot as cfp |
11 | 13 | import cf |
12 | 14 |
|
13 | | -f = cf.read("~/recipes_break/new/POLCOMS_WAM_ZUV_01_16012006.nc") |
14 | | -print(f) |
| 15 | +# %% |
| 16 | +# 2. Read the fields in: |
| 17 | +f = cf.read( |
| 18 | + "~/summerstudents/final-recipes/new-required-datasets/POLCOMS_WAM_ZUV_01_16012006.nc") |
15 | 19 |
|
16 | | -# Get separate vector components |
| 20 | +# %% |
| 21 | +# 3. Get the separate vector components, which are stored as separate fields. |
| 22 | +# The first, 'u', corresponds to the eastward component and the second, 'v', |
| 23 | +# the northward component: |
17 | 24 | u = f[0] |
18 | 25 | v = f[1] |
19 | | -print(u) |
20 | | -print(v) |
21 | 26 |
|
22 | | -# First get rid of the ocean sigma coord size 1 axis |
| 27 | +# %% |
| 28 | +# 4. Squeeze the fields to remove the size 1 axes in each case: |
23 | 29 | u = u.squeeze() |
24 | 30 | v = v.squeeze() |
25 | 31 |
|
26 | | -# Now we need to use some means to condense the u and v fields in the same way into |
27 | | -# having 1 time point, not 720 - for example we can just pick a time value out: |
28 | | -print("Times are", v.construct("T").data.datetime_as_string) |
29 | | -chosen_time = "2006-01-15 23:30:00" # 720 choices to choose from! |
30 | | -v_1 = v.subspace(T=cf.dt(chosen_time)) |
| 32 | +# %% |
| 33 | +# 5. Consider the currents at a set point in time. To do this we |
| 34 | +# select one of the 720 datetime sample points in the fields to |
| 35 | +# investigate, in this case by subspacing to pick out a particular |
| 36 | +# datetime value we saw within the time coordinate data of the field (but |
| 37 | +# you could also use indexing or filtering to select a specific value). |
| 38 | +# Once we subspace to one datetime, we squeeze out the size 1 time axis |
| 39 | +# in each case: |
| 40 | +chosen_time = "2006-01-15 23:30:00" # 720 choices to pick from, try this one! |
31 | 41 | u_1 = u.subspace(T=cf.dt(chosen_time)) |
32 | | -v_1 = v_1.squeeze() |
| 42 | +v_1 = v.subspace(T=cf.dt(chosen_time)) |
33 | 43 | u_1 = u_1.squeeze() |
34 | | -print(u_1) |
35 | | -print(v_1) |
36 | | - |
37 | | -# Are now in a plottable form! Let's give it a go: |
38 | | -### cfp.vect(u=u_1, v=v_1) |
39 | | -# Need to play around with the relative length and spacing of the vectors, using these paramters: |
40 | | -###cfp.vect(u=u_1, v=v_1, key_length=10, scale=50, stride=2) |
41 | | - |
42 | | -# Note that there appear to be some really large vectors all pointing in the |
43 | | -# same direction which are spamming the plot. We need to remove these. By |
44 | | -# looking at the data we can see what these are and work out how to remove them: |
45 | | - |
46 | | -# ... shows more of the array |
47 | | - |
48 | | -# Can see there are lots of -9999 values, seemingly used as a fill/placeholder value |
49 | | -# so we need to remove those so we can plot the menaingful vectors |
50 | | -# Apply steps to mask the -9999 fill values, which spam the plot, to x_1 |
51 | | -u_2 = u_1.where(cf.lt(-9e+03), cf.masked) |
52 | | -v_2 = v_1.where(cf.lt(-9e+03), cf.masked) |
53 | | -print(u_2) |
54 | | -print(v_2) |
55 | | - |
56 | | -# We can even plot the final field, effective wave height, as the |
57 | | -# background contour! |
58 | | -w = f[2] |
59 | | -w_1 = w.subspace(T=cf.dt(chosen_time)) |
60 | | -# This field also needs masking for those data points. |
61 | | -w_2 = w_1.where(cf.lt(-9e+03), cf.masked) |
62 | | -print(w_2) |
| 44 | +v_1 = v_1.squeeze() |
63 | 45 |
|
| 46 | +# %% |
| 47 | +# 6. |
| 48 | +# When inspecting the u and v fields using cf inspection methods such as |
| 49 | +# from print(u_1.data) and u_1.data.dump(), for example, we can see that there are |
| 50 | +# lots of -9999 values in their data array, apparently used as a |
| 51 | +# fill/placeholder value, including to indicate undefined data over the land. |
| 52 | +# In order for these to not skew the data and dominate the plot, we need |
| 53 | +# to mask values matching this, so that only meaningful values remain. |
| 54 | +u_2 = u_1.where(cf.lt(-9000), cf.masked) |
| 55 | +v_2 = v_1.where(cf.lt(-9000), cf.masked) |
64 | 56 |
|
65 | | -# Plot divergence in the background |
| 57 | +# %% |
| 58 | +# 7. Calculate the divergence using the 'div_xy' function operating on the |
| 59 | +# vector eastward and northward components as the first and second argument |
| 60 | +# respectively. We need to calculate this for the latitude-longitude plane |
| 61 | +# of the Earth, defined in spherical polar coordinates, so we must specify |
| 62 | +# the Earth's radius for the appropriate calculation: |
66 | 63 | div = cf.div_xy(u_2, v_2, radius="earth") |
67 | 64 |
|
68 | | - |
69 | | -# Our final basic plot: |
70 | | -cfp.mapset(resolution="10m") # makes UK coastline more high-res |
71 | | -cfp.gopen(file=f"irish-sea-currents-with-divergence-{chosen_time}.png") |
| 65 | +# %% |
| 66 | +# 8. Generate the final plot. First we configure the overall plot by |
| 67 | +# making the map higher resolution, to show the coastlines of the UK and |
| 68 | +# Ireland in greater detail, and changing the colourmap to better reflect |
| 69 | +# the data which can be positive or negative, i.e. has 0 as the 'middle' |
| 70 | +# value of significance, so should use a diverging colour map. Then we |
| 71 | +# plot the current vectors, noting we had to play around with the 'stride' |
| 72 | +# and 'scale' parameter values to adjust the vector spacing and size so that |
| 73 | +# the vector field is best represented and visible without over-cluttering |
| 74 | +# the plot. Finally we plot the divergence as a contour plot without any |
| 75 | +# lines showing. This compound plot is saved on one canvas using 'gopen' |
| 76 | +# and 'gclose' to wrap the two plotting calls: |
| 77 | +cfp.mapset(resolution="10m") |
72 | 78 | cfp.cscale("ncl_default") |
| 79 | +cfp.gopen( |
| 80 | + file=f"irish-sea-currents-divergence-{chosen_time.replace(' ', '-')}.png") |
73 | 81 | cfp.vect(u=u_2, v=v_2, stride=6, scale=3, key_length=1) |
74 | 82 | cfp.con( |
75 | 83 | div, |
76 | 84 | lines=False, |
77 | 85 | title=( |
78 | | - f"Depth-averaged Irish Sea currents at {chosen_time} " |
79 | | - "with their divergence shown" |
| 86 | + f"Depth-averaged Irish Sea currents at {chosen_time} with " |
| 87 | + "their divergence" |
80 | 88 | ) |
81 | 89 | ) |
82 | 90 | cfp.gclose() |
0 commit comments