diff --git a/binarycpython/utils/custom_logging_functions.py b/binarycpython/utils/custom_logging_functions.py index 9f58b705a291e39df188765ba9b286a3b27bddff..b966f6eaed6417cd87e8246c112f57abc8cb767a 100644 --- a/binarycpython/utils/custom_logging_functions.py +++ b/binarycpython/utils/custom_logging_functions.py @@ -5,7 +5,6 @@ import socket import tempfile import ctypes - def autogen_C_logging_code(logging_dict): """ Function that autogenerates PRINTF statements for binaryc. intput is a dictionary where the key is the header of that logging line and items which are lists of parameters\ @@ -221,7 +220,6 @@ def return_compilation_dict(verbose=False): return {"cc": cc, "ld": ld, "ccflags": ccflags, "libs": libs, "inc": inc} - def compile_shared_lib(code, sourcefile_name, outfile_name, verbose=False): """ Function to write the custom logging code to a file and then compile it. diff --git a/binarycpython/utils/functions.py b/binarycpython/utils/functions.py index f6ed5c1c5f2245ceb592a420fdaab4bafa282ddf..fa525601be2710abc0f02b85a64ab047ec76ffb1 100644 --- a/binarycpython/utils/functions.py +++ b/binarycpython/utils/functions.py @@ -163,7 +163,7 @@ def get_arg_keys(): return get_defaults().keys() -def get_help(param_name, return_dict=False): +def get_help(param_name, print_help=True, return_dict=False): """ Function that returns the help info for a given parameter. @@ -237,8 +237,9 @@ def get_help(param_name, return_dict=False): macros = cleaned[macros_line_nr[0] + 1 :] help_info_dict["macros"] = macros - # for key in help_info_dict.keys(): - # print("{}:\n\t{}".format(key, help_info_dict[key])) + if print_help: + for key in help_info_dict.keys(): + print("{}:\n\t{}".format(key, help_info_dict[key])) if return_dict: return help_info_dict @@ -412,6 +413,10 @@ def parse_output(output, selected_header): def load_logfile(logfile): + """ + Function that parses the generated logfile of binary_c + """ + with open(logfile, "r") as f: logfile_data = f.readlines() diff --git a/binarycpython/utils/grid.py b/binarycpython/utils/grid.py index 0980dd3ab6790d404c0790f0a294a3b75d94a437..c846fcbd2d8266cabce747340f1e7c4647545a21 100644 --- a/binarycpython/utils/grid.py +++ b/binarycpython/utils/grid.py @@ -5,20 +5,18 @@ import sys import binary_c_python_api -from binarycpython.utils.functions import get_defaults - import binarycpython +from binarycpython.utils.grid_options_defaults import grid_options_defaults_dict +from binarycpython.utils.custom_logging_functions import autogen_C_logging_code, binary_c_log_code, create_and_load_logging_function +from binarycpython.utils.functions import get_defaults -from grid_options_defaults import grid_options_defaults_dict - -from custom_logging_functions import autogen_C_logging_code, binary_c_log_code, create_and_load_logging_function +# TODO list # TODO: add functionality to parse cmdline args # TODO: add functionality to 'on-init' set arguments # DONE: add functionality to export the arg string. -# TODO: add functionality to export all the options -# TODO: add functionality to create the dict that goes into the arg line. +# DONE: add functionality to export all the options # TODO: add functionality to return the initial_abundance_hash # TODO: add functionality to return the isotope_hash @@ -28,28 +26,97 @@ from custom_logging_functions import autogen_C_logging_code, binary_c_log_code, # TODO: add functionality to return the source_list # TODO: add functionality to return the ensemble_list -# TODO: add functionality to return the evcode_version_string +# DONE: add functionality to return the evcode_version_string # Make this function also an API call. Doest seem to get written to a buffer that is stored into a python object. rather its just written to stdout -# TODO: add functionality to return the evcode_args_list +# DONE: add functionality to return the evcode_args_list + class Population(object): def __init__(self): """ - Lots of initialisation + Initialisation function of the population class """ self.defaults = get_defaults() # Different sections of options - self.bse_options = self.defaults.copy() + self.bse_options = {} # bse_options is just empty. Setting stuff will check against the defaults to see if the input is correct. self.grid_options = grid_options_defaults_dict.copy() self.custom_options = {} # Argline dict self.argline_dict = {} - def return_options(self): + + ################################################### + # Argument functions + ################################################### + + # General flow of generating the arguments for the binary_c call: + # - user provides parameter and value via set (or manually but that is risky) + # - The parameter names of these input get compared to the parameter names in the self.defaults; with this, we know that its a valid + # parameter to give to binary_c. + # - For a single system, the bse_options will be written as a arg line + # - For a population the bse_options will get copied to a temp_bse_options file and updated with all the parameters generated by the grid + + + # I will NOT create the argument line by fully writing ALL the defaults and overriding user input, that seems not necessary + # because by using the get_defaults() function we already know for sure which parameter names are valid for the binary_c version + # And because binary_c uses internal defaults, its not necessary to explicitly pass them + # I do however suggest everyone to export the binary_c defaults to a file, so that you know exactly which values were the defaults + + def set(self, **kwargs): + """ + Function to set the values of the population. This is the preferred method to set values of functions, as it + provides checks on the input. + + the bse_options will get populated with all the those that have a key that is present in the self.defaults + the grid_options will get updated with all the those that have a key that is present in the self.grid_options + + If neither of above is met; the key and the value get stored in a custom_options dict. + """ + + for key in kwargs.keys(): + # Filter out keys for the bse_options + if key in self.defaults.keys(): + print('adding: {}={} to BSE_options'.format(key,kwargs[key])) + self.bse_options[key] = kwargs[key] + + # Filter out keys for the grid_options + elif key in self.grid_options.keys(): + self.grid_options[key] = kwargs[key] + # The of the keys go into a custom_options dict + else: + self.custom_options[key] = kwargs[key] + + def return_argline(self, parameter_dict=None): + """ + Function to create the string for the arg line from a parameter dict + """ + + if not parameter_dict: + parameter_dict = self.bse_options + + argline = "binary_c " + for param_name in sorted(parameter_dict): + argline += "{} {} ".format(param_name, parameter_dict[param_name]) + argline = argline.strip() + return argline + + def generate_population_arglines_file(self, output_file): + """ + Function to generate a file that contains all the argument lines that would be given to binary_c if the population had been run + """ + + pass + + + ################################################### + # Return functions + ################################################### + + def return_population_settings(self): """ Function that returns all the options that have been set. @@ -64,93 +131,73 @@ class Population(object): return options - - def create_argline_dict(self, print_excluded=False): + def return_binary_c_version_info(self): """ - Function to prepare the dictionary of options that go into the argument line for the binary_c call. - - This function + Function that returns the version information of binary_c + + TODO: Put in a nice dict. """ - self.argline_dict = {} - - # Lists to store indices of parameters that have been included and excluded. - included, excluded = [], [] + version_info = binary_c_python_api.return_version_info() - # Go over the parameters. - for i, param_name in enumerate(sorted(self.bse_options)): - # We need to filter out some parameters: - # Filter out those that have an literal empty value. The argument parser of binary_c doesnt work properly with that. - # Filter out those that have value Function. adding these to the argument will execute the function instead of evolving the system - # Filter out those that have value NULL. In general these only come from the defaults of binary_c itself. - # What I do here is comparing whether the value of the bse_option is NULL currently AND as a default. In that way one could set some other part to NULL (don't know what situation that would be tho..) + return version_info.strip() + def return_binary_c_defaults(self): + """ + Function that returns the defaults of the binary_c version that is used. + """ - if (not ((self.bse_options[param_name] == 'NULL') and (self.bse_options[param_name] == self.defaults[param_name]))) \ - and (not self.bse_options[param_name] == "") and (not self.bse_options[param_name] == "Function"): - self.argline_dict[param_name] = self.bse_options[param_name] - # print("{} {} ".format(param_name, self.bse_options[param_name])) - included.append(i) - else: - # print("{} {} ".format(param_name, repr(self.bse_options[param_name]))) - excluded.append(i) + return self.defaults - common = set(included).intersection(excluded) - combined = set(included).union(excluded) + def return_all_info(self): + """ + Function that returns all the information about the population and binary_c + """ - if print_excluded: - print("Total parameters included in the argument: {}. Total excluded: {}. ".format(len(included), len(excluded))) - print([sorted(self.bse_options)[i] for i in excluded]) + from binarycpython.utils.functions import get_help_all + population_settings = self.return_population_settings() + binary_c_defaults = self.return_binary_c_defaults() + binary_c_version_info = self.return_binary_c_version_info() + binary_c_help_all_info = get_help_all(print_help=False, return_dict=True) - def create_argline(self, option_dict): - """ - Function to create the string for the arg line - """ + all_info = {} + all_info['population_settings'] = population_settings + all_info['binary_c_defaults'] = binary_c_defaults + all_info['binary_c_version_info'] = binary_c_version_info + all_info['binary_c_help_all'] = binary_c_help_all_info - argline = "binary_c " - for param_name in sorted(option_dict): - argline += "{} {} ".format(param_name, self.argline_dict[param_name]) - argline = argline.strip() - return argline + return all_info - def return_argline(self, print_excluded=False): + def export_all_info(self, outfile): """ - Function to return the argline that is used in the binary_c api call: - be aware that some of the parameters vary: M1 M2 period etc because these are set by distributions. + Function that exports the all_info to a json file + TODO: if any of the values in the dicts here is of a not-serializable form, then we need to change that to a string or something + so, use a recursive function that goes over the all_info dict and finds those that fit """ - self.create_argline_dict(print_excluded) + all_info = self.return_all_info() - argline = "binary_c " - for param_name in sorted(self.argline_dict.keys()): - argline += "{} {} ".format(param_name, self.argline_dict[param_name]) + # if not outfile.endswith('json'): + with open(outfile, 'w') as f: + f.write(json.dumps(all_info, indent=4)) - argline = argline.strip() - return argline + ################################################### + # Evolution functions + ################################################### - def set(self, **kwargs): + def evolve_single(self): """ - Function to set the values of the population - - The input (as kwargs) is checked compared to the available bse_options and grid options. - if the parameter name is not included in either of those, then it will be stored in an custom_options dict. + Function to run a single system """ - print(self.grid_options.keys()) - - for key in kwargs.keys(): - # Filter out keys for the bse_options - if key in self.bse_options.keys(): - self.bse_options[key] = kwargs[key] - # Filter out keys for the grid_options - elif key in self.grid_options.keys(): - self.grid_options[key] = kwargs[key] - # The of the keys go into a custom_options dict - else: - self.custom_options[key] = kwargs[key] + argline = self.return_argline(self.bse_options) +return_binary_c_version_info + out = binary_c_python_api.run_binary(argline) + # out = binary_c_python_api.run_binary('binary_c M_1 15 M_2 14 separation 0 orbital_period 4530 eccentricity 0 metallicity 0.02 max_evolution_time 15000') + return out def evolve_population(self, custom_arg_file=None): """ @@ -179,9 +226,6 @@ class Population(object): self.grid_options['custom_logging_func_memaddr'] = create_and_load_logging_function(custom_logging_code) ### - - - ### Arguments # If user inputs a file containing arg lines then use that if custom_arg_file: @@ -197,6 +241,11 @@ class Population(object): else: # generate population from options + + + + print('ho') + pass ####### @@ -210,35 +259,9 @@ class Population(object): pass - def generate_population_arglines_file(self, output_file): - """ - Function to generate a file that contains all the argument lines that would be given to binary_c if the population had been run - """ - - - - def evolve_single(self): - """ - Function to run a single system - """ - - self.create_argline_dict() - - argline = self.create_argline(self.argline_dict) - - out = binary_c_python_api.run_binary(argline) - # out = binary_c_python_api.run_binary('binary_c M_1 15 M_2 14 separation 0 orbital_period 4530 eccentricity 0 metallicity 0.02 max_evolution_time 15000') - # print(out) - return out - - def return_binary_c_version_info(self): - """ - Function that returns the version information of binary_c - """ - - out = binary_c_python_api.run_binary('binary_c version') - # out = binary_c_python_api.run_binary('binary_c M_1 15 M_2 14 separation 0 orbital_period 4530 eccentricity 0 metallicity 0.02 max_evolution_time 15000') - return out + ################################################### + # Testing functions + ################################################### def test_evolve_single(self): m1 = 15.0 # Msun @@ -264,52 +287,4 @@ class Population(object): print(output) - - - ################################################################################################ -test_pop = Population() - -# Setting values -# print(test_pop.bse_options['M_1']) -# print(test_pop.bse_options['M_2']) -# test_pop.set(M_1=10, M_2=500) -# print(test_pop.bse_options['M_1']) -# print(test_pop.bse_options['M_2']) -test_pop.set(M_1=10, separation=0, orbital_period=4580, max_evolution_time=15000, eccentricity=0.02, ) - - -## Testing single evolution -# test_pop.evolve_single() -# test_pop.test_evolve_single() - -## Setting custom value -# test_pop.set(data_dir=os.path.join(os.environ['BINARYC_DATA_ROOT'], 'development_example')) -# print(test_pop.custom_options['data_dir']) - - -## printing all options -# print(json.dumps(test_pop.return_options(), indent=4)) - -## return arglines: -# test_pop.set(M_1=10, M_2=500) -# print(test_pop.return_argline()) -# test_pop.return_argline(print_excluded=True) - -#print(test_pop.bse_options) - -## return version info -# a = test_pop.return_binary_c_version_info() -# print(a) - -## Use custom arg file -# test_pop.evolve_population(custom_arg_file='/home/david/projects/binary_c_root/binary_c-python/tests/population/custom_arg_file.txt') - - - -## Custom logging: -# test_pop.set(C_auto_logging={'MY_HEADER_LINE': ['star[0].mass', 'star[1].mass', 'model.probability']}) -# test_pop.set(C_logging_code='Printf("MY_STELLAR_DATA time=%g mass=%g\\n", stardata->model.time, stardata->star[0].mass);') -# test_pop.set(C_logging_code='Printf("MY_HEADER_LINE %g %g %g\\n",((double)stardata->star[0].mass),((double)stardata->star[1].mass),((double)stardata->model.probability));') -# test_pop.evolve_population() - diff --git a/binarycpython/utils/grid_options_defaults.py b/binarycpython/utils/grid_options_defaults.py index f635578f9909022d131051f20b0132b21a3d8df6..d45f0a53b0246816fd76c2995ed1cd134e454cdf 100644 --- a/binarycpython/utils/grid_options_defaults.py +++ b/binarycpython/utils/grid_options_defaults.py @@ -1,13 +1,25 @@ grid_options_defaults_dict = { - 'custom_logging_function': None, # This will hold the custom logging mem addr + # 'amt_cores': 1, # total amount of cores used to evolve the population 'verbose': 0, # Level of verbosity of the simulation - # Custom logging 'C_auto_logging': None, # Should contain a dictionary where the kes are they headers and the values are lists of parameters that should be logged. This will get parsed by autogen_C_logging_code in custom_loggion_functions.py 'C_logging_code': None, # Should contain a string which holds the logging code. 'custom_logging_func_memaddr': -1, # Contains the custom_logging functions memory address + + # Log args: logging of arguments + 'log_args': 0, # + 'log_args_dir': '/tmp/', + - + # return_array_refs=>1, # quicker data parsing mode + # sort_args=>1, + # save_args=>1, + # nice=>'nice -n +20', # nice command e.g. 'nice -n +10' or '' + # timeout=>15, # seconds until timeout + # log_filename=>"/scratch/davidh/results_simulations/tmp/log.txt", + # # current_log_filename=>"/scratch/davidh/results_simulations/tmp/grid_errors.log", + } + diff --git a/include/binary_c_python.h b/include/binary_c_python.h index 01aca72eac4bb71c4e0abfcb8ba4c4fa9c0cd61d..fe229b9b2f003775ebab00743eb0e4f392cf1bfa 100644 --- a/include/binary_c_python.h +++ b/include/binary_c_python.h @@ -9,6 +9,9 @@ #include "binary_c_API_prototypes.h" /* Binary_c's python API prototypes */ + + + int run_binary(char * argstring, char ** const outstring, char ** const errorstring, @@ -20,11 +23,23 @@ int run_binary_with_logfile(char * argstring, size_t * const nbytes); int run_binary_custom_logging(char * argstring, - long int func_memaddr, + long int custom_logging_func_memaddr, char ** const buffer, char ** const error_buffer, size_t * const nbytes); +int run_population(char * argstring, + long int custom_logging_func_memaddr, + long int store_memaddr, + char ** const buffer, + char ** const error_buffer, + size_t * const nbytes); + + +/* =================================================================== */ +/* Functions to call other API functionality like help and arglines */ +/* =================================================================== */ + int return_arglines(char ** const outstring, char ** const errorstring, size_t * const nbytes); @@ -38,6 +53,20 @@ int return_help_all_info(char ** const outstring, char ** const errorstring, size_t * const nbytes); +int return_version_info(char ** const outstring, + char ** const errorstring, + size_t * const nbytes); + + +/* =================================================================== */ +/* Functions to call other functionality */ +/* =================================================================== */ +long int return_store(char * argstring, // can we do this without argstring? + char ** const buffer, + char ** const error_buffer, + size_t * const nbytes); + + /* C macros */ #define BINARY_C_APITEST_VERSION 0.1 #define APIprint(...) APIprintf(__VA_ARGS__); diff --git a/src/binary_c_python.c b/src/binary_c_python.c index 726752d979131dbe451f28f51d71a8fdddebcf90..1c9d589fea7ff72be94a7fcf86f762068df42ffd 100644 --- a/src/binary_c_python.c +++ b/src/binary_c_python.c @@ -37,10 +37,12 @@ static char new_binary_system_docstring[] = // Evolution function docstrings static char run_binary_docstring[] = "Run one binary using binary_c"; -static char run_binary_with_logdocstring[] = +static char run_binary_with_log_docstring[] = "Run one binary using binary_c and allow the logfile to be written. Do not use for populations!"; -static char run_binary_custom_loggingdocstring[] = +static char run_binary_custom_logging_docstring[] = "TODO"; +static char run_population_docstring[] = + "Run population of systems"; // Utility function docstrings static char return_arglines_docstring[] = @@ -49,6 +51,13 @@ static char return_help_info_docstring[] = "Return the help info for a given parameter"; static char return_help_all_info_docstring[] = "Return an overview of all the parameters, their description, categorized in sections"; +static char return_version_info_docstring[] = + "Return the version information of the used binary_c build"; + +// other functionality +static char return_store_docstring[] = + "Return the store memory adress that will be passed to run_population"; + static struct libbinary_c_store_t *store = NULL; @@ -63,11 +72,16 @@ static PyObject* binary_c_new_binary_system(PyObject *self, PyObject *args); static PyObject* binary_c_run_binary(PyObject *self, PyObject *args); static PyObject* binary_c_run_binary_with_logfile(PyObject *self, PyObject *args); static PyObject* binary_c_run_binary_custom_logging(PyObject *self, PyObject *args); +static PyObject* binary_c_run_population(PyObject *self, PyObject *args); // Utility function headers static PyObject* binary_c_return_arglines(PyObject *self, PyObject *args); static PyObject* binary_c_return_help_info(PyObject *self, PyObject *args); static PyObject* binary_c_return_help_all_info(PyObject *self, PyObject *args); +static PyObject* binary_c_return_version_info(PyObject *self, PyObject *args); + +// Other function headers +static PyObject* binary_c_return_store(PyObject *self, PyObject *args); /* * Python 3 interface is described at @@ -88,13 +102,17 @@ static PyMethodDef module_methods[] = { {"new_system", binary_c_new_binary_system, METH_VARARGS, new_binary_system_docstring}, {"run_binary", binary_c_run_binary, METH_VARARGS, run_binary_docstring}, - {"run_binary_with_logfile", binary_c_run_binary_with_logfile, METH_VARARGS, run_binary_with_logdocstring}, - {"run_binary_custom_logging", binary_c_run_binary_custom_logging, METH_VARARGS, run_binary_custom_loggingdocstring}, + {"run_binary_with_logfile", binary_c_run_binary_with_logfile, METH_VARARGS, run_binary_with_log_docstring}, + {"run_binary_custom_logging", binary_c_run_binary_custom_logging, METH_VARARGS, run_binary_custom_logging_docstring}, + {"run_population", binary_c_run_population, METH_VARARGS, run_population_docstring}, {"return_arglines", binary_c_return_arglines, METH_VARARGS, return_arglines_docstring}, {"return_help", binary_c_return_help_info, METH_VARARGS, return_help_info_docstring}, {"return_help_all", binary_c_return_help_all_info, METH_VARARGS, return_help_all_info_docstring}, - + {"return_version_info", binary_c_return_version_info, METH_VARARGS, return_version_info_docstring}, + + {"return_store", binary_c_return_store, METH_VARARGS, return_store_docstring}, + {NULL, NULL, 0, NULL} }; @@ -200,59 +218,59 @@ static PyObject* binary_c_function_prototype(PyObject *self, PyObject *args) } /* - -Below are the real funtions: -binary_c_run_binary -binary_c_run_binary_custom_logging -binary_c_run_binary_with_logfile - -binary_c_return_arglines -binary_c_return_help_info -binary_c_return_help_all_info - - + Below are the real funtions: + binary_c_run_binary + binary_c_run_binary_custom_logging + binary_c_run_binary_with_logfile + binary_c_run_population + + binary_c_return_arglines + binary_c_return_help_info + binary_c_return_help_all_info + binary_c_return_version_info */ -/* Wrappers to functions that evolve binary systems. */ +/* ============================================================================== */ +/* Wrappers to functions that evolve binary systems. */ +/* ============================================================================== */ + static PyObject* binary_c_run_binary(PyObject *self, PyObject *args) { /* Parse the input tuple */ char *argstring; + /* Parse the input tuple */ if(!PyArg_ParseTuple(args, "s", &argstring)) - { + return NULL; - } - else - { - char * buffer; - char * error_buffer; - size_t nbytes; - int out MAYBE_UNUSED = run_binary(argstring, - &buffer, - &error_buffer, - &nbytes); - /* copy the buffer to a python string */ - PyObject * return_string = Py_BuildValue("s", buffer); - PyObject * return_error_string MAYBE_UNUSED = Py_BuildValue("s", error_buffer); - if(error_buffer != NULL && strlen(error_buffer)>0) - { - fprintf(stderr, - "Error in binary_c run : %s\n", - error_buffer); - } - - Safe_free(buffer); - Safe_free(error_buffer); + char * buffer; + char * error_buffer; + size_t nbytes; + int out MAYBE_UNUSED = run_binary(argstring, + &buffer, + &error_buffer, + &nbytes); + /* copy the buffer to a python string */ + PyObject * return_string = Py_BuildValue("s", buffer); + PyObject * return_error_string MAYBE_UNUSED = Py_BuildValue("s", error_buffer); - /* - * TODO - * return the return_error_string as well! - */ - return return_string; + if(error_buffer != NULL && strlen(error_buffer)>0) + { + fprintf(stderr, + "Error in binary_c run : %s\n", + error_buffer); } + + Safe_free(buffer); + Safe_free(error_buffer); + + /* + * TODO + * return the return_error_string as well! + */ + return return_string; } static PyObject* binary_c_run_binary_custom_logging(PyObject *self, PyObject *args) @@ -265,36 +283,34 @@ static PyObject* binary_c_run_binary_custom_logging(PyObject *self, PyObject *ar { return NULL; } - else - { - char * buffer; - char * error_buffer; - size_t nbytes; - int out MAYBE_UNUSED = run_binary_custom_logging(argstring, - func_memaddr, - &buffer, - &error_buffer, - &nbytes); - /* copy the buffer to a python string */ - PyObject * return_string = Py_BuildValue("s", buffer); - PyObject * return_error_string MAYBE_UNUSED = Py_BuildValue("s", error_buffer); - if(error_buffer != NULL && strlen(error_buffer)>0) - { - fprintf(stderr, - "Error in binary_c run : %s\n", - error_buffer); - } - - Safe_free(buffer); - Safe_free(error_buffer); + char * buffer; + char * error_buffer; + size_t nbytes; + int out MAYBE_UNUSED = run_binary_custom_logging(argstring, + func_memaddr, + &buffer, + &error_buffer, + &nbytes); + /* copy the buffer to a python string */ + PyObject * return_string = Py_BuildValue("s", buffer); + PyObject * return_error_string MAYBE_UNUSED = Py_BuildValue("s", error_buffer); - /* - * TODO - * return the return_error_string as well! - */ - return return_string; + if(error_buffer != NULL && strlen(error_buffer)>0) + { + fprintf(stderr, + "Error in binary_c run : %s\n", + error_buffer); } + + Safe_free(buffer); + Safe_free(error_buffer); + + /* + * TODO + * return the return_error_string as well! + */ + return return_string; } static PyObject* binary_c_run_binary_with_logfile(PyObject *self, PyObject *args) @@ -306,39 +322,84 @@ static PyObject* binary_c_run_binary_with_logfile(PyObject *self, PyObject *args { return NULL; } - else + + char * buffer; + char * error_buffer; + size_t nbytes; + int out MAYBE_UNUSED = run_binary_with_logfile(argstring, + &buffer, + &error_buffer, + &nbytes); + + /* copy the buffer to a python string */ + PyObject * return_string = Py_BuildValue("s", buffer); + PyObject * return_error_string MAYBE_UNUSED = Py_BuildValue("s", error_buffer); + + if(error_buffer != NULL && strlen(error_buffer)>0) { - char * buffer; - char * error_buffer; - size_t nbytes; - int out MAYBE_UNUSED = run_binary_with_logfile(argstring, - &buffer, - &error_buffer, - &nbytes); + fprintf(stderr, + "Error in binary_c run : %s\n", + error_buffer); + } + + Safe_free(buffer); + Safe_free(error_buffer); - /* copy the buffer to a python string */ - PyObject * return_string = Py_BuildValue("s", buffer); - PyObject * return_error_string MAYBE_UNUSED = Py_BuildValue("s", error_buffer); + /* + * TODO + * return the return_error_string as well! + */ + return return_string; +} - if(error_buffer != NULL && strlen(error_buffer)>0) - { - fprintf(stderr, - "Error in binary_c run : %s\n", - error_buffer); - } - - Safe_free(buffer); - Safe_free(error_buffer); +static PyObject* binary_c_run_population(PyObject *self, PyObject *args) +{ + /* Parse the input tuple */ + char *argstring; + long int custom_logging_func_memaddr; + long int store_memaddr; - /* - * TODO - * return the return_error_string as well! - */ - return return_string; + + if(!PyArg_ParseTuple(args, "sll", &argstring, &custom_logging_func_memaddr, &store_memaddr)) + { + return NULL; } + + char * buffer; + char * error_buffer; + size_t nbytes; + int out MAYBE_UNUSED = run_population(argstring, + custom_logging_func_memaddr, + store_memaddr, + &buffer, + &error_buffer, + &nbytes); + + /* copy the buffer to a python string */ + PyObject * return_string = Py_BuildValue("s", buffer); + PyObject * return_error_string MAYBE_UNUSED = Py_BuildValue("s", error_buffer); + + if(error_buffer != NULL && strlen(error_buffer)>0) + { + fprintf(stderr, + "Error in binary_c run : %s\n", + error_buffer); + } + + Safe_free(buffer); + Safe_free(error_buffer); + + /* + * TODO + * return the return_error_string as well! + */ + return return_string; } -/* Wrappers to functions that call other API functionality like help and arglines*/ + +/* ============================================================================== */ +/* Wrappers to functions that call other API functionality like help and arglines */ +/* ============================================================================== */ static PyObject* binary_c_return_arglines(PyObject *self, PyObject *args) { @@ -409,15 +470,6 @@ static PyObject* binary_c_return_help_info(PyObject *self, PyObject *args) static PyObject* binary_c_return_help_all_info(PyObject *self, PyObject *args) { - /* Parse the input tuple */ - // char *argstring; - - // if(!PyArg_ParseTuple(args, "s", &argstring)) - // { - // return NULL; - // } - // else - // { char * buffer; char * error_buffer; size_t nbytes; @@ -440,5 +492,75 @@ static PyObject* binary_c_return_help_all_info(PyObject *self, PyObject *args) Safe_free(error_buffer); return return_string; - // } +} + +static PyObject* binary_c_return_version_info(PyObject *self, PyObject *args) +{ + char * buffer; + char * error_buffer; + size_t nbytes; + int out MAYBE_UNUSED = return_version_info(&buffer, + &error_buffer, + &nbytes); + + /* copy the buffer to a python string */ + PyObject * return_string = Py_BuildValue("s", buffer); + PyObject * return_error_string MAYBE_UNUSED = Py_BuildValue("s", error_buffer); + + if(error_buffer != NULL && strlen(error_buffer)>0) + { + fprintf(stderr, + "Error in binary_c run : %s\n", + error_buffer); + } + + Safe_free(buffer); + Safe_free(error_buffer); + + return return_string; +} + +/* ============================================================================== */ +/* Wrappers to functions that call other functionality */ +/* ============================================================================== */ + +static PyObject* binary_c_return_store(PyObject *self, PyObject *args) +{ + /* Parse the input tuple */ + char *argstring; + + if(!PyArg_ParseTuple(args, "s", &argstring)) + { + return NULL; + } + + char * buffer; + char * error_buffer; + size_t nbytes; + long int out MAYBE_UNUSED = return_store(argstring, + &buffer, + &error_buffer, + &nbytes); + + /* copy the buffer to a python string */ + PyObject * return_string = Py_BuildValue("s", buffer); + PyObject * return_error_string MAYBE_UNUSED = Py_BuildValue("s", error_buffer); + + PyObject * return_store_memaddr = Py_BuildValue("l", out); + + if(error_buffer != NULL && strlen(error_buffer)>0) + { + fprintf(stderr, + "Error in binary_c run : %s\n", + error_buffer); + } + + Safe_free(buffer); + Safe_free(error_buffer); + + /* + * TODO + * return the return_error_string as well! + */ + return return_store_memaddr; } \ No newline at end of file diff --git a/src/binary_c_python_api.c b/src/binary_c_python_api.c index 10ab6147a27f35286c4c795f70b9aa3345cb51ab..e8922c589214df74c3d917389eebb027eacb62d7 100644 --- a/src/binary_c_python_api.c +++ b/src/binary_c_python_api.c @@ -48,19 +48,29 @@ int stdoutwas; /* Below are the real calls to the API of binary_c. Currently these are the functions: +// evolution run_binary run_binary_custom_logging -return_arglines run_binary_with_logfile +run_population + + +// utility +return_arglines return_help_info return_help_all_info +return_version_info +// other +create_store */ +/* =================================================================== */ +/* Functions to evolve systems */ +/* =================================================================== */ -/* Functions to evolve binary systems */ int run_binary(char * argstring, char ** const buffer, @@ -96,7 +106,7 @@ int run_binary(char * argstring, /* do binary evolution */ binary_c_evolve_for_dt(stardata, stardata->model.max_evolution_time); - + /* get buffer pointer */ binary_c_buffer_info(stardata,buffer,nbytes); @@ -114,7 +124,7 @@ int run_binary(char * argstring, } int run_binary_custom_logging(char * argstring, - long int func_memaddr, + long int custom_logging_func_memaddr, char ** const buffer, char ** const error_buffer, size_t * const nbytes) @@ -144,7 +154,7 @@ int run_binary_custom_logging(char * argstring, /* output to strings */ stardata->preferences->internal_buffering = INTERNAL_BUFFERING_STORE; stardata->preferences->batchmode = BATCHMODE_LIBRARY; - stardata->preferences->custom_output_function = (void*)(struct stardata_t *)func_memaddr; + stardata->preferences->custom_output_function = (void*)(struct stardata_t *)custom_logging_func_memaddr; /* do binary evolution */ binary_c_evolve_for_dt(stardata, @@ -207,7 +217,69 @@ int run_binary_with_logfile(char * argstring, return 0; } -/* Functions to call other API functionality like help and arglines */ +int run_population(char * argstring, + long int custom_logging_func_memaddr, + long int store_memaddr, + char ** const buffer, + char ** const error_buffer, + size_t * const nbytes) +{ + /* memory for N binary systems */ + struct libbinary_c_stardata_t *stardata; + + // load the store + // struct libbinary_c_store_t * store = (void*)store_memaddr; + struct libbinary_c_store_t * store = NULL; + + /* make new stardata */ + stardata = NULL; + binary_c_new_system(&stardata, + NULL, + NULL, + &store, + &argstring, + -1); + + /* disable logging */ + snprintf(stardata->preferences->log_filename, + STRING_LENGTH-1, + "%s", + "/dev/null"); + snprintf(stardata->preferences->api_log_filename_prefix, + STRING_LENGTH-1, + "%s", + "/dev/null"); + + /* output to strings */ + stardata->preferences->internal_buffering = INTERNAL_BUFFERING_STORE; + stardata->preferences->batchmode = BATCHMODE_LIBRARY; + stardata->preferences->custom_output_function = (void*)(struct stardata_t *)custom_logging_func_memaddr; + + /* do binary evolution */ + binary_c_evolve_for_dt(stardata, + stardata->model.max_evolution_time); + + /* get buffer pointer */ + binary_c_buffer_info(stardata,buffer,nbytes); + + /* get error buffer pointer */ + binary_c_error_buffer(stardata,error_buffer); + + /* set raw_buffer_size = -1 to prevent it being freed */ + stardata->tmpstore->raw_buffer_size = -1; + + /* free stardata (except the buffer) */ + binary_c_free_memory(&stardata,TRUE,TRUE,FALSE,FALSE); + + // Ask rob whether to free the memory here or not? or to free it manually. + + return 0; +} + +/* =================================================================== */ +/* Functions to call other API functionality like help and arglines */ +/* =================================================================== */ + int return_arglines(char ** const buffer, char ** const error_buffer, size_t * const nbytes) @@ -338,4 +410,87 @@ int return_help_all_info(char ** const buffer, binary_c_free_memory(&stardata,TRUE,TRUE,FALSE,FALSE); binary_c_free_store_contents(store); return 0; +} + +int return_version_info(char ** const buffer, + char ** const error_buffer, + size_t * const nbytes) +{ + /* memory for N binary systems */ + struct libbinary_c_stardata_t *stardata; + struct libbinary_c_store_t * store = NULL; + + /* make new stardata */ + stardata = NULL; + char * empty_str = ""; + binary_c_new_system(&stardata, + NULL, + NULL, + &store, + &empty_str, + -1); + + /* output to strings */ + stardata->preferences->internal_buffering = INTERNAL_BUFFERING_STORE; + stardata->preferences->batchmode = BATCHMODE_LIBRARY; + + /* Ask the help api */ + binary_c_version(stardata); + + /* get buffer pointer */ + binary_c_buffer_info(stardata,buffer,nbytes); + + /* get error buffer pointer */ + binary_c_error_buffer(stardata,error_buffer); + + /* set raw_buffer_size = -1 to prevent it being freed */ + stardata->tmpstore->raw_buffer_size = -1; + + /* free stardata (except the buffer) */ + binary_c_free_memory(&stardata,TRUE,TRUE,FALSE,FALSE); + binary_c_free_store_contents(store); + return 0; +} + +/* =================================================================== */ +/* Functions to call other functionality */ +/* =================================================================== */ + + +long int return_store(char * argstring, + char ** const buffer, + char ** const error_buffer, + size_t * const nbytes) +{ + /* memory for N binary systems */ + struct libbinary_c_stardata_t *stardata; + struct libbinary_c_store_t * store = NULL; + + /* make new stardata */ + stardata = NULL; + binary_c_new_system(&stardata, + NULL, + NULL, + &store, + &argstring, + -1); + + /* output to strings */ + // stardata->preferences->internal_buffering = INTERNAL_BUFFERING_STORE; + // stardata->preferences->batchmode = BATCHMODE_LIBRARY; + + /* get buffer pointer */ + binary_c_buffer_info(stardata, buffer, nbytes); + + /* get error buffer pointer */ + binary_c_error_buffer(stardata, error_buffer); + + /* set raw_buffer_size = -1 to prevent it being freed */ + stardata->tmpstore->raw_buffer_size = -1; + + /* free stardata (except the buffer) */ + binary_c_free_memory(&stardata, TRUE, TRUE, FALSE, FALSE); + + // binary_c_free_store_contents(store); + return store; } \ No newline at end of file diff --git a/tests/population/grid_tests.py b/tests/population/grid_tests.py new file mode 100644 index 0000000000000000000000000000000000000000..a8d8ec1e8ce718598644900338c7cbbc7beb56bd --- /dev/null +++ b/tests/population/grid_tests.py @@ -0,0 +1,61 @@ +import os +import json + +from binarycpython.utils.grid import Population +from binarycpython.utils.functions import get_help_all, get_help + + +test_pop = Population() + +## Setting values +# print(test_pop.bse_options['M_1']) +# print(test_pop.bse_options['M_2']) +# test_pop.set(M_1=10, M_2=500) +# print(test_pop.bse_options['M_1']) +# print(test_pop.bse_options['M_2']) +test_pop.set(M_1=10, separation=0, orbital_period=4580, max_evolution_time=15000, eccentricity=0.02, ) +# print(test_pop.bse_options) + +## Testing single evolution +# test_pop.evolve_single() +# test_pop.test_evolve_single() + +## Setting custom value +# test_pop.set(data_dir=os.path.join(os.environ['BINARYC_DATA_ROOT'], 'development_example')) +# print(test_pop.custom_options['data_dir']) + +## printing all options +# print(json.dumps(test_pop.return_population_settings(), indent=4)) + +## return arglines: +# test_pop.set(M_1=10, M_2=500) +# print(test_pop.return_argline()) +# test_pop.return_argline() + +## return version info +# version_info = test_pop.return_binary_c_version_info() +# print(version_info) + +## Use custom arg file +# test_pop.evolve_population(custom_arg_file='/home/david/projects/binary_c_root/binary_c-python/tests/population/custom_arg_file.txt') + +## Custom logging: +# test_pop.set(C_auto_logging={'MY_HEADER_LINE': ['star[0].mass', 'star[1].mass', 'model.probability']}) +# test_pop.set(C_logging_code='Printf("MY_STELLAR_DATA time=%g mass=%g\\n", stardata->model.time, stardata->star[0].mass);') +# test_pop.set(C_logging_code='Printf("MY_HEADER_LINE %g %g %g\\n",((double)stardata->star[0].mass),((double)stardata->star[1].mass),((double)stardata->model.probability));') + +# test_pop.evolve_population() + +## Help all +# print(get_help_all(return_dict=True)) + +# get_help_all() +# print(get_help('M_1', print_help=False, return_dict=True)) + + +# return all info: +# print(json.dumps(test_pop.return_all_info(), indent=4)) +test_pop.export_all_info(outfile=os.path.join(os.getcwd(), 'test_output.txt')) + + + diff --git a/tests/python_API_test.py b/tests/python_API_test.py index cc373d2a47be50c6583b7a521204c0ad372abf61..8d295b57f2e595830749d0832e2b48dad7e1f2f7 100755 --- a/tests/python_API_test.py +++ b/tests/python_API_test.py @@ -121,6 +121,15 @@ def test_return_help_all(): out = binary_c_python_api.return_help_all("M_1") print(out) +def test_return_version_info(): + out = binary_c_python_api.return_version_info() + print(out) + + +def test_return_store(): + out = binary_c_python_api.return_store("binary_c M_1 10") + print(out) + #### if __name__ == "__main__": @@ -135,3 +144,7 @@ if __name__ == "__main__": test_return_arglines() test_return_help_all() + + test_return_version_info() + + test_return_store()