From 8c48e6ff082271f89018e48e8db6ed160ccc6732 Mon Sep 17 00:00:00 2001 From: David Hendriks <davidhendriks93@gmail.com> Date: Mon, 9 Aug 2021 20:17:35 +0100 Subject: [PATCH] updated extra features function --- binarycpython/utils/functions.py | 209 ++++++++++++------------- examples/notebook_extra_features.ipynb | 181 ++++++++++++++++++++- 2 files changed, 283 insertions(+), 107 deletions(-) diff --git a/binarycpython/utils/functions.py b/binarycpython/utils/functions.py index f8b03c8d6..d428ddd70 100644 --- a/binarycpython/utils/functions.py +++ b/binarycpython/utils/functions.py @@ -492,7 +492,7 @@ def create_hdf5(data_dir: str, name: str) -> None: ######################################################## -def return_binary_c_version_info(parsed: bool = False) -> Union[str, dict]: +def return_binary_c_version_info(parsed: bool = True) -> Union[str, dict]: """ Function that returns the version information of binary_c. This function calls the function _binary_c_bindings.return_version_info() @@ -1478,6 +1478,19 @@ def inspect_dict( return structure_dict +def count_keys_recursive(input_dict): + """ + Function to count the total amount of keys in a dictionary + """ + + local_count = 0 + for key in input_dict.keys(): + local_count += 1 + if isinstance(input_dict[key], (dict, OrderedDict)): + local_count += count_keys_recursive(input_dict[key]) + return local_count + + def merge_dicts(dict_1: dict, dict_2: dict) -> dict: """ Function to merge two dictionaries in a custom way. @@ -1603,6 +1616,7 @@ def merge_dicts(dict_1: dict, dict_2: dict) -> dict: # return new_dict + def update_dicts(dict_1: dict, dict_2: dict) -> dict: """ Function to update dict_1 with values of dict_2 in a recursive way. @@ -1695,70 +1709,23 @@ def update_dicts(dict_1: dict, dict_2: dict) -> dict: return new_dict -def count_keys_recursive(input_dict): - """ - Function to count the total amount of keys in a dictionary - """ - - local_count = 0 - for key in input_dict.keys(): - local_count += 1 - if isinstance(input_dict[key], (dict, OrderedDict)): - local_count += count_keys_recursive(input_dict[key]) - return local_count - - -def recursive_change_key_to_float(input_dict): - """ - Function to recursively change the key to float - - This only works if the dict contains just sub-dicts or numbers/strings. - Does not work with lists as values +def multiply_values_dict(input_dict, factor): """ + Function that goes over dictionary recursively and multiplies the value if possible by a factor - new_dict = OrderedDict() # TODO: check if this still works - - for key in input_dict: - if isinstance(input_dict[key], (dict, OrderedDict)): - try: - num_key = float(key) - new_dict[num_key] = recursive_change_key_to_float(copy.deepcopy(input_dict[key])) - except ValueError: - new_dict[key] = recursive_change_key_to_float(copy.deepcopy(input_dict[key])) - else: - try: - num_key = float(key) - new_dict[num_key] = input_dict[key] - except ValueError: - new_dict[key] = input_dict[key] - - return new_dict - -def recursive_change_key_to_string(input_dict): - """ - Function to recursively change the key back to a string but this time in a format that we decide + If the key equals "general_info", the multiplication gets skipped """ - new_dict = OrderedDict() # TODO: check if this still works - for key in input_dict: - if isinstance(input_dict[key], (dict, OrderedDict)): - if isinstance(key, (int, float)): - string_key = "{:g}".format(key) - new_dict[string_key] = recursive_change_key_to_string(copy.deepcopy(input_dict[key])) - else: - new_dict[key] = recursive_change_key_to_string(copy.deepcopy(input_dict[key])) - else: - if isinstance(key, (int, float)): - string_key = "{:g}".format(key) - new_dict[string_key] = input_dict[key] + if not key == 'general_info': + if isinstance(input_dict[key], (dict, OrderedDict)): + input_dict[key] = multiply_values_dict(input_dict[key], factor) else: - new_dict[key] = input_dict[key] - - return new_dict + if isinstance(input_dict[key], (int, float)): + input_dict[key] = input_dict[key] * factor + return input_dict -# New method to create a ordered dictionary def custom_sort_dict(input_dict): """ Returns a dictionary that is ordered, but can handle numbers better than normal OrderedDict @@ -1810,26 +1777,58 @@ def custom_sort_dict(input_dict): return input_dict -def multiply_values_dict(input_dict, factor): +def recursive_change_key_to_float(input_dict): """ - Function that goes over dictionary recursively and multiplies the value if possible by a factor + Function to recursively change the key to float - If the key equals "general_info", the multiplication gets skipped + This only works if the dict contains just sub-dicts or numbers/strings. + Does not work with lists as values """ + new_dict = OrderedDict() # TODO: check if this still works + for key in input_dict: - if not key == 'general_info': - if isinstance(input_dict[key], (dict, OrderedDict)): - input_dict[key] = multiply_values_dict(input_dict[key], factor) + if isinstance(input_dict[key], (dict, OrderedDict)): + try: + num_key = float(key) + new_dict[num_key] = recursive_change_key_to_float(copy.deepcopy(input_dict[key])) + except ValueError: + new_dict[key] = recursive_change_key_to_float(copy.deepcopy(input_dict[key])) + else: + try: + num_key = float(key) + new_dict[num_key] = input_dict[key] + except ValueError: + new_dict[key] = input_dict[key] + + return new_dict + + +def recursive_change_key_to_string(input_dict): + """ + Function to recursively change the key back to a string but this time in a format that we decide + """ + + new_dict = OrderedDict() # TODO: check if this still works + + for key in input_dict: + if isinstance(input_dict[key], (dict, OrderedDict)): + if isinstance(key, (int, float)): + string_key = "{:g}".format(key) + new_dict[string_key] = recursive_change_key_to_string(copy.deepcopy(input_dict[key])) else: - if isinstance(input_dict[key], (int, float)): - input_dict[key] = input_dict[key] * factor + new_dict[key] = recursive_change_key_to_string(copy.deepcopy(input_dict[key])) + else: + if isinstance(key, (int, float)): + string_key = "{:g}".format(key) + new_dict[string_key] = input_dict[key] + else: + new_dict[key] = input_dict[key] - return input_dict + return new_dict ##### - def extract_ensemble_json_from_string(binary_c_output: str) -> dict: """ Function to extract the ensemble_json information from a raw binary_c output string @@ -1875,6 +1874,44 @@ def extract_ensemble_json_from_string(binary_c_output: str) -> dict: return json_dict +def handle_ensemble_string_to_json(raw_output): + """ + Function that deals with the raw output of the ensemble and + creates a working JSON dictionary out of it. + + Having this wrapper makes it easy to + + Args: + raw_output: raw output of the ensemble dump by binary_c + + Returns: + json.loads(raw_output, cls=binarycDecoder) + + """ + + # return json.loads(json.dumps(ast.literal_eval(raw_output)), cls=binarycDecoder) + return json.loads(raw_output, cls=binarycDecoder) + + +def binaryc_json_serializer(obj: Any) -> Any: + """ + Custom serialiser for binary_c to use when functions are present in the dictionary + that we want to export. + + Function objects will be turned into str representations of themselves + + Args: + obj: The object that might not be serialisable + + Returns: + Either string representation of object if the object is a function, or the object itself + """ + + if inspect.isfunction(obj) or isinstance(obj, py_rinterpolate.Rinterpolate): + return str(obj) + return obj + + class binarycDecoder(json.JSONDecoder): """ Custom decoder to transform the numbers that are strings to actual floats @@ -1931,41 +1968,3 @@ class BinaryCEncoder(json.JSONEncoder): # Let the base class default method raise the TypeError return json.JSONEncoder.default(self, o) - - -def binaryc_json_serializer(obj: Any) -> Any: - """ - Custom serialiser for binary_c to use when functions are present in the dictionary - that we want to export. - - Function objects will be turned into str representations of themselves - - Args: - obj: The object that might not be serialisable - - Returns: - Either string representation of object if the object is a function, or the object itself - """ - - if inspect.isfunction(obj) or isinstance(obj, py_rinterpolate.Rinterpolate): - return str(obj) - return obj - - -def handle_ensemble_string_to_json(raw_output): - """ - Function that deals with the raw output of the ensemble and - creates a working JSON dictionary out of it. - - Having this wrapper makes it easy to - - Args: - raw_output: raw output of the ensemble dump by binary_c - - Returns: - json.loads(raw_output, cls=binarycDecoder) - - """ - - # return json.loads(json.dumps(ast.literal_eval(raw_output)), cls=binarycDecoder) - return json.loads(raw_output, cls=binarycDecoder) diff --git a/examples/notebook_extra_features.ipynb b/examples/notebook_extra_features.ipynb index d453a6f5b..b68864639 100644 --- a/examples/notebook_extra_features.ipynb +++ b/examples/notebook_extra_features.ipynb @@ -8,13 +8,190 @@ "# Extra features and functionality of binarycpython\n", "In this notebook we'll go over some of the extra features and functionality that was not covered in the other notebooks.\n", "\n", - "TODO" + "Within the module `binarycpython.utils.functions` there are many functions that can be useful when using binarycpython. We can see which functions are in there, again by using the `help()`" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "de73a2c1-7acd-4b55-a4c4-ee6a7e0758d0", + "metadata": {}, + "outputs": [], + "source": [ + "from binarycpython.utils.functions import (\n", + " get_help,\n", + " get_help_all,\n", + " get_help_super,\n", + " return_binary_c_version_info,\n", + " get_defaults\n", + ")\n", + "# help(binarycpython.utils.functions)" + ] + }, + { + "cell_type": "markdown", + "id": "88b93969-b6aa-41b7-8f4d-2eee38d7a756", + "metadata": {}, + "source": [ + "## getting extra information about binary_c parameters\n", + "There are several functions that can be used to get information about the parameters in binary_c: \n", + "- `get_help(parameter)`: Function to get information about the specific input parameter. Prints the output on default but returns a dictionary containing the information. \n", + "- `get_help_all(print_help=True)`: Function to get information about all the parameters. Prints the output on default but returns a dictionary containing the information. \n", + "- `get_help_super()`: Function to get even more information about all the parameters. Does not print the output on default but returns a dictionary containing the information. \n", + "- `get_defaults()`: Function that will get all the default values for the parameters. Returns a dictionary" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "7cfe1832-7fec-4817-b633-5b275c65667f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "parameter_name:\n", + "\tM_1\n", + "parameter_value_input_type:\n", + "\tFloat\n", + "description:\n", + "\tThe initial mass of star one (in solar units, internally this is star index 0).\n", + "default:\n", + "\t0\n" + ] + }, + { + "data": { + "text/plain": [ + "{'parameter_name': 'M_1',\n", + " 'parameter_value_input_type': 'Float',\n", + " 'description': 'The initial mass of star one (in solar units, internally this is star index 0).',\n", + " 'default': '0'}" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "get_help('M_1')" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "af62a066-ef70-4b59-877e-2b5a6bafcfc2", + "metadata": {}, + "outputs": [], + "source": [ + "# get_help_all()" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "b85f1956-ee69-444a-a212-cd7473007bf1", + "metadata": {}, + "outputs": [], + "source": [ + "# get_help_super()" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "id": "e22b7a47-2748-406e-bba4-e92825ea9b47", + "metadata": {}, + "outputs": [], + "source": [ + "# get_defaults()" + ] + }, + { + "cell_type": "markdown", + "id": "c89ef423-82b9-49ed-8cf9-94c9ce41a82a", + "metadata": {}, + "source": [ + "## Build information of binary_c\n", + "Sometimes we want to know with which settings binary_c has been built. We can use the function `return_binary_c_version_info` for this.\n", + "This function will parse the version info of binary_c and return a dictionary with all the settings." + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "4dae05bd-6a66-4b1f-be4a-d092627dfe37", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "dict_keys(['networks', 'isotopes', 'argpairs', 'ensembles', 'macros', 'elements', 'dt_limits', 'nucleosynthesis_sources', 'miscellaneous'])\n" + ] + } + ], + "source": [ + "version_info_dict = return_binary_c_version_info(parsed=True)\n", + "print(version_info_dict.keys())" + ] + }, + { + "cell_type": "markdown", + "id": "708c7253-9d9d-4705-969b-23f29695517d", + "metadata": {}, + "source": [ + "## Example parse function\n", + "TODO: In the functions module there is an example parse function that can be used in conjunction with run_system. " + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "8656614a-09da-486f-b299-61cc6092187c", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Help on function get_defaults in module binarycpython.utils.functions:\n", + "\n", + "get_defaults(filter_values:bool=False) -> dict\n", + " Function that calls the binaryc get args function and cast it into a dictionary.\n", + " \n", + " All the values are strings\n", + " \n", + " Args:\n", + " filter_values: whether to filter out NULL and Function defaults.\n", + " \n", + " Returns:\n", + " dictionary containing the parameter name as key and the parameter default as value\n", + "\n" + ] + } + ], + "source": [] + }, + { + "cell_type": "markdown", + "id": "6fac26d0-a0d2-40c7-915d-0883247cd24d", + "metadata": {}, + "source": [ + "## Dictionary modification\n", + "- merge_dicts \n", + "- update_dicts\n", + "- multiply_values_dict\n", + "\n", + "TODO:" ] }, { "cell_type": "code", "execution_count": null, - "id": "0020f1bc-2a23-455c-8216-9e63e6e038ae", + "id": "bf3c1e28-1662-47a7-abab-aa6fb0ef0882", "metadata": {}, "outputs": [], "source": [] -- GitLab