Source code for exosim.utils.checks

import astropy.units as u
import numpy as np


[docs]def check_units(input_data, desired_units, calling_class=None, force=False): """ It checks the units of the inputs and returns the quantity rescaled to the desired units. Parameters ---------- input_data: :class:`~numpy.ndarray` or :class:`~astropy.units.Quantity` input class to rescale. desired_units: :class:`~astropy.units.Quantity` desired unit for the input qquantity. calling_class: :class:`~exosim.log.logger.Logger` (optional) calling class. This is needed to print the eventual debug message inside the calling class. force: bool (optional) if True, if the input data has no units, it assumes is expressed in the desired units. Default is False. Returns ------- :class:`~astropy.units.Quantity` scaled input quantity. Raises ------ UnitConversionError if it cannot convert the original units into the desired ones """ def _has_no_unit(_input_data, _desired_units, _force): """If input has no unit, it assigns the desired one, if force is True, or just convert the input data to a :class:`~astropy.units.Quantity` with no unit. """ if calling_class: calling_class.debug("input data has no unit") if _force: if calling_class: calling_class.debug("forcing {} units".format(_desired_units)) _input_data = np.array(_input_data) * u.Unit(_desired_units) else: if calling_class: calling_class.debug("forcing no units") _input_data = np.array(_input_data) * u.Unit("") return _input_data def _has_different_unit(_input_data, _desired_units): """If input has different unit, it converts the input data into the desired one.""" try: output_data = _input_data.to(u.Unit(_desired_units)) if calling_class: calling_class.debug( "converted {} to {}".format( _input_data.unit, _desired_units ) ) calling_class.debug("converted data: {}".format(output_data)) return output_data except u.UnitConversionError: if _input_data.unit == u.s and _desired_units == u.Hz: return check_units(1 / _input_data, _desired_units) elif _input_data.unit == u.Hz and _desired_units == u.s: return check_units(1 / _input_data, _desired_units) else: msg = "impossible to convert {} into {}".format( _input_data.unit, _desired_units ) raise u.UnitConversionError(msg) if desired_units is None: desired_units = "" if not hasattr(input_data, "unit"): input_data = _has_no_unit(input_data, desired_units, force) elif input_data.unit is None: input_data = _has_no_unit(input_data, desired_units, force) else: input_unit = input_data.unit if input_unit == 1 / u.Hz: input_unit = u.s if input_unit == 1 / u.s: input_unit = u.Hz if not input_unit: input_unit = u.Unit("") input_data = np.array(input_data) * u.Unit(input_unit) if calling_class: calling_class.debug("input data: {}".format(input_data)) if input_data.unit != u.Unit(desired_units): return _has_different_unit(input_data, desired_units) else: return input_data
[docs]def find_key(input_class_keys, key_list, calling_class=None): """ Finds which key from key_list is contained in input_class_keys, ignoring case. Parameters ---------- input_class_keys : list List of the input class keys. key_list : list List of the desired keys. calling_class : :class:`~exosim.log.logger.Logger`, optional Calling class. This is needed to print the eventual debug message inside the calling class. Returns ------- str Found key. Raises ------- KeyError If no matching key is found. """ # Create a set of lower-case keys from the input class for efficient lookup lower_input_keys = {key.lower() for key in input_class_keys} try: # Find the first key from key_list that exists in lower_input_keys (case-insensitive) key = [k for k in key_list if k.lower() in lower_input_keys][0] return key except IndexError: msg = "no matching key found" if calling_class: calling_class.error(msg) raise KeyError(msg)
[docs]def look_for_key(input_dict, key, value, foo=False): """ Returns ``True`` if a certain key is in the dictionary and has a certain value. Parameters ---------- input_dict: dict input dictionary key: str key to search value key content to check Returns ------- bool """ for k, val in input_dict.items(): if k == key and val == value: foo = True break else: if isinstance(input_dict[k], dict): foo = look_for_key(input_dict[k], key, value, foo) return foo