Sampling Points#

Use arlmet.sample_points() to interpolate meteorological variables at arbitrary (lon, lat, z, time) points. This is the direct path when you have trajectory points, station locations, or receptors and want field values at each one without building a full Dataset.

Basic usage#

Provide the points as a DataFrame (or dict) with lon, lat, z, and time columns, plus the variables you want sampled. The first argument, files, can be a path to an ARL file — arlmet.sample_points() opens and closes it for you.

import pandas as pd
import arlmet

points = pd.DataFrame(
    {
        "lon": [-111.9, -112.0],
        "lat": [40.7, 40.8],
        "z": [850.0, 700.0],
        "time": ["2024-07-18 00:00", "2024-07-18 00:00"],
    }
)

result = arlmet.sample_points("met.arl", points, ["UWND", "VWND", "TEMP"])

The returned DataFrame is a copy of points with one column added per requested variable. Every column of points (IDs, observations, anything else) and its index are preserved, so you can compare samples with observations row by row. A requested variable whose name matches an existing column raises ValueError rather than overwriting it.

If you already have an open file, pass it instead of a path. The arlmet.File object also exposes the same operation as a method:

with arlmet.File("met.arl") as met:
    result = met.sample_points(points, ["UWND", "VWND", "TEMP"])

A file you open yourself is left open for you to manage; only paths that sample_points opens internally are closed for you.

Choosing the vertical coordinate#

The z column is interpreted according to z_kind (default "pressure"):

z_kind

Meaning of z

Requirements

"native"

fractional level index

none

"pressure"

hPa

PRSS for sigma/hybrid files

"agl"

metres above ground level

flag=2: HGTS + SHGT; flag=1/4: PRSS + TEMP; flag=3: none

"msl"

metres above mean sea level

flag=2: HGTS; flag=1/4: PRSS + TEMP + SHGT; flag=3: SHGT

with arlmet.File("met.arl") as met:
    result = arlmet.sample_points(
        met, points, ["TEMP"], z_kind="agl"
    )

The virtual "pressure" variable can also be requested as a sampled column:

result = arlmet.sample_points(met, points, ["pressure", "TEMP"])

Horizontal interpolation#

method controls horizontal interpolation between grid cells:

  • "linear" (default) — bilinear interpolation

  • "nearest" — nearest grid cell

result = arlmet.sample_points(met, points, ["TEMP"], method="nearest")

Earth-relative winds#

Winds in ARL files on projected grids (Lambert conformal, polar stereographic, Mercator) are stored relative to the grid axes, which is what HYSPLIT expects. Sampled UWND/VWND and U10M/V10M are therefore not directly comparable with observed winds. Pass earth_relative=True to rotate each pair so that u points east and v north, using the meridian convergence of the file’s grid at each point. Both components of a pair must be requested. Lat/lon grids are unaffected.

result = arlmet.sample_points(
    "hrrr.arl", points, ["UWND", "VWND"], earth_relative=True
)

The same rotation is available on the grid for winds you obtained another way, for example from arlmet.open_dataset():

u_earth, v_earth = met.grid.rotate_winds(u, v, lon, lat)

Point times#

Each point’s valid time comes from exactly one place:

  • the time column of points, if it has one;

  • otherwise the time= argument, applied to every point;

  • otherwise, when the input file(s) hold a single valid time, that time.

Passing both a time column and time= is ambiguous and raises ValueError, as does giving neither for inputs that hold more than one time. A point time that no input file contains raises ValueError naming the missing times.

points = pd.DataFrame({"lon": [-111.9], "lat": [40.7], "z": [850.0]})

result = arlmet.sample_points("single_time.arl", points, ["TEMP"])
result = arlmet.sample_points(
    "multi_time.arl", points, ["TEMP"], time="2024-07-18 06:00"
)

Sampling across multiple files#

Pass a sequence of paths (or open files) when your points span time periods stored in different files. Each timestamp must appear in at most one file; arl-met routes each point to the file that contains its time and closes any paths it opened.

paths = ["met_00.arl", "met_06.arl", "met_12.arl"]
result = arlmet.sample_points(paths, points, ["UWND", "VWND"])

You can mix open files and paths in the same sequence; files you opened stay open, and paths are closed for you.

Limitations#

  • Each timestamp must be present in at most one input file; overlapping times raise ValueError.

  • Point times not covered by any input file raise ValueError.

  • z_kind="agl" and "msl" use different field requirements depending on the vertical flag: pressure files (flag=2) require HGTS; sigma/hybrid files (flag=1/4) use hypsometric integration from PRSS and TEMP; terrain-following files (flag=3) use the stored level heights directly. See the Vertical Coordinates guide.