Airborne Time-Domain

This type of survey can be used to store airborne time-domain electromagnetic (ATEM) data defined by a fixed transmitter-receiver loop configuration. The survey is made up of two entities (AirborneTEMTransmitters and AirborneTEMReceivers) linked by their metadata.

The following example shows how to generate an airborne TEM survey with associated data stored in geoh5 format and accessible from Geoscience ANALYST.

atemSurvey

[1]:
import numpy as np

from geoh5py.objects import AirborneTEMReceivers, AirborneTEMTransmitters
from geoh5py.workspace import Workspace


# Create a new project
workspace = Workspace("my_project.geoh5")

# Define the pole locations
n_stations = 9
n_lines = 2
x_loc, y_loc = np.meshgrid(
    np.linspace(0, 60, n_stations), np.linspace(-20, 20.0, n_lines)
)
vertices = np.c_[x_loc.ravel(), y_loc.ravel(), np.zeros_like(x_loc).ravel()]

# Assign a line ID to the poles (vertices)
parts = np.kron(np.arange(n_lines), np.ones(n_stations)).astype("int")

# Create the survey as a coincident loop system
aem_receivers = AirborneTEMReceivers.create(workspace, vertices=vertices, parts=parts)
aem_transmitters = AirborneTEMTransmitters.create(
    workspace, vertices=vertices, parts=parts
)

We have so far created two seperate entities, one for transmitter locations and another for the receivers. In order to finalize the survey, the association must be made between the two entities:

[2]:
aem_receivers.transmitters = aem_transmitters

or equivalently

[3]:
aem_transmitters.receivers = aem_receivers

Only one of the two options above is needed.

Once linked, the two entities will share changes applied to the metadata. For example, changing the input_type property on the transmitters yield:

[4]:
aem_transmitters.input_type = "Tx and Rx"
print(aem_receivers.input_type)
Tx and Rx

Metadata

Along with the survey object itself, the metadata contains all the necessary information to define the geophysical experiment.

[5]:
aem_receivers.metadata
[5]:
{'EM Dataset': {'Channels': [],
  'Input type': 'Tx and Rx',
  'Property groups': [],
  'Receivers': UUID('e035c1a2-91f0-48b7-b51e-f9fc2d16fcb4'),
  'Survey type': 'Airborne TEM',
  'Transmitters': UUID('324a8132-7da3-400b-8d2e-dde34cb3bb2c'),
  'Unit': 'Milliseconds (ms)',
  'Waveform': {'Timing mark': 0.0}}}

Channels

List of time channels at which the data are provided.

[6]:
aem_receivers.channels = np.logspace(-5, -2, 10)  # Simple sweep from 1 to 10 ms

Input type

Label defining how the survey was created.

  • Rx: Survey defined from the AirborneTEMReceivers positions, with theAirborneTEMTransmitters added from offsets.

  • Tx: Survey defined from the AirborneTEMTransmitters position, with theAirborneTEMReceivers added from offsets.

  • Tx and Rx: Survey defined by both the AirborneTEMTransmitters and theAirborneTEMReceivers positions.

Property groups

List of PropertyGroups defining the various data components (e.g. dBzdt, Bz, …). It is expected that each component contains data channels at all times and in the same order as defined in Channels.

The class method add_component_data can help users add data from nested dictionaries. Below is an example using four components:

[7]:
# Create some simple data
def data_fun(t):
    return 1.0 / t * np.sin(np.pi * (x_loc * y_loc).ravel() / 800.0)


# Create a nested dictionary of time data.
data = {
    "dBdt": {
        f"time[{tt}]": {"values": data_fun(time)}
        for tt, time in enumerate(aem_receivers.channels)
    }
}

aem_receivers.add_components_data(data)
[7]:
[<geoh5py.groups.property_group.PropertyGroup at 0x7f61fb6d1b40>]

Metadata are also updated to reflect the addition of component data.

[8]:
aem_receivers.metadata
[8]:
{'EM Dataset': {'Channels': [9.999999999999999e-06,
   2.154434690031882e-05,
   4.6415888336127825e-05,
   9.999999999999999e-05,
   0.00021544346900318823,
   0.00046415888336127773,
   0.001,
   0.002154434690031882,
   0.004641588833612777,
   0.01],
  'Input type': 'Tx and Rx',
  'Property groups': ['dBdt'],
  'Receivers': UUID('e035c1a2-91f0-48b7-b51e-f9fc2d16fcb4'),
  'Survey type': 'Airborne TEM',
  'Transmitters': UUID('324a8132-7da3-400b-8d2e-dde34cb3bb2c'),
  'Unit': 'Milliseconds (ms)',
  'Waveform': {'Timing mark': 0.0}}}

Data channels associated with each component can be quickly accessed through the BaseEMSurvey.components property:

[9]:
aem_receivers.components["dBdt"]
[9]:
[<geoh5py.data.float_data.FloatData at 0x7f61e7953bb0>,
 <geoh5py.data.float_data.FloatData at 0x7f61e7950e80>,
 <geoh5py.data.float_data.FloatData at 0x7f61e79510c0>,
 <geoh5py.data.float_data.FloatData at 0x7f61e7950e20>,
 <geoh5py.data.float_data.FloatData at 0x7f61e7950b50>,
 <geoh5py.data.float_data.FloatData at 0x7f61e7950220>,
 <geoh5py.data.float_data.FloatData at 0x7f61fb501750>,
 <geoh5py.data.float_data.FloatData at 0x7f61fb503d00>,
 <geoh5py.data.float_data.FloatData at 0x7f61fb502ef0>,
 <geoh5py.data.float_data.FloatData at 0x7f61fb503b20>]

Receivers

Generic label used for surveys to identify the receiver entity. References to itself in the case of AirborneTEMReceivers.

Survey type

Static label identifier for Airborne TEM survey type.

Transmitters

Generic label used for surveys to identify the transmitter entity. References to itself in the case of AirborneTEMTransmitters.

Unit

Units for time sampling of the data - must be one of Seconds (s), Milliseconds (ms), Microseconds (us) or Nanoseconds (ns).

Loop radius

Specifies the transmitter loop radius.

Custom fields

Metadata are stored in geoh5 as a json structure allowing for custom data fields to be added to the survey. Information such as flight data, date/time, offsets, etc. can be added as string, float and int.

[10]:
aem_receivers.edit_metadata({"Weather": "sunny"})
/home/docs/checkouts/readthedocs.org/user_builds/mirageoscience-geoh5py/conda/latest/lib/python3.10/site-packages/geoh5py/objects/surveys/electromagnetics/base.py:394: UserWarning: DEPRECATION WARNINGThe method 'edit_metadata' will be deprecated in 0.10 version. It will be replaced by 'edit_em_metadata'
  warn(

atem_custom

Aternatively, a uuid.UUID value can be used if the information is to be provided at every survey position.

[11]:
# Add a new data entry
abc = aem_receivers.add_data(
    {"abc": {"values": np.random.randn(aem_receivers.n_vertices)}}
)

# Assign the data as 'Weather' metadata
aem_receivers.edit_metadata({"Weather": abc.uid})

Geoscience ANALYST will automatically create a link referencing the data field to the entity in the project tree.

atem_uid

Reserved keywords

For known metadata, such as flight dynamics (yaw, pitch, roll) and offsets (inline, crossline, vertical) the suffix property and value will get replaced based on the input value:

[12]:
aem_receivers.yaw = 15.0

atem_yaw_value

[13]:
aem_receivers.yaw = abc.uid  # Assign to the yaw property

atem_yaw_property

[14]:
workspace.close()