Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

xarray select nearest lat/lon with multi-dimension coordinates

I have a xarray dataset with irregular spaced latitude and longitudes coordinates. My goal is to find the value of a variable at the point nearest a certain lat/lon.

Since the x and y dimensions are not the lat/lon values, it doesn't seem that the ds.sel() method can be used by itself in this case. Is there a xarray-centric method to locate the point nearest a desired lat/lon by referencing the multi-dimensional lat/lon dimensions? For example, I want to pluck out the SPEED value nearest lat=21.2 and lon=-122.68.

Below is an example dataset...

lats = np.array([[21.138  , 21.14499, 21.15197, 21.15894, 21.16591],
                 [21.16287, 21.16986, 21.17684, 21.18382, 21.19079],
                 [21.18775, 21.19474, 21.20172, 21.2087 , 21.21568],
                 [21.21262, 21.21962, 21.22661, 21.23359, 21.24056],
                 [21.2375 , 21.2445 , 21.25149, 21.25848, 21.26545]])  

lons = np.array([[-122.72   , -122.69333, -122.66666, -122.63999, -122.61331],
                 [-122.7275 , -122.70082, -122.67415, -122.64746, -122.62078],
                 [-122.735  , -122.70832, -122.68163, -122.65494, -122.62825],
                 [-122.7425 , -122.71582, -122.68912, -122.66243, -122.63573],
                 [-122.75001, -122.72332, -122.69662, -122.66992, -122.64321]])

speed = np.array([[10.934007, 10.941321, 10.991583, 11.063932, 11.159435],
                  [10.98778 , 10.975482, 10.990983, 11.042522, 11.131154],
                  [11.013505, 11.001573, 10.997754, 11.03566 , 11.123781],
                  [11.011163, 11.000227, 11.010223, 11.049   , 11.1449  ],
                  [11.015698, 11.026604, 11.030653, 11.076904, 11.201464]])

ds = xarray.Dataset({'SPEED':(('x', 'y'),speed)},
                    coords = {'latitude': (('x', 'y'), lats),
                              'longitude': (('x', 'y'), lons)},
                    attrs={'variable':'Wind Speed'})

The value of ds:

<xarray.Dataset>
Dimensions:    (x: 5, y: 5)
Coordinates:
    latitude   (x, y) float64 21.14 21.14 21.15 21.16 ... 21.25 21.26 21.27
    longitude  (x, y) float64 -122.7 -122.7 -122.7 ... -122.7 -122.7 -122.6
Dimensions without coordinates: x, y
Data variables:
SPEED      (x, y) float64 10.93 10.94 10.99 11.06 ... 11.03 11.03 11.08 11.2
Attributes:
    variable:  Wind Speed

Again, ds.sel(latitude=21.2, longitude=-122.68) doesn't work because latitude and longitude are not the dataset dimensions.

like image 308
blaylockbk Avatar asked Nov 07 '19 23:11

blaylockbk


1 Answers

A bit late to the party here, but I've come back to this question multiple times. If your x and y coordinates are in a geospatial coordinate system, you can transform the lat/lon point to that coordinate system using cartopy. Constructing the cartopy projection is usually straightforward if you look at the metadata from the netcdf.

import cartopy.crs as ccrs

# Example - your x and y coordinates are in a Lambert Conformal projection
data_crs = ccrs.LambertConformal(central_longitude=-100)

# Transform the point - src_crs is always Plate Carree for lat/lon grid
x, y = data_crs.transform_point(-122.68, 21.2, src_crs=ccrs.PlateCarree())

# Now you can select data
ds.sel(x=x, y=y)
like image 161
Karl Schneider Avatar answered Oct 07 '22 03:10

Karl Schneider