Skip to main content

sci_form/nmr/
nucleus.rs

1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
4pub enum NmrNucleus {
5    H1,
6    H2,
7    H3,
8    He3,
9    Li6,
10    Li7,
11    Be9,
12    B10,
13    B11,
14    C13,
15    N14,
16    N15,
17    O17,
18    F19,
19    Na23,
20    Mg25,
21    Al27,
22    Si29,
23    P31,
24    S33,
25    Cl35,
26    Cl37,
27    K39,
28    K40,
29    K41,
30    Ca43,
31    Sc45,
32    Ti47,
33    Ti49,
34    V50,
35    V51,
36    Cr53,
37    Fe57,
38    Co59,
39    Ni61,
40    Cu63,
41    Cu65,
42    Zn67,
43    Ga69,
44    Ga71,
45    Ge73,
46    As75,
47    Se77,
48    Br79,
49    Br81,
50    Rb85,
51    Rb87,
52    Sr87,
53    Zr91,
54    Nb93,
55    Mo95,
56    Mo97,
57    Ru99,
58    Ru101,
59    Rh103,
60    Pd105,
61    Ag107,
62    Ag109,
63    Cd111,
64    Cd113,
65    In113,
66    In115,
67    Sn115,
68    Sn117,
69    Sn119,
70    Sb121,
71    Sb123,
72    Te123,
73    Te125,
74    I127,
75    Xe129,
76    Xe131,
77    Cs133,
78    Ba135,
79    Ba137,
80    W183,
81    Pt195,
82    Au197,
83    Hg199,
84    Hg201,
85    Tl203,
86    Tl205,
87    Pb207,
88    Bi209,
89    Mn55,
90}
91
92impl NmrNucleus {
93    pub const ALL: [NmrNucleus; 85] = [
94        NmrNucleus::H1,
95        NmrNucleus::H2,
96        NmrNucleus::H3,
97        NmrNucleus::He3,
98        NmrNucleus::Li6,
99        NmrNucleus::Li7,
100        NmrNucleus::Be9,
101        NmrNucleus::B10,
102        NmrNucleus::B11,
103        NmrNucleus::C13,
104        NmrNucleus::N14,
105        NmrNucleus::N15,
106        NmrNucleus::O17,
107        NmrNucleus::F19,
108        NmrNucleus::Na23,
109        NmrNucleus::Mg25,
110        NmrNucleus::Al27,
111        NmrNucleus::Si29,
112        NmrNucleus::P31,
113        NmrNucleus::S33,
114        NmrNucleus::Cl35,
115        NmrNucleus::Cl37,
116        NmrNucleus::K39,
117        NmrNucleus::K40,
118        NmrNucleus::K41,
119        NmrNucleus::Ca43,
120        NmrNucleus::Sc45,
121        NmrNucleus::Ti47,
122        NmrNucleus::Ti49,
123        NmrNucleus::V50,
124        NmrNucleus::V51,
125        NmrNucleus::Cr53,
126        NmrNucleus::Mn55,
127        NmrNucleus::Fe57,
128        NmrNucleus::Co59,
129        NmrNucleus::Ni61,
130        NmrNucleus::Cu63,
131        NmrNucleus::Cu65,
132        NmrNucleus::Zn67,
133        NmrNucleus::Ga69,
134        NmrNucleus::Ga71,
135        NmrNucleus::Ge73,
136        NmrNucleus::As75,
137        NmrNucleus::Se77,
138        NmrNucleus::Br79,
139        NmrNucleus::Br81,
140        NmrNucleus::Rb85,
141        NmrNucleus::Rb87,
142        NmrNucleus::Sr87,
143        NmrNucleus::Zr91,
144        NmrNucleus::Nb93,
145        NmrNucleus::Mo95,
146        NmrNucleus::Mo97,
147        NmrNucleus::Ru99,
148        NmrNucleus::Ru101,
149        NmrNucleus::Rh103,
150        NmrNucleus::Pd105,
151        NmrNucleus::Ag107,
152        NmrNucleus::Ag109,
153        NmrNucleus::Cd111,
154        NmrNucleus::Cd113,
155        NmrNucleus::In113,
156        NmrNucleus::In115,
157        NmrNucleus::Sn115,
158        NmrNucleus::Sn117,
159        NmrNucleus::Sn119,
160        NmrNucleus::Sb121,
161        NmrNucleus::Sb123,
162        NmrNucleus::Te123,
163        NmrNucleus::Te125,
164        NmrNucleus::I127,
165        NmrNucleus::Xe129,
166        NmrNucleus::Xe131,
167        NmrNucleus::Cs133,
168        NmrNucleus::Ba135,
169        NmrNucleus::Ba137,
170        NmrNucleus::W183,
171        NmrNucleus::Pt195,
172        NmrNucleus::Au197,
173        NmrNucleus::Hg199,
174        NmrNucleus::Hg201,
175        NmrNucleus::Tl203,
176        NmrNucleus::Tl205,
177        NmrNucleus::Pb207,
178        NmrNucleus::Bi209,
179    ];
180
181    pub fn parse(alias: &str) -> Result<Self, String> {
182        let normalized: String = alias
183            .chars()
184            .filter(|character| character.is_ascii_alphanumeric())
185            .flat_map(|character| character.to_lowercase())
186            .collect();
187
188        let nucleus = match normalized.as_str() {
189            "1h" | "h1" | "proton" | "hydrogen" => Self::H1,
190            "2h" | "h2" | "deuterium" => Self::H2,
191            "3h" | "h3" | "tritium" => Self::H3,
192            "3he" | "he3" | "helium" => Self::He3,
193            "6li" | "li6" => Self::Li6,
194            "7li" | "li7" | "lithium" => Self::Li7,
195            "9be" | "be9" | "beryllium" => Self::Be9,
196            "10b" | "b10" => Self::B10,
197            "11b" | "b11" | "boron" => Self::B11,
198            "13c" | "c13" | "carbon" => Self::C13,
199            "14n" | "n14" => Self::N14,
200            "15n" | "n15" | "nitrogen" => Self::N15,
201            "17o" | "o17" | "oxygen" => Self::O17,
202            "19f" | "f19" | "fluorine" => Self::F19,
203            "23na" | "na23" | "sodium" => Self::Na23,
204            "25mg" | "mg25" | "magnesium" => Self::Mg25,
205            "27al" | "al27" | "aluminium" | "aluminum" => Self::Al27,
206            "29si" | "si29" | "silicon" => Self::Si29,
207            "31p" | "p31" | "phosphorus" => Self::P31,
208            "33s" | "s33" | "sulfur" | "sulphur" => Self::S33,
209            "35cl" | "cl35" | "chlorine" => Self::Cl35,
210            "37cl" | "cl37" => Self::Cl37,
211            "39k" | "k39" | "potassium" => Self::K39,
212            "40k" | "k40" => Self::K40,
213            "41k" | "k41" => Self::K41,
214            "43ca" | "ca43" | "calcium" => Self::Ca43,
215            "45sc" | "sc45" | "scandium" => Self::Sc45,
216            "47ti" | "ti47" => Self::Ti47,
217            "49ti" | "ti49" | "titanium" => Self::Ti49,
218            "50v" | "v50" => Self::V50,
219            "51v" | "v51" | "vanadium" => Self::V51,
220            "53cr" | "cr53" | "chromium" => Self::Cr53,
221            "55mn" | "mn55" | "manganese" => Self::Mn55,
222            "57fe" | "fe57" | "iron" => Self::Fe57,
223            "59co" | "co59" | "cobalt" => Self::Co59,
224            "61ni" | "ni61" | "nickel" => Self::Ni61,
225            "63cu" | "cu63" | "copper" => Self::Cu63,
226            "65cu" | "cu65" => Self::Cu65,
227            "67zn" | "zn67" | "zinc" => Self::Zn67,
228            "69ga" | "ga69" | "gallium" => Self::Ga69,
229            "71ga" | "ga71" => Self::Ga71,
230            "73ge" | "ge73" | "germanium" => Self::Ge73,
231            "75as" | "as75" | "arsenic" | "arsenico" => Self::As75,
232            "77se" | "se77" | "selenium" => Self::Se77,
233            "79br" | "br79" | "bromine" => Self::Br79,
234            "81br" | "br81" => Self::Br81,
235            "85rb" | "rb85" => Self::Rb85,
236            "87rb" | "rb87" | "rubidium" => Self::Rb87,
237            "87sr" | "sr87" | "strontium" => Self::Sr87,
238            "91zr" | "zr91" | "zirconium" => Self::Zr91,
239            "93nb" | "nb93" | "niobium" => Self::Nb93,
240            "95mo" | "mo95" | "molybdenum" => Self::Mo95,
241            "97mo" | "mo97" => Self::Mo97,
242            "99ru" | "ru99" => Self::Ru99,
243            "101ru" | "ru101" | "ruthenium" => Self::Ru101,
244            "103rh" | "rh103" | "rhodium" => Self::Rh103,
245            "105pd" | "pd105" | "palladium" => Self::Pd105,
246            "107ag" | "ag107" | "silver" => Self::Ag107,
247            "109ag" | "ag109" => Self::Ag109,
248            "111cd" | "cd111" | "cadmium" => Self::Cd111,
249            "113cd" | "cd113" => Self::Cd113,
250            "113in" | "in113" => Self::In113,
251            "115in" | "in115" | "indium" => Self::In115,
252            "115sn" | "sn115" => Self::Sn115,
253            "117sn" | "sn117" => Self::Sn117,
254            "119sn" | "sn119" | "tin" => Self::Sn119,
255            "121sb" | "sb121" | "antimony" => Self::Sb121,
256            "123sb" | "sb123" => Self::Sb123,
257            "123te" | "te123" => Self::Te123,
258            "125te" | "te125" | "tellurium" => Self::Te125,
259            "127i" | "i127" | "iodine" => Self::I127,
260            "129xe" | "xe129" | "xenon" => Self::Xe129,
261            "131xe" | "xe131" => Self::Xe131,
262            "133cs" | "cs133" | "cesium" | "caesium" => Self::Cs133,
263            "135ba" | "ba135" => Self::Ba135,
264            "137ba" | "ba137" | "barium" => Self::Ba137,
265            "183w" | "w183" | "tungsten" | "wolfram" => Self::W183,
266            "195pt" | "pt195" | "platinum" => Self::Pt195,
267            "197au" | "au197" | "gold" => Self::Au197,
268            "199hg" | "hg199" | "mercury" => Self::Hg199,
269            "201hg" | "hg201" => Self::Hg201,
270            "203tl" | "tl203" => Self::Tl203,
271            "205tl" | "tl205" | "thallium" => Self::Tl205,
272            "207pb" | "pb207" | "lead" => Self::Pb207,
273            "209bi" | "bi209" | "bismuth" => Self::Bi209,
274            _ => {
275                return Err(format!(
276                    "Unknown nucleus '{}'. Supported: {}",
277                    alias,
278                    Self::supported_labels().join(", ")
279                ))
280            }
281        };
282
283        Ok(nucleus)
284    }
285
286    pub fn supported_labels() -> Vec<&'static str> {
287        Self::ALL
288            .iter()
289            .map(|nucleus| nucleus.canonical())
290            .collect()
291    }
292
293    pub fn atomic_number(self) -> u8 {
294        match self {
295            Self::H1 | Self::H2 | Self::H3 => 1,
296            Self::He3 => 2,
297            Self::Li6 | Self::Li7 => 3,
298            Self::Be9 => 4,
299            Self::B10 | Self::B11 => 5,
300            Self::C13 => 6,
301            Self::N14 | Self::N15 => 7,
302            Self::O17 => 8,
303            Self::F19 => 9,
304            Self::Na23 => 11,
305            Self::Mg25 => 12,
306            Self::Al27 => 13,
307            Self::Si29 => 14,
308            Self::P31 => 15,
309            Self::S33 => 16,
310            Self::Cl35 | Self::Cl37 => 17,
311            Self::K39 | Self::K40 | Self::K41 => 19,
312            Self::Ca43 => 20,
313            Self::Sc45 => 21,
314            Self::Ti47 | Self::Ti49 => 22,
315            Self::V50 | Self::V51 => 23,
316            Self::Cr53 => 24,
317            Self::Mn55 => 25,
318            Self::Fe57 => 26,
319            Self::Co59 => 27,
320            Self::Ni61 => 28,
321            Self::Cu63 | Self::Cu65 => 29,
322            Self::Zn67 => 30,
323            Self::Ga69 | Self::Ga71 => 31,
324            Self::Ge73 => 32,
325            Self::As75 => 33,
326            Self::Se77 => 34,
327            Self::Br79 | Self::Br81 => 35,
328            Self::Rb85 | Self::Rb87 => 37,
329            Self::Sr87 => 38,
330            Self::Zr91 => 40,
331            Self::Nb93 => 41,
332            Self::Mo95 | Self::Mo97 => 42,
333            Self::Ru99 | Self::Ru101 => 44,
334            Self::Rh103 => 45,
335            Self::Pd105 => 46,
336            Self::Ag107 | Self::Ag109 => 47,
337            Self::Cd111 | Self::Cd113 => 48,
338            Self::In113 | Self::In115 => 49,
339            Self::Sn115 | Self::Sn117 | Self::Sn119 => 50,
340            Self::Sb121 | Self::Sb123 => 51,
341            Self::Te123 | Self::Te125 => 52,
342            Self::I127 => 53,
343            Self::Xe129 | Self::Xe131 => 54,
344            Self::Cs133 => 55,
345            Self::Ba135 | Self::Ba137 => 56,
346            Self::W183 => 74,
347            Self::Pt195 => 78,
348            Self::Au197 => 79,
349            Self::Hg199 | Self::Hg201 => 80,
350            Self::Tl203 | Self::Tl205 => 81,
351            Self::Pb207 => 82,
352            Self::Bi209 => 83,
353        }
354    }
355
356    pub fn mass_number(self) -> u16 {
357        match self {
358            Self::H1 => 1,
359            Self::H2 => 2,
360            Self::H3 => 3,
361            Self::He3 => 3,
362            Self::Li6 => 6,
363            Self::Li7 => 7,
364            Self::Be9 => 9,
365            Self::B10 => 10,
366            Self::B11 => 11,
367            Self::C13 => 13,
368            Self::N14 => 14,
369            Self::N15 => 15,
370            Self::O17 => 17,
371            Self::F19 => 19,
372            Self::Na23 => 23,
373            Self::Mg25 => 25,
374            Self::Al27 => 27,
375            Self::Si29 => 29,
376            Self::P31 => 31,
377            Self::S33 => 33,
378            Self::Cl35 => 35,
379            Self::Cl37 => 37,
380            Self::K39 => 39,
381            Self::K40 => 40,
382            Self::K41 => 41,
383            Self::Ca43 => 43,
384            Self::Sc45 => 45,
385            Self::Ti47 => 47,
386            Self::Ti49 => 49,
387            Self::V50 => 50,
388            Self::V51 => 51,
389            Self::Cr53 => 53,
390            Self::Mn55 => 55,
391            Self::Fe57 => 57,
392            Self::Co59 => 59,
393            Self::Ni61 => 61,
394            Self::Cu63 => 63,
395            Self::Cu65 => 65,
396            Self::Zn67 => 67,
397            Self::Ga69 => 69,
398            Self::Ga71 => 71,
399            Self::Ge73 => 73,
400            Self::As75 => 75,
401            Self::Se77 => 77,
402            Self::Br79 => 79,
403            Self::Br81 => 81,
404            Self::Rb85 => 85,
405            Self::Rb87 => 87,
406            Self::Sr87 => 87,
407            Self::Zr91 => 91,
408            Self::Nb93 => 93,
409            Self::Mo95 => 95,
410            Self::Mo97 => 97,
411            Self::Ru99 => 99,
412            Self::Ru101 => 101,
413            Self::Rh103 => 103,
414            Self::Pd105 => 105,
415            Self::Ag107 => 107,
416            Self::Ag109 => 109,
417            Self::Cd111 => 111,
418            Self::Cd113 => 113,
419            Self::In113 => 113,
420            Self::In115 => 115,
421            Self::Sn115 => 115,
422            Self::Sn117 => 117,
423            Self::Sn119 => 119,
424            Self::Sb121 => 121,
425            Self::Sb123 => 123,
426            Self::Te123 => 123,
427            Self::Te125 => 125,
428            Self::I127 => 127,
429            Self::Xe129 => 129,
430            Self::Xe131 => 131,
431            Self::Cs133 => 133,
432            Self::Ba135 => 135,
433            Self::Ba137 => 137,
434            Self::W183 => 183,
435            Self::Pt195 => 195,
436            Self::Au197 => 197,
437            Self::Hg199 => 199,
438            Self::Hg201 => 201,
439            Self::Tl203 => 203,
440            Self::Tl205 => 205,
441            Self::Pb207 => 207,
442            Self::Bi209 => 209,
443        }
444    }
445
446    pub fn canonical(self) -> &'static str {
447        match self {
448            Self::H1 => "1H",
449            Self::H2 => "2H",
450            Self::H3 => "3H",
451            Self::He3 => "3He",
452            Self::Li6 => "6Li",
453            Self::Li7 => "7Li",
454            Self::Be9 => "9Be",
455            Self::B10 => "10B",
456            Self::B11 => "11B",
457            Self::C13 => "13C",
458            Self::N14 => "14N",
459            Self::N15 => "15N",
460            Self::O17 => "17O",
461            Self::F19 => "19F",
462            Self::Na23 => "23Na",
463            Self::Mg25 => "25Mg",
464            Self::Al27 => "27Al",
465            Self::Si29 => "29Si",
466            Self::P31 => "31P",
467            Self::S33 => "33S",
468            Self::Cl35 => "35Cl",
469            Self::Cl37 => "37Cl",
470            Self::K39 => "39K",
471            Self::K40 => "40K",
472            Self::K41 => "41K",
473            Self::Ca43 => "43Ca",
474            Self::Sc45 => "45Sc",
475            Self::Ti47 => "47Ti",
476            Self::Ti49 => "49Ti",
477            Self::V50 => "50V",
478            Self::V51 => "51V",
479            Self::Cr53 => "53Cr",
480            Self::Mn55 => "55Mn",
481            Self::Fe57 => "57Fe",
482            Self::Co59 => "59Co",
483            Self::Ni61 => "61Ni",
484            Self::Cu63 => "63Cu",
485            Self::Cu65 => "65Cu",
486            Self::Zn67 => "67Zn",
487            Self::Ga69 => "69Ga",
488            Self::Ga71 => "71Ga",
489            Self::Ge73 => "73Ge",
490            Self::As75 => "75As",
491            Self::Se77 => "77Se",
492            Self::Br79 => "79Br",
493            Self::Br81 => "81Br",
494            Self::Rb85 => "85Rb",
495            Self::Rb87 => "87Rb",
496            Self::Sr87 => "87Sr",
497            Self::Zr91 => "91Zr",
498            Self::Nb93 => "93Nb",
499            Self::Mo95 => "95Mo",
500            Self::Mo97 => "97Mo",
501            Self::Ru99 => "99Ru",
502            Self::Ru101 => "101Ru",
503            Self::Rh103 => "103Rh",
504            Self::Pd105 => "105Pd",
505            Self::Ag107 => "107Ag",
506            Self::Ag109 => "109Ag",
507            Self::Cd111 => "111Cd",
508            Self::Cd113 => "113Cd",
509            Self::In113 => "113In",
510            Self::In115 => "115In",
511            Self::Sn115 => "115Sn",
512            Self::Sn117 => "117Sn",
513            Self::Sn119 => "119Sn",
514            Self::Sb121 => "121Sb",
515            Self::Sb123 => "123Sb",
516            Self::Te123 => "123Te",
517            Self::Te125 => "125Te",
518            Self::I127 => "127I",
519            Self::Xe129 => "129Xe",
520            Self::Xe131 => "131Xe",
521            Self::Cs133 => "133Cs",
522            Self::Ba135 => "135Ba",
523            Self::Ba137 => "137Ba",
524            Self::W183 => "183W",
525            Self::Pt195 => "195Pt",
526            Self::Au197 => "197Au",
527            Self::Hg199 => "199Hg",
528            Self::Hg201 => "201Hg",
529            Self::Tl203 => "203Tl",
530            Self::Tl205 => "205Tl",
531            Self::Pb207 => "207Pb",
532            Self::Bi209 => "209Bi",
533        }
534    }
535
536    pub fn unicode_label(self) -> &'static str {
537        match self {
538            Self::H1 => "¹H",
539            Self::H2 => "²H",
540            Self::H3 => "³H",
541            Self::He3 => "³He",
542            Self::Li6 => "⁶Li",
543            Self::Li7 => "⁷Li",
544            Self::Be9 => "⁹Be",
545            Self::B10 => "¹⁰B",
546            Self::B11 => "¹¹B",
547            Self::C13 => "¹³C",
548            Self::N14 => "¹⁴N",
549            Self::N15 => "¹⁵N",
550            Self::O17 => "¹⁷O",
551            Self::F19 => "¹⁹F",
552            Self::Na23 => "²³Na",
553            Self::Mg25 => "²⁵Mg",
554            Self::Al27 => "²⁷Al",
555            Self::Si29 => "²⁹Si",
556            Self::P31 => "³¹P",
557            Self::S33 => "³³S",
558            Self::Cl35 => "³⁵Cl",
559            Self::Cl37 => "³⁷Cl",
560            Self::K39 => "³⁹K",
561            Self::K40 => "⁴⁰K",
562            Self::K41 => "⁴¹K",
563            Self::Ca43 => "⁴³Ca",
564            Self::Sc45 => "⁴⁵Sc",
565            Self::Ti47 => "⁴⁷Ti",
566            Self::Ti49 => "⁴⁹Ti",
567            Self::V50 => "⁵⁰V",
568            Self::V51 => "⁵¹V",
569            Self::Cr53 => "⁵³Cr",
570            Self::Mn55 => "⁵⁵Mn",
571            Self::Fe57 => "⁵⁷Fe",
572            Self::Co59 => "⁵⁹Co",
573            Self::Ni61 => "⁶¹Ni",
574            Self::Cu63 => "⁶³Cu",
575            Self::Cu65 => "⁶⁵Cu",
576            Self::Zn67 => "⁶⁷Zn",
577            Self::Ga69 => "⁶⁹Ga",
578            Self::Ga71 => "⁷¹Ga",
579            Self::Ge73 => "⁷³Ge",
580            Self::As75 => "⁷⁵As",
581            Self::Se77 => "⁷⁷Se",
582            Self::Br79 => "⁷⁹Br",
583            Self::Br81 => "⁸¹Br",
584            Self::Rb85 => "⁸⁵Rb",
585            Self::Rb87 => "⁸⁷Rb",
586            Self::Sr87 => "⁸⁷Sr",
587            Self::Zr91 => "⁹¹Zr",
588            Self::Nb93 => "⁹³Nb",
589            Self::Mo95 => "⁹⁵Mo",
590            Self::Mo97 => "⁹⁷Mo",
591            Self::Ru99 => "⁹⁹Ru",
592            Self::Ru101 => "¹⁰¹Ru",
593            Self::Rh103 => "¹⁰³Rh",
594            Self::Pd105 => "¹⁰⁵Pd",
595            Self::Ag107 => "¹⁰⁷Ag",
596            Self::Ag109 => "¹⁰⁹Ag",
597            Self::Cd111 => "¹¹¹Cd",
598            Self::Cd113 => "¹¹³Cd",
599            Self::In113 => "¹¹³In",
600            Self::In115 => "¹¹⁵In",
601            Self::Sn115 => "¹¹⁵Sn",
602            Self::Sn117 => "¹¹⁷Sn",
603            Self::Sn119 => "¹¹⁹Sn",
604            Self::Sb121 => "¹²¹Sb",
605            Self::Sb123 => "¹²³Sb",
606            Self::Te123 => "¹²³Te",
607            Self::Te125 => "¹²⁵Te",
608            Self::I127 => "¹²⁷I",
609            Self::Xe129 => "¹²⁹Xe",
610            Self::Xe131 => "¹³¹Xe",
611            Self::Cs133 => "¹³³Cs",
612            Self::Ba135 => "¹³⁵Ba",
613            Self::Ba137 => "¹³⁷Ba",
614            Self::W183 => "¹⁸³W",
615            Self::Pt195 => "¹⁹⁵Pt",
616            Self::Au197 => "¹⁹⁷Au",
617            Self::Hg199 => "¹⁹⁹Hg",
618            Self::Hg201 => "²⁰¹Hg",
619            Self::Tl203 => "²⁰³Tl",
620            Self::Tl205 => "²⁰⁵Tl",
621            Self::Pb207 => "²⁰⁷Pb",
622            Self::Bi209 => "²⁰⁹Bi",
623        }
624    }
625
626    pub fn element_symbol(self) -> &'static str {
627        match self.atomic_number() {
628            1 => "H",
629            2 => "He",
630            3 => "Li",
631            4 => "Be",
632            5 => "B",
633            6 => "C",
634            7 => "N",
635            8 => "O",
636            9 => "F",
637            11 => "Na",
638            12 => "Mg",
639            13 => "Al",
640            14 => "Si",
641            15 => "P",
642            16 => "S",
643            17 => "Cl",
644            19 => "K",
645            20 => "Ca",
646            21 => "Sc",
647            22 => "Ti",
648            23 => "V",
649            24 => "Cr",
650            25 => "Mn",
651            26 => "Fe",
652            27 => "Co",
653            28 => "Ni",
654            29 => "Cu",
655            30 => "Zn",
656            31 => "Ga",
657            32 => "Ge",
658            33 => "As",
659            34 => "Se",
660            35 => "Br",
661            37 => "Rb",
662            38 => "Sr",
663            40 => "Zr",
664            41 => "Nb",
665            42 => "Mo",
666            44 => "Ru",
667            45 => "Rh",
668            46 => "Pd",
669            47 => "Ag",
670            48 => "Cd",
671            49 => "In",
672            50 => "Sn",
673            51 => "Sb",
674            52 => "Te",
675            53 => "I",
676            54 => "Xe",
677            55 => "Cs",
678            56 => "Ba",
679            74 => "W",
680            78 => "Pt",
681            79 => "Au",
682            80 => "Hg",
683            81 => "Tl",
684            82 => "Pb",
685            83 => "Bi",
686            _ => "X",
687        }
688    }
689
690    pub fn is_primary_target(self) -> bool {
691        matches!(self, Self::H1 | Self::C13)
692    }
693
694    pub fn is_quadrupolar(self) -> bool {
695        !matches!(
696            self,
697            Self::H1
698                | Self::H3
699                | Self::He3
700                | Self::C13
701                | Self::N15
702                | Self::F19
703                | Self::Si29
704                | Self::P31
705                | Self::Se77
706                | Self::Ge73
707                | Self::Sn115
708                | Self::Sn117
709                | Self::Sn119
710                | Self::Te123
711                | Self::Te125
712                | Self::Xe129
713                | Self::Tl203
714                | Self::Tl205
715                | Self::Pb207
716                | Self::Pt195
717                | Self::Hg199
718                | Self::Rh103
719                | Self::Ag107
720                | Self::Ag109
721                | Self::Cd111
722                | Self::Cd113
723        )
724    }
725
726    pub fn default_for_element(atomic_number: u8) -> Option<Self> {
727        let nucleus = match atomic_number {
728            1 => Self::H1,
729            2 => Self::He3,
730            3 => Self::Li7,
731            4 => Self::Be9,
732            5 => Self::B11,
733            6 => Self::C13,
734            7 => Self::N15,
735            8 => Self::O17,
736            9 => Self::F19,
737            11 => Self::Na23,
738            12 => Self::Mg25,
739            13 => Self::Al27,
740            14 => Self::Si29,
741            15 => Self::P31,
742            16 => Self::S33,
743            17 => Self::Cl35,
744            19 => Self::K39,
745            20 => Self::Ca43,
746            21 => Self::Sc45,
747            22 => Self::Ti49,
748            23 => Self::V51,
749            24 => Self::Cr53,
750            25 => Self::Mn55,
751            26 => Self::Fe57,
752            27 => Self::Co59,
753            28 => Self::Ni61,
754            29 => Self::Cu63,
755            30 => Self::Zn67,
756            31 => Self::Ga69,
757            32 => Self::Ge73,
758            33 => Self::As75,
759            34 => Self::Se77,
760            35 => Self::Br79,
761            37 => Self::Rb87,
762            38 => Self::Sr87,
763            40 => Self::Zr91,
764            41 => Self::Nb93,
765            42 => Self::Mo95,
766            44 => Self::Ru101,
767            45 => Self::Rh103,
768            46 => Self::Pd105,
769            47 => Self::Ag107,
770            48 => Self::Cd111,
771            49 => Self::In115,
772            50 => Self::Sn119,
773            51 => Self::Sb121,
774            52 => Self::Te125,
775            53 => Self::I127,
776            54 => Self::Xe129,
777            55 => Self::Cs133,
778            56 => Self::Ba137,
779            74 => Self::W183,
780            78 => Self::Pt195,
781            79 => Self::Au197,
782            80 => Self::Hg199,
783            81 => Self::Tl205,
784            82 => Self::Pb207,
785            83 => Self::Bi209,
786            _ => return None,
787        };
788
789        Some(nucleus)
790    }
791
792    pub fn default_frequency_mhz(self) -> f64 {
793        match self {
794            Self::H1 => 400.0,
795            Self::H2 => 61.4,
796            Self::H3 => 426.0,
797            Self::He3 => 304.6,
798            Self::Li6 => 58.9,
799            Self::Li7 => 155.5,
800            Self::Be9 => 56.3,
801            Self::B10 => 42.9,
802            Self::B11 => 128.4,
803            Self::C13 => 100.6,
804            Self::N14 => 28.9,
805            Self::N15 => 40.6,
806            Self::O17 => 54.2,
807            Self::F19 => 376.5,
808            Self::Na23 => 105.8,
809            Self::Mg25 => 24.5,
810            Self::Al27 => 104.2,
811            Self::Si29 => 79.5,
812            Self::P31 => 162.0,
813            Self::S33 => 30.7,
814            Self::Cl35 => 39.2,
815            Self::Cl37 => 32.7,
816            Self::K39 => 18.7,
817            Self::K40 => 2.2,
818            Self::K41 => 10.9,
819            Self::Ca43 => 26.9,
820            Self::Sc45 => 97.2,
821            Self::Ti47 => 22.6,
822            Self::Ti49 => 23.2,
823            Self::V50 => 42.1,
824            Self::V51 => 105.2,
825            Self::Cr53 => 22.6,
826            Self::Mn55 => 100.0,
827            Self::Fe57 => 54.2,
828            Self::Co59 => 95.0,
829            Self::Ni61 => 35.2,
830            Self::Cu63 => 106.3,
831            Self::Cu65 => 113.9,
832            Self::Zn67 => 25.1,
833            Self::Ga69 => 122.1,
834            Self::Ga71 => 152.5,
835            Self::Ge73 => 14.1,
836            Self::As75 => 52.2,
837            Self::Se77 => 76.3,
838            Self::Br79 => 100.2,
839            Self::Br81 => 108.3,
840            Self::Rb85 => 130.9,
841            Self::Rb87 => 186.9,
842            Self::Sr87 => 74.2,
843            Self::Zr91 => 24.5,
844            Self::Nb93 => 98.2,
845            Self::Mo95 => 26.1,
846            Self::Mo97 => 26.6,
847            Self::Ru99 => 17.3,
848            Self::Ru101 => 22.2,
849            Self::Rh103 => 15.8,
850            Self::Pd105 => 17.2,
851            Self::Ag107 => 18.6,
852            Self::Ag109 => 21.4,
853            Self::Cd111 => 88.8,
854            Self::Cd113 => 93.3,
855            Self::In113 => 88.6,
856            Self::In115 => 92.9,
857            Self::Sn115 => 149.0,
858            Self::Sn117 => 149.3,
859            Self::Sn119 => 149.2,
860            Self::Sb121 => 102.7,
861            Self::Sb123 => 54.3,
862            Self::Te123 => 126.0,
863            Self::Te125 => 126.3,
864            Self::I127 => 80.0,
865            Self::Xe129 => 110.7,
866            Self::Xe131 => 32.9,
867            Self::Cs133 => 52.4,
868            Self::Ba135 => 28.0,
869            Self::Ba137 => 42.0,
870            Self::W183 => 16.7,
871            Self::Pt195 => 85.8,
872            Self::Au197 => 8.7,
873            Self::Hg199 => 74.7,
874            Self::Hg201 => 22.1,
875            Self::Tl203 => 96.6,
876            Self::Tl205 => 100.2,
877            Self::Pb207 => 83.7,
878            Self::Bi209 => 84.2,
879        }
880    }
881
882    pub fn default_fwhm_hz(self) -> f64 {
883        match self {
884            Self::H1 => 1.0,
885            Self::C13 | Self::F19 | Self::Si29 | Self::Ge73 => 5.0,
886            Self::P31 | Self::N15 | Self::Se77 | Self::Te123 | Self::Te125 => 12.0,
887            Self::H3 | Self::He3 | Self::Xe129 => 15.0,
888            Self::Pt195 | Self::Hg199 | Self::Pb207 | Self::W183 => 25.0,
889            Self::Tl203 | Self::Tl205 | Self::Cd111 | Self::Cd113 => 30.0,
890            Self::Ag107 | Self::Ag109 | Self::Sn115 | Self::Sn117 | Self::Sn119 => 35.0,
891            Self::H2 => 30.0,
892            Self::Li6 | Self::Li7 => 15.0,
893            Self::B11 => 35.0,
894            Self::B10 => 70.0,
895            Self::N14 => 90.0,
896            Self::Na23 | Self::Mg25 | Self::Ca43 | Self::Sr87 => 80.0,
897            Self::Al27 | Self::Sc45 => 120.0,
898            Self::K39 | Self::K41 | Self::Rb87 | Self::Cs133 | Self::Ba135 | Self::Ba137 => 140.0,
899            Self::K40 | Self::Rb85 => 220.0,
900            Self::O17 | Self::S33 => 180.0,
901            Self::Cl35 | Self::Cl37 => 260.0,
902            Self::Br79 | Self::Br81 => 600.0,
903            Self::I127 => 1500.0,
904            Self::Xe131 | Self::Hg201 => 120.0,
905            Self::V50 | Self::V51 | Self::Cu63 | Self::Cu65 | Self::Ga69 | Self::Ga71 => 180.0,
906            Self::Ti47 | Self::Ti49 | Self::Zn67 | Self::As75 | Self::Sb121 | Self::Sb123 => 150.0,
907            Self::Cr53 | Self::Mn55 | Self::Co59 | Self::Nb93 => 260.0,
908            Self::Mo95 | Self::Mo97 | Self::Ru99 | Self::Ru101 | Self::In113 | Self::In115 => 200.0,
909            Self::Bi209 | Self::Au197 => 320.0,
910            _ if self.is_quadrupolar() => 120.0,
911            _ => 15.0,
912        }
913    }
914
915    pub fn empirical_range(self) -> (f64, f64) {
916        match self {
917            Self::H1 | Self::H2 | Self::H3 => (-2.0, 14.0),
918            Self::C13 => (-10.0, 230.0),
919            Self::F19 => (-260.0, 100.0),
920            Self::P31 => (-250.0, 250.0),
921            Self::N14 | Self::N15 => (-400.0, 700.0),
922            Self::B10 | Self::B11 => (-120.0, 120.0),
923            Self::Si29 => (-200.0, 200.0),
924            Self::Se77 => (-1000.0, 2000.0),
925            Self::O17 => (-100.0, 1200.0),
926            Self::S33 => (-500.0, 800.0),
927            Self::Cl35 | Self::Cl37 => (-1000.0, 1500.0),
928            Self::Br79 | Self::Br81 => (-2500.0, 5000.0),
929            Self::I127 => (-4000.0, 9000.0),
930            Self::Te123 | Self::Te125 => (-2000.0, 3000.0),
931            Self::Xe129 | Self::Xe131 => (-500.0, 500.0),
932            Self::Li6 | Self::Li7 | Self::Na23 => (-80.0, 80.0),
933            Self::K39 | Self::K40 | Self::K41 => (-200.0, 200.0),
934            Self::Be9 | Self::Mg25 | Self::Ca43 | Self::Sr87 => (-100.0, 200.0),
935            Self::Rb85 | Self::Rb87 | Self::Cs133 | Self::Ba135 | Self::Ba137 => (-150.0, 250.0),
936            Self::He3 => (-50.0, 50.0),
937            Self::Al27 => (-50.0, 120.0),
938            Self::Sc45 | Self::Ti47 | Self::Ti49 | Self::V50 | Self::V51 => (-2500.0, 2500.0),
939            Self::Cr53 | Self::Mn55 | Self::Fe57 | Self::Co59 | Self::Ni61 => (-5000.0, 10000.0),
940            Self::Cu63 | Self::Cu65 | Self::Zn67 | Self::Ga69 | Self::Ga71 => (-1500.0, 1500.0),
941            Self::Ge73 | Self::As75 => (-1500.0, 1500.0),
942            Self::Zr91 | Self::Nb93 | Self::Mo95 | Self::Mo97 => (-4000.0, 4000.0),
943            Self::Ru99 | Self::Ru101 | Self::Rh103 | Self::Pd105 => (-6000.0, 6000.0),
944            Self::Ag107 | Self::Ag109 => (-2000.0, 2000.0),
945            Self::Cd111 | Self::Cd113 => (-1200.0, 1200.0),
946            Self::In113 | Self::In115 => (-1000.0, 1500.0),
947            Self::Sn115 | Self::Sn117 | Self::Sn119 => (-2500.0, 1500.0),
948            Self::Sb121 | Self::Sb123 => (-3000.0, 3000.0),
949            Self::W183 => (-4000.0, 2000.0),
950            Self::Pt195 => (-7000.0, 2000.0),
951            Self::Au197 => (-2000.0, 8000.0),
952            Self::Hg199 | Self::Hg201 => (-4000.0, 4000.0),
953            Self::Tl203 | Self::Tl205 => (-3000.0, 2000.0),
954            Self::Pb207 => (-6000.0, 6000.0),
955            Self::Bi209 => (-8000.0, 8000.0),
956        }
957    }
958
959    pub fn empirical_center(self) -> f64 {
960        match self {
961            Self::H1 | Self::H2 | Self::H3 => 2.5,
962            Self::C13 => 80.0,
963            Self::N14 | Self::N15 => 120.0,
964            Self::O17 => 180.0,
965            Self::F19 => -120.0,
966            Self::P31 => 10.0,
967            Self::B10 | Self::B11 => 15.0,
968            Self::Si29 => -20.0,
969            Self::Se77 => 120.0,
970            Self::S33 => 80.0,
971            Self::Cl35 | Self::Cl37 | Self::Br79 | Self::Br81 | Self::I127 => 0.0,
972            Self::Te123 | Self::Te125 => 100.0,
973            Self::Al27 => 35.0,
974            Self::Sc45 | Self::Ti47 | Self::Ti49 | Self::V50 | Self::V51 => 0.0,
975            Self::Cr53 | Self::Mn55 | Self::Fe57 | Self::Co59 | Self::Ni61 => 1500.0,
976            Self::Cu63 | Self::Cu65 | Self::Zn67 | Self::Ga69 | Self::Ga71 => 0.0,
977            Self::Ge73 | Self::As75 => 100.0,
978            Self::Zr91 | Self::Nb93 | Self::Mo95 | Self::Mo97 => 0.0,
979            Self::Ru99 | Self::Ru101 | Self::Rh103 | Self::Pd105 => -250.0,
980            Self::Ag107 | Self::Ag109 => 0.0,
981            Self::Cd111 | Self::Cd113 => 0.0,
982            Self::In113 | Self::In115 => 250.0,
983            Self::Sn115 | Self::Sn117 | Self::Sn119 => -300.0,
984            Self::Sb121 | Self::Sb123 => -150.0,
985            Self::W183 => -800.0,
986            Self::Pt195 => -3200.0,
987            Self::Au197 => 1200.0,
988            Self::Hg199 | Self::Hg201 => -200.0,
989            Self::Tl203 | Self::Tl205 => 150.0,
990            Self::Pb207 => 500.0,
991            Self::Bi209 => 1200.0,
992            Self::He3
993            | Self::Li6
994            | Self::Li7
995            | Self::Be9
996            | Self::Na23
997            | Self::Mg25
998            | Self::K39
999            | Self::K40
1000            | Self::K41
1001            | Self::Ca43
1002            | Self::Rb85
1003            | Self::Rb87
1004            | Self::Sr87
1005            | Self::Cs133
1006            | Self::Ba135
1007            | Self::Ba137
1008            | Self::Xe129
1009            | Self::Xe131 => 0.0,
1010        }
1011    }
1012
1013    pub fn reference_shielding(self) -> f64 {
1014        match self {
1015            Self::H1 | Self::H2 | Self::H3 => 31.7,
1016            Self::C13 => 188.0,
1017            Self::N14 | Self::N15 => 244.0,
1018            Self::O17 => 324.0,
1019            Self::F19 => 328.0,
1020            Self::P31 => 328.0,
1021            Self::B10 | Self::B11 => 105.0,
1022            Self::Si29 => 420.0,
1023            Self::Se77 => 860.0,
1024            Self::S33 => 1000.0,
1025            _ => self.free_atom_diamagnetic() * 0.85,
1026        }
1027    }
1028
1029    pub fn free_atom_diamagnetic(self) -> f64 {
1030        match self.atomic_number() {
1031            1 => 17.75,
1032            2 => 59.93,
1033            3 => 97.0,
1034            4 => 140.0,
1035            5 => 185.0,
1036            6 => 260.7,
1037            7 => 325.5,
1038            8 => 398.0,
1039            9 => 479.0,
1040            11 => 610.0,
1041            12 => 690.0,
1042            13 => 780.0,
1043            14 => 872.0,
1044            15 => 993.0,
1045            16 => 1118.0,
1046            17 => 1253.0,
1047            atomic_number => atomic_number as f64 * 17.0,
1048        }
1049    }
1050}