TransmissionMatrix#

The following introduces the TransmissionMatrix class available in pyfar.

Transmission matrices (short T-matrices) are a convenient representation of Two-ports or Quadrupoles. These can represent systems from various fields, e.g. electrical circuits, mechanical vibration, (acoustic) transmission lines.

System properties like input impedance or transfer functions can directly be derived from a T-matrix. Furthermore, systems can be cascaded my multiplying consecutive T-matrices simply using the @ operator:

>>> import numpy as np
>>> import pyfar as pf
>>> frequencies = (100,200,300)
>>>
>>> # T-matrix with arbitrary data
>>> A = np.ones(len(frequencies))
>>> (B,C,D) = (A+1,A+2,A+3)
>>> tmat = pf.TransmissionMatrix.from_abcd(A,B,C,D,frequencies)
>>>
>>> # T-matrix of a bypass system
>>> tmat_bypass = pf.TransmissionMatrix.create_identity(frequencies)
>>>
>>> # Cascade
>>> tmat_out = tmat @ tmat_bypass
>>> tmat_out.freq == tmat.freq

Classes:

TransmissionMatrix(data, frequencies[, comment])

Class representing a transmission matrix.

class pyfar.classes.transmission_matrix.TransmissionMatrix(data, frequencies, comment='')[source]#

Class representing a transmission matrix.

This implementation is based on a paper by Lampton [1] and uses the ABCD- representation. A single T-matrix is a (2x2)-matrix of the form:

\[\begin{split}T = \begin{bmatrix} A & B \\ C & D \end{bmatrix}\end{split}\]

This class is derived from FrequencyData, representing a frequency-dependent matrix of a multi-dimensional form In the easiest case, each matrix entry (A,B,C,D) is a single-channel FrequencyData object (i.e. a vector depending on frequency). However, additional dimensions can be used to represent additional variables (e.g. multiple layouts of an electrical circuit).

Notes

This class is derived from FrequencyData but has a special constraint: The underlying frequency domain data must match a shape like (…, 2, 2, N). The last axis refers to the frequency, and the two axes before to the ABCD-Matrix (which is a 2x2 matrix), so the resulting cshape is (…,2,2).

Another point is the numerical handling when deriving input/output impedance or transfer functions (see input_impedance, output_impedance, transfer_function): In the respective equations, the load impedance Zl is usually multiplied. However, Zl is applied in the form of 1/Zl (as admittance) for Zl = inf to avoid numerical problems. There are additional cases where certain entries of the T-matrix being zero might still lead to the main denominator becoming zero. For these cases, the denominator is set to eps.

References

Attributes:

A

A entry of the transmission matrix.

B

B entry of the transmission matrix.

C

C entry of the transmission matrix.

D

D entry of the transmission matrix.

T

Shorthand for Signal.transpose().

abcd_caxes

The indices of the channel axes referring to the transmission matrix, namely (-2, -1).

abcd_cshape

The channel shape of the transmission matrix entries (A, B, C, D).

cdim

Return channel dimension.

comment

Get comment.

cshape

Return channel shape.

domain

The domain the data is stored in.

freq

Return or set the data in the frequency domain.

frequencies

Frequencies of the discrete signal spectrum.

n_bins

Number of frequency bins.

Methods:

copy()

Return a copy of the audio object.

create_gyrator(transducer_constant)

Creates a transmission matrix representing a gyrator.

create_identity([frequencies])

Creates an object with identity matrix entries (bypass).

create_series_impedance(impedance)

Creates a transmission matrix representing a series impedance.

create_shunt_admittance(admittance)

Creates a transmission matrix representing a shunt admittance (parallel connection).

create_transformer(transducer_constant)

Creates a transmission matrix representing a transformer.

find_nearest_frequency(value)

Return the index that is closest to the query frequency.

flatten()

Return flattened copy of the audio object.

from_abcd(A, B, C, D[, frequencies])

Create a TransmissionMatrix object from A-, B-, C-, D-data, and frequencies.

from_tmatrix(data, frequencies[, comment])

Create TransmissionMatrix using data in T-matrix shape and frequencies.

input_impedance(Zl)

Calculates the input impedance given the load impedance Zl at the output.

is_indexable()

Returns true if ABCD-entries have more than one channel and are therefore indexable.

output_impedance(Zl)

Calculates the output impedance given the load impedance Zl at the input.

reshape(newshape)

Return reshaped copy of the audio object.

transfer_function(quantity_indices, Zl)

Returns the transfer function (output/input) for specified quantities and a given load impedance.

transpose(*axes)

Transpose time/frequency data and return copy of the audio object.

property A: FrequencyData#

A entry of the transmission matrix.

property B: FrequencyData#

B entry of the transmission matrix.

property C: FrequencyData#

C entry of the transmission matrix.

property D: FrequencyData#

D entry of the transmission matrix.

property T#

Shorthand for Signal.transpose().

property abcd_caxes#

The indices of the channel axes referring to the transmission matrix, namely (-2, -1).

property abcd_cshape#

The channel shape of the transmission matrix entries (A, B, C, D).

This is the same as ‘cshape’ without the last two elements. As an exception, a matrix with cshape (2,2) will return (1,) as abcd_cshape.

property cdim#

Return channel dimension.

The channel dimension (cdim) gives the number of dimensions of the audio data excluding the last dimension, which is n_samples for time domain objects and n_bins for frequency domain objects. Therefore it is equivalent to the length of the channel shape (cshape) (e.g. self.cshape = (2, 3); self.cdim = 2).

property comment#

Get comment.

copy()#

Return a copy of the audio object.

static create_gyrator(transducer_constant: complex | FrequencyData) ndarray | TransmissionMatrix[source]#

Creates a transmission matrix representing a gyrator.

The T-matrix is defined by a transducer constant (\(M\)), see Equation (2-14) in Table I of Reference [1]:

\[\begin{split}T = \begin{bmatrix} 0 & M \\ 1/M & 0 \end{bmatrix}\end{split}\]

\(M\) connects the first input and second output quantity (e.g., \(U_\mathrm{out} = I_\mathrm{in} \cdot M\)). A respective system with load \(Z_L\) has the input impedance \(Z_\mathrm{in} = M^2 / Z_L\).

Parameters:

transducer_constant (scalar | FrequencyData) – The transducer constant \(M\). If a scalar is given, i.e. a frequency-independent transformer matrix is requested, the return value will be a 2x2 np.ndarray instead.

Returns:

tmat – A the transmission matrix representing the gyrator and can be cascaded with TransmissionMatrix objects. If a scalar was used as input a frequency-independent matrix is returned, namely an np.ndarray of shape (2,2).

Return type:

np.ndarray | TransmissionMatrix

static create_identity(frequencies=None)[source]#

Creates an object with identity matrix entries (bypass).

See Equation (2-7) in Table I of Reference [1]:

\[\begin{split}T = \begin{bmatrix} 1 & 0 \\ 0 & 1 \end{bmatrix}\end{split}\]
Parameters:

frequencies (None | array_like, optional) – The frequency sampling points in Hz. The default is None which will result in this function to return an np.ndarray instead of an TransmissionMatrix object.

Returns:

tmat – If frequencies are specified, a TransmissionMatrix object that contains one 2x2 identity matrix per bin is returned. Otherwise, this returns a 2x2 np.ndarray.

Return type:

np.ndarray | TransmissionMatrix

static create_series_impedance(impedance: complex | FrequencyData) ndarray | TransmissionMatrix[source]#

Creates a transmission matrix representing a series impedance.

This means the impedance is connected in series with a potential load impedance. See Equation (2-8) in Table I of Reference [1]:

\[\begin{split}T = \begin{bmatrix} 1 & Z \\ 0 & 1 \end{bmatrix}\end{split}\]
Parameters:

impedance (scalar | FrequencyData) – The impedance data of the series impedance.

Returns:

tmat – A transmission matrix representing the series connection and can be cascaded with TransmissionMatrix objects. If a scalar was used as input a frequency-independent matrix is returned, namely an np.ndarray of shape (2,2).

Return type:

np.ndarray | TransmissionMatrix

static create_shunt_admittance(admittance: complex | FrequencyData) ndarray | TransmissionMatrix[source]#

Creates a transmission matrix representing a shunt admittance (parallel connection).

In this case, the impedance (= 1 / admittance) is connected in parallel with a potential load impedance. See Equation (2-9) in Table I of Reference [1]:

\[\begin{split}T = \begin{bmatrix} 1 & 0 \\ Y & 1 \end{bmatrix}\end{split}\]
Parameters:

admittance (scalar | FrequencyData) – The admittance data of the element connected in parallel.

Returns:

tmat – A transmission matrix representing a parallel connection and can be cascaded with TransmissionMatrix objects. If a scalar was used as input a frequency-independent matrix is returned, namely an np.ndarray of shape (2,2).

Return type:

np.ndarray | TransmissionMatrix

static create_transformer(transducer_constant: float | int | FrequencyData) ndarray | TransmissionMatrix[source]#

Creates a transmission matrix representing a transformer.

See Equation (2-12) in Table I of Reference [1]:

\[\begin{split}T = \begin{bmatrix} N & 0 \\ 0 & 1/N \end{bmatrix}\end{split}\]
Parameters:

transducer_constant (scalar | FrequencyData) – The transmission ratio with respect to voltage-like quantity, i.e. \(N=U_\mathrm{out}/U_\mathrm{in}\). If a scalar is given, i.e. a frequency-independent transformer matrix is requested, the return value will be a 2x2 np.ndarray instead.

Returns:

tmat – A transmission matrix representing the transformer and can be cascaded with TransmissionMatrix objects. If a scalar was used as input a frequency-independent matrix is returned, namely an np.ndarray of shape (2,2).

Return type:

np.ndarray | TransmissionMatrix

property cshape#

Return channel shape.

The channel shape gives the shape of the audio data excluding the last dimension, which is n_samples for time domain objects and n_bins for frequency domain objects.

property domain#

The domain the data is stored in.

find_nearest_frequency(value)#

Return the index that is closest to the query frequency.

Parameters:

value (float, array-like) – The frequencies for which the indices are to be returned

Returns:

indices – The index for the given frequency. If the input was an array like, a numpy array of indices is returned.

Return type:

int, array-like

flatten()#

Return flattened copy of the audio object.

Returns:

flat – Flattened copy of audio object with flat.cshape = np.prod(audio.cshape)

Return type:

Signal, FrequencyData, TimeData

Notes

The number of samples and frequency bins always remains the same, e.g., an audio object of cshape=(4,3) and n_samples=512 will have cshape=(12, ) and n_samples=512 after flattening.

property freq#

Return or set the data in the frequency domain.

property frequencies#

Frequencies of the discrete signal spectrum.

classmethod from_abcd(A, B, C, D, frequencies=None)[source]#

Create a TransmissionMatrix object from A-, B-, C-, D-data, and frequencies.

Parameters:
  • A (FrequencyData, array_like, double) – Raw data for the matrix entries A. The data need to match the B, C and D entry or be broadcastable into one shape.

  • B (FrequencyData, array_like, double) – See A.

  • C (FrequencyData, array_like, double) – See A.

  • D (FrequencyData, array_like, double) – See A.

  • frequencies (array, double, None) – Frequencies of the data in Hz. This is optional if using the FrequencyData type for A, B, C, D.

Examples

>>> import numpy as np
>>> import pyfar as pf
>>> frequencies = (100,200,300)
>>> # From np.array
>>> A = np.ones(len(frequencies))
>>> (B,C,D) = (A+1, A+2, A+3)
>>> tmat = pf.TransmissionMatrix.from_abcd(A,B,C,D, frequencies)
>>> tmat
>>> # From FrequencyData objects
>>> A = pf.FrequencyData( A, frequencies )
>>> (B,C,D) = (A+1, A+2, A+3)
>>> tmat = pf.TransmissionMatrix.from_abcd(A,B,C,D)
>>> tmat
>>> # Data with higher abcd dimension
>>> A = np.ones( (3, 4, len(frequencies)) )
>>> (B,C,D) = (A+1, A+2, A+3)
>>> tmat = pf.TransmissionMatrix.from_abcd(A,B,C,D, frequencies)
>>> tmat
classmethod from_tmatrix(data, frequencies, comment='')[source]#

Create TransmissionMatrix using data in T-matrix shape and frequencies.

For using individual objects for A, B, C, D matrix entries, see from_abcd.

Parameters:
  • data (array_like, double) – Raw data in the frequency domain. In contrast to the FrequencyData class, data must have a shape of the form (…, 2, 2, N), e.g. (2, 2, 1024) or (3, 2, 2, 1024). In those examples 1024 refers to the number of frequency bins and the two dimensions before that to the (2x2) ABCD matrices. Supported data types are int, float or complex, where int is converted to float.

  • frequencies (array_like, double) – Frequencies of the data in Hz. The number of frequencies must match the size of the last dimension of data.

  • comment (str, optional) – A comment related to the data. The default is "", which initializes an empty string.

Examples

>>> import pyfar as pf
>>> frequencies = (100,200,300)
>>> data = np.ones( (2, 2, len(frequencies)) )
>>> tmat = pf.TransmissionMatrix.from_tmatrix(data, frequencies)
>>> data = np.ones( (3, 2, 2, len(frequencies)) )
>>> tmat = pf.TransmissionMatrix.from_tmatrix(data, frequencies)
input_impedance(Zl: complex | FrequencyData) FrequencyData[source]#

Calculates the input impedance given the load impedance Zl at the output.

Two-port representation:

        o---xxxxxxxxx---o
            x       x   |
Zin-->      x       x   Zl
            x       x   |
        o---xxxxxxxxx---o

See Equation (2-6) in Reference [1]: \(Z_\mathrm{in} = \frac{AZ_L + B}{CZ_L + D}\)

Parameters:

Zl (scalar | FrequencyData) – The load impedance data as scalar or FrequencyData. In latter case, the shape must match the entries of the T-matrix, i.e. shape(tmat.A.freq) == shape(Zl.freq), or must be broadcastable.

Returns:

Zout – A FrequencyData object with the resulting output impedance. The cshape is identical to the entries of the T-matrix, i.e. tmat.A.cshape == Zout.cshape.

Return type:

FrequencyData

Example

>>> import numpy as np
>>> import pyfar as pf
>>>
>>> # Frequency-dependent load impedance
>>> frequencies = (100,200,300)
>>> load_impedance = pf.FrequencyData((0, 1, np.inf), frequencies)
>>>
>>> # T-Matrix for frequency-independent series impedance R = 1 Ohm
>>> R = pf.FrequencyData((1,1,1), frequencies)
>>> tmat = pf.TransmissionMatrix.create_series_impedance(R)
>>>
>>> # Expected result: (1+0, 1+1, 1+inf) = (1, 2, inf)
>>> # Note, that due to numerical limitations infinite load will
>>> # result in Zin > 1e15.
>>> Zin = tmat.input_impedance(load_impedance)
>>> Zin.freq
is_indexable() bool[source]#

Returns true if ABCD-entries have more than one channel and are therefore indexable.

property n_bins#

Number of frequency bins.

output_impedance(Zl: complex | FrequencyData) FrequencyData[source]#

Calculates the output impedance given the load impedance Zl at the input.

Two-port representation:

o---xxxxxxxxx---o
|   x       x
Zl  x       x      <--Zout
|   x       x
o---xxxxxxxxx---o

See Equation (2-6) in Reference [1]: \(Z_\mathrm{out} = \frac{DZ_L + B}{CZ_L + A}\)

For a code example, see input_impedance and exchange respective method call with output_impedance.

Parameters:

Zl (scalar | FrequencyData) – The load impedance data as scalar or FrequencyData. In latter case, the shape must match the entries of the T-matrix, i.e. shape(tmat.A.freq) == shape(Zl.freq), or must be broadcastable.

Returns:

Zout – A FrequencyData object with the resulting output impedance. The cshape is identical to the entries of the T-matrix, i.e. tmat.A.cshape == Zout.cshape.

Return type:

FrequencyData

reshape(newshape)#

Return reshaped copy of the audio object.

Parameters:

newshape (int, tuple) – new cshape of the audio object. One entry of newshape dimension can be -1. In this case, the value is inferred from the remaining dimensions.

Returns:

reshaped – reshaped copy of the audio object.

Return type:

Signal, FrequencyData, TimeData

Notes

The number of samples and frequency bins always remains the same.

transfer_function(quantity_indices, Zl: complex | FrequencyData) FrequencyData[source]#

Returns the transfer function (output/input) for specified quantities and a given load impedance.

The transfer function is the relation between an output and input quantity of modelled two-port and depends on the load impedance at the output. Since there are two quantities at input and output respectively, four transfer functions exist in total. The first usually refers to the “voltage-like” quantity (\(Q_1\)) whereas the second refers to the “current-like” quantity (\(Q_2\)).

The transfer functions can be derived from Equation (2-1) in Reference [1]:

\[ \begin{align}\begin{aligned}Q_{1,\mathrm{in}} = AQ_{1,\mathrm{out}} + BQ_{2,\mathrm{in}}\\Q_{2,\mathrm{in}} = CQ_{1,\mathrm{out}} + DQ_{2,\mathrm{in}}\end{aligned}\end{align} \]

The four transfer functions are defined as:

  • \(Q_{1,\mathrm{out}} / Q_{1,\mathrm{in}}\) using \(Q_{2,\mathrm{out}} = Q_{1,\mathrm{out}}/Z_L\)

  • \(Q_{2,\mathrm{out}} / Q_{1,\mathrm{in}} = Q_{1,\mathrm{out}} / Q_{1,\mathrm{in}} \cdot \frac{1}{Z_L}\)

  • \(Q_{2,\mathrm{out}} / Q_{2,\mathrm{in}}\) using \(Q_{1,\mathrm{out}} = Q_{2,\mathrm{out}}\cdot Z_L\)

  • \(Q_{1,\mathrm{out}} / Q_{2,\mathrm{in}} = Q_{2,\mathrm{out}} / Q_{2,\mathrm{in}} \cdot Z_L\)

Parameters:
  • quantity_indices (array_like (int, int)) – Array-like object with two integer elements referring to the indices of the utilized quantity at the output (first integer) and input (second integer). For example, (1,0) refers to the transfer function \(Q_{2,\mathrm{out}} / Q_{1,\mathrm{in}}\).

  • Zl (scalar | FrequencyData) – The load impedance data as scalar or FrequencyData. In latter case, the shape must match the entries of the T-matrix, i.e. shape(tmat.A.freq) == shape(Zl.freq), or must be broadcastable.

Returns:

transfer_function – A FrequencyData object with the resulting transfer function. The cshape is identical to the entries of the T-matrix, i.e. tmat.A.cshape == transfer_function.cshape.

Return type:

FrequencyData

transpose(*axes)#

Transpose time/frequency data and return copy of the audio object.

Parameters:

axes (empty, None, iterable of ints, or n ints) –

Define how the :py:mod:` caxes <pyfar._concepts.audio_classes>` are ordered in the transposed audio object. Note that the last dimension of the data in the audio object always contains the time samples or frequency bins and can not be transposed.

empty (default) or None

reverses the order of self.caxes.

iterable of ints

i in the j-th place of the interable means that the i-th caxis becomes transposed object’s j-th caxis.

n ints

same as ‘iterable of ints’.