From 7d30dc17ad1f2ece2b5dadabf79aa5ea2dc9bb89 Mon Sep 17 00:00:00 2001 From: David Hendriks <davidhendriks93@gmail.com> Date: Tue, 15 Sep 2020 21:11:23 +0100 Subject: [PATCH] adding functionality to load binary_c calls from a sourcefile --- binarycpython/utils/functions.py | 2 +- binarycpython/utils/grid.py | 203 ++++++++++++++++--- binarycpython/utils/grid_options_defaults.py | 6 +- tests/core/test_persistent_data.py | 24 ++- 4 files changed, 198 insertions(+), 37 deletions(-) diff --git a/binarycpython/utils/functions.py b/binarycpython/utils/functions.py index 7d54cba16..8ad24f1e6 100644 --- a/binarycpython/utils/functions.py +++ b/binarycpython/utils/functions.py @@ -727,7 +727,7 @@ def inspect_dict(dict_1, indent=0, print_structure=True): if print_structure: print("\t" * indent, key, type(value)) if isinstance(value, dict): - structure_dict[key] = inspect_dict(value, indent=indent + 1) + structure_dict[key] = inspect_dict(value, indent=indent + 1, print_structure=print_structure) return structure_dict diff --git a/binarycpython/utils/grid.py b/binarycpython/utils/grid.py index ed1b651af..3f491f03d 100644 --- a/binarycpython/utils/grid.py +++ b/binarycpython/utils/grid.py @@ -521,6 +521,85 @@ class Population: custom_logging_code, verbose=self.grid_options["verbosity"] ) + ################################################### + # Sourcefile functions + ################################################### + + def load_source_file(self, check=False): + """ + Function that loads the source_file that contains a binary_c calls + """ + + if not os.path.isfile(self.grid_options["source_file_filename"]): + verbose_print("Source file doesnt exist", self.grid_options["verbosity"], 0) + + verbose_print( + message="Loading source file from {}".format( + self.grid_options["gridcode_filename"] + ), + verbosity=self.grid_options["verbosity"], + minimal_verbosity=1, + ) + + # We can choose to perform a check on the sourcefile, which checks if the lines start with 'binary_c' + if check: + source_file_check_filehandle = open(self.grid_options["source_file_filename"], 'r') + for line in source_file_check_filehandle: + if not line.startswith('binary_c') + failed = True + break + if failed: + verbose_print("Error, sourcefile contains lines that do not start with binary_c", self.grid_options["verbosity"], 0) + raise ValueError + + source_file_filehandle = open(self.grid_options["source_file_filename"], 'r') + + self.grid_options["system_generator"] = source_file_filehandle + + verbose_print("Source file loaded", self.grid_options["verbosity"], 1) + + def dict_from_line_source_file(self): + """ + Function that creates a dict from a binary_c argline + """ + + if line.startswith("binary_c "): + line = line.replace("binary_c ", "") + + split_line = line.split() + arg_dict = {} + + for i in range(0, len(split_line), 2): + if "." in split_line[i+1]: + arg_dict[split_line[i]] = float(split_line[i + 1]) + else: + arg_dict[split_line[i]] = int(split_line[i + 1]) + + return arg_dict + + def dry_run_source_file(self): + """ + Function to go through the source_file and count the amount of lines and the total probability + """ + + system_generator = self.grid_options["system_generator"] + + total_starcount = 0 + total_probability = 0 + + contains_probability = False + + for line in system_generator: + + + + total_starcount += 1 + + + total_starcount = system_generator(self) + self.grid_options["total_starcount"] = total_starcount + + ################################################### # Ensemble functions ################################################### @@ -637,44 +716,83 @@ class Population: ) raise ValueError - ####################### - # Dry run and getting starcount - self.grid_options["probtot"] = 0 + # Check which type of population generation + if grid_options["population_type_options"] == "grid": + ####################### + # Dry run and getting starcount + self.grid_options["probtot"] = 0 - # Put in check - if len(self.grid_options["grid_variables"]) == 0: - print("Error: you havent defined any grid variables! Aborting") - raise ValueError + # Put in check + if len(self.grid_options["grid_variables"]) == 0: + print("Error: you havent defined any grid variables! Aborting") + raise ValueError - # Set up the grid code with a dry run option to see total probability - self.generate_grid_code(dry_run=True) + # Set up the grid code with a dry run option to see total probability + self.generate_grid_code(dry_run=True) - # Load the grid code - self.load_grid_function() + # Load the grid code + self.load_grid_function() - # Do a dry run - self.dry_run() + # Do a dry run + self.dry_run() - print( - "Total starcount for this run will be: {}".format( - self.grid_options["total_starcount"] + print( + "Total starcount for this run will be: {}".format( + self.grid_options["total_starcount"] + ) ) - ) - ####################### - # Reset values and prepare the grid function - self.grid_options[ - "probtot" - ] = 0 # To make sure that the values are reset. TODO: fix this in a cleaner way - self.grid_options[ - "start_time_evolution" - ] = time.time() # Setting start time of grid + ####################### + # Reset values and prepare the grid function + self.grid_options[ + "probtot" + ] = 0 # To make sure that the values are reset. TODO: fix this in a cleaner way + self.grid_options[ + "start_time_evolution" + ] = time.time() # Setting start time of grid + + # + self.generate_grid_code(dry_run=False) + + # + self.load_grid_function() + + # Source file + elif grid_options["population_type_options"] == "source_file": + ####################### + # Dry run and getting starcount + self.grid_options["probtot"] = 0 + + # Load the grid code + self.load_source_file_function() + + # Do a dry run + self.dry_run_source_file() + + print( + "Total starcount for this run will be: {}".format( + self.grid_options["total_starcount"] + ) + ) + + ####################### + # Reset values and prepare the grid function + self.grid_options[ + "probtot" + ] = 0 # To make sure that the values are reset. TODO: fix this in a cleaner way + self.grid_options[ + "start_time_evolution" + ] = time.time() # Setting start time of grid + + # + self.load_source_file_function(dry_run=False) + + # + self.load_grid_function() + + - # - self.generate_grid_code(dry_run=False) - # - self.load_grid_function() ####### @@ -1391,6 +1509,31 @@ class Population: # warning; dont use yet. not fully tested. """ + # Check if there is no compiled grid yet. If not, lets try to build it first. + if not self.grid_options["system_generator"]: + + ## check the settings: + if self.bse_options.get("ensemble", None): + if self.bse_options['ensemble'] == 1: + if not self.bse_options["ensemble_defer"] == 1: + verbose_print( + "Error, if you want to run an ensemble in a population, the output needs to be deferred", + self.grid_options["verbosity"], + 0, + ) + raise ValueError + + # Put in check + if len(self.grid_options["grid_variables"]) == 0: + print("Error: you havent defined any grid variables! Aborting") + raise ValueError + + # + self.generate_grid_code(dry_run=False) + + # + self.load_grid_function() + if self.grid_options["system_generator"]: # Check if there is an output dir configured if self.custom_options.get("data_dir", None): @@ -1435,7 +1578,7 @@ class Population: file.write(binary_cmdline_string + "\n") else: print("Error. No grid function found!") - raise KeyError + raise ValueError def cleanup_defaults(self): """ diff --git a/binarycpython/utils/grid_options_defaults.py b/binarycpython/utils/grid_options_defaults.py index ea33f57d4..bbcda861e 100644 --- a/binarycpython/utils/grid_options_defaults.py +++ b/binarycpython/utils/grid_options_defaults.py @@ -27,7 +27,7 @@ grid_options_defaults_dict = { # binary_c files ########################## "binary_c_executable": os.path.join( - os.environ["BINARY_C"], "binary_c-config" + os.environ["BINARY_C"], "binary_c" ), # TODO: make this more robust "binary_c_shared_library": os.path.join( os.environ["BINARY_C"], "src", "libbinary_c.so" @@ -69,7 +69,9 @@ grid_options_defaults_dict = { "population_type": "grid", # "population_type_options": [ "grid", - ], # Available choices for type of population generation # TODO: fill later with monte carlo, source file etc + "source_file", + ], # Available choices for type of population generation # TODO: fill later with monte carlo etc + "source_file_filename": None # filename for the source "count": 0, # total count of systems "probtot": 0, # total probability "weight": 1.0, # weighting for the probability diff --git a/tests/core/test_persistent_data.py b/tests/core/test_persistent_data.py index 4ca955ccc..e5b4e251e 100644 --- a/tests/core/test_persistent_data.py +++ b/tests/core/test_persistent_data.py @@ -65,6 +65,8 @@ def test_return_persistent_data_memaddr(): print("Binary_c output:") print(textwrap.indent(str(output), "\t")) + assert isinstance(output, int), "memory adress has to be an integer" + assert output != 0, "memory adress seems not to have a correct value" def test_passing_persistent_data_to_run_system(): # Function to test the passing of the persistent data memoery adress, and having ensemble_defer = True @@ -286,6 +288,12 @@ def test_adding_ensemble_output(): and output on the second run """ + # + # print(json.dumps(test_1_merged_dict, indent=4)) + # print(json.dumps(test_2_json, indent=4)) + + + # assert inspect_dict(test_1_merged_dict, print_structure=False) == inspect_dict( test_2_json, print_structure=False @@ -293,7 +301,7 @@ def test_adding_ensemble_output(): # assert inspect_dict(test_1_merged_dict, print_structure=False) == inspect_dict(test_3_json, print_structure=False), assert_message_2 -def combine_with_empty_json(): +def test_combine_with_empty_json(): argstring_1 = return_argstring(defer_ensemble=0) output_1 = binary_c_python_api.run_system(argstring=argstring_1) ensemble_jsons_1 = [ @@ -351,12 +359,20 @@ def test_free_and_json_output(): # ensemble_jsons_1 = [line for line in output_1.splitlines() if line.startswith("ENSEMBLE_JSON")] # json_1 = json.loads(ensemble_jsons_1[0][len("ENSEMBLE_JSON "):], cls=binarycDecoder) +def test_all(): + test_return_persistent_data_memaddr() + test_passing_persistent_data_to_run_system() + test_full_ensemble_output() + test_adding_ensemble_output() + test_free_and_json_output() + test_combine_with_empty_json() #### if __name__ == "__main__": # test_return_persistent_data_memaddr() # test_passing_persistent_data_to_run_system() # test_full_ensemble_output() - # test_adding_ensemble_output() - test_free_and_json_output() - # combine_with_empty_json() + test_adding_ensemble_output() + # test_free_and_json_output() + # test_combine_with_empty_json() + print("Done") -- GitLab