This commit is contained in:
François Boulogne 2025-05-27 16:01:50 +02:00
parent 8bb23c3724
commit d321fce459
9 changed files with 371 additions and 261 deletions

View file

@ -7,6 +7,7 @@ import matplotlib.pyplot as plt
from optifik.analysis import * from optifik.analysis import *
from optifik.fft import Prominence_from_fft
from optifik.auto import auto from optifik.auto import auto
from optifik import io from optifik import io
@ -35,6 +36,10 @@ def play():
FILE_NAME = '000004310.xy' #TEST# FILE_NAME = '000004310.xy' #TEST#
spectrum_file = os.path.join(DATA_FOLDER, FILE_NAME) spectrum_file = os.path.join(DATA_FOLDER, FILE_NAME)
spectrum_file = 'tests/spectraVictor1/T5469.xy' #TEST#
lambdas, intensities = io.load_spectrum(spectrum_file) lambdas, intensities = io.load_spectrum(spectrum_file)
plot_spectrum(lambdas, intensities, title='Raw') plot_spectrum(lambdas, intensities, title='Raw')
@ -49,6 +54,13 @@ def play():
min_peak_prominence=prominence, min_peak_prominence=prominence,
plot=True) plot=True)
indice = 1.324188 + 3102.060378 / (lambdas**2)
p, s, w = Prominence_from_fft(lambdas, smoothed_intensities, indice, plot=True)
print(p)
peaks_min, peaks_max = finds_peak(lambdas, smoothed_intensities,
min_peak_prominence=p,
plot=True)
def check_basic(): def check_basic():
@ -125,6 +137,6 @@ def check_SV1():
if __name__ == '__main__': if __name__ == '__main__':
check_basic() #check_basic()
check_SV1() #check_SV1()
play() play()

View file

@ -1,6 +1,3 @@
import pandas as pd
from scipy.signal import savgol_filter from scipy.signal import savgol_filter
from scipy.signal import find_peaks from scipy.signal import find_peaks
@ -13,18 +10,12 @@ plt.rcParams.update({
'legend.fontsize': 23, 'legend.fontsize': 23,
}) })
from .io import load_spectrum
from .fft import *
from .minmax import *
def plot_spectrum(wavelengths, intensities, title=''):
plt.figure(figsize=(10, 6), dpi=300)
plt.plot(wavelengths, intensities, 'o-', markersize=2)
def plot_spectrum(lambdas, intensities, title=''):
plt.figure(figsize=(10, 6),dpi =600)
plt.plot(lambdas, intensities, 'o-', markersize=2)
plt.xlabel(r'$\lambda$ (nm)') plt.xlabel(r'$\lambda$ (nm)')
plt.ylabel(r'$I^*$') plt.ylabel(r'$I^*$')
plt.title(title) plt.title(title)
@ -33,19 +24,27 @@ def plot_spectrum(lambdas, intensities, title=''):
def finds_peak(wavelengths, intensities, min_peak_prominence, min_peak_distance=10, plot=None):
def finds_peak(lambdas, intensities, min_peak_prominence, min_peak_distance=10, plot=None):
""" """
Charge un fichier .xy et affiche les données avec les extrema détectés (minima et maxima). Detect minima and maxima
Parameters Parameters
---------- ----------
filename : str wavelengths : array
Chemin vers le fichier .xy (2 colonnes : lambda et intensité). Wavelength values in nm.
intensities : array
Intensity values.
min_peak_prominence : float min_peak_prominence : float
Importance minimale des pics. min prominence for scipy find_peak.
min_peak_distance : float min_peak_distance : int, optional
Distance minimale entre les pics. min peak distance for scipy find_peak. The default is 10.
plot : bool, optional
Display a curve, useful for checking or debuging. The default is None.
Returns
-------
(peaks_min, peaks_max)
""" """
@ -53,10 +52,10 @@ def finds_peak(lambdas, intensities, min_peak_prominence, min_peak_distance=10,
peaks_min, _ = find_peaks(-intensities, prominence=min_peak_prominence, distance=min_peak_distance) peaks_min, _ = find_peaks(-intensities, prominence=min_peak_prominence, distance=min_peak_distance)
if plot: if plot:
plt.figure(figsize=(10, 6),dpi =600) plt.figure(figsize=(10, 6), dpi=300)
plt.plot(lambdas, intensities, 'o-', markersize=2, label="Smoothed data") plt.plot(wavelengths, intensities, 'o-', markersize=2, label="Smoothed data")
plt.plot(lambdas[peaks_max], intensities[peaks_max], 'ro') plt.plot(wavelengths[peaks_max], intensities[peaks_max], 'ro')
plt.plot(lambdas[peaks_min], intensities[peaks_min], 'ro') plt.plot(wavelengths[peaks_min], intensities[peaks_min], 'ro')
plt.xlabel(r'$\lambda$ (nm)') plt.xlabel(r'$\lambda$ (nm)')
plt.ylabel(r'$I^*$') plt.ylabel(r'$I^*$')
plt.legend() plt.legend()
@ -68,8 +67,23 @@ def finds_peak(lambdas, intensities, min_peak_prominence, min_peak_distance=10,
def smooth_intensities(intensities): def smooth_intensities(intensities, window_size=11):
WIN_SIZE = 11 """
smoothed_intensities = savgol_filter(intensities, WIN_SIZE, 3) Return a smoothed intensities array with a Savitzky-Golay filter.
Parameters
----------
intensities : ndarray
Intensity values
window_size : int, optional
The length of the filter window. The default is 11.
Returns
-------
smoothed_intensities
"""
polynom_order = 3
smoothed_intensities = savgol_filter(intensities, window_size, 3)
return smoothed_intensities return smoothed_intensities

View file

@ -24,8 +24,8 @@ def auto(spectrum_file, plot=None):
##### Determination de la prominence associé ##### ##### Determination de la prominence associé #####
prominence = Prominence_from_fft(lambdas=lambdas, prominence, signal, wavelength = Prominence_from_fft(lambdas,
intensities=smoothed_intensities, smoothed_intensities,
refractive_index=indice, refractive_index=indice,
plot=plot) plot=plot)

View file

@ -17,7 +17,7 @@ from .utils import OptimizeResult
def thickness_from_fft(lambdas, intensities, def thickness_from_fft(wavelengths, intensities,
refractive_index, refractive_index,
num_half_space=None, num_half_space=None,
plot=None): plot=None):
@ -26,7 +26,7 @@ def thickness_from_fft(lambdas, intensities,
Parameters Parameters
---------- ----------
lambdas : array wavelengths : array
Wavelength values in nm. Wavelength values in nm.
intensities : array intensities : array
Intensity values. Intensity values.
@ -34,7 +34,7 @@ def thickness_from_fft(lambdas, intensities,
Value of the refractive index of the medium. Value of the refractive index of the medium.
num_half_space : scalar, optional num_half_space : scalar, optional
Number of points to compute FFT's half space. Number of points to compute FFT's half space.
If `None`, default corresponds to `10*len(lambdas)`. If `None`, default corresponds to `10*len(wavelengths)`.
debug : boolean, optional debug : boolean, optional
Show plot of the transformed signal and the peak detection. Show plot of the transformed signal and the peak detection.
@ -44,32 +44,32 @@ def thickness_from_fft(lambdas, intensities,
The attribute `thickness` gives the thickness value in nm. The attribute `thickness` gives the thickness value in nm.
""" """
if num_half_space is None: if num_half_space is None:
num_half_space = 10 * len(lambdas) num_half_space = 10 * len(wavelengths)
# FFT requires evenly spaced data. # FFT requires evenly spaced data.
# So, we interpolate the signal. # So, we interpolate the signal.
# Interpolate to get a linear increase of 1 / lambdas. # Interpolate to get a linear increase of 1 / wavelengths.
inverse_lambdas_times_n = refractive_index / lambdas inverse_wavelengths_times_n = refractive_index / wavelengths
f = interp1d(inverse_lambdas_times_n, intensities) f = interp1d(inverse_wavelengths_times_n, intensities)
inverse_lambdas_linspace = np.linspace(inverse_lambdas_times_n[0], inverse_wavelengths_linspace = np.linspace(inverse_wavelengths_times_n[0],
inverse_lambdas_times_n[-1], inverse_wavelengths_times_n[-1],
2*num_half_space) 2*num_half_space)
intensities_linspace = f(inverse_lambdas_linspace) intensities_linspace = f(inverse_wavelengths_linspace)
# Perform FFT # Perform FFT
density = (inverse_lambdas_times_n[-1]-inverse_lambdas_times_n[0]) / (2*num_half_space) density = (inverse_wavelengths_times_n[-1]-inverse_wavelengths_times_n[0]) / (2*num_half_space)
inverse_lambdas_fft = fftfreq(2*num_half_space, density) inverse_wavelengths_fft = fftfreq(2*num_half_space, density)
intensities_fft = fft(intensities_linspace) intensities_fft = fft(intensities_linspace)
# The FFT is symetrical over [0:N] and [N:2N]. # The FFT is symetrical over [0:N] and [N:2N].
# Keep over [N:2N], ie for positive freq. # Keep over [N:2N], ie for positive freq.
intensities_fft = intensities_fft[num_half_space:2*num_half_space] intensities_fft = intensities_fft[num_half_space:2*num_half_space]
inverse_lambdas_fft = inverse_lambdas_fft[num_half_space:2*num_half_space] inverse_wavelengths_fft = inverse_wavelengths_fft[num_half_space:2*num_half_space]
idx_max_fft = np.argmax(abs(intensities_fft)) idx_max_fft = np.argmax(abs(intensities_fft))
freq_max = inverse_lambdas_fft[idx_max_fft] freq_max = inverse_wavelengths_fft[idx_max_fft]
thickness_fft = freq_max / 2. thickness_fft = freq_max / 2.
@ -77,7 +77,7 @@ def thickness_from_fft(lambdas, intensities,
plt.figure(figsize=(10, 6),dpi =600) plt.figure(figsize=(10, 6),dpi =600)
if plot: if plot:
plt.loglog(inverse_lambdas_fft, np.abs(intensities_fft)) plt.loglog(inverse_wavelengths_fft, np.abs(intensities_fft))
plt.loglog(freq_max, np.abs(intensities_fft[idx_max_fft]), 'o') plt.loglog(freq_max, np.abs(intensities_fft[idx_max_fft]), 'o')
plt.xlabel('Frequency') plt.xlabel('Frequency')
plt.ylabel(r'FFT($I^*$)') plt.ylabel(r'FFT($I^*$)')
@ -86,67 +86,90 @@ def thickness_from_fft(lambdas, intensities,
return OptimizeResult(thickness=thickness_fft,) return OptimizeResult(thickness=thickness_fft,)
def Prominence_from_fft(lambdas, intensities, refractive_index, num_half_space=None, plot=True): def Prominence_from_fft(wavelengths, intensities, refractive_index,
num_half_space=None, plot=None):
if num_half_space is None: if num_half_space is None:
num_half_space = 10 * len(lambdas) num_half_space = len(wavelengths)
# Interpolation pour que les données soient uniformément espacées # # # 1. Spectre original
inverse_lambdas_times_n = refractive_index / lambdas # if plot:
f = interp1d(inverse_lambdas_times_n, intensities) # plt.figure(figsize=(10, 6), dpi=150)
# plt.plot(1/wavelengths, intensities, label='Spectre original')
# plt.xlabel('1/Longueur d\'onde (nm-1)')
# plt.ylabel('Intensité')
# plt.legend()
# plt.show()
inverse_lambdas_linspace = np.linspace(inverse_lambdas_times_n[0],
inverse_lambdas_times_n[-1],
2*num_half_space)
intensities_linspace = f(inverse_lambdas_linspace)
# FFT # 2. Conversion lambda → k = n(λ) / λ
density = (inverse_lambdas_times_n[-1] - inverse_lambdas_times_n[0]) / (2*num_half_space) k_vals = refractive_index / wavelengths
freqs = fftfreq(2*num_half_space, density) f_interp = interp1d(k_vals, intensities, kind='linear', fill_value="extrapolate")
fft_vals = fft(intensities_linspace)
# On conserve uniquement les fréquences positives # 3. Axe k uniforme + interpolation
freqs = freqs[num_half_space:] k_linspace = np.linspace(k_vals[0], k_vals[-1], 2 * num_half_space)
fft_vals = fft_vals[num_half_space:] intensities_k = f_interp(k_linspace)
# Trouver le pic principal # 4. FFT
abs_fft = np.abs(fft_vals) delta_k = (k_vals[-1] - k_vals[0]) / (2 * num_half_space)
idx_max = np.argmax(abs_fft) fft_vals = fft(intensities_k)
F_max = freqs[idx_max] freqs = fftfreq(2 * num_half_space, delta_k)
# 5. Pic FFT
freqs_pos = freqs[freqs > 0]
abs_fft_pos = np.abs(fft_vals[freqs > 0])
idx_max = np.argmax(abs_fft_pos)
F_max = freqs_pos[idx_max]
if plot: if plot:
print(f"F_max detected at: {F_max:.4f}") plt.figure(figsize=(10, 6), dpi=150)
plt.figure(figsize=(10, 6),dpi = 600) plt.plot(freqs_pos, abs_fft_pos, label='|FFT|')
plt.plot(freqs, abs_fft, label='|FFT|') plt.axvline(F_max, color='r', linestyle='--', label='Pic principal')
plt.axvline(F_max, color='r', linestyle='--', label='F_max') plt.xlabel('Distance optique [nm]')
plt.xlabel('Fréquence') plt.ylabel(r'FFT($I^*$)')
plt.ylabel('Amplitude FFT')
plt.yscale('log')
plt.xscale('log') plt.xscale('log')
plt.yscale('log')
plt.legend() plt.legend()
plt.show() plt.show()
# Filtrage : on garde les composantes au-dessus de 10 * F_max # 6. Filtrage (garde hautes fréquences)
cutoff = 10 * F_max cutoff_HF = 2 * F_max
mask = freqs >= cutoff
fft_filtered = np.zeros_like(fft_vals)
fft_filtered[mask] = fft_vals[mask]
fft_full = np.zeros(2 * num_half_space, dtype=complex) mask_HF = np.abs(freqs) >= cutoff_HF
fft_full[num_half_space:] = fft_filtered # fréquences positives fft_filtered_HF = np.zeros_like(fft_vals, dtype=complex)
fft_full[:num_half_space] = np.conj(fft_filtered[::-1]) fft_filtered_HF[mask_HF] = fft_vals[mask_HF]
# IFFT
signal_filtered = np.real(ifft(fft_full))
# Max amplitude après filtrage # 7. Filtrage (garde basses fréquences)
max_amplitude = np.max(np.abs(signal_filtered)) cutoff_BF = 10 * F_max
mask_BF = np.abs(freqs) <= cutoff_BF
fft_filtered_BF = np.zeros_like(fft_vals, dtype=complex)
fft_filtered_BF[mask_BF] = fft_vals[mask_BF]
# 8. Reconstruction
signal_filtered_HF = np.real(ifft(fft_filtered_HF))
signal_filtered_BF = np.real(ifft(fft_filtered_BF))
lambda_reconstructed = np.interp(k_linspace, k_vals[::-1], wavelengths[::-1])
# Masque dans la plage [550, 700] nm
mask_Cam_Sensitivity = (lambda_reconstructed >= 550) & (lambda_reconstructed <= 700)
# 9. Affichage reconstruction
if plot: if plot:
plt.figure(figsize=(10, 6),dpi = 600) plt.figure(figsize=(10, 6), dpi=150)
plt.plot(signal_filtered, label='Signal filtered') plt.plot(lambda_reconstructed, intensities_k, '--', label='Original interpolé')
plt.xlabel('Échantillons') plt.plot(lambda_reconstructed, signal_filtered_HF,'--', color='gray')
plt.ylabel('Amplitude')
plt.plot(lambda_reconstructed[mask_Cam_Sensitivity], signal_filtered_HF[mask_Cam_Sensitivity],
color='orange', label='Spectre filtré HF')
plt.plot(lambda_reconstructed, signal_filtered_BF,
color='red', label='Spectre filtré BF')
plt.xlabel('Wavelength (nm)')
plt.ylabel('Intensity')
plt.legend() plt.legend()
plt.show() plt.show()
print(f"Amplitude Mal filtered : {max_amplitude:.4f}")
return max_amplitude max_amplitude = np.max(np.abs(signal_filtered_HF[mask_Cam_Sensitivity]))
return max_amplitude, signal_filtered_BF, lambda_reconstructed

View file

@ -1,7 +1,9 @@
import numpy as np import numpy as np
def load_spectrum(spectrum_path, lambda_min=0, lambda_max=np.inf, def load_spectrum(spectrum_path,
lambda_min=0,
lambda_max=np.inf,
delimiter=','): delimiter=','):
""" """
Load a spectrum file. Load a spectrum file.

View file

@ -16,7 +16,7 @@ plt.rcParams.update({
from .utils import OptimizeResult from .utils import OptimizeResult
def thickness_from_minmax(lambdas, def thickness_from_minmax(wavelengths,
intensities, intensities,
refractive_index, refractive_index,
min_peak_prominence, min_peak_prominence,
@ -29,7 +29,7 @@ def thickness_from_minmax(lambdas,
Parameters Parameters
---------- ----------
lambdas : array wavelengths : array
Wavelength values in nm. Wavelength values in nm.
intensities : array intensities : array
Intensity values. Intensity values.
@ -63,11 +63,12 @@ def thickness_from_minmax(lambdas,
peaks.sort() peaks.sort()
k_values = np.arange(len(peaks)) k_values = np.arange(len(peaks))
n_over_lambda = refractive_index[peaks][::-1] / lambdas[peaks][::-1] n_over_lambda = refractive_index[peaks][::-1] / wavelengths[peaks][::-1]
if k_values.size < 2: if k_values.size < 2:
# Can't fit if less than two points. # Can't fit if less than two points.
return np.nan return OptimizeResult(thickness=np.nan)
if isinstance(refractive_index, np.ndarray): if isinstance(refractive_index, np.ndarray):
refractive_index = refractive_index[peaks][::-1] refractive_index = refractive_index[peaks][::-1]
@ -85,7 +86,7 @@ def thickness_from_minmax(lambdas,
thickness_minmax = 1 / slope / 4 thickness_minmax = 1 / slope / 4
# Scikit-learn # Scikit-learn
#X, y = k_values.reshape(-1, 1), 1/lambdas[peaks][::-1] #X, y = k_values.reshape(-1, 1), 1/wavelengths[peaks][::-1]
## Fit line using all data ## Fit line using all data
#lr = linear_model.LinearRegression() #lr = linear_model.LinearRegression()

View file

@ -1,6 +1,4 @@
import numpy as np import numpy as np
from scipy.optimize import curve_fit from scipy.optimize import curve_fit
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
@ -16,8 +14,9 @@ from .io import load_spectrum
from .utils import OptimizeResult from .utils import OptimizeResult
from .analysis import finds_peak from .analysis import finds_peak
def thickness_scheludko_at_order(wavelengths, def thickness_scheludko_at_order(wavelengths,
intensity, intensities,
interference_order, interference_order,
refractive_index, refractive_index,
Imin=None): Imin=None):
@ -26,10 +25,10 @@ def thickness_scheludko_at_order(wavelengths,
Parameters Parameters
---------- ----------
wavelengths : TYPE wavelengths : array
DESCRIPTION. Wavelength values in nm.
intensity : TYPE intensities : array
DESCRIPTION. Intensity values.
interference_order: TYPE interference_order: TYPE
DESCRIPTION. DESCRIPTION.
refractive_index : TYPE refractive_index : TYPE
@ -44,11 +43,11 @@ def thickness_scheludko_at_order(wavelengths,
""" """
if Imin is None: if Imin is None:
Imin = np.min(intensity) Imin = np.min(intensities)
n = refractive_index n = refractive_index
m = interference_order m = interference_order
I = (np.asarray(intensity) - Imin) / (np.max(intensity) - Imin) I = (np.asarray(intensities) - Imin) / (np.max(intensities) - Imin)
prefactor = wavelengths / (2 * np.pi * n) prefactor = wavelengths / (2 * np.pi * n)
@ -64,7 +63,7 @@ def thickness_scheludko_at_order(wavelengths,
return prefactor * (term1 + term2) return prefactor * (term1 + term2)
def Delta(wavelengths, thickness, interference_order, refractive_index):
""" """
Calculates the Delta value for arrays of wavelengths, thicknesses h and r_indexs n. Calculates the Delta value for arrays of wavelengths, thicknesses h and r_indexs n.
@ -78,6 +77,29 @@ def Delta(wavelengths, thickness, interference_order, refractive_index):
- delta: ndarray of corresponding Δ values - delta: ndarray of corresponding Δ values
""" """
def Delta(wavelengths, thickness, interference_order, refractive_index):
"""
Parameters
----------
wavelengths : array
Wavelength values in nm.
thickness : array_like (or float)
Film thickness.
interference_order : int
Interference order.
refractive_index : array_like (or float)
Refractive index.
Returns
-------
TYPE
DESCRIPTION.
"""
# ensure that the entries are numpy arrays # ensure that the entries are numpy arrays
wavelengths = np.asarray(wavelengths) wavelengths = np.asarray(wavelengths)
h = np.asarray(thickness) h = np.asarray(thickness)
@ -103,18 +125,34 @@ def Delta(wavelengths, thickness, interference_order, refractive_index):
return (A * (1 + alpha)) / (1 + A * alpha) return (A * (1 + alpha)) / (1 + A * alpha)
def Delta_fit(xdata, thickness, interference_order): def Delta_fit(xdata, thickness, interference_order):
""" """
Wrapper pour curve_fit : on fixe m, et lambda & n seront passés comme "xdata" Wrapper on Delta() for curve_fit.
Parameters
----------
xdata : tuple
(wavelengths, n)
thickness : array_like (or float)
Film thickness.
interference_order : int
Interference order.
Returns
-------
ndarray
Delta values.
""" """
lambd, n = xdata lambdas, n = xdata
return Delta(lambd, thickness, interference_order, n) return Delta(lambdas, thickness, interference_order, n)
def thickness_from_scheludko(lambdas, def thickness_from_scheludko(wavelengths,
smoothed_intensities, intensities,
refractive_index, refractive_index,
min_peak_prominence, min_peak_prominence,
plot=None): plot=None):
@ -123,16 +161,14 @@ def thickness_from_scheludko(lambdas,
Parameters Parameters
---------- ----------
lambdas : TYPE wavelengths : array
DESCRIPTION. Wavelength values in nm.
raw_intensities : TYPE intensities : array
DESCRIPTION. Intensity values.
smoothed_intensities : TYPE refractive_index : scalar, optional
DESCRIPTION. Value of the refractive index of the medium.
refractive_index : TYPE plot : bool, optional
DESCRIPTION. Display a curve, useful for checking or debuging. The default is None.
plot : TYPE, optional
DESCRIPTION. The default is None.
Returns Returns
------- -------
@ -143,23 +179,25 @@ def thickness_from_scheludko(lambdas,
max_tested_order = 12 max_tested_order = 12
r_index = refractive_index r_index = refractive_index
peaks_min, peaks_max = finds_peak(lambdas, smoothed_intensities, peaks_min, peaks_max = finds_peak(wavelengths, intensities,
min_peak_prominence=min_peak_prominence, min_peak_prominence=min_peak_prominence,
plot=False) plot=False)
# Get the last oscillation peaks
lambda_min = wavelengths[peaks_min[-1]]
lambda_max = wavelengths[peaks_max[-1]]
lambda_min = lambdas[peaks_min[-1]] # Order them
lambda_max = lambdas[peaks_max[-1]]
# On s'assure que lambda_min < lambda_max
lambda_start = min(lambda_min, lambda_max) lambda_start = min(lambda_min, lambda_max)
lambda_end = max(lambda_min, lambda_max) lambda_stop = max(lambda_min, lambda_max)
# On crée le masque pour ne garder que les lambdas entre les deux extrema # mask input data
mask = (lambdas >= lambda_start) & (lambdas <= lambda_end) mask = (wavelengths >= lambda_start) & (wavelengths <= lambda_stop)
lambdas_masked = lambdas[mask] wavelengths_masked = wavelengths[mask]
r_index_masked = r_index[mask] r_index_masked = r_index[mask]
intensities_masked = smoothed_intensities[mask] intensities_masked = intensities[mask]
min_ecart = np.inf min_ecart = np.inf
best_m = None best_m = None
meilleure_h = None meilleure_h = None
@ -171,10 +209,10 @@ def thickness_from_scheludko(lambdas,
for m in range(0, max_tested_order+1): for m in range(0, max_tested_order+1):
h_values = thickness_scheludko_at_order(lambdas_masked, intensities_masked, m, r_index_masked) h_values = thickness_scheludko_at_order(wavelengths_masked, intensities_masked, m, r_index_masked)
if plot: if plot:
plt.plot(lambdas_masked, h_values,'.', markersize=3, label=f"Épaisseur du film (Scheludko, m={m})") plt.plot(wavelengths_masked, h_values,'.', markersize=3, label=f"Épaisseur du film (Scheludko, m={m})")
ecart = np.max(h_values)-np.min(h_values) ecart = np.max(h_values)-np.min(h_values)
print(f"Écart pour m={m} : {ecart:.3f} nm") print(f"Écart pour m={m} : {ecart:.3f} nm")
@ -184,26 +222,28 @@ def thickness_from_scheludko(lambdas,
best_m = m best_m = m
meilleure_h = h_values meilleure_h = h_values
if plot:
plt.figure(figsize=(10, 6), dpi=600)
DeltaVrai = (intensities_masked -np.min(intensities_masked))/(np.max(intensities_masked) -np.min(intensities_masked)) DeltaVrai = (intensities_masked -np.min(intensities_masked))/(np.max(intensities_masked) -np.min(intensities_masked))
#DeltaVrai = (intensities_raw_masked -np.min(intensities_raw_masked))/(np.max(intensities_raw_masked) -np.min(intensities_raw_masked)) #DeltaVrai = (intensities_raw_masked -np.min(intensities_raw_masked))/(np.max(intensities_raw_masked) -np.min(intensities_raw_masked))
DeltaScheludko = Delta(lambdas_masked, np.mean(meilleure_h), best_m, r_index_masked) DeltaScheludko = Delta(wavelengths_masked, np.mean(meilleure_h), best_m, r_index_masked)
#print(np.mean(meilleure_h),np.std(meilleure_h)) #print(np.mean(meilleure_h),np.std(meilleure_h))
if plot: if plot:
plt.plot(lambdas_masked,DeltaVrai,'bo-', markersize=2,label=r'$\mathrm{{Smoothed}}\ \mathrm{{Data}}$') plt.figure(figsize=(10, 6), dpi=600)
plt.plot(lambdas_masked,DeltaScheludko,'go-', markersize=2,label = rf'$\mathrm{{Scheludko}}\ (h = {np.mean(meilleure_h):.1f} \pm {np.std(meilleure_h):.1f}\ \mathrm{{nm}})$') plt.plot(wavelengths_masked, DeltaVrai,
'bo-', markersize=2, label=r'$\mathrm{{Smoothed}}\ \mathrm{{Data}}$')
plt.plot(wavelengths_masked, DeltaScheludko,
'go-', markersize=2, label = rf'$\mathrm{{Scheludko}}\ (h = {np.mean(meilleure_h):.1f} \pm {np.std(meilleure_h):.1f}\ \mathrm{{nm}})$')
xdata = (lambdas_masked, r_index_masked) xdata = (wavelengths_masked, r_index_masked)
popt, pcov = curve_fit(lambda x, h: Delta_fit(x, h, m), xdata, DeltaVrai, p0=[np.mean(meilleure_h)]) popt, pcov = curve_fit(lambda x, h: Delta_fit(x, h, m), xdata, DeltaVrai, p0=[np.mean(meilleure_h)])
fitted_h = popt[0] fitted_h = popt[0]
if plot: if plot:
plt.plot(lambdas_masked, Delta(lambdas_masked, fitted_h, best_m, r_index_masked ), 'ro-',markersize=2, label=rf'$\mathrm{{Fit}}\ (h = {fitted_h:.1f}\pm {np.sqrt(pcov[0][0]):.1f} \ \mathrm{{nm}})$') plt.plot(wavelengths_masked, Delta(wavelengths_masked, fitted_h, best_m, r_index_masked ), 'ro-',markersize=2, label=rf'$\mathrm{{Fit}}\ (h = {fitted_h:.1f}\pm {np.sqrt(pcov[0][0]):.1f} \ \mathrm{{nm}})$')
plt.legend() plt.legend()
plt.ylabel(r'$\Delta$') plt.ylabel(r'$\Delta$')
plt.xlabel(r'$\lambda$ ($ \mathrm{nm} $)') plt.xlabel(r'$\lambda$ ($ \mathrm{nm} $)')
@ -212,8 +252,8 @@ def thickness_from_scheludko(lambdas,
return OptimizeResult(thickness=fitted_h ,) return OptimizeResult(thickness=fitted_h ,)
def thickness_for_order0(lambdas, def thickness_for_order0(wavelengths,
smoothed_intensities, intensities,
refractive_index, refractive_index,
min_peak_prominence, min_peak_prominence,
plot=None): plot=None):
@ -222,23 +262,23 @@ def thickness_for_order0(lambdas,
File_I_min = 'tests/spectre_trou/000043641.xy' File_I_min = 'tests/spectre_trou/000043641.xy'
r_index = refractive_index r_index = refractive_index
peaks_min, peaks_max = finds_peak(lambdas, smoothed_intensities, peaks_min, peaks_max = finds_peak(wavelengths, intensities,
min_peak_prominence=min_peak_prominence, min_peak_prominence=min_peak_prominence,
plot=False) plot=False)
lambdas_I_min, intensities_I_min = load_spectrum(File_I_min, lambda_min=450) wavelengths_I_min, intensities_I_min = load_spectrum(File_I_min, lambda_min=450)
lambda_unique = lambdas[peaks_max[0]] lambda_unique = wavelengths[peaks_max[0]]
# On crée le masque pour ne garder que les lambdas superieures a lambdas unique # On crée le masque pour ne garder que les wavelengths superieures a wavelengths unique
mask = lambdas >= lambda_unique mask = wavelengths >= lambda_unique
lambdas_masked = lambdas[mask] wavelengths_masked = wavelengths[mask]
r_index_masked = r_index[mask] r_index_masked = r_index[mask]
intensities_masked = smoothed_intensities[mask] intensities_masked = intensities[mask]
intensities_I_min_masked =intensities_I_min[mask] intensities_I_min_masked =intensities_I_min[mask]
min_ecart = np.inf min_ecart = np.inf
@ -247,7 +287,7 @@ def thickness_for_order0(lambdas,
m = 0 m = 0
h_values = thickness_scheludko_at_order(lambdas_masked, h_values = thickness_scheludko_at_order(wavelengths_masked,
intensities_masked, intensities_masked,
0, 0,
r_index_masked, r_index_masked,
@ -255,7 +295,7 @@ def thickness_for_order0(lambdas,
if plot: if plot:
plt.figure(figsize=(10, 6), dpi=600) plt.figure(figsize=(10, 6), dpi=600)
plt.plot(lambdas_masked, h_values, label=r"Épaisseur du film (Scheludko, m=0)") plt.plot(wavelengths_masked, h_values, label=r"Épaisseur du film (Scheludko, m=0)")
ecart = np.max(h_values) - np.min(h_values) ecart = np.max(h_values) - np.min(h_values)
best_m = m best_m = m
@ -267,22 +307,22 @@ def thickness_for_order0(lambdas,
#DeltaVrai = (intensities_masked -np.min(intensities_masked))/(np.max(intensities_masked) -np.min(intensities_masked)) #DeltaVrai = (intensities_masked -np.min(intensities_masked))/(np.max(intensities_masked) -np.min(intensities_masked))
DeltaScheludko = Delta(lambdas_masked, np.mean(meilleure_h), best_m, r_index_masked) DeltaScheludko = Delta(wavelengths_masked, np.mean(meilleure_h), best_m, r_index_masked)
#print(np.mean(meilleure_h),np.std(meilleure_h)) #print(np.mean(meilleure_h),np.std(meilleure_h))
if plot: if plot:
plt.figure(figsize=(10, 6), dpi=600) plt.figure(figsize=(10, 6), dpi=600)
plt.plot(lambdas_masked,DeltaVrai,'bo-', markersize=2,label=r'$\mathrm{{Raw}}\ \mathrm{{Data}}$') plt.plot(wavelengths_masked,DeltaVrai,'bo-', markersize=2,label=r'$\mathrm{{Raw}}\ \mathrm{{Data}}$')
plt.plot(lambdas_masked,DeltaScheludko,'ro-', markersize=2,label = rf'$\mathrm{{Scheludko}}\ (h = {np.mean(meilleure_h):.1f} \pm {np.std(meilleure_h):.1f}\ \mathrm{{nm}})$') plt.plot(wavelengths_masked,DeltaScheludko,'ro-', markersize=2,label = rf'$\mathrm{{Scheludko}}\ (h = {np.mean(meilleure_h):.1f} \pm {np.std(meilleure_h):.1f}\ \mathrm{{nm}})$')
xdata = (lambdas_masked, r_index_masked) xdata = (wavelengths_masked, r_index_masked)
popt, pcov = curve_fit(lambda x, h: Delta_fit(x, h, m), xdata, DeltaVrai, p0=[np.mean(meilleure_h)]) popt, pcov = curve_fit(lambda x, h: Delta_fit(x, h, m), xdata, DeltaVrai, p0=[np.mean(meilleure_h)])
fitted_h = popt[0] fitted_h = popt[0]
if plot: if plot:
plt.plot(lambdas_masked, Delta(lambdas_masked, fitted_h, best_m, r_index_masked ), 'go-',markersize=2, label=rf'$\mathrm{{Fit}}\ (h = {fitted_h:.1f}\pm {np.sqrt(pcov[0][0]):.1f} \ \mathrm{{nm}})$') plt.plot(wavelengths_masked, Delta(wavelengths_masked, fitted_h, best_m, r_index_masked ), 'go-',markersize=2, label=rf'$\mathrm{{Fit}}\ (h = {fitted_h:.1f}\pm {np.sqrt(pcov[0][0]):.1f} \ \mathrm{{nm}})$')
plt.legend() plt.legend()
plt.ylabel(r'$\Delta$') plt.ylabel(r'$\Delta$')
plt.xlabel(r'$\lambda$ (nm)') plt.xlabel(r'$\lambda$ (nm)')

View file

@ -1,12 +1,13 @@
import os.path import os.path
import numpy as np import numpy as np
from numpy.testing import assert_allclose from numpy.testing import assert_allclose, assert_equal
import pytest import pytest
from optifik.minmax import thickness_from_minmax from optifik.minmax import thickness_from_minmax
from optifik.io import load_spectrum from optifik.io import load_spectrum
from optifik.analysis import smooth_intensities from optifik.analysis import smooth_intensities
from optifik.analysis import finds_peak from optifik.analysis import finds_peak
from optifik.fft import Prominence_from_fft
import yaml import yaml
@ -26,13 +27,27 @@ def test_minmax(spectrum_path, expected):
lambdas, raw_intensities = load_spectrum(spectrum_path, lambda_min=450) lambdas, raw_intensities = load_spectrum(spectrum_path, lambda_min=450)
smoothed_intensities = smooth_intensities(raw_intensities) smoothed_intensities = smooth_intensities(raw_intensities)
assert_equal(len(lambdas), len(smoothed_intensities))
indice = 1.324188 + 3102.060378 / (lambdas**2) indice = 1.324188 + 3102.060378 / (lambdas**2)
prominence = 0.02 prominence = 0.02
#prominence, s, w = Prominence_from_fft(lambdas, smoothed_intensities, indice)
#prominence *= 10
thickness_minmax = thickness_from_minmax(lambdas, thickness_minmax = thickness_from_minmax(lambdas,
smoothed_intensities, smoothed_intensities,
refractive_index=indice, refractive_index=indice,
min_peak_prominence=prominence) min_peak_prominence=prominence)
#prominence, s, w = Prominence_from_fft(lambdas, smoothed_intensities, indice)
#print(f'Prom: {prominence}')
#indice = 1.324188 + 3102.060378 / (w**2)
#thickness_minmax = thickness_from_minmax(w,
# s,
# refractive_index=indice,
# min_peak_prominence=prominence)
result = thickness_minmax.thickness result = thickness_minmax.thickness
assert_allclose(result, expected, rtol=1e-1) assert_allclose(result, expected, rtol=1e-1)

View file

@ -8,7 +8,7 @@ from optifik.minmax import thickness_from_minmax
from optifik.scheludko import thickness_from_scheludko from optifik.scheludko import thickness_from_scheludko
from optifik.scheludko import thickness_for_order0 from optifik.scheludko import thickness_for_order0
from optifik.analysis import smooth_intensities from optifik.analysis import smooth_intensities
from optifik.analysis import Prominence_from_fft from optifik.fft import Prominence_from_fft
from optifik.io import load_spectrum from optifik.io import load_spectrum
@ -39,8 +39,8 @@ def test_minmax_ransac():
smoothed_intensities = smooth_intensities(raw_intensities) smoothed_intensities = smooth_intensities(raw_intensities)
indice = 1.324188 + 3102.060378 / (lambdas**2) indice = 1.324188 + 3102.060378 / (lambdas**2)
prominence = Prominence_from_fft(lambdas=lambdas, prominence, signal, wavelength = Prominence_from_fft(lambdas,
intensities=smoothed_intensities, smoothed_intensities,
refractive_index=indice, refractive_index=indice,
plot=False) plot=False)
@ -66,7 +66,10 @@ def test_scheludko_4peaks():
smoothed_intensities = smooth_intensities(raw_intensities) smoothed_intensities = smooth_intensities(raw_intensities)
indice = 1.324188 + 3102.060378 / (lambdas**2) indice = 1.324188 + 3102.060378 / (lambdas**2)
prominence = Prominence_from_fft(lambdas=lambdas, intensities=smoothed_intensities, refractive_index=indice, plot=False) prominence, signal, wavelength = Prominence_from_fft(lambdas,
smoothed_intensities,
refractive_index=indice,
plot=False)
result = thickness_from_scheludko(lambdas, smoothed_intensities, result = thickness_from_scheludko(lambdas, smoothed_intensities,