Source code for utu.spectrum._names

"""The names of ions, written the way spectroscopists write them."""

import numpy as np

import named_arrays as na

__all__ = [
    "spectroscopic",
]

_numeral = (
    (1000, "M"),
    (900, "CM"),
    (500, "D"),
    (400, "CD"),
    (100, "C"),
    (90, "XC"),
    (50, "L"),
    (40, "XL"),
    (10, "X"),
    (9, "IX"),
    (5, "V"),
    (4, "IV"),
    (1, "I"),
)


def _roman(number: int) -> str:
    """Write a positive integer as a Roman numeral."""
    result = ""
    for value, numeral in _numeral:
        count, number = divmod(number, value)
        result += numeral * count
    return result


def _spectroscopic(name: str, latex: bool) -> str:
    element, _, stage = str(name).partition(" ")
    element = element.capitalize()
    numeral = _roman(int(stage))
    if latex:
        return rf"{element}\,\textsc{{{numeral.lower()}}}"
    return f"{element} {numeral}"


[docs] def spectroscopic( ion: str | na.AbstractScalar, latex: bool = False, ) -> str | na.AbstractScalar: r""" Write the name of an ion the way a spectroscopist writes it. The charge state is a Roman numeral, one greater than the charge, so that the neutral atom is ``I``. This is how :mod:`fiasco` numbers its ions as well, only in Arabic numerals, so ``O 5`` becomes ``O V``. Parameters ---------- ion The name of an ion, or an array of them, as :mod:`fiasco` writes it. latex Whether to write the numeral as LaTeX small capitals, which is how it is set in print. Examples -------- The ion ESIS was built to observe. .. jupyter-execute:: import utu utu.spectrum.spectroscopic("O 5") And as it would be set in a journal. .. jupyter-execute:: utu.spectrum.spectroscopic("O 5", latex=True) """ if isinstance(ion, str): return _spectroscopic(ion, latex=latex) ion = na.as_named_array(ion) result = np.array([_spectroscopic(i, latex=latex) for i in ion.ndarray.flat]) return na.ScalarArray( ndarray=result.reshape(ion.ndarray.shape), axes=ion.axes, )