refactoring

This commit is contained in:
François Boulogne 2025-06-20 13:26:30 +02:00
parent 439104a17f
commit 12922f0f79
3 changed files with 87 additions and 37 deletions

View file

@ -12,7 +12,7 @@ def _thicknesses_scheludko_at_order(wavelengths,
intensities, intensities,
interference_order, interference_order,
refractive_index, refractive_index,
Imin=None): intensities_void=None):
""" """
Compute thicknesses vs wavelength for a given interference order. Compute thicknesses vs wavelength for a given interference order.
@ -26,25 +26,25 @@ def _thicknesses_scheludko_at_order(wavelengths,
Interference order. Interference order.
refractive_index : array_like (or float) refractive_index : array_like (or float)
Refractive index. Refractive index.
Imin : TYPE, optional intensities_void : array, optional
DESCRIPTION. The default is None. Intensities of void.
Returns Returns
------- -------
thickness : TYPE thicknesses : array
DESCRIPTION.
""" """
if Imin is None: if intensities_void is None:
Imin = np.min(intensities) Imin = np.min(intensities)
else:
Imin = intensities_void
n = refractive_index n = refractive_index
m = interference_order m = interference_order
I = (np.asarray(intensities) - Imin) / (np.max(intensities) - Imin) I_norm = (np.asarray(intensities) - Imin) / (np.max(intensities) - Imin)
prefactor = wavelengths / (2 * np.pi * n) prefactor = wavelengths / (2 * np.pi * n)
argument = np.sqrt(I / (1 + (1 - I) * (n**2 - 1)**2 / (4 * n**2))) argument = np.sqrt(I_norm / (1 + (1 - I_norm) * (n**2 - 1)**2 / (4 * n**2)))
if m % 2 == 0: if m % 2 == 0:
term1 = (m / 2) * np.pi term1 = (m / 2) * np.pi
@ -75,7 +75,6 @@ def _Delta(wavelengths, thickness, interference_order, refractive_index):
------- -------
ndarray ndarray
Delta values. Delta values.
""" """
# ensure that the entries are numpy arrays # ensure that the entries are numpy arrays
@ -131,24 +130,51 @@ def get_default_start_stop_wavelengths(wavelengths,
refractive_index, refractive_index,
min_peak_prominence, min_peak_prominence,
plot=None): plot=None):
"""
Returns the start and stop wavelength values of the last monotonic branch.
Parameters
----------
wavelengths : array
Wavelength values in nm.
intensities : array
Intensity values.
refractive_index : scalar, optional
Value of the refractive index of the medium.
min_peak_prominence : scalar
Required prominence of peaks.
plot : bool, optional
Display a curve, useful for checking or debuging. The default is None.
Raises
------
RuntimeError
if at least one maximum and one minimum are not detected.
Returns
-------
wavelength_start : scalar
wavelength_stop : scalar
"""
# idx_min idx max # idx_min idx max
peaks_min, peaks_max = finds_peak(wavelengths, intensities, idx_peaks_min, idx_peaks_max = finds_peak(wavelengths, intensities,
min_peak_prominence=min_peak_prominence, min_peak_prominence=min_peak_prominence,
plot=plot) plot=plot)
failure, message = False, '' failure, message = False, ''
if len(peaks_min) == 0: if len(idx_peaks_min) == 0:
message += 'Failed to detect at least one minimum. ' message += 'Failed to detect at least one minimum. '
failure = True failure = True
if len(peaks_max) == 0: if len(idx_peaks_max) == 0:
message += 'Failed to detect at least one maximum. ' message += 'Failed to detect at least one maximum. '
failure = True failure = True
if failure: if failure:
raise RuntimeError(message) raise RuntimeError(message)
# Get the last oscillation peaks # Get the last oscillation peaks
lambda_min = wavelengths[peaks_min[-1]] lambda_min = wavelengths[idx_peaks_min[-1]]
lambda_max = wavelengths[peaks_max[-1]] lambda_max = wavelengths[idx_peaks_max[-1]]
# Order them # Order them
wavelength_start = min(lambda_min, lambda_max) wavelength_start = min(lambda_min, lambda_max)
@ -163,9 +189,10 @@ def thickness_from_scheludko(wavelengths,
wavelength_start=None, wavelength_start=None,
wavelength_stop=None, wavelength_stop=None,
interference_order=None, interference_order=None,
intensities_void=None,
plot=None): plot=None):
""" """
Compute the film thickness based on Scheludko method.
Parameters Parameters
---------- ----------
@ -175,13 +202,25 @@ def thickness_from_scheludko(wavelengths,
Intensity values. Intensity values.
refractive_index : scalar, optional refractive_index : scalar, optional
Value of the refractive index of the medium. Value of the refractive index of the medium.
wavelength_start : scalar, optional
Starting value of a monotonic branch.
Mandatory if interference_order != 0.
wavelength_start : scalar, optional
Stoping value of a monotonic branch.
Mandatory if interference_order != 0.
interference_order : scalar, optional
Interference order, zero or positive integer.
If set to None, the value is guessed.
intensities_void : array, optional
Intensity in absence of a film.
Mandatory if interference_order == 0.
plot : bool, optional plot : bool, optional
Display a curve, useful for checking or debuging. The default is None. Display a curve, useful for checking or debuging. The default is None.
Returns Returns
------- -------
thickness : TYPE results : Instance of `OptimizeResult` class.
DESCRIPTION. The attribute `thickness` gives the thickness value in nm.
""" """
if plot: if plot:
@ -196,7 +235,6 @@ def thickness_from_scheludko(wavelengths,
r_index = refractive_index r_index = refractive_index
# Handle the interference order # Handle the interference order
if interference_order is None: if interference_order is None:
# A bit extreme... # A bit extreme...
@ -208,7 +246,6 @@ def thickness_from_scheludko(wavelengths,
r_index_masked = r_index[mask] r_index_masked = r_index[mask]
intensities_masked = intensities[mask] intensities_masked = intensities[mask]
min_difference = np.inf min_difference = np.inf
thickness_values = None thickness_values = None
@ -217,26 +254,25 @@ def thickness_from_scheludko(wavelengths,
plt.ylabel(r'$h$ ($\mathrm{{nm}}$)') plt.ylabel(r'$h$ ($\mathrm{{nm}}$)')
plt.xlabel(r'$\lambda$ ($ \mathrm{nm} $)') plt.xlabel(r'$\lambda$ ($ \mathrm{nm} $)')
for m in range(0, max_tested_order+1): for _order in range(0, max_tested_order+1):
h_values = _thicknesses_scheludko_at_order(wavelengths_masked, h_values = _thicknesses_scheludko_at_order(wavelengths_masked,
intensities_masked, intensities_masked,
m, _order,
r_index_masked) r_index_masked)
difference = np.max(h_values) - np.min(h_values) difference = np.max(h_values) - np.min(h_values)
print(f"h-difference for m={m}: {difference:.1f} nm") print(f"h-difference for m={_order}: {difference:.1f} nm")
if difference < min_difference: if difference < min_difference:
min_difference = difference min_difference = difference
interference_order = m interference_order = _order
thickness_values = h_values thickness_values = h_values
if plot: if plot:
plt.plot(wavelengths_masked, h_values,'.', markersize=3, label=f"Épaisseur du film (Scheludko, m={m})") plt.plot(wavelengths_masked, h_values, '.',
markersize=3, label=f"Order={_order}")
elif interference_order == 0: elif interference_order == 0:
File_I_min = 'tests/spectre_trou/000043641.xy'
_, intensities_I_min = load_spectrum(File_I_min, lambda_min=450)
min_peak_prominence = 0.02 min_peak_prominence = 0.02
peaks_min, peaks_max = finds_peak(wavelengths, intensities, peaks_min, peaks_max = finds_peak(wavelengths, intensities,
@ -252,7 +288,7 @@ def thickness_from_scheludko(wavelengths,
wavelengths_masked = wavelengths[mask] wavelengths_masked = wavelengths[mask]
r_index_masked = r_index[mask] r_index_masked = r_index[mask]
intensities_masked = intensities[mask] intensities_masked = intensities[mask]
intensities_I_min_masked =intensities_I_min[mask] intensities_I_min_masked = intensities_void[mask]
interference_order = 0 interference_order = 0
thickness_values = _thicknesses_scheludko_at_order(wavelengths_masked, thickness_values = _thicknesses_scheludko_at_order(wavelengths_masked,

View file

@ -25,6 +25,10 @@ def load(filename):
@pytest.mark.parametrize("spectrum_path, expected", load('known_value.yaml')) @pytest.mark.parametrize("spectrum_path, expected", load('known_value.yaml'))
def test_SV2o0_small_tol(spectrum_path, expected): def test_SV2o0_small_tol(spectrum_path, expected):
lambdas, raw_intensities = load_spectrum(spectrum_path, lambda_min=450) lambdas, raw_intensities = load_spectrum(spectrum_path, lambda_min=450)
File_I_min = 'tests/spectre_trou/000043641.xy'
_, intensities_void = load_spectrum(File_I_min, lambda_min=450)
smoothed_intensities = smooth_intensities(raw_intensities) smoothed_intensities = smooth_intensities(raw_intensities)
r_index = 1.324188 + 3102.060378 / (lambdas**2) r_index = 1.324188 + 3102.060378 / (lambdas**2)
@ -43,6 +47,7 @@ def test_SV2o0_small_tol(spectrum_path, expected):
wavelength_start=w_start, wavelength_start=w_start,
wavelength_stop=w_stop, wavelength_stop=w_stop,
interference_order=0, interference_order=0,
intensities_void=intensities_void,
plot=False) plot=False)
assert_allclose(result.thickness, expected, rtol=1e-1) assert_allclose(result.thickness, expected, rtol=1e-1)
@ -50,6 +55,10 @@ def test_SV2o0_small_tol(spectrum_path, expected):
@pytest.mark.parametrize("spectrum_path, expected", load('known_value_large_tol.yaml')) @pytest.mark.parametrize("spectrum_path, expected", load('known_value_large_tol.yaml'))
def test_SV2o0_large_tol(spectrum_path, expected): def test_SV2o0_large_tol(spectrum_path, expected):
lambdas, raw_intensities = load_spectrum(spectrum_path, lambda_min=450) lambdas, raw_intensities = load_spectrum(spectrum_path, lambda_min=450)
File_I_min = 'tests/spectre_trou/000043641.xy'
_, intensities_void = load_spectrum(File_I_min, lambda_min=450)
smoothed_intensities = smooth_intensities(raw_intensities) smoothed_intensities = smooth_intensities(raw_intensities)
r_index = 1.324188 + 3102.060378 / (lambdas**2) r_index = 1.324188 + 3102.060378 / (lambdas**2)
@ -68,6 +77,7 @@ def test_SV2o0_large_tol(spectrum_path, expected):
wavelength_start=w_start, wavelength_start=w_start,
wavelength_stop=w_stop, wavelength_stop=w_stop,
interference_order=0, interference_order=0,
intensities_void=intensities_void,
plot=False) plot=False)
assert_allclose(result.thickness, expected, rtol=2.5e-1) assert_allclose(result.thickness, expected, rtol=2.5e-1)

View file

@ -130,10 +130,13 @@ def test_order0():
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)
r_index = 1.324188 + 3102.060378 / (lambdas**2) r_index = 1.324188 + 3102.060378 / (lambdas**2)
prominence = 0.03 prominence = 0.03
File_I_min = 'tests/spectre_trou/000043641.xy'
_, intensities_void = load_spectrum(File_I_min, lambda_min=450)
w_start, w_stop = None, None w_start, w_stop = None, None
result = thickness_from_scheludko(lambdas, result = thickness_from_scheludko(lambdas,
smoothed_intensities, smoothed_intensities,
@ -141,6 +144,7 @@ def test_order0():
wavelength_start=w_start, wavelength_start=w_start,
wavelength_stop=w_stop, wavelength_stop=w_stop,
interference_order=0, interference_order=0,
intensities_void=intensities_void,
plot=False) plot=False)