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

station_test_data()   B

Complexity

Conditions 5

Size

Total Lines 23

Duplication

Lines 23
Ratio 100 %

Importance

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