Note
Go to the end to download the full example code.
Workbench XYZ
This example supports data and models read from Aarhus Workbench XYZ files. What’s unique about these files is that metadata is embedded in the header of the data files, such as the electromagnetic gate times.
The workbench file handler detects when an XYZ file matches this format and parses out the metadata to be joined with additional metadata passed from a YAML file.
Source Reference: U.S. Geological Survey, 2024, Airborne electromagnetic and magnetic survey of Delaware Bay and surrounding regions of New Jersey and Delaware, 2022 (ver 2.0, April 2025): U.S. Geological Survey data release, https://doi.org/10.5066/F7J96592.
import matplotlib.pyplot as plt
from os.path import join
import numpy as np
import gspy
Initialize the Survey
1dataset_attrs:
2 title: Airborne electromagnetic and magnetic survey of Delaware Bay and surrounding regions of New Jersey and Delaware, 2022
3 institution: USGS Geology, Geophysics, and Geochemistry Science Center
4 source: SkyTEM provided raw data, USGS generated inverted resistivity models
5 history: Data acquisition 07/15/2022 - 08/03/2022 by SkyTEM Canada Inc. AEM and magnetic data processing by SkyTEM Canada Inc. 08/2022 - 10/2022. Raw and minimally processed AEM data, and processed magnetic data, received by USGS from SkyTEM Canada Inc 10/2022. Minimally processed AEM data were exported to netCDF using GSPy version 1.0.1 11/2023. Minimally processed binary data received from the contractor were imported into the Aarhus Workbench software (v 6 - 2024.2, Aarhus Geosoftware, Aarhus, Denmark) and processed. Filters were applied to inclinometer and spatial positioning data to smooth raw data and remove sensor dropouts. Altimeter data were filtered, smoothed, and manually edited to correct false altitudes associated with trees, open water, and other obstacles, resulting in processed altitude representative of the distance between the AEM sensor airframe and bare earth. Raw electromagnetic data were visually examined for couplings and noise associated with infrastructure and considered in the context of the locations of known or suspected infrastructure (power lines, pipelines, etc...) and magnetic anomalies; impacted data were manually removed. Some infrastructure-impacted data may remain in the processed dataset. Culled electromagnetic data were spatially averaged using a sounding distance of 1.5 seconds and trapezoidal filter widths of 1.5, 3, and 6 seconds at gate times 1e-5, 5e-4, and 1e-3 seconds (low-moment data) and 3, 3, and 6 seconds at 1e-4, 1e-3, and 1e-2 seconds (high-moment data). Low-signal data were removed from the averaged data through a combination of filters and manual culling. Deterministic inversion of the processed AEM data was implemented in Aarhus Workbench software (v 6 - 2024.2, Aarhus Geosoftware, Aarhus, Denmark) by USGS. Inversion parameters were selected by running a series of test models with varying starting model resistivity values, layer discretization, vertical/lateral constraints, and other inversion parameters. Laterally constrained blocky inversion models were developed using a 40-layer domain with layer top depths ranging between 1 and 300 meters and layer thickness increasing with depth. Inversions were run with vertical and lateral constraints of values of 4.0 and 2.0, respectively, and a spatially varying, data-dependent homogenous half-space starting model. Sensor altitude was treated as a free parameter after the 8th iteration. Depth of investigation was constrained to depths between 5 and 400 meters.
6 references: "U.S. Geological Survey, 2024, Airborne electromagnetic and magnetic survey of Delaware Bay and surrounding regions of New Jersey and Delaware, 2022 (ver 2.0, April 2025): U.S. Geological Survey data release, https://doi.org/10.5066/F7J96592."
7 comment: These data are a subset from the referenced data release, included here for demonstration purposes only
8 content: Delaware Bay SkyTEM survey information
9 summary: Airborne electromagnetic (AEM) and magnetic survey data were collected during July and August 2022 over a distance of 3,588.5 line kilometers covering Delaware Bay and surrounding regions in New Jersey and Delaware. Data were collected as part of the USGS Delaware River Basin Next Generation Water Observing Systems (NGWOS) project to improve understanding of groundwater salinity distributions near Delaware Bay. The survey was primarily funded by the USGS, with partial support through collaboration with the University of Delaware to extend data collection to parts of Rehoboth Bay and Indian River Bay. Data were acquired by SkyTEM Canada Inc. with the SkyTEM 304M time-domain helicopter-borne electromagnetic system together with a Geometrics G822A cesium vapor magnetometer. The survey was acquired at a nominal flight height of 30 - 40 m above terrain along parallel flight lines primarily oriented southwest-northeast and with nominal line spacing of 500 m over land and nearshore, and 3000 m over open-water parts of Delaware Bay. Several irregular flightlines were acquired along, and perpendicular to, nearby rivers to capture salinity patterns along these hydrologic flowpaths. Version 2.0 includes additional processed AEM data and inverted resistivity models.
10
11survey_information:
12 contractor_project_number: 20048
13 contractor: SkyTEM Canada Inc
14 client: U.S. Geological Survey
15 survey_type: ['electromagnetic', 'magnetic']
16 survey_area_name: Delaware Bay
17 state: DE, NJ
18 country: USA
19 acquisition_start: 20220715
20 acquisition_end: 20220803
21 dataset_created: 20231108
22
23survey_units:
24 time: seconds [s]
25 area: square meters [m^2]
26 current: Amperes [A]
27 frequency: Hertz [Hz]
28 angle: Degree [deg]
29 electromagnetic_moment: Ampere square meters [Am^2]
30 magnetometer_b_field: nanoTesla [nT]
31 electromagnetic_dbdt: picoVolt per Ampere per meters to the power 4 [pV/(Am^4)]
32
33spatial_ref:
34 wkid: 32618
35 authority: EPSG
36 vertical_crs: NAVD88
37
38flightline_information:
39 traverse_line_spacing: [ 500 3000]
40 traverse_line_direction: ['sw-ne', 'variable']
41 tie_line_spacing: n/a
42 tie_line_direction: n/a
43 nominal_terrain_clearance: 30 - 40 m
44 final_line_kilometers: 3588.5
45 traverse_line_numbers: 100101 - 104201, 200101 - 202401, 300101 - 306301, 400101 - 415103, 500101 - 509201
46 repeat_line_numbers: 900101 - 900106
47 pre_zero_line_numbers: n/a
48 post_zero_line_numbers: n/a
49
50survey_equipment:
51 aircraft: Eurocopter Astar 350 B3
52 magnetometer: Geometrics G822A, Kroum KMAG4 counter
53 magnetometer_installation: Front of transmitter frame
54 electromagnetic_system: SkyTEM 304M
55 electromagnetic_installation: Rigid transmitter frame 40m beneath helicopter, Receiver coils at rear of transmitter frame
56 spectrometer_system: n/a
57 spectrometer_installation: n/a
58 radar_altimeter_system: n/a
59 radar_altimeter_installation: n/a
60 laser_altimeter_system: MDL ILM300R (2)
61 laser_altimiter_installation: Two laser units mounted on transmitter frame
62 laser_altimiter_information: sample frequency = 30 Hz; uncertainty = 10-30 cm; min/max range = 0.2-200 m
63 inclinometer_system: Bjerre Technology inclinometers (2)
64 inclinometer_installation: Two inclinometers rear of frame near z coil.
65 inclinometer_information: x-angle is parallel to flight direction and positive when front of frame is above horizontal. y-angle is perpendicular to flight direction and negative when the right side of the frame is above horizontal
66 gps_system: Real-time differential GPS Trimble Bullet III (2)
67 gps_installation: Two DGPS sensors on transmitter frame
68 gps_information: position uncertainty = 1m; gps sample frequency = 1 Hz
69 acquisition_system: skytem
Path to example files
data_path = '..//data_files/workbench'
Survey Metadata file
metadata = join(data_path, "survey.yml")
# Establish survey instance
survey = gspy.Survey.from_dict(metadata)
Create a ‘data’ branch and attach data leaves
Make the branch
data_container = survey.gs.add_container('data', **dict(content = "raw data"))
Point to Workbench XYZ data files
d_data = join(data_path, 'data//prod_726_729raw_RAW_export.xyz')
d_supp = join(data_path, 'data//raw_data.yml')
# Add the raw AEM data
rd = data_container.gs.add(key='raw_data', data_filename=d_data, metadata_file=d_supp)
Create a ‘models’ branch and attach data leaves
Make the branch
model_container = survey.gs.add_container('models', **dict(content='inverse models'))
Import Workbench XYZ inversion results (syn/dat/inv)
GSPy automatically recognizes Workbench inversion files (syn/dat/inv), only one of the three files need to be passed to provide the base filename
d_data = join(data_path, 'model//prod_726_729_LBv2_bky_MOD_dat.xyz')
d_supp = join(data_path, 'model//models.yml')
md = model_container.gs.add(key='inversion', data_filename=d_data, metadata_file=d_supp)
Detected gate_time metadata from the workbench files
{'hm_gate_times': {'centers': array([7.292e-05, 7.641e-05, 8.091e-05, 8.641e-05, 9.342e-05, 1.024e-04,
1.139e-04, 1.284e-04, 1.464e-04, 1.689e-04, 1.969e-04, 2.324e-04,
2.779e-04, 3.349e-04, 4.069e-04, 4.979e-04, 6.119e-04, 7.559e-04,
9.374e-04, 1.166e-03, 1.454e-03, 1.818e-03, 2.277e-03, 2.855e-03,
3.574e-03, 4.454e-03, 5.531e-03, 6.849e-03, 8.463e-03, 1.044e-02]),
'long_name': 'calibrated high moment gate times',
'missing_value': 'not_defined',
'standard_name': 'hm_gate_times',
'units': 'seconds'},
'lm_gate_times': {'centers': array([1.273e-05, 1.622e-05, 2.072e-05, 2.622e-05, 3.323e-05, 4.222e-05,
5.372e-05, 6.822e-05, 8.622e-05, 1.087e-04, 1.367e-04, 1.722e-04,
2.177e-04, 2.747e-04, 3.467e-04, 4.377e-04, 5.517e-04, 6.957e-04,
8.772e-04, 1.106e-03, 1.394e-03]),
'long_name': 'calibrated low moment gate times',
'missing_value': 'not_defined',
'standard_name': 'lm_gate_times',
'units': 'seconds'}}
Save to NetCDF file
d_out = join(data_path, 'workbench_example.nc')
survey.gs.to_netcdf(d_out)
Inspect survey
print(survey.dataset)
<xarray.DatasetView> Size: 40B
Dimensions: ()
Coordinates:
spatial_ref float64 8B 0.0
Data variables:
survey_information float64 8B nan
survey_units float64 8B nan
flightline_information float64 8B nan
survey_equipment float64 8B nan
Attributes:
type: survey
title: Airborne electromagnetic and magnetic survey of Delaware B...
institution: USGS Geology, Geophysics, and Geochemistry Science Center
source: SkyTEM provided raw data, USGS generated inverted resistiv...
history: Data acquisition 07/15/2022 - 08/03/2022 by SkyTEM Canada ...
references: U.S. Geological Survey, 2024, Airborne electromagnetic and...
comment: These data are a subset from the referenced data release, ...
content: Delaware Bay SkyTEM survey information /survey; raw data /...
summary: Airborne electromagnetic (AEM) and magnetic survey data we...
gspy_version: 2.2.4
conventions: GS-2.0, CF-1.13
Inspect the two branches
Data Branch
print(survey['data'])
<xarray.DataTree 'data'>
Group: /survey/data
│ Dimensions: ()
│ Data variables:
│ spatial_ref float64 8B 0.0
│ Attributes:
│ content: raw data
│ type: container
└── Group: /survey/data/raw_data
│ Dimensions: (index: 338, lm_gate_times: 28, hm_gate_times: 37)
│ Coordinates:
│ * index (index) int32 1kB 0 1 2 3 4 5 6 ... 332 333 334 335 336 337
│ * lm_gate_times (lm_gate_times) float64 224B 1e-07 2.25e-07 ... 0.001394
│ * hm_gate_times (hm_gate_times) float64 296B 5.892e-05 ... 0.01044
│ spatial_ref float64 8B 0.0
│ x (index) float64 3kB 1.746e+06 1.746e+06 ... 1.745e+06
│ y (index) float64 3kB 1.981e+06 1.981e+06 ... 1.983e+06
│ z (index) float64 3kB 4.82 5.19 5.31 5.66 ... 5.44 5.26 5.21
│ Data variables: (12/15)
│ date (index) object 3kB '2022-07-26' ... '2022-07-26'
│ time (index) object 3kB '12:36:24.002' ... '12:42:21.342'
│ line_no (index) int64 3kB 101201 101201 101201 ... 200801 200801
│ rx_altitude (index) float64 3kB 50.75 49.58 49.3 ... 29.92 31.33 31.79
│ rx_altitude_std (index) float64 3kB 1.061 1.062 1.063 ... 1.105 1.1 1.098
│ tx_altitude (index) float64 3kB 48.13 46.82 46.41 ... 27.26 28.68 29.13
│ ... ...
│ tilt_y (index) float64 3kB 3.8 3.3 3.3 3.0 2.8 ... 2.0 1.9 1.1 0.9
│ tilt_y_std (index) float64 3kB 1.004 1.004 1.004 ... 1.004 1.004 1.004
│ dbdt_lm_z (index, lm_gate_times) float64 76kB 9.999e+03 ... 9.999e+03
│ dbdt_std_lm_z (index, lm_gate_times) float64 76kB 9.999e+03 ... 9.999e+03
│ dbdt_hm_z (index, hm_gate_times) float64 100kB nan nan ... nan nan
│ dbdt_std_hm_z (index, hm_gate_times) float64 100kB nan nan ... nan nan
│ Attributes:
│ content: raw data
│ comment: example raw data imported from XYZ format
│ type: data
│ structure: tabular
│ mode: airborne
│ method: electromagnetic, time domain
│ instrument: skyTEM 304M
└── Group: /survey/data/raw_data/nominal_system
Dimensions: (gate_times: 22, nv: 2,
lm_gate_times: 28,
hm_gate_times: 37,
n_loop_vertices: 8, xyz: 3,
n_transmitter: 2,
transmitter_lm_waveform_time: 21,
transmitter_hm_waveform_time: 36,
n_receiver: 1, n_couplet: 2)
Coordinates:
* gate_times (gate_times) float64 176B 5....
* nv (nv) int64 16B 0 1
* n_loop_vertices (n_loop_vertices) int64 64B ...
* xyz (xyz) int64 24B 0 1 2
* n_transmitter (n_transmitter) int64 16B 0 1
* transmitter_lm_waveform_time (transmitter_lm_waveform_time) float64 168B ...
* transmitter_hm_waveform_time (transmitter_hm_waveform_time) float64 288B ...
* n_receiver (n_receiver) int64 8B 0
* n_couplet (n_couplet) int64 16B 0 1
Data variables: (12/32)
gate_times_bnds (gate_times, nv) float64 352B ...
lm_gate_times_bnds (lm_gate_times, nv) float64 448B ...
hm_gate_times_bnds (hm_gate_times, nv) float64 592B ...
n_loop_vertices_bnds (n_loop_vertices, nv) float64 128B ...
xyz_bnds (xyz, nv) float64 48B -0.5 ....
transmitter_label (n_transmitter) <U2 16B 'lm'...
... ...
couplet_sample_rate (n_couplet) float64 16B 0.1 0.1
couplet_txrx_dx (n_couplet) float64 16B -13....
couplet_txrx_dy (n_couplet) float64 16B 0.0 0.0
couplet_txrx_dz (n_couplet) float64 16B -2.0...
couplet_data_type (n_couplet) <U4 32B 'dBdt' '...
couplet_gate_times (n_couplet) <U13 104B 'lm_ga...
Attributes:
type: system
mode: airborne
method: electromagnetic, time domain
instrument: skyTEM 304M
name: nominal_system
data_normalized: True
skytem_skb_gex_available: True
reference_frame: right-handed positive down
coil_orientations: X, Z
sample_rate: 0.1
Models Branch
print(survey['models'])
<xarray.DataTree 'models'>
Group: /survey/models
│ Dimensions: ()
│ Data variables:
│ spatial_ref float64 8B 0.0
│ Attributes:
│ content: inverse models
│ type: container
└── Group: /survey/models/inversion
│ Dimensions: (index: 926, layer_depth: 40, nv: 2,
│ layers_minus_1: 39, lm_gate_times: 21,
│ hm_gate_times: 30)
│ Coordinates:
│ * index (index) int32 4kB 0 1 2 3 4 5 ... 921 922 923 924 925
│ * layer_depth (layer_depth) float64 320B 0.25 0.7788 ... 284.3 375.0
│ * nv (nv) int64 16B 0 1
│ * layers_minus_1 (layers_minus_1) int64 312B 0 1 2 3 4 ... 35 36 37 38
│ * lm_gate_times (lm_gate_times) float64 168B 1.273e-05 ... 0.001394
│ * hm_gate_times (hm_gate_times) float64 240B 7.292e-05 ... 0.01044
│ spatial_ref float64 8B 0.0
│ x (index) float64 7kB 4.614e+05 4.614e+05 ... 4.8e+05
│ y (index) float64 7kB 4.333e+06 4.333e+06 ... 4.359e+06
│ z (index) float64 7kB 6.4 5.8 5.2 4.7 ... 0.4 0.4 0.4 0.3
│ Data variables: (12/28)
│ layer_depth_bnds (layer_depth, nv) float64 640B 0.0 0.5 ... 300.0 450.0
│ layers_minus_1_bnds (layers_minus_1, nv) float64 624B -0.5 0.5 ... 38.5
│ lm_gate_times_bnds (lm_gate_times, nv) float64 336B -3.145e-06 ... 0.00141
│ hm_gate_times_bnds (hm_gate_times, nv) float64 480B 2.742e-05 ... 0.01049
│ line_no (index) int64 7kB 101201 101201 ... 103801 103801
│ date (index) object 7kB '2022-07-26' ... '2022-07-26'
│ ... ...
│ lm_z_data (index, lm_gate_times) float64 156kB 3.208e-09 ... 9...
│ lm_z_datastd (index, lm_gate_times) float64 156kB 1.03 ... 9.999e+03
│ hm_z_data (index, hm_gate_times) float64 222kB nan ... 9.999e+03
│ hm_z_datastd (index, hm_gate_times) float64 222kB nan ... 9.999e+03
│ lm_z_syn (index, lm_gate_times) float64 156kB 3.274e-09 ... 9...
│ hm_z_syn (index, hm_gate_times) float64 222kB nan ... 9.999e+03
│ Attributes:
│ content: inverted resistivity models with input data and synthetic re...
│ comment: This dataset includes AEM inverted models produced by USGS u...
│ type: model, data
│ structure: tabular
│ mode: airborne
│ method: electromagnetic, time domain
│ instrument: skyTEM 304M
│ property: electrical resistivity
├── Group: /survey/models/inversion/nominal_system
│ Dimensions: (lm_gate_times: 21, nv: 2,
│ hm_gate_times: 30,
│ n_loop_vertices: 8, xyz: 3,
│ n_transmitter: 2,
│ transmitter_lm_waveform_time: 21,
│ transmitter_hm_waveform_time: 36,
│ n_receiver: 1, n_couplet: 2)
│ Coordinates:
│ * n_loop_vertices (n_loop_vertices) int64 64B ...
│ * xyz (xyz) int64 24B 0 1 2
│ * n_transmitter (n_transmitter) int64 16B 0 1
│ * transmitter_lm_waveform_time (transmitter_lm_waveform_time) float64 168B ...
│ * transmitter_hm_waveform_time (transmitter_hm_waveform_time) float64 288B ...
│ * n_receiver (n_receiver) int64 8B 0
│ * n_couplet (n_couplet) int64 16B 0 1
│ Data variables: (12/33)
│ lm_gate_times_bnds (lm_gate_times, nv) float64 336B ...
│ hm_gate_times_bnds (hm_gate_times, nv) float64 480B ...
│ n_loop_vertices_bnds (n_loop_vertices, nv) float64 128B ...
│ xyz_bnds (xyz, nv) float64 48B -0.5 ....
│ transmitter_label (n_transmitter) <U2 16B 'lm'...
│ transmitter_number_of_turns (n_transmitter) int64 16B 1 4
│ ... ...
│ couplet_sample_rate (n_couplet) float64 16B 0.1 0.1
│ couplet_txrx_dx (n_couplet) float64 16B -13....
│ couplet_txrx_dy (n_couplet) float64 16B 0.0 0.0
│ couplet_txrx_dz (n_couplet) float64 16B -2.0...
│ couplet_data_type (n_couplet) <U4 32B 'dBdt' '...
│ couplet_gate_times (n_couplet) <U13 104B 'lm_ga...
│ Attributes:
│ type: system
│ mode: airborne
│ method: electromagnetic, time domain
│ instrument: skyTEM 304M
│ name: nominal_system
│ data_normalized: True
│ skytem_skb_gex_available: True
│ reference_frame: right-handed positive down
│ coil_orientations: X, Z
│ sample_rate: 0.1
└── Group: /survey/models/inversion/inversion_parameters
Dimensions: (dim_0: 1)
Dimensions without coordinates: dim_0
Data variables:
model_file <U33 132B 'prod_726_729_LBv2_bky_MOD_inv.xyz'
inversion_software <U46 184B 'Workbench, Aarhus Geosoftware, Aarhus, Den...
software_version <U33 132B 'Aarhus Workbench version 6 2024.2'
date (dim_0) int64 8B 2024
number_of_layers (dim_0) int64 8B 40
constraints <U21 84B 'laterally constrained'
description <U805 3kB 'Deterministic inversion of the processed A...
data_file <U30 120B 'prod_726_729raw_RAW_export.xyz'
Attributes:
type: parameters
method: electromagnetic, time domain
instrument: skyTEM 304M
mode: airborne
property: electrical resistivity
name: inversion_parameters
Total running time of the script: (0 minutes 0.824 seconds)