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}