| 1 | ### script to handle isotopologues |
|---|
| 2 | ### copy from https://github.com/bmorris3/shone/tree/refs/heads/opacity-downloads |
|---|
| 3 | |
|---|
| 4 | import re |
|---|
| 5 | import numpy as np |
|---|
| 6 | from periodictable import elements |
|---|
| 7 | |
|---|
| 8 | |
|---|
| 9 | __all__ = [ |
|---|
| 10 | 'isotopologue_to_species', |
|---|
| 11 | 'species_name_to_common_isotopologue_name' |
|---|
| 12 | ] |
|---|
| 13 | |
|---|
| 14 | |
|---|
| 15 | def isotopologue_to_species(isotopologue): |
|---|
| 16 | """ |
|---|
| 17 | Convert isotopologue name to common species name. |
|---|
| 18 | |
|---|
| 19 | Example: Take 1H2-16O and turn it to H2O, or take 48Ti-16O and turn it to TiO. |
|---|
| 20 | |
|---|
| 21 | Parameters |
|---|
| 22 | ---------- |
|---|
| 23 | isotopologue : str |
|---|
| 24 | Isotopologue name, like "1H2-16O". |
|---|
| 25 | |
|---|
| 26 | Returns |
|---|
| 27 | ------- |
|---|
| 28 | common_name : str |
|---|
| 29 | Common name, like "H2O". |
|---|
| 30 | """ |
|---|
| 31 | species = "" |
|---|
| 32 | for element in isotopologue.split('-'): |
|---|
| 33 | for s in re.findall(r'\D+\d*', element): |
|---|
| 34 | species += ''.join(s) |
|---|
| 35 | return species if len(species) > 0 else isotopologue |
|---|
| 36 | |
|---|
| 37 | |
|---|
| 38 | def species_name_to_common_isotopologue_name(species): |
|---|
| 39 | """ |
|---|
| 40 | Convert generic species name, like "H2O", to isotopologue name like "1H2-16O". |
|---|
| 41 | |
|---|
| 42 | Parameters |
|---|
| 43 | ---------- |
|---|
| 44 | species : str |
|---|
| 45 | Generic name, like "H2O". |
|---|
| 46 | |
|---|
| 47 | Returns |
|---|
| 48 | ------- |
|---|
| 49 | isotopologue_name : str |
|---|
| 50 | Isotopologue name, like "1H2-16O". |
|---|
| 51 | """ |
|---|
| 52 | atoms = np.array(list(filter( |
|---|
| 53 | lambda x: len(x) > 0, re.split(r"(?<=[a-z])|(?=[A-Z])|\d", species) |
|---|
| 54 | ))) |
|---|
| 55 | |
|---|
| 56 | multipliers = np.array([ |
|---|
| 57 | int(x) if len(x) > 0 else 1 for x in re.split(r'\D', species) |
|---|
| 58 | ]) |
|---|
| 59 | lens = [len(''.join(atom)) for atom in atoms] |
|---|
| 60 | multipliers_skipped = np.array([multipliers[cs] for cs in np.cumsum(lens)]) |
|---|
| 61 | |
|---|
| 62 | masses = np.array([ |
|---|
| 63 | round(getattr(elements, atom).mass) for atom, mult in zip(atoms, multipliers_skipped) |
|---|
| 64 | ]) |
|---|
| 65 | |
|---|
| 66 | if len(atoms) > 1: |
|---|
| 67 | correct_notation = '-'.join([ |
|---|
| 68 | str(mass) + a + (str(mult) if mult > 1 else '') |
|---|
| 69 | for a, mult, mass in zip(atoms, multipliers_skipped, masses) |
|---|
| 70 | ]) |
|---|
| 71 | |
|---|
| 72 | # If single atom, give only the name of the atom: |
|---|
| 73 | else: |
|---|
| 74 | correct_notation = atoms[0] |
|---|
| 75 | |
|---|
| 76 | return correct_notation |
|---|