pycsamt.site.selection#

Functions

by_bbox(sites, minlat, minlon, maxlat, maxlon)

Select sites that fall inside an axis-aligned geographic box.

by_chainage(sites, smin, smax)

Select sites whose stored chainage falls within a closed interval.

by_freq(sites, fmin, fmax)

Select sites that contain at least one data row with frequency inside a closed interval.

by_index(sites, indices)

Select sites by zero-based numeric indices, supporting negative indices.

by_names(sites, patterns, *[, case])

Select sites by matching station names against one or more patterns.

by_predicate(sites, pred)

Select sites using a user-supplied predicate function.

drop_empty(sites)

Drop sites that are effectively empty.

keep_finite_z(sites)

Keep sites that contain at least one finite impedance value.

mask_large_phase_err(sites, thresh)

Filter out sites whose maximum phase-error exceeds a threshold.

pycsamt.site.selection.by_names(sites, patterns, *, case=False)[source]#

Select sites by matching station names against one or more patterns.

This is a flexible name-based selector that accepts several pattern types:

  • string with optional glob-like wildcards * and ?

  • compiled regular expression (re.Pattern)

  • callable fn(name)->bool

  • iterable of any mix of the above

A site is kept if any pattern matches its station name. Matching is stable: the relative order of kept sites is the same as in the input.

Parameters:
  • sites (Any) – A Sites instance, an EDICollection, a sequence of EDIFile objects, or any iterable yielding EDI-like objects.

  • patterns (Iterable[Any] or Any) – One pattern or an iterable of patterns. See the list above for supported pattern types.

  • case (bool, optional) – If True, perform case-sensitive matching. If False (default) names and string patterns are upper-cased before comparison.

Returns:

A new Sites wrapper containing only the matched EDI items. The original container is not modified.

Return type:

pycsamt.site.base.Sites

Notes

String patterns support a minimal glob syntax. * matches any sequence (possibly empty) and ? matches any single character. If you need full regular expressions, pass a compiled re.Pattern.

When multiple patterns are given, the match is an OR over all patterns. Matching uses the station name as returned by station_name(ed) which reflects header normalization.

Examples

>>> from pycsamt.site.base import Sites
>>> from pycsamt.site.selection import by_names
>>> sites = Sites([e1, e2, e3])  # EDIFile objects
>>> out = by_names(sites, "K*")  # glob: all names starting K
>>> [s.name for s in out]
['K01', 'K02']
>>> import re
>>> rx = re.compile(r"^S0[1-3]$")
>>> out = by_names(sites, rx)
>>> [s.name for s in out]
['S01', 'S02', 'S03']
>>> out = by_names(sites, lambda n: n.endswith("A"))
>>> [s.name for s in out]
['X1A', 'X2A']

See also

pycsamt.site.selection.by_index

Select by numeric positions.

pycsamt.site.selection.by_predicate

Keep sites for which a boolean predicate returns True.

pycsamt.site.selection.by_freq

Keep sites that contain data within a frequency window.

References

pycsamt.site.selection.by_index(sites, indices)[source]#

Select sites by zero-based numeric indices, supporting negative indices.

Indices are normalized exactly like Python sequence indexing: -1 addresses the last item, -2 the one before last, and so on. Out-of-range or non-integer indices are ignored. The resulting subset preserves the original ordering of the selected items, not the order in which indices are provided.

Parameters:
  • sites (Any) – A Sites instance, an EDICollection, a sequence of EDIFile objects, or any iterable yielding EDI-like objects.

  • indices (Iterable[int] or int) – One index or an iterable of indices. Negative indices are supported and mapped to their Python equivalents.

Returns:

A new Sites wrapper containing only items at the requested positions. If no valid indices remain after normalization, an empty Sites is returned.

Return type:

pycsamt.site.base.Sites

Notes

Duplicate indices are de-duplicated in the output since the selection is implemented as a membership test over the set of normalized indices. The relative order of kept items is the same as in the original sequence.

Examples

>>> from pycsamt.site.base import Sites
>>> from pycsamt.site.selection import by_index
>>> sites = Sites([e1, e2, e3])  # names: A, B, C
>>> out = by_index(sites, [0, -1])   # first and last
>>> [s.name for s in out]
['A', 'C']
>>> out = by_index(sites, 1)  # single integer
>>> [s.name for s in out]
['B']
>>> out = by_index(sites, [10, -10])  # both invalid -> empty
>>> len(out)
0

See also

pycsamt.site.selection.by_names

Name-based matching using strings, regex, or callables.

pycsamt.site.selection.by_chainage

Select by stored chainage range when available.

pycsamt.site.base.Sites.by_index

Random access to a single site by position.

pycsamt.site.selection.by_chainage(sites, smin, smax)[source]#

Select sites whose stored chainage falls within a closed interval.

This helper reads the chainage value first from the EDI HEAD section (head.chainage) and, if missing, from a top-level attribute edi.chainage. Sites for which a numeric chainage cannot be determined are silently skipped.

Parameters:
  • sites (Any) – A Sites instance, an EDICollection, a sequence of EDIFile objects, or any iterable yielding EDI-like items.

  • smin (float) – Minimum chainage (inclusive).

  • smax (float) – Maximum chainage (inclusive).

Returns:

A new Sites wrapper containing only the EDI items whose chainage \(c\) satisfies \(smin \\le c \\le smax\).

Return type:

pycsamt.site.base.Sites

Notes

Chainage is a linear reference commonly used along profiles or lines, typically measured in meters from a chosen origin. If chainage is not present on a site, that site is excluded. The original order of sites is preserved among the kept items.

Examples

>>> from pycsamt.site.base import Sites
>>> from pycsamt.site.selection import by_chainage
>>> s = Sites([e1, e2, e3])  # EDIFile objects
>>> out = by_chainage(s, smin=100.0, smax=300.0)
>>> [t.name for t in out]
['L02', 'L03']

See also

pycsamt.site.selection.by_index

Select by zero-based positions with negative support.

pycsamt.site.selection.by_names

Select by station names using glob, regex, or callables.

pycsamt.site.selection.by_freq

Keep sites that contain data in a frequency window.

pycsamt.site.base.Sites.to_profile

Build a profile or ordered view along a line.

References

pycsamt.site.selection.by_freq(sites, fmin, fmax)[source]#

Select sites that contain at least one data row with frequency inside a closed interval.

A site is kept if its frequency array f contains any finite value satisfying \(fmin \le f \le fmax\). Sites with empty or non-finite frequency arrays are skipped.

Parameters:
  • sites (Any) – A Sites instance, an EDICollection, a sequence of EDIFile objects, or any iterable yielding EDI-like items.

  • fmin (float) – Minimum frequency (inclusive).

  • fmax (float) – Maximum frequency (inclusive).

Returns:

A new Sites wrapper containing only the EDI items with at least one finite frequency in the requested window.

Return type:

pycsamt.site.base.Sites

Notes

Frequencies are obtained via pycsamt.site.utils.get_freq(ed). The check is membership based (any row in range), not a full slicing or resampling. Use pycsamt.site.edit.select_freq() to actually subset rows by frequency.

Examples

>>> from pycsamt.site.base import Sites
>>> from pycsamt.site.selection import by_freq
>>> s = Sites([e1, e2, e3])  # EDIFile objects
>>> out = by_freq(s, fmin=0.5, fmax=2.0)
>>> [t.name for t in out]
['A02', 'A03']

See also

pycsamt.site.selection.by_names

Name-based selection using glob, regex, or callables.

pycsamt.site.selection.by_chainage

Select by stored chainage range when available.

pycsamt.site.edit.select_freq

Subset frequency rows within sites.

pycsamt.site.selection.by_bbox(sites, minlat, minlon, maxlat, maxlon)[source]#

Select sites that fall inside an axis-aligned geographic box.

The selection is performed in latitude/longitude degrees and assumes a geographic CRS (WGS84-like). A site is kept if its stored coordinates satisfy

\[minlat \le lat \le maxlat \;\;\text{and}\;\; minlon \le lon \le maxlon .\]
Parameters:
  • sites (Any) – A Sites instance, an EDICollection, a sequence of EDIFile objects, or any iterable yielding EDI-like items.

  • minlat (float) – Latitude and longitude bounds in degrees. Bounds are inclusive.

  • minlon (float) – Latitude and longitude bounds in degrees. Bounds are inclusive.

  • maxlat (float) – Latitude and longitude bounds in degrees. Bounds are inclusive.

  • maxlon (float) – Latitude and longitude bounds in degrees. Bounds are inclusive.

Returns:

A new Sites wrapper with only the items whose coords are inside the box.

Return type:

pycsamt.site.base.Sites

Notes

This is a simple axis-aligned test in lat/lon and does not handle antimeridian wrapping. If longitudes cross the antimeridian (for example, from 170 to -170 deg), split the selection into two boxes and union the results. Coordinates are retrieved via pycsamt.site.utils.get_coords().

Examples

>>> from pycsamt.site.base import Sites
>>> from pycsamt.site.selection import by_bbox
>>> s = Sites([e1, e2, e3])  # EDIFile objects
>>> out = by_bbox(s, 24.0, 9.0, 27.0, 11.0)
>>> [site.name for site in out]
['S01', 'S03']

See also

pycsamt.site.selection.by_freq

Keep sites with at least one frequency inside a window.

pycsamt.site.selection.by_chainage

Select by stored chainage range.

pycsamt.site.selection.by_predicate

Arbitrary user-defined filtering.

pycsamt.site.base.Sites.closest

Find the closest site to a target coordinate.

References

pycsamt.site.selection.by_predicate(sites, pred)[source]#

Select sites using a user-supplied predicate function.

The predicate is called for each EDI-like object and should return True to keep the site. Any exception raised by the predicate is caught and treated as a False (site is not kept). This makes bulk filtering robust against occasional data issues.

Parameters:
  • sites (Any) – A Sites instance, an EDICollection, a sequence of EDIFile objects, or any iterable yielding EDI-like items.

  • pred (Callable[[Any], bool]) – Function receiving a single EDI-like object and returning a boolean.

Returns:

A new Sites wrapper containing only the sites for which pred(site) returned True.

Return type:

pycsamt.site.base.Sites

Notes

The objects passed to pred are the raw EDI containers, not the Site wrapper. If you prefer the wrapper API, wrap the object inside the predicate:

lambda ed: Site(ed).has_component("Zxy").

Examples

Keep sites that have at least 3 frequency rows:

>>> from pycsamt.site.base import Sites, Site
>>> from pycsamt.site.selection import by_predicate
>>> s = Sites([e1, e2, e3])
>>> out = by_predicate(
...     s, lambda ed: (Site(ed).freq is not None and
...                    len(Site(ed).freq) >= 3)
... )
>>> [t.name for t in out]
['A01', 'A03']

Keep sites whose name matches a rule:

>>> import re
>>> from pycsamt.site.utils import station_name
>>> rule = re.compile(r"^X_")
>>> out = by_predicate(s, lambda ed: bool(rule.search(
...     station_name(ed))))
>>> [t.name for t in out]
['X_E01', 'X_E02']

See also

pycsamt.site.selection.by_names

Name-based selection with glob or regex patterns.

pycsamt.site.selection.drop_empty

Remove sites with no usable data arrays.

pycsamt.site.base.Sites.select

Selection API on the wrapper.

References

pycsamt.site.selection.keep_finite_z(sites)[source]#

Keep sites that contain at least one finite impedance value.

A site is considered to have finite data if either of the following is true:

  1. The impedance tensor array (Z.z or Z._z) contains any finite real or imaginary entry.

  2. If the tensor is not present, a resistivity array (Z._resistivity or Z.rho) exists and has at least one finite value.

Parameters:

sites (Any) – A Sites instance, an EDICollection, a sequence of EDIFile objects, or any iterable yielding EDI-like items.

Returns:

A new Sites wrapper with only the sites that contain finite impedance (or resistivity) values.

Return type:

pycsamt.site.base.Sites

Notes

This function is intended as a coarse pre-filter to remove empty placeholders and fully invalid sites before more costly processing. It does not inspect errors or phases, and it does not modify the data. If a site has a Z container but all arrays are missing or fully non-finite, the site is dropped.

Examples

>>> from pycsamt.site.base import Sites
>>> from pycsamt.site.selection import keep_finite_z
>>> s = Sites([e1, e2, e3])
>>> out = keep_finite_z(s)
>>> [t.name for t in out]
['MT01', 'MT03']

See also

pycsamt.site.selection.drop_empty

Remove sites with empty frequency or missing Z section.

pycsamt.site.edit.fill_missing

Allocate arrays and replace invalid entries.

pycsamt.site.compute.res_at_freq

Compute apparent resistivity at a specific frequency.

pycsamt.site.selection.mask_large_phase_err(sites, thresh)[source]#

Filter out sites whose maximum phase-error exceeds a threshold.

For each site, the function inspects the phase-error array when present (common attribute names are tried, e.g. _phase_err or phase_err). If no phase-error array is found, the site is conservatively kept. Otherwise, the site is kept only when the maximum finite phase-error is less than or equal to thresh.

Parameters:
  • sites (Any) – A Sites object, an EDICollection, a sequence of EDIFile objects, or any iterable yielding EDI-like items.

  • thresh (float) – Threshold on phase-error (same units as stored by the processing pipeline, usually degrees).

Returns:

New wrapper containing only sites that pass the phase error test.

Return type:

pycsamt.site.base.Sites

Notes

The check uses a “best effort” attribute lookup and ignores non-finite values during the maximum computation. If the phase-error array is entirely missing, the site is kept. This behavior makes the filter robust when some sites did not store uncertainty products.

Examples

>>> from pycsamt.site.base import Sites
>>> from pycsamt.site.selection import mask_large_phase_err
>>> s = Sites([e1, e2, e3])
>>> out = mask_large_phase_err(s, thresh=10.0)
>>> [t.name for t in out]
['E01', 'E03']

See also

pycsamt.site.selection.keep_finite_z

Keep sites that contain at least one finite impedance.

pycsamt.site.selection.drop_empty

Remove sites with no usable arrays.

pycsamt.site.edit.fill_missing

Allocate arrays and replace invalid entries.

References

pycsamt.site.selection.drop_empty(sites)[source]#

Drop sites that are effectively empty.

A site is considered empty when either:

  • The frequency vector is missing or has zero length.

  • The impedance container Z is missing.

  • The Z container is present but holds no usable arrays (for example, no z and no resistivity surrogate).

Parameters:

sites (Any) – A Sites object, an EDICollection, a sequence of EDIFile objects, or any iterable yielding EDI-like items.

Returns:

New wrapper that excludes empty sites.

Return type:

pycsamt.site.base.Sites

Notes

This is a coarse, fast filter that checks structural presence and basic array availability. It does not test for NaN-only content; for that, consider pycsamt.site.selection.keep_finite_z().

Examples

>>> from pycsamt.site.base import Sites
>>> from pycsamt.site.selection import drop_empty
>>> s = Sites([e1, e2, e3])
>>> out = drop_empty(s)
>>> [t.name for t in out]
['MT01', 'MT02']

See also

pycsamt.site.selection.keep_finite_z

Keep only sites with finite impedance or resistivity.

pycsamt.site.selection.by_freq

Keep sites that touch a target frequency window.