diff --git a/binarycpython/utils/NULL b/binarycpython/utils/NULL
new file mode 100644
index 0000000000000000000000000000000000000000..a087085a1d94db519d7f5e429e17cce682acc6b8
Binary files /dev/null and b/binarycpython/utils/NULL differ
diff --git a/binarycpython/utils/grid.py b/binarycpython/utils/grid.py
index bf2ecd3f36678a3f012ea7195559e7cc733a5b53..caf425b34fc4ca3e4caf448a24f4a3d5496cd1ee 100644
--- a/binarycpython/utils/grid.py
+++ b/binarycpython/utils/grid.py
@@ -1,9 +1,31 @@
+import os
+import copy
+import json
+
 import binary_c_python_api
 
 from binarycpython.utils.functions import get_defaults
 
 import binarycpython
 
+from grid_options_defaults import grid_options_defaults_dict
+
+
+
+# TODO: add functionality to 'on-init' set arguments
+# TODO: add functionality to export the arg string.
+# TODO: add functionality to export all the options
+# TODO: add functionality to create the dict that goes into the arg line. 
+# TODO: add functionality to return the initial_abundance_hash
+# TODO: add functionality to return the isotope_hash
+# TODO: add functionality to return the isotope_list
+# TODO: add functionality to return the nuclear_mass_hash
+# TODO: add functionality to return the nuclear_mass_list
+# TODO: add functionality to return the source_list
+# TODO: add functionality to return the ensemble_list
+# TODO: add functionality to return the evcode_version_string
+# TODO: add functionality to return the evcode_args_list
+
 
 class Population(object):
     def __init__(self):
@@ -12,28 +34,200 @@ class Population(object):
         """
 
         self.defaults = get_defaults()
-        pass
+
+        # Different sections of options
+        self.bse_options = self.defaults.copy()
+        self.grid_options = grid_options_defaults_dict.copy()
+        self.custom_options = {}
+
+        # Argline dict
+        self.argline_dict = {}
+
+    def return_options(self):
+        """
+        Function that returns all the options that have been set.
+
+        Can be combined with json to make a nice file. 
+        """
+
+        options = {
+            'bse_options': self.bse_options,
+            'grid_options': self.grid_options,
+            'custom_options': self.custom_options,
+        }
+
+        return options
+
+
+    def create_argline_dict(self, print_excluded=False):
+        """
+        Function to prepare the dictionary of options that go into the argument line for the binary_c call.
+
+        This function 
+        """
+
+        self.argline_dict = {}
+
+        # Lists to store indices of parameters that have been included and excluded. 
+        included, excluded = [], []
+
+        # Go over the parameters.    
+        for i, param_name in enumerate(sorted(self.bse_options)):
+            # We need to filter out some parameters:
+            # Filter out those that have an literal empty value. The argument parser of binary_c doesnt work properly with that.
+            # Filter out those that have value Function. adding these to the argument will execute the function instead of evolving the system
+            # Filter out those that have value NULL. In general these only come from the defaults of binary_c itself. 
+            #   What I do here is comparing whether the value of the bse_option is NULL currently AND as a default. In that way one could set some other part to NULL (don't know what situation that would be tho..) 
+
+
+            if (not ((self.bse_options[param_name] == 'NULL') and (self.bse_options[param_name] == self.defaults[param_name]))) \
+            and (not self.bse_options[param_name] == "") and (not self.bse_options[param_name] == "Function"):
+                self.argline_dict[param_name] = self.bse_options[param_name]
+                # print("{} {} ".format(param_name, self.bse_options[param_name]))
+                included.append(i)
+            else:
+                # print("{} {} ".format(param_name, repr(self.bse_options[param_name])))
+                excluded.append(i)
+
+        common = set(included).intersection(excluded)
+        combined = set(included).union(excluded)
+
+        if print_excluded:
+            print("Total parameters included in the argument: {}. Total excluded: {}. ".format(len(included), len(excluded)))
+            print([sorted(self.bse_options)[i] for i in excluded])
+
+
+    def create_argline(self, option_dict):
+        """
+        Function to create the string for the arg line
+        """
+
+        argline = "binary_c "
+        for param_name in sorted(option_dict):
+            argline += "{} {} ".format(param_name, self.argline_dict[param_name])
+        argline = argline.strip()
+        return argline
+
+    def return_argline(self, print_excluded=False):
+        """
+        Function to return the argline that is used in the binary_c api call:
+        be aware that some of the parameters vary: M1 M2 period etc because these are set by distributions.
+
+        """
+
+        self.create_argline_dict(print_excluded)
+
+        argline = "binary_c "
+        for param_name in sorted(self.argline_dict.keys()):
+            argline += "{} {} ".format(param_name, self.argline_dict[param_name])
+
+        argline = argline.strip()
+        return argline
+
+    def set(self, **kwargs):
+        """
+        Function to set the values of the population
+
+        The input (as kwargs) is checked compared to the available bse_options and grid options.
+        if the parameter name is not included in either of those, then it will be stored in an custom_options dict.
+        """
+
+        for key in kwargs.keys():
+            # Filter out keys for the bse_options
+            if key in self.bse_options.keys():
+                self.bse_options[key] = kwargs[key]
+            # Filter out keys for the grid_options
+            elif key in self.grid_options.keys():
+                self.grid_options[key] = kwargs[key]
+            # The of the keys go into a custom_options dict
+            else:
+                self.custom_options[key] = kwargs[key]
 
     def evolve(self):
         pass
 
+
+
     def evolve_single(self):
-        arg_string = "binary_c "
-        for param in self.defaults.keys():
-            print(param, self.defaults[param])
-            if self.defaults[param] == "":
-                print(self.defaults[param])
+        """
+        Function to run a single system
+        """
+
+        self.create_argline_dict()        
 
-            # arg_string += "{} {} ".format(param, self.defaults[param])
+        argline = self.create_argline(self.argline_dict)
 
-        # arg_string = arg_string.strip()
-        out = binary_c_python_api.run_binary(arg_string)
+        out = binary_c_python_api.run_binary(argline)
+        # out = binary_c_python_api.run_binary('binary_c M_1 15 M_2 14 separation 0 orbital_period 4530 eccentricity 0 metallicity 0.02 max_evolution_time 15000')
         print(out)
-        # print(  arg_string)
 
 
+    def return_binary_c_version_info(self):
+        """
+        Function that returns the version information of binary_c
+        """
+
+        out = binary_c_python_api.run_binary('binary_c version')
+        return out
+
+    def test_evolve_single(self):
+        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
+        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_python_api.run_binary(argstring)
+
+        print("\n\nBinary_c output:")
+        print(output)
+
+
+
+
+
+################################################################################################ 
 test_pop = Population()
 
-# print(test_pop.defaults)
+# Setting values
+# print(test_pop.bse_options['M_1'])
+# print(test_pop.bse_options['M_2'])
+# test_pop.set(M_1=10, M_2=500)
+# print(test_pop.bse_options['M_1'])
+# print(test_pop.bse_options['M_2'])
+test_pop.set(M_1=10, separation=0, orbital_period=4580, max_evolution_time=15000, eccentricity=0.02, )
+
 
+
+# Testing single evolution
 test_pop.evolve_single()
+# test_pop.test_evolve_single()
+
+## Setting custom value
+# test_pop.set(data_dir=os.path.join(os.environ['BINARYC_DATA_ROOT'], 'development_example'))
+# print(test_pop.custom_options['data_dir'])
+
+# printing all options
+# print(json.dumps(test_pop.return_options(), indent=4))
+
+# return arglines:
+# test_pop.set(M_1=10, M_2=500)
+print(test_pop.return_argline())
+# test_pop.return_argline(print_excluded=True)
+
+#print(test_pop.bse_options)
+
+# return version info
+a = str(test_pop.return_binary_c_version_info())
+print(a)
\ No newline at end of file
diff --git a/binarycpython/utils/grid_options_defaults.py b/binarycpython/utils/grid_options_defaults.py
new file mode 100644
index 0000000000000000000000000000000000000000..a426a8814b67af50479ac63c2c8a690369b31176
--- /dev/null
+++ b/binarycpython/utils/grid_options_defaults.py
@@ -0,0 +1,3 @@
+grid_options_defaults_dict = {
+    'custom_logging_function': None,
+}
\ No newline at end of file