Commit 3bc0755e authored by David Hendriks's avatar David Hendriks
Browse files

added functions for the grid. working on the automatic generation of the grid code

parent 12cfa178
Loading
Loading
Loading
Loading
+59 −0
Original line number Diff line number Diff line
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.
+109 −21
Original line number Diff line number Diff line
@@ -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):
@@ -108,6 +109,7 @@ class Population(object):
            parameter_dict = self.bse_options

        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,16 +244,32 @@ 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 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))
@@ -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)



################################################################################################