Survey

class emg3d.surveys.Survey(name, sources, receivers, frequencies, data=None, fixed=0, **kwargs)[source]

Bases: object

Create a survey with sources, receivers, and data.

A survey contains all the sources with their frequencies, receivers, and corresponding data.

Underlying the survey-class is an xarray, which is basically a regular ndarray with axis labels and more. The module xarray is a soft dependency, and has to be installed manually to use the Survey functionality.

This class was developed with a node-based, marine CSEM survey layout in mind. It is therefore optimised for and mostly tested with that setup. This means for a number of receivers which measure for all source positions. The general layout of the data for such a survey is (S, R, F), where S is the number of sources, R the number of receivers, and F the number of frequencies:

                      f1
     Rx1 Rx2  .  RxR /   f2
    ┌───┬───┬───┬───┐   /   .
Tx1 │   │   │   │   │──┐   /   fF
    ├───┼───┼───┼───┤  │──┐   /
Tx2 │   │   │   │   │──┤  │──┐
    ├───┼───┼───┼───┤  │──┤  │
 .  │   │   │   │   │──┤  │──┤
    ├───┼───┼───┼───┤  │──┤  │
TxS │   │   │   │   │──┤  │──┤
    └───┴───┴───┴───┘  │──┤  │
       └───┴───┴───┴───┘  │──┤
          └───┴───┴───┴───┘  │
             └───┴───┴───┴───┘

However, the class can also be used for a CSEM streamer-style survey layout (by setting fixed=True), where there is a moving source with one or several receivers at a fixed offset. The layout of the data is then also (S, R, F), but here S is the number of locations of the only source, R is the number of receiver-offsets, and F is the number of frequencies:

                                 f1
         Offs1     .   OffsR    /   .
       ┌─────────┬───┬─────────┐   /   fF
TxPos1 │ Rx1-TP1 │ . │ RxR-TP1 │──┐   /
       ├─────────┼───┼─────────┤  │──┐
TxPos2 │ Rx1-TP2 │ . │ RxR-TP2 │──┤  │
       ├─────────┼───┼─────────┤  │──┤
 .     │ .       │ . │ .       │──┤  │
       ├─────────┼───┼─────────┤  │──┤
TxPosS │ Rx1-TPS │ . │ RxR-TPS │──┤  │
       └─────────┴───┴─────────┘  │──┤
          └─────────┴───┴─────────┘  │
             └─────────┴───┴─────────┘

This means that even though there is only one source, there are actually S source dipoles, as each position is treated as a different dipole. The number of receiver dipoles in this case is SxR. This setup can also be used for airborne EM.

Parameters:
name : str

Name of the survey

sources, receivers : tuple, list, or dict

Sources and receivers.

  • Tuples: Coordinates in one of the two following formats:

    • (x, y, z, azimuth, dip) [m, m, m, °, °];
    • (x0, x1, y0, y1, z0, z1) [m, m, m, m, m, m].

    Dimensions will be expanded (hence, if n dipoles, each parameter must have length 1 or n). These dipoles will be named sequential with Tx### and Rx###.

    The tuple can additionally contain an additional element at the end (after dip or z1), electric, a boolean of length 1 or n, that indicates if the dipoles are electric or magnetic.

  • List: A list of Dipole-instances. The names of all dipoles in the list must be unique.

  • Dictionary: A dict of de-serialized Dipole-instances; mainly used for loading from file.

frequencies : ndarray

Source frequencies (Hz).

data : ndarray or None

The observed data (dtype=np.complex128); must have shape (nsrc, nrec, nfreq) or, if fixed=True, (nsrc, noff, nfreq). If None, it will be initiated with NaN’s.

fixed : bool

Node-based CSEM survey (fixed=False; default) or streamer-type CSEM survey (fixed=True). In the streamer-type survey, the number of receivers supplied must be a multiple of the source positions. In this case, the receivers are grouped into offsets.

noise_floor, relative_error : float

Noise floor and relative error of the data. Default to None. See Survey.standard_deviation for more info.

std : ndarray or None

Standard deviation of the data, same shape as data. Default to None. See Survey.standard_deviation for more info.

Attributes Summary

data Data, a xarray.DataSet instance.
frequencies Frequency array.
noise_floor Returns the noise floor of the data.
observed Returns the observed data.
rec_coords Return receiver coordinates.
receivers Receiver dict containing all receiver dipoles.
relative_error Returns the relative error of the data.
shape Return nsrc x nrec x nfreq.
size Return actual data size (does NOT equal nsrc x nrec x nfreq).
sources Source dict containing all source dipoles.
src_coords Return source coordinates.
standard_deviation Returns the standard deviation of the data.

Methods Summary

copy() Return a copy of the Survey.
from_dict(inp) Convert dictionary into Survey instance.
from_file(fname[, name]) Load Survey from a file.
to_dict([copy]) Store the necessary information of the Survey in a dict.
to_file(fname[, name]) Store Survey to a file.

Attributes Documentation

data

Data, a xarray.DataSet instance.

Contains the xarray.DataArray element .observed, but other data can be added. E.g., emg3d.simulations.Simulation adds the synthetic array.

frequencies

Frequency array.

noise_floor

Returns the noise floor of the data.

See emg3d.surveys.Survey.standard_deviation for more info.

observed

Returns the observed data.

rec_coords

Return receiver coordinates.

The returned format is (x, y, z, azm, dip), a tuple of 5 tuples. If fixed=True it returns a dict with the offsets as keys, and for each offset it returns the corresponding receiver coordinates as just outlined.

receivers

Receiver dict containing all receiver dipoles.

relative_error

Returns the relative error of the data.

See emg3d.surveys.Survey.standard_deviation for more info.

shape

Return nsrc x nrec x nfreq.

Note that not all source-receiver-frequency pairs do actually have data. Check size to see how many data points there are.

size

Return actual data size (does NOT equal nsrc x nrec x nfreq).

sources

Source dict containing all source dipoles.

src_coords

Return source coordinates.

The returned format is (x, y, z, azm, dip), a tuple of 5 tuples.

standard_deviation

Returns the standard deviation of the data.

The standard deviation can be set by providing an array of the same dimension as the data itself:

survey.standard_deviation = ndarray  # (nsrc, nrec, nfreq)

Alternatively, one can set the noise_floor \(\epsilon_\text{nf}\) and the relative_error \(\epsilon_\text{r}\):

survey.noise_floor = float or ndarray      # (> 0 or None)
survey.relative error = float or ndarray   # (> 0 or None)

They must be either floats, or three-dimensional arrays of shape ([nsrc or 1], [nrec or 1], [nfreq or 1]); dimensions of one will be broadcasted to the corresponding size. E.g., for a dataset of arbitrary amount of sources and receivers with three frequencies you can define a purely frequency-dependent relative error via relative_error=np.array([err_f1, err_f2, err_f3])[None, None, :].

The standard deviation \(\varsigma_i\) of observation \(d_i\) is then given in terms of the noise floor \(\epsilon_{\text{nf};i}\) and the relative error \(\epsilon_{\text{re};i}\) by

(35)\[\varsigma_i = \sqrt{ \epsilon_{\text{nf}; i}^2 + \left(\epsilon_{\text{re}; i}|d_i|\right)^2 } \, .\]

Note that a set standard deviation is prioritized over potentially also defined noise floor and relative error. To use the noise floor and the relative error after defining standard deviation directly you would have to reset it like

survey.standard_deviation = None

after which Equation (35) would be used again.

Methods Documentation

copy()[source]

Return a copy of the Survey.

classmethod from_dict(inp)[source]

Convert dictionary into Survey instance.

Parameters:
inp : dict

Dictionary as obtained from Survey.to_dict(). The dictionary needs the keys name, sources, receivers frequencies, data, and fixed.

Returns:
obj : Survey instance
classmethod from_file(fname, name='survey', **kwargs)[source]

Load Survey from a file.

Parameters:
fname : str

File name including extension. Used backend depends on the file extensions:

  • ‘.npz’: numpy-binary
  • ‘.h5’: h5py-binary (needs h5py)
  • ‘.json’: json
name : str

Name under which the survey is stored within the file.

kwargs : Keyword arguments, optional

Passed through to io.load().

Returns:
survey : Survey

The survey that was stored in the file.

to_dict(copy=False)[source]

Store the necessary information of the Survey in a dict.

to_file(fname, name='survey', **kwargs)[source]

Store Survey to a file.

Parameters:
fname : str

File name inclusive ending, which defines the used data format. Implemented are currently:

  • .h5 (default): Uses h5py to store inputs to a hierarchical, compressed binary hdf5 file. Recommended file format, but requires the module h5py. Default format if ending is not provided or not recognized.
  • .npz: Uses numpy to store inputs to a flat, compressed binary file. Default format if h5py is not installed.
  • .json: Uses json to store inputs to a hierarchical, plain text file.
name : str

Name under which the survey is stored within the file.

kwargs : Keyword arguments, optional

Passed through to io.save().