nx_chem_isotope_pattern.nx
buildroot/runtime/nx_chem_isotope_pattern.nx
about
nx_chem_isotope_pattern.nx -- C2.8b milestone: isotopologue M+1/M+2
peak intensity prediction.
MS adulterant identification relies on more than exact mass: the
natural-abundance isotopologue pattern (M, M+1, M+2 peaks) is a
fingerprint of elemental composition.
Famous halogen signatures:
* Cl in molecule -> M:M+2 ratio approximately 3:1 (75.78% : 24.22%)
* Br in molecule -> M:M+2 ratio approximately 1:1 (50.69% : 49.31%)
* No Cl/Br -> M+2 small (sub-1% per atom)
Sulfur has notable M+2 contribution (~4.5% per S; from 34-S).
Carbon has notable M+1 contribution (~1.08% per C; from 13-C).
Approach: first-order linear approximation -- each atom contributes
its single-substitution probability to M+1 / M+2. Accurate for
0-1 of each halogen + low atom counts; overestimates for multiple
halogens (binomial expansion needed; deferred to C2.8b.1).
Returns Q4 fraction of M-peak intensity (10000 = 100% of M, so
e.g., ethanol M+1 = 232 means M+1 is 2.32% the height of M).
Constants pinned (IUPAC 2021 isotopic compositions):
¹H 99.985%, ²H 0.015%
¹²C 98.93%, ¹³C 1.07%
¹⁴N 99.636%, ¹⁵N 0.364%
¹⁶O 99.757%, ¹⁷O 0.038%, ¹⁸O 0.205%
³²S 94.99%, ³³S 0.75%, ³⁴S 4.25%
³⁵Cl 75.78%, ³⁷Cl 24.22%
⁷⁹Br 50.69%, ⁸¹Br 49.31%
(¹⁹F, ³¹P, ¹²⁷I monoisotopic -- contribute 0 to M+1/M+2)
Honest gaps (deferred):
- Multi-halogen binomial expansion: a molecule with 4 Cl atoms
gives M+2 = 4 * (37Cl/35Cl) * (35Cl/35Cl)^3 = 4 * 0.3196 = 128%
by first-order, but binomial says 4 * 0.3196 * (1 - 0.2422)^3 =
~32% normalized. C2.8b.1 will ship binomial.
- M+3, M+4 peaks: relevant for Cl2, Br2, mixed halogen species.
C2.8b.2.
dependencies 2 imports · 10 importers
imports: nx_chem.nxnx_chem_molecule.nx
imported by: nx_chem_adulterant_db.nxnx_chem_adulterant_db_test.nxnx_chem_isotope_pattern_test.nxnx_chem_peak_list_test.nxnx_chem_report_csv_test.nxnx_chem_report_json_test.nxnx_supplement.nxnx_supplement_batch.nxnx_supplement_check.nxnx_supplement_csv.nx
structs
| none |
consts
| 49 | const NX_ISO_M1_H: nx_int = 2 // ²H / ¹H = 0.00015 -> 2 in Q4 |
| 50 | const NX_ISO_M1_C: nx_int = 108 // ¹³C / ¹²C = 0.01082 -> 108 |
| 51 | const NX_ISO_M1_N: nx_int = 37 // ¹⁵N / ¹⁴N = 0.00365 -> 37 |
| 52 | const NX_ISO_M1_O: nx_int = 4 // ¹⁷O / ¹⁶O = 0.000381 -> 4 |
| 53 | const NX_ISO_M1_S: nx_int = 79 // ³³S / ³²S = 0.00789 -> 79 |
| 58 | const NX_ISO_M2_O: nx_int = 21 // ¹⁸O / ¹⁶O = 0.00206 -> 21 |
| 59 | const NX_ISO_M2_S: nx_int = 447 // ³⁴S / ³²S = 0.0447 -> 447 |
| 60 | const NX_ISO_M2_CL: nx_int = 3196 // ³⁷Cl / ³⁵Cl = 0.3196 -> 3196 |
| 61 | const NX_ISO_M2_BR: nx_int = 9728 // ⁸¹Br / ⁷⁹Br = 0.9728 -> 9728 |
functions
| 73 | func nx_chem_isotope_m1_q4(m: *MolGraph) -> nx_int |
| 97 | func nx_chem_isotope_m2_q4(m: *MolGraph) -> nx_int |
| 126 | func nx_chem_halogen_signature(m: *MolGraph) -> nx_int |