pycsamt.seg.utils#
SEG-EDI helpers: minimal parsing and serialization utilities.
Utility helpers shared by pycsamt.seg sub-modules. The public API is intentionally small – only helpers that are useful outside the core package are exposed.
Functions
Parse measurement definitions from lines. |
|
Write a minimal, valid SEG-EDI text from a structured mapping. |
|
Parse KEY=VALUE pairs from a single line. |
|
|
One-line recap similar to legacy show_stats. |
|
Pretty print collection statistics. |
|
Order EDI sites according to geographic criteria. |
|
Strip a token repeatedly from both ends of strings. |
- pycsamt.seg.utils.sort_edis_by_location(edi_objs, *, by='index', method='strict', metric='cartesian', reference=None, verbose=0)[source]#
Order EDI sites according to geographic criteria.
- Parameters:
edi_objs (Iterable[_Edi]) – Iterable of
Ediobjects.by (str) –
Sorting key:
"ll"or"lonlat"– ascending lon then lat;"latlon"– ascending lat then lon;"distance"– distance from reference;"name"– basename of.edifile;"dataid"– :pyattr:`~pycsamt.seg.heads.Head.dataid`;"index"– first integer found in the filename (default, mimics legacy behaviour).
method (str) –
"strict"(default) uses the selected key only."naive"falls back to filename order when information is ambiguous (identical coordinates).metric (str) – Distance metric when by is
"distance"– one of"cartesian"or"haversine".reference (tuple[float, float] | None) –
(lat, lon)of the origin for distance sorting. When None the first site becomes the origin.verbose (int) – 0 → silent, ≥1 prints a quick recap through :pyfunc:`~pycsamt.seg.stats.quick_edi_stats`.
- Returns:
edi_sorted is a
(N, )numpy array of EDI objects; names the corresponding filenames (without directory).- Return type:
edi_sorted, names
Notes
The function never mutates the input list.
Examples
>>> from pycsamt.seg.utils import sort_edis_by_location >>> edis, names = sort_edis_by_location(my_edi_list, by="lonlat")
- pycsamt.seg.utils.parse_kv_pairs(s)[source]#
Parse KEY=VALUE pairs from a single line.
Handles quoted strings, numeric literals (including Fortran ‘D’ exponents), and D:M:S lat/long. Returns a dictionary with best-effort typing.
Examples
>>> parse_kv_pairs('ID=10011.001 CHTYPE=HX X=0.0 Y=0.0 AZM=0') {'ID': 10011.001, 'CHTYPE': 'HX', 'X': 0.0, 'Y': 0.0, 'AZM': 0}
- pycsamt.seg.utils.gather_measurement_key_value_with_str_parser(lines)[source]#
Parse measurement definitions from lines.
This recognizes blocks like:
>HMEAS ID=... CHTYPE=HX X=... Y=... Z=... AZM=... >EMEAS ID=... CHTYPE=EX X=... Y=... X2=... Y2=...
and returns a list of dicts with a mandatory
"KIND"key ("HMEAS"or"EMEAS") plus all parsed key/value pairs.- Parameters:
lines (iterable of str) – Raw lines from the EDI file.
- Returns:
Each dict contains
"KIND"and the parsed keys.- Return type:
Notes
DMS coordinates (e.g.
26:35:11.0) are converted to decimal degrees.Quoted strings are unquoted.
Numeric tokens (including Fortran
Dexponents) are converted to numbers.
Examples
>>> src = [ ... '>HMEAS ID=10011.001 CHTYPE=HX X=0.0 Y=0.0 AZM=0', ... '>EMEAS ID=10014.001 CHTYPE=EX X=-10.0 Y=0.0 X2=10.0 Y2=0.0', ... ] >>> gather_measurement_key_value_with_str_parser(src)[0]["CHTYPE"] 'HX'
- pycsamt.seg.utils.quick_edi_stats(*, total, ok, label='EDI', width=None)[source]#
One-line recap similar to legacy show_stats.
- pycsamt.seg.utils.minimum_parser_to_write_edi(obj)[source]#
Write a minimal, valid SEG-EDI text from a structured mapping.
This is deliberately small and conservative; it supports the headers and blocks present in your examples and is intended as the last step of the pipeline (the higher-level Edi class should prepare this structure).
Expected structure (keys are optional unless noted):
head(mapping):Keys such as
DATAID,ACQBY,ACQDATE,FILEDATE,PROSPECT,LAT,LONG,ELEV,STDVERS,PROGVERS,PROGDATE,MAXSECT,EMPTY. Values are serialized withKEY=VALUE(quoted if needed).
info(str or list[str]): free text under>INFO.definemeas(mapping):Keys like
MAXCHAN,MAXRUN,MAXMEAS,UNITS,REFTYPE,REFLAT,REFLONG,REFELEV.
measurements(list[dict]): entries produced bygather_measurement_key_value_with_str_parser(). Each must include"KIND".
mtsect(mapping):Must include
SECTID(str) andNFREQ(int). May include channel bindings (HX,HY,HZ,EX,EY,RX,RY).
freq(1-D array-like of float): frequency list.zrot(1-D array-like of float): rotation angles.impedance(mapping): optional numeric blocks with any ofthe standard keys (
ZXXR,ZXXI,ZXX.VAR, …).
resistivity(mapping): optionalRHOXY,RHOXY.ERR,RHOYX,RHOYX.ERR,PHSXY,PHSXY.ERR,PHSYX,PHSYX.ERR.
coherence(list[tuple[str, Sequence[float]]]): optionalpairs of a labelled preamble (e.g.
'COH MEAS1=1 MEAS2=5 ROT=NORTH') and the numeric block.
- Parameters:
obj (mapping) – Structured content as described above.
- Returns:
Text of the EDI file.
- Return type:
Notes
Numeric blocks are formatted at 6 values per line using scientific notation.
If counts are present,
// Nis emitted; otherwise they are inferred from the array length.The function does not touch data ordering; it is up to the caller to ensure
freq,zrotand component arrays are aligned.
Examples
>>> edi_text = minimum_parser_to_write_edi({ ... "head": {"DATAID": "E1_2", "STDVERS": "SEG 1.0", "EMPTY": 1e32}, ... "info": "Processed by pyCSAMT", ... "definemeas": {"MAXCHAN": 16, "UNITS": "M"}, ... "measurements": [{"KIND": "HMEAS", "ID": 1.001, "CHTYPE": "HX"}], ... "mtsect": {"SECTID": "E1_2", "NFREQ": 2, "HX": 1.001}, ... "freq": [7e4, 5.88e4], ... "zrot": [0.0, 0.0], ... }) >>> edi_text.startswith(">HEAD") True
- pycsamt.seg.utils.strip_item(item_to_clean, item=None, multi_space=12)[source]#
Strip a token repeatedly from both ends of strings.
This utility cleans leading/trailing repetitions of a token (default: whitespace) in a flexible way. It accepts a scalar string, a list of strings, or a NumPy array of strings and returns the same container type.
If the input (or all items within) becomes empty after sanitization,
Noneis returned and a warning is issued. This mirrors the legacy behavior where completely blank values are treated as missing.- Parameters:
item_to_clean ({str, list of str, np.ndarray of str}, optional) – The text or collection of texts to sanitize. If
None, returnsNone.item (str, optional) – The token to strip from both ends. If
Noneor a blank string, standard whitespace stripping (str.strip()) is used. For multi-character tokens (e.g.,"//"), the token is removed as repeated whole substrings rather than character sets.multi_space (int, default=12) – Maximum repetition count to consider at each end for a multi-character token (upper bound in the regex quantifier). Must be a positive integer.
- Returns:
Sanitized output preserving the input container type, or
Noneif content is effectively empty after cleaning.- Return type:
Notes
For
itemthat isNone/blank, this function appliesstr.strip()(whitespace). For a non-blankitem, it removes repeated occurrences of that exact token from both ends using a compiled regular expression anchored at the start and end of the string.Returning
Nonefor fully empty results keeps backward compatibility with legacy usage that treats blank fields as missing.
Examples
>>> strip_item(" ss_data ") 'ss_data' >>> strip_item([" a ", " b"], item=None) ['a', 'b'] >>> arr = np.array(["////name////", "////x"], dtype="<U16") >>> strip_item(arr, item="//") array(['name', 'x'], dtype='<U16') >>> strip_item([" ", " "]) is None True
- pycsamt.seg.utils.show_edi_stats(collected, succeeded, *, failed=None, elapsed=None, title='EDI', width=72, sep='~', stream=None)[source]#
Pretty print collection statistics.
- Parameters:
collected (int | Iterable[Any]) – Number of items attempted or an iterable of those items (length will be taken).
succeeded (int | Iterable[Any]) – Number of items successfully processed or an iterable (length will be taken).
failed (int | Iterable[Any] | None) – Number of failed items or an iterable. If None it is inferred:
failed = collected - succeeded.optional – Number of failed items or an iterable. If None it is inferred:
failed = collected - succeeded.elapsed (float | None) – Wall-clock time in seconds.
optional – Wall-clock time in seconds.
title (str) – Short label for the object type (
"EDI"by default).width (int) – Total line width for the banner.
sep (str) – Character used to draw the banner.
stream (TextIO | None) – Output stream (defaults to :pydata:`sys.stdout`).
optional – Output stream (defaults to :pydata:`sys.stdout`).
- Return type:
None