def test_merge_signals_manually(): """Tests the merging behavior with manually generated signals.""" signal1 = sumpf.Signal(channels=numpy.array([(1.1, 1.2, 1.3)]), sampling_rate=1.0, offset=1, labels=("s1c1",)) signal2 = sumpf.Signal(channels=numpy.array([(2.1, 2.2, 2.3, 2.4), (3.1, 3.2, 3.3, 3.4)]), sampling_rate=2.0, offset=-4, labels=("s2c1", "s2c2")) signal12 = sumpf.Signal(channels=numpy.array([(0.0, 0.0, 0.0, 0.0, 0.0, 1.1, 1.2, 1.3), (2.1, 2.2, 2.3, 2.4, 0.0, 0.0, 0.0, 0.0), (3.1, 3.2, 3.3, 3.4, 0.0, 0.0, 0.0, 0.0)]), sampling_rate=1.0, offset=-4, labels=("s1c1", "s2c1", "s2c2")) signal21 = sumpf.Signal(channels=numpy.array([(2.1, 2.2, 2.3, 2.4, 0.0, 0.0, 0.0, 0.0), (3.1, 3.2, 3.3, 3.4, 0.0, 0.0, 0.0, 0.0), (0.0, 0.0, 0.0, 0.0, 0.0, 1.1, 1.2, 1.3)]), sampling_rate=2.0, offset=-4, labels=("s2c1", "s2c2", "s1c1")) signal21c = sumpf.Signal(channels=numpy.array([(2.1, 2.2, 2.3, 2.4, 0.0, 0.0, 0.0, 0.0), (0.0, 0.0, 0.0, 0.0, 0.0, 1.1, 1.2, 1.3), (3.1, 3.2, 3.3, 3.4, 0.0, 0.0, 0.0, 0.0)]), sampling_rate=2.0, offset=-4, labels=("s2c1", "s1c1", "s2c2")) FIRST_CHANNELS_FIRST = sumpf.Merge.modes.FIRST_CHANNELS_FIRST assert sumpf.Merge([signal1, signal2]).output() == signal12 assert sumpf.Merge([signal2, signal1]).output() == signal21 assert sumpf.Merge([signal1, signal2], mode=FIRST_CHANNELS_FIRST).output() == signal12 assert sumpf.Merge([signal2, signal1], mode=FIRST_CHANNELS_FIRST).output() == signal21c
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_connectors_with_spectrums(spectrum1, spectrum2, spectrum3, spectrum4): """tests the connector functionality of the Merge class.""" merger = sumpf.Merge([spectrum1]) p1 = connectors.blocks.PassThrough().output.connect(merger.add) merger.add(spectrum3) p2 = connectors.blocks.PassThrough().input.connect(merger.output) p3 = connectors.blocks.PassThrough().output.connect(merger.set_mode) for mode in sumpf.Merge.modes: p1.input(spectrum2) p3.input(mode) assert p2.output() == sumpf.Merge([spectrum1, spectrum2, spectrum3], mode=mode).output() p1.input(spectrum4) assert p2.output() == sumpf.Merge([spectrum1, spectrum4, spectrum3], mode=mode).output()
def test_connectors_with_filters(filter1, filter2, filter3, filter4): """tests the connector functionality of the Merge class.""" merger = sumpf.Merge([filter1]) p1 = connectors.blocks.PassThrough().output.connect(merger.add) merger.add(filter3) p2 = connectors.blocks.PassThrough().input.connect(merger.output) p3 = connectors.blocks.PassThrough().output.connect(merger.set_mode) for mode in sumpf.Merge.modes: p1.input(filter2) p3.input(mode) assert p2.output() == sumpf.Merge([filter1, filter2, filter3], mode=mode).output() p1.input(filter4) assert p2.output() == sumpf.Merge([filter1, filter4, filter3], mode=mode).output()
def test_connectors_with_spectrograms(spectrogram1, spectrogram2, spectrogram3, spectrogram4): """tests the connector functionality of the Merge class.""" spectrogram1, spectrogram2, spectrogram3, spectrogram4 = _sanitize_offsets((spectrogram1, spectrogram2, spectrogram3, spectrogram4)) # pylint: disable=unbalanced-tuple-unpacking,line-too-long merger = sumpf.Merge([spectrogram1]) p1 = connectors.blocks.PassThrough().output.connect(merger.add) merger.add(spectrogram3) p2 = connectors.blocks.PassThrough().input.connect(merger.output) p3 = connectors.blocks.PassThrough().output.connect(merger.set_mode) for mode in sumpf.Merge.modes: p1.input(spectrogram2) p3.input(mode) assert p2.output() == sumpf.Merge([spectrogram1, spectrogram2, spectrogram3], mode=mode).output() p1.input(spectrogram4) assert p2.output() == sumpf.Merge([spectrogram1, spectrogram4, spectrogram3], mode=mode).output()
def test_merge_filters_manually(): """Tests the merging behavior with manually generated filters.""" filter1 = sumpf.Filter(transfer_functions=(sumpf.Filter.Constant(4.9) / sumpf.Filter.Polynomial((0.2, 3.9, 1.1)),), labels=("f1c1",)) filter2 = sumpf.Filter(transfer_functions=(sumpf.Filter.Exp(12.1), abs(sumpf.Filter.Polynomial((-2.2, 1.2)))), labels=("f2c1", "f2c2")) filter12 = sumpf.Filter(transfer_functions=(sumpf.Filter.Constant(4.9) / sumpf.Filter.Polynomial((0.2, 3.9, 1.1)), sumpf.Filter.Exp(12.1), abs(sumpf.Filter.Polynomial((-2.2, 1.2)))), labels=("f1c1", "f2c1", "f2c2")) filter21 = sumpf.Filter(transfer_functions=(sumpf.Filter.Exp(12.1), abs(sumpf.Filter.Polynomial((-2.2, 1.2))), sumpf.Filter.Constant(4.9) / sumpf.Filter.Polynomial((0.2, 3.9, 1.1))), labels=("f2c1", "f2c2", "f1c1")) filter21c = sumpf.Filter(transfer_functions=(sumpf.Filter.Exp(12.1), sumpf.Filter.Constant(4.9) / sumpf.Filter.Polynomial((0.2, 3.9, 1.1)), abs(sumpf.Filter.Polynomial((-2.2, 1.2)))), labels=("f2c1", "f1c1", "f2c2")) FIRST_CHANNELS_FIRST = sumpf.Merge.modes.FIRST_CHANNELS_FIRST assert sumpf.Merge([filter1, filter2]).output() == filter12 assert sumpf.Merge([filter2, filter1]).output() == filter21 assert sumpf.Merge([filter1, filter2], mode=FIRST_CHANNELS_FIRST).output() == filter12 assert sumpf.Merge([filter2, filter1], mode=FIRST_CHANNELS_FIRST).output() == filter21c
def test_scaling_factor(window_classes, plateau, sampling_rate, length, symmetric, overlap): """tests the internal scaling_factor function by comparing it to the scaling_factor method of the window signals.""" overlap = overlap(length) windows = [ c(plateau=plateau(length), sampling_rate=sampling_rate, length=length, symmetric=symmetric) for c in window_classes ] signal = sumpf.Merge(windows).output() reference = numpy.array([w.scaling_factor(overlap) for w in windows]) assert numpy.array_equal(sumpf_internal.scaling_factor(signal, overlap), reference)
def test_merge_filter_first_channel_first(filters, index): """Tests the merging with the FIRST_CHANNEL_FIRST mode.""" # add a single filter merger = sumpf.Merge(filters[0:1], mode=sumpf.Merge.modes.FIRST_CHANNELS_FIRST) assert merger.output() == filters[0] # merge multiple filter filter_ids = [merger.add(s) for s in filters[1:]] _compare_merge_filters_first_channel_first(filters=filters, merged=merger.output()) # replace one filter if index >= len(filter_ids): index = index % len(filter_ids) filter_id = filter_ids[index] merger.replace(filter_id, filters[0]) _compare_merge_filters_first_channel_first(filters=filters[0:index + 1] + [filters[0]] + filters[index + 2:], merged=merger.output()) # remove one filter merger.remove(filter_id) _compare_merge_filters_first_channel_first(filters=filters[0:index + 1] + filters[index + 2:], merged=merger.output())
def test_merge_first_filter_first(filters, index): """Tests the merging with the FIRST_DATASET_FIRST mode, which is the default.""" # add a single filter merger = sumpf.Merge(filters[0:1]) assert merger.output() == filters[0] # merge multiple filters filter_ids = [merger.add(s) for s in filters[1:]] _compare_merge_first_filter_first(filters=filters, merged=merger.output()) # replace one filter if index >= len(filter_ids): index = index % len(filter_ids) filter_id = filter_ids[index] merger.replace(filter_id, filters[0]) _compare_merge_first_filter_first(filters=filters[0:index + 1] + [filters[0]] + filters[index + 2:], merged=merger.output()) # remove one filter merger.remove(filter_id) _compare_merge_first_filter_first(filters=filters[0:index + 1] + filters[index + 2:], merged=merger.output())
def test_merge_first_spectrum_first(spectrums, index): """Tests the merging with the FIRST_DATASET_FIRST mode, which is the default.""" # add a single spectrum merger = sumpf.Merge(spectrums[0:1]) assert merger.output() == spectrums[0] # merge multiple spectrums spectrum_ids = [merger.add(s) for s in spectrums[1:]] _compare_merge_first_spectrum_first(spectrums=spectrums, merged=merger.output()) # replace one spectrum if index >= len(spectrum_ids): index = index % len(spectrum_ids) spectrum_id = spectrum_ids[index] merger.replace(spectrum_id, spectrums[0]) _compare_merge_first_spectrum_first(spectrums=spectrums[0:index + 1] + [spectrums[0]] + spectrums[index + 2:], merged=merger.output()) # remove one spectrum merger.remove(spectrum_id) _compare_merge_first_spectrum_first(spectrums=spectrums[0:index + 1] + spectrums[index + 2:], merged=merger.output())
def test_merge_signals_first_channel_first(signals, index): """Tests the merging with the FIRST_CHANNEL_FIRST mode.""" signals = _sanitize_offsets(signals) # add a single signal merger = sumpf.Merge(signals[0:1], mode=sumpf.Merge.modes.FIRST_CHANNELS_FIRST) assert merger.output() == signals[0] # merge multiple signals signal_ids = [merger.add(s) for s in signals[1:]] _compare_merge_signals_first_channel_first(signals=signals, merged=merger.output()) # replace one signal if index >= len(signal_ids): index = index % len(signal_ids) signal_id = signal_ids[index] merger.replace(signal_id, signals[0]) _compare_merge_signals_first_channel_first(signals=signals[0:index + 1] + [signals[0]] + signals[index + 2:], merged=merger.output()) # remove one signal merger.remove(signal_id) _compare_merge_signals_first_channel_first(signals=signals[0:index + 1] + signals[index + 2:], merged=merger.output())
def test_merge_spectrums_first_channel_first(spectrums, index): """Tests the merging with the FIRST_CHANNEL_FIRST mode.""" # add a single spectrum merger = sumpf.Merge(spectrums[0:1], mode=sumpf.Merge.modes.FIRST_CHANNELS_FIRST) assert merger.output() == spectrums[0] # merge multiple spectrums spectrum_ids = [merger.add(s) for s in spectrums[1:]] _compare_merge_spectrums_first_channel_first(spectrums=spectrums, merged=merger.output()) # replace one spectrum if index >= len(spectrum_ids): index = index % len(spectrum_ids) spectrum_id = spectrum_ids[index] merger.replace(spectrum_id, spectrums[0]) _compare_merge_spectrums_first_channel_first(spectrums=(spectrums[0:index + 1] + [spectrums[0]] + spectrums[index + 2:]), merged=merger.output()) # remove one spectrum merger.remove(spectrum_id) _compare_merge_spectrums_first_channel_first(spectrums=spectrums[0:index + 1] + spectrums[index + 2:], merged=merger.output())
def test_convolve_with_multiple_channels(signal1, signal2, mode): # pylint: disable=too-many-statements; this function is long, but not too complex """Tests the convolution of two multi-channel signals and the convolution of a multi-channel signal with a two dimensional array.""" # make sure, the signals have multiple channels signal1 = sumpf.Merge([signal1, signal1]).output() signal2 = sumpf.Merge([signal2, signal2]).output() number_of_channels = min(len(signal1), len(signal2)) # test general properties of the convolution with a signal signal_convolution = signal1.convolve(signal2, mode=mode) assert signal_convolution.sampling_rate() == signal1.sampling_rate() assert len(signal_convolution) == number_of_channels assert signal_convolution.labels() == ( "Convolution", ) * len(signal_convolution) # test general properties of the convolution with an array array_convolution = signal1.convolve(signal2.channels(), mode=mode) assert array_convolution.sampling_rate() == signal1.sampling_rate() assert len(array_convolution) == number_of_channels assert array_convolution.labels() == signal1.labels( )[0:len(array_convolution)] # test properties, that are specific to the mode if mode == sumpf.Signal.convolution_modes.FULL: reference = numpy.empty(shape=(number_of_channels, signal1.length() + signal2.length() - 1)) for r, a, b in zip(reference, signal1.channels(), signal2.channels()): r[:] = numpy.convolve(a, b, mode="full") assert (signal_convolution.channels() == reference).all() assert (array_convolution.channels() == reference).all() assert signal_convolution.offset( ) == signal1.offset() + signal2.offset() assert array_convolution.offset() == signal1.offset() elif mode == sumpf.Signal.convolution_modes.SAME: reference = numpy.empty( shape=(number_of_channels, max(signal1.length(), signal2.length()))) for r, a, b in zip(reference, signal1.channels(), signal2.channels()): r[:] = numpy.convolve(a, b, mode="same") o = signal1.offset() + (min(signal1.length(), signal2.length()) - 1) // 2 assert (signal_convolution.channels() == reference).all() assert (array_convolution.channels() == reference).all() assert signal_convolution.offset() == o + signal2.offset() assert array_convolution.offset() == o elif mode == sumpf.Signal.convolution_modes.VALID: reference = numpy.empty( shape=(number_of_channels, abs(signal1.length() - signal2.length()) + 1)) for r, a, b in zip(reference, signal1.channels(), signal2.channels()): r[:] = numpy.convolve(a, b, mode="valid") o = signal1.offset() + min(signal1.length(), signal2.length()) - 1 assert (signal_convolution.channels() == reference).all() assert (array_convolution.channels() == reference).all() assert signal_convolution.offset() == o + signal2.offset() assert array_convolution.offset() == o elif mode == sumpf.Signal.convolution_modes.SPECTRUM: length = max(signal1.length(), signal2.length()) padded1 = signal1[0:number_of_channels].pad(length if length % 2 == 0 else length + 1) padded2 = signal2[0:number_of_channels].pad(length if length % 2 == 0 else length + 1) spectrum1 = padded1.shift(None).fourier_transform() spectrum2 = padded2.shift(None).fourier_transform() reference = (spectrum1 * spectrum2).inverse_fourier_transform()[:, 0:length] assert (signal_convolution.channels() == reference.channels()).all() assert (array_convolution.channels() == reference.channels()).all() assert signal_convolution.offset( ) == signal1.offset() + signal2.offset() assert array_convolution.offset() == signal1.offset() elif mode == sumpf.Signal.convolution_modes.SPECTRUM_PADDED: length = signal1.length() + signal2.length() - 1 padded1 = signal1[0:number_of_channels].pad(length + 2 if length % 2 == 0 else length + 1) padded2 = signal2[0:number_of_channels].pad(length + 2 if length % 2 == 0 else length + 1) spectrum1 = padded1.shift(None).fourier_transform() spectrum2 = padded2.shift(None).fourier_transform() reference = (spectrum1 * spectrum2).inverse_fourier_transform()[:, 0:length] assert (signal_convolution.channels() == reference.channels()).all() assert (array_convolution.channels() == reference.channels()).all() assert signal_convolution.offset( ) == signal1.offset() + signal2.offset() assert array_convolution.offset() == signal1.offset() else: raise RuntimeError(f"Unknown mode: {mode}")
def test_correlate_with_multiple_channels( signal1, signal2, mode): # noqa: C901; this function is long, but not too complex # pylint: disable=too-many-branches,too-many-statements,line-too-long """Tests the correlation of two multi-channel signals and the correlation of a multi-channel signal with a two dimensional array.""" # make sure, the signals have multiple channels signal1 = sumpf.Merge([signal1, signal1]).output() signal2 = sumpf.Merge([signal2, signal2]).output() number_of_channels = min(len(signal1), len(signal2)) # test general properties of the correlation with a signal signal_correlation = signal1.correlate(signal2, mode=mode) assert signal_correlation.sampling_rate() == signal1.sampling_rate() assert len(signal_correlation) == number_of_channels assert signal_correlation.labels() == ( "Correlation", ) * len(signal_correlation) # test general properties of the correlation with an array array_correlation = signal1.correlate(signal2.channels(), mode=mode) assert array_correlation.sampling_rate() == signal1.sampling_rate() assert len(array_correlation) == number_of_channels assert array_correlation.labels() == signal1.labels( )[0:len(array_correlation)] # test properties, that are specific to the mode if mode == sumpf.Signal.convolution_modes.FULL: reference = numpy.empty(shape=(number_of_channels, signal1.length() + signal2.length() - 1)) for r, a, b in zip(reference, signal1.channels(), signal2.channels()): r[:] = numpy.correlate(a, b, mode="full")[::-1] assert (signal_correlation.channels() == reference).all() assert (array_correlation.channels() == reference).all() assert signal_correlation.offset( ) == signal2.offset() - signal1.offset() - signal1.length() + 1 assert array_correlation.offset( ) == -signal1.offset() - signal1.length() + 1 elif mode == sumpf.Signal.convolution_modes.SAME: result_length = max(signal1.length(), signal2.length()) reference = numpy.empty(shape=(number_of_channels, result_length)) for r, a, b in zip(reference, signal1.channels(), signal2.channels()): r[:] = numpy.convolve(a[::-1], b, mode="same") o = -signal1.offset() + signal2.length() - result_length - (min( signal1.length(), signal2.length())) // 2 assert (signal_correlation.channels() == reference).all() assert (array_correlation.channels() == reference).all() assert signal_correlation.offset() == o + signal2.offset() assert array_correlation.offset() == o elif mode == sumpf.Signal.convolution_modes.VALID: result_length = abs(signal1.length() - signal2.length()) + 1 reference = numpy.empty(shape=(number_of_channels, result_length)) for r, a, b in zip(reference, signal1.channels(), signal2.channels()): r[:] = numpy.correlate(a, b, mode="valid")[::-1] o = -signal1.offset() - (signal1.length() - signal2.length() + result_length) // 2 assert (signal_correlation.channels() == reference).all() assert (array_correlation.channels() == reference).all() assert signal_correlation.offset() == o + signal2.offset() assert array_correlation.offset() == o elif mode == sumpf.Signal.convolution_modes.SPECTRUM: length = max(signal1.length(), signal2.length()) if length % 2 == 1: padded_length = length + 1 padded1 = signal1[0:number_of_channels].shift( padded_length - signal1.length(), sumpf.Signal.shift_modes.PAD) padded2 = signal2[0:number_of_channels].pad(padded_length) elif signal1.length() < length: padded1 = signal1[0:number_of_channels].shift( length - signal1.length(), sumpf.Signal.shift_modes.PAD).shift( 1, sumpf.Signal.shift_modes.CYCLE) padded2 = signal2[0:number_of_channels] elif signal2.length() < length: padded1 = signal1[0:number_of_channels] padded2 = signal2[0:number_of_channels].pad(length).shift( -1, sumpf.Signal.shift_modes.CYCLE) else: padded1 = signal1[0:number_of_channels] padded2 = signal2[0:number_of_channels].shift( -1, sumpf.Signal.shift_modes.CYCLE) spectrum1 = padded1.shift(None).fourier_transform().conjugate() spectrum2 = padded2.shift(None).fourier_transform() reference = (spectrum1 * spectrum2).inverse_fourier_transform()[:, -length:] assert (signal_correlation.channels() == reference.channels()).all() assert (array_correlation.channels() == reference.channels()).all() assert signal_correlation.offset( ) == signal2.offset() - signal1.offset() - signal1.length() + 1 assert array_correlation.offset( ) == -signal1.offset() - signal1.length() + 1 elif mode == sumpf.Signal.convolution_modes.SPECTRUM_PADDED: length = signal1.length() + signal2.length() - 1 if length % 2 == 0: padded_length = length + 2 padded1 = signal1[0:number_of_channels].shift( 2, sumpf.Signal.shift_modes.PAD).pad(padded_length) else: padded_length = length + 1 padded1 = signal1[0:number_of_channels].shift( 1, sumpf.Signal.shift_modes.PAD).pad(padded_length) padded2 = signal2[0:number_of_channels].shift( padded_length - signal2.length(), sumpf.Signal.shift_modes.PAD) spectrum1 = padded1.shift(None).fourier_transform().conjugate() spectrum2 = padded2.shift(None).fourier_transform() reference = (spectrum1 * spectrum2).inverse_fourier_transform()[:, 0:length] assert (signal_correlation.channels() == reference.channels()).all() assert (array_correlation.channels() == reference.channels()).all() assert signal_correlation.offset( ) == signal2.offset() - signal1.offset() - signal1.length() + 1 assert array_correlation.offset( ) == -signal1.offset() - signal1.length() + 1 else: raise RuntimeError(f"Unknown mode: {mode}")
def test_harmonic_impulse_response(): """Does some trivial tests with the harmonic_impulse_response method""" # create a sweep, an inverse sweep and a distorted version of the sweep sweep = sumpf.ExponentialSweep(start_frequency=20.0, stop_frequency=7800.0, sampling_rate=48000, length=2**14) inverse = sumpf.InverseExponentialSweep(start_frequency=20.0, stop_frequency=7800.0, sampling_rate=48000, length=2**14) # pylint: disable=line-too-long distorted = 0.5 * sweep**3 - 0.6 * sweep**2 + 0.1 * sweep + 0.02 lowpass = sumpf.ButterworthFilter(cutoff_frequency=1000.0, order=16, highpass=False) highpass = sumpf.ButterworthFilter(cutoff_frequency=1000.0, order=16, highpass=True) response = distorted * highpass * lowpass # test with non-circular deconvolution impulse_response = response.convolve( inverse, mode=sumpf.Signal.convolution_modes.SPECTRUM_PADDED) h1 = sweep.harmonic_impulse_response(impulse_response=impulse_response, harmonic=1) h2 = sweep.harmonic_impulse_response(impulse_response=impulse_response, harmonic=2, length=h1.length()) h3 = sweep.harmonic_impulse_response(impulse_response=impulse_response, harmonic=3) assert h1.length() == h2.length( ) # check if the length parameter has worked assert h3.length() < h2.length( ) # the impulse responses of the higher order harmonics are shorter harmonics = sumpf.Merge([h1, h2, h3]).output() spectrum = harmonics.fourier_transform() magnitude = spectrum.magnitude() max_indices = magnitude.argmax(axis=1) assert max(max_indices) - min( max_indices ) <= 1 # the maximums of all harmonics' transfer functions should be roughly the same assert max_indices.mean() * spectrum.resolution() == pytest.approx( 1000.0, rel=1e-3) # the maximums should be around 1000Hz # test with circular deconvolution impulse_response = response.convolve( inverse, mode=sumpf.Signal.convolution_modes.SPECTRUM).shift(None) h1 = sweep.harmonic_impulse_response(impulse_response=impulse_response, harmonic=1, length=2048) h2 = sweep.harmonic_impulse_response(impulse_response=impulse_response, harmonic=2, length=2048) h3 = sweep.harmonic_impulse_response(impulse_response=impulse_response, harmonic=3, length=2048) assert h1.length() == 2048 assert h2.length() == 2048 assert h3.length() == 2048 harmonics = sumpf.Merge([h1, h2, h3]).output() spectrum = harmonics.fourier_transform() magnitude = spectrum.magnitude() max_indices = magnitude.argmax(axis=1) assert max(max_indices) - min( max_indices ) <= 5 # the maximums of all harmonics' transfer functions should be roughly the same assert max_indices.mean() * spectrum.resolution() == pytest.approx( 1000.0, rel=8e-3) # the maximums should be around 1000Hz
def test_merge_spectrograms_manually(): """Tests the merging behavior with manually generated spectrograms.""" spectrogram1 = sumpf.Spectrogram(channels=numpy.array([([1.11j, 1.12, 1.13j], [1.21j, 1.22, 1.23j], [1.31j, 1.32, 1.33j])]), resolution=1.0, sampling_rate=2.0, offset=1, labels=("s1c1",)) spectrogram2 = sumpf.Spectrogram(channels=numpy.array([([2.11, 2.12j, 2.13, 2.14j], [2.21, 2.22j, 2.23, 2.24j]), ([3.11, 3.12j, 3.13, 3.14j], [3.21, 3.22j, 3.23, 3.24j])]), resolution=2.0, sampling_rate=3.0, offset=-4, labels=("s2c1", "s2c2")) spectrogram12 = sumpf.Spectrogram(channels=numpy.array([([0.0, 0.0, 0.0, 0.0, 0.0, 1.11j, 1.12, 1.13j], [0.0, 0.0, 0.0, 0.0, 0.0, 1.21j, 1.22, 1.23j], [0.0, 0.0, 0.0, 0.0, 0.0, 1.31j, 1.32, 1.33j]), ([2.11, 2.12j, 2.13, 2.14j, 0.0, 0.0, 0.0, 0.0], [2.21, 2.22j, 2.23, 2.24j, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]), ([3.11, 3.12j, 3.13, 3.14j, 0.0, 0.0, 0.0, 0.0], [3.21, 3.22j, 3.23, 3.24j, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0])]), resolution=1.0, sampling_rate=2.0, offset=-4, labels=("s1c1", "s2c1", "s2c2")) spectrogram21 = sumpf.Spectrogram(channels=numpy.array([([2.11, 2.12j, 2.13, 2.14j, 0.0, 0.0, 0.0, 0.0], [2.21, 2.22j, 2.23, 2.24j, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]), ([3.11, 3.12j, 3.13, 3.14j, 0.0, 0.0, 0.0, 0.0], [3.21, 3.22j, 3.23, 3.24j, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]), ([0.0, 0.0, 0.0, 0.0, 0.0, 1.11j, 1.12, 1.13j], [0.0, 0.0, 0.0, 0.0, 0.0, 1.21j, 1.22, 1.23j], [0.0, 0.0, 0.0, 0.0, 0.0, 1.31j, 1.32, 1.33j])]), resolution=2.0, sampling_rate=3.0, offset=-4, labels=("s2c1", "s2c2", "s1c1")) spectrogram21c = sumpf.Spectrogram(channels=numpy.array([([2.11, 2.12j, 2.13, 2.14j, 0.0, 0.0, 0.0, 0.0], [2.21, 2.22j, 2.23, 2.24j, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]), ([0.0, 0.0, 0.0, 0.0, 0.0, 1.11j, 1.12, 1.13j], [0.0, 0.0, 0.0, 0.0, 0.0, 1.21j, 1.22, 1.23j], [0.0, 0.0, 0.0, 0.0, 0.0, 1.31j, 1.32, 1.33j]), ([3.11, 3.12j, 3.13, 3.14j, 0.0, 0.0, 0.0, 0.0], [3.21, 3.22j, 3.23, 3.24j, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0])]), resolution=2.0, sampling_rate=3.0, offset=-4, labels=("s2c1", "s1c1", "s2c2")) FIRST_CHANNELS_FIRST = sumpf.Merge.modes.FIRST_CHANNELS_FIRST assert sumpf.Merge([spectrogram1, spectrogram2]).output() == spectrogram12 assert sumpf.Merge([spectrogram2, spectrogram1]).output() == spectrogram21 assert sumpf.Merge([spectrogram1, spectrogram2], mode=FIRST_CHANNELS_FIRST).output() == spectrogram12 assert sumpf.Merge([spectrogram2, spectrogram1], mode=FIRST_CHANNELS_FIRST).output() == spectrogram21c
def test_empty(): """Tests the behavior when no data is added.""" with pytest.raises(RuntimeError): sumpf.Merge().output()