Survey#

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

Bases: object

Create a survey containing sources, receivers, and data.

A survey contains the acquisition information such as source types, positions, and frequencies and receiver types and positions. A survey contains also any acquired or synthetic data and their expected relative error and noise floor.

The data is stored in an 3D ndarray of dimension nsrc x nrec x nfreq. Underlying the survey-class is an xarray.Dataset, where each individual data set (e.g., acquired data or synthetic data) is stored as a xarray.DataArray. The module xarray is a soft dependency of emg3d, and has to be installed manually to use the survey functionality.

Receivers have a switch relative, which is False by default and means that the coordinates are absolute values (grid-based acquisition). If the switch is set to True, the coordinates are relative to the source. This can be used to model streamer-based acquisitions such as marine streamers or airborne surveys. The two acquisition types can also be mixed in a survey.

Note

The package xarray has to be installed in order to use Survey: pip install xarray or conda install -c conda-forge xarray.

Parameters
sources, receivers{Tx*, Rx*, list, dict)

Any of the available sources or receivers, e.g., emg3d.electrodes.TxElectricDipole, or a list or dict of Tx*/Rx* instances. If it is a dict, it is used as is, including the provided keys. In all other cases keys are assigned to the values.

It can also be a list containing a combination of the above (lists, dicts, and instances).

Receivers can be set to None, if one is only interested in forward modelling the entire fields. In this case, the related data object and the noise floor and relative error have no meaning. Also, in conjunction with a emg3d.simulations.Simulation, the misfit and the gradient will be zero.

frequencies{array_like, dict}

Source frequencies (Hz).

  • array_like: Frequencies will be stored in a dict with keys assigned starting with 'f-1', 'f-2', and so on.

  • dict: Keys can be arbitrary names, values must be floats.

datandarray, default: None

The observed data (dtype=np.complex128); must have shape (nsrc, nrec, nfreq). Alternatively, it can be a dict containing many datasets, in which one could also store, for instance, standard-deviations for each source-receiver-frequency pair.

If None, it will be initiated with NaN’s.

noise_floor, relative_error{float, ndarray}, default: None

Noise floor and relative error of the data. They can be arrays of a shape which can be broadcasted to the data shape, e.g., (nsrc, 1, 1) or (1, nrec, nfreq), or have the dimension of data. See Survey.standard_deviation for more info.

namestr, default: None

Name of the survey.

datestr, default: None

Acquisition date.

infostr, default: None

Survey info or any other info (e.g., what was the intent of the survey, what were the acquisition conditions, problems encountered).

Attributes Summary

count

Count of observed data.

data

Data, a xarray.Dataset instance.

frequencies

Frequency dict containing all frequencies.

noise_floor

Return noise floor of the data.

receivers

Receiver dict containing all receivers.

relative_error

Return relative error of the data.

shape

Shape of data (nsrc, nrec, nfreq).

size

Size of data (nsrc x nrec x nfreq).

sources

Source dict containing all sources.

standard_deviation

Return standard deviation of the data.

Methods Summary

add_noise([min_offset, min_amplitude, add_to])

Add random noise to the data defined by add_to.

copy()

Return a copy of the Survey.

from_dict(inp)

Convert dictionary into emg3d.surveys.Survey instance.

from_file(fname[, name])

Load Survey from a file.

receiver_coordinates([source])

Return receiver center coordinates as ndarray [x, y, z].

select([sources, receivers, frequencies, ...])

Return a Survey with selected sources, receivers, and frequencies.

source_coordinates()

Return source center coordinates as ndarray [x, y, z].

to_dict([copy])

Store the necessary information of the Survey in a dict.

to_file(fname[, name])

Store Survey to a file.

Attributes Documentation

count#

Count of observed data.

data#

Data, a xarray.Dataset instance.

frequencies#

Frequency dict containing all frequencies.

noise_floor#

Return noise floor of the data.

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

receivers#

Receiver dict containing all receivers.

relative_error#

Return relative error of the data.

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

shape#

Shape of data (nsrc, nrec, nfreq).

size#

Size of data (nsrc x nrec x nfreq).

sources#

Source dict containing all sources.

standard_deviation#

Return 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{n}\) and the relative_error \(\epsilon_\text{r}\):

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

They must be either floats, or three-dimensional arrays of shape ({1;nsrc}, {1;nrec}, {1;nfreq}); 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{n};i}\) and the relative error \(\epsilon_{\text{r};i}\) by

(38)#\[\varsigma_i = \sqrt{\epsilon_{\text{n}; i}^2 + \left(\epsilon_{\text{r}; 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 (38) would be used again.

Methods Documentation

add_noise(min_offset=0.0, min_amplitude='half_nf', add_to='observed', **kwargs)[source]#

Add random noise to the data defined by add_to.

The noise is generated with emg3d.surveys.random_noise, consult that function to see how it is actually generated (kwargs are passed through).

This function takes further care of removing data which is too close to the source (min_offset) or has a too low signal (min_amplitude).

Parameters
min_offsetfloat, default: 0.0

Data points in data.observed where the offset < min_offset are set to NaN.

min_amplitude{float, str, None}, default: ‘half_nf’

Data points in data.observed where abs(data) < min_amplitude are set to NaN. If 'half_nf', the noise_floor divided by two is used as min_amplitude. Set to None to include all data.

add_tostr, default: ‘observed’

Data to which to add the noise. By default it is added to the observed data. If a name is provided that is not an existing dataset it will create a dataset of zeroes. You can use that to obtain the pure noise.

copy()[source]#

Return a copy of the Survey.

classmethod from_dict(inp)[source]#

Convert dictionary into emg3d.surveys.Survey instance.

Parameters
inpdict

Dictionary as obtained from emg3d.surveys.Survey.to_dict. The dictionary needs the keys sources, receivers, and frequencies.

Returns
surveySurvey

A emg3d.surveys.Survey instance.

classmethod from_file(fname, name='survey', **kwargs)[source]#

Load Survey from a file.

Parameters
fnamestr

Absolute or relative file name including extension.

namestr, default: ‘survey’

Name under which the survey is stored within the file.

kwargsKeyword arguments, optional

Passed through to io.load.

Returns
surveySurvey

A emg3d.surveys.Survey instance.

infostr, returned if verb<0

Info-string.

receiver_coordinates(source=None)[source]#

Return receiver center coordinates as ndarray [x, y, z].

For relative receivers, all positions are listed one after the other for each source position. Alternatively, a source-name (string) can be provided, in which case only the position for this source is added.

select(sources=None, receivers=None, frequencies=None, remove_empty=True)[source]#

Return a Survey with selected sources, receivers, and frequencies.

Parameters
sources, receivers, frequencieslist, default: None

Lists containing the wanted sources, receivers, and frequencies. If None, all are selected.

remove_emptybool, default: True

If True, and self.data.observed has finite entries, it removes empty source-receiver-frequency entries and according sources, receivers, and frequencies.

Returns
surveySurvey

A emg3d.surveys.Survey instance.

source_coordinates()[source]#

Return source center coordinates as ndarray [x, y, z].

to_dict(copy=False)[source]#

Store the necessary information of the Survey in a dict.

Parameters
copybool, default: False

If True, returns a deep copy of the dict.

Returns
outdict

Dictionary containing all information to re-create the Survey.

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

Store Survey to a file.

Parameters
fnamestr

Absolute or relative file name including ending, which defines the used data format. See emg3d.io.save for the options.

namestr, default: ‘survey’

Name with which the survey is stored in the file.

kwargsKeyword arguments, optional

Passed through to emg3d.io.save.