diff --git a/binarycpython/utils/custom_logging_functions.py b/binarycpython/utils/custom_logging_functions.py index 12af7c84b73eb751501110de17f500cab21923d5..4d8ee5f7595ebf972c53f0dd01f9726ccfa64548 100644 --- a/binarycpython/utils/custom_logging_functions.py +++ b/binarycpython/utils/custom_logging_functions.py @@ -2,11 +2,11 @@ import os import textwrap import subprocess import socket -import tempfile import ctypes import random import uuid +from binarycpython.utils.functions import temp_dir def autogen_C_logging_code(logging_dict, verbose=0): """ @@ -66,7 +66,7 @@ def autogen_C_logging_code(logging_dict, verbose=0): #################################################################################### -def binary_c_log_code(code, verbose): +def binary_c_log_code(code, verbose=0): """ Function to construct the code to construct the custom logging function """ @@ -292,23 +292,7 @@ def compile_shared_lib(code, sourcefile_name, outfile_name, verbose=0): print("Output of compilation command:\n{}".format(res)) -def temp_dir(): - """ - Function to return the path the custom logging library shared object and script will be written to. - - Makes use of os.makedirs exist_ok which requires python 3.2+ - """ - - tmp_dir = tempfile.gettempdir() - path = os.path.join(tmp_dir, "binary_c_python") - - # - os.makedirs(path, exist_ok=True) - - return path - - -def create_and_load_logging_function(custom_logging_code, verbose): +def create_and_load_logging_function(custom_logging_code, verbose=0): """ Function to automatically compile the shared library with the given custom logging code and load it with ctypes diff --git a/binarycpython/utils/functions.py b/binarycpython/utils/functions.py index 688ee8c447effe7ce24eb9772e7c5705b04a738b..dcdc4ffe796a7628cdd5381cb48008712e44e27d 100644 --- a/binarycpython/utils/functions.py +++ b/binarycpython/utils/functions.py @@ -2,13 +2,31 @@ import copy import json import os import h5py +import tempfile + from collections import defaultdict import numpy as np import binary_c_python_api -from binarycpython.utils.custom_logging_functions import ( - create_and_load_logging_function, -) + +# from binarycpython.utils.custom_logging_functions import ( +# create_and_load_logging_function, +# ) + +def temp_dir(): + """ + Function to return the path the custom logging library shared object and script will be written to. + + Makes use of os.makedirs exist_ok which requires python 3.2+ + """ + + tmp_dir = tempfile.gettempdir() + path = os.path.join(tmp_dir, "binary_c_python") + + # + os.makedirs(path, exist_ok=True) + + return path def output_lines(output): @@ -478,99 +496,6 @@ def get_help(param_name="", print_help=True, return_dict=False, fail_silently=Fa ) return None - -def run_system(**kwargs): - """ - Wrapper to run a system with settings - - This function determines which underlying python-c api function will be called based upon the arguments that are passed via kwargs. - - - if custom_logging_code or custom_logging_dict is included in the kwargs then it will - - if - - """ - - # Load default args - args = get_defaults() - if "custom_logging_code" in kwargs: - # Use kwarg value to override defaults and add new args - for key in kwargs.keys(): - if not key == "custom_logging_code": - args[key] = kwargs[key] - - # Generate library and get memaddr - func_memaddr = create_and_load_logging_function(kwargs["custom_logging_code"]) - - # Construct arguments string and final execution string - arg_string = create_arg_string(args) - arg_string = "binary_c {}".format(arg_string) - - # Run it and get output - output = binary_c_python_api.run_binary_custom_logging(arg_string, func_memaddr) - return output - - elif "log_filename" in kwargs: - # Use kwarg value to override defaults and add new args - for key in kwargs.keys(): - args[key] = kwargs[key] - - # Construct arguments string and final execution string - arg_string = create_arg_string(args) - arg_string = "binary_c {}".format(arg_string) - - # Run it and get output - output = binary_c_python_api.run_binary_with_logfile(arg_string) - return output - - else: # run the plain basic type - - # Use kwarg value to override defaults and add new args - for key in kwargs.keys(): - args[key] = kwargs[key] - - # Construct arguments string and final execution string - arg_string = create_arg_string(args) - arg_string = "binary_c {}".format(arg_string) - - # Run it and get output - output = binary_c_python_api.run_binary(arg_string) - - return output - - -def run_system_with_log(**kwargs): - """ - Wrapper to run a system with settings AND logs the files to a designated place defined by the log_filename parameter. - """ - - # Load default args - args = get_defaults() - # args = {} - - # For example - # physics_args['M_1'] = 20 - # physics_args['separation'] = 0 # 0 = ignored, use period - # physics_args['orbital_period'] = 100000000000 # To make it single - - # Use kwarg value to override defaults and add new args - for key in kwargs.keys(): - args[key] = kwargs[key] - - # Construct arguments string and final execution string - arg_string = create_arg_string(args) - arg_string = "binary_c {}".format(arg_string) - - # print(arg_string) - - # Run it and get output - output = binary_c_python_api.run_binary_with_logfile(arg_string) - - return output - - -# run_system_with_log() - - def parse_output(output, selected_header): """ Function that parses output of binary_c: diff --git a/binarycpython/utils/grid.py b/binarycpython/utils/grid.py index ddba33e741c32da7804fe9193aa8c32e0b9eb870..6501ca2cda39b41f1c2996c4e54c5e4aa5d1770f 100644 --- a/binarycpython/utils/grid.py +++ b/binarycpython/utils/grid.py @@ -513,10 +513,11 @@ class Population(object): Function that the multiprocessing evolution method calls to evolve a system """ - out = binary_c_python_api.run_population( - binary_cmdline_string, + out = binary_c_python_api.run_system( + arg_string=binary_cmdline_string, self.grid_options["custom_logging_func_memaddr"], self.grid_options["store_memaddr"], + ) if self.grid_options["parse_function"]: self.grid_options["parse_function"](self, out) diff --git a/binarycpython/utils/run_system_wrapper.py b/binarycpython/utils/run_system_wrapper.py new file mode 100644 index 0000000000000000000000000000000000000000..5de0de40c59c2076e3f3b30792f7d5f290e8b5ef --- /dev/null +++ b/binarycpython/utils/run_system_wrapper.py @@ -0,0 +1,87 @@ +def run_system(**kwargs): + """ + Wrapper to run a system with settings + + This function determines which underlying python-c api function will be called based upon the arguments that are passed via kwargs. + + - if custom_logging_code or custom_logging_dict is included in the kwargs then it will + - if + + """ + + # Load default args + args = get_defaults() + if "custom_logging_code" in kwargs: + # Use kwarg value to override defaults and add new args + for key in kwargs.keys(): + if not key == "custom_logging_code": + args[key] = kwargs[key] + + # Generate library and get memaddr + func_memaddr = create_and_load_logging_function(kwargs["custom_logging_code"]) + + # Construct arguments string and final execution string + arg_string = create_arg_string(args) + arg_string = "binary_c {}".format(arg_string) + + # Run it and get output + output = binary_c_python_api.run_binary_custom_logging(arg_string, func_memaddr) + return output + + elif "log_filename" in kwargs: + # Use kwarg value to override defaults and add new args + for key in kwargs.keys(): + args[key] = kwargs[key] + + # Construct arguments string and final execution string + arg_string = create_arg_string(args) + arg_string = "binary_c {}".format(arg_string) + + # Run it and get output + output = binary_c_python_api.run_binary_with_logfile(arg_string) + return output + + else: # run the plain basic type + + # Use kwarg value to override defaults and add new args + for key in kwargs.keys(): + args[key] = kwargs[key] + + # Construct arguments string and final execution string + arg_string = create_arg_string(args) + arg_string = "binary_c {}".format(arg_string) + + # Run it and get output + output = binary_c_python_api.run_binary(arg_string) + + return output + + +def run_system_with_log(**kwargs): + """ + Wrapper to run a system with settings AND logs the files to a designated place defined by the log_filename parameter. + """ + + # Load default args + args = get_defaults() + # args = {} + + # For example + # physics_args['M_1'] = 20 + # physics_args['separation'] = 0 # 0 = ignored, use period + # physics_args['orbital_period'] = 100000000000 # To make it single + + # Use kwarg value to override defaults and add new args + for key in kwargs.keys(): + args[key] = kwargs[key] + + # Construct arguments string and final execution string + arg_string = create_arg_string(args) + arg_string = "binary_c {}".format(arg_string) + + # print(arg_string) + + # Run it and get output + output = binary_c_python_api.run_binary_with_logfile(arg_string) + + return output diff --git a/include/binary_c_python.h b/include/binary_c_python.h index ee7544c26bcefd875e8018fc0e9b345b6a914add..9c65d76767755485bdcdf78fff31b9b7df60ad72 100644 --- a/include/binary_c_python.h +++ b/include/binary_c_python.h @@ -9,32 +9,11 @@ #include "binary_c_API_prototypes.h" /* Binary_c's python API prototypes */ -int run_binary(char * argstring, - char ** const outstring, - char ** const errorstring, - size_t * const nbytes); - -int run_binary_with_logfile(char * argstring, - char ** const outstring, - char ** const errorstring, - size_t * const nbytes); - -int run_binary_custom_logging(char * argstring, - 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); - int run_system(char * argstring, long int custom_logging_func_memaddr, long int store_memaddr, + int write_logfile, + int population, char ** const buffer, char ** const error_buffer, size_t * const nbytes); diff --git a/src/binary_c_python.c b/src/binary_c_python.c index 49fb8dbf7824501b1234e610ed37b5f8d7cd2882..3b7e913280034546644226d9ac0ad78552ef2412 100644 --- a/src/binary_c_python.c +++ b/src/binary_c_python.c @@ -11,6 +11,11 @@ * * See also * http://www-h.eng.cam.ac.uk/help/tpl/languages/mixinglanguages.html + * https://realpython.com/build-python-c-extension-module/ + * https://docs.python.org/3/extending/extending.html + * https://docs.python.org/3/c-api/arg.html#c.PyArg_ParseTuple + * https://realpython.com/python-bindings-overview/ + * http://scipy-lectures.org/advanced/interfacing_with_c/interfacing_with_c.html */ /* list of variables used in the Py<>C interface */ @@ -22,9 +27,12 @@ */ /************************************************************/ +/* Preparing all the functions of the module */ // Docstrings static char module_docstring[] MAYBE_UNUSED = "This module is a python wrapper around binary_c"; + + #ifdef __DEPRECATED static char create_binary_docstring[] = "Allocate memory for a binary"; @@ -35,16 +43,8 @@ static char new_binary_system_docstring[] = "Return an object containing a binary, ready for evolution"; // Evolution function docstrings -static char run_binary_docstring[] = - "Run one binary using binary_c"; -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_logging_docstring[] = - "TODO"; -static char run_population_docstring[] = - "Run population of systems"; static char run_system_docstring[] = - "Function to run a system. This is a general function that will be able to handle different kinds of situations: single system run with different settings, population run with different settings, etc. To avoid having too many functions doing slightly different things."; + "Function to run a system. This is a general function that will be able to handle different kinds of situations: single system run with different settings, population run with different settings, etc. To avoid having too many functions doing slightly different things. \n\nArguments:\n\targstring: argument string for binary_c\n\t(opt) custom_logging_func_memaddr: memory address value for custom logging function. Default = -1 (None)\n\t(opt) store_memaddr: memory adress of the store. Default = -1 (None)\n\t(opt) write_logfile: Boolean (in int form) for whether to enable the writing of the log function. Default = 0\n\t(opt) population: Boolean (in int form) for whether this system is part of a population run. Default = 0."; // Utility function docstrings static char return_arglines_docstring[] = @@ -60,10 +60,10 @@ static char return_version_info_docstring[] = 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; -static struct libbinary_c_store_t *store = NULL; - -// Initialize pyobjects +/* Initialize pyobjects */ +// #ifdef __DEPRECATED static PyObject* binary_c_create_binary(PyObject *self, PyObject *args); #endif @@ -71,11 +71,7 @@ static PyObject* binary_c_function_prototype(PyObject *self, PyObject *args); static PyObject* binary_c_new_binary_system(PyObject *self, PyObject *args); // Evolution function headers -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); -static PyObject* binary_c_run_system(PyObject *self, PyObject *args); +static PyObject* binary_c_run_system(PyObject *self, PyObject *args, PyObject *kwargs); // Utility function headers static PyObject* binary_c_return_arglines(PyObject *self, PyObject *args); @@ -86,13 +82,8 @@ 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 - * - * http://scipy-lectures.org/advanced/interfacing_with_c/interfacing_with_c.html - */ - +/* Set the module functions */ static PyMethodDef module_methods[] = { #ifdef __DEPRECATED {"create_binary", @@ -104,13 +95,8 @@ static PyMethodDef module_methods[] = { {"function_prototype", binary_c_function_prototype, METH_VARARGS, function_prototype_docstring}, {"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_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}, - {"run_system", binary_c_run_system, METH_VARARGS, run_system_docstring}, - - + {"run_system", (PyCFunction)binary_c_run_system, METH_VARARGS|METH_KEYWORDS, run_system_docstring}, + // Wierdly, this casting to a PyCFunction, which usually takes only 2 args, now works when giving keywords. See https://stackoverflow.com/q/10264080 {"return_arglines", binary_c_return_arglines, METH_VARARGS, return_arglines_docstring}, {"return_help", binary_c_return_help_info, METH_VARARGS, return_help_info_docstring}, @@ -122,6 +108,13 @@ static PyMethodDef module_methods[] = { {NULL, NULL, 0, NULL} }; +/* ============================================================================== */ +/* Making the module */ +/* ============================================================================== */ + + +/* */ +// TODO: enforce python3 #if PY_MAJOR_VERSION >= 3 /* Python 3+ */ @@ -155,6 +148,11 @@ PyMODINIT_FUNC initbinary_c(void) } #endif // Python version check +/* ============================================================================== */ +/* Some wierd function */ +/* ============================================================================== */ + + #ifdef __DEPRECATED static PyObject* binary_c_create_binary(PyObject *self, PyObject *args) @@ -224,11 +222,9 @@ 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 + Below are the real functions: binary_c_run_population + binary_c_run_system binary_c_return_arglines binary_c_return_help_info @@ -240,99 +236,33 @@ static PyObject* binary_c_function_prototype(PyObject *self, PyObject *args) /* Wrappers to functions that evolve binary systems. */ /* ============================================================================== */ - -static PyObject* binary_c_run_binary(PyObject *self, PyObject *args) +static PyObject* binary_c_run_system(PyObject *self, PyObject *args, PyObject *kwargs) { - /* Parse the input tuple */ - char *argstring; - - /* Parse the input tuple */ - if(!PyArg_ParseTuple(args, "s", &argstring)) - - return NULL; - - 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); - /* - * TODO - * return the return_error_string as well! - */ - return return_string; -} + static char* keywords[] = {"argstring", "custom_logging_func_memaddr", "store_memaddr", "write_logfile", "population", NULL}; -static PyObject* binary_c_run_binary_custom_logging(PyObject *self, PyObject *args) -{ - /* Parse the input tuple */ + /* set vars and default values for some*/ char *argstring; - long int func_memaddr; - - if(!PyArg_ParseTuple(args, "sl", &argstring, &func_memaddr)) - { - return NULL; - } - - 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); + long int custom_logging_func_memaddr = -1; + long int store_memaddr = -1; + int write_logfile = 0; + int population = 0; - 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) -{ /* Parse the input tuple */ - char *argstring; - - if(!PyArg_ParseTuple(args, "s", &argstring)) + if(!PyArg_ParseTupleAndKeywords(args, kwargs, "s|llii", keywords, &argstring, &custom_logging_func_memaddr, &store_memaddr, &write_logfile, &population)) { return NULL; } + /* Call c-function */ char * buffer; char * error_buffer; size_t nbytes; - int out MAYBE_UNUSED = run_binary_with_logfile(argstring, + int out MAYBE_UNUSED = run_system(argstring, // the argstring + custom_logging_func_memaddr, // memory adress for the function for custom logging + store_memaddr, // memory adress for the store object + write_logfile, // boolean for whether to write the logfile + population, // boolean for whether this is part of a population. &buffer, &error_buffer, &nbytes); @@ -341,10 +271,11 @@ static PyObject* binary_c_run_binary_with_logfile(PyObject *self, PyObject *args PyObject * return_string = Py_BuildValue("s", buffer); PyObject * return_error_string MAYBE_UNUSED = Py_BuildValue("s", error_buffer); + /* Display error */ if(error_buffer != NULL && strlen(error_buffer)>0) { fprintf(stderr, - "Error in binary_c run : %s\n", + "Error in binary_c run (via binary_c_run_system): %s\n", error_buffer); } @@ -358,95 +289,6 @@ static PyObject* binary_c_run_binary_with_logfile(PyObject *self, PyObject *args return return_string; } -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; - - - 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; -} - -static PyObject* binary_c_run_system(PyObject *self, PyObject *args) -{ - /* Parse the input tuple */ - char *argstring; - long int custom_logging_func_memaddr; - long int store_memaddr; - - 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_system(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 */ /* ============================================================================== */ @@ -593,7 +435,7 @@ static PyObject* binary_c_return_store(PyObject *self, PyObject *args) &nbytes); /* copy the buffer to a python string */ - PyObject * return_string = Py_BuildValue("s", buffer); + PyObject * return_string MAYBE_UNUSED = Py_BuildValue("s", buffer); PyObject * return_error_string MAYBE_UNUSED = Py_BuildValue("s", error_buffer); PyObject * return_store_memaddr = Py_BuildValue("l", out); diff --git a/src/binary_c_python_api.c b/src/binary_c_python_api.c index 68be4e74c8e83f7737f0ab1fd1f6ed06d968ada8..01fc7438e33d0641b96efe35db28a91463abccec 100644 --- a/src/binary_c_python_api.c +++ b/src/binary_c_python_api.c @@ -7,34 +7,24 @@ #include <unistd.h> #include <stdint.h> - - -/* - * apitest - * - * Short test programme to throw random binary systems at binary_c's - * library via its API. - * - * Note that it looks more complicated than it is because I have included - * code to capture binary_c's stdout stream and output it here. - * - * This code sends output to stderr : you should use apitest.sh to run it - * and hence force output to your terminal's stdout. - * - * Output lines: - * - * APITEST .... is information about what this code is doing. - * STATUS .... is information about the binary system. - * BINARY_C .... is output from binary_c (see iterate_logging.c etc.) - * which would have gone to stdout - * - * If you define the NO_OUTPUT macro, there will be no output except - * the memory allocation and test system information. This is useful for speed tests, - * but note that you may end up in a race condition where the pipe which replaces - * stdout's buffer fills and hence the code stops. +/* Binary_c python API + * Set of c-functions that interface with the binary_c api. + * These functions are called by python, first through binary_c_python.c, + * and there further instructions are given on how to interface + * + * Contains several functions: + * // evolution + * run_system + + * // utility + * return_arglines + * return_help_info + * return_help_all_info + * return_version_info + + * // other + * create_store * - * Note: - * I have tested this with gcc 4.7.2 (Ubuntu 12.10) only. */ // #define _CAPTURE @@ -47,250 +37,23 @@ static void capture_stdout(void); int out_pipe[2]; 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 -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 */ /* =================================================================== */ - -int run_binary(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); - - /* 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; - - /* 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); - binary_c_free_store_contents(store); - - return 0; -} - -int run_binary_custom_logging(char * argstring, - long int custom_logging_func_memaddr, - 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); - - /* 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); - binary_c_free_store_contents(store); - - return 0; -} - -int run_binary_with_logfile(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; - - /* 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); - binary_c_free_store_contents(store); - return 0; -} - -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 from the integer that has been passed - struct libbinary_c_store_t * store = (void*)store_memaddr; - - /* 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; - - /* Check the value of the custom_logging_memaddr */ - if(custom_logging_func_memaddr != -1) - { - 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); - - // TODO: Ask rob whether to free the memory here or not? or to free it manually. - return 0; -} - - -// This one will replace the different ones above. needs to handle multiple input choices and decide what to do. +/* Function that runs a system. Has multiple input parameters: +Big function. Takes several arguments. See binary_c_python.c docstring. +*/ int run_system(char * argstring, long int custom_logging_func_memaddr, long int store_memaddr, + int write_logfile, + int population, char ** const buffer, char ** const error_buffer, size_t * const nbytes) { - /* memory for N binary systems */ + /* memory for system */ struct libbinary_c_stardata_t *stardata; // Store: @@ -317,15 +80,19 @@ int run_system(char * argstring, &argstring, -1); + // Add flag to enable /* 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"); + if(write_logfile != 1) + { + 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; @@ -352,12 +119,17 @@ int run_system(char * argstring, /* free stardata (except the buffer) */ binary_c_free_memory(&stardata,TRUE,TRUE,FALSE,FALSE); // CHeck if this is good for single runs.. TODO: - + + // add flag or logic to free store contents. + if (store_memaddr == -1) + { + binary_c_free_store_contents(store); + } + // TODO: 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 */ /* =================================================================== */ @@ -454,6 +226,7 @@ int return_help_info(char * argstring, return 0; } + int return_help_all_info(char ** const buffer, char ** const error_buffer, size_t * const nbytes) @@ -494,6 +267,7 @@ int return_help_all_info(char ** const buffer, return 0; } + int return_version_info(char ** const buffer, char ** const error_buffer, size_t * const nbytes) @@ -538,7 +312,6 @@ int return_version_info(char ** const buffer, /* Functions to call other functionality */ /* =================================================================== */ - long int return_store(char * argstring, char ** const buffer, char ** const error_buffer, diff --git a/tests/python_API_test.py b/tests/python_API_test.py index 8e05cd65e3be02d03348ec786847e2cb346e57c4..e70f0ed8fe50bef66dcf995e5366eea8d58bbd25 100755 --- a/tests/python_API_test.py +++ b/tests/python_API_test.py @@ -7,15 +7,22 @@ from binarycpython.utils.custom_logging_functions import ( binary_c_log_code, create_and_load_logging_function, ) +from binarycpython.utils.functions import ( + temp_dir, +) import tempfile ############################################################ # Test script for the api functions +# TODO: Add asserts to these functions and use em as +# unittests ############################################################ -def test_run_binary(): +# Evolution functionality + +def test_run_system(): m1 = 15.0 # Msun m2 = 14.0 # Msun separation = 0 # 0 = ignored, use period @@ -33,23 +40,12 @@ def test_run_binary(): max_evolution_time, ) - output = binary_c_python_api.run_binary(argstring) + output = binary_c_python_api.run_system(argstring=argstring) print("\n\nBinary_c output:") print(output) - -def test_return_help(): - out = binary_c_python_api.return_help("M_1") - print(out) - - -def test_return_arglines(): - out = binary_c_python_api.return_arglines() - print(out) - - -def test_run_binary_with_log(): +def test_run_system_with_log(): m1 = 15.0 # Msun m2 = 14.0 # Msun separation = 0 # 0 = ignored, use period @@ -58,8 +54,8 @@ def test_run_binary_with_log(): metallicity = 0.02 max_evolution_time = 15000 - log_filename = tempfile.gettempdir() + "/test_log.txt" - api_log_filename_prefix = tempfile.gettempdir() + "/test_log" + log_filename = temp_dir() + "/test_log.txt" + api_log_filename_prefix = temp_dir() + "/test_log" argstring = "binary_c M_1 {0:g} M_2 {1:g} separation {2:g} orbital_period {3:g} eccentricity {4:g} metallicity {5:g} max_evolution_time {6:g} log_filename {7:s} api_log_filename_prefix {8:s}".format( m1, @@ -73,12 +69,12 @@ def test_run_binary_with_log(): api_log_filename_prefix, ) - output = binary_c_python_api.run_binary_with_logfile(argstring) + output = binary_c_python_api.run_system(argstring=argstring, write_logfile=1) + print("\n\nBinary_c output:") print(output) - -def test_run_binary_with_custom_logging(): +def test_run_system_with_custom_logging(): """ """ @@ -92,8 +88,9 @@ def test_run_binary_with_custom_logging(): custom_logging_code = binary_c_log_code(logging_line) # Load memory adress - func_memaddr = create_and_load_logging_function(custom_logging_code) + func_memaddr, shared_lib_filename = create_and_load_logging_function(custom_logging_code) + # Some values m1 = 15.0 # Msun m2 = 14.0 # Msun separation = 0 # 0 = ignored, use period @@ -101,8 +98,8 @@ def test_run_binary_with_custom_logging(): eccentricity = 0.0 metallicity = 0.02 max_evolution_time = 15000 - log_filename = tempfile.gettempdir() + "/test_log.txt" - argstring = "binary_c M_1 {0:g} M_2 {1:g} separation {2:g} orbital_period {3:g} eccentricity {4:g} metallicity {5:g} max_evolution_time {6:g} log_filename {7:s}".format( + + argstring = "binary_c M_1 {0:g} M_2 {1:g} separation {2:g} orbital_period {3:g} eccentricity {4:g} metallicity {5:g} max_evolution_time {6:g}".format( m1, m2, separation, @@ -110,12 +107,23 @@ def test_run_binary_with_custom_logging(): eccentricity, metallicity, max_evolution_time, - log_filename, ) - out = binary_c_python_api.run_binary_custom_logging(argstring, func_memaddr) + print(func_memaddr) + + out = binary_c_python_api.run_system(argstring, custom_logging_func_memaddr=func_memaddr) print(out) +# Testing other utility functions + +def test_return_help(): + out = binary_c_python_api.return_help("M_1") + print(out) + + +def test_return_arglines(): + out = binary_c_python_api.return_arglines() + print(out) def test_return_help_all(): out = binary_c_python_api.return_help_all("M_1") @@ -126,52 +134,27 @@ def test_return_version_info(): out = binary_c_python_api.return_version_info() print(out) +# Testing other functions def test_return_store(): out = binary_c_python_api.return_store("") print(out) - -def test_run_system(): - - m1 = 15.0 # Msun - m2 = 14.0 # Msun - separation = 0 # 0 = ignored, use period - orbital_period = 4530.0 # days - eccentricity = 0.0 - metallicity = 0.02 - max_evolution_time = 15000 - log_filename = tempfile.gettempdir() + "/test_log.txt" - argstring = "binary_c M_1 {0:g} M_2 {1:g} separation {2:g} orbital_period {3:g} eccentricity {4:g} metallicity {5:g} max_evolution_time {6:g}".format( - m1, - m2, - separation, - orbital_period, - eccentricity, - metallicity, - max_evolution_time, - log_filename, - ) - out = binary_c_python_api.run_system(argstring, -1, -1) - print(out) - - #### if __name__ == "__main__": - # test_run_binary() + test_run_system() - # test_run_binary_with_log() + test_run_system_with_log() - # test_run_binary_with_custom_logging() + test_run_system_with_custom_logging() - # test_return_help() + test_return_help() - # test_return_arglines() + test_return_arglines() - # test_return_help_all() + test_return_help_all() - # test_return_version_info() + test_return_version_info() - # test_return_store() + test_return_store() - test_run_system()