Signal

Inheritance diagram of hermespy.core.signal_model.Signal, hermespy.core.signal_model.DenseSignal, hermespy.core.signal_model.SparseSignal, hermespy.core.signal_model.SignalBlock

Signal models are HermesPy’s way of representing complex-valued electromagnetic multi-stream time-domain sequences.

class Signal[source]

Bases: ABC, HDFSerializable

Abstract base class for all signal models in HermesPy.

static Create(samples, sampling_rate=1.0, carrier_frequency=0.0, noise_power=0.0, delay=0.0, offsets=None)[source]

Creates a signal model instance given signal samples.

Subclasses of Signal should reroute the given arguments to init and return the result.

Parameters:
  • samples (numpy.ndarray | Sequence[np.ndarray]) – Single or a sequence of 2D matricies with shapes MxT_i, where M - number of streams, T_i - number of samples in the matrix i. Note that M for each entry of the sequence must be the same. SignalBlock and Sequence[SignalBlock] can also be passed here.

  • sampling_rate (float) – Sampling rate of the signal in Hz.

  • offsets (List[int]) – Integer offsets of the samples if given in a sequence. Ignored if samples is not a Sequence of np.ndarray. len(offsets) must be equal to len(samples). Offset number i must be greater then offset i-1 + samples[i-1].shape[1].

Return type:

Signal

Returns: SparseSignal if samples argument is a list of np.ndarrays. DenseSignal otherwise.

static Empty(sampling_rate, num_streams=0, num_samples=0, **kwargs)[source]

Creates an empty signal model instance. Initializes it with the given arguments. If both num_streams and num_samples are not 0, then initilizes samples with np.empty.

Return type:

Signal

append_samples(signal)[source]

Append samples in time-domain to the signal model.

Parameters:

signal (Signal) – The signal to be appended.

Raises:

ValueError – If the number of streams don’t align.

Return type:

None

append_streams(signal)[source]

Append streams to the signal model.

Parameters:

signal (Signal) – The signal to be appended.

Raises:

ValueError – If the number of samples don’t align.

Return type:

None

copy()[source]

Copy this signal model to a new object.

Returns:

A copy of this signal model.

Return type:

Signal

classmethod from_interleaved(interleaved_samples, scale=True, **kwargs)[source]

Initialize a signal model from interleaved samples.

Parameters:
  • interleaved_samples (numpy.ndarray) – Numpy array of interleaved samples.

  • scale (bool, optional) – Scale the samples after interleaving

  • **kwargs – Additional class initialization arguments.

Return type:

Signal

from_ndarray(samples)[source]

Create a new signal using parameters from this signal. Equivalent to create(samples, **self.kwargs).

getitem(key=slice(None, None, None), unflatten=True)[source]

Get specified samples. Works like np.ndarray.__getitem__, but de-sparsifies the signal.

Parameters:
  • key (Any) – an int, a slice, a tuple (int, int), (int, slice), (slice, int), (slice, slice) or a boolean mask. Defaults to slice(None, None) (same as [:, :])

  • unflatten (bool) – Set to True to ensure the result ndim to be 2 even if only one stream is selected. Set to False to allow the numpy-like degenerate dimensions reduction.

Return type:

ndarray

Examples

getitem(slice(None, None)):

Select all samples from the signal. Warning: can cause memory overflow if used with a sparse signal.

getitem(0):

Select and de-sparsify the first stream. Result shape is (1, num_samples)

getitem(0, False):

Same, but allow the numpy flattening. Result shape is (num_samples,)

getitem((slice(None, 2), slice(50, 100))):

Select streams 0, 1 and samples 50-99. Same as samples_matrix[:2, 50:100]

Returns: np.ndarray with ndim 2 or less and dtype dtype np.complex128

getstreams(streams_key)[source]

Create a new signal like this, but with only the selected streams.

Parameters:

streams_key (int, slice, Sequence[int]) – Stream indices to select.

Returns:

Signal of the same implementation as the caller, containing only the selected streams

Return type:

signal (Signal)

resample(sampling_rate, aliasing_filter=True)[source]

Resample the modeled signal to a different sampling rate.

Parameters:
  • sampling_rate (float) – Sampling rate of the new signal model in Hz.

  • aliasing_filter (bool, optional) – Apply an anti-aliasing filter during downsampling. Enabled by default.

Returns:

The resampled signal model.

Return type:

Signal

Raises:

ValueError – If sampling_rate is smaller or equal to zero.

set_samples(samples, offsets=None)[source]

Sets given samples into this dense signal model. Validates given samples and optional offsets, writes them into _blocks attribute and resambles, if needed.

Return type:

None

superimpose(added_signal, resample=True, aliasing_filter=True, stream_indices=None)[source]

Superimpose an additive signal model to this model.

Internally re-samples added_signal to this model’s sampling rate, if required. Mixes added_signal according to the carrier-frequency distance.

Parameters:
  • added_signal (Signal) – The signal to be superimposed onto this one.

  • resample (bool) – Allow for dynamic resampling during superposition.

  • aliasing_filter (bool, optional) – Apply an anti-aliasing filter during mixing.

  • stream_indices (Sequence[int], optional) – Indices of the streams to be mixed.

Raises:
  • ValueError – If added_signal contains a different number of streams than this signal model.

  • RuntimeError – If resampling is required but not allowd.

  • NotImplementedError – If the delays if this signal and added_signal differ.

Return type:

None

to_dense()[source]

Concatenate all the blocks in the signal into one block. Accounts for offsets. Warning - if offset values are to big, memory overflow is possible.

Returns:

Dense form for this signal

Return type:

signal (DenseSignal)

to_interleaved(data_type=<class 'numpy.int16'>, scale=True)[source]

Convert the complex-valued floating-point model samples to interleaved integers.

Parameters:
  • data_type (optional) – Numpy resulting data type.

  • scale (bool, optional) – Scale the floating point values to stretch over the whole range of integers.

Returns:

Numpy array of interleaved samples. Will contain double the samples in time-domain.

Return type:

samples (numpy.ndarray)

property carrier_frequency: float

The center frequency of the modeled signal in the radio-frequency transmit band.

Returns:

The carrier frequency in Hz.

Return type:

float

delay: float
property duration: float

Signal model duration in time-domain.

Returns:

Duration in seconds.

Return type:

float

property energy: ndarray

Compute the energy of the modeled signal.

Returns: The energy of each modeled stream within a numpy vector.

property eye: _EyeVisualization

Visualize the eye diagram of the signal model.

filter_order: int = 10
property frequencies: ndarray

The signal model’s discrete sample points in frequcy domain.

Returns: Numpy vector of frequency bins.

property kwargs: dict

Returns: {“sampling_rate”: self.sampling_rate, “carrier_frequency”: self.carrier_frequency, “delay”: self.delay, “noise_power”: self.noise_power}

property noise_power: float

Noise power of the superimposed noise signal.

Returns:

Noise power.

Raises:

ValueError – If the noise power is smaller than zero.

property num_samples: int

The number of samples within this signal model.

Returns:

The number of samples.

Return type:

int

property num_streams: int

The number of streams within this signal model.

Returns:

The number of streams.

Return type:

int

property plot: _SamplesVisualization

Visualize the samples of the signal model.

property power: ndarray

Compute the power of the modeled signal.

Returns: The power of each modeled stream within a numpy vector.

property sampling_rate: float

The rate at which the modeled signal was sampled.

Returns:

The sampling rate in Hz.

Return type:

float

property shape: tuple

(num_streams, num_samples)

Type:

Returns

property timestamps: ndarray

The sample-points of the signal block.

Returns:

Vector of length T containing sample-timestamps in seconds.

Return type:

np.ndarray

property title: str
class DenseSignal(samples, sampling_rate=1.0, carrier_frequency=0.0, noise_power=0.0, delay=0.0, offsets=None)[source]

Bases: Signal

Dense signal model class.

Signal model initialization.

Parameters:
  • samples (numpy.ndarray | Sequence[np.ndarray] | Sequence[SignalBlock]) – A MxT matrix containing uniformly sampled base-band samples of the modeled signal. M is the number of individual streams, T the number of available samples. Note that you can pass here a 2D ndarray, a SignalBlock, a Sequence[np.ndarray] or a Sequence[SignalBlock]. Given Sequence[SignalBlock], concatenates all signal blocks into one, accounting for their offsets. Given Sequence[np.ndarray], concatenates them all into one matrix sequentially. Warning: do not pass sparse sequences of SignalBlocks here as it can lead to memory bloat. Consider SparseSignal instead.

  • sampling_rate (float) – Sampling rate of the modeled signal in Hz (in the base-band).

  • carrier_frequency (float, optional) – Carrier-frequency of the modeled signal in the radio-frequency band in Hz. Zero by default.

  • noise_power (float, optional) – Power of the noise superimposed to this signal model. Zero by default.

  • delay (float, optional) – Delay of the signal in seconds. Zero by default.

  • offsets (List[int], optional) – If provided, must be of the same length as the samples argument. If samples argument is not an Sequence[SignalBlock], then offsets will be used to dislocate the blocks in the signal.

static Create(samples, sampling_rate=1.0, carrier_frequency=0.0, noise_power=0.0, delay=0.0, offsets=None)[source]

Creates a signal model instance given signal samples.

Subclasses of Signal should reroute the given arguments to init and return the result.

Parameters:
  • samples (numpy.ndarray | Sequence[np.ndarray]) – Single or a sequence of 2D matricies with shapes MxT_i, where M - number of streams, T_i - number of samples in the matrix i. Note that M for each entry of the sequence must be the same. SignalBlock and Sequence[SignalBlock] can also be passed here.

  • sampling_rate (float) – Sampling rate of the signal in Hz.

  • offsets (List[int]) – Integer offsets of the samples if given in a sequence. Ignored if samples is not a Sequence of np.ndarray. len(offsets) must be equal to len(samples). Offset number i must be greater then offset i-1 + samples[i-1].shape[1].

Return type:

DenseSignal

Returns: SparseSignal if samples argument is a list of np.ndarrays. DenseSignal otherwise.

static Empty(sampling_rate, num_streams=0, num_samples=0, **kwargs)[source]

Creates an empty signal model instance. Initializes it with the given arguments. If both num_streams and num_samples are not 0, then initilizes samples with np.empty.

Return type:

DenseSignal

append_samples(signal)[source]

Append samples in time-domain to the signal model.

Parameters:

signal (Signal) – The signal to be appended.

Raises:

ValueError – If the number of streams don’t align.

Return type:

None

append_streams(signal)[source]

Append streams to the signal model.

Parameters:

signal (Signal) – The signal to be appended.

Raises:

ValueError – If the number of samples don’t align.

Return type:

None

getitem(key=slice(None, None, None), unflatten=True)[source]

Reroutes the argument to the single block of this model. Refer the numpy.ndarray.__getitem__ documentation. The result is always a 2D ndarray.

Return type:

ndarray

set_samples(samples, offsets=None)[source]

Sets given samples into this dense signal model. SignalBlock or Sequence[SignalBlock] can be provided in samples. In this case they all will be resampled and the offsets argument will be ignored. A single 2D ndarray can be provided to construct a SignalBlock. Offsets will be ignored. A Sequence[ndarray] can be provided. If no offsets are given, then they all will be concatenated. If offsets are provided, the samples will be concatenated, including zero gaps accounting for offsets. If samples is Sequence[SignalBlock] and offsets are provided, blocks’ offsets will be ignored Warning: avoid using sparse offsets as this can cause a memory bloat. Consider SparseSignal instead.

Return type:

None

to_dense()[source]

Concatenate all the blocks in the signal into one block. Accounts for offsets. Warning - if offset values are to big, memory overflow is possible.

Returns:

Dense form for this signal

Return type:

signal (DenseSignal)

property energy: ndarray

Compute the energy of the modeled signal.

Returns: The energy of each modeled stream within a numpy vector.

property power: ndarray

Compute the power of the modeled signal.

Returns: The power of each modeled stream within a numpy vector.

property title: str
class SparseSignal(samples, sampling_rate=1.0, carrier_frequency=0.0, noise_power=0.0, delay=0.0, offsets=None)[source]

Bases: Signal

Sparse signal model class. HermesPy signal sparsification can be described as follows. Given M signal streams, N samples are recorded for each stream with some constant temporal sampling rate. Thus, a MxN complex matrix of samples can be constructed. If at some point streams do not contain any recorded/transmitted signal, then fully zeroed columns appear in the matrix. This signal model contains a list of SignalBlocks, each representing non-zero regions of the original samples matrix. Thus, regions with only zeros are avoided. Note, that SignalBlocks are sorted by their offset time and don’t overlap.

Signal model initialization.

Parameters:
  • samples (numpy.ndarray | Sequence[SignalBlock]) – A MxT matrix containing uniformly sampled base-band samples of the modeled signal. M is the number of individual streams, T the number of available samples. Note that you can pass here a 2D ndarray, a SignalBlock, a Sequence[np.ndarray] or a Sequence[SignalBlock]. Given Sequence[SignalBlock], concatenates all signal blocks into one, accounting for their offsets. Given Sequence[np.ndarray], concatenates them all into one matrix sequentially.

  • sampling_rate (float) – Sampling rate of the modeled signal in Hz (in the base-band).

  • carrier_frequency (float, optional) – Carrier-frequency of the modeled signal in the radio-frequency band in Hz. Zero by default.

  • noise_power (float, optional) – Power of the noise superimposed to this signal model. Zero by default.

  • delay (float, optional) – Delay of the signal in seconds. Zero by default.

  • offsets (List[int], optional) – If provided, must be of the same length as the samples argument. If samples argument is not an Sequence[SignalBlock], then offsets will be used to dislocate the blocks in the signal.

static Create(samples, sampling_rate=1.0, carrier_frequency=0.0, noise_power=0.0, delay=0.0, offsets=None)[source]

Creates a signal model instance given signal samples.

Subclasses of Signal should reroute the given arguments to init and return the result.

Parameters:
  • samples (numpy.ndarray | Sequence[np.ndarray]) – Single or a sequence of 2D matricies with shapes MxT_i, where M - number of streams, T_i - number of samples in the matrix i. Note that M for each entry of the sequence must be the same. SignalBlock and Sequence[SignalBlock] can also be passed here.

  • sampling_rate (float) – Sampling rate of the signal in Hz.

  • offsets (List[int]) – Integer offsets of the samples if given in a sequence. Ignored if samples is not a Sequence of np.ndarray. len(offsets) must be equal to len(samples). Offset number i must be greater then offset i-1 + samples[i-1].shape[1].

Return type:

SparseSignal

Returns: SparseSignal if samples argument is a list of np.ndarrays. DenseSignal otherwise.

static Empty(sampling_rate, num_streams=0, num_samples=0, **kwargs)[source]

Creates an empty signal model instance. Initializes it with the given arguments. If both num_streams and num_samples are not 0, then initilizes samples with np.empty.

Return type:

SparseSignal

append_samples(signal)[source]

Append samples in time-domain to the signal model.

Parameters:

signal (Signal) – The signal to be appended.

Raises:

ValueError – If the number of streams don’t align.

Return type:

None

append_streams(signal)[source]

Append streams to the signal model.

Parameters:

signal (Signal) – The signal to be appended.

Raises:

ValueError – If the number of samples don’t align.

Return type:

None

set_samples(samples, offsets=None)[source]

Sets given samples into this sparse signal model.

Return type:

None

Usage:
samples (numpy.ndarray):

In this case samples array (a 2D complex matrix) will be divided onto several non-zero blocks.

samples (Sequence[np.ndarray]):

In this case all entries (2D complex matrices) will be concatenated among the samples axis and sparsified.

samples (Sequence[np.ndarray]), offsets(Sequence[integer]):

In this case SignalBlocks will be constructed directly out of the samples entries, avoiding sparsification. Note that number of offsets entries must equal to the number of samples entries. Offsets must be sorted in an increasing order and samples entries must not overlap (e.g. offsets[i] + samples[i].shape[1] < offsets[i+1]).

samples (SignalBlock):

In this case given SignalBlock will be resampled and sparcified. The block’s offset property will be preserved. Consider setting it to zero beforehand (samples.offset= 0).

samples (Sequence[SignalBlock]):

In this case each entry will be resampled and stored in the model, avoiding sparsification. Note that the entries must be sorted by an offset in an increasing order and must not overlap (e.g. samples[i].offset+ samples[i].num_samples < samples[i+1].off).

samples (List[SignalBlock]), offsets(Sequence[integer]):

In this case the same actions will be taken as in the previous case, but given offsets will be set into the samples entries before resampling. Note that number of offsets entries must equal to the number of samples entries.

property title: str
class SignalBlock(samples: Any, offset: int)[source]

Bases: ndarray

A TxN matrix of complex entries representing signal samples over T streams and N time samples. Used in Signal to store pieces of signal samples. Use “offset” property to set the offset of this block relative to a signal start sample.

Create a new SignalBlock instance.

Parameters:
  • samples (array_like) – The object to be converted to a 2D matrix. Arrays of higher dim count are not allowed. Uses np.asarray for conversion.

  • offset (int) – Integer offset of this block in a signal model

Raises:

ValueError – If ndim of given samples is bigger then 2.

append_samples(value)[source]

Append samples to this signal block. Creates a new instance.

Return type:

SignalBlock

copy(order=None)[source]

Copy this signal block to a new object.

Parameters:

order (Optional[Literal['K', 'A', 'C', 'F']]) – Ignored.

Returns:

A copy of this signal model.

Return type:

Signal

resample(sampling_rate_old, sampling_rate_new, aliasing_filter=True)[source]

Resample a signal block to a different sampling rate.

Parameters:
  • sampling_rate_old (float) – Old sampling rate of the signal block in Hz.

  • sampling_rate_new (float) – New sampling rate of the signal block in Hz.

  • aliasing_filter (bool, optional) – Apply an anti-aliasing filter during downsampling. Enabled by default.

Returns:

The resampled signal block.

Return type:

SignalBlock

Raises:

ValueError – If sampling_rate_old or sampling_rate_new are smaller or equal to zero.

property end: int

Get block stop sample. b.num_samples = b.end - b.off

property energy: ndarray

Compute the energy of the modeled signal.

Returns: The energy of each modeled stream as a numpy vector.

property num_samples: int

The number of samples within this signal block.

Returns:

The number of samples.

Return type:

int

property num_streams: int

The number of streams within this signal block.

Returns:

The number of streams.

Return type:

int

property offset: int

Get block’s offset

property power: ndarray

Compute power of the modeled signal.

Returns: The power of each modeled stream as a numpy vector.

class _SamplesVisualization(signal)[source]

Bases: _SignalVisualization

Visualize the samples of a signal model.

Parameters:

signal (Signal) – The signal model to be visualized.

create_figure(space='both', **kwargs)[source]

Create a new figure for plotting.

Returns: Newly generated figure and axes to plot into.

Return type:

Tuple[FigureBase, ndarray[Tuple[int, int], dtype[Any]]]

property title: str

Title of the visualizable.

Returns: Title string.

class _EyeVisualization(signal)[source]

Bases: _SignalVisualization

Visualize the eye diagram of a signal model.

Depending on the domain flag the eye diagram will either be rendered with the time-domain on the plot’s x-axis

(Source code, png, hires.png, pdf)

../../_images/signal-1.png

or on the complex plane

(Source code, png, hires.png, pdf)

../../_images/signal-2.png
Parameters:
  • symbol_duration (float) – Assumed symbol repetition interval in seconds. Will be rounded to match the signal model’s sampling rate.

  • line_width (float, optional) – Line width of a single plot line.

  • title (str, optional) – Title of the plotted figure. Eye Diagram by default.

  • domain (Literal["time", "complex"]) – Plotting behaviour of the eye diagram. time by default. See above examples for rendered results.

  • legend (bool, optional) – Display a plot legend. Enabled by default. Only considered when in time domain plotting mode.

  • linewidth (float, optional) – Line width of the eye plot. \(.75\) by default.

  • symbol_cutoff (float, optional) – Relative amount of symbols ignored during plotting. \(0.1\) by default. This is required to properly visualize intersymbol interferences within the communication frame, since special effects may occur at the start and end.

  • signal (Signal) – The signal model to be visualized.

property title: str

Title of the visualizable.

Returns: Title string.

class _SignalVisualization(signal)[source]

Bases: VisualizableAttribute[PlotVisualization]

Visualization of signal samples.

Parameters:

signal (Signal) – The signal model to be visualized.

property signal: Signal

The signal model to be visualized.