High Frequency doppler Radars

See background review. Also, see presentation.

In this lecture, we will explore further how to plot vector maps in python.

[1]:
import numpy as np
import scipy.io as sio
import matplotlib.pyplot as plt
import pandas as pd
from datetime import datetime, timedelta

# add mapping routines
import cartopy.crs as ccrs
import cartopy.feature as cf
import matplotlib.ticker as mticker
from cartopy.mpl.gridliner import LONGITUDE_FORMATTER, LATITUDE_FORMATTER

First, we will load the matlab binary file “hfr_2011.mat” using the scipy.io routine (loaded above as sio).

[2]:
# primary data set, south Oahu
hfr = sio.loadmat('/home/ocn463-data/hfr/hfr_2011.mat')

It contains:

Name, Size, Bytes, Class

README 1x122 244 char
T 8760x1 70080 double
U 32x39x8760 87459840 double
V 32x39x8760 87459840 double
X 32x39 9984 double
Y 32x39 9984 double
coast 1831x2 29296 double

Like netcdf files, matlab files can be explored by just typing in the file name.

[3]:
hfr

[3]:
{'__header__': b'MATLAB 5.0 MAT-file, Platform: GLNXA64, Created on: Wed Apr 27 11:16:15 2022',
 '__version__': '1.0',
 '__globals__': [],
 'coast': array([[-157.6503,   21.3079],
        [-157.6493,   21.3068],
        [-157.6493,   21.3054],
        ...,
        [-157.6517,   21.3093],
        [-157.6507,   21.3083],
        [-157.6503,   21.3079]]),
 'T': array([[734504.02083291],
        [734504.06249957],
        [734504.10416624],
        ...,
        [734868.89583155],
        [734868.93749821],
        [734868.97916488]]),
 'X': array([[nan, nan, nan, ..., nan, nan, nan],
        [nan, nan, nan, ..., nan, nan, nan],
        [nan, nan, nan, ..., nan, nan, nan],
        ...,
        [nan, nan, nan, ..., nan, nan, nan],
        [nan, nan, nan, ..., nan, nan, nan],
        [nan, nan, nan, ..., nan, nan, nan]]),
 'Y': array([[nan, nan, nan, ..., nan, nan, nan],
        [nan, nan, nan, ..., nan, nan, nan],
        [nan, nan, nan, ..., nan, nan, nan],
        ...,
        [nan, nan, nan, ..., nan, nan, nan],
        [nan, nan, nan, ..., nan, nan, nan],
        [nan, nan, nan, ..., nan, nan, nan]]),
 'README': array(['2011 HFDR currents clean and detided, T is time in matlab format, U and V are in m/s and X and Y are lon and lat in degree'],
       dtype='<U122'),
 'U': array([[[        nan,         nan,         nan, ..., -2.28903437,
          -2.81524868, -3.08926222],
         [        nan,         nan,         nan, ..., -2.2359242 ,
          -3.88160247, -3.94921084],
         [        nan,         nan,         nan, ..., -3.1498654 ,
          -4.03816528, -4.8022171 ],
         ...,
         [        nan,         nan,         nan, ...,         nan,
                  nan, -0.37626221],
         [        nan,         nan,         nan, ...,         nan,
                  nan, -0.97906876],
         [        nan,         nan,         nan, ...,         nan,
                  nan,         nan]],

        [[        nan,         nan,         nan, ..., -2.55943637,
          -3.42399995, -2.74154142],
         [-2.41129668,         nan,         nan, ..., -3.37086532,
          -4.44360008, -4.87301323],
         [-1.6614966 ,  2.53829481,         nan, ..., -3.3576725 ,
          -3.48378386, -4.23251635],
         ...,
         [        nan,         nan,         nan, ...,         nan,
                  nan, -0.24761281],
         [        nan,         nan,         nan, ...,         nan,
                  nan,  2.83584583],
         [        nan,         nan,         nan, ...,         nan,
                  nan, -0.79939173]],

        [[-0.34274512, -2.24851056,  1.25880269, ..., -3.28266232,
          -3.86356129, -3.91432103],
         [-0.30126183, -1.24112729, -0.56163281, ..., -3.72570423,
          -3.91486649, -3.91774765],
         [-1.03515178, -1.75623236, -0.88225632, ..., -4.32275363,
          -3.95083582, -4.85862864],
         ...,
         [        nan,         nan,         nan, ...,         nan,
                  nan, -0.17602402],
         [        nan,         nan,         nan, ...,         nan,
                  nan,  0.31123404],
         [        nan,         nan,         nan, ...,         nan,
                  nan, -0.83010557]],

        ...,

        [[        nan,         nan,         nan, ...,         nan,
                  nan,         nan],
         [        nan,         nan,         nan, ...,         nan,
                  nan,         nan],
         [        nan,         nan,         nan, ...,         nan,
                  nan,         nan],
         ...,
         [        nan,         nan,         nan, ...,         nan,
                  nan,         nan],
         [        nan,         nan,         nan, ...,         nan,
                  nan,         nan],
         [        nan,         nan,         nan, ...,         nan,
                  nan,         nan]],

        [[        nan,         nan,         nan, ...,         nan,
                  nan,         nan],
         [        nan,         nan,         nan, ...,         nan,
                  nan,         nan],
         [        nan,         nan,         nan, ...,         nan,
                  nan,         nan],
         ...,
         [        nan,         nan,         nan, ...,         nan,
                  nan,         nan],
         [        nan,         nan,         nan, ...,         nan,
                  nan,         nan],
         [        nan,         nan,         nan, ...,         nan,
                  nan,         nan]],

        [[        nan,         nan,         nan, ...,         nan,
                  nan,         nan],
         [        nan,         nan,         nan, ...,         nan,
                  nan,         nan],
         [        nan,         nan,         nan, ...,         nan,
                  nan,         nan],
         ...,
         [        nan,         nan,         nan, ...,         nan,
                  nan,         nan],
         [        nan,         nan,         nan, ...,         nan,
                  nan,         nan],
         [        nan,         nan,         nan, ...,         nan,
                  nan,         nan]]]),
 'V': array([[[        nan,         nan,         nan, ..., -2.66567   ,
          -2.22315384, -0.99844656],
         [        nan,         nan,         nan, ..., -2.44023533,
          -1.45101395, -0.70535918],
         [        nan,         nan,         nan, ..., -2.57074761,
          -2.17096201, -1.2426105 ],
         ...,
         [        nan,         nan,         nan, ...,         nan,
                  nan, -0.01555032],
         [        nan,         nan,         nan, ...,         nan,
                  nan,  0.67034064],
         [        nan,         nan,         nan, ...,         nan,
                  nan,         nan]],

        [[        nan,         nan,         nan, ..., -2.49613084,
          -2.17967113, -1.73102186],
         [-0.19085314,         nan,         nan, ..., -2.24216667,
          -1.60634045, -0.68446314],
         [-0.47985682, -2.6897498 ,         nan, ..., -3.09012476,
          -2.5473986 , -2.29142956],
         ...,
         [        nan,         nan,         nan, ...,         nan,
                  nan, -0.53484962],
         [        nan,         nan,         nan, ...,         nan,
                  nan, -0.24008878],
         [        nan,         nan,         nan, ...,         nan,
                  nan, -0.53568459]],

        [[-0.93326312,  0.80451525, -2.70141882, ..., -1.50553473,
          -1.36389759, -0.97748875],
         [-0.92073983,  1.20430801, -0.23245133, ..., -2.48700702,
          -1.71913439, -1.9057203 ],
         [-0.28947553,  1.65032955,  0.21173892, ..., -2.3592551 ,
          -2.42616244, -2.00186308],
         ...,
         [        nan,         nan,         nan, ...,         nan,
                  nan, -0.29636747],
         [        nan,         nan,         nan, ...,         nan,
                  nan, -0.21941662],
         [        nan,         nan,         nan, ...,         nan,
                  nan,  0.00773721]],

        ...,

        [[        nan,         nan,         nan, ...,         nan,
                  nan,         nan],
         [        nan,         nan,         nan, ...,         nan,
                  nan,         nan],
         [        nan,         nan,         nan, ...,         nan,
                  nan,         nan],
         ...,
         [        nan,         nan,         nan, ...,         nan,
                  nan,         nan],
         [        nan,         nan,         nan, ...,         nan,
                  nan,         nan],
         [        nan,         nan,         nan, ...,         nan,
                  nan,         nan]],

        [[        nan,         nan,         nan, ...,         nan,
                  nan,         nan],
         [        nan,         nan,         nan, ...,         nan,
                  nan,         nan],
         [        nan,         nan,         nan, ...,         nan,
                  nan,         nan],
         ...,
         [        nan,         nan,         nan, ...,         nan,
                  nan,         nan],
         [        nan,         nan,         nan, ...,         nan,
                  nan,         nan],
         [        nan,         nan,         nan, ...,         nan,
                  nan,         nan]],

        [[        nan,         nan,         nan, ...,         nan,
                  nan,         nan],
         [        nan,         nan,         nan, ...,         nan,
                  nan,         nan],
         [        nan,         nan,         nan, ...,         nan,
                  nan,         nan],
         ...,
         [        nan,         nan,         nan, ...,         nan,
                  nan,         nan],
         [        nan,         nan,         nan, ...,         nan,
                  nan,         nan],
         [        nan,         nan,         nan, ...,         nan,
                  nan,         nan]]])}

This file has a lot of information, but we are specifically interested in the location (X,Y), and velocity components (U,V). In this example we load a single time (first one).

[4]:
# for south Oahu, use this
# Note that X and Y are 2D fields for the location;
# U and V are functions of time (3D), so first we
# pick a specific time
# t = 0 for first time
# t = -1 for last time
t = 0
time = hfr['T']
X = hfr['X']
Y = hfr['Y']
uvel = hfr['U'][:,:,t]
vvel = hfr['V'][:,:,t]

And now a quick vector plot using quiver.

[5]:
fig = plt.subplots(figsize=(12,12))
plt.quiver(X,Y,uvel,vvel);
../_images/notebooks_0427_HFR_12_0.png

We can use the same map drawing commands as before to place the land and orient the plot.

[6]:
plt.figure(figsize=(10,10))

ax = plt.axes(projection = ccrs.PlateCarree())
#ax.add_feature(cf.COASTLINE)
#ax.add_feature(cf.LAND)
land_50m = cf.NaturalEarthFeature('physical', 'land', '50m',
                                        edgecolor='face',
                                        facecolor=cf.COLORS['land'])
ax.add_feature(land_50m, edgecolor='gray')

ax.set_extent([-158.25, -157.5, 20.7, 21.5], crs=ccrs.PlateCarree())

gl = ax.gridlines(crs=ccrs.PlateCarree(), draw_labels=True,
                  linewidth=2, color='gray', alpha = 0.25, linestyle='--')

# labels on bottom and left axes
gl.xlabels_top = False
gl.ylabels_right = False

# define the label style
gl.xlabel_style = {'size': 10, 'color': 'black'}
gl.ylabel_style = {'size': 10, 'color': 'black'}

# now we define exactly which ones to label and spruce up the labels
gl.xlocator = mticker.FixedLocator([-158.2,-158.1,-158.0,-157.9,-157.8,-157.7,-157.6])
gl.ylocator = mticker.FixedLocator([20.8,20.9,21.0,21.1,21.2,21.3,21.4])
gl.xformatter = LONGITUDE_FORMATTER
gl.yformatter = LATITUDE_FORMATTER

plt.quiver(X,Y,uvel,vvel,
             transform=ccrs.PlateCarree());

/opt/tljh/user/lib/python3.9/site-packages/cartopy/mpl/gridliner.py:451: UserWarning: The .xlabels_top attribute is deprecated. Please use .top_labels to toggle visibility instead.
  warnings.warn('The .xlabels_top attribute is deprecated. Please '
/opt/tljh/user/lib/python3.9/site-packages/cartopy/mpl/gridliner.py:487: UserWarning: The .ylabels_right attribute is deprecated. Please use .right_labels to toggle visibility instead.
  warnings.warn('The .ylabels_right attribute is deprecated. Please '
../_images/notebooks_0427_HFR_14_1.png
[7]:
# redo the plot, but instead of a single time, do over the median values over
# all time
# NOTE: time is the third dimension, so we have to include "axis=2" to compute
#       the median over time; without this, nanmedian would return a single number
#       nanmedian over all x,y,y
uvel = np.nanmedian(hfr['U'],axis=2)
vvel = np.nanmedian(hfr['V'],axis=2)
/opt/tljh/user/lib/python3.9/site-packages/numpy/lib/nanfunctions.py:1096: RuntimeWarning: All-NaN slice encountered
  result = np.apply_along_axis(_nanmedian1d, axis, a, overwrite_input)
[8]:
plt.figure(figsize=(10,10))

ax = plt.axes(projection = ccrs.PlateCarree())
#ax.add_feature(cf.COASTLINE)
#ax.add_feature(cf.LAND)
land_50m = cf.NaturalEarthFeature('physical', 'land', '50m',
                                        edgecolor='face',
                                        facecolor=cf.COLORS['land'])
ax.add_feature(land_50m, edgecolor='gray')

ax.set_extent([-158.25, -157.5, 20.7, 21.5], crs=ccrs.PlateCarree())

gl = ax.gridlines(crs=ccrs.PlateCarree(), draw_labels=True,
                  linewidth=2, color='gray', alpha = 0.25, linestyle='--')

# labels on bottom and left axes
gl.xlabels_top = False
gl.ylabels_right = False

# define the label style
gl.xlabel_style = {'size': 10, 'color': 'black'}
gl.ylabel_style = {'size': 10, 'color': 'black'}

# now we define exactly which ones to label and spruce up the labels
gl.xlocator = mticker.FixedLocator([-158.2,-158.1,-158.0,-157.9,-157.8,-157.7,-157.6])
gl.ylocator = mticker.FixedLocator([20.8,20.9,21.0,21.1,21.2,21.3,21.4])
gl.xformatter = LONGITUDE_FORMATTER
gl.yformatter = LATITUDE_FORMATTER

plt.quiver(X,Y,uvel,vvel,
             transform=ccrs.PlateCarree());
../_images/notebooks_0427_HFR_16_0.png

A note about time

Typical of a matlab file, time is recorded as “days since 0-0-0” or alternately hours/minutes/seconds can be included. So, if we import the time and have a look, we see the following.

[9]:
time = hfr['T']
print("The first time is", time[0], "and the last time is", time[-1])
The first time is [734504.02083291] and the last time is [734868.97916488]

Matlab has a useful function to conver this to a calendar date, but to do this in python, we need to parse the dates out.

Note this only works on pandas data series and not regular numpy arrays. Recall you can use type(time) to see what we’re dealing with here.

[10]:
type(time)
[10]:
numpy.ndarray
[11]:
# convert to a flat pandas data series
time = pd.Series(hfr['T'].squeeze())
[12]:
# and now covert to calendar date
# You don't need worry about the details here, but hopefully the
# syntax is somewhat recognizable
calendar_time = time.apply(lambda \
                 Time: datetime.fromordinal(int(Time)) + timedelta(days=Time%1) \
                      - timedelta(days = 366 ))
[13]:
calendar_time
[13]:
0      2011-01-01 00:29:59.963069
1      2011-01-01 01:29:59.963056
2      2011-01-01 02:29:59.963043
3      2011-01-01 03:29:59.963029
4      2011-01-01 04:29:59.963016
                  ...
8755   2011-12-31 19:29:59.845656
8756   2011-12-31 20:29:59.845642
8757   2011-12-31 21:29:59.845629
8758   2011-12-31 22:29:59.845615
8759   2011-12-31 23:29:59.845602
Length: 8760, dtype: datetime64[ns]

Second, we will load the matlab binary file “hfr_2003.mat”, again using the scipy.io routine.

[14]:
# secondary data set, west Oahu
hfr = sio.loadmat('/home/ocn463-data/hfr/hfr_2003.mat')

It contains:

Name, Size, Bytes, Class

I 460x1 3680 double
T 3537x1 28296 double
U 3537x460 13016160 double
V 3537x460 13016160 double
X 460x1 3680 double
Y 460x1 3680 double
lat 185x182 269360 double
lon 185x182 269360 double

CAUTION! configuration of arrays U,V for west Oahu are different from the south Oahu data set. Note that X and Y are 1-D fields covering both latitude and longitude. U and V are 2-D functions of time at each location.

[15]:
# first we pick a specific time
# t = 0 for first time
# t = -1 for last time
t = 1
time = hfr['T']
X = hfr['X']
Y = hfr['Y']
# for west Oahu, use this for 2D array
uvel = hfr['U'][t,:]
vvel = hfr['V'][t,:]

And again a quick vector plot using quiver:

[16]:
fig = plt.subplots(figsize=(12,12))
plt.quiver(X,Y,uvel,vvel);
../_images/notebooks_0427_HFR_30_0.png

We can again use the map drawing commands to place the land and orient the plot.

[17]:
plt.figure(figsize=(10,10))

ax = plt.axes(projection = ccrs.PlateCarree())
#ax.add_feature(cf.COASTLINE)
#ax.add_feature(cf.LAND)
land_50m = cf.NaturalEarthFeature('physical', 'land', '50m',
                                        edgecolor='face',
                                        facecolor=cf.COLORS['land'])
ax.add_feature(land_50m, edgecolor='gray')

ax.set_extent([-159.1, -158.1, 20.7, 21.7], crs=ccrs.PlateCarree())

gl = ax.gridlines(crs=ccrs.PlateCarree(), draw_labels=True,
                  linewidth=2, color='gray', alpha = 0.25, linestyle='--')

# labels on bottom and left axes
gl.xlabels_top = False
gl.ylabels_right = False

# define the label style
gl.xlabel_style = {'size': 10, 'color': 'black'}
gl.ylabel_style = {'size': 10, 'color': 'black'}

# now we define exactly which ones to label and spruce up the labels
gl.xlocator = mticker.FixedLocator([-159.0, -158.9, -158.8,-158.7,-158.6,-158.5,-158.4,-158.3,-158.2])
gl.ylocator = mticker.FixedLocator([20.7,20.8,20.9,21.0,21.1,21.2,21.3,21.4,21.5, 21.6])
gl.xformatter = LONGITUDE_FORMATTER
gl.yformatter = LATITUDE_FORMATTER

plt.quiver(X,Y,uvel,vvel,
             transform=ccrs.PlateCarree());

../_images/notebooks_0427_HFR_32_0.png

STOP HERE; OLD MATLAB CODE BELOW

[year,month,day]=datevec(T);

figure() subplot(221) fi = find(month==2); s=0.04; quiver(X,Y,nanmedian(U(:,:,fi),3)s,nanmedian(V(:,:,fi),3)s,0) axis square grid fi = find(month==5); subplot(222) quiver(X,Y,nanmedian(U(:,:,fi),3)s,nanmedian(V(:,:,fi),3)s,0) axis square grid fi = find(month==7); subplot(223) grid quiver(X,Y,nanmedian(U(:,:,fi),3)s,nanmedian(V(:,:,fi),3)s,0) axis square grid fi = find(month==11); subplot(224) quiver(X,Y,nanmedian(U(:,:,fi),3)s,nanmedian(V(:,:,fi),3)s,0) axis square grid

figure() for i=1:12 fi =find(month==i); quiver(X(1:3:end, 1:3:end), Y(1:3:end, 1:3:end), nanmedian(U(1:3:end,1:3:end,fi),3)s,nanmedian(V(1:3:end,1:3:end,fi),3)s,0) axis equal axis([-158.4 -157.5 20.65 21.3]) hold on text(-157.6,20.82,‘30 cm/s’) quiver(-157.6,20.8,.30*s,0) title(sprintf(‘Currents for Month %d, 2011’,i),‘FontSize’,14) grid
drawnow pause(1) hold off end

Let’s make a color map of the two-year mean currents

figure() contourf(X, Y, nanmedian(U,3)) axis square axis([-158.4 -157.5 20.65 21.3]) hold on title(‘Two year median of surface currents from HFR’) grid

You can also plot the data from different dimensions

figure() pcolor(squeeze(V(:, 20, :))) shading flat colorbar caxis([-6 6])

figure() feather(squeeze(U(10,20,:)), squeeze(V(10,20,:)))

figure() pcolor(T, Y(:,20), squeeze(U(:,20,:))) shading flat datetick(‘x’,’ mmyy’)

figure() pcolor(Y(:,20), T, squeeze(U(:,20,:))‘) shading flat datetick(’y’,’ mmyy’) colorbar() caxis([-6 6])

figure() pcolor(X(10,:), T, squeeze(U(10,:,:))‘) shading flat datetick(’y’,’ mmyy’) colorbar() caxis([-6 6])%Let’s make a zoom where we see more energy and find the propagation speed of the perturbation observed.

axis ([-158.17 -157.66 734721.13 734750.09])

figure() pcolor(X(10,:), T, squeeze(V(10,:,:))‘) shading flat datetick(’y’,’ mmyy’) colorbar() caxis([-6 6]) %Let’s make a zoom where we see more energy and find the propagation speed of the perturbation observed.

axis ([-158.17 -157.66 734721.13 734750.09])

Select two points in the graph to find the two latitudes and the two times

ginput(2) speed = diff(ans)

The first value will give you the degrees of longitude the perturbation moved and the second value will give you the time it took to move. You should get something about 60 km/day or 0.8 m/s.

vprog = speed(1) * cosd(21) * 10e7/90/(speed(2) *86400) % in m/s

Histograms and normal distributions

Selecting one point in the HFR spatial domain

up = squeeze(U(15, 15, :)); figure() subplot(211) hist(up, 32) % you can select the number of “little bars” to separate your distribution title(‘u’)

vp = squeeze(V(15, 15, :)); subplot(212) hist(vp, 32) % you can select the number of “little bars” to separate your distribution title(‘v’)

Selecting all the data in the HFR spatial domain

figure() u0 = U(:); hist(u0, 512)

figure() v0 = V(:); hist(v0, 512)