OpenMS
Loading...
Searching...
No Matches
ProFormaDataJson.h
Go to the documentation of this file.
1// Copyright (c) 2002-present, OpenMS Inc. -- EKU Tuebingen, ETH Zurich, and FU Berlin
2// SPDX-License-Identifier: BSD-3-Clause
3//
4// --------------------------------------------------------------------------
5// $Maintainer: Timo Sachsenberg $
6// $Authors: Timo Sachsenberg $
7// --------------------------------------------------------------------------
8
9#pragma once
10
12#include <nlohmann/json.hpp>
13
14namespace OpenMS
15{
16
17 //--------------------------------------------------------------------------
18 // JSON Serialization (nlohmann/json ADL pattern)
19 //--------------------------------------------------------------------------
20
23
25 inline void to_json(nlohmann::json& j, const ProForma::CvDatabase& db)
26 {
27 switch (db)
28 {
29 case ProForma::CvDatabase::UNIMOD: j = "UNIMOD"; break;
30 case ProForma::CvDatabase::MOD: j = "MOD"; break;
31 case ProForma::CvDatabase::RESID: j = "RESID"; break;
32 case ProForma::CvDatabase::XLMOD: j = "XLMOD"; break;
33 case ProForma::CvDatabase::GNO: j = "GNO"; break;
34 }
35 }
36
38 inline void from_json(const nlohmann::json& j, ProForma::CvDatabase& db)
39 {
40 std::string s = j.get<std::string>();
41 if (s == "UNIMOD") db = ProForma::CvDatabase::UNIMOD;
42 else if (s == "MOD") db = ProForma::CvDatabase::MOD;
43 else if (s == "RESID") db = ProForma::CvDatabase::RESID;
44 else if (s == "XLMOD") db = ProForma::CvDatabase::XLMOD;
45 else if (s == "GNO") db = ProForma::CvDatabase::GNO;
46 else throw std::invalid_argument("Unknown ProForma::CvDatabase: " + s);
47 }
48
50
51
54
56 inline void to_json(nlohmann::json& j, const ProForma::CvAccession& cv)
57 {
58 j = nlohmann::json{{"database", cv.database}, {"accession", static_cast<std::string>(cv.accession)}};
59 }
60
62 inline void from_json(const nlohmann::json& j, ProForma::CvAccession& cv)
63 {
64 j.at("database").get_to(cv.database);
65 cv.accession = j.at("accession").get<std::string>();
66 }
67
69
70
73
75 inline void to_json(nlohmann::json& j, const ProForma::NamedMod& nm)
76 {
77 j = nlohmann::json{{"name", static_cast<std::string>(nm.name)}};
78 if (nm.cv_hint.has_value())
79 {
80 j["cv_hint"] = nm.cv_hint.value();
81 }
82 }
83
85 inline void from_json(const nlohmann::json& j, ProForma::NamedMod& nm)
86 {
87 nm.name = j.at("name").get<std::string>();
88 if (j.contains("cv_hint") && !j.at("cv_hint").is_null())
89 {
90 nm.cv_hint = j.at("cv_hint").get<ProForma::CvDatabase>();
91 }
92 else
93 {
94 nm.cv_hint = std::nullopt;
95 }
96 }
97
99
100
103
105 inline void to_json(nlohmann::json& j, const ProForma::MassDelta::Source& src)
106 {
107 switch (src)
108 {
109 case ProForma::MassDelta::Source::NONE: j = "NONE"; break;
110 case ProForma::MassDelta::Source::OBS: j = "OBS"; break;
111 case ProForma::MassDelta::Source::U: j = "U"; break;
112 case ProForma::MassDelta::Source::M: j = "M"; break;
113 case ProForma::MassDelta::Source::R: j = "R"; break;
114 case ProForma::MassDelta::Source::X: j = "X"; break;
115 case ProForma::MassDelta::Source::G: j = "G"; break;
116 }
117 }
118
120 inline void from_json(const nlohmann::json& j, ProForma::MassDelta::Source& src)
121 {
122 std::string s = j.get<std::string>();
123 if (s == "NONE") src = ProForma::MassDelta::Source::NONE;
124 else if (s == "OBS") src = ProForma::MassDelta::Source::OBS;
125 else if (s == "U") src = ProForma::MassDelta::Source::U;
126 else if (s == "M") src = ProForma::MassDelta::Source::M;
127 else if (s == "R") src = ProForma::MassDelta::Source::R;
128 else if (s == "X") src = ProForma::MassDelta::Source::X;
129 else if (s == "G") src = ProForma::MassDelta::Source::G;
130 else throw std::invalid_argument("Unknown ProForma::MassDelta::Source: " + s);
131 }
132
134
135
138
140 inline void to_json(nlohmann::json& j, const ProForma::MassDelta& md)
141 {
142 j = nlohmann::json{
143 {"source", md.source},
144 {"mass", md.mass},
145 {"original_text", static_cast<std::string>(md.original_text)}
146 };
147 }
148
150 inline void from_json(const nlohmann::json& j, ProForma::MassDelta& md)
151 {
152 j.at("source").get_to(md.source);
153 j.at("mass").get_to(md.mass);
154 md.original_text = j.at("original_text").get<std::string>();
155 }
156
158
159
162
164 inline void to_json(nlohmann::json& j, const ProForma::FormulaTag& ft)
165 {
166 j = nlohmann::json{{"formula_string", static_cast<std::string>(ft.formula_string)}};
167 if (ft.charge.has_value())
168 {
169 j["charge"] = ft.charge.value();
170 }
171 }
172
174 inline void from_json(const nlohmann::json& j, ProForma::FormulaTag& ft)
175 {
176 ft.formula_string = j.at("formula_string").get<std::string>();
177 if (j.contains("charge") && !j.at("charge").is_null())
178 {
179 ft.charge = j.at("charge").get<int>();
180 }
181 else
182 {
183 ft.charge = std::nullopt;
184 }
185 }
186
188
189
192
194 inline void to_json(nlohmann::json& j, const ProForma::GlycanComposition::Monosaccharide& mono)
195 {
196 std::visit([&j](auto&& arg) {
197 using T = std::decay_t<decltype(arg)>;
198 if constexpr (std::is_same_v<T, OpenMS::String>)
199 {
200 j = nlohmann::json{{"type", "name"}, {"value", static_cast<std::string>(arg)}};
201 }
202 else if constexpr (std::is_same_v<T, ProForma::FormulaTag>)
203 {
204 j = nlohmann::json{{"type", "formula"}, {"value", arg}};
205 }
206 }, mono);
207 }
208
210 inline void from_json(const nlohmann::json& j, ProForma::GlycanComposition::Monosaccharide& mono)
211 {
212 std::string type = j.at("type").get<std::string>();
213 if (type == "name")
214 {
215 mono = String(j.at("value").get<std::string>());
216 }
217 else if (type == "formula")
218 {
219 mono = j.at("value").get<ProForma::FormulaTag>();
220 }
221 else
222 {
223 throw std::invalid_argument("Unknown ProForma::GlycanComposition::Monosaccharide type: " + type);
224 }
225 }
226
228
229
232
234 inline void to_json(nlohmann::json& j, const ProForma::GlycanComposition& gc)
235 {
236 j = nlohmann::json::array();
237 for (const auto& [mono, count] : gc.components)
238 {
239 nlohmann::json component;
240 component["monosaccharide"] = mono;
241 component["count"] = count;
242 j.push_back(component);
243 }
244 }
245
247 inline void from_json(const nlohmann::json& j, ProForma::GlycanComposition& gc)
248 {
249 gc.components.clear();
250 for (const auto& item : j)
251 {
253 from_json(item.at("monosaccharide"), mono);
254 int count = item.at("count").get<int>();
255 gc.components.emplace_back(mono, count);
256 }
257 }
258
260
261
264
266 inline void to_json(nlohmann::json& j, const ProForma::InfoTag& it)
267 {
268 j = nlohmann::json{{"text", static_cast<std::string>(it.text)}};
269 }
270
272 inline void from_json(const nlohmann::json& j, ProForma::InfoTag& it)
273 {
274 it.text = j.at("text").get<std::string>();
275 }
276
278
279
282
284 inline void to_json(nlohmann::json& j, const ProForma::PositionConstraint& pc)
285 {
286 j = nlohmann::json{
287 {"residues", std::string(pc.residues.begin(), pc.residues.end())},
288 {"n_term", pc.n_term},
289 {"c_term", pc.c_term}
290 };
291 }
292
294 inline void from_json(const nlohmann::json& j, ProForma::PositionConstraint& pc)
295 {
296 std::string residue_str = j.at("residues").get<std::string>();
297 pc.residues.assign(residue_str.begin(), residue_str.end());
298 if (j.contains("n_term")) pc.n_term = j.at("n_term").get<bool>();
299 if (j.contains("c_term")) pc.c_term = j.at("c_term").get<bool>();
300 }
301
303
304
307
309 inline void to_json(nlohmann::json& j, const ProForma::ModificationTag& tag)
310 {
311 std::visit([&j](auto&& arg) {
312 using T = std::decay_t<decltype(arg)>;
313 if constexpr (std::is_same_v<T, ProForma::CvAccession>)
314 {
315 j = nlohmann::json{{"type", "cv_accession"}, {"value", arg}};
316 }
317 else if constexpr (std::is_same_v<T, ProForma::NamedMod>)
318 {
319 j = nlohmann::json{{"type", "named_mod"}, {"value", arg}};
320 }
321 else if constexpr (std::is_same_v<T, ProForma::MassDelta>)
322 {
323 j = nlohmann::json{{"type", "mass_delta"}, {"value", arg}};
324 }
325 else if constexpr (std::is_same_v<T, ProForma::FormulaTag>)
326 {
327 j = nlohmann::json{{"type", "formula"}, {"value", arg}};
328 }
329 else if constexpr (std::is_same_v<T, ProForma::GlycanComposition>)
330 {
331 j = nlohmann::json{{"type", "glycan"}, {"value", arg}};
332 }
333 else if constexpr (std::is_same_v<T, ProForma::InfoTag>)
334 {
335 j = nlohmann::json{{"type", "info"}, {"value", arg}};
336 }
337 else if constexpr (std::is_same_v<T, ProForma::PositionConstraint>)
338 {
339 j = nlohmann::json{{"type", "position"}, {"value", arg}};
340 }
341 }, tag);
342 }
343
345 inline void from_json(const nlohmann::json& j, ProForma::ModificationTag& tag)
346 {
347 std::string type = j.at("type").get<std::string>();
348 if (type == "cv_accession")
349 {
350 tag = j.at("value").get<ProForma::CvAccession>();
351 }
352 else if (type == "named_mod")
353 {
354 tag = j.at("value").get<ProForma::NamedMod>();
355 }
356 else if (type == "mass_delta")
357 {
358 tag = j.at("value").get<ProForma::MassDelta>();
359 }
360 else if (type == "formula")
361 {
362 tag = j.at("value").get<ProForma::FormulaTag>();
363 }
364 else if (type == "glycan")
365 {
366 tag = j.at("value").get<ProForma::GlycanComposition>();
367 }
368 else if (type == "info")
369 {
370 tag = j.at("value").get<ProForma::InfoTag>();
371 }
372 else if (type == "position")
373 {
374 tag = j.at("value").get<ProForma::PositionConstraint>();
375 }
376 else
377 {
378 throw std::invalid_argument("Unknown ProForma::ModificationTag type: " + type);
379 }
380 }
381
383
384
387
389 inline void to_json(nlohmann::json& j, const ProForma::Label::Type& lt)
390 {
391 switch (lt)
392 {
393 case ProForma::Label::Type::CROSSLINK: j = "CROSSLINK"; break;
394 case ProForma::Label::Type::BRANCH: j = "BRANCH"; break;
395 case ProForma::Label::Type::AMBIGUOUS: j = "AMBIGUOUS"; break;
396 }
397 }
398
400 inline void from_json(const nlohmann::json& j, ProForma::Label::Type& lt)
401 {
402 std::string s = j.get<std::string>();
403 if (s == "CROSSLINK") lt = ProForma::Label::Type::CROSSLINK;
404 else if (s == "BRANCH") lt = ProForma::Label::Type::BRANCH;
405 else if (s == "AMBIGUOUS") lt = ProForma::Label::Type::AMBIGUOUS;
406 else throw std::invalid_argument("Unknown ProForma::Label::Type: " + s);
407 }
408
410
411
414
416 inline void to_json(nlohmann::json& j, const ProForma::Label& lbl)
417 {
418 j = nlohmann::json{
419 {"type", lbl.type},
420 {"identifier", static_cast<std::string>(lbl.identifier)}
421 };
422 if (lbl.score.has_value())
423 {
424 j["score"] = lbl.score.value();
425 }
426 }
427
429 inline void from_json(const nlohmann::json& j, ProForma::Label& lbl)
430 {
431 j.at("type").get_to(lbl.type);
432 lbl.identifier = j.at("identifier").get<std::string>();
433 if (j.contains("score") && !j.at("score").is_null())
434 {
435 lbl.score = j.at("score").get<double>();
436 }
437 else
438 {
439 lbl.score = std::nullopt;
440 }
441 }
442
444
445
448
450 inline void to_json(nlohmann::json& j, const ProForma::Modification& mod)
451 {
452 j = nlohmann::json::array();
453 for (const auto& [tag, label] : mod.alternatives)
454 {
455 nlohmann::json alt;
456 alt["tag"] = tag;
457 if (label.has_value())
458 {
459 alt["label"] = label.value();
460 }
461 j.push_back(alt);
462 }
463 }
464
466 inline void from_json(const nlohmann::json& j, ProForma::Modification& mod)
467 {
468 mod.alternatives.clear();
469 mod.resolved_mod = nullptr; // Reset to avoid stale pointers
470 for (const auto& item : j)
471 {
472 ProForma::ModificationTag tag = item.at("tag").get<ProForma::ModificationTag>();
473 std::optional<ProForma::Label> label;
474 if (item.contains("label") && !item.at("label").is_null())
475 {
476 label = item.at("label").get<ProForma::Label>();
477 }
478 mod.alternatives.emplace_back(tag, label);
479 }
480 }
481
483
484
487
489 inline void to_json(nlohmann::json& j, const ProForma::SequenceElement& se)
490 {
491 j = nlohmann::json{
492 {"amino_acid", std::string(1, se.amino_acid)},
493 {"modifications", se.modifications}
494 };
495 }
496
498 inline void from_json(const nlohmann::json& j, ProForma::SequenceElement& se)
499 {
500 std::string aa = j.at("amino_acid").get<std::string>();
501 if (aa.size() != 1)
502 {
503 throw std::invalid_argument("amino_acid must be exactly 1 character, got length " + std::to_string(aa.size()));
504 }
505 se.amino_acid = aa[0];
506 j.at("modifications").get_to(se.modifications);
507 }
508
510
511
514
516 inline void to_json(nlohmann::json& j, const ProForma::AmbiguousRegion& ar)
517 {
518 j = nlohmann::json{{"elements", ar.elements}};
519 }
520
522 inline void from_json(const nlohmann::json& j, ProForma::AmbiguousRegion& ar)
523 {
524 j.at("elements").get_to(ar.elements);
525 }
526
528
529
532
534 inline void to_json(nlohmann::json& j, const ProForma::ModifiedRange& mr)
535 {
536 j = nlohmann::json{
537 {"elements", mr.elements},
538 {"modifications", mr.modifications}
539 };
540 }
541
543 inline void from_json(const nlohmann::json& j, ProForma::ModifiedRange& mr)
544 {
545 j.at("elements").get_to(mr.elements);
546 j.at("modifications").get_to(mr.modifications);
547 }
548
550
551
554
556 inline void to_json(nlohmann::json& j, const ProForma::SequenceSection& ss)
557 {
558 std::visit([&j](auto&& arg) {
559 using T = std::decay_t<decltype(arg)>;
560 if constexpr (std::is_same_v<T, ProForma::SequenceElement>)
561 {
562 j = nlohmann::json{{"type", "element"}, {"value", arg}};
563 }
564 else if constexpr (std::is_same_v<T, ProForma::AmbiguousRegion>)
565 {
566 j = nlohmann::json{{"type", "ambiguous_region"}, {"value", arg}};
567 }
568 else if constexpr (std::is_same_v<T, ProForma::ModifiedRange>)
569 {
570 j = nlohmann::json{{"type", "modified_range"}, {"value", arg}};
571 }
572 }, ss);
573 }
574
576 inline void from_json(const nlohmann::json& j, ProForma::SequenceSection& ss)
577 {
578 std::string type = j.at("type").get<std::string>();
579 if (type == "element")
580 {
581 ss = j.at("value").get<ProForma::SequenceElement>();
582 }
583 else if (type == "ambiguous_region")
584 {
585 ss = j.at("value").get<ProForma::AmbiguousRegion>();
586 }
587 else if (type == "modified_range")
588 {
589 ss = j.at("value").get<ProForma::ModifiedRange>();
590 }
591 else
592 {
593 throw std::invalid_argument("Unknown ProForma::SequenceSection type: " + type);
594 }
595 }
596
598
599
602
604 inline void to_json(nlohmann::json& j, const ProForma::UnlocalisedMod& um)
605 {
606 j = nlohmann::json{{"modifications", um.modifications}};
607 if (um.occurrence.has_value())
608 {
609 j["occurrence"] = um.occurrence.value();
610 }
611 }
612
614 inline void from_json(const nlohmann::json& j, ProForma::UnlocalisedMod& um)
615 {
616 j.at("modifications").get_to(um.modifications);
617 if (j.contains("occurrence") && !j.at("occurrence").is_null())
618 {
619 um.occurrence = j.at("occurrence").get<int>();
620 }
621 else
622 {
623 um.occurrence = std::nullopt;
624 }
625 }
626
628
629
632
634 inline void to_json(nlohmann::json& j, const ProForma::LabileModification& lm)
635 {
636 j = nlohmann::json{{"modification", lm.modification}};
637 }
638
640 inline void from_json(const nlohmann::json& j, ProForma::LabileModification& lm)
641 {
642 j.at("modification").get_to(lm.modification);
643 }
644
646
647
650
652 inline void to_json(nlohmann::json& j, const ProForma::GlobalModification& gm)
653 {
654 std::vector<std::string> locs;
655 for (const auto& loc : gm.locations)
656 {
657 locs.push_back(static_cast<std::string>(loc));
658 }
659 j = nlohmann::json{
660 {"modification", gm.modification},
661 {"locations", locs}
662 };
663 }
664
666 inline void from_json(const nlohmann::json& j, ProForma::GlobalModification& gm)
667 {
668 j.at("modification").get_to(gm.modification);
669 gm.locations.clear();
670 for (const auto& loc : j.at("locations"))
671 {
672 gm.locations.push_back(String(loc.get<std::string>()));
673 }
674 }
675
677
678
681
683 inline void to_json(nlohmann::json& j, const ProForma::IsotopeReplacement& ir)
684 {
685 j = nlohmann::json{{"isotope", static_cast<std::string>(ir.isotope)}};
686 }
687
689 inline void from_json(const nlohmann::json& j, ProForma::IsotopeReplacement& ir)
690 {
691 ir.isotope = j.at("isotope").get<std::string>();
692 }
693
695
696
699
701 inline void to_json(nlohmann::json& j, const ProForma::GlobalModEntry& gme)
702 {
703 std::visit([&j](auto&& arg) {
704 using T = std::decay_t<decltype(arg)>;
705 if constexpr (std::is_same_v<T, ProForma::IsotopeReplacement>)
706 {
707 j = nlohmann::json{{"type", "isotope_replacement"}, {"value", arg}};
708 }
709 else if constexpr (std::is_same_v<T, ProForma::GlobalModification>)
710 {
711 j = nlohmann::json{{"type", "global_modification"}, {"value", arg}};
712 }
713 }, gme);
714 }
715
717 inline void from_json(const nlohmann::json& j, ProForma::GlobalModEntry& gme)
718 {
719 std::string type = j.at("type").get<std::string>();
720 if (type == "isotope_replacement")
721 {
722 gme = j.at("value").get<ProForma::IsotopeReplacement>();
723 }
724 else if (type == "global_modification")
725 {
726 gme = j.at("value").get<ProForma::GlobalModification>();
727 }
728 else
729 {
730 throw std::invalid_argument("Unknown ProForma::GlobalModEntry type: " + type);
731 }
732 }
733
735
736
739
741 inline void to_json(nlohmann::json& j, const ProForma::AdductIon& ai)
742 {
743 j = nlohmann::json{
744 {"formula", static_cast<std::string>(ai.formula)},
745 {"charge", ai.charge}
746 };
747 if (ai.occurrence.has_value())
748 {
749 j["occurrence"] = ai.occurrence.value();
750 }
751 }
752
754 inline void from_json(const nlohmann::json& j, ProForma::AdductIon& ai)
755 {
756 ai.formula = j.at("formula").get<std::string>();
757 j.at("charge").get_to(ai.charge);
758 if (j.contains("occurrence") && !j.at("occurrence").is_null())
759 {
760 ai.occurrence = j.at("occurrence").get<int>();
761 }
762 else
763 {
764 ai.occurrence = std::nullopt;
765 }
766 }
767
769
770
773
775 inline void to_json(nlohmann::json& j, const ProForma::ChargeState& cs)
776 {
777 std::visit([&j](auto&& arg) {
778 using T = std::decay_t<decltype(arg)>;
779 if constexpr (std::is_same_v<T, int>)
780 {
781 j = nlohmann::json{{"type", "simple"}, {"value", arg}};
782 }
783 else if constexpr (std::is_same_v<T, std::vector<ProForma::AdductIon>>)
784 {
785 j = nlohmann::json{{"type", "adducts"}, {"value", arg}};
786 }
787 }, cs);
788 }
789
791 inline void from_json(const nlohmann::json& j, ProForma::ChargeState& cs)
792 {
793 std::string type = j.at("type").get<std::string>();
794 if (type == "simple")
795 {
796 cs = j.at("value").get<int>();
797 }
798 else if (type == "adducts")
799 {
800 cs = j.at("value").get<std::vector<ProForma::AdductIon>>();
801 }
802 else
803 {
804 throw std::invalid_argument("Unknown ProForma::ChargeState type: " + type);
805 }
806 }
807
809
810
813
815 inline void to_json(nlohmann::json& j, const ProForma::Peptidoform& pf)
816 {
817 j = nlohmann::json{
818 {"global_mods", pf.global_mods},
819 {"unlocalised_mods", pf.unlocalised_mods},
820 {"labile_mods", pf.labile_mods},
821 {"n_term_mods", pf.n_term_mods},
822 {"sequence", pf.sequence},
823 {"c_term_mods", pf.c_term_mods}
824 };
825 if (pf.name.has_value())
826 {
827 j["name"] = static_cast<std::string>(pf.name.value());
828 }
829 if (pf.charge.has_value())
830 {
831 j["charge"] = pf.charge.value();
832 }
833 }
834
836 inline void from_json(const nlohmann::json& j, ProForma::Peptidoform& pf)
837 {
838 if (j.contains("global_mods"))
839 {
840 j.at("global_mods").get_to(pf.global_mods);
841 }
842 else
843 {
844 pf.global_mods.clear(); // Clear when field is omitted
845 }
846 j.at("unlocalised_mods").get_to(pf.unlocalised_mods);
847 j.at("labile_mods").get_to(pf.labile_mods);
848 j.at("n_term_mods").get_to(pf.n_term_mods);
849 j.at("sequence").get_to(pf.sequence);
850 j.at("c_term_mods").get_to(pf.c_term_mods);
851 if (j.contains("name") && !j.at("name").is_null())
852 {
853 pf.name = String(j.at("name").get<std::string>());
854 }
855 else
856 {
857 pf.name = std::nullopt;
858 }
859 if (j.contains("charge") && !j.at("charge").is_null())
860 {
861 pf.charge = j.at("charge").get<ProForma::ChargeState>();
862 }
863 else
864 {
865 pf.charge = std::nullopt;
866 }
867 }
868
870
871
874
876 inline void to_json(nlohmann::json& j, const ProForma::PeptidoformIon& pfi)
877 {
878 j = nlohmann::json{{"chains", pfi.chains}, {"is_chimeric", pfi.is_chimeric}};
879 if (pfi.name.has_value())
880 {
881 j["name"] = static_cast<std::string>(pfi.name.value());
882 }
883 if (pfi.charge.has_value())
884 {
885 j["charge"] = pfi.charge.value();
886 }
887 }
888
890 inline void from_json(const nlohmann::json& j, ProForma::PeptidoformIon& pfi)
891 {
892 j.at("chains").get_to(pfi.chains);
893 if (j.contains("name") && !j.at("name").is_null())
894 {
895 pfi.name = String(j.at("name").get<std::string>());
896 }
897 else
898 {
899 pfi.name = std::nullopt;
900 }
901 if (j.contains("charge") && !j.at("charge").is_null())
902 {
903 pfi.charge = j.at("charge").get<ProForma::ChargeState>();
904 }
905 else
906 {
907 pfi.charge = std::nullopt;
908 }
909 if (j.contains("is_chimeric"))
910 {
911 pfi.is_chimeric = j.at("is_chimeric").get<bool>();
912 }
913 else
914 {
915 pfi.is_chimeric = false;
916 }
917 }
918
920
921
924
926 inline void to_json(nlohmann::json& j, const ProForma::CrossLinkGroup& clg)
927 {
928 nlohmann::json sites_json = nlohmann::json::array();
929 for (const auto& [chain_idx, site_idx] : clg.sites)
930 {
931 sites_json.push_back(nlohmann::json{{"chain_index", chain_idx}, {"site_index", site_idx}});
932 }
933 j = nlohmann::json{
934 {"label", static_cast<std::string>(clg.label)},
935 {"sites", sites_json}
936 };
937 }
938
940 inline void from_json(const nlohmann::json& j, ProForma::CrossLinkGroup& clg)
941 {
942 clg.label = j.at("label").get<std::string>();
943 clg.sites.clear();
944 for (const auto& site : j.at("sites"))
945 {
946 size_t chain_idx = site.at("chain_index").get<size_t>();
947 size_t site_idx = site.at("site_index").get<size_t>();
948 clg.sites.emplace_back(chain_idx, site_idx);
949 }
950 }
951
953
954
955 // Note: The convenience functions toJSON(), peptidoformFromJSON(), peptidoformIonFromJSON()
956 // are declared in ProFormaData.h and implemented in ProFormaDataJson.cpp.
957 // This header provides the nlohmann::json ADL overloads needed by those implementations.
958
959} // namespace OpenMS
CvDatabase database
The source database (UNIMOD, MOD, RESID, XLMOD, or GNO)
Definition ProForma.h:171
std::optional< ChargeState > charge
Optional per-chain charge (for chimeric spectra)
Definition ProForma.h:524
std::vector< Modification > n_term_mods
N-terminal modifications: [Acetyl]-.
Definition ProForma.h:521
std::vector< LabileModification > labile_mods
Labile modifications: {Glycan:Hex}.
Definition ProForma.h:520
std::vector< std::pair< ModificationTag, std::optional< Label > > > alternatives
Each alternative is a (tag, optional_label) pair.
Definition ProForma.h:339
const ResidueModification * resolved_mod
Definition ProForma.h:343
std::optional< int > occurrence
Optional occurrence count from ^N suffix.
Definition ProForma.h:414
String isotope
The isotope specification (e.g., "13C", "15N", "D")
Definition ProForma.h:457
bool is_chimeric
True if chains are chimeric (+ separator), false if cross-linked (//)
Definition ProForma.h:541
std::variant< SequenceElement, AmbiguousRegion, ModifiedRange > SequenceSection
Variant type representing a section of the sequence.
Definition ProForma.h:399
std::variant< CvAccession, NamedMod, MassDelta, FormulaTag, GlycanComposition, InfoTag, PositionConstraint > ModificationTag
Variant type representing any modification tag content.
Definition ProForma.h:297
std::vector< std::pair< Monosaccharide, int > > components
List of (monosaccharide, count) pairs.
Definition ProForma.h:244
String formula_string
The chemical formula string (e.g., "C12H20O2")
Definition ProForma.h:225
std::vector< SequenceSection > sequence
The sequence with modifications.
Definition ProForma.h:522
CvDatabase
Controlled vocabulary database prefix for modification accessions.
Definition ProForma.h:110
@ GNO
Glycan naming ontology.
@ XLMOD
Cross-linking modifications ontology.
@ UNIMOD
UniMod database (https://www.unimod.org/)
@ MOD
PSI-MOD ontology (https://www.ebi.ac.uk/ols/ontologies/mod)
String text
The info text content.
Definition ProForma.h:256
std::optional< int > charge
Optional charge from :z+N suffix.
Definition ProForma.h:226
std::variant< IsotopeReplacement, GlobalModification > GlobalModEntry
Variant type for global modification entries.
Definition ProForma.h:471
std::optional< CvDatabase > cv_hint
Optional CV prefix hint (U, M, R, X, G)
Definition ProForma.h:185
Modification modification
The labile modification.
Definition ProForma.h:428
std::vector< String > locations
Target locations ("K", "N-term", "C-term:K", etc.)
Definition ProForma.h:443
std::vector< Modification > modifications
Modifications at this position.
Definition ProForma.h:356
String name
The modification name (e.g., "Oxidation", "Phospho")
Definition ProForma.h:186
String accession
The accession identifier (e.g., "35" for UNIMOD:35, full string for GNO)
Definition ProForma.h:172
std::vector< Peptidoform > chains
One or more peptide chains (separated by // or + in ProForma)
Definition ProForma.h:539
std::vector< std::pair< size_t, size_t > > sites
(chain_index, site_index) pairs
Definition ProForma.h:556
std::variant< String, FormulaTag > Monosaccharide
A monosaccharide component: either a name (String) or a custom formula (FormulaTag)
Definition ProForma.h:242
String formula
The adduct formula (e.g., "Na", "H", "K")
Definition ProForma.h:484
std::vector< SequenceElement > elements
The ambiguous amino acid possibilities.
Definition ProForma.h:368
bool c_term
True if modification can be at C-terminus.
Definition ProForma.h:273
int charge
The charge contribution of this adduct.
Definition ProForma.h:485
std::variant< int, std::vector< AdductIon > > ChargeState
Charge state specification.
Definition ProForma.h:500
String label
The cross-link label (e.g., XL1)
Definition ProForma.h:555
std::optional< String > name
Optional name from (>name) v2.1 extension.
Definition ProForma.h:517
std::vector< GlobalModEntry > global_mods
Global modifications: <13C>, <[TMT6plex]@K>
Definition ProForma.h:518
bool n_term
True if modification can be at N-terminus.
Definition ProForma.h:272
std::vector< UnlocalisedMod > unlocalised_mods
Unlocalised modifications: [Phospho]?
Definition ProForma.h:519
std::vector< char > residues
List of allowed amino acid residues.
Definition ProForma.h:271
std::vector< Modification > c_term_mods
C-terminal modifications: -[Amidated].
Definition ProForma.h:523
char amino_acid
Single-letter amino acid code (A-Z)
Definition ProForma.h:355
Adduct ion specification for charge state.
Definition ProForma.h:483
Ambiguous amino acid region.
Definition ProForma.h:367
Cross-link group connecting sites across chains.
Definition ProForma.h:554
Controlled vocabulary accession for a modification.
Definition ProForma.h:170
Chemical formula with optional charge.
Definition ProForma.h:224
Global modification applied to specific locations.
Definition ProForma.h:441
Glycan composition specification.
Definition ProForma.h:240
Info tag for arbitrary text annotations.
Definition ProForma.h:255
Isotope replacement for stable isotope labeling.
Definition ProForma.h:456
Labile modification that may be lost during fragmentation.
Definition ProForma.h:427
A modification with one or more alternative tags.
Definition ProForma.h:337
Modified sequence range with shared modifications.
Definition ProForma.h:381
Named modification with optional CV prefix hint.
Definition ProForma.h:184
A single peptidoform (one peptide chain)
Definition ProForma.h:516
A peptidoform ion (one or more chains with optional charge)
Definition ProForma.h:537
Position constraint specifying allowed residues for a modification.
Definition ProForma.h:270
A single amino acid with its modifications.
Definition ProForma.h:354
Unlocalised modification with optional occurrence count.
Definition ProForma.h:412
A more convenient string class.
Definition String.h:34
Main OpenMS namespace.
Definition openswathalgo/include/OpenMS/OPENSWATHALGO/DATAACCESS/ISpectrumAccess.h:19
void to_json(nlohmann::json &j, const ProForma::CvDatabase &db)
Convert CvDatabase enum to JSON string.
Definition ProFormaDataJson.h:25
void from_json(const nlohmann::json &j, ProForma::CvDatabase &db)
Construct CvDatabase enum from JSON string.
Definition ProFormaDataJson.h:38
Label for cross-links, branches, or ambiguous grouping.
Definition ProForma.h:309
Type
The type of label.
Definition ProForma.h:312
@ AMBIGUOUS
Ambiguous localization group (e.g., #g1)
@ BRANCH
Branch point label (#BRANCH)
@ CROSSLINK
Cross-link label (e.g., #XL1)
std::optional< double > score
Optional localization score for ambiguous labels (e.g., 0.90)
Definition ProForma.h:320
Type type
The label type.
Definition ProForma.h:318
String identifier
The label identifier (e.g., XL1, BRANCH, g1)
Definition ProForma.h:319
Mass delta modification with optional source hint.
Definition ProForma.h:198
Source
Source hint for mass delta values.
Definition ProForma.h:201
@ NONE
No source hint specified.
double mass
The mass delta value in Daltons.
Definition ProForma.h:212
String original_text
Original text for lossless roundtrip (e.g., "+15.99" vs "+15.9900")
Definition ProForma.h:213
Source source
Optional source hint prefix.
Definition ProForma.h:211