Completed
Pull Request — master (#283)
by Ryan
01:32
created

station_test_data()   B

Complexity

Conditions 5

Size

Total Lines 23

Duplication

Lines 22
Ratio 95.65 %

Importance

Changes 6
Bugs 0 Features 0
Metric Value
cc 5
c 6
b 0
f 0
dl 22
loc 23
rs 8.2508
1
# Copyright (c) 2008-2016 MetPy Developers.
2
# Distributed under the terms of the BSD 3-Clause License.
3
# SPDX-License-Identifier: BSD-3-Clause
4
"""
5
Wind and Sea Level Pressure Interpolation
6
=========================================
7
8
Interpolate sea level pressure, as well as wind component data,
9
to make a consistent looking analysis, featuring contours of pressure and wind barbs.
10
"""
11
import cartopy
12
import cartopy.crs as ccrs
13
from matplotlib.colors import BoundaryNorm
14
import matplotlib.pyplot as plt
15
import numpy as np
16
17
from metpy.calc import get_wind_components
18
from metpy.cbook import get_test_data
19
from metpy.gridding.gridding_functions import interpolate, remove_nan_observations
20
from metpy.units import units
21
22
from_proj = ccrs.Geodetic()
23
to_proj = ccrs.AlbersEqualArea(central_longitude=-97., central_latitude=38.)
24
25
26
def station_test_data(variable_names, proj_from=None, proj_to=None):
27 View Code Duplication
    f = get_test_data('station_data.txt')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
28
29
    all_data = np.loadtxt(f, skiprows=1, delimiter=',',
30
                          usecols=(1, 2, 3, 4, 5, 6, 7, 17, 18, 19),
31
                          dtype=np.dtype([('stid', '3S'), ('lat', 'f'), ('lon', 'f'),
32
                                          ('slp', 'f'), ('air_temperature', 'f'),
33
                                          ('cloud_fraction', 'f'), ('dewpoint', 'f'),
34
                                          ('weather', '16S'),
35
                                          ('wind_dir', 'f'), ('wind_speed', 'f')]))
36
37
    all_stids = [s.decode('ascii') for s in all_data['stid']]
38
    data = np.concatenate([all_data[all_stids.index(site)].reshape(1, ) for site in all_stids])
39
40
    value = data[variable_names]
41
    lon = data['lon']
42
    lat = data['lat']
43
44
    if proj_from is not None and proj_to is not None:
45
            proj_points = proj_to.transform_points(proj_from, lon, lat)
46
            return proj_points[:, 0], proj_points[:, 1], value
47
48
    return lon, lat, value
49
50
51
###########################################
52
# Get pressure information using the sample station data
53
xp, yp, pres = station_test_data(['slp'], from_proj, to_proj)
54
55
###########################################
56
# Remove all missing data from pressure
57
pres = np.array([p[0] for p in pres])
58
59
xp, yp, pres = remove_nan_observations(xp, yp, pres)
60
61
###########################################
62
# Interpolate pressure as usual
63
slpgridx, slpgridy, slp = interpolate(xp, yp, pres, interp_type='cressman',
64
                                      minimum_neighbors=1, search_radius=400000, hres=100000)
65
66
###########################################
67
# Get wind information
68
x, y, wind = station_test_data(['wind_speed', 'wind_dir'], from_proj, to_proj)
69
70
###########################################
71
# Remove bad data from wind information
72
wind_speed = np.array([w[0] for w in wind])
73
wind_dir = np.array([w[1] for w in wind])
74
75
good_indices = np.where((~np.isnan(wind_dir)) & (~np.isnan(wind_speed)))
76
77
x = x[good_indices]
78
y = y[good_indices]
79
wind_speed = wind_speed[good_indices]
80
wind_dir = wind_dir[good_indices]
81
82
###########################################
83
# Calculate u and v components of wind and then interpolate both.
84
#
85
# Both will have the same underlying grid so throw away grid returned from v interpolation.
86
u, v = get_wind_components((wind_speed * units('m/s')).to('knots'),
87
                           wind_dir * units.degree)
88
89
windgridx, windgridy, uwind = interpolate(x, y, np.array(u), interp_type='cressman',
90
                                          search_radius=400000, hres=100000)
91
92
_, _, vwind = interpolate(x, y, np.array(v), interp_type='cressman', search_radius=400000,
93
                          hres=100000)
94
95
###########################################
96
# Get temperature information
97
levels = list(range(-20, 20, 1))
98
cmap = plt.get_cmap('viridis')
99
norm = BoundaryNorm(levels, ncolors=cmap.N, clip=True)
100
101
xt, yt, t = station_test_data('air_temperature', from_proj, to_proj)
102
xt, yt, t = remove_nan_observations(xt, yt, t)
103
104
tempx, tempy, temp = interpolate(xt, yt, t, interp_type='cressman', minimum_neighbors=3,
105
                                 search_radius=400000, hres=35000)
106
107
temp = np.ma.masked_where(np.isnan(temp), temp)
108
109
###########################################
110
# Set up the map and plot the interpolated grids appropriately.
111
fig = plt.figure(figsize=(20, 10))
112
view = fig.add_subplot(1, 1, 1, projection=to_proj)
113
114
view.set_extent([-120, -70, 20, 50])
115
view.add_feature(cartopy.feature.NaturalEarthFeature(category='cultural',
116
                                                     name='admin_1_states_provinces_lakes',
117
                                                     scale='50m', facecolor='none'))
118
view.add_feature(cartopy.feature.OCEAN)
119
view.add_feature(cartopy.feature.COASTLINE)
120
view.add_feature(cartopy.feature.BORDERS, linestyle=':')
121
122
cs = view.contour(slpgridx, slpgridy, slp, colors='k', levels=list(range(990, 1034, 4)))
123
plt.clabel(cs, inline=1, fontsize=12, fmt='%i')
124
125
mmb = view.pcolormesh(tempx, tempy, temp, cmap=cmap, norm=norm)
126
plt.colorbar(mmb, shrink=.4, pad=0.02, boundaries=levels)
127
128
view.barbs(windgridx, windgridy, uwind, vwind, alpha=.4, length=5)
129
130
plt.title('Surface Temperature (shaded), SLP, and Wind.')
131
132
plt.show()
133