Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve argmin2d-based calibration. Example added #183

Merged
merged 1 commit into from
Nov 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
157 changes: 157 additions & 0 deletions examples/ne_si_calibration_argmin2d_example.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"id": "c2c4861b-fc4c-4cbe-8c46-149f461bab1a",
"metadata": {},
"outputs": [],
"source": [
"import ramanchada2.protocols.calib_ne_si_argmin2d_iter_gg as calgg\n",
"import ramanchada2 as rc2\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"import ramanchada2.misc.constants as rc2const"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "36b733f3-bb8a-4663-8604-c832556ccaf1",
"metadata": {},
"outputs": [],
"source": [
"# Load spectra\n",
"ne = rc2.spectrum.from_test_spe(OP=['01'], laser_wl=['785'], device=['Horiba'], provider=['FNMT'], sample=['Neon'])\n",
"si = rc2.spectrum.from_test_spe(OP=['01'], laser_wl=['785'], device=['Horiba'], provider=['FNMT'], sample=['S0N'])\n",
"ps = rc2.spectrum.from_test_spe(OP=['01'], laser_wl=['785'], device=['Horiba'], provider=['FNMT'], sample=['PST'])\n",
"wl = 785\n",
"\n",
"# Perform all-in-one calibration\n",
"nesi_calib_fn = calgg.neon_silicon_calibration(ne, si, wl)\n",
"\n",
"# Apply the calibration to Polystyrene\n",
"ps_cal = ps.scale_xaxis_fun(nesi_calib_fn)\n",
"\n",
"# Plot Polystyrene\n",
"fig, ax = plt.subplots(figsize=(30, 8))\n",
"ps.plot(ax=ax, label='original')\n",
"ps_cal.plot(ax=ax, label='calibrated')\n",
"ax.set_title(f'Polystyrene')\n",
"ax.set_xlabel('1/cm')\n",
"twx = ax.twinx()\n",
"rc2.spectrum.from_delta_lines(rc2const.PST_RS_dict).plot(ax=twx, fmt='r:', label='reference')\n",
"twx.legend(loc='upper right')\n",
"ax.legend(loc='upper left')\n",
"fig.tight_layout()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "18161b18-36c3-4bb1-8df3-d498d125cd51",
"metadata": {},
"outputs": [],
"source": [
"opts = [\n",
" dict(OP=['01'], laser_wl=['532'], device=['BWtek'], provider=['FNMT']),\n",
" dict(OP=['01'], laser_wl=['785'], device=['Horiba'], provider=['FNMT']),\n",
" dict(OP=['03'], laser_wl=['785'], device=['Horiba'], provider=['FNMT']),\n",
" dict(OP=['050'], laser_wl=['532'], device=['BWtek'], provider=['ICV']),\n",
" dict(OP=['100'], laser_wl=['532'], device=['BWtek'], provider=['ICV']),\n",
" dict(OP=['100'], laser_wl=['785'], device=['BWtek'], provider=['ICV']),\n",
" dict(OP=['010'], laser_wl=['633'], device=['Horiba'], provider=['TOP']),\n",
"]\n",
"for opt in opts:\n",
" base = str(opt).replace(':', '').replace(' ','')\n",
" wl = int(opt['laser_wl'][0])\n",
"\n",
" # load spectra\n",
" ne = rc2.spectrum.from_test_spe(**opt, sample=['Neon'])\n",
" si = rc2.spectrum.from_test_spe(**opt, sample=['S0N'])\n",
" ps = rc2.spectrum.from_test_spe(**opt, sample=['PST'])\n",
"\n",
" # Calculate wavelength calibration curve\n",
" ne_calib_fn = calgg.neon_calibration(ne, wl)\n",
" ne_cal = ne.scale_xaxis_fun(ne_calib_fn).dropna()\n",
"\n",
" # Calculate real laser wavelength\n",
" si_nm = si.scale_xaxis_fun(ne_calib_fn).dropna()\n",
" si_calib_fn, wl_real = calgg.silicon_calibration(si_nm, wl)\n",
" si_cal = si_nm.scale_xaxis_fun(si_calib_fn)\n",
"\n",
" # All-in-one calibration\n",
" nesi_calib_fn = calgg.neon_silicon_calibration(ne, si, wl)\n",
" \n",
" # Apply the calibration to Polystyrene\n",
" ps_cal = ps.scale_xaxis_fun(nesi_calib_fn)\n",
"\n",
" # Plot Neon\n",
" fig, ax = plt.subplots(figsize=(30, 8))\n",
" ne.shift_cm_1_to_abs_nm_filter(wl).plot(ax=ax, label='original')\n",
" ne_cal.plot(ax=ax, label='calibrated')\n",
" twx = ax.twinx()\n",
" rc2const.neon_wl_spe[wl].plot(ax=twx, fmt='g:', label='reference')\n",
" ax.set_title(f'Neon {base} {wl}nm')\n",
" ax.set_xlabel('nm')\n",
" twx.legend(loc='upper right')\n",
" ax.legend(loc='upper left')\n",
" fig.tight_layout()\n",
" #fig.savefig(f'{base}_{wl}nm_neon.pdf')\n",
" display(fig)\n",
" plt.close(fig)\n",
"\n",
" # Plot Silicon\n",
" fig, ax = plt.subplots(figsize=(12, 5))\n",
" si.plot(ax=ax, label='original')\n",
" si_cal.plot(ax=ax, label='calibrated')\n",
" ax.set_title(rf'Silicon {base} {wl}nm, $\\lambda_{{laser}}={wl_real:8.3f}$nm')\n",
" ax.set_xlabel('1/cm')\n",
" ax.set_xlim(500, 540)\n",
" ax.axvline(520.45)\n",
" twx.legend(loc='upper right')\n",
" ax.legend(loc='upper left')\n",
" fig.tight_layout()\n",
" #fig.savefig(f'{base}_{wl}nm_silicon.pdf')\n",
" display(fig)\n",
" plt.close(fig)\n",
" \n",
" # Plot Polystyrene\n",
" fig, ax = plt.subplots(figsize=(30, 8))\n",
" ps.plot(ax=ax, label='original')\n",
" ps_cal.plot(ax=ax, label='calibrated')\n",
" ax.set_title(f'Polystyrene {base} {wl}nm')\n",
" ax.set_xlabel('1/cm')\n",
" twx = ax.twinx()\n",
" rc2.spectrum.from_delta_lines(rc2const.PST_RS_dict).plot(ax=twx, fmt='r:', label='reference')\n",
" twx.legend(loc='upper right')\n",
" ax.legend(loc='upper left')\n",
" fig.tight_layout()\n",
" #fig.savefig(f'{base}_{wl}nm_polystyrene.pdf')\n",
" display(fig)\n",
" plt.close(fig)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "ramanchada2",
"language": "python",
"name": "ramanchada2"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.7"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
55 changes: 47 additions & 8 deletions src/ramanchada2/protocols/calib_ne_si_argmin2d_iter_gg.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,65 @@ def neon_calibration(ne_cm_1: Spectrum,


def silicon_calibration(si_nm: Spectrum,
wl: Literal[514, 532, 633, 785]):
si_nm = si_nm.dropna().normalize() # type: ignore
peaks = si_nm.find_peak_multipeak(prominence=.05, width=2, wlen=50) # type: ignore
fitres = si_nm.fit_peak_multimodel(candidates=peaks, profile='Pearson4') # type: ignore
wl: Literal[514, 532, 633, 785],
find_peaks_kw={},
fit_peaks_kw={}):
"""
Calculate calibration function for lazer zeroing

Args:
si_nm: Spectrum
Silicon spectrum
wl: Literal[514, 532, 633, 785]
Laser wavelength
find_peaks_kw: dict, optional
keywords for find_peak. Default values are
`{'prominence': min(.8, si_nm.y_noise_MAD()*50), 'width': 2, 'wlen': 100}`
fit_peaks_kw: dict, optional
keywords for fit_peaks. Default values are
`{'profile': 'Pearson4', 'vary_baseline': False}`

Returns:
spline, esitmated_wavelength: int
"""
si_nm_orig = si_nm
fnd_kw = {'prominence': min(.8, si_nm.y_noise_MAD()*50),
'width': 2,
'wlen': 100,
}
fnd_kw.update(find_peaks_kw)
ll = wl/(1-wl*(520-50)*1e-7)
rr = wl/(1-wl*(520+50)*1e-7)
si_nm = si_nm.dropna().trim_axes(method='x-axis', boundaries=(ll, rr)).normalize() # type: ignore
peaks = si_nm.find_peak_multipeak(**fnd_kw) # type: ignore
fp_kw = {'profile': 'Pearson4',
'vary_baseline': False
}
fp_kw.update(fit_peaks_kw)
fitres = si_nm.fit_peak_multimodel(candidates=peaks, **fp_kw) # type: ignore
si_wl = fitres.centers
if len(si_wl) < 1:
raise ValueError('No peaks were found. Please refind find_peaks parameters.')
laser_wl = 1/(520.45/1e7 + 1/si_wl)

laser_wl = laser_wl[np.argmin(np.abs(laser_wl-wl))]
x_cm_1 = 1e7*(1/laser_wl-1/si_nm.x)
x_cm_1 = 1e7*(1/laser_wl-1/si_nm_orig.x)

spline = interpolate.Akima1DInterpolator(si_nm.x, x_cm_1, method='makima')
spline = interpolate.Akima1DInterpolator(si_nm_orig.x, x_cm_1, method='makima')
return spline, laser_wl


def neon_silicon_calibration(ne_cm_1: Spectrum,
si_cm_1: Spectrum,
wl: Literal[514, 532, 633, 785]):
wl: Literal[514, 532, 633, 785],
sil_fit_kw={},
sil_find_kw={}
):
ne_spline = neon_calibration(ne_cm_1, wl)
si_nm = si_cm_1.scale_xaxis_fun(ne_spline) # type: ignore
si_spline, wl = silicon_calibration(si_nm, wl)
si_spline, wl = silicon_calibration(si_nm, wl,
find_peaks_kw=sil_find_kw,
fit_peaks_kw=sil_fit_kw)
ne_nm = ne_cm_1.scale_xaxis_fun(ne_spline) # type: ignore
ne_cal_cm_1 = ne_nm.abs_nm_to_shift_cm_1_filter(wl)
spline = interpolate.Akima1DInterpolator(ne_cm_1.x, ne_cal_cm_1.x, method='makima')
Expand Down
Loading