Skip to content

Commit

Permalink
Add docstrings to calib_gg functions and their dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
georgievgeorgi committed Nov 19, 2024
1 parent 6191d24 commit e8b4a69
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 3 deletions.
17 changes: 16 additions & 1 deletion src/ramanchada2/misc/utils/argmin2d.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,24 @@ def align(x, y,
**kw_args):
"""
Iteratively finds best match between x and y and evaluates the x scaling parameters.
min((lambda(x, *p)-y)**2 | *p)
Finds best parameters *p that minimise L2 distance between scaled x and original y
min((lambda(x, *p)-y)**2 | *p)
Args:
x (ArrayLike[float]): values that need to match the reference
y (ArrayLike[float]): reference values
p0 (Union[List[float], npt.NDArray], optional): initial values for the parameters `p`.
Defaults to [0, 1, 0, 0].
func (Callable, optional): Objective function to minimize. Returns list penalties
calculated for each `p`. The total objective function is sum of the elements.
Defaults to polynomial of 3-th degree.
max_iter (PositiveInt, optional): max number of iterations. Defaults to 1000.
Returns:
ArrayLike[float]: array of parameters `p` that minimize the objective funciton
"""

if isinstance(p0, list):
p = np.array(p0)
else:
Expand Down
43 changes: 41 additions & 2 deletions src/ramanchada2/protocols/calib_ne_si_argmin2d_iter_gg.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,22 @@

def neon_calibration(ne_cm_1: Spectrum,
wl: Literal[514, 532, 633, 785]):
"""
Neon calibration
The approximate laser wavelengt `wl` is used to translate the neon spectrum to [nm].
Then using :func:`~ramanchada2.spectrum.calibration.by_deltas.xcal_argmin2d_iter_lowpass`
the approximate neon spectrum in [nm] is scaled to match the reference lines.
This way it is calibrated to absolute wavelengths. A Makima spline is calculated so that
it takes wavenumbers [1/cm] and return wavelength-calibrated x-axis in wavelengths [nm].
Args:
ne_cm_1 (Spectrum): neon spectrum used for the calibration. Should be in [1/cm]
wl (Literal[514, 532, 633, 785]): Approximate laser wavelength in [nm]
Returns:
Callable(ArrayLike[float]): callable (spline) that applies the calibration
"""
ref = rc2const.neon_wl_dict[wl]
ne_nm = ne_cm_1.subtract_moving_minimum(200).shift_cm_1_to_abs_nm_filter(wl).normalize() # type: ignore

Expand All @@ -24,11 +40,16 @@ def silicon_calibration(si_nm: Spectrum,
"""
Calculate calibration function for lazer zeroing
Takes wavelength-calibrated Silicon spectrum in wavelengths [nm] and using
the Silicon peak position it calculates the real laser wavelength and a Makima
spline that translates the wavelengt-calibrated x-axis wavelength [nm] values to
lazer-zeroed Raman shift in wavenumbers [1/cm].
Args:
si_nm: Spectrum
Silicon spectrum
Wavelength-calibrated Silicon spectrum in wavelengths [nm]
wl: Literal[514, 532, 633, 785]
Laser wavelength
Approximate 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}`
Expand Down Expand Up @@ -72,6 +93,24 @@ def neon_silicon_calibration(ne_cm_1: Spectrum,
sil_fit_kw={},
sil_find_kw={}
):
"""
Perform neon and silicon calibration together
Combines :func:`~ramanchada2.protocols.calib_ne_si_argmin2d_iter_gg.neon_calibration`
and :func:`~ramanchada2.protocols.calib_ne_si_argmin2d_iter_gg.silicon_calibration`.
Returned spline is calculated using the wavlength-calibrated x-axis values translated
to Raman shift wavenumbers using the calculated laser wavelength in `silicon_calibration`
Args:
ne_cm_1 (Spectrum): neon spectrum used for the calibration. Should be in [1/cm]
si_cm_1 (Spectrum): silicon spectrum to estimate laser wavelength. Should be in [1/cm].
wl (Literal[514, 532, 633, 785]): Approximate laser wavelength in [nm]
sil_fit_kw (dict, optional): kwargs sent as `find_peaks_kw` in `silicon_calibration`. Defaults to {}.
sil_find_kw (dict, optional): kwargs sent as `fit_peaks_kw` in `silicon_calibration`. Defaults to {}.
Returns:
Callable(ArrayLike[float]): callable (spline) that applies the calibration
"""
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,
Expand Down
37 changes: 37 additions & 0 deletions src/ramanchada2/spectrum/calibration/by_deltas.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,25 @@ def xcal_fine(old_spe: Spectrum,
poly_order: NonNegativeInt,
find_peaks_kw={},
):
"""
Iterative calibration with provided reference based on :func:`~ramanchada2.misc.utils.argmin2d.align`
Iteratively apply polynomial of `poly_order` degree to match
the found peaks to the reference locations. The pairs are created
using :func:`~ramanchada2.misc.utils.argmin2d.align` algorithm.
Args:
old_spe (Spectrum): internal use only
new_spe (Spectrum): internal use only
ref (Union[Dict[float, float], List[float]]): _description_
ref (Dict[float, float]):
If a dict is provided - wavenumber - amplitude pairs.
If a list is provided - wavenumbers only.
poly_order (NonNegativeInt): polynomial degree to be used usualy 2 or 3
should_fit (bool, optional): Whether the peaks should be fit or to
associate the positions with the maxima. Defaults to False.
find_peaks_kw (dict, optional): kwargs to be used in find_peaks. Defaults to {}.
"""

if isinstance(ref, dict):
ref_pos = np.array(list(ref.keys()))
Expand Down Expand Up @@ -260,6 +279,24 @@ def xcal_argmin2d_iter_lowpass(old_spe: Spectrum,
new_spe: Spectrum, /, *,
ref: Dict[float, float],
low_pass_nfreqs: List[int] = [100, 500]):
"""
Calibrate spectrum
The calibration is done in multiple steps. Both the spectrum and the reference
are passed through a low-pass filter to preserve only general structure of the
spectrum. `low_pass_nfreqs` defines the number of frequencies to be preserved in
each step. Once all steps with low-pass filter a final step without a low-pass
filter is performed. Each calibration step is performed using
:func:`~ramanchada2.spectrum.calibration.by_deltas.xcal_fine` algorithm.
Args:
old_spe (Spectrum): internal use only
new_spe (Spectrum): internal use only
ref (Dict[float, float]): wavenumber - amplitude pairs
low_pass_nfreqs (List[int], optional): The number of elements defines the
number of low-pass steps and their values define the amount of frequencies
to keep. Defaults to [100, 500].
"""
def semi_spe_from_dict(deltas: dict, xaxis):
y = np.zeros_like(xaxis)
for pos, ampl in deltas.items():
Expand Down

0 comments on commit e8b4a69

Please sign in to comment.