diff --git a/src/backscattering_analyzer/__init__.py b/src/backscattering_analyzer/__init__.py index 0f07c25..94a9b30 100644 --- a/src/backscattering_analyzer/__init__.py +++ b/src/backscattering_analyzer/__init__.py @@ -1,9 +1,10 @@ +from __future__ import annotations from numpy.typing import NDArray from numpy import arange from scipy.interpolate import CubicSpline -def interpolate_abciss(signals: tuple["Signal", ...]) -> NDArray: +def interpolate_abciss(signals: tuple[Signal, ...]) -> NDArray: """ return the axis that would be used by the interpolate function """ @@ -15,7 +16,7 @@ def interpolate_abciss(signals: tuple["Signal", ...]) -> NDArray: return arange(start, end, 1 / max(rates)) -def interpolate(signals: tuple["Signal", ...]) -> tuple["Signal", ...]: +def interpolate(signals: tuple[Signal, ...]) -> tuple[Signal, ...]: """ Interpolate multiple signals with a single abciss list, which has the smallest interval and the bigget rate @@ -29,3 +30,6 @@ def interpolate(signals: tuple["Signal", ...]) -> tuple["Signal", ...]: ] return tuple(new_signals) + + +from backscattering_analyzer.signal import Signal # no circular import diff --git a/src/backscattering_analyzer/analyzer.py b/src/backscattering_analyzer/analyzer.py index e599974..a79c4a7 100644 --- a/src/backscattering_analyzer/analyzer.py +++ b/src/backscattering_analyzer/analyzer.py @@ -41,8 +41,9 @@ class Analyzer: file = self.settings.bench_file() self.settings.log("loading bench movement") try: + data = loadtxt(file).T self.bench_movement = Signal( - *loadtxt(file).T, self.settings + data[0], data[1], self.settings ) except OSError: raise Exception("{file} does not exist".format(file=file)) @@ -54,8 +55,9 @@ class Analyzer: file = self.settings.mirror_file() self.settings.log("loading mirror movement") try: + data = loadtxt(file).T self.mirror_movement = Signal( - *loadtxt(file).T, self.settings + data[0], data[1], self.settings ) except OSError: raise Exception("{file} does not exist".format(file=file)) @@ -65,9 +67,10 @@ class Analyzer: Load excited h(t) """ file = self.settings.data_file() - self.setings.log("loading excited h(t)") + self.settings.log("loading excited h(t)") try: - self.data_signal = Signal(*loadtxt(file).T, self.settings) + data = loadtxt(file).T + self.data_signal = Signal(data[0], data[1], self.settings) except OSError: raise Exception("{file} does not exist".format(file=file)) @@ -78,8 +81,9 @@ class Analyzer: file = self.settings.reference_file() self.settings.log("loading reference h(t)") try: + data = loadtxt(file).T self.reference_signal = Signal( - *loadtxt(file).T, self.settings + data[0], data[1], self.settings ) except OSError: raise Exception("{file} does not exist".format(file=file)) @@ -95,16 +99,14 @@ class Analyzer: coupling_values = self.modelisation[ self.settings.coupling_name() ] - self.coupling = array( - [ - Signal( - self.modelisation["freq"][0], - coupling, - self.settings, - ) - for coupling in coupling_values - ] - ) + self.coupling = [ + Signal( + self.modelisation["freq"][0], + coupling, + self.settings, + ) + for coupling in coupling_values + ] except OSError: raise Exception("{file} does not exist".format(file=file)) @@ -130,7 +132,11 @@ class Analyzer: excitation """ result = zeros( - len(interpolate_abciss(self.movement, self.coupling[0])) + len( + interpolate_abciss( + (self.movement.psd(), self.coupling[0].abs()) + ) + ) ) # frequencies depends of psd result, which we do not have yet @@ -150,25 +156,12 @@ class Analyzer: # no need to redefine it each time but simpler here frequencies = factor_n.x - """ - result += ( - sqrt(self.settings.scattering_factor[index]) - * self.settings.wavelength / ( 4 * pi ) - * sqrt( - coupling_n[1]**2 * factor_n[1] - + coupling_d[1]**2 * factor_d[1] - )**2 - ) - """ result += ( sqrt(self.settings.scattering_factor[index]) * self.settings.power_in / self.settings.power_out - * ( - coupling_n[1] * factor_n[1] - + coupling_d[1] * factor_d[1] - ).y + * (coupling_n * factor_n + coupling_d * factor_d).y ) return array( [ diff --git a/src/backscattering_analyzer/settings.py b/src/backscattering_analyzer/settings.py index 7210211..c04ac1e 100644 --- a/src/backscattering_analyzer/settings.py +++ b/src/backscattering_analyzer/settings.py @@ -182,4 +182,4 @@ class Settings: def log(self, message) -> None: if self.verbose: - self.console.log(message) + self.console.log(message, _stack_offset=2) diff --git a/src/backscattering_analyzer/signal.py b/src/backscattering_analyzer/signal.py index 9f69679..f07cb65 100644 --- a/src/backscattering_analyzer/signal.py +++ b/src/backscattering_analyzer/signal.py @@ -64,22 +64,27 @@ class Signal: freq_y = rfft(self.y) index_to_remove = where(abs(freq_x) > cutoff) freq_y[index_to_remove] = 0 - - return Signal( + signal = Signal( self.x, irfft(freq_y), self.settings, ) + return signal + + def plot(self) -> None: + """ + Plot the signal + """ + import matplotlib.pyplot as plt + + plt.plot(self.x, self.y) + plt.show() def abs(self) -> Signal: """ - Abs of the signal (hacky way) + Abs of the signal (alias) """ - return Signal( - self.x, - abs(self.y), - self.settings, - ) + return self.__abs__() def cos(self) -> Signal: """ @@ -106,11 +111,14 @@ class Signal: Substract float or a signal to another """ if isinstance(other, Signal): - signal_1, signal_2 = interpolate((self, other)) + if len(other) != len(self): + signal_1, signal_2 = interpolate((self, other)) + else: + signal_1, signal_2 = self, other return Signal( signal_1.frequencies, - signal_2.value - signal_1.value, + signal_2.y - signal_1.y, self.settings, ) else: @@ -125,11 +133,14 @@ class Signal: Add a float or a signal to another """ if isinstance(other, Signal): - signal_1, signal_2 = interpolate((self, other)) + if len(other) != len(self): + signal_1, signal_2 = interpolate((self, other)) + else: + signal_1, signal_2 = self, other return Signal( signal_1.x, - signal_1 + signal_2, + signal_1.y + signal_2.y, self.settings, ) else: @@ -144,17 +155,20 @@ class Signal: Multiply a signal by a value or another signal """ if isinstance(other, Signal): - signal_1, signal_2 = interpolate((self, other)) + if len(other) != len(self): + signal_1, signal_2 = interpolate((self, other)) + else: + signal_1, signal_2 = self, other return Signal( signal_1.frequencies, - signal_1.value * signal_2.value, + signal_1.y * signal_2.y, self.settings, ) else: return Signal( self.x, - other * self.value, + other * self.y, self.settings, ) @@ -168,3 +182,25 @@ class Signal: self.y, ] ) + + def __abs__(self) -> Signal: + """ + Absolute value of the signal + """ + return Signal( + self.x, + abs(self.y), + self.settings, + ) + + def __getitem__(self, key) -> NDArray: + """ + Get an element of the signal + """ + return self.y[key] + + def __len__(self) -> int: + """ + Get length of a signal + """ + return len(self.x)