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).