Source code for fmu.ensemble.util

"""Common utility functions used in fmu.ensemble"""

import os
from collections.abc import MutableMapping


[docs]def flatten(dictionary, parent_key="", sep="_"): """Flatten nested dictionaries by introducing new keys with the accumulated path. e.g. {"foo": {"bar": "com"}} becomes {"foo-bar": "com"} Args: dictionary (dict): Possibly nested dictionary parent_key (str): If provided, append as top level key sep (str): Separator used in merged keys. Returns: dict with only one level. """ items = [] for key, value in dictionary.items(): new_key = parent_key + sep + key if parent_key else key if isinstance(value, MutableMapping): items.extend(flatten(value, new_key, sep=sep).items()) else: items.append((new_key, value)) return dict(items)
[docs]def parse_number(value): """Try to parse the string first as an integer, then as float, if both fails, return the original string. Caveats: Know your Python numbers: https://stackoverflow.com/questions/379906/how-do-i-parse-a-string-to-a-float-or-int-in-python Beware, this is a minefield. Args: value (str) Returns: int, float or string """ if isinstance(value, int): return value if isinstance(value, float): # int(afloat) fails on some, e.g. NaN try: if int(value) == value: return int(value) return value except ValueError: return value # return float try: return int(value) except ValueError: try: return float(value) except ValueError: return value
[docs]def shortcut2path(keys, shortpath): """ Convert short pathnames to fully qualified pathnames within the datastore. If the fully qualified localpath is 'share/results/volumes/simulator_volume_fipnum.csv' then you can also access this with these alternatives: * simulator_volume_fipnum * simulator_volume_fipnum.csv * share/results/volumes/simulator_volume_fipnum but only as long as there is no ambiguity. In case of ambiguity, the shortpath will be returned. Args: keys (list of str): List if all keys in the internal datastore shortpath (str): The search string, the short pathname that should resolve to a fully qualified localpath Returns: Fully qualified path if found in keys, returns the shortpath input untouched if nothing is found, or of the shortpath is already fully qualified. """ basenames = list(map(os.path.basename, keys)) if basenames.count(shortpath) == 1: short2path = {os.path.basename(x): x for x in keys} return short2path[shortpath] noexts = ["".join(x.split(".")[:-1]) for x in keys] if noexts.count(shortpath) == 1: short2path = {"".join(x.split(".")[:-1]): x for x in keys} return short2path[shortpath] basenamenoexts = ["".join(os.path.basename(x).split(".")[:-1]) for x in keys] if basenamenoexts.count(shortpath) == 1: short2path = {"".join(os.path.basename(x).split(".")[:-1]): x for x in keys} return short2path[shortpath] # If we get here, we did not find anything that # this shorthand could point to. Return as is, and let the # calling function handle further errors. return shortpath