def _extract_charge(arg: str): """ Receive a `str` representing an element, isotope, or ion. Return a `tuple` containing a `str` that should represent an element or isotope, and either an `int` representing the charge or `None` if no charge information is provided. Raise an `~plasmapy.utils.InvalidParticleError` if charge information is inputted incorrectly. """ invalid_charge_errmsg = (f"Invalid charge information in the particle string '{arg}'.") if arg.count(' ') == 1: # Cases like 'H 1-' and 'Fe-56 1+' isotope_info, charge_info = arg.split(' ') sign_indicator_only_on_one_end = ( charge_info.endswith(('-', '+')) ^ charge_info.startswith(('-', '+'))) just_one_sign_indicator = ( (charge_info.count('-') == 1 and charge_info.count('+') == 0) or (charge_info.count('-') == 0 and charge_info.count('+') == 1)) if not sign_indicator_only_on_one_end and just_one_sign_indicator: raise InvalidParticleError(invalid_charge_errmsg) from None charge_str = charge_info.strip('+-') try: if roman.is_roman_numeral(charge_info): Z_from_arg = roman.from_roman(charge_info) - 1 elif '-' in charge_info: Z_from_arg = - int(charge_str) elif '+' in charge_info: Z_from_arg = int(charge_str) else: raise InvalidParticleError(invalid_charge_errmsg) from None except ValueError: raise InvalidParticleError(invalid_charge_errmsg) from None elif arg.endswith(('-', '+')): # Cases like 'H-' and 'Pb-209+++' char = arg[-1] match = re.match(f"[{char}]*", arg[::-1]) Z_from_arg = match.span()[1] isotope_info = arg[0:len(arg) - match.span()[1]] if char == '-': Z_from_arg = -Z_from_arg if isotope_info.endswith(('-', '+')): raise InvalidParticleError(invalid_charge_errmsg) from None else: isotope_info = arg Z_from_arg = None return isotope_info, Z_from_arg
def __init__(self, ion_name, hdf5_dbase_root=None, **kwargs): self._element, ion = ion_name.split() if '+' in ion: ion = f"{int(ion.strip('+')) + 1}" if roman.is_roman_numeral(ion.upper()): ion = roman.from_roman(ion.upper()) self.ionization_stage = int(ion) self.charge_state = self.ionization_stage - 1 if hdf5_dbase_root is None: self.hdf5_dbase_root = fiasco.defaults['hdf5_dbase_root'] else: self.hdf5_dbase_root = hdf5_dbase_root check_database(self.hdf5_dbase_root, **kwargs) if self.ion_name not in fiasco.list_ions(self.hdf5_dbase_root, sort=False): raise MissingIonError( f'{self.ion_name} not found in {self.hdf5_dbase_root}')
def extract_charge(arg: str): """ Receive a `str` representing an element, isotope, or ion. Return a `tuple` containing a `str` that should represent an element or isotope, and either an `int` representing the charge or `None` if no charge information is provided. Raise an `~plasmapy.particles.exceptions.InvalidParticleError` if charge information is inputted incorrectly. """ invalid_charge_errmsg = ( f"Invalid charge information in the particle string '{arg}'.") match = re.fullmatch( r"\s*(?P<isotope>\w+(-[0-9]+)*([+-]*)*)" r"(\s*(?P<charge>[+-]?[IVXLCDM0-9]+[+-]?)*)*\s*", arg, ) if match is None: raise InvalidParticleError(invalid_charge_errmsg) from None isotope_info = match.groupdict()["isotope"] charge_info = match.groupdict()["charge"] Z_from_arg = None if charge_info is not None and isotope_info.endswith(("-", "+")): # charge info is defined on both the charge_info and isotope_into strings raise InvalidParticleError(invalid_charge_errmsg) from None elif charge_info is not None: # Cases like 'H 1-' and 'Fe-56 1+' sign_indicator_only_on_one_end = charge_info.endswith( ("-", "+")) ^ charge_info.startswith(("-", "+")) just_one_sign_indicator = (charge_info.count("-") == 1 and charge_info.count("+") == 0) or (charge_info.count("-") == 0 and charge_info.count("+") == 1) if not sign_indicator_only_on_one_end and just_one_sign_indicator: raise InvalidParticleError(invalid_charge_errmsg) from None charge_str = charge_info.strip("+-") try: if roman.is_roman_numeral(charge_info): Z_from_arg = roman.from_roman(charge_info) - 1 elif "-" in charge_info: Z_from_arg = -int(charge_str) elif "+" in charge_info: Z_from_arg = int(charge_str) else: raise InvalidParticleError(invalid_charge_errmsg) from None except ValueError: raise InvalidParticleError(invalid_charge_errmsg) from None elif isotope_info.endswith(("-", "+")): # Cases like 'H-' and 'Pb-209+++' match = re.fullmatch( r"\s*(?P<isotope>\w+(-[0-9]+)?)(?P<charge>[-+]+)\s*", isotope_info, ) isotope_info = match.groupdict()["isotope"] charge_info = match.groupdict()["charge"] if len(set(charge_info)) != 1: raise InvalidParticleError(invalid_charge_errmsg) from None Z_from_arg = len(charge_info) if charge_info[0] == "-": Z_from_arg = -Z_from_arg return isotope_info, Z_from_arg