CRS & Reprojection¶
Assign or read a coordinate reference system (via rioxarray / pyproj),
reproject a dataset, convert between geographic (lon/lat) and projected
(x/y) coordinates, and express coordinates in a metric local frame anchored
at a site (UTM zone picked from the origin).
Operators¶
AssignLocalXY
¶
AssignLocalXY(frame: LocalFrame | dict[str, Any], *, lon: str = 'lon', lat: str = 'lat', x: str = 'x', y: str = 'y')
Bases: Operator
Add metric x/y coordinates relative to a :class:LocalFrame.
Wraps :func:xrops.geom.assign_local_xy — the point / swath
counterpart of :class:ReprojectMatch. The frame is stored as its
JSON payload, so get_config() round-trips through the constructor.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
frame
|
LocalFrame | dict[str, Any]
|
A :class: |
required |
lon
|
str
|
Longitude coordinate name. |
'lon'
|
lat
|
str
|
Latitude coordinate name. |
'lat'
|
x
|
str
|
Name of the output east coordinate. |
'x'
|
y
|
str
|
Name of the output north coordinate. |
'y'
|
Returns:
| Type | Description |
|---|---|
|
The dataset with |
|
|
and swaths, 1-D for along-track points) and |
|
|
set. |
Source code in packages/xrtoolz-ops/src/xrops/geom/operators.py
Local metric frames¶
local_frame(origin_lon, origin_lat) picks the UTM zone containing the
origin and returns a frozen, JSON-serialisable LocalFrame whose to_xy
gives metres east / north of the origin and whose to_lonlat inverts it.
assign_local_xy stamps those coordinates onto a dataset (1-D rectilinear,
2-D swath, or paired 1-D along-track lon/lat on one dim); calc_latlon is
the inverse direction for gridded
rasters that already carry projected x/y axes.
utm_crs_for
¶
CRS authority code of the UTM zone containing (lon, lat).
The zone number follows the standard 6° bands plus the Norway
(zone 32 widened over 56–64°N) and Svalbard (zones 31/33/35/37 over
72–84°N) exceptions. A zone-boundary meridian belongs to the zone
east of it (lon=-102.0 → zone 14), longitudes are wrapped into
[-180, 180) first (so 0–360 grids work), and lat=0 counts
as the northern hemisphere. The code itself comes from
:func:pyproj.database.query_utm_crs_info for datum (a point
:class:~pyproj.aoi.AreaOfInterest on the zone's central meridian);
when the database has no entry the WGS 84 convention
"EPSG:326NN" (north) / "EPSG:327NN" (south) is used.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lon
|
float
|
Longitude in degrees east. |
required |
lat
|
float
|
Latitude in degrees north. |
required |
datum
|
str
|
Datum name as spelled in the PROJ database
(e.g. |
'WGS 84'
|
Returns:
| Type | Description |
|---|---|
str
|
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Example
from xrops.geom import utm_crs_for utm_crs_for(-102.5, 31.5) 'EPSG:32613' utm_crs_for(151.2, -33.9) 'EPSG:32756'
Source code in packages/xrtoolz-ops/src/xrops/geom/_src/crs.py
LocalFrame
dataclass
¶
A metric frame: projected CRS plus an origin expressed in that CRS.
to_xy returns metres east / north of the origin in crs; to_lonlat
inverts it. The frame holds only plain strings and floats, so it is
hashable and JSON-serialisable (to_dict / from_dict); the
:class:pyproj.Transformer pair is cached at module level per CRS.
Attributes:
| Name | Type | Description |
|---|---|---|
crs |
str
|
A projected CRS with metre axes, as any specifier accepted by
:class: |
origin_lon |
float
|
WGS-84 longitude of the origin, degrees east. |
origin_lat |
float
|
WGS-84 latitude of the origin, degrees north. |
origin_xy |
tuple[float, float]
|
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Example
from xrops.geom import local_frame frame = local_frame(-102.5, 31.5) frame.crs 'EPSG:32613' x, y = frame.to_xy(-102.5, 31.5) float(x), float(y) (0.0, 0.0)
to_xy
¶
to_xy(lon: float | Sequence[float] | ndarray, lat: float | Sequence[float] | ndarray) -> tuple[Float[ndarray, '...'], Float[ndarray, '...']]
Project WGS-84 lon/lat to metres relative to the origin.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lon
|
float | Sequence[float] | ndarray
|
Longitude(s) in degrees east (any shape). |
required |
lat
|
float | Sequence[float] | ndarray
|
Latitude(s) in degrees north (same shape as |
required |
Returns:
| Type | Description |
|---|---|
tuple[Float[ndarray, '...'], Float[ndarray, '...']]
|
|
Source code in packages/xrtoolz-ops/src/xrops/geom/_src/crs.py
to_lonlat
¶
to_lonlat(x: float | Sequence[float] | ndarray, y: float | Sequence[float] | ndarray) -> tuple[Float[ndarray, '...'], Float[ndarray, '...']]
Inverse of :meth:to_xy: metres from the origin to WGS-84 lon/lat.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
float | Sequence[float] | ndarray
|
Metres east of the origin (any shape). |
required |
y
|
float | Sequence[float] | ndarray
|
Metres north of the origin (same shape as |
required |
Returns:
| Type | Description |
|---|---|
tuple[Float[ndarray, '...'], Float[ndarray, '...']]
|
|
Source code in packages/xrtoolz-ops/src/xrops/geom/_src/crs.py
to_dict
¶
JSON-serialisable {"crs", "origin_lon", "origin_lat"} payload.
Source code in packages/xrtoolz-ops/src/xrops/geom/_src/crs.py
from_dict
classmethod
¶
from_dict(d: dict[str, Any]) -> LocalFrame
Rebuild a frame from a :meth:to_dict payload.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
d
|
dict[str, Any]
|
Mapping with |
required |
Returns:
| Type | Description |
|---|---|
LocalFrame
|
The reconstructed :class: |
Source code in packages/xrtoolz-ops/src/xrops/geom/_src/crs.py
local_frame
¶
local_frame(origin_lon: float, origin_lat: float, *, crs: str | None = None) -> LocalFrame
Build a :class:LocalFrame anchored at (origin_lon, origin_lat).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
origin_lon
|
float
|
WGS-84 longitude of the origin, degrees east. |
required |
origin_lat
|
float
|
WGS-84 latitude of the origin, degrees north. |
required |
crs
|
str | None
|
Projected CRS to use. |
None
|
Returns:
| Type | Description |
|---|---|
LocalFrame
|
The frame; |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in packages/xrtoolz-ops/src/xrops/geom/_src/crs.py
assign_local_xy
¶
assign_local_xy(ds: Dataset, frame: LocalFrame, *, lon: str = 'lon', lat: str = 'lat', x: str = 'x', y: str = 'y') -> Dataset
Add metric x/y coordinates (metres from frame's origin).
Rectilinear grids, swaths and point tracks are supported. Because a
UTM grid is not axis-aligned with lon/lat, gridded output is 2-D: for
1-D lon/lat on different dims they are broadcast onto
(lat_dim, lon_dim); for 2-D lon/lat (e.g.
(scanline, ground_pixel)) they share the input dims. Paired 1-D
lon/lat on the same dim (along-track points, e.g.
lon(obs)/lat(obs)) are transformed elementwise and yield 1-D
x/y on that dim.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ds
|
Dataset
|
Dataset carrying geographic coordinates. |
required |
frame
|
LocalFrame
|
Local frame that defines the CRS and origin. |
required |
lon
|
str
|
Longitude coordinate name. |
'lon'
|
lat
|
str
|
Latitude coordinate name. |
'lat'
|
x
|
str
|
Name of the output east coordinate. |
'x'
|
y
|
str
|
Name of the output north coordinate. |
'y'
|
Returns:
| Type | Description |
|---|---|
Dataset
|
|
Dataset
|
and swaths, 1-D for point tracks) and |
Dataset
|
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in packages/xrtoolz-ops/src/xrops/geom/_src/crs.py
Functions¶
These pure functions back the operators above; each takes xr.DataArray/xr.Dataset and a dim: argument.
assign_crs
¶
Attach a CRS to ds via :mod:rioxarray.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ds
|
Dataset
|
Input dataset. |
required |
crs
|
str
|
Any CRS specifier accepted by :class: |
'EPSG:4326'
|
Returns:
| Type | Description |
|---|---|
Dataset
|
Dataset with the CRS attached ( |
Source code in packages/xrtoolz-ops/src/xrops/geom/_src/crs.py
get_crs
¶
reproject
¶
reproject(ds: Dataset, target_crs: str, resolution: float | None = None, resampling: str = 'bilinear') -> Dataset
Reproject a raster dataset to target_crs via :mod:rioxarray.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ds
|
Dataset
|
Input dataset with a CRS attached. |
required |
target_crs
|
str
|
Any CRS specifier accepted by :class: |
required |
resolution
|
float | None
|
If provided, resample to this output cell size. |
None
|
resampling
|
str
|
Name of the |
'bilinear'
|
Returns:
| Type | Description |
|---|---|
Dataset
|
Reprojected dataset. |
Source code in packages/xrtoolz-ops/src/xrops/geom/_src/crs.py
lonlat_to_xy
¶
lonlat_to_xy(crs: str, lon: Sequence[float] | ndarray, lat: Sequence[float] | ndarray) -> tuple[Float[ndarray, '...'], Float[ndarray, '...']]
Convert WGS-84 lon/lat to crs x/y coordinates (same shape as input).
Source code in packages/xrtoolz-ops/src/xrops/geom/_src/crs.py
xy_to_lonlat
¶
xy_to_lonlat(crs: str, x: Sequence[float] | ndarray, y: Sequence[float] | ndarray) -> tuple[Float[ndarray, '...'], Float[ndarray, '...']]
Convert crs x/y coordinates back to WGS-84 lon/lat (same shape).