Skip to content

komm.TransmitFilter

Transmit filter (pulse shaping). Given a sequence of $N$ real or complex symbols $x[n]$, this filter outputs samples of the signal $$ y(t) = \sum_{n=0}^{N-1} x[n] p(t - n), $$ where $p(t)$ is the waveform of a given pulse, and the samples of the output signal are taken at an integer rate of $\beta$ samples per symbol. Note that the symbol interval is normalized to $1$.

The time span of $y(t)$ is given by $[ n_0, n_1 + N - 1 )$, where $[ n_0, n_1 )$ is the integer-bounded time span of $p(t)$. In turn, $n_0$ and $n_1$ depend on the support of $p(t)$:

  • If $p(t)$ has finite support $[ t_0, t_1 ]$, then $n_0 = \lfloor t_0 \rfloor$ and $n_1 = \lceil t_1 \rceil$.

  • If $p(t)$ has infinite support, then $n_0 = -L/2$ and $n_1 = L/2$, where $L$ is a given even positive integer, called the truncation window length.

Attributes:

  • pulse (Pulse)

    The pulse whose waveform is $p(t)$.

  • samples_per_symbol (int)

    The number $\beta$ of samples (of the output) per symbol (of the input). Must be a positive integer.

  • truncation (int | None)

    The truncation window length $L$. Only applies to infinite-duration pulses. Must be an even positive integer. The default value is 32.

pulse_time_span tuple[int, int] cached property

The integer-bounded time span $[ n_0, n_1 )$ of the pulse waveform $p(t)$.

Examples:

>>> pulse = komm.RectangularPulse(0.25)
>>> pulse.support
(0.0, 0.25)
>>> tx_filter = komm.TransmitFilter(pulse=pulse, samples_per_symbol=3)
>>> tx_filter.pulse_time_span
(0, 1)
>>> pulse = komm.SincPulse()
>>> pulse.support
(-inf, inf)
>>> tx_filter = komm.TransmitFilter(
...     pulse=pulse, samples_per_symbol=4, truncation=4
... )
>>> tx_filter.pulse_time_span
(-2, 2)

taps NDArray[floating] cached property

The FIR filter taps of the transmit filter.

Examples:

>>> pulse = komm.RectangularPulse(width=0.25)
>>> tx_filter = komm.TransmitFilter(pulse=pulse, samples_per_symbol=3)
>>> tx_filter.taps
array([1., 0., 0.])
>>> pulse = komm.SincPulse()
>>> tx_filter = komm.TransmitFilter(
...     pulse=pulse, samples_per_symbol=4, truncation=4
... )
>>> tx_filter.taps.reshape((-1, 4)).round(6)
array([[-0.      , -0.128617, -0.212207, -0.180063],
       [ 0.      ,  0.300105,  0.63662 ,  0.900316],
       [ 1.      ,  0.900316,  0.63662 ,  0.300105],
       [ 0.      , -0.180063, -0.212207, -0.128617]])

__call__()

Process the input symbols through the transmit filter.

Parameters:

  • input (ArrayLike)

    The input symbols $x[n]$, of length $N$.

Returns:

  • output (NDArray[floating | complexfloating])

    The samples of the output signal $y(t)$, of length $(N + n_1 - n_0 - 1) \beta$.

Examples:

>>> pulse = komm.RectangularPulse(width=1.0)
>>> tx_filter = komm.TransmitFilter(pulse=pulse, samples_per_symbol=3)
>>> tx_filter([1.0, -1.0, 1.0, 1.0])
array([ 1.,  1.,  1., -1., -1., -1.,  1.,  1.,  1.,  1.,  1.,  1.])
>>> pulse = komm.RectangularPulse(width=0.25)
>>> tx_filter = komm.TransmitFilter(pulse=pulse, samples_per_symbol=3)
>>> tx_filter([1.0, -1.0, 1.0, 1.0])
array([ 1.,  0.,  0., -1.,  0.,  0.,  1.,  0.,  0.,  1.,  0.,  0.])
>>> pulse = komm.SincPulse()
>>> tx_filter = komm.TransmitFilter(
...     pulse=pulse, samples_per_symbol=4, truncation=4
... )
>>> tx_filter([1.0, -1.0, 1.0, 1.0]).reshape((-1, 4)).round(6)
array([[-0.      , -0.128617, -0.212207, -0.180063],
       [ 0.      ,  0.428722,  0.848826,  1.08038 ],
       [ 1.      ,  0.471594, -0.212207, -0.780274],
       [-1.      , -0.908891, -0.424413,  0.291531],
       [ 1.      ,  1.380485,  1.485446,  1.329038],
       [ 1.      ,  0.720253,  0.424413,  0.171489],
       [ 0.      , -0.180063, -0.212207, -0.128617]])
>>> pulse = komm.RectangularPulse()
>>> tx_filter = komm.TransmitFilter(
...     pulse=pulse, samples_per_symbol=4, truncation=4
... )
Traceback (most recent call last):
...
ValueError: 'truncation' only applies to infinite-support pulses

axes()

Convenience function to generate the time and frequency axes of the output signal given the input symbols.

Parameters:

  • input (ArrayLike)

    The input symbols $x[n]$, of length $N$.

Returns:

  • ts (NDArray[floating])

    The time axis of the output signal, having the same length as the output signal.

  • fs (NDArray[floating])

    The frequency axis of the output signal, having the same length as the output signal.

Examples:

>>> pulse = komm.RectangularPulse()
>>> tx_filter = komm.TransmitFilter(pulse=pulse, samples_per_symbol=3)
>>> ts, fs = tx_filter.axes([1.0, -1.0, 1.0, 1.0])
>>> ts.reshape((-1, 3))
array([[0.        , 0.33333333, 0.66666667],
       [1.        , 1.33333333, 1.66666667],
       [2.        , 2.33333333, 2.66666667],
       [3.        , 3.33333333, 3.66666667]])
>>> fs
array([-1.5 , -1.25, -1.  , -0.75, -0.5 , -0.25,  0.  ,  0.25,  0.5 ,
        0.75,  1.  ,  1.25])
>>> pulse = komm.SincPulse()
>>> tx_filter = komm.TransmitFilter(
...     pulse=pulse, samples_per_symbol=4, truncation=4
... )
>>> ts, fs = tx_filter.axes([1.0, -1.0, 1.0, 1.0])
>>> ts.reshape((-1, 4))
array([[-2.  , -1.75, -1.5 , -1.25],
       [-1.  , -0.75, -0.5 , -0.25],
       [ 0.  ,  0.25,  0.5 ,  0.75],
       [ 1.  ,  1.25,  1.5 ,  1.75],
       [ 2.  ,  2.25,  2.5 ,  2.75],
       [ 3.  ,  3.25,  3.5 ,  3.75],
       [ 4.  ,  4.25,  4.5 ,  4.75]])
>>> fs
array([-3.5 , -3.25, -3.  , -2.75, -2.5 , -2.25, -2.  , -1.75, -1.5 ,
       -1.25, -1.  , -0.75, -0.5 , -0.25,  0.  ,  0.25,  0.5 ,  0.75,
        1.  ,  1.25,  1.5 ,  1.75,  2.  ,  2.25,  2.5 ,  2.75,  3.  ,
        3.25])