Source code for cagey._internal.nmr

from collections.abc import Iterable, Iterator, Sequence
from dataclasses import replace
from operator import attrgetter
from pathlib import Path

import nmrglue
import numpy as np

from cagey._internal.types import NmrPeak, NmrSpectrum


[docs] def get_spectrum(spectrum_dir: Path) -> NmrSpectrum: """Get NMR spectrum from the machine data directory. Parameters: spectrum_dir: Path to the directory containing the spectrum data. Returns: The NMR spectrum. """ peaks = tuple(_pick_peaks(spectrum_dir)) reference_peak_ppm = 7.28 possible_reference_peaks = filter( lambda peak: peak.has_ppm(reference_peak_ppm), peaks, ) reference_peak = max( possible_reference_peaks, key=attrgetter("amplitude"), ) reference_shift = 7.26 - reference_peak.ppm chloroform_peaks = [7.26, 7.52, 7.00] return NmrSpectrum( aldehyde_peaks=tuple( _get_aldehyde_peaks(peaks, reference_shift, chloroform_peaks) ), imine_peaks=tuple( _get_imine_peaks(peaks, reference_shift, chloroform_peaks) ), )
def _pick_peaks(spectrum_dir: Path) -> Iterator[NmrPeak]: metadata, data = nmrglue.bruker.read_pdata(str(spectrum_dir)) udic = nmrglue.bruker.guess_udic(metadata, data) unit_conversion = nmrglue.fileio.fileiobase.uc_from_udic(udic) for peak in nmrglue.peakpick.pick(data, pthres=1e4, nthres=None): shift = unit_conversion.ppm(peak["X_AXIS"]) amplitude = peak["VOL"] yield NmrPeak(shift, amplitude) def _shift_peaks( peaks: Iterable[NmrPeak], shift: float, ) -> Iterator[NmrPeak]: for peak in peaks: yield replace(peak, ppm=peak.ppm + shift) def _remove_peaks( peaks: Iterable[NmrPeak], to_remove: Sequence[float], ) -> Iterator[NmrPeak]: for peak in peaks: if not np.any(np.isclose(peak.ppm, to_remove, atol=0.02)): yield peak def _get_aldehyde_peaks( peaks: Iterable[NmrPeak], reference_shift: float, solvent_peaks: Sequence[float], ) -> Iterator[NmrPeak]: peaks = filter( lambda peak: peak.in_range(9.0, 11.0), peaks, ) peaks = _shift_peaks(peaks, reference_shift) peaks = _remove_peaks(peaks, solvent_peaks) return filter( lambda peak: peak.amplitude > 0, peaks, ) def _get_imine_peaks( peaks: Iterable[NmrPeak], reference_shift: float, solvent_peaks: Sequence[float], ) -> Iterator[NmrPeak]: peaks = filter( lambda peak: peak.in_range(6.5, 9.0), peaks, ) peaks = _shift_peaks(peaks, reference_shift) peaks = _remove_peaks(peaks, solvent_peaks) return filter( lambda peak: peak.amplitude > 0, peaks, )