Loading binaryc_python_utils/custom_logging_functions.py +105 −81 Original line number Diff line number Diff line Loading @@ -27,7 +27,7 @@ def autogen_C_logging_code(logging_dict): print("Error: please use a dictionary as input") return None code = '' code = "" # Loop over dict keys for key in logging_dict: logging_dict_entry = logging_dict[key] Loading @@ -37,22 +37,25 @@ def autogen_C_logging_code(logging_dict): # Construct print statement code += 'Printf("{}'.format(key) code += ' {}'.format('%g '*len(logging_dict_entry)) code += " {}".format("%g " * len(logging_dict_entry)) code = code.strip() code += '\\n"' # Add format keys for param in logging_dict_entry: code += ',((double)stardata->{})'.format(param) code += ');\n' code += ",((double)stardata->{})".format(param) code += ");\n" else: print('Error: please use a list for the list of parameters that you want to have logged') print( "Error: please use a list for the list of parameters that you want to have logged" ) code = code.strip() # print("MADE AUTO CODE\n\n{}\n\n{}\n\n{}\n".format('*'*60, repr(code), '*'*60)) return code #################################################################################### def binary_c_log_code(code): """ Loading @@ -77,11 +80,14 @@ void binary_c_API_function custom_output_function(struct stardata_t * stardata) #undef MIN #pragma pop_macro(\"MIN\") #pragma pop_macro(\"MAX\")\ """.format(code) """.format( code ) # print(repr(textwrap.dedent(custom_logging_function_string))) return textwrap.dedent(custom_logging_function_string) def binary_c_write_log_code(code, filename): """ Function to write the generated logging code to a file Loading @@ -96,21 +102,26 @@ def binary_c_write_log_code(code, filename): except: print("Error while deleting file {}".format(filePath)) with open(filePath, 'w') as f: with open(filePath, "w") as f: f.write(code) def from_binary_c_config(config_file, flag): """ Function to run the binaryc_config command with flags """ res = subprocess.check_output('{config_file} {flag}'.format(config_file=config_file, flag=flag), shell=True, stderr=subprocess.STDOUT) res = subprocess.check_output( "{config_file} {flag}".format(config_file=config_file, flag=flag), shell=True, stderr=subprocess.STDOUT, ) # convert and chop off newline res = res.decode('utf').rstrip() res = res.decode("utf").rstrip() return res def return_compilation_dict(): """ Function to build the compile command for the shared library Loading @@ -126,78 +137,88 @@ def return_compilation_dict(): """ # use binary_c-config to get necessary flags BINARY_C_DIR = os.getenv('BINARY_C') BINARY_C_DIR = os.getenv("BINARY_C") if BINARY_C_DIR: BINARY_C_CONFIG = os.path.join(BINARY_C_DIR, 'binary_c-config') BINARY_C_SRC_DIR = os.path.join(BINARY_C_DIR, 'src') BINARY_C_CONFIG = os.path.join(BINARY_C_DIR, "binary_c-config") BINARY_C_SRC_DIR = os.path.join(BINARY_C_DIR, "src") # TODO: build in check to see whether the file exists else: raise NameError('Envvar BINARY_C doesnt exist') raise NameError("Envvar BINARY_C doesnt exist") return None # TODO: make more options for the compiling cc = from_binary_c_config(BINARY_C_CONFIG, 'cc') cc = from_binary_c_config(BINARY_C_CONFIG, "cc") # Check for binary_c BINARY_C_EXE = os.path.join(BINARY_C_DIR, 'binary_c') BINARY_C_EXE = os.path.join(BINARY_C_DIR, "binary_c") if not os.path.isfile(BINARY_C_EXE): print("We require binary_c executable; have you built binary_c?") raise NameError('BINARY_C executable doesnt exist') raise NameError("BINARY_C executable doesnt exist") # TODO: debug libbinary_c = '-lbinary_c' binclibs = from_binary_c_config(BINARY_C_CONFIG, 'libs') libdirs = "{} -L{}".format(from_binary_c_config(BINARY_C_CONFIG, 'libdirs'), BINARY_C_SRC_DIR) bincflags = from_binary_c_config(BINARY_C_CONFIG, 'cflags') bincincdirs = from_binary_c_config(BINARY_C_CONFIG, 'incdirs') libbinary_c = "-lbinary_c" binclibs = from_binary_c_config(BINARY_C_CONFIG, "libs") libdirs = "{} -L{}".format( from_binary_c_config(BINARY_C_CONFIG, "libdirs"), BINARY_C_SRC_DIR ) bincflags = from_binary_c_config(BINARY_C_CONFIG, "cflags") bincincdirs = from_binary_c_config(BINARY_C_CONFIG, "incdirs") # combine binclibs = ' {} {} {}'.format(libdirs, libbinary_c, binclibs) binclibs = " {} {} {}".format(libdirs, libbinary_c, binclibs) # setup defaults: defaults = { 'cc': 'gcc', # default compiler 'ccflags': bincflags, 'ld': 'ld', # 'ld': $Config{ld}, # default linker 'debug': 0, 'inc': '{} -I{}'.format(bincincdirs, BINARY_C_SRC_DIR), "cc": "gcc", # default compiler "ccflags": bincflags, "ld": "ld", # 'ld': $Config{ld}, # default linker "debug": 0, "inc": "{} -I{}".format(bincincdirs, BINARY_C_SRC_DIR), # inc => ' '.($Config{inc}//' ').' '.$bincincdirs." -I$srcdir ", # include the defaults plus # GSL and binary_c # 'libname': libname, # libname is usually just binary_c corresponding to libbinary_c.so 'libs': binclibs, "libs": binclibs, } # set values with defaults. TODO: make other input possile. ld = defaults['ld'] debug = defaults['debug'] inc = defaults['inc'] # = ($ENV{BINARY_GRID2_INC} // $defaults{inc}).' '.($ENV{BINARY_GRID2_EXTRAINC} // ''); libs = defaults['libs'] # = ($ENV{BINARY_GRID2_LIBS} // $defaults{libs}).' '.($ENV{BINARY_GRID2_EXTRALIBS}//''); ccflags = defaults['ccflags'] # = $ENV{BINARY_GRID2_CCFLAGS} // ($defaults{ccflags}) . ($ENV{BINARY_GRID2_EXTRACCFLAGS} // ''); ld = defaults["ld"] debug = defaults["debug"] inc = defaults[ "inc" ] # = ($ENV{BINARY_GRID2_INC} // $defaults{inc}).' '.($ENV{BINARY_GRID2_EXTRAINC} // ''); libs = defaults[ "libs" ] # = ($ENV{BINARY_GRID2_LIBS} // $defaults{libs}).' '.($ENV{BINARY_GRID2_EXTRALIBS}//''); ccflags = defaults[ "ccflags" ] # = $ENV{BINARY_GRID2_CCFLAGS} // ($defaults{ccflags}) . ($ENV{BINARY_GRID2_EXTRACCFLAGS} // ''); # you must define _SEARCH_H to prevent it being loaded twice ccflags += ' -shared -D_SEARCH_H' ccflags += " -shared -D_SEARCH_H" # remove the visibility=hidden for this compilation ccflags = ccflags.replace('-fvisibility=hidden', '') ccflags = ccflags.replace("-fvisibility=hidden", "") # ensure library paths to the front of the libs: libs_content = libs.split(' ') library_paths = [el for el in libs_content if el.startswith('-L')] non_library_paths = [el for el in libs_content if (not el.startswith('-L') and not el=='')] libs = "{} {}".format(' '.join(library_paths), ' '.join(non_library_paths)) print("Building shared library for custom logging with (binary_c.h) at {} on {}\n".format(BINARY_C_SRC_DIR, socket.gethostname())) print("With options:\n\tcc = {cc}\n\tccflags = {ccflags}\n\tld = {ld}\n\tlibs = {libs}\n\tinc = {inc}\n\n".format( cc=cc, ccflags=ccflags, ld=ld, libs=libs, inc=inc) libs_content = libs.split(" ") library_paths = [el for el in libs_content if el.startswith("-L")] non_library_paths = [ el for el in libs_content if (not el.startswith("-L") and not el == "") ] libs = "{} {}".format(" ".join(library_paths), " ".join(non_library_paths)) print( "Building shared library for custom logging with (binary_c.h) at {} on {}\n".format( BINARY_C_SRC_DIR, socket.gethostname() ) ) print( "With options:\n\tcc = {cc}\n\tccflags = {ccflags}\n\tld = {ld}\n\tlibs = {libs}\n\tinc = {inc}\n\n".format( cc=cc, ccflags=ccflags, ld=ld, libs=libs, inc=inc ) ) return { 'cc': cc, 'ld': ld, 'ccflags': ccflags, 'libs': libs, 'inc': inc } return {"cc": cc, "ld": ld, "ccflags": ccflags, "libs": libs, "inc": inc} def compile_shared_lib(code, sourcefile_name, outfile_name): """ Loading @@ -212,23 +233,23 @@ def compile_shared_lib(code, sourcefile_name, outfile_name): # Construct full command command = "{cc} {ccflags} {libs} -o {outfile_name} {sourcefile_name} {inc}".format( cc=compilation_dict['cc'], ccflags=compilation_dict['ccflags'], libs=compilation_dict['libs'], cc=compilation_dict["cc"], ccflags=compilation_dict["ccflags"], libs=compilation_dict["libs"], outfile_name=outfile_name, sourcefile_name=sourcefile_name, inc=compilation_dict['inc']) inc=compilation_dict["inc"], ) # remove extra whitespaces: command = ' '.join(command.split()) command = " ".join(command.split()) # Execute compilation print('Executing following command:\n{command}'.format(command=command)) res = subprocess.check_output('{command}'.format(command=command), shell=True) print("Executing following command:\n{command}".format(command=command)) res = subprocess.check_output("{command}".format(command=command), shell=True) if res: print('Output of compilation command:\n{}'.format(res)) print("Output of compilation command:\n{}".format(res)) def temp_custom_logging_dir(): Loading @@ -239,7 +260,7 @@ def temp_custom_logging_dir(): """ tmp_dir = tempfile.gettempdir() path = os.path.join(tmp_dir, 'binary_c_python') path = os.path.join(tmp_dir, "binary_c_python") # os.makedirs(path, exist_ok=True) Loading @@ -256,17 +277,20 @@ def create_and_load_logging_function(custom_logging_code): """ # compile_shared_lib(custom_logging_code, sourcefile_name=os.path.join(temp_custom_logging_dir(), 'custom_logging.c'), outfile_name=os.path.join(temp_custom_logging_dir(), 'libcustom_logging.so') compile_shared_lib( custom_logging_code, sourcefile_name=os.path.join(temp_custom_logging_dir(), "custom_logging.c"), outfile_name=os.path.join(temp_custom_logging_dir(), "libcustom_logging.so"), ) # Loading library dll1 = ctypes.CDLL('libgslcblas.so', mode=ctypes.RTLD_GLOBAL) dll2 = ctypes.CDLL('libgsl.so', mode=ctypes.RTLD_GLOBAL) dll3 = ctypes.CDLL('libbinary_c.so', mode=ctypes.RTLD_GLOBAL) libmean = ctypes.CDLL(os.path.join(temp_custom_logging_dir(), 'libcustom_logging.so'), mode=ctypes.RTLD_GLOBAL) # loads the shared library dll1 = ctypes.CDLL("libgslcblas.so", mode=ctypes.RTLD_GLOBAL) dll2 = ctypes.CDLL("libgsl.so", mode=ctypes.RTLD_GLOBAL) dll3 = ctypes.CDLL("libbinary_c.so", mode=ctypes.RTLD_GLOBAL) libmean = ctypes.CDLL( os.path.join(temp_custom_logging_dir(), "libcustom_logging.so"), mode=ctypes.RTLD_GLOBAL, ) # loads the shared library # Get memory adress of function. mimicking a pointer func_memaddr = ctypes.cast(libmean.custom_output_function, ctypes.c_void_p).value Loading binaryc_python_utils/functions.py +35 −25 Original line number Diff line number Diff line from collections import defaultdict import binary_c from binaryc_python_utils.custom_logging_functions import create_and_load_logging_function from binaryc_python_utils.custom_logging_functions import ( create_and_load_logging_function, ) def create_arg_string(arg_dict): """ Function that creates the arg string """ arg_string = '' arg_string = "" for key in arg_dict.keys(): arg_string += "{key} {value} ".format(key=key, value=arg_dict[key]) arg_string = arg_string.strip() return arg_string def get_defaults(): """ Function that calls the binaryc get args function and cast it into a dictionary Loading @@ -21,16 +25,17 @@ def get_defaults(): default_output = binary_c.return_arglines() default_dict = {} for default in default_output.split('\n'): if not default in ['__ARG_BEGIN', '__ARG_END', '']: key, value = default.split(' = ') for default in default_output.split("\n"): if not default in ["__ARG_BEGIN", "__ARG_END", ""]: key, value = default.split(" = ") # Filter out NULLS (not compiled anyway) if not value in ['NULL', 'Function']: if not value=='': if not value in ["NULL", "Function"]: if not value == "": default_dict[key] = value return default_dict def get_arg_keys(): """ Function that return the list of possible keys to give in the arg string Loading @@ -38,6 +43,7 @@ def get_arg_keys(): return get_defaults().keys() def run_system(**kwargs): """ Wrapper to run a system with settings Loading @@ -51,31 +57,31 @@ def run_system(**kwargs): # Load default args args = get_defaults() if 'custom_logging_code' in kwargs: 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': 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']) 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) arg_string = "binary_c {}".format(arg_string) # Run it and get output output = binary_c.run_binary_custom_logging(arg_string, func_memaddr) return output elif 'log_filename' in kwargs: 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) arg_string = "binary_c {}".format(arg_string) # Run it and get output output = binary_c.run_binary_with_logfile(arg_string) Loading @@ -89,13 +95,14 @@ def run_system(**kwargs): # Construct arguments string and final execution string arg_string = create_arg_string(args) arg_string = 'binary_c {}'.format(arg_string) arg_string = "binary_c {}".format(arg_string) # Run it and get output output = binary_c.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. Loading @@ -116,7 +123,7 @@ def run_system_with_log(**kwargs): # Construct arguments string and final execution string arg_string = create_arg_string(args) arg_string = 'binary_c {}'.format(arg_string) arg_string = "binary_c {}".format(arg_string) # print(arg_string) Loading @@ -126,6 +133,7 @@ def run_system_with_log(**kwargs): return output def parse_output(output, selected_header): """ Function that parses output of binaryc when it is construction like this: Loading @@ -140,9 +148,9 @@ def parse_output(output, selected_header): val_lists = [] # split output on newlines for i, line in enumerate(output.split('\n')): for i, line in enumerate(output.split("\n")): # Skip any blank lines if not line=='': if not line == "": split_line = line.split() # Select parts Loading @@ -155,12 +163,14 @@ def parse_output(output, selected_header): # Make a dict value_dict = {} for el in value_array: key, val = el.split('=') key, val = el.split("=") value_dict[key] = val value_dicts.append(value_dict) if len(value_dicts) == 0: print('Sorry, didnt find any line matching your header {}'.format(selected_header)) print( "Sorry, didnt find any line matching your header {}".format(selected_header) ) return None keys = value_dicts[0].keys() Loading binaryc_python_utils/stellar_types.py +17 −17 Original line number Diff line number Diff line stellar_type = { 0: 'low mass main sequence', 1: 'Main Sequence', 2: 'Hertzsprung Gap', 3: 'First Giant Branch', 4: 'Core Helium Burning', 5: 'Early Asymptotic Giant Branch', 6: 'Thermally Pulsing', 7: 'NAKED_MAIN_SEQUENCE_HELIUM_STAR', 8: 'NAKED_HELIUM_STAR_HERTZSPRUNG_GAP', 9: 'NAKED_HELIUM_STAR_GIANT_BRANCH', 10: 'HELIUM_WHITE_DWARF', 11: 'CARBON_OXYGEN_WHITE_DWARF', 12: 'OXYGEN_NEON_WHITE_DWARF', 13: 'NEUTRON_STAR', 14: 'BLACK_HOLE', 15: 'MASSLESS REMNANT' 0: "low mass main sequence", 1: "Main Sequence", 2: "Hertzsprung Gap", 3: "First Giant Branch", 4: "Core Helium Burning", 5: "Early Asymptotic Giant Branch", 6: "Thermally Pulsing", 7: "NAKED_MAIN_SEQUENCE_HELIUM_STAR", 8: "NAKED_HELIUM_STAR_HERTZSPRUNG_GAP", 9: "NAKED_HELIUM_STAR_GIANT_BRANCH", 10: "HELIUM_WHITE_DWARF", 11: "CARBON_OXYGEN_WHITE_DWARF", 12: "OXYGEN_NEON_WHITE_DWARF", 13: "NEUTRON_STAR", 14: "BLACK_HOLE", 15: "MASSLESS REMNANT", } examples/example_run_binary_with_custom_logging.py +18 −10 Original line number Diff line number Diff line Loading @@ -2,14 +2,20 @@ import ctypes import tempfile import os from binaryc_python_utils.custom_logging_functions import autogen_C_logging_code, binary_c_log_code, compile_shared_lib, temp_custom_logging_dir, create_and_load_logging_function from binaryc_python_utils.custom_logging_functions import ( autogen_C_logging_code, binary_c_log_code, compile_shared_lib, temp_custom_logging_dir, create_and_load_logging_function, ) import binary_c # generate logging lines logging_line = autogen_C_logging_code( { 'MY_STELLAR_DATA': ['model.time', 'star[0].mass'], 'my_sss2': ['model.time', 'star[1].mass'] "MY_STELLAR_DATA": ["model.time", "star[0].mass"], "my_sss2": ["model.time", "star[1].mass"], } ) Loading @@ -27,6 +33,8 @@ orbital_period = 4530.0 # days eccentricity = 0.0 metallicity = 0.02 max_evolution_time = 15000 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) 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 ) output = binary_c.run_binary_custom_logging(argstring, func_memaddr) print(output) examples/examples_run_binary.py +53 −28 Original line number Diff line number Diff line Loading @@ -5,7 +5,10 @@ import sys import binary_c from binaryc_python_utils.functions import run_system, parse_output from binaryc_python_utils.custom_logging_functions import autogen_C_logging_code, binary_c_log_code from binaryc_python_utils.custom_logging_functions import ( autogen_C_logging_code, binary_c_log_code, ) """ Very basic scripts to run a binary system and print the output. Loading @@ -13,6 +16,7 @@ Very basic scripts to run a binary system and print the output. Use these as inspiration/base """ def run_example_binary(): """ Function to run a binary system. Very basic approach which directly adresses the run_binary(..) python-c wrapper function. Loading @@ -30,12 +34,22 @@ def run_example_binary(): # argstring = "binary_c M_1 {m1} M_2 {m2} separation {separation} orbital_period {orbital_period} \ eccentricity {eccentricity} metallicity {metallicity} \ max_evolution_time {max_evolution_time}".format(m1=m1, m2=m2, separation=separation, orbital_period=orbital_period, eccentricity=eccentricity, metallicity=metallicity, max_evolution_time=max_evolution_time) max_evolution_time {max_evolution_time}".format( m1=m1, m2=m2, separation=separation, orbital_period=orbital_period, eccentricity=eccentricity, metallicity=metallicity, max_evolution_time=max_evolution_time, ) output = binary_c.run_binary(argstring) print(output) # run_example_binary() def run_example_binary_with_run_system(): """ This function serves as an example on the function run_system and parse_output. Loading @@ -55,7 +69,7 @@ def run_example_binary_with_run_system(): output = run_system(M_1=10, M_2=20, separation=0, orbital_period=100000000000) # Catch results that start with a given header. (Mind that binary_c has to be configured to print them if your not using a custom logging function) result_example_header = parse_output(output, 'example_header') result_example_header = parse_output(output, "example_header") #### Now do whatever you want with it: # Put it in numpy arrays Loading Loading @@ -86,9 +100,7 @@ def run_example_binary_with_custom_logging(): # generate logging lines. Here you can choose whatever you want to have logged, and with what header # this generates working print statements logging_line = autogen_C_logging_code( { 'MY_STELLAR_DATA': ['model.time', 'star[0].mass'], } {"MY_STELLAR_DATA": ["model.time", "star[0].mass"],} ) # OR # You can also decide to `write` your own logging_line, which allows you to write a more complex logging statement with conditionals. Loading @@ -98,11 +110,18 @@ def run_example_binary_with_custom_logging(): custom_logging_code = binary_c_log_code(logging_line) # Run system. all arguments can be given as optional arguments. the custom_logging_code is one of them and will be processed automatically. output = run_system(M_1=1, metallicity=0.002, M_2=0.1, separation=0, orbital_period=100000000000, custom_logging_code=custom_logging_code) output = run_system( M_1=1, metallicity=0.002, M_2=0.1, separation=0, orbital_period=100000000000, custom_logging_code=custom_logging_code, ) # Catch results that start with a given header. (Mind that binary_c has to be configured to print them if your not using a custom logging function) # DOESNT WORK YET if you have the line autogenerated. result_example_header = parse_output(output, 'MY_STELLAR_DATA') result_example_header = parse_output(output, "MY_STELLAR_DATA") # Cast the data into a dataframe. df = pd.DataFrame.from_dict(result_example_header, dtype=np.float64) Loading @@ -122,10 +141,16 @@ def run_example_binary_with_writing_logfile(): import tempfile # Run system. all arguments can be given as optional arguments. output = run_system(M_1=10, M_2=20, separation=0, orbital_period=100000000000, log_filename=tempfile.gettempdir()+'/test_log.txt') output = run_system( M_1=10, M_2=20, separation=0, orbital_period=100000000000, log_filename=tempfile.gettempdir() + "/test_log.txt", ) # Catch results that start with a given header. (Mind that binary_c has to be configured to print them if your not using a custom logging function) result_example_header = parse_output(output, 'example_header') result_example_header = parse_output(output, "example_header") #### Now do whatever you want with it: # Put it in numpy arrays Loading Loading
binaryc_python_utils/custom_logging_functions.py +105 −81 Original line number Diff line number Diff line Loading @@ -27,7 +27,7 @@ def autogen_C_logging_code(logging_dict): print("Error: please use a dictionary as input") return None code = '' code = "" # Loop over dict keys for key in logging_dict: logging_dict_entry = logging_dict[key] Loading @@ -37,22 +37,25 @@ def autogen_C_logging_code(logging_dict): # Construct print statement code += 'Printf("{}'.format(key) code += ' {}'.format('%g '*len(logging_dict_entry)) code += " {}".format("%g " * len(logging_dict_entry)) code = code.strip() code += '\\n"' # Add format keys for param in logging_dict_entry: code += ',((double)stardata->{})'.format(param) code += ');\n' code += ",((double)stardata->{})".format(param) code += ");\n" else: print('Error: please use a list for the list of parameters that you want to have logged') print( "Error: please use a list for the list of parameters that you want to have logged" ) code = code.strip() # print("MADE AUTO CODE\n\n{}\n\n{}\n\n{}\n".format('*'*60, repr(code), '*'*60)) return code #################################################################################### def binary_c_log_code(code): """ Loading @@ -77,11 +80,14 @@ void binary_c_API_function custom_output_function(struct stardata_t * stardata) #undef MIN #pragma pop_macro(\"MIN\") #pragma pop_macro(\"MAX\")\ """.format(code) """.format( code ) # print(repr(textwrap.dedent(custom_logging_function_string))) return textwrap.dedent(custom_logging_function_string) def binary_c_write_log_code(code, filename): """ Function to write the generated logging code to a file Loading @@ -96,21 +102,26 @@ def binary_c_write_log_code(code, filename): except: print("Error while deleting file {}".format(filePath)) with open(filePath, 'w') as f: with open(filePath, "w") as f: f.write(code) def from_binary_c_config(config_file, flag): """ Function to run the binaryc_config command with flags """ res = subprocess.check_output('{config_file} {flag}'.format(config_file=config_file, flag=flag), shell=True, stderr=subprocess.STDOUT) res = subprocess.check_output( "{config_file} {flag}".format(config_file=config_file, flag=flag), shell=True, stderr=subprocess.STDOUT, ) # convert and chop off newline res = res.decode('utf').rstrip() res = res.decode("utf").rstrip() return res def return_compilation_dict(): """ Function to build the compile command for the shared library Loading @@ -126,78 +137,88 @@ def return_compilation_dict(): """ # use binary_c-config to get necessary flags BINARY_C_DIR = os.getenv('BINARY_C') BINARY_C_DIR = os.getenv("BINARY_C") if BINARY_C_DIR: BINARY_C_CONFIG = os.path.join(BINARY_C_DIR, 'binary_c-config') BINARY_C_SRC_DIR = os.path.join(BINARY_C_DIR, 'src') BINARY_C_CONFIG = os.path.join(BINARY_C_DIR, "binary_c-config") BINARY_C_SRC_DIR = os.path.join(BINARY_C_DIR, "src") # TODO: build in check to see whether the file exists else: raise NameError('Envvar BINARY_C doesnt exist') raise NameError("Envvar BINARY_C doesnt exist") return None # TODO: make more options for the compiling cc = from_binary_c_config(BINARY_C_CONFIG, 'cc') cc = from_binary_c_config(BINARY_C_CONFIG, "cc") # Check for binary_c BINARY_C_EXE = os.path.join(BINARY_C_DIR, 'binary_c') BINARY_C_EXE = os.path.join(BINARY_C_DIR, "binary_c") if not os.path.isfile(BINARY_C_EXE): print("We require binary_c executable; have you built binary_c?") raise NameError('BINARY_C executable doesnt exist') raise NameError("BINARY_C executable doesnt exist") # TODO: debug libbinary_c = '-lbinary_c' binclibs = from_binary_c_config(BINARY_C_CONFIG, 'libs') libdirs = "{} -L{}".format(from_binary_c_config(BINARY_C_CONFIG, 'libdirs'), BINARY_C_SRC_DIR) bincflags = from_binary_c_config(BINARY_C_CONFIG, 'cflags') bincincdirs = from_binary_c_config(BINARY_C_CONFIG, 'incdirs') libbinary_c = "-lbinary_c" binclibs = from_binary_c_config(BINARY_C_CONFIG, "libs") libdirs = "{} -L{}".format( from_binary_c_config(BINARY_C_CONFIG, "libdirs"), BINARY_C_SRC_DIR ) bincflags = from_binary_c_config(BINARY_C_CONFIG, "cflags") bincincdirs = from_binary_c_config(BINARY_C_CONFIG, "incdirs") # combine binclibs = ' {} {} {}'.format(libdirs, libbinary_c, binclibs) binclibs = " {} {} {}".format(libdirs, libbinary_c, binclibs) # setup defaults: defaults = { 'cc': 'gcc', # default compiler 'ccflags': bincflags, 'ld': 'ld', # 'ld': $Config{ld}, # default linker 'debug': 0, 'inc': '{} -I{}'.format(bincincdirs, BINARY_C_SRC_DIR), "cc": "gcc", # default compiler "ccflags": bincflags, "ld": "ld", # 'ld': $Config{ld}, # default linker "debug": 0, "inc": "{} -I{}".format(bincincdirs, BINARY_C_SRC_DIR), # inc => ' '.($Config{inc}//' ').' '.$bincincdirs." -I$srcdir ", # include the defaults plus # GSL and binary_c # 'libname': libname, # libname is usually just binary_c corresponding to libbinary_c.so 'libs': binclibs, "libs": binclibs, } # set values with defaults. TODO: make other input possile. ld = defaults['ld'] debug = defaults['debug'] inc = defaults['inc'] # = ($ENV{BINARY_GRID2_INC} // $defaults{inc}).' '.($ENV{BINARY_GRID2_EXTRAINC} // ''); libs = defaults['libs'] # = ($ENV{BINARY_GRID2_LIBS} // $defaults{libs}).' '.($ENV{BINARY_GRID2_EXTRALIBS}//''); ccflags = defaults['ccflags'] # = $ENV{BINARY_GRID2_CCFLAGS} // ($defaults{ccflags}) . ($ENV{BINARY_GRID2_EXTRACCFLAGS} // ''); ld = defaults["ld"] debug = defaults["debug"] inc = defaults[ "inc" ] # = ($ENV{BINARY_GRID2_INC} // $defaults{inc}).' '.($ENV{BINARY_GRID2_EXTRAINC} // ''); libs = defaults[ "libs" ] # = ($ENV{BINARY_GRID2_LIBS} // $defaults{libs}).' '.($ENV{BINARY_GRID2_EXTRALIBS}//''); ccflags = defaults[ "ccflags" ] # = $ENV{BINARY_GRID2_CCFLAGS} // ($defaults{ccflags}) . ($ENV{BINARY_GRID2_EXTRACCFLAGS} // ''); # you must define _SEARCH_H to prevent it being loaded twice ccflags += ' -shared -D_SEARCH_H' ccflags += " -shared -D_SEARCH_H" # remove the visibility=hidden for this compilation ccflags = ccflags.replace('-fvisibility=hidden', '') ccflags = ccflags.replace("-fvisibility=hidden", "") # ensure library paths to the front of the libs: libs_content = libs.split(' ') library_paths = [el for el in libs_content if el.startswith('-L')] non_library_paths = [el for el in libs_content if (not el.startswith('-L') and not el=='')] libs = "{} {}".format(' '.join(library_paths), ' '.join(non_library_paths)) print("Building shared library for custom logging with (binary_c.h) at {} on {}\n".format(BINARY_C_SRC_DIR, socket.gethostname())) print("With options:\n\tcc = {cc}\n\tccflags = {ccflags}\n\tld = {ld}\n\tlibs = {libs}\n\tinc = {inc}\n\n".format( cc=cc, ccflags=ccflags, ld=ld, libs=libs, inc=inc) libs_content = libs.split(" ") library_paths = [el for el in libs_content if el.startswith("-L")] non_library_paths = [ el for el in libs_content if (not el.startswith("-L") and not el == "") ] libs = "{} {}".format(" ".join(library_paths), " ".join(non_library_paths)) print( "Building shared library for custom logging with (binary_c.h) at {} on {}\n".format( BINARY_C_SRC_DIR, socket.gethostname() ) ) print( "With options:\n\tcc = {cc}\n\tccflags = {ccflags}\n\tld = {ld}\n\tlibs = {libs}\n\tinc = {inc}\n\n".format( cc=cc, ccflags=ccflags, ld=ld, libs=libs, inc=inc ) ) return { 'cc': cc, 'ld': ld, 'ccflags': ccflags, 'libs': libs, 'inc': inc } return {"cc": cc, "ld": ld, "ccflags": ccflags, "libs": libs, "inc": inc} def compile_shared_lib(code, sourcefile_name, outfile_name): """ Loading @@ -212,23 +233,23 @@ def compile_shared_lib(code, sourcefile_name, outfile_name): # Construct full command command = "{cc} {ccflags} {libs} -o {outfile_name} {sourcefile_name} {inc}".format( cc=compilation_dict['cc'], ccflags=compilation_dict['ccflags'], libs=compilation_dict['libs'], cc=compilation_dict["cc"], ccflags=compilation_dict["ccflags"], libs=compilation_dict["libs"], outfile_name=outfile_name, sourcefile_name=sourcefile_name, inc=compilation_dict['inc']) inc=compilation_dict["inc"], ) # remove extra whitespaces: command = ' '.join(command.split()) command = " ".join(command.split()) # Execute compilation print('Executing following command:\n{command}'.format(command=command)) res = subprocess.check_output('{command}'.format(command=command), shell=True) print("Executing following command:\n{command}".format(command=command)) res = subprocess.check_output("{command}".format(command=command), shell=True) if res: print('Output of compilation command:\n{}'.format(res)) print("Output of compilation command:\n{}".format(res)) def temp_custom_logging_dir(): Loading @@ -239,7 +260,7 @@ def temp_custom_logging_dir(): """ tmp_dir = tempfile.gettempdir() path = os.path.join(tmp_dir, 'binary_c_python') path = os.path.join(tmp_dir, "binary_c_python") # os.makedirs(path, exist_ok=True) Loading @@ -256,17 +277,20 @@ def create_and_load_logging_function(custom_logging_code): """ # compile_shared_lib(custom_logging_code, sourcefile_name=os.path.join(temp_custom_logging_dir(), 'custom_logging.c'), outfile_name=os.path.join(temp_custom_logging_dir(), 'libcustom_logging.so') compile_shared_lib( custom_logging_code, sourcefile_name=os.path.join(temp_custom_logging_dir(), "custom_logging.c"), outfile_name=os.path.join(temp_custom_logging_dir(), "libcustom_logging.so"), ) # Loading library dll1 = ctypes.CDLL('libgslcblas.so', mode=ctypes.RTLD_GLOBAL) dll2 = ctypes.CDLL('libgsl.so', mode=ctypes.RTLD_GLOBAL) dll3 = ctypes.CDLL('libbinary_c.so', mode=ctypes.RTLD_GLOBAL) libmean = ctypes.CDLL(os.path.join(temp_custom_logging_dir(), 'libcustom_logging.so'), mode=ctypes.RTLD_GLOBAL) # loads the shared library dll1 = ctypes.CDLL("libgslcblas.so", mode=ctypes.RTLD_GLOBAL) dll2 = ctypes.CDLL("libgsl.so", mode=ctypes.RTLD_GLOBAL) dll3 = ctypes.CDLL("libbinary_c.so", mode=ctypes.RTLD_GLOBAL) libmean = ctypes.CDLL( os.path.join(temp_custom_logging_dir(), "libcustom_logging.so"), mode=ctypes.RTLD_GLOBAL, ) # loads the shared library # Get memory adress of function. mimicking a pointer func_memaddr = ctypes.cast(libmean.custom_output_function, ctypes.c_void_p).value Loading
binaryc_python_utils/functions.py +35 −25 Original line number Diff line number Diff line from collections import defaultdict import binary_c from binaryc_python_utils.custom_logging_functions import create_and_load_logging_function from binaryc_python_utils.custom_logging_functions import ( create_and_load_logging_function, ) def create_arg_string(arg_dict): """ Function that creates the arg string """ arg_string = '' arg_string = "" for key in arg_dict.keys(): arg_string += "{key} {value} ".format(key=key, value=arg_dict[key]) arg_string = arg_string.strip() return arg_string def get_defaults(): """ Function that calls the binaryc get args function and cast it into a dictionary Loading @@ -21,16 +25,17 @@ def get_defaults(): default_output = binary_c.return_arglines() default_dict = {} for default in default_output.split('\n'): if not default in ['__ARG_BEGIN', '__ARG_END', '']: key, value = default.split(' = ') for default in default_output.split("\n"): if not default in ["__ARG_BEGIN", "__ARG_END", ""]: key, value = default.split(" = ") # Filter out NULLS (not compiled anyway) if not value in ['NULL', 'Function']: if not value=='': if not value in ["NULL", "Function"]: if not value == "": default_dict[key] = value return default_dict def get_arg_keys(): """ Function that return the list of possible keys to give in the arg string Loading @@ -38,6 +43,7 @@ def get_arg_keys(): return get_defaults().keys() def run_system(**kwargs): """ Wrapper to run a system with settings Loading @@ -51,31 +57,31 @@ def run_system(**kwargs): # Load default args args = get_defaults() if 'custom_logging_code' in kwargs: 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': 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']) 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) arg_string = "binary_c {}".format(arg_string) # Run it and get output output = binary_c.run_binary_custom_logging(arg_string, func_memaddr) return output elif 'log_filename' in kwargs: 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) arg_string = "binary_c {}".format(arg_string) # Run it and get output output = binary_c.run_binary_with_logfile(arg_string) Loading @@ -89,13 +95,14 @@ def run_system(**kwargs): # Construct arguments string and final execution string arg_string = create_arg_string(args) arg_string = 'binary_c {}'.format(arg_string) arg_string = "binary_c {}".format(arg_string) # Run it and get output output = binary_c.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. Loading @@ -116,7 +123,7 @@ def run_system_with_log(**kwargs): # Construct arguments string and final execution string arg_string = create_arg_string(args) arg_string = 'binary_c {}'.format(arg_string) arg_string = "binary_c {}".format(arg_string) # print(arg_string) Loading @@ -126,6 +133,7 @@ def run_system_with_log(**kwargs): return output def parse_output(output, selected_header): """ Function that parses output of binaryc when it is construction like this: Loading @@ -140,9 +148,9 @@ def parse_output(output, selected_header): val_lists = [] # split output on newlines for i, line in enumerate(output.split('\n')): for i, line in enumerate(output.split("\n")): # Skip any blank lines if not line=='': if not line == "": split_line = line.split() # Select parts Loading @@ -155,12 +163,14 @@ def parse_output(output, selected_header): # Make a dict value_dict = {} for el in value_array: key, val = el.split('=') key, val = el.split("=") value_dict[key] = val value_dicts.append(value_dict) if len(value_dicts) == 0: print('Sorry, didnt find any line matching your header {}'.format(selected_header)) print( "Sorry, didnt find any line matching your header {}".format(selected_header) ) return None keys = value_dicts[0].keys() Loading
binaryc_python_utils/stellar_types.py +17 −17 Original line number Diff line number Diff line stellar_type = { 0: 'low mass main sequence', 1: 'Main Sequence', 2: 'Hertzsprung Gap', 3: 'First Giant Branch', 4: 'Core Helium Burning', 5: 'Early Asymptotic Giant Branch', 6: 'Thermally Pulsing', 7: 'NAKED_MAIN_SEQUENCE_HELIUM_STAR', 8: 'NAKED_HELIUM_STAR_HERTZSPRUNG_GAP', 9: 'NAKED_HELIUM_STAR_GIANT_BRANCH', 10: 'HELIUM_WHITE_DWARF', 11: 'CARBON_OXYGEN_WHITE_DWARF', 12: 'OXYGEN_NEON_WHITE_DWARF', 13: 'NEUTRON_STAR', 14: 'BLACK_HOLE', 15: 'MASSLESS REMNANT' 0: "low mass main sequence", 1: "Main Sequence", 2: "Hertzsprung Gap", 3: "First Giant Branch", 4: "Core Helium Burning", 5: "Early Asymptotic Giant Branch", 6: "Thermally Pulsing", 7: "NAKED_MAIN_SEQUENCE_HELIUM_STAR", 8: "NAKED_HELIUM_STAR_HERTZSPRUNG_GAP", 9: "NAKED_HELIUM_STAR_GIANT_BRANCH", 10: "HELIUM_WHITE_DWARF", 11: "CARBON_OXYGEN_WHITE_DWARF", 12: "OXYGEN_NEON_WHITE_DWARF", 13: "NEUTRON_STAR", 14: "BLACK_HOLE", 15: "MASSLESS REMNANT", }
examples/example_run_binary_with_custom_logging.py +18 −10 Original line number Diff line number Diff line Loading @@ -2,14 +2,20 @@ import ctypes import tempfile import os from binaryc_python_utils.custom_logging_functions import autogen_C_logging_code, binary_c_log_code, compile_shared_lib, temp_custom_logging_dir, create_and_load_logging_function from binaryc_python_utils.custom_logging_functions import ( autogen_C_logging_code, binary_c_log_code, compile_shared_lib, temp_custom_logging_dir, create_and_load_logging_function, ) import binary_c # generate logging lines logging_line = autogen_C_logging_code( { 'MY_STELLAR_DATA': ['model.time', 'star[0].mass'], 'my_sss2': ['model.time', 'star[1].mass'] "MY_STELLAR_DATA": ["model.time", "star[0].mass"], "my_sss2": ["model.time", "star[1].mass"], } ) Loading @@ -27,6 +33,8 @@ orbital_period = 4530.0 # days eccentricity = 0.0 metallicity = 0.02 max_evolution_time = 15000 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) 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 ) output = binary_c.run_binary_custom_logging(argstring, func_memaddr) print(output)
examples/examples_run_binary.py +53 −28 Original line number Diff line number Diff line Loading @@ -5,7 +5,10 @@ import sys import binary_c from binaryc_python_utils.functions import run_system, parse_output from binaryc_python_utils.custom_logging_functions import autogen_C_logging_code, binary_c_log_code from binaryc_python_utils.custom_logging_functions import ( autogen_C_logging_code, binary_c_log_code, ) """ Very basic scripts to run a binary system and print the output. Loading @@ -13,6 +16,7 @@ Very basic scripts to run a binary system and print the output. Use these as inspiration/base """ def run_example_binary(): """ Function to run a binary system. Very basic approach which directly adresses the run_binary(..) python-c wrapper function. Loading @@ -30,12 +34,22 @@ def run_example_binary(): # argstring = "binary_c M_1 {m1} M_2 {m2} separation {separation} orbital_period {orbital_period} \ eccentricity {eccentricity} metallicity {metallicity} \ max_evolution_time {max_evolution_time}".format(m1=m1, m2=m2, separation=separation, orbital_period=orbital_period, eccentricity=eccentricity, metallicity=metallicity, max_evolution_time=max_evolution_time) max_evolution_time {max_evolution_time}".format( m1=m1, m2=m2, separation=separation, orbital_period=orbital_period, eccentricity=eccentricity, metallicity=metallicity, max_evolution_time=max_evolution_time, ) output = binary_c.run_binary(argstring) print(output) # run_example_binary() def run_example_binary_with_run_system(): """ This function serves as an example on the function run_system and parse_output. Loading @@ -55,7 +69,7 @@ def run_example_binary_with_run_system(): output = run_system(M_1=10, M_2=20, separation=0, orbital_period=100000000000) # Catch results that start with a given header. (Mind that binary_c has to be configured to print them if your not using a custom logging function) result_example_header = parse_output(output, 'example_header') result_example_header = parse_output(output, "example_header") #### Now do whatever you want with it: # Put it in numpy arrays Loading Loading @@ -86,9 +100,7 @@ def run_example_binary_with_custom_logging(): # generate logging lines. Here you can choose whatever you want to have logged, and with what header # this generates working print statements logging_line = autogen_C_logging_code( { 'MY_STELLAR_DATA': ['model.time', 'star[0].mass'], } {"MY_STELLAR_DATA": ["model.time", "star[0].mass"],} ) # OR # You can also decide to `write` your own logging_line, which allows you to write a more complex logging statement with conditionals. Loading @@ -98,11 +110,18 @@ def run_example_binary_with_custom_logging(): custom_logging_code = binary_c_log_code(logging_line) # Run system. all arguments can be given as optional arguments. the custom_logging_code is one of them and will be processed automatically. output = run_system(M_1=1, metallicity=0.002, M_2=0.1, separation=0, orbital_period=100000000000, custom_logging_code=custom_logging_code) output = run_system( M_1=1, metallicity=0.002, M_2=0.1, separation=0, orbital_period=100000000000, custom_logging_code=custom_logging_code, ) # Catch results that start with a given header. (Mind that binary_c has to be configured to print them if your not using a custom logging function) # DOESNT WORK YET if you have the line autogenerated. result_example_header = parse_output(output, 'MY_STELLAR_DATA') result_example_header = parse_output(output, "MY_STELLAR_DATA") # Cast the data into a dataframe. df = pd.DataFrame.from_dict(result_example_header, dtype=np.float64) Loading @@ -122,10 +141,16 @@ def run_example_binary_with_writing_logfile(): import tempfile # Run system. all arguments can be given as optional arguments. output = run_system(M_1=10, M_2=20, separation=0, orbital_period=100000000000, log_filename=tempfile.gettempdir()+'/test_log.txt') output = run_system( M_1=10, M_2=20, separation=0, orbital_period=100000000000, log_filename=tempfile.gettempdir() + "/test_log.txt", ) # Catch results that start with a given header. (Mind that binary_c has to be configured to print them if your not using a custom logging function) result_example_header = parse_output(output, 'example_header') result_example_header = parse_output(output, "example_header") #### Now do whatever you want with it: # Put it in numpy arrays Loading