From 3bc0755e190b3abfb2393dfe83f58bd28eae409a Mon Sep 17 00:00:00 2001 From: David Hendriks <davidhendriks93@gmail.com> Date: Thu, 23 Jan 2020 16:46:47 +0000 Subject: [PATCH] added functions for the grid. working on the automatic generation of the grid code --- binarycpython/utils/functions.py | 59 ++++++++++++++ binarycpython/utils/grid.py | 130 ++++++++++++++++++++++++++----- 2 files changed, 168 insertions(+), 21 deletions(-) diff --git a/binarycpython/utils/functions.py b/binarycpython/utils/functions.py index f5ebd8729..e045c5614 100644 --- a/binarycpython/utils/functions.py +++ b/binarycpython/utils/functions.py @@ -1,13 +1,72 @@ import copy import json +import os +import h5py 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, ) +def create_hdf5(data_dir): + """ + Function to create an hdf5 file from the contents of a directory: + - settings file is selected by checking on files ending on settings + - data files are selected by checking on files ending with .dat + """ + + # Get content of data_dir + content_data_dir = os.listdir(data_dir) + + # Settings + settings_file = [file for file in content_data_dir if file.endswith('_settings.json')][0] + with open(settings_file, 'r') as f: + settings_json = json.load(f) + + # create basename for hdf5 + base_name = settings_file.replace('_settings.json', '') + + # Get data files + data_files = [el for el in content_data_dir if el.endswith('.dat')] + + # Create the file + hdf5_filename = os.path.join(data_dir,'{base_name}.hdf5'.format(base_name=base_name)) + f = h5py.File(hdf5_filename, 'w') + + # Create settings group + settings_grp = f.create_group('settings') + + # Write version_string to settings_group + settings_grp.create_dataset('used_settings', data=json.dumps(settings_json)) + + # Create the data group + data_grp = f.create_group('data') + + print('Creating {}'.format(hdf5_filename)) + + # Write the data to the file: + # Make sure: + for data_file in data_files: + # filename stuff + filename = data_file + full_path = os.path.join(data_dir, filename) + base_name = os.path.splitext(os.path.basename(filename))[0] + + # Get header info + header_name = '{base_name}_header'.format(base_name=base_name) + data_headers = np.genfromtxt(full_path, dtype='str', max_rows=1) + data_headers = np.char.encode(data_headers) + data_grp.create_dataset(header_name, data=data_headers) + + # Add data + data = np.loadtxt(full_path, skiprows=1) + data_grp.create_dataset(base_name, data=data) + + f.close() + def get_help_super(print_help=False, return_dict=True, fail_silently=True): """ Function that first runs get_help_all, and then per argument also run the help function to get as much information as possible. diff --git a/binarycpython/utils/grid.py b/binarycpython/utils/grid.py index 507983858..f09371556 100644 --- a/binarycpython/utils/grid.py +++ b/binarycpython/utils/grid.py @@ -11,6 +11,7 @@ from binarycpython.utils.custom_logging_functions import ( autogen_C_logging_code, binary_c_log_code, create_and_load_logging_function, + temp_custom_logging_dir, ) from binarycpython.utils.functions import get_defaults @@ -32,7 +33,7 @@ from binarycpython.utils.functions import get_defaults # 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 # DONE: add functionality to return the evcode_args_list - +# TODO: add grid generation script class Population(object): def __init__(self): @@ -107,7 +108,8 @@ class Population(object): if not parameter_dict: parameter_dict = self.bse_options - argline = "binary_c " + argline = "binary_c " + # TODO: check if that sort actually works for param_name in sorted(parameter_dict): argline += "{} {} ".format(param_name, parameter_dict[param_name]) argline = argline.strip() @@ -120,18 +122,7 @@ class Population(object): pass - def add_grid_variable( - self, - name, - longname, - range, - resolution, - spacingfunc, - precode, - probdist, - dphasevol, - condition, - ): + def add_grid_variable(self, name, longname, valuerange, resolution, spacingfunc, precode, probdist, dphasevol, condition=None): """ Function to add grid variables to the grid_options. @@ -173,9 +164,9 @@ class Population(object): grid_variable = { "name": name, "longname": longname, - "range": range, # TODO: change name + "valuerange": valuerange, "resolution": resolution, - "spacingfunction": spacingfunction, + "spacingfunc": spacingfunc, "precode": precode, "probdist": probdist, "dphasevol": dphasevol, @@ -253,19 +244,35 @@ class Population(object): return all_info - def export_all_info(self, outfile): + def export_all_info(self, use_datadir=False, outfile=None): """ 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 + + TODO: Fix to write things to the directory. which options do which etc """ all_info = self.return_all_info() - # if not outfile.endswith('json'): - with open(outfile, "w") as f: - f.write(json.dumps(all_info, indent=4)) + if use_datadir: + base_name = os.path.splitext(self.custom_options['base_filename'])[0] + settings_name = base_name + '_settings.json' + + # Check directory, make if necessary + os.makedirs(self.custom_options['data_dir'], exist_ok=True) + + settings_fullname = os.path.join(self.custom_options['data_dir'], settings_name) + + # if not outfile.endswith('json'): + with open(settings_fullname, "w") as f: + f.write(json.dumps(all_info, indent=4)) + + else: + # if not outfile.endswith('json'): + with open(outfile, "w") as f: + f.write(json.dumps(all_info, indent=4)) def set_custom_logging(self): """ @@ -425,5 +432,86 @@ class Population(object): print("\n\nBinary_c output:") print(output) + ################################################### + # Unordered functions + ################################################### + + + def generate_grid_code(self): + """ + Function that generates the code from which the population will be made. + + # TODO: make a generator for this. + # TODO: Add correct logging everywhere + # TODO: add different types of grid. + """ + + code_string = "" + depth = 0 + indent = ' ' + + # Set some values in the generated code: + + # TODO: add imports + # TODO: + + code_string += "starcount = 0\n" + code_string += "probsum = []\n" + + + + + + + + + + + + + + + + + + + + + + + + + + # Generate code + print("Generating grid code") + for el in sorted(self.grid_options["grid_variables"].items(), key=lambda x: x[1]['grid_variable_number']): + print("Constructing/adding: {}".format(el[0])) + grid_variable = el[1] + + # Adding for loop structure + code_string += indent * depth + 'for {} in range({}, {}):'.format(grid_variable['name'], grid_variable['valuerange'][0], grid_variable['valuerange'][1]) + '\n' + + # Add pre-code + code_string += indent * (depth + 1) + '{}'.format(grid_variable['precode'].replace('\n', '\n'+indent * (depth + 1))) + '\n' + + # Calculate probability + + + # some testing line. + code_string += indent * (depth + 1) + 'print({})'.format(grid_variable['name']) + '\n' + + # Add some space + code_string += "\n" + + # + depth += 1 + + + # Write to file + gridcode_filename = os.path.join(temp_custom_logging_dir(), 'example_grid.py') + with open(gridcode_filename, 'w') as f: + f.write(code_string) + + -################################################################################################ \ No newline at end of file +################################################################################################ -- GitLab