Data Classes
============
The package provides several classes for storing frequency-domain EM sensor data.
Channel Data
------------
The ``sitem1d.ChannelData`` class provides the basic representation of
complex relative magnetic field data of one EM channel. More on the
definition of a channel below. ``ChannelData`` contains only an array of
complex values, but provides an interface to the typical
inphase/quadrature and amplitude/phase representations of EM data.
Input
^^^^^
The class is initialized by arrays or scalars of inphase and quadrature
values. These must be of type float and any arrays must have only one
dimension.
.. code-block:: none
>>> sitem1d.ChannelData([1.0, 2.0, 3.0], [1.0, 2.0, 3.0])
sitem1d.ChannelData object:
[1.+1.j 2.+2.j 3.+3.j] (3 records)
The instance can also be initialized from a complex object and the
following statement will result in an identical instance:
.. code-block:: none
>>> sitem1d.ChannelData.from_complex([1.0+1.0j, 2.0+2.0j, 3.0+3.0j])
sitem1d.ChannelData object:
[1.+1.j 2.+2.j 3.+3.j] (3 records)
An optional unit and label can be added to the instance:
.. code-block:: none
>>> ChannelData([1.0, 2.0, 3.0], [1.0, 2.0, 3.0], unit="ppm", label="Label")
sitem1d.ChannelData object:
[1.+1.j 2.+2.j 3.+3.j] (3 records)
label: Label
unit: ppm
While scalar input is allowed, the value will be converted to an array.
.. code-block:: none
>>> hshp = ChannelData(1.0, 1.0)
>>> hshp.iq
array([1.+1.j])
Properties
^^^^^^^^^^
The instance contains the properties for the all representations of the
complex values of one EM channel (e.g. one frequency +
transmitter/receiver configuration). The data is traditionally
represented by the inphase (real) and quadrature (imaginary) compents of
the
.. code-block:: python
hshp = ChannelData([1.0, 2.0, 3.0], [1.0, 2.0, 3.0], unit="ppm", label="Label")
.. tabularcolumns:: p{0.132\linewidth}p{0.198\linewidth}
.. list-table:: sitem1d.ChannelData properties
:name: channel-data-properties
:widths: 30, 30
:class: longtable
:header-rows: 1
:align: center
:width: 66%
* - Property
- Value
* - ``hshp.iq``
- array([1.+1.j, 2.+2.j, 3.+3.j])
* - ``hshp.z``
- array([1.+1.j, 2.+2.j, 3.+3.j])
* - ``hshp.inphase``
- array([1., 2., 3.])
* - ``hshp.quadrature``
- array([1., 2., 3.])
* - ``hshp.amplitude``
- array([1.41421356, 2.82842712, 4.24264069])
* - ``hshp.phase``
- array([45., 45., 45.])
* - ``hshp.phase_radian``
- array([0.78539816, 0.78539816, 0.78539816])
* - ``hshp.n_records``
- 3
* - ``hshp.unit``
- ppm
* - ``hshp.label``
- Label
.. note:: Note that the properity ``z`` is an alias of ``iq`` and kept for historical reasons.
The data content in ``ChannelData`` is protected against modification by
any means other than the intented operators.
1. Properties are immutable
.. code-block:: none
:emphasize-lines: 2
>>> hshp = ChannelData([1.0, 2.0, 3.0], [1.0, 2.0, 3.0])
>>> hshp.inphase = 0.0
Traceback (most recent call last):
File "C:\python\anaconda3\envs\py3p8\lib\code.py", line 90, in runcode
exec(code, self.locals)
File "", line 1, in
AttributeError: can't set attribute
2. Properties return copies of the variables and not references
.. code-block:: none
:emphasize-lines: 3
>>> hshp = ChannelData([1.0, 2.0, 3.0], [1.0, 2.0, 3.0])
>>> inphase = hshp.inphase
>>> inphase[0] = 1000
>>> hshp.inphase
array([1., 2., 3.])
Operators
^^^^^^^^^
The ``ChannelData`` object allows operators:
1. Slicing ``[Iterable]``: Selecting a subset of the data container.
.. code:: none
>>> hshp = ChannelData([1.0, 2.0, 3.0], [1.0, 2.0, 3.0])
>>> hshp[1:]
sitem1d.ChannelData object:
[2.+2.j 3.+3.j] (2 records)
2. Addition ``+``: Complex addition of two data sets
.. code:: none
>>> a = ChannelData([1.0, 2.0, 3.0], [1.0, 2.0, 3.0])
>>> b = ChannelData([1.0, 1.0, 1.0], [1.0, 1.0, 1.0])
>>> a + b
sitem1d.ChannelData object:
[2.+2.j 3.+3.j 4.+4.j] (3 records)
3. Subtraction ``-``: Complex subtraction of two data sets
.. code:: none
>>> a = ChannelData([1.0, 2.0, 3.0], [1.0, 2.0, 3.0])
>>> b = ChannelData([1.0, 1.0, 1.0], [1.0, 1.0, 1.0])
>>> a - b
sitem1d.ChannelData object:
[0.+0.j 1.+1.j 2.+2.j] (3 records)
4. Calibration Operator ``*``
The ``*`` operator is reserved for modification of the content by
appropriate other classes. . It can be used between ``ChannelData``
and any class that has a ``calibrate_channel_data`` method, which
returns a calibrated ``ChannelData`` object. One example of such a
functionality is given by
.. code:: none
>>> from sitem1d.cal import GainPhaseOffsetCal
>>> hshp = ChannelData([1.0, 2.0, 3.0], [1.0, 2.0, 3.0])
>>> cal = GainPhaseOffsetCal(gain=2)
>>> hshp * cal
sitem1d.ChannelData object:
[2.+2.j 4.+4.j 6.+6.j] (3 records)
Methods
^^^^^^^
``ChannelData`` only contains three methods.
1. ``clone()``: Return a full copy of the ``ChannelData`` instance.
.. code:: none
>>> hshp = ChannelData([1.0, 2.0, 3.0], [1.0, 2.0, 3.0])
>>> hshp.clone()
sitem1d.ChannelData object:
[1.+1.j 2.+2.j 3.+3.j] (3 records)
..
Note: ``hshp.clone()`` is equivalent to ``hshp[:]``
2. ``ChannelData.iq2ap(inphase, quadrature)``: Class method to convert
inphase/quadrature to amplitude/phase notation.
.. code:: none
>>> amplitude, phase = ChannelData.iq2ap([1.0, 2.0, 3.0], [1.0, 2.0, 3.0])
>>> amplitude, phase
(array([1.41421356, 2.82842712, 4.24264069]), array([45., 45., 45.]))
The method return phase as degree by default, but this can be
changed:
.. code:: none
>>> ChannelData.iq2ap([1.0, 2.0, 3.0], [1.0, 2.0, 3.0], degree=False)
(array([1.41421356, 2.82842712, 4.24264069]), array([0.78539816, 0.78539816, 0.78539816]))
3. ``ChannelData.iq2ap(amplitude, phase)``: Inverse transformation from
amplitude/phase to inphase/quadrature. The methods assumes that phase
in given in degree, which can be changed by passing ``degree=False``
keyword.
.. code:: none
>>> ChannelData.ap2iq(amplitude, phase)
(array([1., 2., 3.]), array([1., 2., 3.]))
Channel Definition
------------------
The class ``sitem1d.ChannelDefinition`` is a light data class that
contains metadata of a given channel. The metadata contains the
following properties:
1. transmitter frequency in Hz
2. separation (spacing) between the transmitter (tx) and receiver (rx)
coils in meter
3. a string describing the transmitter/receiver coil configuration.
Currently supported are ``hcp`` (horizontal coplanar) and ``vpc``
vertical coplanar.
4. [Optional] separation (spacing) between the transmittter (tx) and
bucking (bx) coils in meter.
.. code:: none
>>> from sitem1d import ChannelDefinition
>>> ChannelDefinition(18325., 1.660, "hcp")
Channel Definition (f18325r1p66hcp):
Transmitter frequency: 18325.0 Hz
Rx-Tx coil separation: 1.66 m
Rx-Tx coil mode : hcp (flag: 0)
Bx-Tx coil separation: N/A
respectively with bucking coil:
.. code:: none
>>> ChannelDefinition(18325., 1.660, "hcp", 1.035)
Channel Definition (f18325r1p66hcpbx):
Transmitter frequency: 18325.0 Hz
Rx-Tx coil separation: 1.66 m
Rx-Tx coil mode : hcp (flag: 0)
Bx-Tx coil separation: 1.035 m
The class creates a unique id based on the properties (in this case
``f18325r1p66hcp``/``f18325r1p66hcpbx`` without/with the bucking coil
definition).