def test_merge_spectrums_manually(): """Tests the merging behavior with manually generated spectrums.""" spectrum1 = sumpf.Spectrum(channels=numpy.array([(1.1j, 1.2, 1.3j)]), resolution=1.0, labels=("s1c1",)) spectrum2 = sumpf.Spectrum(channels=numpy.array([(2.1, 2.2j, 2.3, 2.4j), (3.1, 3.2j, 3.3, 3.4j)]), resolution=2.0, labels=("s2c1", "s2c2")) spectrum12 = sumpf.Spectrum(channels=numpy.array([(1.1j, 1.2, 1.3j, 0.0), (2.1, 2.2j, 2.3, 2.4j), (3.1, 3.2j, 3.3, 3.4j)]), resolution=1.0, labels=("s1c1", "s2c1", "s2c2")) spectrum21 = sumpf.Spectrum(channels=numpy.array([(2.1, 2.2j, 2.3, 2.4j), (3.1, 3.2j, 3.3, 3.4j), (1.1j, 1.2, 1.3j, 0.0)]), resolution=2.0, labels=("s2c1", "s2c2", "s1c1")) spectrum21c = sumpf.Spectrum(channels=numpy.array([(2.1, 2.2j, 2.3, 2.4j), (1.1j, 1.2, 1.3j, 0.0), (3.1, 3.2j, 3.3, 3.4j)]), resolution=2.0, labels=("s2c1", "s1c1", "s2c2")) FIRST_CHANNELS_FIRST = sumpf.Merge.modes.FIRST_CHANNELS_FIRST assert sumpf.Merge([spectrum1, spectrum2]).output() == spectrum12 assert sumpf.Merge([spectrum2, spectrum1]).output() == spectrum21 assert sumpf.Merge([spectrum1, spectrum2], mode=FIRST_CHANNELS_FIRST).output() == spectrum12 assert sumpf.Merge([spectrum2, spectrum1], mode=FIRST_CHANNELS_FIRST).output() == spectrum21c
def test_subtract(): """Tests the overload of the ``-`` operator.""" spectrum1 = sumpf.Spectrum(channels=numpy.array([(1.0, 0.0, 0.0), (0.0, 2.0, 0.0)]), labels=("one1", "two1")) spectrum2 = sumpf.Spectrum(channels=numpy.array([(1.0, 0.0, 0.0), (0.0, 2.0, 0.0), (0.0, 0.0, 3.0)]), labels=("one2", "two2", "three2")) # test subtracting a number difference = spectrum1 - 3.7 assert difference.resolution() == spectrum1.resolution() assert difference.labels() == spectrum1.labels() assert (difference.channels() == numpy.subtract(spectrum1.channels(), 3.7)).all() assert ((3.7 - spectrum1).channels() == numpy.subtract( 3.7, spectrum1.channels())).all() # test subtracting an array difference = spectrum1 - (1.9, -3.8, 5.5) assert difference.resolution() == spectrum1.resolution() assert difference.labels() == spectrum1.labels() assert (difference.channels() == numpy.subtract(spectrum1.channels(), (1.9, -3.8, 5.5))).all() assert (((1.9, -3.8, 5.5) - spectrum1).channels() == numpy.subtract( (1.9, -3.8, 5.5), spectrum1.channels())).all() # test subtracting a Spectrum with the same number of channels difference = spectrum1 - spectrum1 assert difference.resolution() == spectrum1.resolution() assert difference.labels() == ("Difference", ) * 2 assert (difference.channels() == numpy.zeros( shape=spectrum1.shape())).all() # test subtracting a Spectrum with a higher number of channels difference = spectrum1 - spectrum2 assert difference.resolution() == spectrum1.resolution() assert difference.labels() == ("Difference", ) * 3 assert (difference.channels() == [ numpy.subtract(spectrum1.channels()[0], spectrum2.channels()[0]), numpy.subtract(spectrum1.channels()[1], spectrum2.channels()[1]), numpy.subtract(0.0, spectrum2.channels()[2]) ]).all() assert ((spectrum2 - spectrum1).channels() == [ numpy.subtract(spectrum2.channels()[0], spectrum1.channels()[0]), numpy.subtract(spectrum2.channels()[1], spectrum1.channels()[1]), spectrum2.channels()[2] ]).all() # test subtracting a single channel Spectrum difference = spectrum1 - spectrum2[2] assert difference.resolution() == spectrum1.resolution() assert difference.labels() == ("Difference", ) * 2 assert (difference.channels() == numpy.subtract( spectrum1.channels(), spectrum2.channels()[2])).all() assert ((spectrum2[2] - spectrum1).channels() == numpy.subtract( spectrum2.channels()[2], spectrum1.channels())).all()
def test_divide(): """Tests the overload of the ``/`` operator.""" spectrum1 = sumpf.Spectrum(channels=numpy.array([(1.5, 1.0, 1.0), (1.0, 1.2, 1.0)]), labels=("one1", "two1")) spectrum2 = sumpf.Spectrum(channels=numpy.array([(2.0, 1.0, 1.0), (1.0, 0.5, 1.0), (1.0, 1.0, 0.2)]), labels=("one2", "two2", "three2")) # test dividing by a number quotient = spectrum1 / 3.7 assert quotient.resolution() == spectrum1.resolution() assert quotient.labels() == spectrum1.labels() assert (quotient.channels() == numpy.divide(spectrum1.channels(), 3.7)).all() assert ((3.7 / spectrum1).channels() == numpy.divide( 3.7, spectrum1.channels())).all() # test dividing by an array quotient = spectrum1 / (1.9, -3.8, 5.5) assert quotient.resolution() == spectrum1.resolution() assert quotient.labels() == spectrum1.labels() assert (quotient.channels() == numpy.divide(spectrum1.channels(), (1.9, -3.8, 5.5))).all() assert (((1.9, -3.8, 5.5) / spectrum1).channels() == numpy.divide( (1.9, -3.8, 5.5), spectrum1.channels())).all() # test dividing by a Spectrum with the same number of channels quotient = spectrum1 / spectrum1 assert quotient.resolution() == spectrum1.resolution() assert quotient.labels() == ("Quotient", ) * 2 assert (quotient.channels() == numpy.ones(shape=spectrum1.shape())).all() # test dividing by a Spectrum with a higher number of channels quotient = spectrum1 / spectrum2 assert quotient.resolution() == spectrum1.resolution() assert quotient.labels() == ("Quotient", ) * 3 assert (quotient.channels() == [ numpy.divide(spectrum1.channels()[0], spectrum2.channels()[0]), numpy.divide(spectrum1.channels()[1], spectrum2.channels()[1]), numpy.divide(1.0, spectrum2.channels()[2]) ]).all() assert ((spectrum2 / spectrum1).channels() == [ numpy.divide(spectrum2.channels()[0], spectrum1.channels()[0]), numpy.divide(spectrum2.channels()[1], spectrum1.channels()[1]), spectrum2.channels()[2] ]).all() # test dividing by a single channel Spectrum quotient = spectrum1 / spectrum2[2] assert quotient.resolution() == spectrum1.resolution() assert quotient.labels() == ("Quotient", ) * 2 assert (quotient.channels() == numpy.divide( spectrum1.channels(), spectrum2.channels()[2])).all() assert ((spectrum2[2] / spectrum1).channels() == numpy.divide( spectrum2.channels()[2], spectrum1.channels())).all()
def test_power(): """Tests the overload of the ``**`` operator.""" spectrum1 = sumpf.Spectrum(channels=numpy.array([(1.5 + 4.0j, 1.0, 0.0 + 0.1j), (1.0, -1.2, 1.0 + 1.0j)]), labels=("one1", "two1")) spectrum2 = sumpf.Spectrum(channels=numpy.array([(2.0 + 1.0j, 0.0, -1.0), (1.0 - 0.6j, -0.5, 1.0), (1.0, 1.0, 0.2 - 2.0j)]), labels=("one2", "two2", "three2")) # test computing the power with a number power = spectrum1**3.7 assert power.resolution() == spectrum1.resolution() assert power.labels() == spectrum1.labels() assert (power.channels() == numpy.power(spectrum1.channels(), 3.7)).all() assert ((3.7**spectrum1).channels() == numpy.power( 3.7, spectrum1.channels())).all() # test computing the power with an array power = spectrum1**(1.9, -3.8, 5.5) assert power.resolution() == spectrum1.resolution() assert power.labels() == spectrum1.labels() assert (power.channels() == numpy.power(spectrum1.channels(), (1.9, -3.8, 5.5))).all() assert (((1.9, -3.8, 5.5)**spectrum1).channels() == numpy.power( (1.9, -3.8, 5.5), spectrum1.channels())).all() # test computing the power with a Spectrum with the same number of channels power = spectrum1**spectrum1 assert power.resolution() == spectrum1.resolution() assert power.labels() == ("Power", ) * 2 assert (power.channels() == numpy.power(spectrum1.channels(), spectrum1.channels())).all() # test computing the power with a Spectrum with a higher number of channels power = spectrum1**spectrum2 assert power.resolution() == spectrum1.resolution() assert power.labels() == ("Power", ) * 3 assert (power.channels() == [ numpy.power(spectrum1.channels()[0], spectrum2.channels()[0]), numpy.power(spectrum1.channels()[1], spectrum2.channels()[1]), spectrum2.channels()[2] ]).all() assert ((spectrum2**spectrum1).channels() == [ numpy.power(spectrum2.channels()[0], spectrum1.channels()[0]), numpy.power(spectrum2.channels()[1], spectrum1.channels()[1]), spectrum2.channels()[2] ]).all() # test computing the power with a single channel Spectrum power = spectrum1**spectrum2[2] assert power.resolution() == spectrum1.resolution() assert power.labels() == ("Power", ) * 2 assert (power.channels() == numpy.power(spectrum1.channels(), spectrum2.channels()[2])).all() assert ((spectrum2[2]**spectrum1).channels() == numpy.power( spectrum2.channels()[2], spectrum1.channels())).all()
def test_eq(parameters): """Tests the operator overloads for ``==`` and ``!=``.""" spectrum1 = sumpf.Spectrum(**parameters) spectrum2 = sumpf.Spectrum(**parameters) assert spectrum1 is not spectrum2 assert spectrum1 == spectrum2 if spectrum2.length() > 1: assert spectrum1 != spectrum2[:, 0: -1] # test for a case, where the NumPy comparison of the channels returns a boolean rather than an array of booleans assert spectrum1 != (spectrum2 + spectrum2) * spectrum2 assert spectrum1 != spectrum1.channels()
def test_hash(parameters): """Tests the operator overload for hashing a spectrum with the builtin :func:`hash` function.""" parameters2 = copy.copy(parameters) parameters2["channels"] = numpy.empty(shape=parameters["channels"].shape, dtype=numpy.complex128) parameters2["channels"][:] = parameters["channels"][:] spectrum1 = sumpf.Spectrum(**parameters) spectrum2 = sumpf.Spectrum(**parameters2) spectrum3 = (spectrum2 + spectrum2) * spectrum2 assert spectrum1.channels() is not spectrum2.channels() assert hash(spectrum1) == hash(spectrum2) assert hash(spectrum1) != hash(spectrum3)
def from_rows(frequency_column, data_rows, labels): # pylint: disable=too-many-branches; the branches are not too complicated in this one """Deserializes a spectrum from tabular data. :param frequency_column: a vector with frequency values, that correspond to the rows in the data_rows matrix with the same index. :param data_rows: a matrix, where the rows contain a complex sample for each channel of the spectrum. :param labels: the labels for the channels or an empty tuple. :returns: the deserialized spectrum """ if len(data_rows) and len(data_rows[0]): # pylint: disable=len-as-condition; data_rows can be a NumPy array # determine the resolution sorted_frequency_row = sorted(frequency_column) minimum_frequency = sorted_frequency_row[0] maximum_frequency = sorted_frequency_row[-1] if len(sorted_frequency_row) <= 1: resolution = 0.0 else: resolution = (maximum_frequency - minimum_frequency) / (len(sorted_frequency_row) - 1) # determine the offset, that must be either cropped or filled with zero samples if resolution == 0.0: offset = 0 else: offset = int(round(minimum_frequency / resolution)) # sort the data rows by their corresponding value in the frequency column if numpy.array_equal(frequency_column, sorted_frequency_row): sorted_data_rows = data_rows else: sorted_data_rows = [[e for _, e in sorted(zip(frequency_column, data_row))] for data_row in data_rows] # create the channels if offset == 0: channels = allocate_array(shape=numpy.shape(sorted_data_rows), dtype=numpy.complex128) channels[:] = sorted_data_rows elif offset < 0: channels = allocate_array(shape=numpy.subtract(numpy.shape(sorted_data_rows), (0, offset)), dtype=numpy.complex128) channels[:] = sorted_data_rows[:, offset:] else: channels = allocate_array(shape=numpy.add(numpy.shape(sorted_data_rows), (0, offset)), dtype=numpy.complex128) channels[:, 0:offset] = 0.0 + 0j channels[:, offset:] = sorted_data_rows[:] # extend the labels if necessary if len(labels) < len(channels): labels = tuple(labels) + ("",) * (len(channels) - len(labels)) elif len(labels) > len(channels): labels = labels[0:len(channels)] # create the Spectrum instance return sumpf.Spectrum(channels=channels, resolution=resolution, labels=labels) else: return sumpf.Spectrum()
def test_multiply(): """Tests the overload of the ``*`` operator.""" spectrum1 = sumpf.Spectrum(channels=numpy.array([(1.1, 1.0, 1.0), (1.0, 1.2, 1.0)]), labels=("one1", "two1")) spectrum2 = sumpf.Spectrum(channels=numpy.array([(2.0, 1.0, 1.0), (1.0, 3.0, 1.0), (1.0, 1.0, 4.0)]), labels=("one2", "two2", "three2")) # test multiplying with a number product = spectrum1 * 3.7 assert product.resolution() == spectrum1.resolution() assert product.labels() == spectrum1.labels() assert (product.channels() == numpy.multiply(spectrum1.channels(), 3.7)).all() assert ((3.7 * spectrum1).channels() == product.channels()).all() # test multiplying with an array product = spectrum1 * (1.9, -3.8, 5.5) assert product.resolution() == spectrum1.resolution() assert product.labels() == spectrum1.labels() assert (product.channels() == numpy.multiply(spectrum1.channels(), (1.9, -3.8, 5.5))).all() assert (((1.9, -3.8, 5.5) * spectrum1).channels() == product.channels()).all() # test multiplying with a Spectrum with the same number of channels product = spectrum1 * spectrum1 assert product.resolution() == spectrum1.resolution() assert product.labels() == ("Product", ) * 2 assert (product.channels() == numpy.square(spectrum1.channels())).all() # test multiplying with a Spectrum with a higher number of channels product = spectrum1 * spectrum2 assert product.resolution() == spectrum1.resolution() assert product.labels() == ("Product", ) * 3 assert (product.channels() == [ numpy.multiply(spectrum1.channels()[0], spectrum2.channels()[0]), numpy.multiply(spectrum1.channels()[1], spectrum2.channels()[1]), spectrum2.channels()[2] ]).all() assert ((spectrum2 * spectrum1).channels() == product.channels()).all() # test multiplying with a single channel Spectrum product = spectrum1 * spectrum2[2] assert product.resolution() == spectrum1.resolution() assert product.labels() == ("Product", ) * 2 assert (product.channels() == numpy.multiply( spectrum1.channels(), spectrum2.channels()[2])).all() assert ((spectrum2[2] * spectrum1).channels() == product.channels()).all()
def test_inverse_fourier_transform_results(): """Tests the inverse Fourier transform of a spectrum with trivial examples.""" # an empty spectrum assert sumpf.Spectrum().inverse_fourier_transform().shape() == (1, 0) # a group delay of 1s spectrum = sumpf.Spectrum(channels=numpy.array([ (1.0, numpy.exp(-1j * math.pi), numpy.exp(-2j * math.pi)), (2.0, 2.0, 2.0) ]), resolution=0.5) signal = spectrum.inverse_fourier_transform() assert signal.duration() == 2.0 assert signal.sampling_rate() == 2.0 assert signal.channels()[0] == pytest.approx((0.0, 0.0, 1.0, 0.0)) assert (signal[1].channels() == [(2.0, 0.0, 0.0, 0.0)]).all()
def test_constructor_parameters(parameters): """Tests if the constructor parameters are interpreted correctly and have the expected default values.""" # test an empty Spectrum spectrum = sumpf.Spectrum() assert (spectrum.channels() == [[]]).all() assert spectrum.resolution() == 1.0 assert spectrum.labels() == ("", ) # test a Spectrum with all constructor parameters set channels = parameters["channels"] resolution = parameters["resolution"] labels = tuple(parameters["labels"][0:len(channels)]) + ("", ) * ( len(channels) - len(parameters["labels"])) spectrum = sumpf.Spectrum(**parameters) assert (spectrum.channels() == channels).all() assert spectrum.resolution() == resolution assert spectrum.labels() == labels
def cut_spectrum(input_spectrum, desired_frequency_range): """ Cut the input spectrum to the desired frequency range. It appends zero outside the desired frequency range. :param input_spectrum: the input spectrum to which zero has to be appended outside the desired frequency range :param desired_frequency_range: the desired freqency range :return: the modified spectrum """ channels_ip = [] for ip in input_spectrum.GetChannels(): channel_ip = [] channel_op = [] for n, i in enumerate(ip): if n > desired_frequency_range[0] / input_spectrum.GetResolution() and n < desired_frequency_range[1] / \ input_spectrum.GetResolution(): channel_ip.append(i) else: channel_ip.append(0.0) channel_op.append(0.0) channels_ip.append(tuple(channel_ip)) input_spectrum_modified = sumpf.Spectrum( channels=tuple(channels_ip), resolution=input_spectrum.GetResolution(), labels=input_spectrum.GetLabels()) return input_spectrum_modified
def smooth_filter_kernels(kernels=None, window_size=53, polynomial_order=3): """ Smooth the spectrum of the filter kernels, to make it suitable for curve fitting algorithm. :param kernels: the input filter kernels :type kernels: tuple :return: the smoothened output filter kernels :rtype: tuple """ kernels_smooth = [] for kernel in kernels: kernel_spec = sumpf.modules.FourierTransform(kernel).GetSpectrum() kernel_spec_channel = kernel_spec.GetChannels()[0] kernel_spec_channel_smooth = savitzky_golay(kernel_spec_channel, window_size, polynomial_order) kernel_spec_smooth = sumpf.Spectrum( channels=[ kernel_spec_channel_smooth, ], resolution=kernel_spec.GetResolution(), labels=kernel_spec.GetLabels()) kernel_smooth = sumpf.modules.InverseFourierTransform( kernel_spec_smooth).GetSignal() kernels_smooth.append(kernel_smooth) return kernels_smooth
def linearweighting(input): """ Compute the linearly weighted spectrum. :param input: the input signal or spectrum :type input: sumpf.Signal or sumpf.Spectrum :return: the exponentially weighted sum :rtype: tuple """ if isinstance(input, (sumpf.Signal)): ip = sumpf.modules.FourierTransform(signal=input).GetSpectrum() else: ip = input dummy = 0.0001 while True: dummy = dummy + 0.0001 low = 1 * (dummy**1) high = 1 * (dummy**(len(input) - 1)) if low > 1 and high > 10000: break energy_allchannels = [] for c in ip.GetChannels(): energy_singlechannel = [] c = reversed(c) for i, s in enumerate(c): energy_singlechannel.append((abs(s)) * (1 * (dummy**i))) energy_singlechannel = numpy.asarray(energy_singlechannel)[::-1] energy_allchannels.append(energy_singlechannel) energy_allchannels = sumpf.Spectrum(channels=tuple(energy_allchannels), resolution=ip.GetResolution(), labels=ip.GetLabels()) return energy_allchannels
def test_add(): """Tests the overload of the ``+`` operator.""" spectrum1 = sumpf.Spectrum(channels=numpy.array([(1.0, 0.0, 0.0), (0.0, 2.0, 0.0)]), labels=("one1", "two1")) spectrum2 = sumpf.Spectrum(channels=numpy.array([(1.0, 0.0, 0.0), (0.0, 2.0, 0.0), (0.0, 0.0, 3.0)]), labels=("one2", "two2", "three2")) # test adding a number sum_ = spectrum1 + 3.7 assert sum_.resolution() == spectrum1.resolution() assert sum_.labels() == spectrum1.labels() assert (sum_.channels() == numpy.add(spectrum1.channels(), 3.7)).all() assert ((3.7 + spectrum1).channels() == sum_.channels()).all() # test adding an array sum_ = spectrum1 + (1.9, -3.8, 5.5) assert sum_.resolution() == spectrum1.resolution() assert sum_.labels() == spectrum1.labels() assert (sum_.channels() == numpy.add(spectrum1.channels(), (1.9, -3.8, 5.5))).all() assert (((1.9, -3.8, 5.5) + spectrum1).channels() == sum_.channels()).all() # test adding a Spectrum with the same number of channels sum_ = spectrum1 + spectrum1 assert sum_.resolution() == spectrum1.resolution() assert sum_.labels() == ("Sum", ) * 2 assert (sum_.channels() == numpy.multiply(spectrum1.channels(), 2)).all() # test adding a Spectrum with a higher number of channels sum_ = spectrum1 + spectrum2 assert sum_.resolution() == spectrum1.resolution() assert sum_.labels() == ("Sum", ) * 3 assert (sum_.channels() == [ numpy.add(spectrum1.channels()[0], spectrum2.channels()[0]), numpy.add(spectrum1.channels()[1], spectrum2.channels()[1]), spectrum2.channels()[2] ]).all() assert ((spectrum2 + spectrum1).channels() == sum_.channels()).all() # test adding a single channel Spectrum sum_ = spectrum1 + spectrum2[2] assert sum_.resolution() == spectrum1.resolution() assert sum_.labels() == ("Sum", ) * 2 assert (sum_.channels() == numpy.add(spectrum1.channels(), spectrum2.channels()[2])).all() assert ((spectrum2[2] + spectrum1).channels() == sum_.channels()).all()
def _compare_merge_first_spectrum_first(spectrums, merged): """tests if the merged spectrum's channels are ordered like the input spectrums""" c = 0 resolution = spectrums[0].resolution() for s in spectrums: spectrum = sumpf.Spectrum(channels=s.channels(), resolution=resolution, # take the resolution from the first spectrum labels=s.labels()) # the merged spectrum has a label for each channel, which could be empty stop = s.length() assert merged[c:c + len(spectrum), 0:stop] == spectrum c += len(spectrum) assert c == len(merged)
def exponential_weighting(input_spectrum, base=2): if isinstance(input_spectrum, (sumpf.Signal)): input_spectrum = sumpf.modules.FourierTransform( signal=input_spectrum).GetSpectrum() else: input_spectrum = input_spectrum channels_ip = [] for ip in input_spectrum.GetChannels(): channel_ip = [] for n, i in enumerate(ip): exp = i * (base)**(1.0 / (n + 1) * input_spectrum.GetResolution()) channel_ip.append(exp) channels_ip.append(tuple(channel_ip)) output = sumpf.Spectrum(channels=tuple(channels_ip), resolution=input_spectrum.GetResolution(), labels=input_spectrum.GetLabels()) return output
def spectrum(self, resolution=48000.0 / 4096, length=2049): """Samples the transfer functions with the given resolution and given number of samples and returns the result as a spectrum. :param resolution: the frequency resolution of the resulting spectrum :param length: the number of samples per channel of the resulting spectrum :returns: a :class:`~sumpf.Spectrum` instance """ frequencies = numpy.linspace(0.0, (length - 1) * resolution, length) s = S(frequencies) channels = sumpf_internal.allocate_array(shape=(len( self.__transfer_functions), length), dtype=numpy.complex128) for tf, c in zip(self.__transfer_functions, channels): tf(s, out=c) return sumpf.Spectrum(channels=channels, resolution=resolution, labels=self.__labels)
def _compare_merge_spectrums_first_channel_first(spectrums, merged): """test if the merged spectrum's channels are ordered in a way that the first channels of all input spectrum come first""" resolution = spectrums[0].resolution() spectrums = list(spectrums) c = 0 d = 0 while spectrums: to_remove = [] for s in spectrums: if d < len(s): spectrum = sumpf.Spectrum(channels=s[d].channels(), resolution=resolution, # take the resolution from the first spectrum labels=s[d].labels()) # the merged spectrum has a label for each channel, which could be empty stop = spectrum.length() assert merged[c, 0:stop] == spectrum c += 1 else: to_remove.append(s) for s in to_remove: spectrums.remove(s) d += 1 assert c == len(merged)
def test_getitem_samples(): """Tests the slicing of a spectrum with the ``[]`` overload""" spectrum = sumpf.Spectrum(channels=numpy.array([(1.0, 0.0, 0.0), (0.0, 2.0, 0.0), (0.0, 0.0, 3.0)]), labels=("one", "two", "three")) # integer sliced = spectrum[1, 1] assert (sliced.channels() == [(2.0, )]).all() assert sliced.labels() == ("two", ) # float assert spectrum[:, 0.5] == spectrum[:, 1] # integer slice sliced = spectrum[1:3, 1:3] assert (sliced.channels() == [(2.0, 0.0), (0.0, 3.0)]).all() assert sliced.labels() == ("two", "three") # integer slice with step sliced = spectrum[:, 0:3:2] assert (sliced.channels() == [(1.0, 0.0), (0.0, 0.0), (0.0, 3.0)]).all() assert sliced.labels() == ("one", "two", "three") # incomplete slices assert spectrum[:, :] == spectrum assert spectrum[:2, :1] == spectrum[0:2, 0] assert spectrum[1:, 2:] == spectrum[1:3, 2] assert spectrum[0::2, 0::2] == spectrum[0:3:2, 0:3:2] # float slices assert spectrum[0.33:1.0, 0.0:0.66] == spectrum[1:3, 0:2] assert spectrum[0:3:0.66, 0.0:1.0:0.66] == spectrum[0:3:2, 0:3:2] # negative slices assert spectrum[0:-2, 0:-1] == spectrum[0, 0:2] assert spectrum[-2:, -1:] == spectrum[1:3, 2] sliced = spectrum[::-1, ::-1] assert (sliced.channels() == [(3.0, 0.0, 0.0), (0.0, 2.0, 0.0), (0.0, 0.0, 1.0)]).all() assert sliced.labels() == ("three", "two", "one") assert spectrum[-0.99:-0.01:-0.66, -0.99:-0.01:-0.66] == spectrum[0:3:-2, 0:3:-2]
def output(self): """Computes the merged data set and returns it. :returns: a data set, that contains all channels of the added data sets. """ if not self.__data: raise RuntimeError("Nothing to merge") if len(self.__data) == 1: return next(iter(self.__data.values()) ) # simply return the first and only data set else: first = next(iter(self.__data.values())) number_of_channels = sum(len(s) for s in self.__data.values()) labels = [""] * number_of_channels if isinstance(first, sumpf.Signal): merged_offset = min(s.offset() for s in self.__data.values()) length = max(s.offset() + s.length() for s in self.__data.values()) - merged_offset channels = sumpf_internal.allocate_array( shape=(number_of_channels, length)) for index, channel, offset, label in zip( self.__indices(), (c for d in self.__data.values() for c in d.channels()), (d.offset() for d in self.__data.values() for l in d.channels()), # pylint: disable=line-too-long (l for d in self.__data.values() for l in d.labels())): start = offset - merged_offset stop = start + len(channel) channels[index, 0:start] = 0.0 channels[index, start:stop] = channel channels[index, stop:] = 0.0 labels[index] = label return sumpf.Signal(channels=channels, sampling_rate=first.sampling_rate(), offset=merged_offset, labels=labels) elif isinstance(first, sumpf.Spectrum): length = max(s.length() for s in self.__data.values()) channels = sumpf_internal.allocate_array( shape=(number_of_channels, length), dtype=numpy.complex128) for index, channel, label in zip( self.__indices(), (c for d in self.__data.values() for c in d.channels()), (l for d in self.__data.values() for l in d.labels())): channels[index, 0:len(channel)] = channel channels[index, len(channel):] = 0.0 labels[index] = label return sumpf.Spectrum(channels=channels, resolution=first.resolution(), labels=labels) elif isinstance(first, sumpf.Spectrogram): merged_offset = min(s.offset() for s in self.__data.values()) length = max(s.offset() + s.length() for s in self.__data.values()) - merged_offset number_of_frequencies = max(s.number_of_frequencies() for s in self.__data.values()) channels = sumpf_internal.allocate_array( shape=(number_of_channels, number_of_frequencies, length), dtype=numpy.complex128) channels[:] = 0.0 for index, channel, offset, label in zip( self.__indices(), (c for d in self.__data.values() for c in d.channels()), (d.offset() for d in self.__data.values() for l in d.channels()), # pylint: disable=line-too-long (l for d in self.__data.values() for l in d.labels())): channel_frequencies, channel_length = channel.shape start = offset - merged_offset stop = start + channel_length channels[index, 0:channel_frequencies, start:stop] = channel labels[index] = label return sumpf.Spectrogram(channels=channels, resolution=first.resolution(), sampling_rate=first.sampling_rate(), offset=merged_offset, labels=labels) elif isinstance(first, sumpf.Filter): transfer_functions = [None] * number_of_channels for index, transfer_function, label in zip( self.__indices(), (tf for d in self.__data.values() for tf in d.transfer_functions()), # pylint: disable=line-too-long (l for d in self.__data.values() for l in d.labels())): transfer_functions[index] = transfer_function labels[index] = label return sumpf.Filter(transfer_functions=transfer_functions, labels=labels) else: raise ValueError( f"Cannot merge data sets of type {type(first)}")
def test_absolute(spectrum): """Tests if computing the magnitude of a spectrum yields the expected result.""" assert abs(spectrum) == sumpf.Spectrum(channels=numpy.absolute( spectrum.channels()), resolution=spectrum.resolution(), labels=spectrum.labels())
def from_dict(channels, dictionary): """Deserializes a spectrum from a dictionary.""" return sumpf.Spectrum(channels=channels, resolution=dictionary.get("resolution", 1.0), labels=dictionary.get("labels", ()))
def test_negative(spectrum): """Tests if inverting the phase of a spectrum yields the expected result.""" assert -spectrum == sumpf.Spectrum(channels=numpy.subtract( 0.0, spectrum.channels()), resolution=spectrum.resolution(), labels=spectrum.labels())