code wiki / (root) / nx_qc_svc.nx

nx_qc_svc.nx source

↩ module page · 445 lines · 17524 B

1// nx_qc_svc.nx -- QUALITY-CONTROL / ANALYTICAL SERVICE FACADE. The third 2// organ on the nx_service base, over the analytical-chemistry domain: screen 3// an observed LC-MS peak against the peptide-adulterant catalog across charge 4// states, report a compound's detectability, and verify a label-claim dose. 5// 6// WHY THIS IS PRODUCTION INFRASTRUCTURE, NOT A DEMO. 21 CFR 111 -- the 7// dietary-supplement cGMP rule the operator must satisfy before a fill run -- 8// requires 100% identity testing of every incoming dietary ingredient and 9// finished-product testing against specification. This facade is the compute 10// behind that: given a peak an instrument actually reports, it says which 11// prohibited peptide it is (across the charge ladder a [M+H]+-only method 12// misses), and given a measured amount it says whether the label is honest. 13// 14// Three facades now share one nx_service base across three unrelated domains 15// (go-to-market, lab science, analytical QC) -- the architecture scales. 16// 17// USAGE: nx_qc_svc <verb> [args...] 18// describe 19// screen <observed_mz_q4> <tol_ppm_q1> (which prohibited peptide is this peak?) 20// detect <entry_id> (mass, charge ladder, blind-spot flag) 21// label <measured_ug> <declared_ug> (USP dose recovery + verdict) 22// 23// Same discipline: NO new domain logic, every number from a gated library. 24// 25// genealogy_id: supplement_adulterant_arc + service_infrastructure 26 27import "nx_syscalls.nx" 28import "nx_service.nx" 29import "nx_grounding.nx" 30import "nx_peptide.nx" 31import "nx_peptide_formula.nx" 32import "nx_peptide_isotope.nx" 33import "nx_peptide_msms.nx" 34import "nx_peptide_deconv.nx" 35import "nx_peptide_identify.nx" 36import "nx_peptide_denovo.nx" 37import "nx_supplement_screen.nx" 38const QC_MAGIC_8192: i64 = 8192 39 40const QC_SVC: *u8 = "qc" as *u8 41 42// ===== describe ======================================================= 43 44func qc_describe(j: *NxJson) -> i64 { 45 nsvc_ok_open(j, QC_SVC, "describe" as *u8) 46 nj_kv_str(j, "service" as *u8, "supplement identity + adulterant screening (21 CFR 111)" as *u8) 47 nj_comma(j) 48 nj_kv_int(j, "verb_count" as *u8, 8) 49 nj_comma(j) 50 nj_kv_int(j, "catalog_size" as *u8, SUP_N_ENTRY) 51 nj_comma(j) 52 nj_key(j, "verbs" as *u8) 53 nj_puts(j, "[" as *u8) 54 nj_puts(j, "{\"verb\":\"screen\",\"args\":[\"observed_mz_q4:int\",\"tol_ppm_q1:int\"]}," as *u8) 55 nj_puts(j, "{\"verb\":\"detect\",\"args\":[\"entry_id:int\"]}," as *u8) 56 nj_puts(j, "{\"verb\":\"label\",\"args\":[\"measured_ug:int\",\"declared_ug:int\"]}," as *u8) 57 nj_puts(j, "{\"verb\":\"envelope\",\"args\":[\"sequence:string\"]}," as *u8) 58 nj_puts(j, "{\"verb\":\"msms\",\"args\":[\"sequence:string\"]}," as *u8) 59 nj_puts(j, "{\"verb\":\"deconv\",\"args\":[\"mz_lo_q4:int\",\"mz_hi_q4:int\"]}," as *u8) 60 nj_puts(j, "{\"verb\":\"identify\",\"args\":[\"mz_q4...:int (2+ peaks, any order)\"]}," as *u8) 61 nj_puts(j, "{\"verb\":\"denovo\",\"args\":[\"precursor_q4:int\",\"b_ion_q4...:int (ascending ladder)\"]}" as *u8) 62 nj_puts(j, "]" as *u8) 63 nsvc_ok_close_g(j, GND_ASSERTED) 64 return 0 65} 66 67// ===== denovo: de novo sequencing -- sequence from a spectrum, no database = 68// 69// The crown jewel: given the precursor neutral mass and the b-ion ladder, 70// reconstruct the sequence with NO candidate. ANCHORED (residue masses + exact 71// gaps); the honest Leu/Ile ambiguity is REPORTED, not hidden. This answers 72// "what IS this peptide" where identify answered "which catalogued one". 73 74func qc_denovo(j: *NxJson, argc: i64, argv: *i64) -> i64 { 75 let precursor: i64 = nsvc_arg_int(argc, argv, 2) 76 if precursor <= 0 { 77 nsvc_error(j, QC_SVC, "denovo" as *u8, NSVC_ERR_BAD_ARGS, "precursor_q4 (neutral mass) must be positive, first arg" as *u8) 78 return 0 79 } 80 // b-ions are argv[3..], already ascending (a b-ion ladder is). 81 let ladder: *i64 = sys_mmap(256 * 8) 82 var nb: i64 = 0 83 var a: i64 = 3 84 while a < argc { 85 let v: i64 = nsvc_arg_int(argc, argv, a) 86 if v > 0 { ladder[nb] = v; nb = nb + 1 } 87 a = a + 1 88 } 89 if nb < 1 { 90 nsvc_error(j, QC_SVC, "denovo" as *u8, NSVC_ERR_BAD_ARGS, "need >=1 b-ion after the precursor mass" as *u8) 91 return 0 92 } 93 let out: *u8 = sys_mmap(256) 94 let len: i64 = denovo_sequence(ladder, nb, precursor, 50, out) 95 if len == DENOVO_UNKNOWN { 96 nsvc_error(j, QC_SVC, "denovo" as *u8, NSVC_ERR_REFUSED, "a mass gap matches no residue (corrupt/incomplete ladder) -- refusing a wrong sequence" as *u8) 97 return 0 98 } 99 let amb: i64 = denovo_ambiguous_count(ladder, nb, precursor, 50) 100 nsvc_ok_open(j, QC_SVC, "denovo" as *u8) 101 nj_kv_int(j, "precursor_q4" as *u8, precursor) 102 nj_comma(j) 103 nj_kv_int(j, "n_b_ions" as *u8, nb) 104 nj_comma(j) 105 nj_kv_str(j, "sequence" as *u8, out) 106 nj_comma(j) 107 nj_kv_int(j, "length" as *u8, len) 108 nj_comma(j) 109 nj_kv_int(j, "leu_ile_ambiguous_positions" as *u8, amb) 110 nsvc_ok_close_g(j, GND_ANCHORED) 111 return 0 112} 113 114// ===== identify: the flagship -- raw spectrum in, identity out ========= 115// 116// Takes the multiply-charged peak list (argv[2..], any order), deconvolves it 117// to a neutral mass, screens the catalog, and returns the identification with 118// a confidence that REFUSES to name noise. The end-to-end SOTA capstone. 119// Tagged ASSERTED because the actionable verdict includes the catalog's 120// regulatory status; the recovered MASS is separately verifiable via `deconv` 121// (which reports ANCHORED). Honest weakest-link. 122 123func qc_identify(j: *NxJson, argc: i64, argv: *i64) -> i64 { 124 // collect peaks from argv[2..] and sort ascending (simple insertion). 125 let peaks: *i64 = sys_mmap(512 * 8) 126 var np: i64 = 0 127 var a: i64 = 2 128 while a < argc { 129 let v: i64 = nsvc_arg_int(argc, argv, a) 130 if v > 0 { 131 // insertion sort into ascending order: shift larger elements right, 132 // then drop v into the gap. Flag loop (no break in NishiLang). 133 var q: i64 = np 134 var placed: i64 = 0 135 while placed == 0 { 136 if q == 0 { peaks[0] = v; placed = 1 } 137 if placed == 0 { 138 if peaks[q - 1] <= v { peaks[q] = v; placed = 1 } else { peaks[q] = peaks[q - 1]; q = q - 1 } 139 } 140 } 141 np = np + 1 142 } 143 a = a + 1 144 } 145 if np < 2 { 146 nsvc_error(j, QC_SVC, "identify" as *u8, NSVC_ERR_BAD_ARGS, "need >=2 m/z peaks to deconvolve a charge ladder" as *u8) 147 return 0 148 } 149 let r: *NxIdentResult = nx_identify_spectrum(peaks, np, 100) 150 nsvc_ok_open(j, QC_SVC, "identify" as *u8) 151 nj_kv_int(j, "n_peaks" as *u8, np) 152 nj_comma(j) 153 nj_kv_int(j, "neutral_mass_q4" as *u8, r.neutral_mass_q4) 154 nj_comma(j) 155 nj_kv_int(j, "charge_support" as *u8, r.charge_support) 156 nj_comma(j) 157 nj_kv_bool(j, "confident" as *u8, r.confident) 158 nj_comma(j) 159 nj_kv_int(j, "matched_entry" as *u8, r.matched_entry) 160 nj_comma(j) 161 nj_kv_str(j, "identified_sequence" as *u8, ident_sequence(r)) 162 nj_comma(j) 163 nj_kv_int(j, "mass_error_ppm_q1" as *u8, r.mass_error_ppm_q1) 164 nj_comma(j) 165 nj_kv_bool(j, "prohibited" as *u8, ident_is_prohibited(r)) 166 nj_comma(j) 167 nj_kv_str(j, "mass_grounding" as *u8, "ANCHORED" as *u8) 168 nsvc_ok_close_g(j, GND_ASSERTED) 169 return 0 170} 171 172// ===== deconv: recover a neutral mass from two multiply-charged peaks = 173// 174// The inverse of the charge ladder. Given two adjacent-charge-state peaks 175// (mz_lo = higher charge / lower m/z; mz_hi = lower charge / higher m/z), 176// deduce the charges and the neutral monoisotopic mass, and report whether the 177// pair is self-consistent. ANCHORED (exact arithmetic + anchored proton). This 178// reduces an unknown electrospray spectrum to a mass the catalog can screen. 179 180func qc_deconv(j: *NxJson, mz_lo: i64, mz_hi: i64) -> i64 { 181 if mz_lo <= 0 { 182 nsvc_error(j, QC_SVC, "deconv" as *u8, NSVC_ERR_BAD_ARGS, "mz values must be positive Q4" as *u8) 183 return 0 184 } 185 if mz_hi <= mz_lo { 186 nsvc_error(j, QC_SVC, "deconv" as *u8, NSVC_ERR_BAD_ARGS, "mz_hi must exceed mz_lo (lower m/z = higher charge)" as *u8) 187 return 0 188 } 189 let z_hi: i64 = deconv_charge_hi(mz_lo, mz_hi) 190 if z_hi <= 0 { 191 nsvc_error(j, QC_SVC, "deconv" as *u8, NSVC_ERR_REFUSED, "peaks are not an adjacent charge-state pair" as *u8) 192 return 0 193 } 194 let mass: i64 = deconv_neutral_mass(mz_lo, mz_hi) 195 nsvc_ok_open(j, QC_SVC, "deconv" as *u8) 196 nj_kv_int(j, "mz_lo_q4" as *u8, mz_lo) 197 nj_comma(j) 198 nj_kv_int(j, "mz_hi_q4" as *u8, mz_hi) 199 nj_comma(j) 200 nj_kv_int(j, "charge_of_mz_hi" as *u8, z_hi) 201 nj_comma(j) 202 nj_kv_int(j, "charge_of_mz_lo" as *u8, z_hi + 1) 203 nj_comma(j) 204 nj_kv_int(j, "neutral_mass_q4" as *u8, mass) 205 nj_comma(j) 206 nj_kv_bool(j, "pair_consistent" as *u8, deconv_pair_consistent(mz_lo, mz_hi, 100)) 207 nsvc_ok_close_g(j, GND_ANCHORED) 208 return 0 209} 210 211// ===== msms: the theoretical b/y fragment ladder a lab matches against = 212// 213// Given a peptide sequence, the predicted b-ion and y-ion m/z values -- the 214// target spectrum an MS/MS run tries to reproduce to confirm identity. ANCHORED 215// (b/y masses from the anchored residue table). This is the reference a lab 216// searches an observed spectrum against. 217 218func qc_msms(j: *NxJson, seq: *u8) -> i64 { 219 if seq[0] == (0 as u8) { 220 nsvc_error(j, QC_SVC, "msms" as *u8, NSVC_ERR_BAD_ARGS, "empty sequence" as *u8) 221 return 0 222 } 223 if pep_seq_valid(seq) != 1 { 224 nsvc_error(j, QC_SVC, "msms" as *u8, NSVC_ERR_REFUSED, "sequence has a non-standard residue (refused)" as *u8) 225 return 0 226 } 227 let n: i64 = pep_len(seq) 228 nsvc_ok_open(j, QC_SVC, "msms" as *u8) 229 nj_kv_str(j, "sequence" as *u8, seq) 230 nj_comma(j) 231 nj_kv_int(j, "n_fragments" as *u8, msms_theoretical_count(seq)) 232 nj_comma(j) 233 nj_key(j, "b_ions_q4" as *u8) 234 nj_puts(j, "[" as *u8) 235 var i: i64 = 1 236 while i < n { 237 if i > 1 { nj_comma(j) } 238 nj_puti(j, pep_b_ion_q4(seq, i)) 239 i = i + 1 240 } 241 nj_puts(j, "]" as *u8) 242 nj_comma(j) 243 nj_key(j, "y_ions_q4" as *u8) 244 nj_puts(j, "[" as *u8) 245 var k: i64 = 1 246 while k < n { 247 if k > 1 { nj_comma(j) } 248 nj_puti(j, pep_y_ion_q4(seq, k)) 249 k = k + 1 250 } 251 nj_puts(j, "]" as *u8) 252 nsvc_ok_close_g(j, GND_ANCHORED) 253 return 0 254} 255 256// ===== envelope: the isotopic pattern a high-res MS observes =========== 257// 258// Given a peptide sequence, the M / M+1 / M+2 relative intensities and which 259// peak is actually tallest. This is ANCHORED (NIST isotope abundances + exact 260// combinatorics + published cross-check), so -- unlike the regulatory-status 261// fields elsewhere in this facade -- it reports verified:true. Same facade, 262// honestly different grounding per verb. 263 264func qc_envelope(j: *NxJson, seq: *u8) -> i64 { 265 if seq[0] == (0 as u8) { 266 nsvc_error(j, QC_SVC, "envelope" as *u8, NSVC_ERR_BAD_ARGS, "empty sequence" as *u8) 267 return 0 268 } 269 if pep_seq_valid(seq) != 1 { 270 nsvc_error(j, QC_SVC, "envelope" as *u8, NSVC_ERR_REFUSED, "sequence has a non-standard residue (refused)" as *u8) 271 return 0 272 } 273 let ff: *NxFormula = pfm_formula(seq) 274 nsvc_ok_open(j, QC_SVC, "envelope" as *u8) 275 nj_kv_str(j, "sequence" as *u8, seq) 276 nj_comma(j) 277 nj_kv_int(j, "monoisotopic_mass_q4" as *u8, pep_mass_mono_q4(seq)) 278 nj_comma(j) 279 nj_kv_int(j, "carbons" as *u8, ff.c) 280 nj_comma(j) 281 nj_kv_int(j, "m_plus_0_permil" as *u8, 1000) 282 nj_comma(j) 283 nj_kv_int(j, "m_plus_1_permil" as *u8, iso_m1_permil(seq)) 284 nj_comma(j) 285 nj_kv_int(j, "m_plus_2_permil" as *u8, iso_m2_permil(seq)) 286 nj_comma(j) 287 nj_kv_int(j, "base_peak" as *u8, iso_base_peak(seq)) 288 nj_comma(j) 289 nj_kv_bool(j, "monoisotopic_is_base_peak" as *u8, iso_monoisotopic_is_base_peak(seq)) 290 // ANCHORED: isotope abundances + exact combinatorics + published cross-check. 291 nsvc_ok_close_g(j, GND_ANCHORED) 292 return 0 293} 294 295// ===== screen: which prohibited peptide is this peak? ================= 296// 297// The spiked-sample question. Scans the catalog across charge states 1..4, 298// returns the matched entry, the charge it matched at, and its regulatory 299// standing. A no-match is a first-class result (found=-1), not an error -- 300// a clean sample legitimately matches nothing. 301 302func qc_screen(j: *NxJson, mz_q4: i64, tol_ppm_q1: i64) -> i64 { 303 if mz_q4 <= 0 { 304 nsvc_error(j, QC_SVC, "screen" as *u8, NSVC_ERR_BAD_ARGS, "observed_mz_q4 must be positive" as *u8) 305 return 0 306 } 307 let hit: i64 = sup_screen(mz_q4, tol_ppm_q1) 308 var matched: i64 = 0 309 if hit != SUP_NO_MATCH { matched = 1 } 310 nsvc_ok_open(j, QC_SVC, "screen" as *u8) 311 nj_kv_int(j, "observed_mz_q4" as *u8, mz_q4) 312 nj_comma(j) 313 nj_kv_int(j, "tol_ppm_q1" as *u8, tol_ppm_q1) 314 nj_comma(j) 315 nj_kv_bool(j, "matched" as *u8, matched) 316 nj_comma(j) 317 nj_kv_int(j, "matched_entry" as *u8, hit) 318 if hit != SUP_NO_MATCH { 319 let z: i64 = sup_match_charge(hit, mz_q4, tol_ppm_q1) 320 nj_comma(j) 321 nj_kv_str(j, "sequence" as *u8, sup_seq(hit)) 322 nj_comma(j) 323 nj_kv_int(j, "at_charge" as *u8, z) 324 nj_comma(j) 325 nj_kv_int(j, "regulatory_status" as *u8, sup_status(hit)) 326 nj_comma(j) 327 nj_kv_bool(j, "prohibited" as *u8, sup_is_prohibited(hit)) 328 } 329 nsvc_ok_close_g(j, GND_ASSERTED) 330 return 0 331} 332 333// ===== detect: a compound's mass, charge ladder, and blind-spot flag == 334 335func qc_detect(j: *NxJson, id: i64) -> i64 { 336 if id < 0 { 337 nsvc_error(j, QC_SVC, "detect" as *u8, NSVC_ERR_NOT_FOUND, "no such catalog entry" as *u8) 338 return 0 339 } 340 if id >= SUP_N_ENTRY { 341 nsvc_error(j, QC_SVC, "detect" as *u8, NSVC_ERR_NOT_FOUND, "no such catalog entry" as *u8) 342 return 0 343 } 344 let mass: i64 = sup_mass_q4(id) 345 if mass == PEP_INVALID { 346 nsvc_error(j, QC_SVC, "detect" as *u8, NSVC_ERR_REFUSED, "catalog sequence has a non-standard residue (refused)" as *u8) 347 return 0 348 } 349 nsvc_ok_open(j, QC_SVC, "detect" as *u8) 350 nj_kv_int(j, "entry_id" as *u8, id) 351 nj_comma(j) 352 nj_kv_str(j, "sequence" as *u8, sup_seq(id)) 353 nj_comma(j) 354 nj_kv_int(j, "monoisotopic_mass_q4" as *u8, mass) 355 nj_comma(j) 356 nj_kv_int(j, "mh_plus_q4" as *u8, sup_mz_q4(id, 1)) 357 nj_comma(j) 358 nj_kv_int(j, "m2h_plus_q4" as *u8, sup_mz_q4(id, 2)) 359 nj_comma(j) 360 nj_kv_int(j, "m3h_plus_q4" as *u8, sup_mz_q4(id, 3)) 361 nj_comma(j) 362 nj_kv_bool(j, "mh_plus_in_scan_window" as *u8, sup_mh_plus_in_range(id)) 363 nj_comma(j) 364 nj_kv_int(j, "charges_in_window" as *u8, sup_detectable_charges_in_range(id)) 365 nj_comma(j) 366 nj_kv_bool(j, "single_charge_blind_spot" as *u8, sup_single_charge_blind_spot(id)) 367 nj_comma(j) 368 nj_kv_bool(j, "prohibited" as *u8, sup_is_prohibited(id)) 369 nsvc_ok_close_g(j, GND_ASSERTED) 370 return 0 371} 372 373// ===== label: USP dose recovery + verdict ============================= 374 375func qc_label(j: *NxJson, measured: i64, declared: i64) -> i64 { 376 if declared <= 0 { 377 nsvc_error(j, QC_SVC, "label" as *u8, NSVC_ERR_BAD_ARGS, "declared_ug must be positive" as *u8) 378 return 0 379 } 380 if measured < 0 { 381 nsvc_error(j, QC_SVC, "label" as *u8, NSVC_ERR_BAD_ARGS, "measured_ug cannot be negative" as *u8) 382 return 0 383 } 384 nsvc_ok_open(j, QC_SVC, "label" as *u8) 385 nj_kv_int(j, "measured_ug" as *u8, measured) 386 nj_comma(j) 387 nj_kv_int(j, "declared_ug" as *u8, declared) 388 nj_comma(j) 389 nj_kv_int(j, "recovery_pct" as *u8, sup_recovery_pct(measured, declared)) 390 nj_comma(j) 391 nj_kv_bool(j, "label_compliant" as *u8, sup_label_compliant(measured, declared)) 392 nj_comma(j) 393 nj_kv_int(j, "dose_verdict" as *u8, sup_dose_verdict(measured, declared)) 394 nsvc_ok_close_g(j, GND_ASSERTED) 395 return 0 396} 397 398// ===== dispatch ======================================================= 399 400func qc_dispatch(argc: i64, argv: *i64, j: *NxJson) -> i64 { 401 let verb: *u8 = nsvc_arg(argc, argv, 1) 402 if verb[0] == (0 as u8) { qc_describe(j); return 0 } 403 if nsvc_streq(verb, "describe" as *u8) == 1 { qc_describe(j); return 0 } 404 if nsvc_streq(verb, "screen" as *u8) == 1 { 405 qc_screen(j, nsvc_arg_int(argc, argv, 2), nsvc_arg_int(argc, argv, 3)) 406 return 0 407 } 408 if nsvc_streq(verb, "detect" as *u8) == 1 { 409 qc_detect(j, nsvc_arg_int(argc, argv, 2)) 410 return 0 411 } 412 if nsvc_streq(verb, "label" as *u8) == 1 { 413 qc_label(j, nsvc_arg_int(argc, argv, 2), nsvc_arg_int(argc, argv, 3)) 414 return 0 415 } 416 if nsvc_streq(verb, "envelope" as *u8) == 1 { 417 qc_envelope(j, nsvc_arg(argc, argv, 2)) 418 return 0 419 } 420 if nsvc_streq(verb, "msms" as *u8) == 1 { 421 qc_msms(j, nsvc_arg(argc, argv, 2)) 422 return 0 423 } 424 if nsvc_streq(verb, "deconv" as *u8) == 1 { 425 qc_deconv(j, nsvc_arg_int(argc, argv, 2), nsvc_arg_int(argc, argv, 3)) 426 return 0 427 } 428 if nsvc_streq(verb, "identify" as *u8) == 1 { 429 qc_identify(j, argc, argv) 430 return 0 431 } 432 if nsvc_streq(verb, "denovo" as *u8) == 1 { 433 qc_denovo(j, argc, argv) 434 return 0 435 } 436 nsvc_error(j, QC_SVC, verb, NSVC_ERR_UNKNOWN_VERB, "unknown verb; call describe for the catalog" as *u8) 437 return 1 438} 439 440func main(argc: i64, argv: *i64) -> i64 { 441 let j: *NxJson = nx_json_new(QC_MAGIC_8192) 442 let rc: i64 = qc_dispatch(argc, argv, j) 443 nj_flush(j) 444 return rc 445}