pycsamt.site.location#
Functions
|
Update site coordinates from a tabular frame by station id. |
|
Compute the azimuth from point |
|
Project points onto a profile axis and return chainages. |
|
Compute distance between two geographic points. |
|
Create or update HEAD coordinates on an EDI-like object. |
|
Parse elevation from a numeric or string value. |
|
Parse a latitude value from decimal or DMS text. |
|
Parse a longitude value from decimal or DMS text. |
|
Project points from one CRS to another using pyproj or GDAL. |
Classes
|
Lightweight geographic coordinate container. |
- class pycsamt.site.location.Coord(lat, lon, elev=0.0)[source]#
Bases:
objectLightweight geographic coordinate container.
- Parameters:
Notes
This class is a convenience container used across the site tools. Values are not validated at construction time. Use
pycsamt.gis.utils.assert_lat_valueand related helpers if you need strict range checking.Examples
>>> from pycsamt.site.location import Coord >>> c = Coord(10.0, 20.0, 100.0) >>> (c.lat, c.lon, c.elev) (10.0, 20.0, 100.0)
- pycsamt.site.location.parse_lat(x)[source]#
Parse a latitude value from decimal or DMS text.
Accepts floats, ints, or strings like
"10","-3.2","12 30 00 N","12:30:00N","12d30mE"(hemisphere letter required for disambiguation when not using sign).- Parameters:
x (any) – Numeric or string representation of a latitude value.
- Returns:
Parsed latitude in decimal degrees. Returns
nanon parsing failure.- Return type:
Notes
Hemisphere letters are interpreted as
N=+1andS=-1. Signed decimal values override hemisphere if both are given.Examples
>>> from pycsamt.site.location import parse_lat >>> parse_lat("12 30 0 N") 12.5 >>> parse_lat("-7.25") -7.25
See also
- pycsamt.site.location.parse_lon(x)[source]#
Parse a longitude value from decimal or DMS text.
Accepts floats, ints, or strings like
"20","3.5W","12 30 00 E", or"12:30:00W".- Parameters:
x (any) – Numeric or string representation of a longitude value.
- Returns:
Parsed longitude in decimal degrees. Returns
nanon parsing failure.- Return type:
Notes
Hemisphere letters are interpreted as
E=+1andW=-1. Signed decimal values override hemisphere if both are given.Examples
>>> from pycsamt.site.location import parse_lon >>> parse_lon("3.5W") -3.5
See also
- pycsamt.site.location.parse_elev(x)[source]#
Parse elevation from a numeric or string value.
- Parameters:
x (any) – Numeric or string representation of elevation in meters.
- Returns:
Elevation in meters. Returns
nanon parsing failure.- Return type:
Examples
>>> from pycsamt.site.location import parse_elev >>> parse_elev("123.4") 123.4
- pycsamt.site.location.ensure_head_coords(ed, *, lat=None, lon=None, elev=None, empty=None)[source]#
Create or update HEAD coordinates on an EDI-like object.
This function guarantees that the EDI “head” section exists and that the
lat,lonandlongaliases, andelevfields are present and numeric. Inputs are parsed withparse_lat(),parse_lon()andparse_elev(), validated withpycsamt.gis.utils.assert_*, and then written back. When a value is missing or not finite, a default empty sentinel is used (0.0 by default).- Parameters:
ed (any) – EDI-like object providing
get_section('head')and optionallyset_section('head', head). A fallback attribute-based path is used when the API is not available.lat (any, optional) – Optional overrides. If omitted, the current values are read from the head and re-validated. If still missing, the
emptyvalue is used.lon (any, optional) – Optional overrides. If omitted, the current values are read from the head and re-validated. If still missing, the
emptyvalue is used.elev (any, optional) – Optional overrides. If omitted, the current values are read from the head and re-validated. If still missing, the
emptyvalue is used.empty (float, optional) – Empty sentinel for lat, lon and elev. Default is 0.0.
- Returns:
The head section object that now carries
lat,lon(and aliaslong) andelev.- Return type:
any
Notes
This routine writes both
lonandlongto maximize compatibility with various EDI headers.Examples
>>> from pycsamt.site.location import ensure_head_coords >>> class H: pass >>> class EDI: ... def __init__(self): self._h = H() ... def get_section(self, k): return self._h if k=='head' else None ... def set_section(self, k, v): self._h = v ... >>> ed = EDI() >>> h = ensure_head_coords(ed, lat="12N", lon="3E", elev="10") >>> (h.lat, h.lon, h.elev) (12.0, 3.0, 10.0)
- pycsamt.site.location.apply_topography(ed_or_sites, frame, *, empty=None, inplace=True)[source]#
Update site coordinates from a tabular frame by station id.
Matches rows in
frameagainst the EDI “station” or related identifiers and writes the associatedlatitude,longitudeandelevationinto the EDI head section.- Parameters:
ed_or_sites (any or iterable) – A single EDI-like object, an iterable of EDI-like objects, or a container with a private
._itemslist of site objects having an.ediattribute.frame (pandas.DataFrame or dict-like) – Table with columns naming a station id and coordinates. Station id columns are matched in order among
["station","site","dataid","id","name"]. Coordinate columns are searched among["latitude","lat"],["longitude","lon","long"], and["elevation","elev","alt"].empty (float, optional) – Empty sentinel applied when values are missing. Default is 0.0.
inplace (bool, optional) – If
True(default), update the provided objects. IfFalse, return a deep-copied updated structure.
- Returns:
The updated object(s). For lists or containers, the return type mirrors the input.
- Return type:
any
Notes
Matching is case-insensitive and robust to whitespace. For containers, the function duck-types a
._itemsattribute and attempts to update the underlying.ediobjects.Examples
>>> import pandas as pd >>> from pycsamt.site.location import apply_topography >>> # ed is an EDI-like object with a valid head and dataid >>> df = pd.DataFrame({'station':['S1'], ... 'latitude':[10.0], ... 'longitude':[2.0], ... 'elevation':[100.0]}) >>> _ = apply_topography(ed, df, inplace=True)
- pycsamt.site.location.project(pts, *, crs_from, crs_to)[source]#
Project points from one CRS to another using pyproj or GDAL.
- Parameters:
pts (sequence of (float, float) or (float, float)) – Either a single coordinate pair or a sequence of pairs. Coordinates are interpreted according to
crs_from.crs_from (any) – Source CRS. For pyproj this can be an EPSG code, PROJ string, or CRS object. For GDAL, EPSG code, WKT, PROJ4, or a SpatialReference.
crs_to (any) – Target CRS in the same form as
crs_from.
- Returns:
Arrays
(X, Y)holding transformed coordinates.- Return type:
- Raises:
RuntimeError – If neither pyproj nor GDAL are available.
TypeError – If CRS specification cannot be parsed.
Notes
When both pyproj and GDAL are available, pyproj is used. The axis order is forced to the traditional GIS order
(x, y).Examples
>>> from pycsamt.site.location import project >>> X, Y = project([(0.0, 0.0)], crs_from="EPSG:4326", ... crs_to="EPSG:3857")
- pycsamt.site.location.distance(a, b, *, mode='geodetic', crs_to=None)[source]#
Compute distance between two geographic points.
Supports three modes:
geodeticuses a haversine approximation on a spherical Earth of radius_EARTH_R.flatuses a local small-extent planar approximation (about the mid-latitude).utmprojects both points to UTM (auto zone unlesscrs_tois given) and computes the Euclidean distance.- Parameters:
a (Coord or (float, float)) – Points given as
Coordor(lat, lon).b (Coord or (float, float)) – Points given as
Coordor(lat, lon).mode ({'geodetic', 'flat', 'utm'}, optional) – Distance model. Default is
'geodetic'.crs_to (any, optional) – Target CRS for
'utm'mode. If omitted, the UTM zone is inferred from the mean coordinate.
- Returns:
Distance in meters.
- Return type:
- Raises:
ValueError – If
modeis not one of the supported options.
Notes
Geodetic mode implements the haversine formula:
\[d = 2 R \arcsin\left( \sqrt{ \sin^2\Delta\phi/2 + \cos\phi_1 \cos\phi_2 \sin^2\Delta\lambda/2 } \right)\]where angles are in radians.
Examples
>>> from pycsamt.site.location import distance, Coord >>> distance(Coord(0,0,0), Coord(0,1,0), mode='geodetic') 111000.0
- pycsamt.site.location.bearing(a, b, *, mode='geodetic', crs_to=None)[source]#
Compute the azimuth from point
ato pointb.Supports the same three modes as
distance():geodetic,flat, andutm. The azimuth is expressed in degrees with 0 deg pointing to north and 90 deg to east.- Parameters:
a (Coord or (float, float)) – Points given as
Coordor(lat, lon).b (Coord or (float, float)) – Points given as
Coordor(lat, lon).mode ({'geodetic', 'flat', 'utm'}, optional) – Bearing model. Default is
'geodetic'.crs_to (any, optional) – Target CRS for
'utm'mode. If omitted, the UTM zone is inferred.
- Returns:
Azimuth in degrees in the range
[0, 360).- Return type:
- Raises:
ValueError – If
modeis not supported.
Notes
Geodetic mode uses the spherical forward azimuth:
\[\theta = \operatorname{atan2}(\sin\Delta\lambda\cos\phi_2,\, \cos\phi_1\sin\phi_2 - \sin\phi_1\cos\phi_2\cos\Delta\lambda)\]Angles are converted to degrees and wrapped to
[0, 360).Examples
>>> from pycsamt.site.location import bearing, Coord >>> bearing(Coord(0,0,0), Coord(1,0,0)) 0.0 >>> bearing(Coord(0,0,0), Coord(0,1,0)) 90.0
- pycsamt.site.location.chainage_along(origin, azimuth, pts)[source]#
Project points onto a profile axis and return chainages.
Chainage is the signed distance along the axis defined by an origin and an azimuth (0 deg north, 90 deg east). A local flat-Earth approximation is used, with 1 deg roughly equal to 111 km scaled by cosine of latitude for the east axis.
- Parameters:
- Returns:
Chainage(s) in meters. Returns a scalar for a single point, or a 1-D array for multiple points.
- Return type:
Notes
Let local offsets be
dxeast anddynorth from the origin. The chainage uses\[s = dx \sin A + dy \cos A\]where \(A\) is the azimuth in radians and \(dx, dy\) are derived from degree differences using a local metric scale.
Examples
>>> from pycsamt.site.location import chainage_along >>> s = chainage_along((0.0, 0.0), 90.0, (0.0, 1.0)) >>> s > 100000.0 True