|
1 | 1 | """Utilities for CRD processors. Mostly methods that can be jitted.""" |
2 | 2 |
|
3 | | -from typing import Tuple, Union |
| 3 | +from typing import List, Tuple, Union |
4 | 4 |
|
5 | 5 | from numba import njit |
6 | 6 | import numpy as np |
7 | 7 | from scipy import optimize |
8 | 8 |
|
9 | | -from .utilities import fitting, utils |
| 9 | +from .utilities import fitting, ini, utils |
10 | 10 |
|
11 | 11 |
|
12 | 12 | @njit |
@@ -82,6 +82,72 @@ def dead_time_correction( |
82 | 82 | return data |
83 | 83 |
|
84 | 84 |
|
| 85 | +def delta_calc(names: List[str], integrals: np.ndarray) -> np.ndarray: |
| 86 | + """Calculate delta values for a given set of integrals. |
| 87 | +
|
| 88 | + Use ``iniabu`` to calculate the delta values with respect to major isotope. |
| 89 | + If the name of a peak is not valid or the major isotope not present, return |
| 90 | + ``np.nan`` for that entry. Appropriate error propagation is done as well. |
| 91 | +
|
| 92 | + :param names: Names of the peaks as list. |
| 93 | + :param integrals: Integrals, as defined in ``CRDFileProcessor.integrals``. |
| 94 | +
|
| 95 | + :return: List of delta values, same shape and format as ``integrals``. |
| 96 | + """ |
| 97 | + # transform all names to valid ``iniabu`` names or call them ``None`` |
| 98 | + names_iniabu = [] |
| 99 | + for name in names: |
| 100 | + try: |
| 101 | + names_iniabu.append(ini.iso[name].name) |
| 102 | + except IndexError: |
| 103 | + names_iniabu.append(None) |
| 104 | + |
| 105 | + # find major isotope names |
| 106 | + major_iso_name = [] |
| 107 | + for name in names_iniabu: |
| 108 | + if name is None: |
| 109 | + major_iso_name.append(None) |
| 110 | + else: |
| 111 | + ele = name.split("-")[0] |
| 112 | + try: |
| 113 | + maj = ini._get_major_iso(ele) |
| 114 | + except IndexError: |
| 115 | + maj = None |
| 116 | + major_iso_name.append(maj) |
| 117 | + |
| 118 | + integrals_dict = dict(zip(names_iniabu, range(len(names_iniabu)))) |
| 119 | + |
| 120 | + integrals_delta = np.zeros_like(integrals, dtype=float) |
| 121 | + |
| 122 | + for it, iso in enumerate(names_iniabu): |
| 123 | + maj_iso = major_iso_name[it] |
| 124 | + |
| 125 | + if iso is None or maj_iso not in names_iniabu: |
| 126 | + integrals_delta[it][0] = np.nan |
| 127 | + integrals_delta[it][1] = np.nan |
| 128 | + else: |
| 129 | + msr_nom = integrals[it][0] |
| 130 | + msr_nom_unc = integrals[it][1] |
| 131 | + msr_denom = integrals[integrals_dict[maj_iso]][0] |
| 132 | + msr_denom_unc = integrals[integrals_dict[maj_iso]][1] |
| 133 | + |
| 134 | + msr_ratio = msr_nom / msr_denom |
| 135 | + integrals_delta[it][0] = ini.iso_delta(iso, maj_iso, msr_ratio) |
| 136 | + |
| 137 | + # error calculation |
| 138 | + std_ratio = ini.iso_ratio(iso, maj_iso) |
| 139 | + integrals_delta[it][1] = ( |
| 140 | + 1000 |
| 141 | + / std_ratio |
| 142 | + * np.sqrt( |
| 143 | + (msr_nom_unc / msr_denom) ** 2 |
| 144 | + + (msr_nom * msr_denom_unc / msr_denom**2) ** 2 |
| 145 | + ) |
| 146 | + ) |
| 147 | + |
| 148 | + return integrals_delta |
| 149 | + |
| 150 | + |
85 | 151 | def gaussian_fit_get_max(xdata: np.ndarray, ydata: np.ndarray) -> float: |
86 | 152 | """Fit a Gaussian to xdata and ydata and return the xvalue of the peak. |
87 | 153 |
|
|
0 commit comments