Waveform

The module waveform.py implements the Waveform class which encapsulates a time-domain signal transmitted from a set of transmitter antennas or received by a set of receiver antennas. A waveform object is usually created by applying OFDM modulation to a resource grid object. See ofdmModulate() method of the Grid class for more information.

class neoradium.waveform.Waveform(waveform, noiseVar=0)

This class encapsulates a set of sequences of complex values representing the time-domain signals as transmitted by each transmitter antenna or as received by each receiver antenna. A Waveform object is usually created by applying OFDM modulation to a resource grid.

Once you have a Waveform object, you can apply a channel model to it, add AWGN noise to it, or apply other signal processing tasks such as windowing. All of these processes result in new Waveform objects.

At the receiver the received signals are usually converted back to the frequency domain by applying OFDM demodulation, which results in a Grid object representing the received resource grid.

Parameters:
  • waveform (2D complex NumPy array) – A P x Ns 2D complex NumPy array representing a set of time-domain signals of length Ns for each one of P antenna elements. The value P is equal to Nt, the number of transmitter antennas when this is a transmitted signal, and equal to Nr, the number of receiver antennas when this is a received signal.

  • noiseVar (float) – The variance of the noise applied to the time-domain signals in this Waveform object. This is usually initialized to zero. When an AWGN noise is applied to the waveform using the addNoise() function, the variance of the noise is saved in the Waveform object.

Other Read-Only Properties:

shape:

Returns the shape of the 2-dimensional waveform NumPy array.

numPorts:

The number of transmitter or receiver antennas (P) for this waveform.

length:

The length of the time-domain signal in number of samples (Ns).

print(indent=0, title=None, getStr=False)

Prints the properties of this Waveform object.

Parameters:
  • indent (int) – The number of indentation characters.

  • title (str) – If specified, it is used as a title for the printed information.

  • getStr (Boolean) – If True, returns a text string instead of printing it.

Returns:

If the getStr parameter is True, then this function returns the information in a text string. Otherwise, nothing is returned.

Return type:

None or str

getNoiseStd(snr, bwp)

This function calculates the noise standard deviation for the given signal-to-noise ratio. It first calculates the average received signal power per resource element (RE) and then uses it, along with the given signal-to-noise ratio, to calculate the noise power. The returned standard deviation can be used directly by the addNoise() method using the noiseStd argument.

Parameters:
  • snr (float) – The signal-to-noise ratio in the linear form (not dB).

  • bwp (BandwidthPart) – The bandwidth part object used to create the waveform.

Returns:

The noise standard deviation.

Return type:

float

addNoise(**kwargs)

Adds Additive White Gaussian Noise (AWGN) to this waveform based on the given noise properties. The noisy waveform is then returned in a new Waveform object.

This is similar to the addNoise() method of the Grid class, which applies noise in the frequency domain.

If you have the noise signal in a numpy array, you can use the noise parameter of this function to apply it to this waveform:

Example
myNoise = random.awgn(rxWaveform.shape, 0.1)    # Create AWGN with σ = 0.1
rxWaveform.addNoise(noise=myNoise)

If you know the variance or standard deviation of the noise, then you can use them directly by setting the arguments noiseStd and noiseVar respectively.

Example
rxWaveform.addNoise(noiseStd=0.1)       # Same results as above
rxWaveform.addNoise(noiseVar=0.01)      # Same results as above

If you have a signal-to-noise ratio, there are two different approaches to adding noise to the received waveform.

Matlab Approach:

In this case, it is assumed that the received signal power is normalized to \(\frac 1 {N_r}\) where \(N_r\) is the number of receiver antenna. Please note that when channel models such as CDL, TDL, or trajectory based channel models are used in the communication pipleline, this assumption is not always true. Support for this approach is included only to allow comparison with Matlab.

\[\sigma^2_{AWGN} = \frac 1 {N_r.nFFT.10^{\frac {snrDb} {10}}}\]

where \(nFFT\) is the FFT size derived from the given BandwidthPart object.

Example
rxWaveform.addNoise(snrDb=mySnrDb, bwp=bwp, useRxPower=False)

Using RX Power:

In this case, this function first calculates the average received signal power per resource element (RE), and uses it, along with the given signal-to-noise ratio to calculate the noise power.

\[\sigma^2_{AWGN} = \frac {\sigma^2_{RX}} {nFFT.10^{\frac {snrDb} {10}}}\]
Example
rxWaveform.addNoise(snrDb=mySnrDb, bwp=bwp, useRxPower=True)

Please refer to the notebook SNR Calculations in NeoRadium for a complete analysis of how NeoRadium calculates and applies noise power for a given signal-to-noise ratio.

Parameters:

kwargs (dict) –

One of the following methods of specifying the noise must be specified.

noise:

A NumPy array with the same shape as this Waveform object containing the noise information. If the noise information is provided by noise, it is added directly to the waveform. In this case all other parameters are ignored.

noiseStd:

The standard deviation of the noise. An AWGN complex noise signal is generated with zero mean and the specified standard deviation. If noiseStd is specified, noiseVar and snrDb are ignored.

noiseVar:

The variance of the noise. An AWGN complex noise signal is generated with zero mean and the specified variance. If noiseVar is specified, the value of snrDb is ignored.

snrDb:

The signal-to-noise ratio in dB. First the noise standard deviation is calculated using the given SNR value and the bwp and useRxPower parameters. Then an AWGN complex noise signal is generated with zero mean and the calculated standard deviation. Please note that if an SNR value is used to specify the amount of noise, then a BandwidthPart object also needs to be provided.

bwp:

BandwidthPart The bandwidth part object used to extract the FFT information. This is only used if snrDb is used to specify the amount of noise.

useRxPower:

Boolean If True, this function first calculates the average received signal power per resource element (RE), and uses it with the given signal-to-noise ratio to calculate the noise power. Otherwise, it is assumed that the received signal power is normalized to \(\frac 1 {N_r}\) where \(N_r\) is the number of receiver antenna (Matlab Approach).

Note

Currently the default value of useRxPower is False (Matlab approach) for backward compatibility. However, in future releases this may be changed to True. To ensure forward-compatible code, explicitly set this parameter instead of relying on the default.

ranGen:

If provided, it is used as the random generator for the AWGN generation. Otherwise, if this is not specified, NeoRadium’s global random generator is used.

Returns:

A new Waveform object containing the noisy version of this waveform.

Return type:

Waveform

pad(numPad)

Appends a sequence of numPad zeros to the end of time-domain signals in this Waveform object.

To make sure a signal is received in its entirety when it goes through a channel model, we usually need to pad zeros to the end of the time-domain signal. The number of these zeros usually depends on the maximum channel delay. The function getMaxDelay() of the channel model can be used to get the number of padded zeros.

Parameters:

numPad (int) – The number of time-domain zero samples to be appended to the end of this waveform.

Returns:

A new Waveform object which is numPad samples longer than the original waveform.

Return type:

Waveform

sync(timingOffset)

Removes timingOffset values from the beginning of the time-domain signals in this Waveform object. This effectively shifts the signal in time domain by timingOffset samples.

When a time-domain signal goes through a channel model, it is delayed in time because of the propagation delay. Different transmission paths may be affected by different propagation delays. The channel’s chanOffset member can be used to obtain the timingOffset. In practice, this value is calculated by finding the time-domain sample index where the correlation between the received signal and a set of reference signals is at its maximum. See for example the function estimateTimingOffset() of the Grid class.

Parameters:

timingOffset (int) – The number of time-domain samples that are removed from the beginning of the time-domain signals in this Waveform object.

Returns:

A new Waveform object which is timingOffset samples shorter than the original waveform.

Return type:

Waveform

applyChannel(channel)

Applies the channel model channel to this Waveform object and returns a new Waveform object representing the received signal. This function internally calls the applyToSignal() method of the channel model passing in this waveform object as the inputSignal.

Parameters:

channel (ChannelModel) – The channel model that is applied to this time-domain waveform.

Returns:

A new Waveform object which represents the received time-domain waveform.

Return type:

Waveform

applyWindowing(cpLens, windowing, bwp)

This is a helper function that is used to apply windowing to the OFDM waveform obtained from OFDM modulation of a resource grid.

This method supports several different windowing approaches including the ones specified in 3GPP TS 38.104, Sections B.5.2 and C.5.2.

You usually do not need to call this function directly. It is called internally at the end of the OFDM modulation process when the function ofdmModulate() of the Grid class is called.

Parameters:
  • cpLens (list) – A list of integer values each representing the length of cyclic prefix part at the beginning of each OFDM symbol in number of time-domain samples. This list can be obtained from the BandwidthPart object.

  • windowing (str) –

    A text string specifying how the window length is obtained. It can be one of the following:

    ”STD”:

    The windowing size is determined based on 3GPP TS 38.104, Sections B.5.2 and C.5.2.

    Ratio as percentage:

    A windowing ratio can be specified as a percentage value. For example, the text string “%25” represents a windowing ratio of 0.25. The window length is calculated as the minimum value of cpLens multiplied by the windowing ratio, and rounded to the nearest integer value.

    Ratio:

    A windowing ratio (between 0 and 1) can be specified as a number. For example, the text string “0.125” represents a windowing ratio of 0.125. The window length is calculated as the minimum value of cpLens multiplied by the windowing ratio and rounded to the nearest integer value.

    Window Length:

    The actual window length can also be specified as an integer value. For example, the text string “164” represents a window length equal to 164.

  • bwp (BandwidthPart) – The bandwidth part used for the communication.

Returns:

A new Waveform object which represents the waveform after applying the windowing.

Return type:

Waveform

ofdmDemodulate(bwp, f0=0, cpOffsetRatio=0.5)

Applies OFDM demodulation to the waveform which results in a frequency-domain resource grid returned as a Grid object.

If an AWGN noise was applied to the waveform using the addNoise() method, then the amount of noise is transferred to the Grid object that is created. The noise variance of the returned resource grid is equal to the waveform’s noise variance times nFFT.

Parameters:
  • bwp (BandwidthPart) – The bandwidth part used for the communication.

  • f0 (float) – The carrier frequency of the waveform. If it is 0 (default), then a baseband waveform is assumed. This should match the value originally used when applying OFDM modulation at the transmitter side. See the ofdmModulate() method of the Grid class.

  • cpOffsetRatio (float) – This value determines where, in the cyclic prefix (as a ratio from the beginning of the CP), the FFT should be applied. The default value of 0.5 means that the FFT is applied at the midpoint of the cyclic prefix.”

Returns:

A Grid object representing the received resource grid.

Return type:

Grid