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