resistics.transfunc module

Module defining transfer functions

pydantic model resistics.transfunc.Component[source]

Bases: resistics.common.Metadata

Data class for a single component in a Transfer function

Example

>>> from resistics.transfunc import Component
>>> component = Component(real=[1, 2, 3, 4, 5], imag=[-5, -4, -3, -2 , -1])
>>> component.get_value(0)
(1-5j)
>>> component.to_numpy()
array([1.-5.j, 2.-4.j, 3.-3.j, 4.-2.j, 5.-1.j])

Show JSON schema
{
   "title": "Component",
   "description": "Data class for a single component in a Transfer function\n\nExample\n-------\n>>> from resistics.transfunc import Component\n>>> component = Component(real=[1, 2, 3, 4, 5], imag=[-5, -4, -3, -2 , -1])\n>>> component.get_value(0)\n(1-5j)\n>>> component.to_numpy()\narray([1.-5.j, 2.-4.j, 3.-3.j, 4.-2.j, 5.-1.j])",
   "type": "object",
   "properties": {
      "real": {
         "title": "Real",
         "type": "array",
         "items": {
            "type": "number"
         }
      },
      "imag": {
         "title": "Imag",
         "type": "array",
         "items": {
            "type": "number"
         }
      }
   },
   "required": [
      "real",
      "imag"
   ]
}

field real: List[float] [Required]

The real part of the component

field imag: List[float] [Required]

The complex part of the component

get_value(eval_idx: int) complex[source]

Get the value for an evaluation frequency

to_numpy() numpy.ndarray[source]

Get the component as a numpy complex array

resistics.transfunc.get_component_key(out_chan: str, in_chan: str) str[source]

Get key for out channel and in channel combination in the solution

Parameters
  • out_chan (str) – The output channel

  • in_chan (str) – The input channel

Returns

The component key

Return type

str

Examples

>>> from resistics.regression import get_component_key
>>> get_component_key("Ex", "Hy")
'ExHy'
pydantic model resistics.transfunc.TransferFunction[source]

Bases: resistics.common.Metadata

Define a generic transfer function

This class is a describes generic transfer function, including:

  • The output channels for the transfer function

  • The input channels for the transfer function

  • The cross channels for the transfer function

The cross channels are the channels that will be used to calculate out the cross powers for the regression.

This generic parent class has no implemented plotting function. However, child classes may have a plotting function as different transfer functions may need different types of plots.

Note

Users interested in writing a custom transfer function should inherit from this generic Transfer function

See also

ImpandanceTensor

Transfer function for the MT impedance tensor

Tipper

Transfer function for the MT tipper

Examples

A generic example

>>> tf = TransferFunction(variation="example", out_chans=["bye", "see you", "ciao"], in_chans=["hello", "hi_there"])
>>> print(tf.to_string())
| bye      |   | bye_hello         bye_hi_there      | | hello    |
| see you  | = | see you_hello     see you_hi_there  | | hi_there |
| ciao     |   | ciao_hello        ciao_hi_there     |

Combining the impedance tensor and the tipper into one TransferFunction

>>> tf = TransferFunction(variation="combined", out_chans=["Ex", "Ey"], in_chans=["Hx", "Hy", "Hz"])
>>> print(tf.to_string())
| Ex |   | Ex_Hx Ex_Hy Ex_Hz | | Hx |
| Ey | = | Ey_Hx Ey_Hy Ey_Hz | | Hy |
                               | Hz |

Show JSON schema
{
   "title": "TransferFunction",
   "description": "Define a generic transfer function\n\nThis class is a describes generic transfer function, including:\n\n- The output channels for the transfer function\n- The input channels for the transfer function\n- The cross channels for the transfer function\n\nThe cross channels are the channels that will be used to calculate out the\ncross powers for the regression.\n\nThis generic parent class has no implemented plotting function. However,\nchild classes may have a plotting function as different transfer functions\nmay need different types of plots.\n\n.. note::\n\n    Users interested in writing a custom transfer function should inherit\n    from this generic Transfer function\n\nSee Also\n--------\nImpandanceTensor : Transfer function for the MT impedance tensor\nTipper : Transfer function for the MT tipper\n\nExamples\n--------\nA generic example\n\n>>> tf = TransferFunction(variation=\"example\", out_chans=[\"bye\", \"see you\", \"ciao\"], in_chans=[\"hello\", \"hi_there\"])\n>>> print(tf.to_string())\n| bye      |   | bye_hello         bye_hi_there      | | hello    |\n| see you  | = | see you_hello     see you_hi_there  | | hi_there |\n| ciao     |   | ciao_hello        ciao_hi_there     |\n\nCombining the impedance tensor and the tipper into one TransferFunction\n\n>>> tf = TransferFunction(variation=\"combined\", out_chans=[\"Ex\", \"Ey\"], in_chans=[\"Hx\", \"Hy\", \"Hz\"])\n>>> print(tf.to_string())\n| Ex |   | Ex_Hx Ex_Hy Ex_Hz | | Hx |\n| Ey | = | Ey_Hx Ey_Hy Ey_Hz | | Hy |\n                               | Hz |",
   "type": "object",
   "properties": {
      "name": {
         "title": "Name",
         "type": "string"
      },
      "variation": {
         "title": "Variation",
         "default": "generic",
         "maxLength": 16,
         "type": "string"
      },
      "out_chans": {
         "title": "Out Chans",
         "type": "array",
         "items": {
            "type": "string"
         }
      },
      "in_chans": {
         "title": "In Chans",
         "type": "array",
         "items": {
            "type": "string"
         }
      },
      "cross_chans": {
         "title": "Cross Chans",
         "type": "array",
         "items": {
            "type": "string"
         }
      },
      "n_out": {
         "title": "N Out",
         "type": "integer"
      },
      "n_in": {
         "title": "N In",
         "type": "integer"
      },
      "n_cross": {
         "title": "N Cross",
         "type": "integer"
      }
   },
   "required": [
      "out_chans",
      "in_chans"
   ]
}

field name: Optional[str] = None

The name of the transfer function, this will be set automatically

Validated by
  • validate_name

field variation: resistics.transfunc.ConstrainedStrValue = 'generic'

A short additional bit of information about this variation

Constraints
  • maxLength = 16

field out_chans: List[str] [Required]

The output channels

field in_chans: List[str] [Required]

The input channels

field cross_chans: Optional[List[str]] = None

The channels to use for calculating the cross spectra

Validated by
  • validate_cross_chans

field n_out: Optional[int] = None

The number of output channels

Validated by
  • validate_n_out

field n_in: Optional[int] = None

The number of input channels

Validated by
  • validate_n_in

field n_cross: Optional[int] = None

The number of cross power channels

Validated by
  • validate_n_cross

classmethod validate(value: Union[resistics.transfunc.TransferFunction, Dict[str, Any]]) resistics.transfunc.TransferFunction[source]

Validate a TransferFunction

Parameters

value (Union[TransferFunction, Dict[str, Any]]) – A TransferFunction child class or a dictionary

Returns

A TransferFunction or TransferFunction child class

Return type

TransferFunction

Raises
  • ValueError – If the value is neither a TransferFunction or a dictionary

  • KeyError – If name is not in the dictionary

  • ValueError – If initialising from dictionary fails

Examples

The following example will show how a child TransferFunction class can be instantiated using a dictionary and the parent TransferFunction (but only as long as that child class has been imported).

>>> from resistics.transfunc import TransferFunction

Show known TransferFunction types in built into resistics

>>> for entry in TransferFunction._types.items():
...     print(entry)
('ImpedanceTensor', <class 'resistics.transfunc.ImpedanceTensor'>)
('Tipper', <class 'resistics.transfunc.Tipper'>)

Now let’s initialise an ImpedanceTensor from the base TransferFunction and a dictionary.

>>> mytf = {"name": "ImpedanceTensor", "variation": "ecross", "cross_chans": ["Ex", "Ey"]}
>>> test = TransferFunction(**mytf)
Traceback (most recent call last):
...
KeyError: 'out_chans'

This is not quite what we were expecting. The generic TransferFunction requires out_chans to be defined, but they are not in the dictionary as the ImpedanceTensor child class defaults these. To get this to work, instead use the validate class method. This is the class method used by pydantic when instantiating.

>>> mytf = {"name": "ImpedanceTensor", "variation": "ecross", "cross_chans": ["Ex", "Ey"]}
>>> test = TransferFunction.validate(mytf)
>>> test.summary()
{
    'name': 'ImpedanceTensor',
    'variation': 'ecross',
    'out_chans': ['Ex', 'Ey'],
    'in_chans': ['Hx', 'Hy'],
    'cross_chans': ['Ex', 'Ey'],
    'n_out': 2,
    'n_in': 2,
    'n_cross': 2
}

That’s more like it. This will raise errors if an unknown type of TransferFunction is received.

>>> mytf = {"name": "NewTF", "cross_chans": ["Ex", "Ey"]}
>>> test = TransferFunction.validate(mytf)
Traceback (most recent call last):
...
ValueError: Unable to initialise NewTF from dictionary

Or if the dictionary does not have a name key

>>> mytf = {"cross_chans": ["Ex", "Ey"]}
>>> test = TransferFunction.validate(mytf)
Traceback (most recent call last):
...
KeyError: 'No name provided for initialisation of TransferFunction'

Unexpected inputs will also raise an error

>>> test = TransferFunction.validate(5)
Traceback (most recent call last):
...
ValueError: TransferFunction unable to initialise from <class 'int'>
n_eqns_per_output() int[source]

Get the number of equations per output

n_regressors() int[source]

Get the number of regressors

to_string()[source]

Get the transfer function as as string

pydantic model resistics.transfunc.ImpedanceTensor[source]

Bases: resistics.transfunc.TransferFunction

Standard magnetotelluric impedance tensor

Notes

Information about data units

  • Magnetic permeability in nT . m / A

  • Electric (E) data is in mV/m

  • Magnetic (H) data is in nT

  • Z = E/H is in mV / m . nT

  • Units of resistance = Ohm = V / A

Examples

>>> from resistics.transfunc import ImpedanceTensor
>>> tf = ImpedanceTensor()
>>> print(tf.to_string())
| Ex | = | Ex_Hx Ex_Hy | | Hx |
| Ey |   | Ey_Hx Ey_Hy | | Hy |

Show JSON schema
{
   "title": "ImpedanceTensor",
   "description": "Standard magnetotelluric impedance tensor\n\nNotes\n-----\nInformation about data units\n\n- Magnetic permeability in nT . m / A\n- Electric (E) data is in mV/m\n- Magnetic (H) data is in nT\n- Z = E/H is in mV / m . nT\n- Units of resistance = Ohm = V / A\n\nExamples\n--------\n>>> from resistics.transfunc import ImpedanceTensor\n>>> tf = ImpedanceTensor()\n>>> print(tf.to_string())\n| Ex | = | Ex_Hx Ex_Hy | | Hx |\n| Ey |   | Ey_Hx Ey_Hy | | Hy |",
   "type": "object",
   "properties": {
      "name": {
         "title": "Name",
         "type": "string"
      },
      "variation": {
         "title": "Variation",
         "default": "default",
         "maxLength": 16,
         "type": "string"
      },
      "out_chans": {
         "title": "Out Chans",
         "default": [
            "Ex",
            "Ey"
         ],
         "type": "array",
         "items": {
            "type": "string"
         }
      },
      "in_chans": {
         "title": "In Chans",
         "default": [
            "Hx",
            "Hy"
         ],
         "type": "array",
         "items": {
            "type": "string"
         }
      },
      "cross_chans": {
         "title": "Cross Chans",
         "type": "array",
         "items": {
            "type": "string"
         }
      },
      "n_out": {
         "title": "N Out",
         "type": "integer"
      },
      "n_in": {
         "title": "N In",
         "type": "integer"
      },
      "n_cross": {
         "title": "N Cross",
         "type": "integer"
      }
   }
}

field variation: resistics.transfunc.ConstrainedStrValue = 'default'

A short additional bit of information about this variation

Constraints
  • maxLength = 16

field out_chans: List[str] = ['Ex', 'Ey']

The output channels

field in_chans: List[str] = ['Hx', 'Hy']

The input channels

static get_resistivity(periods: numpy.ndarray, component: resistics.transfunc.Component) numpy.ndarray[source]

Get apparent resistivity for a component

Parameters
  • periods (np.ndarray) – The periods of the component

  • component (Component) – The component values

Returns

Apparent resistivity

Return type

np.ndarray

static get_phase(key: str, component: resistics.transfunc.Component) numpy.ndarray[source]

Get the phase for the component

Note

Components ExHx and ExHy are wrapped around in [0,90]

Parameters
  • key (str) – The component name

  • component (Component) – The component values

Returns

The phase values

Return type

np.ndarray

static get_fig(x_lim: Optional[List[float]] = None, res_lim: Optional[List[float]] = None, phs_lim: Optional[List[float]] = None) plotly.graph_objs._figure.Figure[source]

Get a figure for plotting the ImpedanceTensor

Parameters
  • x_lim (Optional[List[float]], optional) – The x limits, to be provided as powers of 10, by default None. For example, for 0.001, use -3

  • res_lim (Optional[List[float]], optional) – The y limits for resistivity, to be provided as powers of 10, by default None. For example, for 1000, use 3

  • phs_lim (Optional[List[float]], optional) – The phase limits, by default None

Returns

Plotly figure

Return type

go.Figure

static plot(freqs: List[float], components: Dict[str, resistics.transfunc.Component], fig: Optional[plotly.graph_objs._figure.Figure] = None, to_plot: Optional[List[str]] = None, legend: str = 'Impedance tensor', x_lim: Optional[List[float]] = None, res_lim: Optional[List[float]] = None, phs_lim: Optional[List[float]] = None, symbol: Optional[str] = 'circle') plotly.graph_objs._figure.Figure[source]

Plot the Impedance tensor

Parameters
  • freqs (List[float]) – The frequencies where the impedance tensor components have been calculated

  • components (Dict[str, Component]) – The component data

  • fig (Optional[go.Figure], optional) – Figure to add to, by default None

  • to_plot (Optional[List[str]], optional) – The components to plot, by default all of the components of the impedance tensor

  • legend (str, optional) – Legend prefix for the components, by default “Impedance tensor”

  • x_lim (Optional[List[float]], optional) – The x limits, to be provided as powers of 10, by default None. For example, for 0.001, use -3. Only used when a figure is not provided.

  • res_lim (Optional[List[float]], optional) – The y limits for resistivity, to be provided as powers of 10, by default None. For example, for 1000, use 3. Only used when a figure is not provided.

  • phs_lim (Optional[List[float]], optional) – The phase limits, by default None. Only used when a figure is not provided.

  • symbol (Optional[str], optional) – The marker symbol to use, by default “circle”

Returns

[description]

Return type

go.Figure

pydantic model resistics.transfunc.Tipper[source]

Bases: resistics.transfunc.TransferFunction

Magnetotelluric tipper

The tipper components are Tx = HzHx and Ty = HzHy

The tipper length is sqrt(Re(Tx)^2 + Re(Ty)^2)

The tipper angle is arctan (Re(Ty)/Re(Tx))

Notes

Information about units

  • Tipper T = H/H is dimensionless

Examples

>>> from resistics.transfunc import Tipper
>>> tf = Tipper()
>>> print(tf.to_string())
| Hz | = | Hz_Hx Hz_Hy | | Hx |
                         | Hy |

Show JSON schema
{
   "title": "Tipper",
   "description": "Magnetotelluric tipper\n\nThe tipper components are Tx = HzHx and Ty = HzHy\n\nThe tipper length is sqrt(Re(Tx)^2 + Re(Ty)^2)\n\nThe tipper angle is arctan (Re(Ty)/Re(Tx))\n\nNotes\n-----\nInformation about units\n\n- Tipper T = H/H is dimensionless\n\nExamples\n--------\n>>> from resistics.transfunc import Tipper\n>>> tf = Tipper()\n>>> print(tf.to_string())\n| Hz | = | Hz_Hx Hz_Hy | | Hx |\n                         | Hy |",
   "type": "object",
   "properties": {
      "name": {
         "title": "Name",
         "type": "string"
      },
      "variation": {
         "title": "Variation",
         "default": "default",
         "maxLength": 16,
         "type": "string"
      },
      "out_chans": {
         "title": "Out Chans",
         "default": [
            "Hz"
         ],
         "type": "array",
         "items": {
            "type": "string"
         }
      },
      "in_chans": {
         "title": "In Chans",
         "default": [
            "Hx",
            "Hy"
         ],
         "type": "array",
         "items": {
            "type": "string"
         }
      },
      "cross_chans": {
         "title": "Cross Chans",
         "type": "array",
         "items": {
            "type": "string"
         }
      },
      "n_out": {
         "title": "N Out",
         "type": "integer"
      },
      "n_in": {
         "title": "N In",
         "type": "integer"
      },
      "n_cross": {
         "title": "N Cross",
         "type": "integer"
      }
   }
}

field variation: resistics.transfunc.ConstrainedStrValue = 'default'

A short additional bit of information about this variation

Constraints
  • maxLength = 16

field out_chans: List[str] = ['Hz']

The output channels

field in_chans: List[str] = ['Hx', 'Hy']

The input channels

get_length(components: Dict[str, resistics.transfunc.Component]) numpy.ndarray[source]

Get the tipper length

get_real_angle(components: Dict[str, resistics.transfunc.Component]) numpy.ndarray[source]

Get the real angle

get_imag_angle(components: Dict[str, resistics.transfunc.Component]) numpy.ndarray[source]

Get the imaginary angle

plot(freqs: List[float], components: Dict[str, resistics.transfunc.Component], x_lim: Optional[List[float]] = None, len_lim: Optional[List[float]] = None, ang_lim: Optional[List[float]] = None) plotly.graph_objs._figure.Figure[source]

Plot the impedance tensor

Warning

This probably needs further checking and verification

Parameters
  • freqs (List[float]) – The x axis frequencies

  • components (Dict[str, Component]) – The component data

  • x_lim (Optional[List[float]], optional) – The x limits, to be provided as powers of 10, by default None. For example, for 0.001, use -3

  • len_lim (Optional[List[float]], optional) – The y limits for tipper length, to be provided as powers of 10, by default None. For example, for 1000, use 3

  • ang_lim (Optional[List[float]], optional) – The angle limits, by default None

Returns

Plotly figure

Return type

go.Figure