code wiki / (root) / nx_chem_mass.nx

nx_chem_mass.nx source

↩ module page · 124 lines · 5715 B

1// nx_chem_mass.nx -- C2.8a milestone: monoisotopic mass + ion m/z 2// prediction for LC-MS work. 3// 4// Standard atomic weight (Element.mass_q3 in milli-AMU, C1) is used 5// for nominal molecular weight via nx_chem_mol_weight_q3 (C2.3a). 6// For MS work, the EXACT MASS of the most-abundant isotope is needed 7// instead -- e.g., glucose monoisotopic = 180.0634 Da (not 180.156 8// average) because LC-MS resolves a single isotope peak. 9// 10// This file composes on C1 AtomicData.iso_mass_q4 (Q4 micro-AMU) + 11// C2.3a implicit-H to produce exact-mass + protonated-ion m/z. 12// 13// Units: 14// iso_mass_q4 : exact isotope mass * 10000 (Q4 micro-AMU) 15// monoiso_q4 : whole-molecule monoisotopic mass in Q4 16// proton_mass_q4 : 10073 (= 1.00728 Da, the proton mass; used for 17// [M+H]+ ion m/z which differs from monoisotopic 18// by adding a proton, not a neutral H atom; the 19// difference is the electron mass = 0.00055 Da 20// which is below Q4 precision) 21// 22// Honest gaps (DEFERRED): 23// - Multi-charge ions [M+2H]2+, [M+nH]n+: trivially obtainable 24// by dividing m/z by n; left for caller in MVP. 25// - Isotopologue pattern prediction (M+1, M+2 peaks from natural 26// abundance distribution): C2.8b composes on AtomicData 27// iso_abund_ppm field; requires combinatorial expansion over 28// all C/H/N/O isotopes. 29// - Adduct ions [M+Na]+, [M+K]+, [M+NH4]+ common in ESI+: 30// just substitute proton with respective ion mass. 31 32import "nx_chem.nx" 33import "nx_chem_molecule.nx" 34import "nx_chem_periodic.nx" 35 36// Proton mass in Q4 micro-AMU: 1.00728 Da * 10000 = 10073. 37const NX_PROTON_MASS_Q4: nx_int = 10073 38// Sodium adduct mass (²³Na exact): 22.9898 Da * 10000 = 229898. 39// Subtract proton -> 219825 = Na+ ion contribution for [M+Na]+. 40const NX_SODIUM_MASS_Q4: nx_int = 229898 41const NX_SODIUM_ION_DELTA_Q4: nx_int = 219825 42// Ammonium adduct [NH4]+ exact: N(14.0031) + 4*H(1.00783) - electron = 43// 18.03437. Q4 = 180344. 44const NX_AMMONIUM_ION_Q4: nx_int = 180344 45 46// ================================================================= 47// Compute monoisotopic mass of molecule m using the AtomicData table. 48// Returns mass in Q4 micro-AMU (multiply by 0.0001 for Da). 49// 50// Caller MUST run nx_chem_compute_implicit_h(m) FIRST so non-bracket 51// atoms have h_count populated. Caller passes the AtomicData table 52// (typically from nx_chem_atomic_data_table_118()). 53// 54// Algorithm: 55// For each atom i: 56// total += AtomicData[z-1].iso_mass_q4 57// if h_count > 0: total += h_count * AtomicData[0].iso_mass_q4 (H) 58// ================================================================= 59func nx_chem_mol_monoisotopic_mass_q4(m: *MolGraph, ad_table: *AtomicData) -> nx_int { 60 let h_data: *AtomicData = ((ad_table as nx_int) + (0 * NX_ATOMIC_DATA_BYTES)) as *AtomicData 61 let h_mass: nx_int = h_data.iso_mass_q4 62 var total: nx_int = 0 63 var i: nx_int = 0 64 while i < m.n_atoms { 65 let a: *Atom = ((m.atoms as nx_int) + (i * NX_ATOM_BYTES)) as *Atom 66 if a.z >= 1 { 67 if a.z <= 118 { 68 let ad: *AtomicData = ((ad_table as nx_int) + ((a.z - 1) * NX_ATOMIC_DATA_BYTES)) as *AtomicData 69 total = total + ad.iso_mass_q4 70 } 71 } 72 if a.h_count > 0 { 73 total = total + (a.h_count * h_mass) 74 } 75 i = i + 1 76 } 77 return total 78} 79 80// ================================================================= 81// [M+H]+ ion m/z: monoisotopic mass + proton. Singly charged so 82// m/z == mass + proton (no division by charge). 83// ================================================================= 84func nx_chem_mol_mh_plus_q4(m: *MolGraph, ad_table: *AtomicData) -> nx_int { 85 return nx_chem_mol_monoisotopic_mass_q4(m, ad_table) + NX_PROTON_MASS_Q4 86} 87 88// ================================================================= 89// [M-H]- ion m/z: monoisotopic mass - proton. 90// ================================================================= 91func nx_chem_mol_mh_minus_q4(m: *MolGraph, ad_table: *AtomicData) -> nx_int { 92 return nx_chem_mol_monoisotopic_mass_q4(m, ad_table) - NX_PROTON_MASS_Q4 93} 94 95// ================================================================= 96// [M+Na]+ ion m/z: monoisotopic mass + Na - electron. 97// Common in ESI+ when sodium is present in the sample (e.g., MS run 98// with sodium-containing buffer). 99// ================================================================= 100func nx_chem_mol_mna_plus_q4(m: *MolGraph, ad_table: *AtomicData) -> nx_int { 101 return nx_chem_mol_monoisotopic_mass_q4(m, ad_table) + NX_SODIUM_ION_DELTA_Q4 102} 103 104// ================================================================= 105// [M+NH4]+ ion m/z: monoisotopic mass + NH4+ ion mass. 106// Common in ESI+ with ammonium-acetate buffer. 107// ================================================================= 108func nx_chem_mol_mnh4_plus_q4(m: *MolGraph, ad_table: *AtomicData) -> nx_int { 109 return nx_chem_mol_monoisotopic_mass_q4(m, ad_table) + NX_AMMONIUM_ION_Q4 110} 111 112// ================================================================= 113// Multi-charge [M+nH]n+ ion m/z: (monoisotopic + n*proton) / n. 114// Common for proteins / large molecules in ESI+ which carry multiple 115// charges in observed spectrum. 116// 117// For n=1, equivalent to [M+H]+. For n=2, m/z is roughly half the 118// singly-charged value. 119// ================================================================= 120func nx_chem_mol_multi_charge_mh_q4(m: *MolGraph, ad_table: *AtomicData, n_charge: nx_int) -> nx_int { 121 if n_charge <= 0 { return 0 } 122 let mh_total: nx_int = nx_chem_mol_monoisotopic_mass_q4(m, ad_table) + (n_charge * NX_PROTON_MASS_Q4) 123 return mh_total / n_charge 124}