2.8.1.3. pycsamt.site.edit#
Functions
|
Replace missing or non-finite values in Z and/or tipper arrays with zeros or NaNs. |
|
Recompute apparent resistivity and phase from the impedance tensor Z for a single site. |
|
Rename a station using an explicit name or a policy function. |
|
Batch rename a collection of sites. |
|
Rotate impedance tensor Z (and tipper T, if present) by an azimuthal angle in degrees. |
|
Rotate every site in a collection by an azimuthal angle in degrees. |
|
Subset the dataset along frequency by range or explicit indices, keeping all affected arrays aligned. |
|
Subset all sites in a collection along frequency, keeping arrays aligned. |
|
Set geographic coordinates on the EDI header. |
|
Batch set coordinates for a collection of sites. |
|
Project (easting, northing) to lon/lat and set a site's coords. |
|
Set site coordinates for many EDI files from a table. |
- pycsamt.site.edit.rotate(site, angle_deg, *, inplace=False)[source]
Rotate impedance tensor Z (and tipper T, if present) by an azimuthal angle in degrees.
The rotation is applied in the horizontal plane using the similarity transform \(Z' = R Z R^{-1}\), where \(R\) is the 2x2 rotation matrix built from
angle_deg. When a tipper is available (either on the EDI object asT/TIP/Tipor attached toZ), the 2-component vector is rotated consistently.- Parameters:
site (Any) – An EDI-like object (e.g.,
pycsamt.seg.edi.EDIFile) or wrapper exposing aZsection compatible with a complex 2x2 impedance array and, optionally, a tipper.angle_deg (float) – Rotation angle in degrees. Positive values rotate the measurement axes according to the internal convention of this package. If your acquisition system defines the sign oppositely, use the negative of your desired angle.
inplace (bool, optional) – If
True, mutatesitein place. Otherwise, work on a shallow copy and return that copy. Default isFalse.
- Returns:
The rotated object. If
inplaceisTrue, this is the same object assite; otherwise a new object.- Return type:
Any
Notes
Error arrays (
z_erroror aliases) are rotated with a magnitude-only scheme (using absolute values of the rotation matrices) as a pragmatic best-effort. This is a common, but approximate, practice.Only arrays with shapes consistent with MT tensors (
(n, 2, 2)for Z,(n, 2)for T) are rotated. Other shapes are ignored silently.The function is no-throw by design. If a section is not present or incompatible, it is skipped.
Examples
>>> from pycsamt.seg.edi import EDIFile >>> from pycsamt.site.edit import rotate >>> ed = EDIFile("path/to/station.edi") >>> ed_rot = rotate(ed, 30.0) # copy by default >>> ed_rot2 = rotate(ed, -45.0, inplace=True)
See also
select_freqSubset rows by frequency range or indices.
renameRename the station using a policy or explicit name.
pycsamt.site.edit.rotate_allBroadcast rotation over a collection.
References
[rotate-1]Simpson, F. and Bahr, K. (2005). Practical Magnetotellurics. Cambridge Univ. Press.
[rotate-2]SEG EDI format usage notes for MT tensors.
- pycsamt.site.edit.select_freq(site, *, fmin=None, fmax=None, keep=None, inplace=False)[source]
Subset the dataset along frequency by range or explicit indices, keeping all affected arrays aligned.
This applies the selection to every frequency-indexed array found on the object, including Z, Z errors, derived resistivity/phase, and any tipper arrays resident on either the root EDI object or under its
Zsection.- Parameters:
site (Any) – An EDI-like object (e.g.,
pycsamt.seg.edi.EDIFile) with a discoverable frequency vector.fmin (float, optional) – Keep rows with
freq >= fmin. Ignored ifNone.fmax (float, optional) – Keep rows with
freq <= fmax. Ignored ifNone.keep (Iterable[int] or numpy.ndarray, optional) – Explicit indices or a boolean mask to keep. If provided,
fminandfmaxare ignored. Use integer indices for exact row picks, or a boolean mask of the same length as the frequency vector.inplace (bool, optional) – If
True, mutatesitein place. Otherwise, operate on a shallow copy. Default isFalse.
- Returns:
The object after selection. If
inplaceisTrue, this is the same object assite; otherwise a new object.- Return type:
Any
Notes
All known aliases are sliced consistently (e.g., frequency, Z, Z error, resistivity, phase, tipper, and related per-row arrays) to preserve alignment.
If the frequency vector is empty or missing, the call is a no-op.
The function is no-throw by design; incompatible shapes are skipped silently.
Examples
Keep only rows with frequency >= 10 Hz:
>>> from pycsamt.seg.edi import EDIFile >>> from pycsamt.site.edit import select_freq >>> ed = EDIFile("path/to/station.edi") >>> ed_hi = select_freq(ed, fmin=10.0)
Keep the first and last rows explicitly:
>>> sel = [0, -1] >>> ed_edge = select_freq(ed, keep=sel)
Apply in place:
>>> _ = select_freq(ed, fmin=1.0, fmax=100.0, inplace=True)
See also
rotateRotate Z and tipper by an azimuth angle.
renameRename the station identifiers.
pycsamt.site.edit.select_freq_allBroadcast selection over a collection.
References
[select-freq-1]SEG EDI format usage notes for frequency-indexed MT arrays.
- pycsamt.site.edit.rename(site, name=None, policy=None, *, inplace=False)[source]
Rename a station using an explicit name or a policy function.
This updates common station identifiers across the EDI header and attempts to keep them in sync so that downstream code resolves the new name consistently.
- Parameters:
site (Any) – An EDI-like object (e.g.,
pycsamt.seg.edi.EDIFile) or wrapper with a modifiable HEAD section.name (str, optional) – Explicit new station name to set. If provided, this takes precedence over
policy.policy (Callable[[str], str], optional) – A function mapping the current station name to a new one. Ignored when
nameis provided.inplace (bool, optional) – If
True, mutatesitein place. Otherwise, operate on a shallow copy. Default isFalse.
- Returns:
The object with updated identifiers. If
inplaceisTrue, this is the same object assite; otherwise a new object.- Return type:
Any
Notes
The function writes multiple header fields when present (e.g.,
dataid,station, and other common aliases) and also mirrors the name toedi.name. This increases the chance that name resolution remains stable across different readers.The rename operation does not touch on-disk filenames. File paths remain unchanged unless you later write out using a template that depends on the station name.
If both
nameandpolicyare given,namewins.
Examples
Policy-based rename:
>>> from pycsamt.seg.edi import EDIFile >>> from pycsamt.site.edit import rename >>> ed = EDIFile("path/to/station.edi") >>> ed2 = rename(ed, policy=lambda n: f"X_{n}")
Explicit name, in place:
>>> _ = rename(ed, name="ST123A", inplace=True)
See also
rotateRotate Z and tipper by an azimuth angle.
select_freqSubset rows by frequency range or indices.
pycsamt.site.edit.rename_allBroadcast rename over a collection.
pycsamt.site.base.SiteWrapper that resolves a stable site name for indexing.
References
[rename-1]SEG EDI format field naming and common aliases for station identifiers.
- pycsamt.site.edit.set_coords(site, *, lat=None, lon=None, elev=None, inplace=False)[source]
Set geographic coordinates on the EDI header.
Only the values explicitly provided are updated. The call delegates to the same coordinate writer used by the Site API, so downstream tools see consistent lat, lon, and elev fields.
- Parameters:
site (Any) – An EDI-like object (e.g.,
pycsamt.seg.edi.EDIFile) or wrapper exposing a mutable HEAD section.lat (float, optional) – Latitude in degrees. If
None, the field is left unchanged.lon (float, optional) – Longitude in degrees. If
None, the field is left unchanged.elev (float, optional) – Elevation in meters. If
None, the field is left unchanged.inplace (bool, optional) – If
True, mutatesitein place. Otherwise, work on a shallow copy and return that copy. Default isFalse.
- Returns:
The updated object. If
inplaceisTrue, this is the same object assite; otherwise a new object.- Return type:
Any
Notes
The function validates numeric types and writes to common HEAD attribute names (
lat,lon,elev).If a field is not present in the header, a best-effort attribute is created.
Examples
>>> from pycsamt.seg.edi import EDIFile >>> from pycsamt.site.edit import set_coords >>> ed = EDIFile("path/to/station.edi") >>> ed2 = set_coords(ed, lat=35.1, lon=12.8, elev=1234.0) >>> _ = set_coords(ed, lat=36.0, inplace=True)
See also
pycsamt.site.base.Site.set_coordsObject-oriented wrapper.
pycsamt.site.edit.set_coords_allBroadcast over a collection.
References
[set-coords-1]SEG EDI format, HEAD section fields for station coordinates.
- pycsamt.site.edit.fill_missing(site, *, how='zero', components=('Z', 'Tip'), inplace=False)[source]
Replace missing or non-finite values in Z and/or tipper arrays with zeros or NaNs.
The operation preserves shapes and alignment across arrays. If an array is absent, a new one is allocated with the correct shape inferred from the frequency vector.
- Parameters:
site (Any) – An EDI-like object with a discoverable frequency vector and optionally Z and tipper sections.
how ({"zero", "nan"}, optional) – Replacement policy. Use
"zero"to fill with numeric zeros. Use"nan"to fill with NaN for all non-finite entries. Default is"zero".components (Iterable[str], optional) – Which components to process. Accepts items like
"Z"or"Tip"(case-insensitive). Default is("Z", "Tip").inplace (bool, optional) – If
True, mutate in place. Otherwise, operate on a shallow copy and return that copy. Default isFalse.
- Returns:
The object after filling. If
inplaceisTrue, this is the same object assite; otherwise a new object.- Return type:
Any
Notes
Z arrays are expected as shape
(n, 2, 2)and tipper as(n, 2). Only arrays with the expected shapes are modified or allocated.When Z exists, the function also fills common aliases for errors and derived quantities, such as
z_error,rho(resistivity), andphasearrays, if present.The frequency vector length
ndefines the number of rows used for any new arrays.This function is no-throw by design. Incompatible or absent pieces are skipped silently.
Examples
Fill Z and tipper with zeros where values are non-finite:
>>> from pycsamt.seg.edi import EDIFile >>> from pycsamt.site.edit import fill_missing >>> ed = EDIFile("path/to/station.edi") >>> ed2 = fill_missing(ed, how="zero")
Fill only Z with NaNs, in place:
>>> _ = fill_missing(ed, how="nan", components=("Z",), inplace=True)
See also
select_freqSubset rows by frequency while keeping arrays aligned.
rotateRotate Z and tipper by an azimuth angle.
References
[fill-missing-1]Simpson, F. and Bahr, K. (2005). Practical Magnetotellurics. Cambridge Univ. Press.
[fill-missing-2]SEG EDI format usage notes for MT arrays and tipper.
- pycsamt.site.edit.recompute_res_phase(site, *, inplace=False)[source]
Recompute apparent resistivity and phase from the impedance tensor Z for a single site.
The function looks for a
Zsection and, if present, calls itscompute_resistivity_phase()method. The operation is best-effort and suppresses exceptions.- Parameters:
site (Any) – An EDI-like object (
EDIFile) or a wrapper exposing aZsection with the expected API.inplace (bool, optional) – If
True, mutate the given object in place. Otherwise work on a shallow copy and return it. Default isFalse.
- Returns:
The mutated object (in place) or a new object (copy).
- Return type:
Any
Notes
Derived quantities are typically written under common aliases (e.g.,
rhoorresistivityfor apparent resistivity in ohm-m, andphasein degrees).The method assumes Z has shape
(n, 2, 2)and that a frequency vector is present. If these are missing or incompatible, nothing is changed.
Examples
Single-site:
>>> from pycsamt.seg.edi import EDIFile >>> from pycsamt.site.edit import recompute_res_phase >>> ed = EDIFile("path/to/station.edi") >>> ed2 = recompute_res_phase(ed)
In place:
>>> _ = recompute_res_phase(ed, inplace=True)
See also
select_freqKeep a subset of rows by frequency.
fill_missingEnsure arrays are allocated and finite before recomputation.
pycsamt.site.base.Site.to_dataframeInspect derived arrays.
References
[recompute-res-phase-1]Simpson, F. and Bahr, K. (2005). Practical Magnetotellurics. Cambridge Univ. Press.
[recompute-res-phase-2]SEG EDI format usage notes for derived MT quantities.
- pycsamt.site.edit.rotate_all(sites, angle_deg, *, inplace=False)[source]
Rotate every site in a collection by an azimuthal angle in degrees.
This is the broadcast variant of
rotate(). It accepts either aSiteswrapper or any iterable of EDI-like objects and returns a newSitesunlessinplaceis requested.- Parameters:
sites (Any) – A
pycsamt.site.base.Sitesinstance or any iterable of EDI-like objects.angle_deg (float) – Rotation angle in degrees, passed through to
rotate().inplace (bool, optional) – If
True, attempt to apply the rotation in place on the given container. Otherwise, return a newSites. Default isFalse.
- Returns:
A sites collection holding the rotated items, or the original container when mutated in place.
- Return type:
Notes
The function preserves the input order of items.
If some items lack compatible arrays, they are skipped silently.
Examples
Using a list of EDI files:
>>> from pycsamt.seg.edi import EDIFile >>> from pycsamt.site.edit import rotate_all >>> eds = [EDIFile("A.edi"), EDIFile("B.edi")] >>> ro = rotate_all(eds, 15.0)
Using a Sites wrapper:
>>> from pycsamt.site.base import Sites >>> sites = Sites(eds) >>> ro2 = rotate_all(sites, -30.0)
See also
rotateSingle-site rotation.
select_freq_allBroadcast selection by frequency.
- pycsamt.site.edit.select_freq_all(sites, *, fmin=None, fmax=None, keep=None, inplace=False)[source]
Subset all sites in a collection along frequency, keeping arrays aligned.
This is the broadcast variant of
select_freq(). It accepts aSiteswrapper or any iterable of EDI-like objects and returns a newSitesunlessinplaceis requested.- Parameters:
sites (Any) – A
pycsamt.site.base.Sitesinstance or any iterable of EDI-like objects.fmin (float, optional) – Keep rows with
freq >= fmin. Ignored ifNone.fmax (float, optional) – Keep rows with
freq <= fmax. Ignored ifNone.keep (Iterable[int] or numpy.ndarray, optional) – Explicit indices or a boolean mask to keep. If provided,
fminandfmaxare ignored.inplace (bool, optional) – If
True, attempt to modify the given container in place. Otherwise, return a newSites. Default isFalse.
- Returns:
A sites collection with selection applied, or the original container when mutated in place.
- Return type:
Notes
All known frequency-indexed arrays are sliced in sync for each site (Z, errors, derived quantities, and tipper).
Items missing a frequency vector are left unchanged.
Examples
>>> from pycsamt.seg.edi import EDIFile >>> from pycsamt.site.base import Sites >>> from pycsamt.site.edit import select_freq_all >>> eds = [EDIFile("A.edi"), EDIFile("B.edi")] >>> sites = Sites(eds) >>> out = select_freq_all(sites, fmin=1.0, fmax=100.0)
Use explicit row indices for all sites:
>>> out2 = select_freq_all(eds, keep=[0, -1])
See also
select_freqSingle-site selection by frequency.
rotate_allBroadcast rotation over a collection.
References
[select-freq-all-1]SEG EDI format usage notes for frequency-indexed MT arrays.
- pycsamt.site.edit.rename_all(sites, *, policy=None, name_fn=None, inplace=False)[source]
Batch rename a collection of sites.
This is the broadcast variant of
rename(). It accepts aSiteswrapper or any iterable of EDI-like objects and produces a newSites(unlessinplaceisTrue).- Parameters:
sites (Any) – A
pycsamt.site.base.Sitesinstance or any iterable of EDI-like objects.policy (Callable[[str], str], optional) – Function mapping the current station name to a new one, e.g.
lambda n: f"X_{n}". Ignored ifname_fnis provided.name_fn (Callable[[Any], str], optional) – Function mapping each EDI object to a new name, e.g. from the file stem. This takes precedence over
policyand is useful to guarantee uniqueness across sites.inplace (bool, optional) – If
True, attempt to modify the given container in place. Otherwise, return a newSites. Default isFalse.
- Returns:
A collection holding the renamed items, or the original container when mutated in place.
- Return type:
Notes
The rename updates common header identifiers and mirrors the name to
edi.namefor robust downstream resolution.If multiple sites share the same original name, a simple
policylikelambda n: "X_" + nmay produce duplicate outputs. Prefername_fnthat uses a unique attribute (e.g., the file stem) to avoid collisions.The function preserves input order and is no-throw; items that cannot be renamed are skipped.
Examples
Policy-based rename for all items:
>>> from pycsamt.site.edit import rename_all >>> out = rename_all(eds, policy=lambda n: f"X_{n}")
Unique names from file stems:
>>> from pathlib import Path >>> out = rename_all( ... eds, ... name_fn=lambda e: f"X_{Path(getattr(e, 'path', '')).stem}", ... )
See also
renameSingle-site rename helper.
set_coords_allBatch coordinate assignment.
pycsamt.site.base.SitesCollection wrapper used here.
References
[rename-all-1]SEG EDI format field naming conventions for station identifiers.
- pycsamt.site.edit.set_coords_all(sites, src, *, inplace=False)[source]
Batch set coordinates for a collection of sites.
Coordinates can be provided by a callable, a mapping keyed by station name, or an object exposing a
.frameattribute with tabular data.- Parameters:
sites (Any) – A
pycsamt.site.base.Sitesinstance or any iterable of EDI-like objects.src (Any) –
- One of:
callable(edi) -> (lat, lon, elev)mapping[name] -> (lat, lon, elev)object with
.frameDataFrame-like with columns:stationplus eitherlat/lonorlatitude/longitude, and optionallyelev/elevation.
inplace (bool, optional) – If
True, attempt to modify the given container in place. Otherwise, return a newSites. Default isFalse.
- Returns:
A collection with updated coordinates, or the original container when mutated in place.
- Return type:
Notes
The lookup order is:
callablethenmappingby station name, then the optional.frametable. The first source that returns a non-Nonetriple is used.Latitude and longitude are expected in degrees; elevation in meters.
The function preserves input order and is no-throw; items without a matching entry are left unchanged.
Examples
From a mapping keyed by names:
>>> from pycsamt.site.edit import set_coords_all >>> coords = {"S01": (35.1, 12.8, 1234.0)} >>> out = set_coords_all(eds, coords)
From a callable using file stems:
>>> from pathlib import Path >>> def pick(edi): ... stem = Path(getattr(edi, "path", "")).stem ... return (10.0, 20.0, 100.0) if stem == "S01" else \ ... (11.0, 21.0, 110.0) >>> out = set_coords_all(eds, pick)
From a pandas DataFrame holder:
>>> class Holder: ... def __init__(self, frame): ... self.frame = frame >>> out = set_coords_all(eds, Holder(df))
See also
set_coordsSingle-site coordinate update.
rename_allBatch rename helper.
pycsamt.site.base.Site.set_coordsOOP variant per site.
References
[set-coords-all-1]SEG EDI HEAD section fields for station coordinates.
- pycsamt.site.edit.set_coords_from_table(sites, table, *, columns=None, crs_from=None, to_crs='EPSG:4326', inplace=False)[source]
Set site coordinates for many EDI files from a table.
This high-level helper accepts a wide range of table-like objects (CSV path, pandas DataFrame, numpy structured array, or list of dicts / tuples). It normalizes column names, optionally projects easting/northing to lon/lat, builds a mapping
{station: (lat, lon, elev)}, and delegates toset_coords_all().- Parameters:
sites (Any) – A
Sitesinstance, an iterable ofEDIFileobjects, or anything accepted byset_coords_all().table (Any) –
- One of:
Path to a CSV or whitespace-delimited text file.
A
pandas.DataFrame.A numpy structured array.
A list of dicts or a list of tuples.
columns (dict, optional) – Explicit column mapping. Keys are canonical names and values are the actual column names present in
table. Supported canonical keys are:'station','lat','lon','elev','easting','northing'. Matching is case-insensitive.crs_from (str, optional) – Source CRS used when the table provides
eastingandnorthinginstead oflatandlon. Required in that case. Example:'EPSG:32631'for UTM 31N.to_crs (str, default "EPSG:4326") – Target CRS for output coordinates. The default is WGS84 lon/lat.
inplace (bool, default False) – If
True, mutate the given collection and return it. Otherwise return a newSiteswith updated EDI objects.
- Returns:
The same semantics as
set_coords_all(): either the mutated input (inplace=True) or a newSitesinstance.- Return type:
Any
- Raises:
ValueError – If the
stationcolumn cannot be resolved, or if neither (lat,lon) nor (easting,northing) can be resolved, or ifcrs_fromis required but missing.ImportError – If projection is needed (
easting/northingpresent) butpyprojis not installed.
Notes
Column detection is case-insensitive and understands common aliases:
station:station,name,site,id.lat:lat,latitude.lon:lon,long,longitude.elev:elev,elevation,z.easting:easting,x.northing:northing,y.
When both geographic and projected fields are present, the geographic pair (
lat,lon) is preferred. If only projected fields are present, a validcrs_frommust be provided andpyprojwill be used for projection.Examples
Load from a CSV path with standard columns:
>>> from pycsamt.site.edit import set_coords_from_table >>> from pycsamt.site.base import Sites >>> edis = Sites([...]) # your EDI files >>> out = set_coords_from_table( ... edis, "coords.csv", inplace=False ... ) >>> isinstance(out, Sites) True
Pass a DataFrame with aliases and an explicit mapping:
>>> import pandas as pd >>> df = pd.DataFrame({ ... "name": ["S01", "S02"], ... "latitude": [35.1, 35.2], ... "long": [12.8, 12.9], ... "elevation": [120.0, 130.0], ... }) >>> out = set_coords_from_table( ... edis, ... df, ... columns={"station": "name", ... "lat": "latitude", ... "lon": "long", ... "elev": "elevation"}, ... inplace=False, ... )
Use easting/northing with a source CRS:
>>> df = pd.DataFrame({ ... "station": ["S10"], ... "easting": [400000.0], ... "northing": [5750000.0], ... }) >>> out = set_coords_from_table( ... edis, ... df, ... crs_from="EPSG:32631", # UTM 31N ... inplace=False, ... )
See also
set_coords_allBroadcast setting of coordinates using a mapping.
set_coordsSingle-site coordinate update helper.
References
[set-coords-from-table-1]EPSG Geodetic Parameter Registry, https://epsg.org/
[set-coords-from-table-2]pyproj documentation, https://pyproj4.github.io/pyproj/
- pycsamt.site.edit.set_coords_from_en(site, easting, northing, *, crs_from, elev=None, to_crs='EPSG:4326', inplace=False)[source]
Project (easting, northing) to lon/lat and set a site’s coords.
This convenience wraps projection and assignment for a single EDI site. It projects the provided easting/northing from
crs_fromtoto_crs(default WGS84 lon/lat), then callsset_coords().- Parameters:
site (Any) – A single EDI-like object compatible with
set_coords().easting (float) – Easting value in meters for the source CRS.
northing (float) – Northing value in meters for the source CRS.
crs_from (str) – The EPSG or PROJ string that identifies the source CRS, for example
'EPSG:32631'for UTM 31N.elev (float, optional) – Elevation in meters to store in the EDI header. If not provided, the previous elevation is kept (if any).
to_crs (str, default "EPSG:4326") – Target CRS for output coordinates. The default is WGS84 lon/lat.
inplace (bool, default False) – If
True, mutate the given object and return it. Otherwise work on a copy and return the copy.
- Returns:
The mutated site (
inplace=True) or a new site object with updated coordinates.- Return type:
Any
- Raises:
ImportError – If
pyprojis not installed.Exception – Any errors raised by the underlying projection engine or by
set_coords()may propagate.
Notes
Projection uses
pyprojwithalways_xy=Trueso that the axis order is interpreted as (lon, lat). Units are assumed to be meters for the easting and northing values.The returned object follows the same semantics as
set_coords(). If you need to update many sites, preferset_coords_from_table()orset_coords_all().Examples
Update a single site from UTM 31N (EPSG:32631) coordinates:
>>> from pycsamt.site.edit import set_coords_from_en >>> site = ... # an EDIFile >>> site2 = set_coords_from_en( ... site, ... easting=400000.0, ... northing=5750000.0, ... crs_from="EPSG:32631", ... elev=250.0, ... inplace=False, ... )
Do the update in place and keep the existing elevation:
>>> _ = set_coords_from_en( ... site, ... easting=500000.0, ... northing=4600000.0, ... crs_from="EPSG:32630", ... inplace=True, ... )
See also
set_coordsAssign lat, lon, elev on a single site.
set_coords_from_tableBatch update from tabular input.
set_coords_allBroadcast update using a mapping.
References
[set-coords-from-en-1]EPSG Geodetic Parameter Registry, https://epsg.org/
[set-coords-from-en-2]pyproj documentation, https://pyproj4.github.io/pyproj/