# How to Select Specific Spatial Points from Weather Model Data Using Herbie

> Easily select specific spatial points from weather model data with Herbie. Learn to extract values at custom lat/lon locations using the ds.herbie.pick_points xarray accessor.

- Repository: [Brian Blaylock/herbie](https://github.com/blaylockbk/herbie)
- Tags: how-to-guide
- Published: 2026-02-26

---

**Use the `ds.herbie.pick_points` xarray accessor to extract values at specific latitude/longitude locations from any gridded weather model dataset loaded through Herbie.**

Herbie is a Python package that simplifies downloading and reading GRIB2 weather model data. When you need to extract forecast values at specific station locations, buoy coordinates, or custom points rather than working with full grids, Herbie provides a high-performance spatial indexing system through an xarray accessor interface.

## Understanding the Herbie Point Selection Architecture

The point extraction capability relies on two core components that work together to provide fast, model-agnostic spatial queries.

### The Xarray Accessor Interface

Herbie registers a custom accessor under `xarray.Dataset.herbie` through the `HerbieAccessor` class defined in [`src/herbie/accessors.py`](https://github.com/blaylockbk/herbie/blob/main/src/herbie/accessors.py). This accessor acts as a namespace that attaches Herbie-specific methods to any dataset loaded via Herbie's `xarray()` method. When you call `ds.herbie.pick_points()`, the accessor forwards the request to the underlying `GridPointPicker` implementation while preserving the dataset's metadata and coordinate system.

### Spatial Indexing with BallTree

The actual spatial logic resides in [`src/herbie/pick_points.py`](https://github.com/blaylockbk/herbie/blob/main/src/herbie/pick_points.py) within the `GridPointPicker` class. Rather than performing expensive distance calculations for every query, Herbie builds a **BallTree** spatial index using `sklearn.neighbors.BallTree` on the model's grid coordinates (latitude/longitude). This tree structure enables logarithmic-time nearest-neighbor searches, making it efficient to query thousands of points against high-resolution grids like HRRR or GFS. The index is constructed once per dataset and can be cached to disk for reuse across sessions.

## How to Select Spatial Points from GRIB2 Data

The `pick_points` method provides two interpolation strategies: nearest-neighbor extraction for speed and inverse-distance weighting for smoother results at grid scale boundaries.

### Loading Model Data and Defining Points

First, load your weather model data through Herbie and prepare a pandas DataFrame containing your target coordinates:

```python
import pandas as pd
from herbie import Herbie

# Load HRRR 2-meter temperature data

H = Herbie("2024-03-01 00:00", model="hrrr")
ds = H.xarray("TMP:2 m")

# Define points of interest (stations, cities, sensors)

points = pd.DataFrame({
    "longitude": [-100.0, -105.2, -98.4],
    "latitude":  [  40.0,   29.5,  42.3],
    "stid":      ["AAA",   "BBB",  "CCC"]   # Extra metadata preserved

})

```

### Nearest-Neighbor Extraction

Use the `nearest` method to extract values from the closest grid point to each location. This is fastest and appropriate when you want exact model values without interpolation:

```python

# Extract nearest grid point for each location

nearest_ds = ds.herbie.pick_points(points, method="nearest")
print(nearest_ds)

```

The resulting dataset contains your original data variables plus new coordinates: `point_latitude`, `point_longitude`, and `point_grid_distance` (the distance in kilometers between your requested point and the actual grid point used).

### Inverse-Distance Weighted Interpolation

Use the `weighted` method to compute an inverse-distance weighted mean of the *k* nearest grid points. This smooths values across grid boundaries and reduces discontinuities:

```python

# Weighted interpolation using default k=4 neighbors

weighted_ds = ds.herbie.pick_points(points, method="weighted")

```

By default, Herbie uses the 4 nearest neighbors. The weights are calculated as the inverse of the distance to each neighbor, normalized so that closer points contribute more to the final value.

## Advanced Point Selection Options

The `pick_points` method exposes several parameters to control search behavior, performance, and result formatting.

### Controlling Search Radius with max_distance

Prevent extraction from grid points that are too far from your locations using the `max_distance` parameter (specified in kilometers). This is useful when working with sparse global models like GFS where distant grid points may not represent local conditions:

```python

# Only return values if the nearest grid point is within 200 km

filtered_ds = ds.herbie.pick_points(points, max_distance=200)

```

If no grid points fall within the specified radius for a given location, that point is excluded from the results.

### Caching the BallTree for Performance

When processing multiple variables from the same model run, building the spatial index can be reused. Herbie automatically caches BallTree objects to disk when `use_cached_tree=True` (the default):

```python

# Force rebuilding the cache (useful if grid definition changes)

cached_ds = ds.herbie.pick_points(
    points,
    use_cached_tree="replant",  # Options: True, False, or "replant"

    tree_name="hrrr_20240301"   # Custom name for cache file

)

```

Cached trees are stored as pickle files under the configured `cache_dir` in a `BallTree/` subdirectory, significantly speeding up repeated extractions from the same model grid.

### Customizing Neighbor Count (k)

Adjust the number of neighbors used for weighted interpolation to control smoothing. Higher values produce smoother fields but may blur sharp gradients:

```python

# Use 8 neighbors for smoother weighted interpolation

smooth_ds = ds.herbie.pick_points(points, method="weighted", k=8)

```

## Working with Results

The output of `pick_points` is a standard xarray Dataset that integrates seamlessly with the scientific Python ecosystem.

### Converting to Pandas DataFrames

For tabular analysis or export to CSV, convert the result to a pandas DataFrame:

```python
df = nearest_ds.to_dataframe().reset_index()
print(df.head())

```

The DataFrame contains columns for the original data variables, the point index, and the `point_*` coordinate columns including distances and any custom metadata you provided.

### Indexing by Station ID

If your input points DataFrame contains a station identifier column (like `stid` in the examples above), you can swap the generic `point` dimension for your custom ID to make selection more intuitive:

```python

# Replace point index with station ID for easier selection

by_station = nearest_ds.swap_dims({"point": "point_stid"})
print(by_station.sel(point_stid="AAA"))

```

This allows you to select data using meaningful identifiers rather than integer indices.

## Summary

- **Herbie provides the `ds.herbie.pick_points` accessor** to extract values at specific lat/lon coordinates from any loaded GRIB2 dataset.
- **Two interpolation methods are available**: `nearest` for exact grid-point values and `weighted` for inverse-distance interpolation using *k* neighbors (default 4).
- **Spatial indexing uses sklearn's BallTree** ([`src/herbie/pick_points.py`](https://github.com/blaylockbk/herbie/blob/main/src/herbie/pick_points.py)) for efficient logarithmic-time queries, with optional disk caching to speed up repeated extractions.
- **Key parameters** include `max_distance` (km), `k` (neighbor count), and `use_cached_tree` for cache control.
- **Results are returned as xarray Datasets** with `point_*` coordinates including grid distance in kilometers, and can be converted to pandas DataFrames or indexed by custom station IDs.

## Frequently Asked Questions

### What is the difference between the "nearest" and "weighted" methods in Herbie?

The `nearest` method extracts the exact value from the single closest grid point to your requested location, making it fastest and preserving original model values. The `weighted` method calculates an inverse-distance weighted average of the *k* nearest grid points (default 4), which smooths values across grid boundaries and reduces discontinuities when sampling near terrain features or coastlines.

### How does Herbie handle points that are far from the model grid?

Herbie uses the `max_distance` parameter (specified in kilometers) to filter out grid points that are too distant from requested locations. If the nearest grid point exceeds this distance threshold, that point is excluded from results. This prevents inappropriate extrapolation when working with sparse global models like GFS or when requesting points outside the model domain.

### Can I reuse the spatial index for multiple variables from the same model run?

Yes, Herbie automatically caches the BallTree spatial index to disk when `use_cached_tree=True` (the default). The cache is stored as a pickle file under the configured `cache_dir/BallTree/` directory using a hash of the grid coordinates. When processing multiple variables from the same model run, subsequent calls reuse the cached tree, eliminating the overhead of rebuilding the spatial index and significantly speeding up batch extractions.