Comprehensive Python library for meteorological data analysis and weather visualization.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
MetPy provides seamless integration with xarray through custom accessors that make data arrays and datasets meteorology-aware. The .metpy accessor automatically handles coordinate identification, unit management, coordinate reference systems, and meteorological coordinate transformations.
The MetPy DataArray accessor provides meteorological functionality directly on xarray DataArrays through the .metpy attribute.
@property
def units:
"""
Get or set units of the DataArray as a pint.Unit.
Returns:
pint.Unit object representing the data units
"""
@property
def magnitude:
"""
Return magnitude of data values without units.
Returns:
Data array values without units attached
"""
@property
def unit_array:
"""
Return data values as a pint.Quantity.
Returns:
pint.Quantity with data and units
"""
def convert_units(units):
"""
Convert DataArray to different units.
Parameters:
- units: target units for conversion
Returns:
New DataArray with converted units
"""
def convert_to_base_units():
"""
Convert DataArray to base SI units.
Returns:
New DataArray with base units
"""
def convert_coordinate_units(coord, units):
"""
Convert coordinate to different units.
Parameters:
- coord: coordinate name to convert
- units: target units
Returns:
New DataArray with converted coordinate units
"""
def quantify():
"""
Convert data to pint.Quantity if not already quantified.
Returns:
DataArray with pint.Quantity data
"""
def dequantify():
"""
Convert pint.Quantity data to magnitude with units as attribute.
Returns:
DataArray with numeric data and units attribute
"""Automatic identification and access to meteorological coordinate axes.
@property
def time:
"""
Return the time coordinate.
Returns:
Time coordinate DataArray
"""
@property
def vertical:
"""
Return the vertical coordinate (pressure, height, etc.).
Returns:
Vertical coordinate DataArray
"""
@property
def y:
"""
Return the y coordinate (latitude or projected y).
Returns:
Y coordinate DataArray
"""
@property
def latitude:
"""
Return the latitude coordinate.
Returns:
Latitude coordinate DataArray
"""
@property
def x:
"""
Return the x coordinate (longitude or projected x).
Returns:
X coordinate DataArray
"""
@property
def longitude:
"""
Return the longitude coordinate.
Returns:
Longitude coordinate DataArray
"""
def coordinates(*args):
"""
Return coordinate variables for specified axis types.
Parameters:
- args: axis type strings ('time', 'vertical', 'y', 'latitude', 'x', 'longitude')
Returns:
Generator yielding coordinate DataArrays
"""
def coordinates_identical(other):
"""
Check if coordinates match another DataArray.
Parameters:
- other: DataArray to compare coordinates with
Returns:
Boolean indicating coordinate match
"""Handle map projections and coordinate transformations for meteorological data.
@property
def crs:
"""
Return coordinate reference system as CFProjection object.
Returns:
CFProjection object with CRS information
"""
@property
def cartopy_crs:
"""
Return CRS as cartopy projection object.
Returns:
cartopy CRS object for plotting
"""
@property
def cartopy_globe:
"""
Return globe associated with the CRS.
Returns:
cartopy Globe object
"""
@property
def cartopy_geodetic:
"""
Return cartopy geodetic CRS for the globe.
Returns:
cartopy Geodetic CRS
"""
@property
def pyproj_crs:
"""
Return CRS as pyproj object.
Returns:
pyproj CRS object
"""
@property
def pyproj_proj:
"""
Return Proj object for coordinate transformations.
Returns:
pyproj Proj object
"""
def assign_crs(cf_attributes=None, **kwargs):
"""
Assign coordinate reference system using CF conventions.
Parameters:
- cf_attributes: dictionary of CF projection attributes
- kwargs: CF attributes as keyword arguments
Returns:
New DataArray with CRS coordinate assigned
"""
def assign_latitude_longitude(force=False):
"""
Assign 2D latitude/longitude coordinates from y/x coordinates.
Parameters:
- force: overwrite existing lat/lon coordinates if True
Returns:
New DataArray with latitude/longitude coordinates
"""
def assign_y_x(force=False, tolerance=None):
"""
Assign 1D y/x coordinates from 2D latitude/longitude.
Parameters:
- force: overwrite existing y/x coordinates if True
- tolerance: maximum range tolerance for 2D to 1D collapse
Returns:
New DataArray with y/x dimension coordinates
"""Meteorological grid analysis utilities for spatial derivatives and coordinate spacing.
@property
def time_deltas:
"""
Return time differences in seconds.
Returns:
pint.Quantity with time differences
"""
@property
def grid_deltas:
"""
Return horizontal grid spacing for derivatives.
Returns:
Dictionary with 'dx' and 'dy' grid spacing arrays
"""
def find_axis_name(axis):
"""
Find coordinate name for given axis identifier.
Parameters:
- axis: axis identifier (int, string, or axis type)
Returns:
String name of the coordinate
"""
def find_axis_number(axis):
"""
Find dimension number for given axis identifier.
Parameters:
- axis: axis identifier (int, string, or axis type)
Returns:
Integer dimension number
"""Assign and manage meteorological coordinate metadata.
def assign_coordinates(coordinates):
"""
Assign coordinates to specific MetPy axis types.
Parameters:
- coordinates: dict mapping axis types to coordinates, or None to clear
Returns:
New DataArray with assigned coordinate metadata
"""Unit-aware and coordinate-type-aware data selection.
@property
def loc:
"""
Unit-aware .loc indexer for DataArrays.
Returns:
Indexer object supporting units and coordinate types
"""
def sel(indexers=None, method=None, tolerance=None, drop=False, **indexers_kwargs):
"""
Unit-aware selection method.
Parameters:
- indexers: coordinate indexers (can include units)
- method: selection method for inexact matches
- tolerance: tolerance for inexact matches
- drop: drop scalar coordinates
- indexers_kwargs: indexers as keyword arguments
Returns:
Selected DataArray subset
"""The MetPy Dataset accessor provides meteorological functionality for entire datasets.
def parse_cf(varname=None, coordinates=None):
"""
Parse CF conventions for coordinate metadata.
Parameters:
- varname: variable name(s) to parse (default: all)
- coordinates: manual coordinate assignments
Returns:
DataArray or Dataset with parsed CF metadata
"""
@property
def loc:
"""
Unit-aware .loc indexer for Datasets.
Returns:
Indexer object supporting units
"""
def sel(indexers=None, method=None, tolerance=None, drop=False, **indexers_kwargs):
"""
Unit-aware Dataset selection.
Parameters:
- indexers: coordinate indexers
- method: selection method
- tolerance: selection tolerance
- drop: drop scalar coordinates
- indexers_kwargs: indexers as keywords
Returns:
Selected Dataset subset
"""
def assign_crs(cf_attributes=None, **kwargs):
"""
Assign CRS to Dataset variables.
Parameters:
- cf_attributes: CF projection attributes dictionary
- kwargs: CF attributes as keywords
Returns:
New Dataset with CRS coordinate
"""
def assign_latitude_longitude(force=False):
"""
Assign lat/lon coordinates to all applicable variables.
Parameters:
- force: overwrite existing coordinates
Returns:
New Dataset with latitude/longitude coordinates
"""
def assign_y_x(force=False, tolerance=None):
"""
Assign y/x coordinates to all applicable variables.
Parameters:
- force: overwrite existing coordinates
- tolerance: tolerance for coordinate collapse
Returns:
New Dataset with y/x coordinates
"""
def update_attribute(attribute, mapping):
"""
Update attribute across all Dataset variables.
Parameters:
- attribute: attribute name to update
- mapping: dict or callable for new attribute values
Returns:
New Dataset with updated attributes
"""
def quantify():
"""
Convert all numeric variables to pint.Quantities.
Returns:
New Dataset with quantified variables
"""
def dequantify():
"""
Convert pint.Quantities to magnitudes with units attributes.
Returns:
New Dataset with dequantified variables
"""import xarray as xr
import metpy.xarray # Enables .metpy accessor
from metpy.units import units
# Load meteorological data
ds = xr.open_dataset('temperature_data.nc')
# Enable MetPy functionality
ds = ds.metpy.parse_cf()
# Access meteorological coordinates automatically
print("Time coordinate:", ds['temperature'].metpy.time)
print("Pressure levels:", ds['temperature'].metpy.vertical)
print("Spatial coordinates:", ds['temperature'].metpy.x, ds['temperature'].metpy.y)
# Check coordinate reference system
if hasattr(ds['temperature'].metpy, 'crs'):
print("Projection:", ds['temperature'].metpy.crs)# Work with units automatically
temp = ds['temperature']
print("Original units:", temp.metpy.units)
# Convert units seamlessly
temp_celsius = temp.metpy.convert_units('celsius')
temp_kelvin = temp.metpy.convert_units('kelvin')
print(f"Temperature range: {temp_celsius.min().values:.1f} to {temp_celsius.max().values:.1f} °C")
# Convert coordinates
if 'height' in ds.coords:
# Convert height from meters to kilometers
ds_km = ds.metpy.convert_coordinate_units('height', 'km')
print("Height now in km:", ds_km.height.metpy.units)# Assign coordinate reference system
import metpy.plots.mapping as mp
# For Lambert Conformal Conic projection
lcc_attrs = {
'grid_mapping_name': 'lambert_conformal_conic',
'standard_parallel': [25.0, 60.0],
'longitude_of_central_meridian': -100.0,
'latitude_of_projection_origin': 50.0
}
# Assign CRS to data
ds_proj = ds.metpy.assign_crs(lcc_attrs)
print("CRS assigned:", ds_proj.metpy.crs)
# Generate latitude/longitude coordinates from projection
ds_with_latlon = ds_proj.metpy.assign_latitude_longitude()
print("Latitude range:", ds_with_latlon.latitude.min().values, "to", ds_with_latlon.latitude.max().values)from metpy.units import units
# Unit-aware selection
temp_500mb = ds.sel(pressure=500 * units.hPa)
temp_region = ds.sel(
latitude=slice(30 * units.degrees_north, 50 * units.degrees_north),
longitude=slice(-120 * units.degrees_east, -90 * units.degrees_east)
)
# Select using coordinate types instead of names
temp_surface = ds.isel(vertical=0) # Surface level
temp_recent = ds.isel(time=-1) # Most recent time
# Advanced indexing with .loc
temp_point = ds.metpy.loc[{
'y': 40.0 * units.degrees_north,
'x': -105.0 * units.degrees_east,
'vertical': 850 * units.hPa
}]# Calculate grid spacing for derivatives
temp = ds['temperature']
grid_info = temp.metpy.grid_deltas
print("Grid spacing dx:", grid_info['dx'])
print("Grid spacing dy:", grid_info['dy'])
# Use with MetPy calculation functions
import metpy.calc as mpcalc
# Calculate temperature advection
u_wind = ds['u_wind']
v_wind = ds['v_wind']
# Grid deltas automatically used by calculation functions
temp_advection = mpcalc.advection(temp, u_wind, v_wind)
print("Temperature advection calculated with automatic grid spacing")# GRIB data with CF conventions
grib_ds = xr.open_dataset('forecast.grib2', engine='cfgrib')
grib_ds = grib_ds.metpy.parse_cf()
# NetCDF data from THREDDS
netcdf_ds = xr.open_dataset('http://thredds.server.edu/data.nc')
netcdf_ds = netcdf_ds.metpy.parse_cf()
# Manual coordinate assignment when automatic parsing fails
coords_manual = {
'time': 'time',
'vertical': 'pressure',
'y': 'lat',
'x': 'lon'
}
ds_manual = ds.metpy.assign_coordinates(coords_manual)import metpy.calc as mpcalc
# Load upper-air data
sounding = xr.open_dataset('sounding.nc').metpy.parse_cf()
# Extract profiles - coordinates automatically identified
pressure = sounding['pressure'].metpy.vertical
temperature = sounding['temperature']
dewpoint = sounding['dewpoint']
# Calculations work seamlessly with xarray data
theta = mpcalc.potential_temperature(pressure, temperature)
rh = mpcalc.relative_humidity_from_dewpoint(temperature, dewpoint)
# Results maintain coordinate information
print("Potential temperature coordinates:", theta.coords)
print("Relative humidity range:", rh.min().values, "to", rh.max().values)# Convert to pint quantities for advanced unit operations
temp_quantity = ds['temperature'].metpy.quantify()
print("Temperature as quantity:", type(temp_quantity.data))
# Perform complex unit operations
temp_rankine = temp_quantity.metpy.convert_units('rankine')
temp_difference = temp_quantity - temp_quantity.mean()
# Convert back to normal xarray with units as attributes
temp_dequant = temp_quantity.metpy.dequantify()
print("Units attribute:", temp_dequant.attrs['units'])MetPy uses multiple criteria to automatically identify coordinate types:
# Coordinate axis types recognized by MetPy
metpy_axes = ['time', 'vertical', 'y', 'latitude', 'x', 'longitude']
# Identification criteria (examples)
coordinate_criteria = {
'standard_name': {
'time': 'time',
'vertical': {'air_pressure', 'height', 'geopotential_height'},
'latitude': 'latitude',
'longitude': 'longitude'
},
'axis': {
'time': 'T',
'vertical': 'Z',
'y': 'Y',
'x': 'X'
},
'units': {
'vertical': {'match': 'dimensionality', 'units': 'Pa'},
'latitude': {'match': 'name', 'units': {'degree_north', 'degrees_north'}},
'longitude': {'match': 'name', 'units': {'degree_east', 'degrees_east'}}
}
}try:
# Attempt to access coordinate
time_coord = ds['temperature'].metpy.time
except AttributeError:
print("Time coordinate not found or not identifiable")
try:
# Attempt coordinate conversion
temp_kelvin = ds['temperature'].metpy.convert_units('kelvin')
except DimensionalityError:
print("Units are not compatible with temperature")
# Check for CRS before using projection methods
if hasattr(ds['temperature'].metpy, 'crs'):
cartopy_crs = ds['temperature'].metpy.cartopy_crs
else:
print("No CRS information available")from typing import Optional, Dict, Generator, Union
import xarray as xr
from pint import Quantity
# Accessor types
MetPyDataArrayAccessor = object
MetPyDatasetAccessor = object
# Coordinate types
CoordinateArray = xr.DataArray
CoordinateMapping = Dict[str, str]
# CRS types
CRS = object # CFProjection object
CartopyCRS = object
PyProjCRS = object
# Selection types
IndexerDict = Dict[str, Union[slice, Quantity, float, int]]
SelectionResult = Union[xr.DataArray, xr.Dataset]