1
|
|
|
# Copyright (c) 2016 MetPy Developers. |
2
|
|
|
# Distributed under the terms of the BSD 3-Clause License. |
3
|
|
|
# SPDX-License-Identifier: BSD-3-Clause |
4
|
|
|
""" |
5
|
|
|
Point Interpolation |
6
|
|
|
=================== |
7
|
|
|
|
8
|
|
|
Compares different point interpolation approaches. |
9
|
|
|
""" |
10
|
|
|
import cartopy |
11
|
|
|
import cartopy.crs as ccrs |
12
|
|
|
from matplotlib.colors import BoundaryNorm |
13
|
|
|
import matplotlib.pyplot as plt |
14
|
|
|
import numpy as np |
15
|
|
|
|
16
|
|
|
from metpy.cbook import get_test_data |
17
|
|
|
from metpy.gridding.gridding_functions import (interpolate, remove_nan_observations, |
18
|
|
|
remove_repeat_coordinates) |
19
|
|
|
|
20
|
|
|
|
21
|
|
|
########################################### |
22
|
|
|
from metpy.plots import add_metpy_logo |
23
|
|
|
|
24
|
|
|
|
25
|
|
|
def basic_map(proj): |
26
|
|
|
"""Make our basic default map for plotting""" |
27
|
|
|
fig = plt.figure(figsize=(15, 10)) |
28
|
|
|
add_metpy_logo(fig) |
29
|
|
|
view = fig.add_axes([0, 0, 1, 1], projection=proj) |
30
|
|
|
view.set_extent([-120, -70, 20, 50]) |
31
|
|
|
view.add_feature(cartopy.feature.NaturalEarthFeature(category='cultural', |
32
|
|
|
name='admin_1_states_provinces_lakes', |
33
|
|
|
scale='50m', facecolor='none')) |
34
|
|
|
view.add_feature(cartopy.feature.OCEAN) |
35
|
|
|
view.add_feature(cartopy.feature.COASTLINE) |
36
|
|
|
view.add_feature(cartopy.feature.BORDERS, linestyle=':') |
37
|
|
|
return view |
38
|
|
|
|
39
|
|
|
|
40
|
|
|
def station_test_data(variable_names, proj_from=None, proj_to=None): |
41
|
|
|
with get_test_data('station_data.txt') as f: |
42
|
|
|
all_data = np.loadtxt(f, skiprows=1, delimiter=',', |
43
|
|
|
usecols=(1, 2, 3, 4, 5, 6, 7, 17, 18, 19), |
44
|
|
|
dtype=np.dtype([('stid', '3S'), ('lat', 'f'), ('lon', 'f'), |
45
|
|
|
('slp', 'f'), ('air_temperature', 'f'), |
46
|
|
|
('cloud_fraction', 'f'), ('dewpoint', 'f'), |
47
|
|
|
('weather', '16S'), |
48
|
|
|
('wind_dir', 'f'), ('wind_speed', 'f')])) |
49
|
|
|
|
50
|
|
|
all_stids = [s.decode('ascii') for s in all_data['stid']] |
51
|
|
|
|
52
|
|
|
data = np.concatenate([all_data[all_stids.index(site)].reshape(1, ) for site in all_stids]) |
53
|
|
|
|
54
|
|
|
value = data[variable_names] |
55
|
|
|
lon = data['lon'] |
56
|
|
|
lat = data['lat'] |
57
|
|
|
|
58
|
|
|
if proj_from is not None and proj_to is not None: |
59
|
|
|
|
60
|
|
|
try: |
61
|
|
|
|
62
|
|
|
proj_points = proj_to.transform_points(proj_from, lon, lat) |
63
|
|
|
return proj_points[:, 0], proj_points[:, 1], value |
64
|
|
|
|
65
|
|
|
except Exception as e: |
66
|
|
|
|
67
|
|
|
print(e) |
68
|
|
|
return None |
69
|
|
|
|
70
|
|
|
return lon, lat, value |
71
|
|
|
|
72
|
|
|
|
73
|
|
|
from_proj = ccrs.Geodetic() |
74
|
|
|
to_proj = ccrs.AlbersEqualArea(central_longitude=-97.0000, central_latitude=38.0000) |
75
|
|
|
|
76
|
|
|
levels = list(range(-20, 20, 1)) |
77
|
|
|
cmap = plt.get_cmap('magma') |
78
|
|
|
norm = BoundaryNorm(levels, ncolors=cmap.N, clip=True) |
79
|
|
|
|
80
|
|
|
x, y, temp = station_test_data('air_temperature', from_proj, to_proj) |
81
|
|
|
|
82
|
|
|
x, y, temp = remove_nan_observations(x, y, temp) |
83
|
|
|
x, y, temp = remove_repeat_coordinates(x, y, temp) |
84
|
|
|
|
85
|
|
|
########################################### |
86
|
|
|
# Scipy.interpolate linear |
87
|
|
|
# ------------------------ |
88
|
|
|
gx, gy, img = interpolate(x, y, temp, interp_type='linear', hres=75000) |
89
|
|
|
img = np.ma.masked_where(np.isnan(img), img) |
90
|
|
|
view = basic_map(to_proj) |
91
|
|
|
mmb = view.pcolormesh(gx, gy, img, cmap=cmap, norm=norm) |
92
|
|
|
plt.colorbar(mmb, shrink=.4, pad=0, boundaries=levels) |
93
|
|
|
|
94
|
|
|
########################################### |
95
|
|
|
# Natural neighbor interpolation (MetPy implementation) |
96
|
|
|
# ----------------------------------------------------- |
97
|
|
|
# `Reference <https://github.com/Unidata/MetPy/files/138653/cwp-657.pdf>`_ |
98
|
|
|
gx, gy, img = interpolate(x, y, temp, interp_type='natural_neighbor', hres=75000) |
99
|
|
|
img = np.ma.masked_where(np.isnan(img), img) |
100
|
|
|
view = basic_map(to_proj) |
101
|
|
|
mmb = view.pcolormesh(gx, gy, img, cmap=cmap, norm=norm) |
102
|
|
|
plt.colorbar(mmb, shrink=.4, pad=0, boundaries=levels) |
103
|
|
|
|
104
|
|
|
########################################### |
105
|
|
|
# Cressman interpolation |
106
|
|
|
# ---------------------- |
107
|
|
|
# search_radius = 100 km |
108
|
|
|
# |
109
|
|
|
# grid resolution = 25 km |
110
|
|
|
# |
111
|
|
|
# min_neighbors = 1 |
112
|
|
|
gx, gy, img = interpolate(x, y, temp, interp_type='cressman', minimum_neighbors=1, hres=75000, |
113
|
|
|
search_radius=100000) |
114
|
|
|
img = np.ma.masked_where(np.isnan(img), img) |
115
|
|
|
view = basic_map(to_proj) |
116
|
|
|
mmb = view.pcolormesh(gx, gy, img, cmap=cmap, norm=norm) |
117
|
|
|
plt.colorbar(mmb, shrink=.4, pad=0, boundaries=levels) |
118
|
|
|
|
119
|
|
|
########################################### |
120
|
|
|
# Barnes Interpolation |
121
|
|
|
# -------------------- |
122
|
|
|
# search_radius = 100km |
123
|
|
|
# |
124
|
|
|
# min_neighbors = 3 |
125
|
|
|
gx, gy, img1 = interpolate(x, y, temp, interp_type='barnes', hres=75000, search_radius=100000) |
126
|
|
|
img1 = np.ma.masked_where(np.isnan(img1), img1) |
127
|
|
|
view = basic_map(to_proj) |
128
|
|
|
mmb = view.pcolormesh(gx, gy, img1, cmap=cmap, norm=norm) |
129
|
|
|
plt.colorbar(mmb, shrink=.4, pad=0, boundaries=levels) |
130
|
|
|
|
131
|
|
|
########################################### |
132
|
|
|
# Radial basis function interpolation |
133
|
|
|
# ------------------------------------ |
134
|
|
|
# linear |
135
|
|
|
gx, gy, img = interpolate(x, y, temp, interp_type='rbf', hres=75000, rbf_func='linear', |
136
|
|
|
rbf_smooth=0) |
137
|
|
|
img = np.ma.masked_where(np.isnan(img), img) |
138
|
|
|
view = basic_map(to_proj) |
139
|
|
|
mmb = view.pcolormesh(gx, gy, img, cmap=cmap, norm=norm) |
140
|
|
|
plt.colorbar(mmb, shrink=.4, pad=0, boundaries=levels) |
141
|
|
|
|
142
|
|
|
plt.show() |
143
|
|
|
|