pyphysim.channels package

Submodules

pyphysim.channels.antennagain module

class pyphysim.channels.antennagain.AntGainBS3GPP25996(number_of_sectors: int = 3)[source]

Bases: pyphysim.channels.antennagain.AntGainBase

Class for antenna model defined by 3GPP in the 25996 norm for sectorized Base Stations.

The antenna gain (in dBi) will depend on the number of sectors of the Base Station.

NOTE: The antenna pattern here is targeted for diversity-oriented implementations (i.e. large inter-element spacings). For beamforming applications that require small spacings, alternative antenna designs may have to be considered leading to a different antenna pattern.

Parameters

number_of_sectors (int) – The number of sectors of the base station. It can be either 3 or 6.

get_antenna_gain(angle: NumberOrArray) → NumberOrArray[source]

Get the antenna gain for the given angle.

Parameters

angle (float | np.ndarray) – Angle between the direction of interest and the boresight of the antenna. This can also be a numpy array with angles.

Returns

The gain (in linear scale) for the provided angle.

Return type

float | np.ndarray

class pyphysim.channels.antennagain.AntGainBase[source]

Bases: object

Base class for antenna models.

get_antenna_gain(angle: NumberOrArray) → NumberOrArray[source]

Get the antenna gain for the given angle.

Parameters

angle (float | np.ndarray) – Angle between the direction of interest and the boresight of the antenna. This can also be a numpy array with angles.

Returns

The gain (in linear scale) for the provided angle.

Return type

float | np.ndarray

class pyphysim.channels.antennagain.AntGainOmni(ant_gain: Optional[float] = None)[source]

Bases: pyphysim.channels.antennagain.AntGainBase

Class for Omnidirectional antenna gain model.

Parameters

ant_gain (float, optional) – The antenna gain (in dBi). If not provided then 0dBi will be assumed.

get_antenna_gain(angle: NumberOrArray) → NumberOrArray[source]

Get the antenna gain for the given angle.

Parameters

angle (float | np.ndarray) – Angle between the direction of interest and the boresight of the antenna. This can also be a numpy array with angles.

Returns

The gain (in linear scale) for the provided angle.

Return type

float | np.ndarray

pyphysim.channels.fading module

class pyphysim.channels.fading.TdlChannel(fading_generator: Union[pyphysim.channels.fading_generators.JakesSampleGenerator, pyphysim.channels.fading_generators.RayleighSampleGenerator], channel_profile: Optional[pyphysim.channels.fading.TdlChannelProfile] = None, tap_powers_dB: Optional[numpy.ndarray] = None, tap_delays: Optional[numpy.ndarray] = None, Ts: Optional[float] = None)[source]

Bases: object

Tapped Delay Line channel model, which corresponds to a multipath channel.

You can create a new TdlChannel object either specifying the channel profile or specifying both the channel tap powers and delays.

Parameters
  • fading_generator (FadingGenerator) – The instance of a fading generator in the fading_generators module. It should be a subclass of FadingSampleGenerator. The fading generator will be used to generate the channel samples. If the shape of the fading_generator is not None, then it must contain two positive integers, and a MIMO transmission will be employed, where the first integer in shape corresponds to the number of receive antennas while the second integer corresponds to the number of transmit antennas

  • channel_profile (TdlChannelProfile) – The channel profile, which specifies the tap powers and delays.

  • tap_powers_dB (np.ndarray) – The powers of each tap (in dB). Dimension: L x 1 Note: The power of each tap will be a negative number (in dB).

  • tap_delays (np.ndarray) – The delay of each tap (in seconds). Dimension: L x 1

_TdlChannel__prepare_transmit_signal_shape(signal: numpy.ndarray)numpy.ndarray

Helper method called in corrupt_data and corrupt_data_in_freq_domain methods to prepare the shape of transmit signal.

It there is only one transmit antenna but signal is 1D, then an extra dimension will be added to signal. Otherwise the signal will be just returned.

Parameters

signal (np.ndarray) – The signal to be transmitted. This should be 1D for SISO systems (or SIMO systems) and 2D for MIMO systems.

Returns

Either the same signal of signal with an added dimension.

Return type

np.ndarray

_set_fading_generator_shape(new_shape: Optional[Tuple[int, …]])None[source]

Set the shape of the fading generator.

Parameters

new_shape (tuple[int], None) – The new shape of the fading generator. Note that the actual shape will be set to (self.num_taps, new_shape)

property channel_profile

Return the channel profile.

Returns

The channel profile.

Return type

TdlChannelProfile

corrupt_data(signal: numpy.ndarray)numpy.ndarray[source]

Transmit the signal though the TDL channel.

Parameters

signal (np.ndarray) – The signal to be transmitted. This should be 1D for SISO systems (or SIMO systems) and 2D for MIMO systems.

Returns

The received signal after transmission through the TDL channel

Return type

np.ndarray

corrupt_data_in_freq_domain(signal: numpy.ndarray, fft_size: int, carrier_indexes: Optional[Union[numpy.ndarray, List[int], slice]] = None)numpy.ndarray[source]

Transmit the signal through the TDL channel, but in the frequency domain.

This is ROUGHLY equivalent to modulating signal with OFDM using fft_size subcarriers, transmitting through a regular TdlChannel, and then demodulating with OFDM to recover the received signal.

One important difference is that here the channel is considered constant during the transmission of fft_size elements in signal, and then it is varied by the equivalent of the variation for that number of elements. That is, the channel is block static.

Parameters
  • signal (np.ndarray) – The signal to be transmitted. This should be 1D for SISO systems (or SIMO systems) and 2D for MIMO systems.

  • fft_size (int) – The size of the Fourier transform to get the frequency response.

  • carrier_indexes (slice | np.ndarray | list[int]) – The indexes of the subcarriers where signal is to be transmitted. If it is None assume all subcarriers will be used. This can be a slice object or a numpy array of integers.

Returns

The received signal after transmission through the TDL channel

Return type

np.ndarray

generate_impulse_response(num_samples: int = 1)None[source]

Generate a new impulse response of all discretized taps (not including possible zero padding) for num_samples channel realizations.

NOTE: This method is automatically called in the corrupt_data and corrupt_data_in_freq_domain methods and you don’t need to call it befortransmitting data. After one of them has been called the generated impulse response can ge get with the get_last_impulse_response method.

The number of discretized taps of the generated impulse response will depend on the channel delay profile (the tap_delays passed during creation of the TdlChannel object) as well as on the sampling interval.

As an example, the COST259 TU channel profile has 20 different taps where the last one has a delay equal to 2.14 microseconds. If the sampling interval is configured as 3.25e-08 then the discretized channel will have more than 60 taps ( including the zeros padding), where only 15 taps are different from zero. These 15 taps are what is returned by this method.

Alternatively, with a sampling time of 1e-6 you will end up with only 3 discretized taps.

Parameters

num_samples (int) – The number of samples to generate (for each tap).

get_last_impulse_response()pyphysim.channels.fading.TdlImpulseResponse[source]

Get the last generated impulse response.

A new impulse response is generated when the method corrupt_data is called. You can use the get_last_impulse_response method to get the impulse response used to corrupt the last data.

Returns

The impulse response of the channel that was used to corrupt the last data.

Return type

TdlImpulseResponse

property num_rx_antennas

Get the number of receive antennas.

Returns

The number of receive antennas.

Return type

int

property num_taps

Number of taps not including zero taps after discretization.

Returns

The number of taps (not including padding)

Return type

int

property num_taps_with_padding

Number of taps including zero taps after discretization.

Returns

The number of taps (including padding)

Return type

int

property num_tx_antennas

Get the number of transmit antennas.

Returns

The number of transmit antennas.

Return type

int

set_num_antennas(num_rx_antennas: int, num_tx_antennas: int)None[source]

Set the number of transmit and receive antennas for MIMO transmission.

Set both num_rx_antennas and num_tx_antennas to None for SISO transmission

Parameters
  • num_rx_antennas (int) – The number of receive antennas.

  • num_tx_antennas (int) – The number of transmit antennas.

property switched_direction

Get the value of switched_direction.

Returns

True if direction is switched and False otherwise.

Return type

bool

class pyphysim.channels.fading.TdlChannelProfile(tap_powers_dB: Optional[numpy.ndarray] = None, tap_delays: Optional[numpy.ndarray] = None, name: str = 'custom')[source]

Bases: object

Channel Profile class.

This class is just a nice way to present known profiles from the norm or the literature, which are represented as instances of this class.

A TDL channel profile store information about the TDL taps. That is, it stores the power and delay of each tap. The power and delay of each tap can be accessed through the tap_powers_* and tap_delays properties.

Some profiles are defined as objects of this class, such as COST259_TUx, COST259_RAx and COST259_HTx. These can be used when instantiating a TdlChannel object.

Note that the tap powers and delays are not necessarily discretized to some sampling interval.

Parameters
  • tap_powers_dB (np.ndarray) – The tap powers (in dB). If both tap_powers_dB and tap_delays are None then a single tap with 0dB power will be assumed at delay 0.

  • tap_delays (np.ndarray) – The tap delays.

  • name (str) – A name for the channel profile

Examples

>>> jakes_generator = fading_generators.JakesSampleGenerator(Ts=3.25e-8)
>>> tdlchannel = TdlChannel(jakes_generator, channel_profile=COST259_TUx)
property Ts

Get the sampling interval used for discretizing this channel profile object.

If it is not discretized then this returns None.

Returns

The sampling interval (in seconds).

Return type

float, None

_calc_discretized_tap_powers_and_delays(Ts: float) → Tuple[numpy.ndarray, numpy.ndarray][source]

Discretize the taps according to the sampling time.

The discretized taps will be equally spaced and the delta time from two taps corresponds to the sampling time.

Parameters

Ts (float) – The sampling time.

Returns

A tuple with the discretized powers and delays.

Return type

np.ndarray, np.ndarray

get_discretize_profile(Ts: float)pyphysim.channels.fading.TdlChannelProfile[source]

Compute the discretized taps (power and delay) and return a new discretized TdlChannelProfile object.

The tap powers and delays of the returned TdlChannelProfile object correspond to the taps and delays of the TdlChannelProfile object used to call get_discretize_profile after discretizing with the sampling interval Ts.

Parameters

Ts (float) – The sampling time for the discretization of the tap powers and delays.

Returns

The discretized channel profile

Return type

TdlChannelProfile

property is_discretized

Returns True if the channel profile is discretized

property mean_excess_delay

The mean excess delay is the first moment of the power delay profile and is defined to be

\[\overline{\tau} = \frac{\sum_k P(\tau_k)\tau_k}{\sum_k P(\tau_k)}\]
Returns

The mean excess delay.

Return type

float

property name

Get the profile name.

Returns

Profile name.

Return type

str

property num_taps

Get the number of taps in the profile.

Returns

Number of taps before discretization (does not count possible padding).

Return type

int

property num_taps_with_padding

Get the number of taps in the profile including zero-padding when the profile is discretized.

If the profile is not discretized an exception is raised.

Returns

Number of taps after discretization (it counts possible any added padding).

Return type

int

property rms_delay_spread

The RMS delay spread is the square root of the second central moment of the power delay profile. It is defined to be

\[\sigma_t = \sqrt{\overline{t^2} - \overline{\tau}^2}\]

where

\[\overline{\tau^2}=\frac{\sum_k P(\tau_k)\tau_k^2}{\sum_k P(\tau_k)}\]

Typically, when the symbol time period is greater than 10 times the RMS delay spread, no ISI equalizer is needed in the receiver.

Returns

The RMS delay spread.

Return type

float

property tap_delays

Get the tap delays.

Returns

The tap delays.

Return type

np.ndarray

property tap_powers_dB

Get the tap powers (in dB).

Returns

The tap powers (in dB).

Return type

np.ndarray

property tap_powers_linear

Get the tap powers (in linear scale).

Returns

The tap powers (in linear scale).

Return type

np.ndarray

class pyphysim.channels.fading.TdlImpulseResponse(tap_values: numpy.ndarray, channel_profile: pyphysim.channels.fading.TdlChannelProfile)[source]

Bases: object

Class that represents impulse response for a TdlChannel object.

This impulse response corresponds to the generated samples for one or more channel realization of the TdlChannel with the configured fading generator.

Parameters
  • tap_values (np.ndarray) – The tap_values (not including zero padded taps) of a TDL channel generated for the non-zero taps. Dimension: Num sparse taps x SHAPE x num_samples. The value SHAPE here is the shape of the fading generator and corresponds to independent impulse responses. Often the shape of the used fading generator is None and thus the dimension of tap_values is just Num sparse taps x num_samples

  • channel_profile (TdlChannelProfile) – The channel profile that was considering to generate this impulse response.

property Ts

Return the sampling interval of this impulse response.

If the impulse response is not discretized this returns None.

Returns

The sampling interval.

Return type

float

_get_samples_including_the_extra_zeros()numpy.ndarray[source]

Return the samples including the zeros for the zero taps.

Returns

samples_with_zeros – The samples including the extra delays containing zeros.

Return type

np.ndarray

property channel_profile

Return the channel profile.

Returns

The channel profile.

Return type

TdlChannelProfile

static concatenate_samples(impulse_responses: List[TdlImpulseResponse])pyphysim.channels.fading.TdlImpulseResponse[source]

Concatenate multiple TdlImpulseResponse objects and return the new concatenated TdlImpulseResponse.

This concatenation is performed in the “samples” dimension.

Parameters

impulse_responses (list[TdlImpulseResponse]) – A list of TdlImpulseResponse objects to be concatenated.

Returns

The new concatenated TdlImpulseResponse.

Return type

TdlImpulseResponse

get_freq_response(fft_size: int)numpy.ndarray[source]

Get the frequency response for this impulse response.

Parameters

fft_size (int) – The size of the FFT to be applied.

Returns

The frequency response. Dimension: fft_size x num_samples for SISO impulse response or fft_size x num_rx x num_tx x num_samples for MIMO impulse response.

Return type

np.ndarray

property num_samples

Get the number of samples (different, “neighbor” impulse responses) stored here.

Returns

The number of samples in the TdlImpulseResponse object.

Return type

int

plot_frequency_response(fft_size: int)None[source]

Plot the frequency response.

Parameters

fft_size (int) – The size of the FFT to be applied.

plot_impulse_response()None[source]

Plot the impulse response.

property tap_delays_sparse

Return the tap delays (which are multiples of the sampling interval).

Returns

The tap delays.

Return type

np.ndarray

property tap_indexes_sparse

Return the (sparse) tap indexes.

Returns

Return type

The indexes of the non-zero taps.

property tap_values

Return the tap values (including zero padding) as a numpy array.

Returns

The tap values (including zero padding).

Return type

np.ndarray

property tap_values_sparse

Return the tap values (not including zero padding) as a numpy array.

Returns

The tap values (not including possible zero padding).

Return type

np.ndarray

class pyphysim.channels.fading.TdlMimoChannel(fading_generator: Union[pyphysim.channels.fading_generators.JakesSampleGenerator, pyphysim.channels.fading_generators.RayleighSampleGenerator], channel_profile: Optional[pyphysim.channels.fading.TdlChannelProfile] = None, tap_powers_dB: Optional[numpy.ndarray] = None, tap_delays: Optional[numpy.ndarray] = None, Ts: Optional[float] = None)[source]

Bases: pyphysim.channels.fading.TdlChannel

Tapped Delay Line channel model, which corresponds to a multipath channel.

You can create a new TdlMimoChannel object either specifying the channel profile or specifying both the channel tap powers and delays.

Note that the TdlChannel class can already work with multiple antennas if provided fading_generator has a shape with two elements (number of receive antennas and number of transmit antennas). The TdlMimoChannel only adds a slight better interface over TdlChannel class for working with MIMO. This class is also useful to test MIMO transmission, with the added num_tx_antennas and num_rx_antennas properties.

Parameters
  • fading_generator (FadingGenerator) – The instance of a fading generator in the fading_generators module. It should be a subclass of FadingSampleGenerator. The fading generator will be used to generate the channel samples. The shape of the fading_generator will be ignored and replaced by provided number of antennas.

  • channel_profile (TdlChannelProfile) – The channel profile, which specifies the tap powers and delays.

  • tap_powers_dB (np.ndarray) – The powers of each tap (in dB). Dimension: L x 1 Note: The power of each tap will be a negative number (in dB).

  • tap_delays (np.ndarray) – The delay of each tap (in seconds). Dimension: L x 1

pyphysim.channels.fading_generators module

class pyphysim.channels.fading_generators.FadingSampleGenerator(shape: Optional[Union[int, Tuple[int, …]]] = None)[source]

Bases: object

Base class for fading generators.

Parameters

shape (tuple[int] | int, optional) – The shape of the sample generator. Each time generate_more_samples(num_samples) method is called it will generate samples with this shape as the first dimensions.

generate_more_samples(num_samples: Optional[int] = None)None[source]

Generate next samples.

When implementing this method in a subclass you must take the value of the self._shape attribute into account.

Parameters

num_samples (int, optional) – Number of samples (with the provided shape) to generate. If not provided it will be assumed to be 1.

get_samples()numpy.ndarray[source]

Get the last generated sample.

Returns

Return type

np.ndarray

get_similar_fading_generator() → Any[source]

Get a similar fading generator with the same configuration, but that generates independent samples.

property shape

Get the shape of the sampling generator

This is the shape of the samples that will be generated (not including num_samples).

Returns

Return type

tuple[int] | None

skip_samples_for_next_generation(num_samples: int)None[source]

Advance sample generation process by num_samples similarly to what would happen if you call generate_more_samples( num_samples=num_samples), but without actually generating the samples.

Parameters

num_samples (int) – How many samples to skip.

class pyphysim.channels.fading_generators.JakesSampleGenerator(Fd: float = 100, Ts: float = 0.001, L: int = 8, shape: Optional[Union[int, Tuple[int, …]]] = None, RS: Optional[numpy.random.mtrand.RandomState] = None)[source]

Bases: pyphysim.channels.fading_generators.FadingSampleGenerator

Class that generated fading samples according to the Jakes model given by

\[h(t) = \frac{1}{\sqrt{L}}\sum_{l=0}^{L-1}\exp\{j[2\pi f_D \cos(\phi_l)t+\psi_l]\}\]
Parameters
  • Fd (float) – The Doppler frequency (in Hertz).

  • Ts (float) – The sample interval (in seconds).

  • L (int) – The number of rays for the Jakes model.

  • shape (int | tuple[int], optional) – The shape of the sample generator. Each time the generate_jakes_samples method is called it will generate samples with this shape. If not provided, then 1 will be assumed. This could be used to generate MIMO channels. For instance, in order to generate channels samples for a MIMO scenario with 3 receive antennas and 2 transmit antennas use a shape of (3, 2).

  • RS (np.random.RandomState) – The RandomState object used to generate the random values. If not provided, the global RandomState in numpy will be used.

property Fd

The Doppler frequency (in Hertz)

property L

The number of rays for the Jakes model

property Ts

The sample interval (in seconds)

_generate_time_samples(num_samples: Optional[int] = None)numpy.ndarray[source]

Generate the time samples that will be used internally in generate_more_samples method.

Parameters

num_samples (int, optional) – Number of samples to be generated.

Returns

The numpy array with the time samples. The shape of the generated time variable is “(1, A, num_samples)”, where ‘A’ has as many ‘1’s as the length of self._shape. Ex: If self._shape is None then the shape of the returned ‘t’ variable is (1, num_samples). If self._shape is (2,3) then the shape of the returned ‘t’ variable is (1, 1, 1, num_samples)

Return type

np.ndarray

Notes

Each time _generate_time_samples is called it will update _current_time to reflect the advance of the time after generating the new samples.

_set_phi_and_psi_according_to_shape()None[source]

This will update the phi and psi attributes used to generate the jakes samples to reflect the current value of self._shape.

generate_more_samples(num_samples: Optional[int] = None)None[source]

Generate next samples.

Note that any subsequent call to this method continues from the point where the last call stopped. That is, if you generate 10 samples and then 15 more samples, you will get the same samples you would have got if you had generated 25 samples.

Parameters

num_samples (int, optional) – Number of samples (with the provided shape) to generate. If not provided it will be assumed to be 1.

Notes

This method will update the self._current_time variable.

get_similar_fading_generator() → Any[source]

Get a similar fading generator with the same configuration, but that generates independent samples.

Returns

Another JakesSampleGenerator object with the same configuration of this object.

Return type

JakesSampleGenerator

property shape

Get the shape of the sampling generator

This is the shape of the samples that will be generated (not including num_samples).

Returns

Return type

tuple[int] | None

skip_samples_for_next_generation(num_samples: int)None[source]

Advance sample generation process by num_samples similarly to what would happen if you call generate_more_samples( num_samples=num_samples), but without actually generating the samples.

This has the effect of advancing the internal time using by JakesSampleGenerator without generating any samples.

Parameters

num_samples (int) – How many samples to skip.

class pyphysim.channels.fading_generators.RayleighSampleGenerator(shape: Optional[Union[int, Tuple[int, …]]] = None)[source]

Bases: pyphysim.channels.fading_generators.FadingSampleGenerator

Class that generates fading samples from a Raleigh distribution.

Parameters

shape (int | tuple[int] | None) – The shape of the sample generator. Each time the generate_jakes_samples method is called it will generate samples with this shape. If not provided, then 1 will be assumed.

generate_more_samples(num_samples: Optional[int] = None)None[source]

Generate next samples.

Parameters

num_samples (int, optional) – Number of samples (with the provided shape) to generate. If not provided it will be assumed to be 1.

get_similar_fading_generator() → Any[source]

Get a similar fading generator with the same configuration, but that generates independent samples.

Returns

Another RayleighSampleGenerator object with the same configuration of this object.

Return type

RayleighSampleGenerator

skip_samples_for_next_generation(num_samples: int)None[source]

Advance sample generation process by num_samples similarly to what would happen if you call generate_more_samples( num_samples=num_samples), but without actually generating the samples.

Since the samples generated by RayleighSampleGenerator are independent, calling this method has no effect.

Parameters

num_samples (int) – How many samples to skip. This is ignored in the RayleighSampleGenerator. Since the different samples are uncorrelated then calling skip_samples_for_next_generation does not do anything.

pyphysim.channels.fading_generators.generate_jakes_samples(Fd: float, Ts: float = 0.001, NSamples: int = 100, L: int = 8, shape: Optional[Tuple[int, …]] = None, current_time: float = 0, phi_l: Optional[numpy.ndarray] = None, psi_l: Optional[numpy.ndarray] = None) → Tuple[float, numpy.ndarray][source]

Generates channel samples according to the Jakes model.

This functions generates channel samples for a single tap according to the Jakes model given by

(1)\[h(t) = \frac{1}{\sqrt{L}}\sum_{l=0}^{L-1}\exp\{j[2\pi f_D \cos(\phi_l)t+\psi_l]\}\]
Parameters
  • Fd (float) – The Doppler frequency (in Hertz).

  • Ts (float) – The sample interval (in seconds).

  • NSamples (int) – The number of samples to generate.

  • L (int) – The number of rays for the Jakes model.

  • shape (tuple[int]) – The shape of the generated channel. This is used to generate MIMO channels. For instance, in order to generate channels samples for a MIMO scenario with 3 receive antennas and 2 transmit antennas use a shape of (3, 2).

  • current_time (float) – The current start time

  • phi_l (np.ndarray) – The “phi” part in Jakes model

  • psi_l (np.ndarray) – The “psi” part in Jakes model

Returns

The first element in the returned tuple is the new current time (that should be used the next time this function is called to ‘continue’ the fading).

The second element in the returned tuple is the generated channel. If shape is None the the shape of the returned h is equal to ( NSamples,). That is, h is a 1-dimensional numpy array. If shape was provided then the shape of h is the provided shape with an additional dimension for the time (the last dimension). For instance, if a shape of (3, 2) was provided then the shape of the returned h will be (3, 2, NSamples).

Return type

(float, np.ndarray)

pyphysim.channels.multiuser module

Module containing multiuser channels.

The MultiUserChannelMatrix and MultiUserChannelMatrixExtInt classes implement the MIMO Interference Channel (MIMO-IC) model, where the first one does not include an external interference source while the last one includes it. The MIMO-IC model is shown in the Figure below.

_images/mimo_ic.svg

MIMO Interference Channel

class pyphysim.channels.multiuser.MuChannel(N: Union[int, Tuple[int, int]], fading_generator: Optional[Union[pyphysim.channels.fading_generators.JakesSampleGenerator, pyphysim.channels.fading_generators.RayleighSampleGenerator]] = None, channel_profile: Optional[pyphysim.channels.fading.TdlChannelProfile] = None, tap_powers_dB: Optional[numpy.ndarray] = None, tap_delays: Optional[numpy.ndarray] = None, Ts: Optional[float] = None)[source]

Bases: object

SISO multiuser channel.

Each transmitter sends data to its own receiver while interfering to other receivers.

Note that noise is NOT added.

Parameters
  • N (int | tuple[int,int]) – The number of transmit/receive pairs.

  • fading_generator (T <= fading_generators.FadingSampleGenerator) – The instance of a fading generator in the fading_generators module. It should be a subclass of FadingSampleGenerator. The fading generator will be used to generate the channel samples. However, since we have multiple links, the provided fading generator will actually be used to create similar (but independent) fading generators. If not provided then RayleighSampleGenerator will be used

  • channel_profile (TdlChannelProfile) – The channel profile, which specifies the tap powers and delays.

  • tap_powers_dB (np.ndarray) – The powers of each tap (in dB). Dimension: L x 1 Note: The power of each tap will be a negative number (in dB).

  • tap_delays (np.ndarray) – The delay of each tap (in seconds). Dimension: L x 1

Returns

The created object.

Return type

MuChannel

property channel_profile

Return the channel profile.

Returns

The channel profile.

Return type

TdlChannelProfile

corrupt_data(signal: numpy.ndarray)numpy.ndarray[source]

Corrupt data passed through the TDL channels of each link.

Note that noise is NOT added in corrupt_data.

Parameters

signal (np.ndarray) – Signal to be transmitted through the channel. This should be a 2D numpy array (1D array if there is only one transmitter), where each row corresponds to the transmit data of one transmitter.

Returns

Received signal at each receiver. Each row corresponds to one receiver.

Return type

np.ndarray

corrupt_data_in_freq_domain(signal: numpy.ndarray, fft_size: int, carrier_indexes: Union[numpy.ndarray, List[int], slice] = None)numpy.ndarray[source]

Corrupt data passed through the TDL channels of each link, but in the frequency domain..

For each link, this is ROUGHLY equivalent to modulating signal with OFDM using fft_size subcarriers, transmitting through a regular TdlChannel, and then demodulating with OFDM to recover the received signal.

One important difference is that here the channel is considered constant during the transmission of fft_size elements in signal, and then it is varied by the equivalent of the variation for that number of elements. That is, the channel is block static.

Note that noise is NOT added in corrupt_data.

Parameters
  • signal (np.ndarray | list[np.ndarray]) – Signal to be transmitted through the channel. This should be a 2D numpy array where each row corresponds to the transmit data of one transmitter. It can also be a list of numpy arrays or, if there is only one transmitter, a single 1D numpy array.

  • fft_size (int) – The size of the Fourier transform to get the frequency response.

  • carrier_indexes (slice | np.ndarray | list[int]) – The indexes of the subcarriers where signal is to be transmitted (all users will use the same indexes). If it is None assume all subcarriers will be used.

Returns

Received signal at each receiver. Each row corresponds to one receiver.

Return type

np.ndarray

get_last_impulse_response(rx_idx: int, tx_idx: int)pyphysim.channels.fading.TdlImpulseResponse[source]

Get the last generated impulse response.

A new impulse response is generated when the method corrupt_data is called. You can use the get_last_impulse_response method to get the impulse response used to corrupt the last data.

Parameters
  • rx_idx (int) – The index of the receiver.

  • tx_idx (int) – The index of the transmitter

Returns

The impulse response of the channel that was used to corrupt the last data for the link from transmitter tx_idx to receiver rx_idx.

Return type

TdlImpulseResponse

property num_rx_antennas

Get the number of receive antennas.

Returns

The number of receive antennas.

Return type

int

property num_taps

Get the number of taps in the profile.

Note that all links have the same channel profile.

Returns

The number of taps in the channel (not including any zero padding).

Return type

int

property num_taps_with_padding

Get the number of taps in the profile including zero-padding when the profile is discretized.

If the profile is not discretized an exception is raised.

Note that all links have the same channel profile.

Returns

The number of taps in the channel (including any zero padding).

Return type

int

property num_tx_antennas

Get the number of transmit antennas.

Returns

The number of transmit antennas.

Return type

np.ndarray

property pathloss_matrix

Get the matrix with the pathloss from each transmitter to each receiver.

Returns

The pathloss matrix, if it was set, or None if there is no pathloss.

Return type

np.ndarray

set_pathloss(pathloss_matrix: numpy.ndarray)None[source]

Set the path loss (IN LINEAR SCALE) from each transmitter to each receiver.

The path loss will be accounted when calling the corrupt_data method.

If you want to disable the path loss, set pathloss_matrix to None.

Parameters

pathloss_matrix (np.ndarray) – A matrix with dimension “K x K”, where K is the number of users, with the path loss (IN LINEAR SCALE) from each transmitter (columns) to each receiver (rows). If you want to disable the path loss then set it to None.

Notes

Note that path loss is a power relation, which means that the channel coefficients will be multiplied by the square root of elements in pathloss_matrix.

property switched_direction

Get the value of switched_direction.

Returns

True if direction is switched and False otherwise.

Return type

bool

class pyphysim.channels.multiuser.MuMimoChannel(N: Union[int, Tuple[int, int]], num_rx_antennas: int, num_tx_antennas: int, fading_generator: Optional[Union[pyphysim.channels.fading_generators.JakesSampleGenerator, pyphysim.channels.fading_generators.RayleighSampleGenerator]] = None, channel_profile: Optional[pyphysim.channels.fading.TdlChannelProfile] = None, tap_powers_dB: Optional[numpy.ndarray] = None, tap_delays: Optional[numpy.ndarray] = None, Ts: Optional[float] = None)[source]

Bases: pyphysim.channels.multiuser.MuChannel

MIMO multiuser channel.

Each transmitter sends data to its own receiver while interfering to other receivers.

Note that noise is NOT added.

Parameters
  • N (int | tuple[int, int]) – The number of transmit/receive pairs.

  • num_rx_antennas (int) – Number of receive antennas of each user.

  • num_tx_antennas (int) – Number of transmit antennas of each user.

  • fading_generator (T <= fading_generators.FadingSampleGenerator) – The instance of a fading generator in the fading_generators module. It should be a subclass of FadingSampleGenerator. The fading generator will be used to generate the channel samples. However, since we have multiple links, the provided fading generator will actually be used to create similar (but independent) fading generators. If not provided then RayleighSampleGenerator will be used

  • channel_profile (TdlChannelProfile) – The channel profile, which specifies the tap powers and delays.

  • tap_powers_dB (np.ndarray) – The powers of each tap (in dB). Dimension: L x 1 Note: The power of each tap will be a negative number (in dB).

  • tap_delays (np.ndarray) – The delay of each tap (in seconds). Dimension: L x 1

class pyphysim.channels.multiuser.MultiUserChannelMatrix[source]

Bases: object

Stores the (fast fading) channel matrix of a multi-user scenario. The path-loss from each transmitter to each receiver is also be accounted if the set_pathloss is called to set the path-loss matrix.

This channel matrix can be seem as an concatenation of blocks (of non-uniform size) where each block is a channel from one transmitter to one receiver and the block size is equal to the number of receive antennas of the receiver times the number of transmit antennas of the transmitter.

For instance, in a 3-users scenario the block (1,0) corresponds to the channel between the transmit antennas of user 0 and the receive antennas of user 1 (indexing staring at zero). If the number of receive antennas and transmit antennas of the three users are [2, 4, 6] and [2, 3, 5], respectively, then the block (1,0) would have a dimension of 4x2. Likewise, the channel matrix would look similar to the block structure below.

2 x 2

2 x 3

2 x 5

4 x 2

4 x 3

4 x 5

6 x 2

6 x 3

6 x 5

It is possible to initialize the channel matrix randomly by calling the randomize method, or from a given matrix by calling the init_from_channel_matrix method.

In order to get the channel matrix of a specific user k to another user l, call the get_Hkl method.

property H

Get method for the H property.

Returns

The channel from all transmitters to all receivers. This is a numpy array of numpy arrays.

Return type

np.ndarray

property K

Get method for the K property.

Returns

The number of users (transmit-receive pairs).

Return type

int

property Nr

Get method for the Nr property.

Returns

The number of receive antennas of all users.

Return type

np.ndarray

property Nt

Get method for the Nt property.

Returns

The number of transmit antennas of all users.

Return type

np.ndarray

property W

Post processing filters (a list of 2D numpy arrays) for each user.

Returns

The Post processing filters for each user.

Return type

list[np.ndarray]

_calc_Bkl_cov_matrix_all_l(F_all_users: numpy.ndarray, k: int, N0_or_Rek: NumberOrArray = 0.0)numpy.ndarray[source]

Calculates the interference-plus-noise covariance matrix for all streams at receiver \(k\) according to equation (28) in [ Cadambe2008]_.

The interference-plus-noise covariance matrix for stream \(l\) of user \(k\) is given by Equation (28) in [Cadambe2008], which is reproduced below

\(\mtB^{[kl]} = \sum_{j=1}^{K} \frac{P^{[j]}}{d^{[j]}} \sum_{d=1}^{d^{[j]}} \mtH^{[kj]}\mtV_{\star l}^{[j]} \mtV_{\star l}^{[j]\dagger} \mtH^{[kj]\dagger} - \frac{P^{[k]}}{d^{[k]}} \mtH^{[kk]} \mtV_{\star l}^{[k]} \mtV_{\star l}^{[k]\dagger} \mtH^{[kk]\dagger} + \mtI_{N^{[k]}}\)

where \(P^{[k]}\) is the transmit power of transmitter \(k\), \(d^{[k]}\) is the number of degrees of freedom of user \(k\), \(\mtH^{[kj]}\) is the channel between transmitter \(j\) and receiver \(k\), \(\mtV_{\star l}\) is the \(l\)-th column of the precoder of user \(k\) and \(\mtI_{N^{k}}\) is an identity matrix with size equal to the number of receive antennas of receiver \(k\).

Parameters
  • F_all_users (list[np.ndarray] | np.ndarray) – The precoder of all users (already taking into account the transmit power). This can be a list of numpy arrays or a 1D numpy array of numpy arrays.

  • k (int) – Index of the desired user.

  • N0_or_Rek (float | np.ndarray) – If this is a 2D numpy array, it is interpreted as the covariance matrix of any external interference plus noise. If this is a number, it is interpreted as the noise power, in which case the covariance matrix will be an identity matrix times this noise power.

Returns

Bkl – Covariance matrix of all streams of user k. Each element of the returned 1D numpy array is a 2D numpy complex array corresponding to the covariance matrix of one stream of user k.

Return type

np.ndarray

Notes

To be simple, a function that returns the covariance matrix of only a single stream “l” of the desired user “k” could be implemented, but in the order to calculate the max SINR algorithm we need the covariance matrix of all streams and returning them in single function as is done here allows us to calculate the first part in equation (28) of [Cadambe2008] only once, since it is the same for all streams.

_calc_Bkl_cov_matrix_first_part(F_all_users: numpy.ndarray, k: int, N0_or_Rek: NumberOrArray = 0.0)numpy.ndarray[source]

Calculates the first part in the equation of the Blk covariance matrix in equation (28) of [Cadambe2008].

The first part is given by

\(\sum_{j=1}^{K} \frac{P^{[j]}}{d^{[j]}} \sum_{d=1}^{d^{[j]}} \mtH^{[kj]}\mtV_{\star d}^{[j]} \mtV_{\star d}^{[j]\dagger} \mtH^{[kj]\dagger} + \mtI_{Nk}\)

Note that it only depends on the value of \(k\).

Parameters
  • F_all_users (list[np.ndarray] | np.ndarray) – The precoder of all users (already taking into account the transmit power). It can be a list of numpy arrays or a numpy array of numpy arrays.

  • k (int) – Index of the desired user.

  • N0_or_Rek (float | np.ndarray) – If this is a 2D numpy array, it is interpreted as the covariance matrix of any external interference plus noise. If this is a number, it is interpreted as the noise power, in which case the covariance matrix will be an identity matrix times this noise power.

Returns

first_part

Return type

np.ndarray

_calc_Bkl_cov_matrix_second_part(Fk: numpy.ndarray, k: int, l: int)numpy.ndarray[source]

Calculates the second part in the equation of the Blk covariance matrix in equation (28) of [Cadambe2008] (note that it does not include the identity matrix).

The second part is given by

\(\frac{P^{[k]}}{d^{[k]}} \mtH^{[kk]} \mtV_{\star l}^{[k]} \mtV_{\star l}^{[k]\dagger} \mtH^{[kk]\dagger}\)

Parameters
  • Fk (np.ndarray) – The precoder of the desired user.

  • k (int) – Index of the desired user.

  • l (int) – Index of the desired stream.

Returns

second_part – Second part in equation (28) of [Cadambe2008].

Return type

np.ndarray

_calc_JP_Bkl_cov_matrix_all_l(F_all_users: numpy.ndarray, k: int, N0_or_Rek: NumberOrArray = 0.0)numpy.ndarray[source]

Calculates the interference-plus-noise covariance matrix for all streams at receiver \(k\) according to equation (28) in [ Cadambe2008]_.

The interference-plus-noise covariance matrix for stream \(l\) of user \(k\) is given by Equation (28) in [Cadambe2008], which is reproduced below

\(\mtB^{[kl]} = \sum_{j=1}^{K} \frac{P^{[j]}}{d^{[j]}} \sum_{d=1}^{d^{[j]}} \mtH^{[kj]}\mtV_{\star l}^{[j]} \mtV_{\star l}^{[j]\dagger} \mtH^{[kj]\dagger} - \frac{P^{[k]}}{d^{[k]}} \mtH^{[kk]} \mtV_{\star l}^{[k]} \mtV_{\star l}^{[k]\dagger} \mtH^{[kk]\dagger} + \mtI_{N^{[k]}}\)

where \(P^{[k]}\) is the transmit power of transmitter \(k\), \(d^{[k]}\) is the number of degrees of freedom of user \(k\), \(\mtH^{[kj]}\) is the channel between transmitter \(j\) and receiver \(k\), \(\mtV_{\star l}\) is the \(l\)-th column of the precoder of user \(k\) and \(\mtI_{N^{k}}\) is an identity matrix with size equal to the number of receive antennas of receiver \(k\).

Parameters
  • F_all_users (list[np.ndarray] | np.ndarray) – The precoder of all users (already taking into account the transmit power). This can be either a 1D numpy array of numpy arrays or a list of numpy arrays.

  • k (int) – Index of the desired user.

  • N0_or_Rek (float | np.ndarray) – If this is a 2D numpy array, it is interpreted as the covariance matrix of any external interference plus noise. If this is a number, it is interpreted as the noise power, in which case the covariance matrix will be an identity matrix times this noise power.

Returns

Bkl – Covariance matrix of all streams of user k. Each element of the returned 1D numpy array is a 2D numpy complex array corresponding to the covariance matrix of one stream of user k.

Return type

np.ndarray

Notes

To be simple, a function that returns the covariance matrix of only a single stream “l” of the desired user “k” could be implemented, but in the order to calculate the max SINR algorithm we need the covariance matrix of all streams and returning them in single function as is done here allows us to calculate the first part in equation (28) of [Cadambe2008] only once, since it is the same for all streams.

_calc_JP_Bkl_cov_matrix_first_part(F_all_users: numpy.ndarray, k: int, noise_power: float = 0.0)numpy.ndarray[source]

Calculates the first part in the equation of the Blk covariance matrix in equation (28) of [Cadambe2008] when joint process is employed.

The first part is given by

\(\sum_{j=1}^{K} \frac{P^{[j]}}{d^{[j]}} \sum_{d=1}^{d^{[j]}} \mtH^{[kj]}\mtV_{\star d}^{[j]} \mtV_{\star d}^{[j]\dagger} \mtH^{[kj]\dagger} + \mtI_{Nk}\)

Note that it only depends on the value of \(k\).

Parameters
  • F_all_users (list[np.ndarray] | np.ndarray) – The precoder of all users (already taking into account the transmit power). It can be a list of numpy arrays or a numpy array of numpy arrays.

  • k (int) – Index of the desired user.

  • noise_power (float | None, optional) – The noise power.

Returns

Return type

np.ndarray

_calc_JP_Bkl_cov_matrix_first_part_impl(Hk: numpy.ndarray, F_all_users: numpy.ndarray, Rek: NumberOrArray)numpy.ndarray[source]

Common implementation of the _calc_JP_Bkl_cov_matrix_first_part.

Parameters
  • Hk (np.ndarray) – The channel from all transmitters (not including external interference source, if any) to receiver k.

  • F_all_users (list[np.ndarray]) – The precoder of all users (already taking into account the transmit power).

  • Rek (np.ndarray | float) – Covariance matrix of the external interference (if there is any) plus noise.

Returns

The first_part for the Bkl matrix computation.

Return type

np.ndarray

_calc_JP_Bkl_cov_matrix_second_part(Fk: numpy.ndarray, k: int, l: int)numpy.ndarray[source]

Calculates the second part in the equation of the Blk covariance matrix in equation (28) of [Cadambe2008] (note that it does not include the identity matrix).

The second part is given by

\(\frac{P^{[k]}}{d^{[k]}} \mtH^{[kk]} \mtV_{\star l}^{[k]} \mtV_{\star l}^{[k]\dagger} \mtH^{[kk]\dagger}\)

Parameters
  • Fk (np.ndarray) – The precoder of the desired user.

  • k (int) – Index of the desired user.

  • l (int) – Index of the desired stream.

Returns

second_part – Second part in equation (28) of [Cadambe2008].

Return type

np.ndarray.

static _calc_JP_Bkl_cov_matrix_second_part_impl(Hk: numpy.ndarray, Fk: numpy.ndarray, l: int)numpy.ndarray[source]

Common implementation of the _calc_JP_Bkl_cov_matrix_second_part method.

Parameters
  • Hk (np.ndarray) –

  • Fk (np.ndarray) –

  • l (int) –

Returns

Return type

np.ndarray

_calc_JP_Q_impl(k: int, F_all_users: numpy.ndarray)numpy.ndarray[source]

Calculates the interference covariance matrix (without any noise) at the \(k\)-th receiver with a joint processing scheme.

See the documentation of the calc_JP_Q method.

Parameters
  • k (int) – The user index.

  • F_all_users (list[np.ndarray] | np.ndarray) – The precoders of all users. It can be a list of numpy arrays or a numpy array of numpy arrays.

Returns

The interference covariance matrix (without any noise).

Return type

np.ndarray

_calc_JP_SINR_k(k: int, Fk: numpy.ndarray, Uk: numpy.ndarray, Bkl_all_l: numpy.ndarray)numpy.ndarray[source]

Calculates the SINR of all streams of user ‘k’.

Parameters
  • k (int) – Index of the desired user.

  • Fk (np.ndarray) – The precoder of user k.

  • Uk (np.ndarray) – The receive filter of user k (before applying the conjugate transpose).

  • Bkl_all_l (list[np.ndarray] | np.ndarray) – A sequence (1D numpy array, a list, etc) of 2D numpy arrays corresponding to the Bkl matrices for all ‘l’s.

Returns

SINR_k – The SINR for the different streams of user k.

Return type

np.ndarray

static _calc_JP_SINR_k_impl(Hk: numpy.ndarray, Fk: numpy.ndarray, Uk: numpy.ndarray, Bkl_all_l: numpy.ndarray)numpy.ndarray[source]

Implementation of the _calc_JP_SINR_k() method.

Parameters
  • Hk (np.ndarray) – Channel from all transmitters to receiver k.

  • Fk (np.ndarray) – The precoder of user k.

  • Uk (np.ndarray) – The receive filter of user k (before applying the conjugate transpose).

  • Bkl_all_l (list[np.ndarray]) – A sequence (1D numpy array, a list, etc) of 2D numpy arrays corresponding to the Bkl matrices for all ‘l’s.

Returns

SINR_k – The SINR for the different streams of user k.

Return type

np.ndarray

Notes

The implementation of the _calc_JP_SINR_k method is almost the same for the MultiuserChannelMatrix and MultiuserChannelMatrixExtint class, except for the Hk argument. Therefore, the common code was put here and in each class the _calc_JP_SINR_k() is implemented as simply getting the correct Hk argument and then calling _calc_JP_SINR_k_impl().

_calc_Q_impl(k: int, F_all_users: numpy.ndarray)numpy.ndarray[source]

Calculates the interference covariance matrix (without any noise) at the \(k\)-th receiver.

See the documentation of the calc_Q method.

Parameters
  • k (int) – Index of the desired receiver.

  • F_all_users (np.ndarray) – The precoder of all users (already taking into account the transmit power). This should be a 1D numpy array of 2D numpy arrays.

Returns

Return type

np.ndarray

_calc_SINR_k(k: int, Fk: numpy.ndarray, Uk: numpy.ndarray, Bkl_all_l: numpy.ndarray)numpy.ndarray[source]

Calculates the SINR of all streams of user ‘k’.

Parameters
  • k (int) – Index of the desired user.

  • Fk (np.ndarray) – The precoder of user k.

  • Uk (np.ndarray) – The receive filter of user k (before applying the conjugate transpose).

  • Bkl_all_l (list[np.ndarray] | np.ndarray) – A sequence (1D numpy array, a list, etc) of 2D numpy arrays corresponding to the Bkl matrices for all ‘l’s.

Returns

SINR_k – The SINR for the different streams of user k.

Return type

np.ndarray

static _from_small_matrix_to_big_matrix(small_matrix: numpy.ndarray, Nr: numpy.ndarray, Nt: numpy.ndarray, Kr: int, Kt: Optional[int] = None)numpy.ndarray[source]

Convert from a small matrix to a big matrix by repeating elements according to the number of receive and transmit antennas.

Parameters
  • small_matrix (np.ndarray) – Any 2D numpy array

  • Nr (np.ndarray) – Number of antennas at each receiver. This should be a 1D numpy array.

  • Nt (np.ndarray) – Number of antennas at each transmitter. This should be a 1D numpy array.

  • Kr (int) – Number of receivers to consider.

  • Kt (int, optional) – Number of transmitters to consider. It not provided the value of Kr will be used.

Returns

big_matrix – The converted matrix. This is a 2D numpy array

Return type

np.ndarray

Notes

Since a ‘user’ is a transmit/receive pair then the small_matrix will be a square matrix and Kr must be equal to Kt. However, in the MultiUserChannelMatrixExtInt class we will only have the ‘transmitter part’ for the external interference sources. That means that small_matrix will have more columns then rows and Kt will be greater then Kr.

Examples

>>> K = 3
>>> Nr = np.array([2, 4, 6])
>>> Nt = np.array([2, 3, 5])
>>> small_matrix = np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> MultiUserChannelMatrix._from_small_matrix_to_big_matrix(                small_matrix, Nr, Nt, K)
array([[1, 1, 2, 2, 2, 3, 3, 3, 3, 3],
       [1, 1, 2, 2, 2, 3, 3, 3, 3, 3],
       [4, 4, 5, 5, 5, 6, 6, 6, 6, 6],
       [4, 4, 5, 5, 5, 6, 6, 6, 6, 6],
       [4, 4, 5, 5, 5, 6, 6, 6, 6, 6],
       [4, 4, 5, 5, 5, 6, 6, 6, 6, 6],
       [7, 7, 8, 8, 8, 9, 9, 9, 9, 9],
       [7, 7, 8, 8, 8, 9, 9, 9, 9, 9],
       [7, 7, 8, 8, 8, 9, 9, 9, 9, 9],
       [7, 7, 8, 8, 8, 9, 9, 9, 9, 9],
       [7, 7, 8, 8, 8, 9, 9, 9, 9, 9],
       [7, 7, 8, 8, 8, 9, 9, 9, 9, 9]])
property big_H

Get method for the big_H property.

Returns

The channel from all transmitters to all receivers as a single big matrix (numpy complex array)

Return type

np.ndarray

property big_W

Post processing filters (a block diagonal matrix) for each user.

Returns

The big block diagonal matrix with the post processing filters for each user.

Return type

np.ndarray

calc_JP_Q(k: int, F_all_users: numpy.ndarray)numpy.ndarray[source]

Calculates the interference plus noise covariance matrix at the \(k\)-th receiver with a joint processing scheme.

The interference covariance matrix at the \(k\)-th receiver, \(\mtQ k\), is given by

\(\mtQ k = \sum_{j=1, j \neq k}^{K} \frac{P_j}{Ns_j} \mtH_{k} \mtF_j \mtF_j^H \mtH_{k}^H\)

where \(P_j\) is the transmit power of transmitter \(j\), and \(Ns_j\) is the number of streams for user \(j\).

Parameters
  • k (int) – Index of the desired receiver.

  • F_all_users (np.ndarray | list[np.ndarray]) – The precoder of all users (already taking into account the transmit power).

Returns

Qk – The interference covariance matrix at receiver \(k\).

Return type

np.ndarray

calc_JP_SINR(F: numpy.ndarray, U: numpy.ndarray)numpy.ndarray[source]

Calculates the SINR values (in linear scale) of all streams of all users with the current IA solution.

The noise variance used will be the value of the noise_var property.

Parameters
  • F (np.ndarray) – The precoders of all users. This should be a 1D numpy array of 2D numpy arrays.

  • U (np.ndarray) – The receive filters of all users. This should be a 1D numpy array of 2D numpy arrays.

Returns

SINRs – The SINR (in linear scale) of all streams of all users. This is a 1D numpy array of 1D numpy arrays (of floats).

Return type

np.ndarray

calc_Q(k: int, F_all_users: numpy.ndarray)numpy.ndarray[source]

Calculates the interference plus noise covariance matrix at the \(k\)-th receiver.

The interference covariance matrix at the \(k\)-th receiver, \(\mtQ k\), is given by

\(\mtQ k = \sum_{j=1, j \neq k}^{K} \frac{P_j}{Ns_j} \mtH_{kj} \mtF_j \mtF_j^H \mtH_{kj}^H\)

where \(P_j\) is the transmit power of transmitter \(j\), and \(Ns_j\) is the number of streams for user \(j\).

Parameters
  • k (int) – Index of the desired receiver.

  • F_all_users (np.ndarray) – The precoder of all users (already taking into account the transmit power). This should be a 1D numpy array of 2D numpy arrays.

Returns

Qk – The interference covariance matrix at receiver \(k\) (a 2D numpy complex array).

Return type

np.ndarray

calc_SINR(F: numpy.ndarray, U: numpy.ndarray)numpy.ndarray[source]

Calculates the SINR values (in linear scale) of all streams of all users with the current IA solution.

The noise variance used will be the value of the noise_var property.

Parameters
  • F (np.ndarray) – The precoders of all users. This should be a 1D numpy array of 2D numpy arrays.

  • U (np.ndarray) – The receive filters of all users. This should be a 1D numpy array of 2D numpy arrays.

Returns

SINRs – The SINR (in linear scale) of all streams of all users. This is a 1D numpy array of 1D numpy arrays (of floats)

Return type

np.ndarray

corrupt_concatenated_data(data: numpy.ndarray)numpy.ndarray[source]

Corrupt data passed through the channel.

If self.noise_var is set to some scalar number then white noise will also be added.

Parameters

data (np.ndarray) – A bi-dimensional numpy array with the concatenated data of all transmitters. The dimension of data is sum(self.Nt) x NSymb. That is, the number of rows corresponds to the sum of the number of transmit antennas of all users and the number of columns correspond to the number of transmitted symbols.

Returns

A bi-dimension numpy array where the number of rows corresponds to the sum of the number of receive antennas of all users and the number of columns correspond to the number of transmitted symbols.

Return type

np.ndarray

corrupt_data(data: numpy.ndarray)numpy.ndarray[source]

Corrupt data passed through the channel.

If the noise_var is supplied then an white noise will also be added.

Parameters

data (np.ndarray) – An array of numpy matrices with the data of the multiple users. The k-th element in data is a numpy array with dimension Nt_k x NSymbs, where Nt_k is the number of transmit antennas of the k-th user and NSymbs is the number of transmitted symbols.

Returns

A numpy array where each element contains the received data (a 2D numpy array) of a user.

Return type

np.ndarray

get_Hk(k: int)numpy.ndarray[source]

Get the channel from all transmitters to receiver k.

Parameters

k (int) – Receiving user.

Returns

channel_k – Channel from all transmitters to receiver k. This is a 2D numpy array.

Return type

np.ndarray

See also

get_Hkl()

Examples

>>> multiH = MultiUserChannelMatrix()
>>> H = np.reshape(np.r_[0:16], [4,4])
>>> Nt = np.array([2, 2])
>>> Nr = np.array([2, 2])
>>> multiH.init_from_channel_matrix(H, Nr, Nt, 2)
>>> print(multiH.big_H)
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]]
>>> print(multiH.get_Hk(0))
[[0 1 2 3]
 [4 5 6 7]]
>>> print(multiH.get_Hk(1))
[[ 8  9 10 11]
 [12 13 14 15]]
get_Hkl(k: int, l: int)numpy.ndarray[source]

Get the channel matrix from user l to user k.

Parameters
  • l (int) – Transmitting user.

  • k (int) – Receiving user.

Returns

channel – Channel from transmitter l to receiver k. This is a 2D numpy array.

Return type

np.ndarray

See also

get_Hk()

Examples

>>> multiH = MultiUserChannelMatrix()
>>> H = np.reshape(np.r_[0:16], [4,4])
>>> Nt = np.array([2, 2])
>>> Nr = np.array([2, 2])
>>> multiH.init_from_channel_matrix(H, Nr, Nt, 2)
>>> print(multiH.big_H)
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]]
>>> print(multiH.get_Hkl(0, 0))
[[0 1]
 [4 5]]
>>> print(multiH.get_Hkl(1, 0))
[[ 8  9]
 [12 13]]
init_from_channel_matrix(channel_matrix: numpy.ndarray, Nr: Union[numpy.ndarray, int], Nt: Union[numpy.ndarray, int], K: int)None[source]

Initializes the multiuser channel matrix from the given channel_matrix.

Parameters
  • channel_matrix (np.ndarray) – A matrix concatenating the channel of all users (from each transmitter to each receiver). This is a 2D numpy array.

  • Nr (int | np.ndarray) – Number of antennas at each receiver.

  • Nt (int | np.ndarray) – Number of antennas at each transmitter.

  • K (int) – Number of transmit/receive pairs.

Raises

ValueError – If the arguments are invalid.

property last_noise

Get method for the last_noise property.

Returns

The last AWGN noise array added to corrupt the data.

Return type

None | np.ndarray

property noise_var

Get method for the noise_var property.

Returns

The noise variance, if noise is being added in “corrupt_*data” methods.

Return type

None | float

property pathloss

Get method for the pathloss property.

Returns

The pathloss matrix (if one was set).

Return type

None | np.ndarray

randomize(Nr: Union[numpy.ndarray, int], Nt: Union[numpy.ndarray, int], K: int)None[source]

Generates a random channel matrix for all users.

Parameters
  • Nr (int | np.ndarray) – Number of receive antennas of each user. If an integer is specified, all users will have that number of receive antennas.

  • Nt (int | np.ndarray) – Number of transmit antennas of each user. If an integer is specified, all users will have that number of receive antennas.

  • K (int) – Number of users.

re_seed()None[source]

Re-seed the channel and noise RandomState objects randomly.

If you want to specify the seed for each of them call the set_channel_seed and set_noise_seed methods and pass the desired seed for each of them.

set_channel_seed(seed: Optional[Union[int, List[int], numpy.ndarray]] = None)None[source]

Set the seed of the RandomState object used to generate the random elements of the channel (when self.randomize is called).

Parameters

seed (None | int | array_like) – Random seed initializing the pseudo-random number generator. See np.random.RandomState help for more info.

set_noise_seed(seed: Optional[Union[int, List[int], numpy.ndarray]] = None)None[source]

Set the seed of the RandomState object used to generate the random noise elements (when the corrupt data function is called).

Parameters

seed (None | int | array_like) – Random seed initializing the pseudo-random number generator. See np.random.RandomState help for more info.

set_pathloss(pathloss_matrix: Optional[numpy.ndarray] = None)None[source]

Set the path loss (IN LINEAR SCALE) from each transmitter to each receiver.

The path loss will be accounted when calling the get_Hkl, get_Hk, the corrupt_concatenated_data and the corrupt_data methods.

If you want to disable the path loss, set pathloss_matrix to None.

Parameters

pathloss_matrix (np.ndarray) – A matrix with dimension “K x K”, where K is the number of users, with the path loss (IN LINEAR SCALE) from each transmitter (columns) to each receiver (rows). If you want to disable the path loss then set it to None.

Notes

Note that path loss is a power relation, which means that the channel coefficients will be multiplied by the square root of elements in pathloss_matrix.

set_post_filter(filters: numpy.ndarray)None[source]

Set the post-processing filters.

The post-processing filters will be applied to the data after if has been corrupted by the channel in either the corrupt_data or the corrupt_concatenated_data methods.

Parameters

filters (list[np.ndarray] | np.ndarray) – The post processing filters of each user. This should be a list of 2D np arrays or a 1D np array of 2D np arrays.

class pyphysim.channels.multiuser.MultiUserChannelMatrixExtInt[source]

Bases: pyphysim.channels.multiuser.MultiUserChannelMatrix

Very similar to the MultiUserChannelMatrix class, but the MultiUserChannelMatrixExtInt also includes the effect of an external interference.

This channel matrix can be seem as an concatenation of blocks (of non-uniform size) where each block is a channel from one transmitter to one receiver and the block size is equal to the number of receive antennas of the receiver times the number of transmit antennas of the transmitter. The difference compared with MultiUserChannelMatrix is that in the MultiUserChannelMatrixExtInt class the interference user counts as one more user, but with zero receive antennas.

For instance, in a 3-users scenario the block (1,0) corresponds to the channel between the transmit antennas of user 0 and the receive antennas of user 1 (indexing staring at zero). If the number of receive antennas and transmit antennas of the three users are [2, 4, 6] and [2, 3, 5], respectively, then the block (1,0) would have a dimension of 4x2. The external interference will count as one more block where the number of columns of this block corresponds to the rank of the external interference. If the external interference has a rank 2 then the complete channel matrix would look similar to the block structure below.

2 x 2

2 x 3

2 x 5

2 x 2

4 x 2

4 x 3

4 x 5

4 x 2

6 x 2

6 x 3

6 x 5

6 x 2

The methods from the MultiUserChannelMatrix class that makes sense were reimplemented here to include information regarding the external interference.

property H

Get method for the H property.

property H_no_ext_int

Get method for the H_no_ext_int property.

property K

Get method for the K property.

property Nr

Get method for the Nr property.

property Nt

Get method for the Nt property.

_calc_JP_Bkl_cov_matrix_first_part(F_all_users: numpy.ndarray, k: int, Rek: NumberOrArray)numpy.ndarray[source]

Calculates the first part in the equation of the Blk covariance matrix in equation (28) of [Cadambe2008] when joint process is employed.

The first part is given by

\(\sum_{j=1}^{K} \frac{P^{[j]}}{d^{[j]}} \sum_{d=1}^{d^{[j]}} \mtH^{[kj]}\mtV_{\star d}^{[j]} \mtV_{\star d}^{[j]\dagger} \mtH^{[kj]\dagger} + \mtI_{Nk}\)

Note that it only depends on the value of \(k\).

Parameters
  • F_all_users (list[np.ndarray] | np.ndarray) – The precoder of all users (already taking into account the transmit power). This can be either a 1D numpy array of numpy arrays or a list of numpy arrays.

  • k (int) – Index of the desired user.

  • Rek (np.ndarray | float) – Covariance matrix of the external interference plus noise.

Returns

The first part in the equation of the Blk covariance matrix.

Return type

np.ndarray

_calc_JP_Bkl_cov_matrix_second_part(Fk: numpy.ndarray, k: int, l: int)numpy.ndarray[source]

Calculates the second part in the equation of the Blk covariance matrix in equation (28) of [Cadambe2008] (note that it does not include the identity matrix).

The second part is given by

\(\frac{P^{[k]}}{d^{[k]}} \mtH^{[kk]} \mtV_{\star l}^{[k]} \mtV_{\star l}^{[k]\dagger} \mtH^{[kk]\dagger}\)

Parameters
  • Fk (np.ndarray) – The precoder of the desired user.

  • k (int) – Index of the desired user.

  • l (int) – Index of the desired stream.

Returns

second_part – Second part in equation (28) of [Cadambe2008].

Return type

np.ndarray

_calc_JP_Q(k: int, F_all_users: numpy.ndarray)numpy.ndarray[source]

Calculates the interference covariance matrix at the \(k\)-th receiver with a joint processing scheme (not including the covariance matrix of the external interference plus noise)

Parameters
  • k (int) – Index of the desired receiver.

  • F_all_users (np.ndarray) – The precoder of all users (already taking into account the transmit power). This is a 1D numpy array of 2D numpy array.

See also

calc_JP_Q()

_calc_JP_SINR_k(k: int, Fk: numpy.ndarray, Uk: numpy.ndarray, Bkl_all_l: numpy.ndarray)numpy.ndarray[source]

Calculates the SINR of all streams of user ‘k’.

Parameters
  • Fk (np.ndarray) – The precoder of user k.

  • Uk (np.ndarray) – The receive filter of user k (before applying the conjugate transpose).

  • k (int) – Index of the desired user.

  • Bkl_all_l (list[np.ndarray] | np.ndarray) – A sequence (1D numpy array, a list, etc) of 2D numpy arrays corresponding to the Bkl matrices for all ‘l’s.

Returns

The SINR for the different streams of user k.

Return type

np.ndarray

static _prepare_input_parans(Nr: numpy.ndarray, Nt: numpy.ndarray, K: int, NtE: Iterable[int]) → Tuple[numpy.ndarray, numpy.ndarray, int, int, numpy.ndarray][source]

Helper method used in the init_from_channel_matrix and randomize method definitions.

Parameters
  • Nr (np.ndarray) – Number of antennas at each receiver.

  • Nt (np.ndarray) – Number of antennas at each transmitter.

  • K (int) – Number of transmit/receive pairs.

  • NtE (int | list[int] | np.ndarray) – Number of transmit antennas of the external interference source(s). If NtE is an iterable, the number of external interference sources will be the len(NtE).

Returns

output – The tuple (full_Nr, full_Nt, full_K, extIntK, extIntNt).

Return type

tuple

property big_H_no_ext_int

Get method for the big_H_no_est_int property.

big_H_no_est_int is similar to big_H, but does not include the last column(s) corresponding to the external interference channel.

calc_JP_Q(k: int, F_all_users: numpy.ndarray, pe: float = 1.0)numpy.ndarray[source]

Calculates the interference covariance matrix at the \(k\)-th receiver with a joint processing scheme.

The interference covariance matrix at the \(k\)-th receiver, \(\mtQ k\), is given by

\(\mtQ k = \sum_{j=1, j \neq k}^{K} \frac{P_j}{Ns_j} \mtH_{k} \mtF_j \mtF_j^H \mtH_{k}^H\)

where \(P_j\) is the transmit power of transmitter \(j\), and \(Ns_j\) is the number of streams for user \(j\).

Parameters
  • k (int) – Index of the desired receiver.

  • F_all_users (list[np.ndarray] | np.ndarray) – The precoder of all users (already taking into account the transmit power). This is a 1D numpy array of 2D numpy array.

  • pe (float) – The power of the external interference source(s).

Returns

Qk – The interference covariance matrix at receiver \(k\).

Return type

np.ndarray

calc_JP_SINR(F: numpy.ndarray, U: numpy.ndarray, pe: float = 1.0)numpy.ndarray[source]

Calculates the SINR values (in linear scale) of all streams of all users with the current IA solution.

The noise variance used will be the value of the noise_var property.

Parameters
  • F (np.ndarray) – The precoders of all users. This is a 1D numpy array of 2D numpy arrays.

  • U (np.ndarray) – The receive filters of all users. This is a 1D numpy array of 2D numpy arrays.

  • pe (float) – The external interference power.

Returns

The SINR (in linear scale) of all streams of all users. This is a 1D numpy array of 1D numpy arrays (of floats).

Return type

np.ndarray

calc_Q(k: int, F_all_users: numpy.ndarray, pe: float = 1.0)numpy.ndarray[source]

Calculates the interference covariance matrix at the \(k\)-th receiver.

The interference covariance matrix at the \(k\)-th receiver, \(\mtQ k\), is given by

\(\mtQ k = \sum_{j=1, j \neq k}^{K} \frac{P_j}{Ns_j} \mtH_{kj} \mtF_j \mtF_j^H \mtH_{kj}^H\)

where \(P_j\) is the transmit power of transmitter \(j\), and \(Ns_j\) is the number of streams for user \(j\).

Parameters
  • k (int) – Index of the desired receiver.

  • F_all_users (list[np.ndarray] | np.ndarray) – The precoder of all users (already taking into account the transmit power). This should be either a list of numpy 2D arrays or a 1D numpy array of 2D numpy arrays.

  • pe (float) – The power of the external interference source(s).

Returns

Qk – The interference covariance matrix at receiver \(k\).

Return type

np.ndarray

calc_SINR(F: numpy.ndarray, U: numpy.ndarray, pe: float = 1.0)numpy.ndarray[source]

Calculates the SINR values (in linear scale) of all streams of all users with the current IA solution.

The noise variance used will be the value of the noise_var property.

Parameters
  • F (list[np.ndarray] | np.ndarray) – The precoders of all users. This should be either a list of numpy 2D arrays or a 1D numpy array of 2D numpy arrays.

  • U (list[np.ndarray] | np.ndarray) – The receive filters of all users. This should be either a list of numpy 2D arrays or a 1D numpy array of 2D numpy arrays.

  • pe (float) – Power of the external interference source.

Returns

SINRs – The SINR (in linear scale) of all streams of all users. This is a 1D numpy array of 1D numpy arrays (of floats)

Return type

np.ndarray

calc_cov_matrix_extint_plus_noise(pe: float = 1.0)numpy.ndarray[source]

Calculates the covariance matrix of the external interference plus noise.

Parameters

pe (float, optional [default=1]) – External interference power (in linear scale)

Returns

R_all_k – Return a numpy array, where each element is the covariance matrix of the external interference plus noise at one receiver.

Return type

np.ndarray

calc_cov_matrix_extint_without_noise(pe: float = 1.0)numpy.ndarray[source]

Calculates the covariance matrix of the external interference without include the noise.

Parameters

pe (float, optional) – External interference power (in linear scale)

Returns

R_all_k – Return a numpy array, where each element is the covariance matrix of the external interference at one receiver.

Return type

np.ndarray

corrupt_concatenated_data(data: numpy.ndarray)numpy.ndarray[source]

Corrupt data passed through the channel.

If the noise_var member variable is not None then an white noise will also be added.

Parameters

data (np.ndarray) – A bi-dimensional numpy array with the concatenated data of all transmitters as well as the data from all external interference sources. The dimension of data is (sum(self._Nt) + sum(self.extIntNt)) x NSymb. That is, the number of rows corresponds to the sum of the number of transmit antennas of all users and external interference sources and the number of columns correspond to the number of transmitted symbols.

Returns

output – A bi-dimension numpy array where the number of rows corresponds to the sum of the number of receive antennas of all users and the number of columns correspond to the number of transmitted symbols.

Return type

np.ndarray

corrupt_data(data: numpy.ndarray, ext_int_data: numpy.ndarray)numpy.ndarray[source]

Corrupt data passed through the channel.

If the noise_var member variable is not None then an white noise will also be added.

Parameters
  • data (np.ndarray) – An array of numpy matrices with the data of the multiple users. The k-th element in data is a numpy array with dimension Nt_k x NSymbs, where Nt_k is the number of transmit antennas of the k-th user and NSymbs is the number of transmitted symbols.

  • ext_int_data (list[np.ndarray] | np.ndarray) – An array of numpy matrices with the data of the external interference sources. The l-th element is the data transmitted by the l-th external interference source, which must have a dimension of NtEl x NSymbs, where NtEl is the number of transmit antennas of the l-th external interference source.

Returns

output – A numpy array where each element contains the received data (a 2D numpy array) of a user.

Return type

np.ndarray

property extIntK

Get method for the extIntK property.

property extIntNt

Get method for the extIntNt property.

get_Hk_with_ext_int(k: int)numpy.ndarray[source]

Get the channel from all transmitters (including the external interference sources) to receiver k.

This method is essentially the same as the get_Hk method.

Parameters

k (int) – Receiving user.

Returns

channel_k – Channel from all transmitters to receiver k.

Return type

np.ndarray

Examples

>>> multiH = MultiUserChannelMatrixExtInt()
>>> H = np.reshape(np.r_[0:20], [4,5])
>>> Nt = np.array([2, 2])
>>> Nr = np.array([2, 2])
>>> NextInt = np.array([1])
>>> multiH.init_from_channel_matrix(H, Nr, Nt, 2, 1)
>>> # Note that the last column of multiH.big_H corresponds to the
>>> # external interference source
>>> print(multiH.big_H)
[[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]
 [15 16 17 18 19]]
>>> print(multiH.get_Hk_with_ext_int(0))
[[0 1 2 3 4]
 [5 6 7 8 9]]
>>> print(multiH.get_Hk_with_ext_int(1))
[[10 11 12 13 14]
 [15 16 17 18 19]]
get_Hk_without_ext_int(k: int)numpy.ndarray[source]

Get the channel from all transmitters (without including the external interference sources) to receiver k.

Parameters

k (int) – Receiving user.

Returns

channel_k – Channel from all transmitters to receiver k (2D numpy array).

Return type

np.ndarray

Examples

>>> multiH = MultiUserChannelMatrixExtInt()
>>> H = np.reshape(np.r_[0:20], [4,5])
>>> Nt = np.array([2, 2])
>>> Nr = np.array([2, 2])
>>> NextInt = np.array([1])
>>> multiH.init_from_channel_matrix(H, Nr, Nt, 2, 1)
>>> # Note that the last column of multiH.big_H corresponds to the
>>> # external interference source
>>> print(multiH.big_H)
[[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]
 [15 16 17 18 19]]
>>> print(multiH.get_Hk_without_ext_int(0))
[[0 1 2 3]
 [5 6 7 8]]
>>> print(multiH.get_Hk_without_ext_int(1))
[[10 11 12 13]
 [15 16 17 18]]
init_from_channel_matrix(channel_matrix: numpy.ndarray, Nr: numpy.ndarray, Nt: numpy.ndarray, K: int, NtE: Iterable[int])None[source]

Initializes the multiuser channel matrix from the given channel_matrix.

Note that channel_matrix must also include the channel terms for the external interference, which must be the last NtE columns of channel_matrix. The number of rows in channel_matrix must be equal to np.sum(Nr), while the number of columns must be np.sum(Nt) + NtE.

Parameters
  • channel_matrix (np.ndarray) – A matrix concatenating the channel of all transmitters (including the external interference sources) to all receivers.

  • Nr (np.ndarray) – Number of antennas at each receiver.

  • Nt (np.ndarray) – Number of antennas at each transmitter.

  • K (int) – Number of transmit/receive pairs.

  • NtE (int | list[int] | np.ndarray) – Number of transmit antennas of the external interference source(s). If NtE is an iterable, the number of external interference sources will be the len(NtE).

Raises

ValueError – If the arguments are invalid.

randomize(Nr: Union[numpy.ndarray, int], Nt: Union[numpy.ndarray, int], K: int, NtE: Iterable[int])None[source]

Generates a random channel matrix for all users as well as for the external interference source(s).

Parameters
  • Nr (int | np.ndarray) – Number of receive antennas of each user. If an integer is specified, all users will have that number of receive antennas.

  • Nt (int | np.ndarray) – Number of transmit antennas of each user. If an integer is specified, all users will have that number of receive antennas.

  • K (int) – Number of users.

  • NtE (int | list[int] | np.ndarray) – Number of transmit antennas of the external interference source(s). If NtE is an iterable, the number of external interference sources will be the len(NtE).

set_pathloss(pathloss_matrix: Optional[numpy.ndarray] = None, ext_int_pathloss: Optional[numpy.ndarray] = None)None[source]

Set the path loss (IN LINEAR SCALE) from each transmitter to each receiver, as well as the path loss from the external interference source(s) to each receiver.

The path loss will be accounted when calling the get_Hkl, get_Hk, the corrupt_concatenated_data and the corrupt_data methods.

Note that path loss is a power relation, which means that the channel coefficients will be multiplied by the square root of elements in pathloss_matrix.

If you want to disable the path loss, set pathloss_matrix to None.

Parameters
  • pathloss_matrix (np.ndarray) – A matrix with dimension “K x K”, where K is the number of users, with the path loss (IN LINEAR SCALE) from each transmitter (columns) to each receiver (rows). If you want to disable the path loss then set it to None. ext_int_pathloss : 2D numpy array The path loss from each interference source to each receiver. The number of rows of ext_int_pathloss must be equal to the number of receives, while the number of columns must be equal to the number of external interference sources.

  • ext_int_pathloss (np.ndarray) – The external interference path loss.

pyphysim.channels.noise module

pyphysim.channels.noise.calc_thermal_noise_power_dBm(T: float, delta_f: float)float[source]

Calculate the thermal noise power (in dBm) for the given room temperature T (in Cº) and bandwidth delta_f (in Hz).

Parameters
  • T (float) – Room temperature in Cesium degrees.

  • delta_f (float) – Bandwidth in Hz.

Returns

noise_var – The noise power.

Return type

float

pyphysim.channels.pathloss module

Implement classes for several Path loss models.

The PathLossBase class implements the common code to every path loss model and only two methods need to be implemented in subclasses: the PathLossBase.which_distance_dB() and the PathLossBase._calc_deterministic_path_loss_dB() methods. However, instead of inheriting directly from PathLossBase, inherit from either PathLossIndoorBase or PathLossOutdoorBase.

The most common usage of a path loss class is to instantiate an object of the desired path loss model and then call the calc_path_loss_dB or the calc_path_loss methods to actually calculate the path loss.

class pyphysim.channels.pathloss.PathLoss3GPP1[source]

Bases: pyphysim.channels.pathloss.PathLossGeneral

Class to calculate the Path Loss according to the model from 3GPP (scenario 1). That is, the Path Loss (in dB) is equal to

\[PL = 128.1 + 37.6*\log10(d)\]

This model is valid for LTE assumptions and at 2GHz frequency, where the distance is in Km.

Examples

Determining the path loss in the free space for a distance of 1Km (without considering shadowing).

>>> pl = PathLoss3GPP1()
>>> pl.calc_path_loss(1)        # linear scale
1.5488166189124858e-13
>>> pl.calc_path_loss_dB(1)     # log scale
128.1

Determining the distance (in Km) that yields a path loss of 130dB.

>>> pl.which_distance_dB(130)
1.1233935211892188
_repr_latex_()str[source]

Get a Latex representation of the PathLossFreeSpace class.

This is useful for representing the path loss object in an IPython notebook.

Returns

The Latex representation of the path loss object.

Return type

str

class pyphysim.channels.pathloss.PathLossBase[source]

Bases: object

Base class for the different Path Loss models.

The common interface for the path loss classes is provided by the calc_path_loss_dB() or the calc_path_loss() methods to actually calculate the path loss for a given distance, as well as the which_distance_dB() or which_distance() methods to determine the distance that yields the given path loss.

Each subclass of PathLossBase NEED TO IMPLEMENT only the which_distance_dB() and the _calc_deterministic_path_loss_dB() functions.

If the use_shadow_bool attribute is set to True then calling calc_path_loss_dB() or calc_path_loss() will take the shadowing specified in the sigma_shadow attribute into account. However, shadowing is not taken into account in the which_distance_dB() and which_distance() functions, regardless of the value of the use_shadow_bool variable.

sigma_shadow

The shadowing (in dB)

Type

int

use_shadow_bool

If True then shadowing will be used.

Type

bool

handle_small_distances_bool

If this is True then any negative path loss (in dB) that appears because a distance is too small will considered as 0dB. If this s False then an exception will be raised instead.

Type

bool

_TYPE = 'base'
abstract _calc_deterministic_path_loss_dB(d: NumberOrArray, **kargs: Any) → NumberOrArray[source]

Calculates the Path Loss (in dB) for a given distance (in Km) without including the shadowing.

Parameters
  • d (float | np.ndarray) – Distance (in Km)

  • kargs (dict, optional) – Optional parameters for use in subclasses if required.

Other Parameters

kwargs (dict) – Additional keywords that might be necessary in a subclass.

Returns

PL – Path loss (in dB).

Return type

float | np.ndarray

Raises

NotImplementedError – If the _calc_deterministic_path_loss_dB method of the PathLossBase class is called.

_plot_deterministic_path_loss_in_dB_impl(d: numpy.ndarray, ax: Optional[Any] = None, extra_args: Optional[Any] = None, distance_unit: str = 'Km')None[source]

Plot the path loss (in dB) for the distance values in d (in Km).

Parameters
  • d (np.ndarray) – Distance (in correct unit)

  • ax (A matplotlib ax, optional) – The ax where the path loss will be plotted. If not provided, a new figure (and ax) will be created.

  • extra_args (dict) – Extra arguments that will be passed to the ax.plot command as **extra_args (see Matplotlib documentation). Ex: {‘label’: ‘curve name’, ‘linewidth’: 2}

calc_path_loss(d: NumberOrArray, **kargs: Any) → NumberOrArray[source]

Calculates the path loss (linear scale) for a given distance (in Km).

Parameters
  • d (float | np.ndarray) – Distance (in Km)

  • kargs (dict) – Extra named parameters. This is used in subclasses for extra parameters for the path loss calculation.

Other Parameters

kwargs (dict) – Additional keywords that might be necessary in a subclass.

Returns

pl – Path loss (in linear scale) for the given distance(s).

Return type

float | np.ndarray

calc_path_loss_dB(d: NumberOrArray, **kargs: Any) → NumberOrArray[source]

Calculates the Path Loss (in dB) for a given distance (in Km).

Note that the returned value is positive, but should be understood as “a loss”.

Parameters
  • d (float | np.ndarray) – Distance (in Km)

  • kargs (dict) – Optional parameters for use in subclasses if required.

Other Parameters

kwargs (dict) – Additional keywords that might be necessary in a subclass.

Returns

PL – Path loss (in dB) for the given distance(s).

Return type

float | np.ndarray

plot_deterministic_path_loss_in_dB(d: numpy.ndarray, ax: Optional[Any] = None, extra_args: Optional[Any] = None)None[source]

Plot the path loss (in dB) for the distance values in d (in Km).

Parameters
  • d (np.ndarray) – Distance (in Km)

  • ax (A matplotlib ax, optional) – The ax where the path loss will be plotted. If not provided, a new figure (and ax) will be created.

  • extra_args (dict) – Extra arguments that will be passed to the ax.plot command as **extra_args (see Matplotlib documentation). Ex: {‘label’: ‘curve name’, ‘linewidth’: 2}

property type

Get method for the type property.

which_distance(pl: NumberOrArray) → NumberOrArray[source]

Calculates the required distance (in Km) to achieve the given path loss. It is the inverse of the calc_path_loss function.

Parameters

pl (float | np.ndarray) – Path loss (in linear scale).

Returns

d – Distance(s) that will yield the path loss pl.

Return type

float | np.ndarray

abstract which_distance_dB(PL: NumberOrArray) → NumberOrArray[source]

Calculates the distance that yields the given path loss (in dB).

Parameters

PL (float | np.ndarray) – Path Loss (in dB)

Returns

d – Distance to get the desired path loss PL.

Return type

float | np.ndarray

Raises

NotImplementedError – If the which_distance_dB method of the PathLossBase class is called.

class pyphysim.channels.pathloss.PathLossFreeSpace(n: float = 2.0, fc: float = 900.0)[source]

Bases: pyphysim.channels.pathloss.PathLossGeneral

Class to calculate the Path Loss in the free space.

The common interface for the path loss classes is provided by the PathLossOutdoorBase.calc_path_loss_dB() or the PathLossOutdoorBase.calc_path_loss() methods to actually calculate the path loss for a given distance, as well as the PathLossGeneral.which_distance_dB() or PathLossBase.which_distance() methods to determine the distance that yields the given path loss.

For the path loss in free space you also need to set the n variable, corresponding to the path loss coefficient, and the fc variable, corresponding to the frequency. The n variable defaults to 2 and fc defaults to 900 (that is, 900MHz).

The path loss (in dB) in free space is calculated as:

\[PL = 10 n ( \log_{10}(d)+\log_{10}(fc * 1e6) - 4.3779113907)\]

Likewise, the PathLossGeneral.which_distance_dB() function calculates the value of

\[10^{(PL/(10n) - \log_{10}(fc) + 4.377911390697565)}\]
Parameters
  • n (float) – Path loss exponent.

  • fc (float) – Central carrier frequency (in MHz).

Examples

Determining the path loss in the free space for a distance of 1Km (without considering shadowing).

>>> pl = PathLossFreeSpace()
>>> pl.calc_path_loss(1)        # linear scale
7.036193308495632e-10
>>> pl.calc_path_loss_dB(1)     # log scale
91.5266223748352

Determining the distance (in Km) that yields a path loss of 90dB.

>>> pl.which_distance_dB(90)
0.8388202017414481
static _calculate_C_from_fc_and_n(fc: float, n: float)float[source]

Calculate the value of the constant C for the frequency value fc and path loss exponent n.

Parameters
  • fc (float) – Central carrier frequency (in MHz)

  • n (float) – Path loss exponent

Returns

C – Constant C for the Free Space path loss model for the given frequency and path loss exponent.

Return type

float

_repr_latex_()str[source]

Get a Latex representation of the PathLossFreeSpace class.

This is useful for representing the path loss object in an IPython notebook.

Returns

The Latex representation of the path loss object.

Return type

str

property fc

Get the central carrier frequency.

Returns

The central carrier frequency.

Return type

float

property n

Get method for the n property.

Returns

The path loss exponent.

Return type

float

class pyphysim.channels.pathloss.PathLossGeneral(n: float, C: float)[source]

Bases: pyphysim.channels.pathloss.PathLossOutdoorBase

Class to calculate the path loss given the path loss for a reference distance.

In its simplest form, the path loss can be calculated using the formula

\(PL = 10 n \log_{10} (d) + C\)

where PL is in dB, n is the path loss exponent (usually in the range of 2 to 4) and d is the distance between the transmitter and the receiver.

Parameters
  • n (float) – The path loss exponent.

  • C (float) – The constant C in the path loss formula.

_calc_deterministic_path_loss_dB(d: NumberOrArray, **kargs: Any) → NumberOrArray[source]

Calculates the Path Loss (in dB) for a given distance (in Km).

Note that the returned value is positive, but should be understood as “a loss”.

For d in Km and self.fc in MHz, the free space Path Loss is given by

\[PL = 10 n \log_{10}(d) + C\]
Parameters

d (float | np.ndarray) – Distance (in Km).

Returns

pl_dB – Path loss in dB.

Return type

float | np.ndarray

_get_latex_repr()str[source]

Get the Latex representation (equation) for the PathLossGeneral class.

The general equation is given by

\[PL = 10 n \log_{10} (d) + C\]
Returns

The Latex representation of the path loss object.

Return type

str

_repr_latex_()str[source]

Get a Latex representation of the PathLossGeneral class.

This is useful for representing the path loss object in an IPython notebook.

Returns

The Latex representation of the path loss object.

Return type

str

which_distance_dB(PL: NumberOrArray) → NumberOrArray[source]

Calculates the required distance (in Km) to achieve the given path loss (in dB).

It is the inverse of the calc_path_loss function.

\[10^{(PL/(10n) - C)}\]

d = obj.whichDistance(dB2Linear(-PL));

Parameters

PL (float | np.ndarray) – Path Loss (in dB).

Returns

d – Distance (in Km).

Return type

float | np.ndarray

class pyphysim.channels.pathloss.PathLossIndoorBase[source]

Bases: pyphysim.channels.pathloss.PathLossBase

Base class for the different Indoor Path Loss models.

The common interface for the path loss classes is provided by the calc_path_loss_dB() or the calc_path_loss() methods to actually calculate the path loss for a given distance, as well as the which_distance_dB() or which_distance methods to determine the distance that yields the given path loss.

Each subclass of PathLossBase NEED TO IMPLEMENT only the which_distance_dB() and the _calc_deterministic_path_loss_dB() functions.

If the use_shadow_bool is set to True then calling calc_path_loss_dB() or calc_path_loss() will take the shadowing specified in the sigma_shadow variable into account. However, shadowing is not taken into account in the which_distance_dB() and which_distance() functions, regardless of the value of the use_shadow_bool variable.

_TYPE = 'indoor'
abstract _calc_deterministic_path_loss_dB(d: NumberOrArray, **kargs: Any) → NumberOrArray[source]

Calculates the Path Loss (in dB) for a given distance (in meters) without including the shadowing.

Parameters

d (float | np.ndarray) – Distance (in meters)

Other Parameters

kwargs (dict) – Additional keywords that might be necessary in a subclass.

Returns

PL – The calculated path loss.

Return type

float | np.ndarray

Raises

NotImplementedError – If the _calc_deterministic_path_loss_dB method of the PathLossBase class is called.

calc_path_loss(d: NumberOrArray, **kargs: Any) → NumberOrArray[source]

Calculates the path loss (linear scale) for a given distance (in meters).

Parameters
  • d (float | np.ndarray) – Distance (in meters)

  • kargs (dict) – Additional keywords that might be necessary in a subclass.

Returns

pl – Path loss (in linear scale) for the given distance(s).

Return type

float | np.ndarray

calc_path_loss_dB(d: NumberOrArray, **kargs: Any) → NumberOrArray[source]

Calculates the Path Loss (in dB) for a given distance (in meters).

Note that the returned value is positive, but should be understood as “a loss”.

Parameters
  • d (float | np.ndarray) – Distance (in meters)

  • kargs (dict) – Additional keywords that might be necessary in a subclass.

Returns

PL – Path loss (in dB) for the given distance(s).

Return type

float | np.ndarray

plot_deterministic_path_loss_in_dB(d: NumberOrArray, ax: Optional[Any] = None, extra_args: Optional[Any] = None)None[source]

Plot the path loss (in dB) for the distance values in d (in meters).

Parameters
  • d (np.ndarray) – Distance (in meters)

  • ax (A matplotlib ax, optional) – The ax where the path loss will be plotted. If not provided, a new figure (and ax) will be created.

  • extra_args (dict) – Extra arguments that will be passed to the ax.plot command as **extra_args (see Matplotlib documentation). Ex: {‘label’: ‘curve name’, ‘linewidth’: 2}

which_distance(pl: NumberOrArray) → NumberOrArray[source]

Calculates the required distance (in meters) to achieve the given path loss. It is the inverse of the calc_path_loss function.

Parameters

pl (float | np.ndarray) – Path loss (in linear scale).

Returns

d – Distance(s) that will yield the path loss pl.

Return type

float | np.ndarray

abstract which_distance_dB(PL: NumberOrArray) → NumberOrArray[source]

Calculates the distance that yields the given path loss (in dB).

Parameters

PL (float | np.ndarray) – Path Loss (in dB)

Returns

d – The distance to yield the given path loss.

Return type

float | np.ndarray

Raises

NotImplementedError – If the which_distance_dB method of the PathLossBase class is called.

class pyphysim.channels.pathloss.PathLossMetisPS7(fc: float = 900.0)[source]

Bases: pyphysim.channels.pathloss.PathLossIndoorBase

Class to calculate the Path Loss (indoor) according to the model described for the Propagation Scenario (PS) 7 of the METIS project.

This model is an indoor-2-indoor model.

_calc_PS7_path_loss_dB_LOS_same_floor(d: NumberOrArray) → NumberOrArray[source]

Calculate the deterministic path loss according to the Propagation Scenario (PS) 7 of the METIS project for the LOS case.

The path loss (in dB) is calculated as

\[PL = A \log_{10}(d) + B + C \log_{10}(f_c/5)\]

The distance \(d\) is in meters, while the frequency \(f_c\) is in GHz.

The other variables (NLOS case) are:

\[A = 18.7 B = 46.8, C = 20\]

where \(n_w\) is the number of walls between the transmitter and receiver.

Parameters

d (float | np.ndarray) – Distance (in meters).

Returns

pl_dB – Path loss in dB.

Return type

float | np.ndarray

_calc_PS7_path_loss_dB_NLOS_same_floor(d: NumberOrArray, num_walls: int = 1) → NumberOrArray[source]

Calculate the deterministic path loss according to the Propagation Scenario (PS) 7 of the METIS project for the NLOS case.

The path loss (in dB) is calculated as

\[PL = A \log_{10}(d) + B + C \log_{10}(f_c/5) + X\]

The distance \(d\) is in meters, while the frequency \(f_c\) is in Hz.

The other variables (NLOS case) are:

\[A = 36.8 B = 43.8, C = 20, X = 5 ( n_w - 1 )\]

where \(n_w\) is the number of walls between the transmitter and receiver.

Parameters
  • d (float | np.ndarray) – Distance (in meters).

  • num_walls (int | np.ndarray) – Number of walls between the transmitter and the receiver. If it is an int array it must have the same dimension as d.

Returns

pl_dB – Path loss in dB.

Return type

float | np.ndarray

_calc_PS7_path_loss_dB_same_floor(d: NumberOrArray, num_walls: int = 0) → NumberOrArray[source]

Calculate the deterministic path loss according to the Propagation Scenario (PS) 7 of the METIS project.

The path loss (in dB) is calculated as

\[PL = A \log_{10}(d) + B + C \log_{10}(f_c/5) + X\]

The distance \(d\) is in meters, while the frequency \(f_c\) is in GHz. Na others variables a different for the LOS and NLOS cases.

For the LOS case we have:

\[A = 18.7 B = 46.8, C = 20, X = 0\]

For the NLOS case we have:

\[A = 36.8 B = 43.8, C = 20, X = 5 ( n_w - 1 )\]

where \(n_w\) is the number of walls between the transmitter and receiver.

Parameters
  • d (float | np.ndarray) – Distance (in meters).

  • num_walls (int | np.ndarray) – Indicates how many walls the signal has to pass. If num_walls is zero, then Line-of-Sight parameters are used. If it is greater than zero then Non-Sign-of-Sight parameters are used. If num_walls is a numpy array then it must have the same dimension as d and it then specifies the number of walls for each individual value of d

Returns

pl_dB – Path loss in dB.

Return type

float | np.ndarray

_calc_deterministic_path_loss_dB(d: NumberOrArray, num_walls: int = 0) → NumberOrArray[source]

Calculates the Path Loss (in dB) for a given distance (in meters) without including the shadowing.

Parameters
  • d (float | np.ndarray) – Distance (in meters)

  • num_walls (int | np.ndarray) – Number of walls between the transmitter and the receiver. If it is an int array it must have the same dimension as d.

Returns

PL – The calculated path loss.

Return type

float | np.ndarray

_repr_latex_()str[source]

Get a Latex representation of the PathLossMetisPS7 class.

This is useful for representing the path loss object in an IPython notebook.

Returns

The Latex representation of the path loss object.

Return type

str

property fc

Get the central carrier frequency.

Returns

The central carrier frequency.

Return type

float

static get_latex_repr(num_walls: Optional[int] = None)str[source]

Get the Latex representation (equation) for the PathLossGeneral class.

The general equation is given by

\[PL = A \log_{10}(d) + B + C \log_{10}(f_c/5) + X\]

where the parameters A, B, C and X depend on the number of walls.

Parameters

num_walls (int, None) – Number of walls. LOS is used if it is 0 and NLOS is used if it is greater than zero. If it is None, then letters are used instead of numeric values.

Returns

The Latex representation (equation) for the PathLossGeneral class.

Return type

str

which_distance_dB(PL: NumberOrArray) → NumberOrArray[source]

Calculates the distance that yields the given path loss (in dB).

Parameters

PL (float | np.ndarray) – Path Loss (in dB)

Returns

d – The distance to yield the given path loss.

Return type

float | np.ndarray

Raises

NotImplementedError – If the which_distance_dB method of the PathLossBase class is called.

class pyphysim.channels.pathloss.PathLossOkomuraHata[source]

Bases: pyphysim.channels.pathloss.PathLossOutdoorBase

Class to calculate the Path Loss according to the Okomura Hata model.

The exact formula depend on the area type, but in general the path loss is given by (in dB):

\[PL = 69.55 + 26.16 * \log(fc) - 13.82*\log(h_{bs}) - a(h_{ms}) + (44.9 - 6.55\log(h_{bs})) \log(d) - K\]

The term \(a(h_{ms})\) is the mobile station correction factor (see _calc_mobile_antenna_height_correction_factor()).

The term \(K\) is a correction factor that depends on the area type (see _calc_K()).

The possible area types are (in ascending order): ‘open’, ‘suburban’, ‘medium city’ and ‘large city’.

_calc_K()float[source]

Calculates the “‘medium city’/’suburban’/’open area’” correction factor.

Returns

K – The correction factor “K”.

Return type

float

_calc_deterministic_path_loss_dB(d: NumberOrArray, **kargs: Any) → NumberOrArray[source]

Calculates the Path Loss (in dB) for a given distance (in Km).

Note that the returned value is positive, but should be understood as “a loss”.

For d in Km and self.fc in Hz, the free space Path Loss is given by

\[PL = 10n ( \log_{10}(d) + \log_{10}(f) - 4.3779113907 )\]
Parameters

d (float | np.ndarray) – Distance (in Km). Can be between 1km and 20Km.

Returns

PL – Path loss in dB.

Return type

float | np.ndarray

_calc_mobile_antenna_height_correction_factor()float[source]

Calculates the mobile antenna height correction factor.

This factor is strongly impacted by surrounding buildings and is refined according to city sizes. For all area types, except ‘large city’, the mobile antenna correction factor is given by

\[a(h_{ms}) = (1.1 \log(f) - 0.7) h_{ms} - 1.56 \log(f) + 0.8\]

For the ‘large city’ area type, the mobile antenna height correction is given by

\[a(h_{ms}) = 3.2 (\log(11.75*h_{ms})^2) - 4.97\]

if the frequency is greater then 300MHz, or

\[a(h_{ms}) = 8.29 (\log(1.54 h_{ms}))^2 - 1.10\]

if the frequency is lower than 300MHz (and greater than 150MHz where the Okomura Hata model is valid).

Returns

The mobile antenna height correction.

Return type

float

property area_type

Get method for the area_type property.

property fc

Get the central carrier frequency.

Returns

The central carrier frequency.

Return type

float

property hbs

Get the height of the Base Station property.

Returns

Height of the Base Station (in meters).

Return type

float

property hms

Get the height of the Mobile Station property.

Returns

Height of the Mobile Station (in meters).

Return type

float

which_distance_dB(PL: NumberOrArray) → NumberOrArray[source]

Calculates the required distance (in Km) to achieve the given path loss (in dB).

It is the inverse of the calc_path_loss function.

Parameters

PL (float | np.ndarray) – Path loss (in dB).

Returns

d – Distance (in Km).

Return type

float | np.ndarray

class pyphysim.channels.pathloss.PathLossOutdoorBase[source]

Bases: pyphysim.channels.pathloss.PathLossBase

Base class for the different Outdoor Path Loss models.

The common interface for the path loss classes is provided by the calc_path_loss_dB() or the calc_path_loss() methods to actually calculate the path loss for a given distance, as well as the which_distance_dB() or PathLossBase.which_distance() methods to determine the distance that yields the given path loss.

Each subclass of PathLossBase NEED TO IMPLEMENT only the which_distance_dB() and the _calc_deterministic_path_loss_dB() functions.

If the use_shadow_bool is set to True then calling calc_path_loss_dB() or calc_path_loss() will take the shadowing specified in the sigma_shadow variable into account. However, shadowing is not taken into account in the which_distance_dB() and PathLossBase.which_distance() functions, regardless of the value of the use_shadow_bool variable.

_TYPE = 'outdoor'
abstract _calc_deterministic_path_loss_dB(d: NumberOrArray, **kargs: Any) → NumberOrArray[source]

Calculates the Path Loss (in dB) for a given distance (in Km) without including the shadowing.

Parameters

d (float | np.ndarray) – Distance (in Km)

Other Parameters

kwargs (dict) – Additional keywords that might be necessary in a subclass.

Returns

PL – The calculated path loss (in dB).

Return type

float | np.ndarray

Raises

NotImplementedError – If the _calc_deterministic_path_loss_dB method of the PathLossBase class is called.

calc_path_loss(d: NumberOrArray, **kargs: Any) → NumberOrArray[source]

Calculates the path loss (linear scale) for a given distance (in Km).

Parameters
  • d (float | np.ndarray | list[float]) – Distance (in Km)

  • kargs (dict) – Additional keywords that might be necessary in a subclass.

Returns

pl – Path loss (in linear scale) for the given distance(s).

Return type

float | np.ndarray

calc_path_loss_dB(d: NumberOrArray, **kargs: Any) → NumberOrArray[source]

Calculates the Path Loss (in dB) for a given distance (in Km).

Note that the returned value is positive, but should be understood as “a loss”.

Parameters
  • d (float | np.ndarray | list[float]) – Distance (in Km)

  • kargs (dict) – Additional keywords that might be necessary in a subclass.

Returns

PL – Path loss (in dB) for the given distance(s).

Return type

float | np.ndarray

plot_deterministic_path_loss_in_dB(d: NumberOrArray, ax: Optional[Any] = None, extra_args: Optional[Any] = None)None[source]

Plot the path loss (in dB) for the distance values in d (in Km).

Parameters
  • d (np.ndarray) – Distance (in Km)

  • ax (A matplotlib ax, optional) – The ax where the path loss will be plotted. If not provided, a new figure (and ax) will be created.

  • extra_args (dict) – Extra arguments that will be passed to the ax.plot command as **extra_args (see Matplotlib documentation). Ex: {‘label’: ‘curve name’, ‘linewidth’: 2}

abstract which_distance_dB(PL: NumberOrArray) → NumberOrArray[source]

Calculates the distance that yields the given path loss (in dB).

Parameters

PL (float | np.ndarray) – Path Loss (in dB)

Returns

d – The distance that yields the given path loss.

Return type

float | np.ndarray

Raises

NotImplementedError – If the which_distance_dB method of the PathLossBase class is called.

pyphysim.channels.singleuser module

Module containing single user channels.

class pyphysim.channels.singleuser.SuChannel(fading_generator: Optional[Union[pyphysim.channels.fading_generators.JakesSampleGenerator, pyphysim.channels.fading_generators.RayleighSampleGenerator]] = None, channel_profile: Optional[pyphysim.channels.fading.TdlChannelProfile] = None, tap_powers_dB: Optional[numpy.ndarray] = None, tap_delays: Optional[numpy.ndarray] = None, Ts: Optional[float] = None)[source]

Bases: object

Single User channel corresponding to a Tapped Delay Line channel model, which corresponds to a multipath channel. You can use a single tap in order to get a flat fading channel.

You can create a new SuChannel object either specifying the channel profile or specifying both the channel tap powers and delays. If only the fading_generator is specified then a single tap with unitary power and delay zero will be assumed, which corresponds to a flat fading channel model.

Parameters
  • fading_generator (FadingGenerator) – The instance of a fading generator in the fading_generators module. It should be a subclass of FadingSampleGenerator. The fading generator will be used to generate the channel samples. If not provided then RayleighSampleGenerator will be used

  • channel_profile (fading.TdlChannelProfile) – The channel profile, which specifies the tap powers and delays.

  • tap_powers_dB (np.ndarray) – The powers of each tap (in dB). Dimension: L x 1 Note: The power of each tap will be a negative number (in dB).

  • tap_delays (np.ndarray) – The delay of each tap (in seconds). Dimension: L x 1

  • Ts (float, optional) – The sampling interval.

property channel_profile

Return the channel profile.

Returns

The channel profile.

Return type

fading.TdlChannelProfile

corrupt_data(signal: numpy.ndarray)numpy.ndarray[source]

Transmit the signal through the TDL channel.

Parameters

signal (np.ndarray) – The signal to be transmitted.

Returns

The received signal after transmission through the TDL channel.

Return type

np.ndarray

corrupt_data_in_freq_domain(signal: numpy.ndarray, fft_size: int, carrier_indexes: Optional[Union[numpy.ndarray, List[int], slice]] = None)numpy.ndarray[source]

Transmit the signal through the TDL channel, but in the frequency domain.

This is ROUGHLY equivalent to modulating signal with OFDM using fft_size subcarriers, transmitting through a regular TdlChannel, and then demodulating with OFDM to recover the received signal.

One important difference is that here the channel is considered constant during the transmission of fft_size elements in signal, and then it is varied by the equivalent of the variation for that number of elements. That is, the channel is block static.

Parameters
  • signal (np.ndarray) – The signal to be transmitted.

  • fft_size (int) – The size of the Fourier transform to get the frequency response.

  • carrier_indexes (slice | np.ndarray) – The indexes of the subcarriers where signal is to be transmitted. If it is None assume all subcarriers will be used. This can be a slice object or a numpy array of integers.

Returns

The received signal after transmission through the TDL channel

Return type

np.ndarray

get_last_impulse_response()pyphysim.channels.fading.TdlImpulseResponse[source]

Get the last generated impulse response.

A new impulse response is generated when the method corrupt_data is called. You can use the get_last_impulse_response method to get the impulse response used to corrupt the last data.

Returns

The impulse response of the channel that was used to corrupt the last data.

Return type

fading.TdlImpulseResponse

property num_rx_antennas

Get the number of receive antennas.

Returns

The number of receive antennas.

Return type

int

property num_taps

Get the number of taps in the profile.

Returns

The number of taps in the channel (not including any zero padding).

Return type

int

property num_taps_with_padding

Get the number of taps in the profile including zero-padding when the profile is discretized.

If the profile is not discretized an exception is raised.

Returns

The number of taps in the channel (including any zero padding).

Return type

int

property num_tx_antennas

Get the number of transmit antennas.

Returns

The number of transmit antennas.

Return type

int

set_num_antennas(num_rx_antennas: int, num_tx_antennas: int)None[source]

Set the number of transmit and receive antennas for MIMO transmission.

Set both num_rx_antennas and num_tx_antennas to None for SISO transmission

Parameters
  • num_rx_antennas (int) – The number of receive antennas.

  • num_tx_antennas (int) – The number of transmit antennas.

set_pathloss(pathloss_value: Optional[float] = None)None[source]

Set the path loss (IN LINEAR SCALE).

The path loss will be accounted when calling the corrupt_data method.

If you want to disable the path loss, set pathloss_value to None.

Parameters

pathloss_value (float | None) – The path loss (IN LINEAR SCALE) from the transmitter to the receiver. If you want to disable the path loss then set it to None.

Notes

Note that path loss is a power relation, which means that the channel coefficients will be multiplied by the square root of elements in pathloss_value.

property switched_direction

Get the value of switched_direction.

Returns

True if direction is switched and False otherwise.

Return type

bool

class pyphysim.channels.singleuser.SuMimoChannel(num_antennas: int, fading_generator: Optional[Union[pyphysim.channels.fading_generators.JakesSampleGenerator, pyphysim.channels.fading_generators.RayleighSampleGenerator]] = None, channel_profile: Optional[pyphysim.channels.fading.TdlChannelProfile] = None, tap_powers_dB: Optional[numpy.ndarray] = None, tap_delays: Optional[numpy.ndarray] = None, Ts: Optional[float] = None)[source]

Bases: pyphysim.channels.singleuser.SuChannel

Single User channel corresponding to a Tapped Delay Line channel model, which corresponds to a multipath channel. You can use a single tap in order to get a flat fading channel.

You can create a new SuMimoChannel object either specifying the channel profile or specifying both the channel tap powers and delays. If only the fading_generator is specified then a single tap with unitary power and delay zero will be assumed, which corresponds to a flat fading channel model.

Parameters
  • num_antennas (int) – Number of transmit and receive antennas.

  • fading_generator (FadingGenerator) – The instance of a fading generator in the fading_generators module. It should be a subclass of FadingSampleGenerator. The fading generator will be used to generate the channel samples. If not provided then RayleighSampleGenerator will be used

  • channel_profile (fading.TdlChannelProfile) – The channel profile, which specifies the tap powers and delays.

  • tap_powers_dB (np.ndarray) – The powers of each tap (in dB). Dimension: L x 1 Note: The power of each tap will be a negative number (in dB).

  • tap_delays (np.ndarray) – The delay of each tap (in seconds). Dimension: L x 1

  • Ts (float, optional) – The sampling interval.

Module contents

Module with implementation of channel related classes.