First Survey#

This page walks through the first practical pyCSAMT workflow: load a field survey, inspect the station inventory, check parser errors, build a quality table, save a first quality-control figure, and run a small reproducible pipeline.

The examples use EDI files because EDI is the normal exchange format for MT/AMT/CSAMT transfer functions. If your first dataset is a Zonge AVG, J-format, TEM, or intermediate inversion file, start with Data Formats and then return here once you have a collection of EDI sites or a pyCSAMT site collection.

What This First Workflow Should Answer#

A first survey pass is not an inversion and it is not a final interpretation. It is the short diagnostic pass that tells you whether the dataset is ready for deeper processing.

By the end of this page you should know:

  • how many stations were loaded;

  • which stations have coordinates and tipper data;

  • whether any EDI files failed to parse;

  • whether the station/frequency coverage is usable;

  • where pyCSAMT writes first-pass outputs;

  • which documentation page to open next.

Configure The Session#

pyCSAMT has separate configuration layers for API views, plotting style, and pipeline output. For a first run, keep the configuration explicit at the top of the script or notebook.

 1from pycsamt.api import configure_api_view, configure_pipe, use_style
 2
 3configure_api_view(backend="pycsamt")
 4configure_pipe(
 5    output_root="results/first_survey",
 6    show_progress=True,
 7    plot_dpi=200,
 8    plot_fmt="png",
 9)
10use_style("publication")

The configuration call is intentionally lightweight:

configure_api_view(backend="pycsamt")

Keeps returned tables as pyCSAMT APIFrame objects. These objects still expose the underlying pandas dataframe through .df.

configure_pipe(output_root=...)

Sets the default root directory for pipeline outputs when a pipeline run does not receive an explicit outdir.

use_style("publication")

Applies the package plotting defaults for readable saved figures.

For a deeper explanation of these layers, see Configuration.

Read The Survey#

The simplest survey reader is pycsamt.api.read_edis(). It accepts a single file, a directory, or a sequence of files/directories and returns an APISurvey object.

 1from pycsamt.api import read_edis
 2
 3survey = read_edis(
 4    "data/edis",
 5    recursive=True,
 6    strict=False,
 7    on_dup="replace",
 8    progress="auto",
 9)
10
11print(survey)

The important options are:

recursive=True

Search subdirectories below data/edis. This is useful when field exports are grouped by line, date, or crew.

strict=False

Load every readable file and collect parser failures for review. Use strict=True when you want the read operation to fail immediately on the first malformed file.

on_dup="replace"

If duplicate station names are found, keep the last station encountered. Use on_dup="keep" only when you know that the first occurrence is the one you want.

progress="auto"

Shows progress when the current environment supports it.

Inspect The Loaded Survey#

Start with the survey object itself. It exposes a compact public interface for common first-pass questions.

1print("Number of stations:", survey.n_sites)
2print("First stations:", survey.stations[:10])
3print("First paths:", survey.paths[:3])
4
5if survey.n_sites == 0:
6    raise RuntimeError("No EDI stations were loaded.")

survey.stations is the station-name inventory. survey.paths is the source-file inventory. If the station count is lower than expected, check for duplicate names, failed parses, or an input path that does not include all exported EDI files.

Check Parser Errors#

When strict=False, pyCSAMT keeps readable stations and stores parser errors for the files that could not be loaded. Always check these errors before trusting a first survey summary.

1errors = survey.errors()
2
3if errors:
4    print(f"{len(errors)} file(s) could not be read.")
5    for path, exc in errors[:5]:
6        print(f"- {path}: {type(exc).__name__}: {exc}")
7else:
8    print("All discovered EDI files were read successfully.")

If only a few files fail, you can continue with QC while you repair or remove the bad files. If many files fail, stop and inspect the export format before running processing steps.

Build A Station Summary#

survey.summary() returns an APIFrame. It prints cleanly in terminals, but it also behaves like a dataframe wrapper.

1summary = survey.summary()
2print(summary)
3
4station_table = summary.df
5print(station_table.head())
6print(station_table.columns)

For first-pass review, the most useful columns are usually:

station

Station name resolved from the EDI metadata or file identity.

n_freq

Number of frequency samples available for the station.

period_min and period_max

Period range represented by the station.

has_tipper

Whether vertical-field transfer-function information is available.

lat and lon

Geographic coordinates when present in the EDI metadata.

You can request a smaller station table when preparing a report or debugging specific metadata.

1compact = survey.summary(
2    fields=("station", "n_freq", "period_min", "period_max", "lat", "lon")
3)
4print(compact.df)

Inspect One Station#

Before plotting the whole survey, inspect one station object. This confirms that station naming, frequency arrays, impedance tensors, and optional tipper metadata are reachable.

 1station_name = survey.stations[0]
 2site = survey.get_site(station_name)
 3
 4print("Station:", station_name)
 5print(site)
 6
 7# Many EDI-like objects expose these attributes.  Use getattr so the
 8# first workflow remains tolerant of partial metadata.
 9print("Path:", getattr(site, "path", None))
10print("Frequencies:", getattr(site, "freq", None))
11print("Has tipper:", getattr(site, "tipper", None) is not None)

If survey.get_site(name) returns None, the station name you supplied does not match a loaded station, filename stem, or source path.

Use The Public Table Helper#

The survey object is convenient when you want to keep a loaded collection in memory. For a quick script, the public table helper can read a directory and return a station summary in one call.

 1from pycsamt.api import sites_summary
 2
 3sites = sites_summary(
 4    "data/edis",
 5    recursive=True,
 6    strict=False,
 7    on_dup="replace",
 8)
 9
10print(sites)
11print(sites.df.head())

Use read_edis when the next step will reuse the same loaded survey. Use sites_summary when you only need a station inventory table.

Build A First Quality Table#

The station inventory tells you what was loaded. The quality table starts to answer whether the transfer-function data are suitable for processing.

1from pycsamt.api import quality_dataframe
2
3quality = quality_dataframe(survey.to_collection())
4print(quality)
5print(quality.df.head())

Depending on the metadata available in the loaded EDI files, the quality table may include coverage, missing-value, uncertainty, and station-level diagnostic columns. Treat it as a screening table: it helps you identify stations that deserve closer plotting, not as a replacement for geophysical judgment.

Save A First QC Figure#

A confidence profile is a compact first figure because it reduces the station quality assessment to one value per station along the profile. It is a good way to spot stations that require cleaning, masking, or removal before inversion.

 1from pathlib import Path
 2
 3import matplotlib.pyplot as plt
 4
 5from pycsamt.emtools.qc import plot_confidence_profile
 6
 7outdir = Path("results/first_survey")
 8outdir.mkdir(parents=True, exist_ok=True)
 9
10ax = plot_confidence_profile(
11    survey.to_collection(),
12    method="composite",
13    ci_hi=0.95,
14    ci_lo=0.50,
15    station_label_step=None,
16)
17fig = ax.get_figure()
18fig.savefig(outdir / "station_confidence_profile.png", dpi=200,
19            bbox_inches="tight")
20plt.close(fig)

Use method="presence" for a very simple completeness check. Use method="composite" when you want a more informative first-pass score that combines several transfer-function diagnostics.

For a station-frequency view, save a pseudo-section as well.

 1from pycsamt.emtools.qc import plot_frequency_confidence_psection
 2
 3ax = plot_frequency_confidence_psection(
 4    survey.to_collection(),
 5    method="composite",
 6)
 7fig = ax.get_figure()
 8fig.savefig(outdir / "frequency_confidence_psection.png", dpi=200,
 9            bbox_inches="tight")
10plt.close(fig)

The station profile shows where weak stations are located along the line. The frequency pseudo-section shows whether the weak data are isolated at particular periods or distributed through an entire station.

Run A First Pipeline#

Once the survey can be read and inspected, run the built-in basic_qc preset. This is the recommended first pipeline because it is small enough for fast feedback and structured enough to produce reproducible outputs.

 1from pycsamt.pipeline import Pipeline
 2
 3pipe = Pipeline.from_preset("basic_qc")
 4print(pipe)
 5
 6result = pipe.run(
 7    survey.to_collection(),
 8    outdir="results/first_survey/basic_qc",
 9    save_plots=True,
10    save_edis=True,
11    save_report=True,
12)
13
14print(result.summary())
15print("Pipeline ok:", result.ok)
16print("Step errors:", result.n_errors)
17print("Output directory:", result.outdir)

The pipeline writes a reproducible run directory. The exact files depend on the enabled output settings and the steps in the preset, but the first things to inspect are:

pipeline.yaml

The pipeline configuration that produced the run.

reports/

Text or HTML summaries of the run, including step status.

plots/

QC plots produced by the pipeline steps.

processed/

Processed EDI files when save_edis=True.

If result.ok is False, inspect the reported step errors before using the processed files. With the default warning policy, a failed step may leave the previous station collection in place so that the rest of the run can continue.

Command-Line Equivalent#

The same first pass can be started from the command line. These commands are useful for quick validation, automation, and sharing a workflow with another developer.

 1pycsamt edi info data/edis
 2pycsamt edi stations data/edis --format text
 3pycsamt edi validate data/edis
 4
 5pycsamt pipe run data/edis \
 6    --preset basic_qc \
 7    --out results/first_survey/basic_qc \
 8    --on-error warn \
 9    --dpi 200 \
10    --plot-fmt png

Use pycsamt pipe run ... --dry-run before a long run to confirm that the survey path, preset, step count, and output directory resolve as expected.

1pycsamt pipe run data/edis \
2    --preset basic_qc \
3    --out results/first_survey/basic_qc \
4    --dry-run

First-Survey Checklist#

Before moving to filtering, static-shift correction, dimensionality analysis, or inversion preparation, confirm the following:

  • survey.n_sites matches the expected number of field stations.

  • survey.errors() is empty or every failed file is understood.

  • Station names are unique and ordered as expected.

  • Coordinates are present when profile distance or maps matter.

  • Frequency/period ranges are comparable across neighbouring stations.

  • Missing tipper data are expected, or downstream steps do not require tipper.

  • The confidence profile does not show unexplained clusters of weak stations.

  • The pipeline report has no unexpected failed steps.

  • The output directory contains the run configuration and generated reports.

Troubleshooting#

No stations are loaded

Check that the input path exists and contains files with an EDI extension. If the files are nested by survey line or date, keep recursive=True.

The station count is too low

Look for duplicate station names and parser errors. Re-run with on_dup="keep" if the first duplicate should win, or fix station names in the source files before processing.

Many files appear in survey.errors()

Confirm the files are EDI files rather than SEG blocks, Zonge AVG files, or another export format. See Data Formats for format-specific entry points.

Coordinates are missing

The EDI metadata may not include latitude and longitude. You can still inspect frequencies and transfer functions, but maps and distance-based plots require station-location metadata.

The plot is empty

Confirm that the survey contains stations and that the station objects expose frequency and impedance arrays. If the dataset is partial, try a simpler table first with survey.summary().df.

The pipeline writes somewhere unexpected

Pass outdir=... to Pipeline.run or --out ... to the CLI. The pipeline otherwise falls back to its own configured output directory and then to the global pipeline configuration.

Where To Go Next#

After a successful first survey pass, continue with the page that matches your task:

  • Data Formats for converting or understanding non-EDI inputs.

  • Read an EDI Survey for a deeper EDI-reading tutorial.

  • Inspect and QC a Survey for richer station diagnostics.

  • ../pipeline/presets for choosing a processing preset.

  • ../pipeline/outputs for understanding generated pipeline files.

  • Prepare an Occam2D Inversion when the data are ready for Occam2D preparation.

  • ../agents/overview if you want the AI-assisted agents to help review a survey, plan processing, or summarize results.

In Short#

A good first pyCSAMT survey pass is deliberately simple:

 1from pycsamt.api import read_edis, quality_dataframe
 2from pycsamt.pipeline import Pipeline
 3
 4survey = read_edis("data/edis", strict=False)
 5print(survey)
 6print(survey.summary().df.head())
 7print(quality_dataframe(survey.to_collection()).df.head())
 8
 9pipe = Pipeline.from_preset("basic_qc")
10result = pipe.run(survey.to_collection(), outdir="results/first_survey")
11print(result.summary())

If this short script reads the survey, prints sensible station tables, and produces a successful basic_qc run, the project is ready for deeper processing.