pyphysim.mimo package

Submodules

pyphysim.mimo.mimo module

Module implementing different MIMO schemes.

Each MIMO scheme is implemented as a class inheriting from MimoBase and implements at least the methods encode, decode and getNumberOfLayers.

class pyphysim.mimo.mimo.Alamouti(channel: Optional[numpy.ndarray] = None)[source]

Bases: pyphysim.mimo.mimo.MimoBase

MIMO class for the Alamouti scheme.

Parameters

channel (np.ndarray) – MIMO channel matrix.

static _calc_precoder(channel: numpy.ndarray)numpy.ndarray[source]

Not defined.

There is no linear precoder for the Almost scheme and thus an exception is called if this method is ever called.

static _calc_receive_filter(channel: numpy.ndarray, noise_var: Optional[float] = None)numpy.ndarray[source]

Not defined.

There is no linear receive filter for the Alamouti scheme that can be directly applied to the received data. Thus, an exception is called if this method is ever called.

static _decode(received_data: numpy.ndarray, channel: numpy.ndarray)numpy.ndarray[source]

Perform the decoding of the received_data for the Alamouti scheme with the channel channel, but does not compensate for the power division among transmit antennas.

The idea is that the decode method will call _decode and perform the power compensation. This separation allows better code reuse.

Parameters
  • received_data (np.ndarray) – Received data, which was encoded with the Alamouti scheme and corrupted by the channel channel.

  • channel (np.ndarray) – MIMO channel matrix.

Returns

decoded_data – The decoded data (without power compensating the power division performed during transmission).

Return type

np.ndarray

See also

decode()

static _encode(transmit_data: numpy.ndarray)numpy.ndarray[source]

Perform the Alamouti encoding, but without dividing the power among the transmit antennas.

The idea is that the encode method will call _encode and perform the power division. This separation allows better code reuse.

Parameters

transmit_data (np.ndarray) – Data to be encoded by the Alamouti scheme.

Returns

encoded_data – The encoded transmit_data (without dividing the power among transmit antennas).

Return type

np.ndarray

See also

encode()

calc_linear_SINRs(noise_var: float)numpy.ndarray[source]

Calculate the SINRs (in linear scale) of the multiple streams.

Parameters

noise_var (float) – The noise variance.

Returns

sinrs – The sinrs (in linear scale) of the multiple streams.

Return type

np.ndarray

decode(received_data: numpy.ndarray)numpy.ndarray[source]

Perform the decoding of the received_data for the Alamouti scheme with the channel channel.

Parameters

received_data (np.ndarray) – Received data, which was encoded with the Alamouti scheme and corrupted by the channel channel.

Returns

decoded_data – The decoded data.

Return type

np.ndarray

encode(transmit_data: numpy.ndarray)numpy.ndarray[source]

Perform the Alamouti encoding.

Parameters

transmit_data (np.ndarray) – Data to be encoded by the Alamouti scheme.

Returns

encoded_data – The encoded transmit_data.

Return type

np.ndarray

getNumberOfLayers()int[source]

Get the number of layers of the Alamouti scheme.

The number of layers in the Alamouti scheme is always equal to one.

Returns

Nl – Number of layers of the Alamouti scheme, which is always one.

Return type

int

set_channel_matrix(channel: numpy.ndarray)None[source]

Set the channel matrix.

Parameters

channel (np.ndarray) – MIMO channel matrix.

Returns

Return type

None

class pyphysim.mimo.mimo.Blast(channel: Optional[numpy.ndarray] = None)[source]

Bases: pyphysim.mimo.mimo.MimoBase

MIMO class for the BLAST scheme.

The receive filter used will depend on the noise variance (see the set_noise_var() method). If the noise variance is positive the MMSE filter will be used, otherwise noise variance will be ignored and the Zero-Forcing filter will be used.

Parameters

channel (np.ndarray) – MIMO channel matrix.

static _calc_precoder(channel: numpy.ndarray)numpy.ndarray[source]

Calculate the linear precoder for the BLAST scheme.

The BLAST scheme simple send the data through the multiple streams without any particular precoding. Therefore, its linear precoder is equivalent to an identity matrix.

Parameters

channel (np.ndarray) – MIMO channel matrix.

Returns

W – The precoder that can be applied to the input data.

Return type

np.ndarray

static _calc_receive_filter(channel: numpy.ndarray, noise_var: Optional[float] = None)numpy.ndarray[source]

Calculate the receive filter for the MIMO scheme, if there is any.

Parameters
  • channel (np.ndarray) – MIMO channel matrix.

  • noise_var (float) – The noise variance. If a value is provided then MMSE filter will be used. If it is not provided (or None is passes) then Zero Force filter will be used.

Returns

G_H – The receive_filter that can be applied to the input data.

Return type

np.ndarray

decode(received_data: numpy.ndarray)numpy.ndarray[source]

Decode the received data array.

Parameters

received_data (np.ndarray) – Received data, which was encoded with the Blast scheme and corrupted by the channel channel.

Returns

decoded_data – The decoded data.

Return type

np.ndarray

encode(transmit_data: numpy.ndarray)numpy.ndarray[source]

Encode the transmit data array to be transmitted using the BLAST scheme.

Parameters

transmit_data (np.ndarray) – A numpy array with a number of elements which is a multiple of the number of transmit antennas.

Returns

encoded_data – The encoded transmit_data.

Return type

np.ndarray

Raises

ValueError – If the number of elements in transmit_data is not multiple of the number of transmit antennas.

getNumberOfLayers()int[source]

Get the number of layers of the Blast scheme.

Returns

Nl – Number of layers of the MIMO scheme.

Return type

int

set_channel_matrix(channel: numpy.ndarray)None[source]

Set the channel matrix.

Parameters

channel (np.ndarray) – MIMO channel matrix.

set_noise_var(noise_var: Optional[float])None[source]

Set the noise variance for the MMSE receive filter.

If noise_var is non-positive then the Zero-Force filter will be used instead.

Parameters

noise_var (float | None) – Noise variance for the MMSE filter (if noise_var is positive). If noise_var is 0.0 or None then the Zero-Forcing filter will be used.

Returns

Return type

None

class pyphysim.mimo.mimo.GMDMimo(channel: Optional[numpy.ndarray] = None)[source]

Bases: pyphysim.mimo.mimo.Blast

MIMO class for the GMD based MIMO scheme.

Parameters

channel (np.ndarray) – MIMO channel matrix.

static _calc_precoder(channel: numpy.ndarray)numpy.ndarray[source]

Calculate the linear precoder for the GMD scheme.

Parameters

channel (np.ndarray) – MIMO channel matrix with dimension (1, Nt).

Returns

W – The precoder that can be applied to the input data.

Return type

np.ndarray

static _calc_receive_filter(channel: numpy.ndarray, noise_var: Optional[float] = None)numpy.ndarray[source]

Calculate the receive filter for the MRT scheme.

Parameters
  • channel (np.ndarray) – MIMO channel matrix.

  • noise_var (float) – The noise variance.

Returns

G_H – The receive_filter that can be applied to the input data.

Return type

np.ndarray

decode(received_data: numpy.ndarray)numpy.ndarray[source]

Perform the decoding of the received_data for the GMD MIMO.

Parameters

received_data (np.ndarray) – Received data, which was encoded with the Alamouti scheme and corrupted by the channel channel.

Returns

decoded_data – The decoded data.

Return type

np.ndarray

encode(transmit_data: numpy.ndarray)numpy.ndarray[source]

Encode the transmit data array to be transmitted using the GMD MIMO scheme.

The GMD MIMO scheme is based on the Geometric Mean Decomposition (GMD) of the channel. The channel is decomposed into H = Q R P^H, where R is an upper triangular matrix with all diagonal elements being equal to the geometric mean of the singular values of the channel matrix H.

corresponds to using the ‘U’ and ‘V’ matrices from the SVD decomposition of the channel as the precoder and receive filter.

Parameters

transmit_data (np.ndarray) – A numpy array with the data to be transmitted.

Returns

encoded_data – The encoded transmit_data.

Return type

np.ndarray

class pyphysim.mimo.mimo.MRC(channel: Optional[numpy.ndarray] = None)[source]

Bases: pyphysim.mimo.mimo.Blast

MIMO class for the MRC scheme.

The receive filter used will depend on the noise variance (see the set_noise_var() method). If the noise variance is positive the MMSE filter will be used, otherwise noise variance will be ignored and the Zero-Forcing filter will be used.

The receive filter in the Blast class already does the maximum ratio combining. Therefore, this MRC class simply inherits from the Blast class and only exists for completion.

Parameters

channel (np.ndarray) – MIMO channel matrix.

set_channel_matrix(channel: numpy.ndarray)None[source]

Set the channel matrix.

Parameters

channel (np.ndarray) – MIMO channel matrix. The MRC MIMO scheme is defined for the scenario with multiple receive antennas and a single receive antenna. If channel is 1D assume that the number of transmit antennas is equal to 1.

class pyphysim.mimo.mimo.MRT(channel: Optional[numpy.ndarray] = None)[source]

Bases: pyphysim.mimo.mimo.MisoBase

MIMO class for the MRT scheme.

The number of streams for the MRT scheme is always equal to one, but it still employs multiple transmit antennas.

If channel is not provided you need to call the set_channel_matrix method before calling the other methods.

Parameters

channel (np.ndarray) – MISO channel vector. It must be a 1D numpy array, where the number of receive antennas is assumed to be equal to 1.

static _calc_precoder(channel: numpy.ndarray)numpy.ndarray[source]

Calculate the linear precoder for the MRT scheme.

The MRT scheme corresponds to multiplying the symbol from each transmit antenna with a complex number corresponding to the inverse of the phase of the channel so as to ensure that the signals add constructively at the receiver. This also means that the MRT scheme only be applied to scenarios with a single receive antenna.

Parameters

channel (np.ndarray) – MIMO channel matrix with dimension (1, Nt).

Returns

W – The precoder that can be applied to the input data.

Return type

np.ndarray

static _calc_receive_filter(channel: numpy.ndarray, noise_var: Optional[float] = None)numpy.ndarray[source]

Calculate the receive filter for the MRT scheme.

Parameters
  • channel (np.ndarray) – MIMO channel matrix.

  • noise_var (float) – The noise variance.

Returns

G_H – The receive_filter that can be applied to the input data.

Return type

np.ndarray

decode(received_data: numpy.ndarray)numpy.ndarray[source]

Decode the received data array.

Parameters

received_data (np.ndarray) – Received data, which was encoded with the MRT scheme and corrupted by the channel channel.

Returns

decoded_data – The decoded data.

Return type

np.ndarray

encode(transmit_data: numpy.ndarray)numpy.ndarray[source]

Encode the transmit data array to be transmitted using the MRT scheme.

The MRT scheme corresponds to multiplying the symbol from each transmit antenna with a complex number corresponding to the inverse of the phase of the channel so as to ensure that the signals add constructively at the receiver. This also means that the MRT scheme only be applied to scenarios with a single receive antenna.

Parameters

transmit_data (np.ndarray) – A numpy array with the data to be transmitted.

Returns

encoded_data – The encoded transmit_data.

Return type

np.ndarray

class pyphysim.mimo.mimo.MimoBase(channel: Optional[numpy.ndarray] = None)[source]

Bases: object

Base Class for MIMO schemes.

All subclasses must implement at least the following methods:

  • getNumberOfLayers(): Should return the number of layers of that specific MIMO scheme

  • encode(): The encode method must perform everything executed at the transmitter for that specific MIMO scheme. This also include the power division among the transmit antennas.

  • decode(): Analogous to the encode method, the decode method must perform everything performed at the receiver.

If possible, subclasses should implement the _calc_precoder and _calc_receive_filter static methods and use them in the implementation of encode and decode. This will allow using the calc_linear_SINRs and calc_SINRs methods to calculate the post processing SINRs. Note that calling the _calcZeroForceFilter and _calcMMSEFilter methods in the implementation of the receive filter calculation can be useful.

If you can’t implement the _calc_precoder and _calc_receive_filter static methods` (because there is no linear precoder or receive filter for the MIMO scheme in the subclass, for instance), then you should implement the calc_linear_SINRs method in the subclass instead.

Parameters

channel (np.ndarray | None) – MIMO channel matrix. This should be a 1D or 2D numpy array. The allowed dimensions will depend on the particular MIMO scheme implemented in a subclass.

property Nr

Get the number of receive antennas

Returns

The number of receive antennas.

Return type

int

property Nt

Get the number of transmit antennas

Returns

The number of transmit antennas.

Return type

int

static _calcMMSEFilter(channel: numpy.ndarray, noise_var: float)numpy.ndarray[source]

Calculates the MMSE filter to cancel the inter-stream interference.

Parameters
  • channel (np.ndarray) – MIMO channel matrix.

  • noise_var (float) – Noise variance.

Returns

W – The MMSE receive filter.

Return type

np.ndarray

static _calcZeroForceFilter(channel: numpy.ndarray)numpy.ndarray[source]

Calculates the Zero-Force filter to cancel the inter-stream interference.

Parameters

channel (np.ndarray) – MIMO channel matrix.

Returns

W – The Zero-Forcing receive filter.

Return type

np.ndarray

Notes

The Zero-Force filter basically corresponds to the pseudo-inverse of the channel matrix.

static _calc_precoder(channel: numpy.ndarray)numpy.ndarray[source]

Calculate the linear precoder for the MIMO scheme, if there is any.

Parameters

channel (np.ndarray) – MIMO channel matrix.

Returns

W – The precoder that can be applied to the input data.

Return type

np.ndarray

static _calc_receive_filter(channel: numpy.ndarray, noise_var: Optional[float] = None)numpy.ndarray[source]

Calculate the receive filter for the MIMO scheme, if there is any.

Parameters
  • channel (np.ndarray) – MIMO channel matrix.

  • noise_var (float) – The noise variance.

Returns

G_H – The receive_filter that can be applied to the input data.

Return type

np.ndarray

calc_SINRs(noise_var: float)numpy.ndarray[source]

Calculate the SINRs (in dB) of the multiple streams.

Parameters

noise_var (float) – The noise variance.

Returns

SINRs – The SINRs (in dB) of the multiple streams.

Return type

np.ndarray

calc_linear_SINRs(noise_var: float)numpy.ndarray[source]

Calculate the SINRs (in linear scale) of the multiple streams.

Parameters

noise_var (float) – The noise variance.

Returns

sinrs – The sinrs (in linear scale) of the multiple streams.

Return type

np.ndarray

abstract decode(received_data: numpy.ndarray)numpy.ndarray[source]

Method to decode the transmit data array to be transmitted using some MIMO scheme. This method must be implemented in a subclass.

Parameters

received_data (np.ndarray) – The received data.

Returns

decoded_data – The decoded data.

Return type

np.ndarray

abstract encode(transmit_data: numpy.ndarray)numpy.ndarray[source]

Method to encode the transmit data array to be transmitted using some MIMO scheme. This method must be implemented in a subclass.

Parameters

transmit_data (np.ndarray) – The data to be transmitted.

Returns

encoded_data – The encoded transmit_data.

Return type

np.ndarray

abstract getNumberOfLayers()int[source]

Get the number of layers of the MIMO scheme.

Notes

This method must be implemented in each subclass of MimoBase.

Returns

The number of layers.

Return type

int

set_channel_matrix(channel: numpy.ndarray)None[source]

Set the channel matrix.

Parameters

channel (np.ndarray) – MIMO channel matrix. This should be a 1D or 2D numpy array. The allowed dimensions will depend on the particular MIMO scheme implemented in a subclass.

class pyphysim.mimo.mimo.MisoBase(channel: Optional[numpy.ndarray] = None)[source]

Bases: pyphysim.mimo.mimo.MimoBase

Base Class for MISO schemes.

All subclasses must implement at least the following methods:

  • MimoBase.encode(): The encode method must perform everything executed at the transmitter for that specific MIMO scheme. This also include the power division among the transmit antennas.

  • MimoBase.decode(): Analogous to the encode method, the decode method must perform everything performed at the receiver.

Other optional methods that might be useful implementing in subclasses are the _calc_precoder and _calc_receive_filter methods.

Parameters

channel (np.ndarray) – MISO channel matrix/vector. MISO schemes are defined for scenarios with multiple transmit antennas and a single receive antenna. If channel is 2D, then the first dimension size must be equal to 1.

getNumberOfLayers()int[source]

Get the number of layers of the MISO scheme.

Because a MISO scheme only has one receive antenna then then number of layers is always equal to 1.

Returns

The number of layers.

Return type

int

set_channel_matrix(channel: numpy.ndarray)None[source]

Set the channel matrix.

Parameters

channel (np.ndarray) – MISO channel vector. A MISO scheme is defined for the scenario with multiple transmit antennas and a single receive antenna. If channel is 2D then the first dimension size must be equal to 1.

Returns

Return type

None

class pyphysim.mimo.mimo.SVDMimo(channel: Optional[numpy.ndarray] = None)[source]

Bases: pyphysim.mimo.mimo.Blast

MIMO class for the SVD MIMO scheme.

Parameters

channel (np.ndarray) – MIMO channel matrix.

static _calc_precoder(channel: numpy.ndarray)numpy.ndarray[source]

Calculate the linear precoder for the SVD MIMO scheme.

The SVD MIMO scheme employs as precoder the right singular matrix from SVD (Singular Value Decomposition) of the channel.

Parameters

channel (np.ndarray) – MIMO channel matrix with dimension (1, Nt).

Returns

W – The precoder that can be applied to the input data.

Return type

np.ndarray

static _calc_receive_filter(channel: numpy.ndarray, noise_var: Optional[float] = None)numpy.ndarray[source]

Calculate the receive filter for the SVD MIMO scheme.

Parameters
  • channel (np.ndarray) – MIMO channel matrix.

  • noise_var (float) – The noise variance.

Returns

G_H – The receive_filter that can be applied to the input data.

Return type

np.ndarray

decode(received_data: numpy.ndarray)numpy.ndarray[source]

Perform the decoding of the received_data for the SVD MIMO scheme with the channel channel.

Parameters

received_data (np.ndarray) – Received data, which was encoded with the Alamouti scheme and corrupted by the channel channel.

Returns

decoded_data – The decoded data.

Return type

np.ndarray

encode(transmit_data: numpy.ndarray)numpy.ndarray[source]

Encode the transmit data array to be transmitted using the SVD MIMO scheme.

The SVD MIMO scheme corresponds to using the ‘U’ and ‘V’ matrices from the SVD decomposition of the channel as the precoder and receive filter.

Parameters

transmit_data (np.ndarray) – A numpy array with the data to be transmitted.

Returns

encoded_data – The encoded transmit_data.

Return type

np.ndarray

Module contents