Interpolation example#
Evaltools also has interpolation features. In
interpolation
module, you can find
tools to perform bilinear interpolation at lat/lon locations from grid values.
However, interpolation
can be easily replaced
by scipy or xarray.
First, we import a list of stations where we want interpolated values.
In [1]: import numpy as np
In [2]: import evaltools as evt
In [3]: listing_path = "../doc/sample_data/listing"
In [4]: stations = evt.utils.read_listing(listing_path)
Let’s define our domain boundaries and create arbitrarily simulated data.
In [5]: min_lat = 45.
In [6]: min_lon = 6.
In [7]: d_lon = .5
In [8]: d_lat = .5
In [9]: nb_lon = 28
In [10]: nb_lat = 14
In [11]: sim_a = np.array(
....: [
....: [lat*lon for lon in range(nb_lon)]
....: for lat in range(nb_lat)
....: ]
....: )
....:
In [12]: sim_b = np.array(
....: [
....: [lat + lon for lon in range(nb_lon)]
....: for lat in range(nb_lat)
....: ]
....: )
....:
We now have a grid of values for two species A and B.
Note
Such grids could have been loaded from a netcdf or a grib file using libraries like netCDF4 or xarray.
With xarray#
In [13]: import xarray as xr
In [14]: interp_lat = xr.DataArray(stations.lat, dims='station')
In [15]: interp_lon = xr.DataArray(stations.lon, dims='station')
In [16]: data = xr.DataArray(
....: np.flipud(sim_a),
....: dims=('lat', 'lon'),
....: coords={
....: 'lat': np.arange(min_lat, min_lat + d_lat*nb_lat, d_lat),
....: 'lon': np.arange(min_lon, min_lon + d_lon*nb_lon, d_lon),
....: },
....: )
....:
In [17]: data.interp(lat=interp_lat, lon=interp_lon)
Out[17]:
<xarray.DataArray (station: 14)> Size: 112B
array([ nan, 134.42659828, 154.110888 , 140.68272232,
139.47795 , 17.70654577, 42.82960844, 43.67600354,
41.72561363, 50.42877972, 51.38245376, 69.97642392,
52.33722192, 80.67082356])
Coordinates:
lat (station) float64 112B 42.51 46.68 47.84 ... 49.57 49.73 49.86
lon (station) float64 112B 1.539 12.97 16.53 16.3 ... 15.08 13.4 18.27
* station (station) object 112B 'AD0942A' 'AT0VOR1' ... 'CZ0PPLA' 'CZ0TOPR'
With Scipy#
In [18]: from scipy.interpolate import RegularGridInterpolator
In [19]: interpolator = RegularGridInterpolator(
....: (
....: np.arange(min_lat, min_lat + d_lat*nb_lat, d_lat),
....: np.arange(min_lon, min_lon + d_lon*nb_lon, d_lon),
....: ),
....: np.flipud(sim_a),
....: method='linear',
....: bounds_error=False,
....: fill_value=np.nan,
....: )
....:
In [20]: interpolator(
....: stations[['lat', 'lon']].values
....: )
....:
Out[20]:
array([ nan, 134.42659828, 154.110888 , 140.68272232,
139.47795 , 17.70654577, 42.82960844, 43.67600354,
41.72561363, 50.42877972, 51.38245376, 69.97642392,
52.33722192, 80.67082356])
With evaltools#
We need to create a Grid
object,
load metadata from a station list file and load one list of stations per
species where interpolation will be performed (in our case we will take the
first five stations of the stations variable defined above for species A
and the last five for species B).
In [21]: interpolator = evt.interpolation.Grid(
....: min_lat, min_lon, d_lon, d_lat, nb_lon, nb_lat,
....: )
....:
In [22]: interpolator.load_stations_metadata(listing_path)
In [23]: interpolator.load_station_lists(
....: {'A': stations.index[:5], 'B': stations.index[-5:]}
....: )
....:
*** 1 stations dropped since they do not appear in self.stations.index (these are stations not found in the metadata file or located outside the domain).
All that remains to be done is to load the input arrays and perform the interpolation.
In [24]: interpolator.set_grids({'A': sim_a, 'B': sim_b})
In [25]: interpolator.interpolate()
Out[25]:
{'A': AT0VOR1 134.426627
AT10001 154.110868
AT31401 140.682664
AT31402 139.477942
dtype: float64,
'B': CZ0ALIB 19.877197
CZ0HHKB 22.302000
CZ0JKOS 22.013803
CZ0PPLA 18.339802
CZ0TOPR 27.826797
dtype: float64}
Note
Before performing the interpolation, you could
use view
method to
visualize input array and check that values are not upside down.
Note
If you then want to perform interpolation from other input arrays
for the same species you don’t have to load station lists again but only
updating the arrays by calling
set_grids
method again.