Source code for aviary.utils.merge_variable_metadata

import numpy as np


[docs] def almost_equal(a, b, rel_tol=1e-8, abs_tol=0.0): """check if two floats, or two ndarray, or two dictionary are equal. Return True if they are equal.""" if isinstance(a, (float, np.float32, np.float64)) and isinstance(b, (float, np.float32, np.float64)): return np.isclose(a, b, rtol=rel_tol, atol=abs_tol) if isinstance(a, np.ndarray) and isinstance(b, np.ndarray): return np.allclose(a, b, rtol=rel_tol, atol=abs_tol) if isinstance(a, dict) and isinstance(b, dict): if a.keys() != b.keys(): return False for key in a.keys(): if not almost_equal(a[key], b[key]): return False return True return a == b
[docs] def merge_2_meta_data_dicts(dict1, dict2): ''' Combines metadata from two dictionaries into a single dictionary containing metadata of both. Performs a check to ensure that the two dictionaries don't have the same variable with conflicting metadata. Assuming that check passes, the variables and their associated metadata from both dictionaries are combined into one dictionary. Parameters ---------- dict1, dict2 : dict Dictionaries with keys of Aviary variables and values of their associated metadata. Returns ------- new_dict : dict Single dictionary with all the combined entries from the two input Aviary metadata dictionaries. Raises ------ ValueError Raises error if dict1 and dict2 have differing metadata for the same variable. ''' dict1_keys = set(dict1.keys()) # get keys of provided dictionaries dict2_keys = set(dict2.keys()) # get keys of provided dictionaries # get keys that are unique to each dictionary all_unique_keys = (dict1_keys | dict2_keys) - (dict1_keys & dict2_keys) # get all keys that are repeated in both dictionaries all_duplicate_keys = dict1_keys & dict2_keys # merge the two dictionaries, and allow the repeated keys to be overwritten merged = {**dict1, **dict2} dict_of_unique_variables = dict( # get a dictionary of all the unique keys (and their values) from the input dictionaries map(lambda key: (key, merged.get(key, None)), all_unique_keys)) # initialize a dictionary of the values with duplicated keys in both input dictionaries dict_of_duplicate_variables = {} for key in sorted(all_duplicate_keys): # check that the metadata in both dictionaries associated with the same key is the same value1, value2 = dict1[key], dict2[key] # throw an error if the dicts have the same key with different metadata if not almost_equal(value1, value2): raise ValueError( f'You have attempted to merge metadata dictionaries that contain the same variable with different metadata. The offending variable present in multiple dictionaries is "{key}".') # add the key and metadata to the dictionary of duplicate variables dict_of_duplicate_variables[key] = dict1[key] # merge together the final dictionary new_dict = {**dict_of_duplicate_variables, **dict_of_unique_variables} return new_dict
[docs] def merge_meta_data(dicts_to_merge): ''' Merges the metadata of multiple Aviary metadata dictionaries into a single metadata dictionary. Checks the metadata of all the provided Aviary metadata dictionaries to see if there are identical variables with conflicting metadata. Assuming this check passes, the input dictionaries are merged together into a single dictionary containing all their information. Parameters ---------- dicts_to_merge : list of dicts List of Aviary metadata dictionaries to be merged. Returns ------- merged_dict : dict Single Aviary metadata dictionary with all the information of the inputted metadata dictionaries. Raises ------ None No exceptions raised by this method, although other methods called within may raise exceptions. ''' merged_dict = dicts_to_merge[0] # iterate through all the dictionaries and merge them together into one, two by two for dict_item in dicts_to_merge: merged_dict = merge_2_meta_data_dicts(merged_dict, dict_item) return merged_dict