256 lines
7.5 KiB
Python
256 lines
7.5 KiB
Python
from sys import argv
|
|
from backscattering_analyzer.settings import Settings
|
|
from backscattering_analyzer.signal import Signal
|
|
from backscattering_analyzer import (
|
|
compute_light,
|
|
fit_compute_light,
|
|
opt_compute_light,
|
|
interpolate,
|
|
)
|
|
from numpy import loadtxt, logspace, pi
|
|
from scipy.io.matlab import loadmat
|
|
from scipy.optimize import Bounds, minimize
|
|
|
|
|
|
class Analyzer:
|
|
"""
|
|
Utility class to study backscattering light in VIRGO
|
|
"""
|
|
|
|
def __init__(
|
|
self, arguments: None | list[str] | str = None
|
|
) -> None:
|
|
if arguments is None:
|
|
options = []
|
|
elif isinstance(arguments, str):
|
|
options = arguments.split(" ")
|
|
else:
|
|
options = arguments
|
|
self.settings = Settings(argv[1:] + options)
|
|
self.load()
|
|
self.process_movement()
|
|
self.compute_light()
|
|
|
|
def load(self):
|
|
"""
|
|
Load all data
|
|
"""
|
|
self.settings.log("Load all data")
|
|
try:
|
|
self.load_bench()
|
|
self.load_mirror()
|
|
self.load_data()
|
|
self.load_reference()
|
|
self.load_coupling()
|
|
except Exception:
|
|
raise Exception("An error occured during data loading")
|
|
|
|
def load_bench(self):
|
|
"""
|
|
Load bench movement
|
|
"""
|
|
file = self.settings.bench_file()
|
|
self.settings.log("loading bench movement")
|
|
try:
|
|
data = loadtxt(file).T
|
|
self.bench_movement = (
|
|
Signal(data[0], data[1], self.settings) * 1e-6
|
|
) # um
|
|
except OSError:
|
|
raise Exception("{file} does not exist".format(file=file))
|
|
|
|
def load_mirror(self):
|
|
"""
|
|
Load mirror movement
|
|
"""
|
|
file = self.settings.mirror_file()
|
|
self.settings.log("loading mirror movement")
|
|
try:
|
|
data = loadtxt(file).T
|
|
self.mirror_movement = (
|
|
Signal(data[0], data[1], self.settings) * 1e-6
|
|
)
|
|
except OSError:
|
|
raise Exception("{file} does not exist".format(file=file))
|
|
|
|
def load_data(self):
|
|
"""
|
|
Load excited h(t)
|
|
"""
|
|
file = self.settings.data_file()
|
|
self.settings.log("loading excited h(t)")
|
|
try:
|
|
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))
|
|
|
|
def load_reference(self):
|
|
"""
|
|
Load reference h(t)
|
|
"""
|
|
file = self.settings.reference_file()
|
|
self.settings.log("loading reference h(t)")
|
|
try:
|
|
data = loadtxt(file).T
|
|
self.reference_signal = Signal(
|
|
data[0], data[1], self.settings
|
|
)
|
|
except OSError:
|
|
raise Exception("{file} does not exist".format(file=file))
|
|
|
|
def load_coupling(self):
|
|
"""
|
|
Load modelisation coupling data
|
|
"""
|
|
file = self.settings.modelisation_file()
|
|
self.settings.log("loading matlab modelisation data")
|
|
try:
|
|
self.modelisation = loadmat(file)
|
|
coupling_values = self.modelisation[
|
|
self.settings.coupling_name()
|
|
]
|
|
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))
|
|
|
|
def process_movement(self):
|
|
"""
|
|
Clean and compute relative movement between the bench and the
|
|
miror
|
|
"""
|
|
self.settings.log("computing relative movement")
|
|
|
|
self.movement = (
|
|
(
|
|
self.bench_movement * self.settings.calib_bench
|
|
- self.mirror_movement * self.settings.calib_mirror
|
|
)
|
|
.detrend("linear")
|
|
.low_pass_filter(5 * self.settings.vibration_frequency)
|
|
)
|
|
|
|
def compute_light(self) -> None:
|
|
"""
|
|
Compute projection with current bench excitation
|
|
"""
|
|
self.projection = compute_light(
|
|
scatter_factor=self.settings.scattering_factor,
|
|
coupling=self.coupling,
|
|
movement=self.movement,
|
|
wavelength=self.settings.wavelength,
|
|
power_in=self.settings.power_in,
|
|
power_out=self.settings.power_out,
|
|
)
|
|
|
|
def fit_scatter_factor(self, guess: None | float = None) -> float:
|
|
"""
|
|
Find the best scatter factor (first order only) in the given
|
|
range
|
|
"""
|
|
if guess is None:
|
|
guess = self.settings.scattering_factor[0]
|
|
phase = 4 * pi / self.settings.wavelength
|
|
factor_n = (self.movement * phase).sin().psd().sqrt()
|
|
coupling_n = self.coupling[0].abs()
|
|
factor_d = (self.movement * phase).cos().psd().sqrt()
|
|
coupling_d = self.coupling[1].abs()
|
|
|
|
coupling_d = coupling_d.cut_x(
|
|
10, 200
|
|
) # cut signal between 10 and 200 Hz
|
|
|
|
factor_n, coupling_n, factor_d, coupling_d, data, reference = (
|
|
interpolate(
|
|
(
|
|
factor_n,
|
|
coupling_n,
|
|
factor_d,
|
|
coupling_d,
|
|
self.data_signal.psd().sqrt(),
|
|
self.reference_signal.psd().sqrt(),
|
|
)
|
|
)
|
|
)
|
|
|
|
bounds = Bounds(1e-30, 1e-3)
|
|
min_result = minimize(
|
|
fit_compute_light,
|
|
guess,
|
|
(
|
|
factor_n,
|
|
coupling_n,
|
|
factor_d,
|
|
coupling_d,
|
|
self.settings.power_in,
|
|
self.settings.power_out,
|
|
data,
|
|
reference,
|
|
),
|
|
method="Powell",
|
|
bounds=bounds,
|
|
)
|
|
|
|
if not min_result.success:
|
|
raise Exception(min_result.message)
|
|
|
|
self.settings.log(
|
|
"found the best scattering factor in {} iterations".format(
|
|
min_result.nit
|
|
)
|
|
)
|
|
|
|
import matplotlib.pyplot as plt
|
|
|
|
projection = Signal(
|
|
factor_n.x,
|
|
opt_compute_light(
|
|
scatter_factor=min_result.x,
|
|
factor_n=factor_n,
|
|
coupling_n=coupling_n,
|
|
factor_d=factor_d,
|
|
coupling_d=coupling_d,
|
|
power_in=self.settings.power_in,
|
|
power_out=self.settings.power_out,
|
|
),
|
|
self.settings,
|
|
)
|
|
|
|
_ = plt.loglog(projection.x, projection.y, label="projection")
|
|
_ = plt.loglog(reference.x, reference.y, label="référence")
|
|
_ = plt.loglog(data.x, data.y, label="data")
|
|
_ = plt.loglog(
|
|
reference.x, projection.y + reference.y, label="somme"
|
|
)
|
|
_ = plt.legend()
|
|
_ = plt.show()
|
|
|
|
"""
|
|
as the minimization does not work (why ?), visual help
|
|
"""
|
|
x = logspace(-50, 0, 1000)
|
|
y = [
|
|
fit_compute_light(
|
|
x[i],
|
|
factor_n,
|
|
coupling_n,
|
|
factor_d,
|
|
coupling_d,
|
|
self.settings.power_in,
|
|
self.settings.power_out,
|
|
data,
|
|
reference,
|
|
)
|
|
for i in range(len(x))
|
|
]
|
|
_ = plt.loglog(x, y)
|
|
_ = plt.show()
|
|
|
|
return min_result.x
|