diff --git a/binarycpython/utils/functions.py b/binarycpython/utils/functions.py
index 7d54cba16837a4f05f084fa7ab9819aae73b6dfc..8ad24f1e6a2e6cc1baca342c01e138cbed77f8c0 100644
--- a/binarycpython/utils/functions.py
+++ b/binarycpython/utils/functions.py
@@ -727,7 +727,7 @@ def inspect_dict(dict_1, indent=0, print_structure=True):
         if print_structure:
             print("\t" * indent, key, type(value))
         if isinstance(value, dict):
-            structure_dict[key] = inspect_dict(value, indent=indent + 1)
+            structure_dict[key] = inspect_dict(value, indent=indent + 1, print_structure=print_structure)
     return structure_dict
 
 
diff --git a/binarycpython/utils/grid.py b/binarycpython/utils/grid.py
index ed1b651afe988f44f0719a52f4d1c54e31210c5f..3f491f03d68c3bee1b300f45e769ebd667b1b4f7 100644
--- a/binarycpython/utils/grid.py
+++ b/binarycpython/utils/grid.py
@@ -521,6 +521,85 @@ class Population:
                 custom_logging_code, verbose=self.grid_options["verbosity"]
             )
 
+    ###################################################
+    # Sourcefile functions
+    ###################################################
+
+    def load_source_file(self, check=False):
+        """
+        Function that loads the source_file that contains a binary_c calls
+        """
+
+        if not os.path.isfile(self.grid_options["source_file_filename"]):
+            verbose_print("Source file doesnt exist", self.grid_options["verbosity"], 0)
+
+        verbose_print(
+            message="Loading source file from {}".format(
+                self.grid_options["gridcode_filename"]
+            ),
+            verbosity=self.grid_options["verbosity"],
+            minimal_verbosity=1,
+        )
+
+        # We can choose to perform a check on the sourcefile, which checks if the lines start with 'binary_c'
+        if check:
+            source_file_check_filehandle = open(self.grid_options["source_file_filename"], 'r')
+            for line in source_file_check_filehandle:
+                if not line.startswith('binary_c')
+                    failed = True
+                    break
+            if failed:
+                verbose_print("Error, sourcefile contains lines that do not start with binary_c", self.grid_options["verbosity"], 0)
+                raise ValueError
+
+        source_file_filehandle = open(self.grid_options["source_file_filename"], 'r')
+
+        self.grid_options["system_generator"] = source_file_filehandle
+
+        verbose_print("Source file loaded", self.grid_options["verbosity"], 1)
+
+    def dict_from_line_source_file(self):
+        """
+        Function that creates a dict from a binary_c argline 
+        """
+
+        if line.startswith("binary_c "):
+            line = line.replace("binary_c ", "")
+
+        split_line = line.split()
+        arg_dict = {}
+
+        for i in range(0, len(split_line), 2):
+            if "." in split_line[i+1]:
+                arg_dict[split_line[i]] = float(split_line[i + 1])
+            else: 
+                arg_dict[split_line[i]] = int(split_line[i + 1])
+
+        return arg_dict
+
+    def dry_run_source_file(self):
+        """
+        Function to go through the source_file and count the amount of lines and the total probability
+        """
+
+        system_generator = self.grid_options["system_generator"]
+
+        total_starcount = 0
+        total_probability = 0
+
+        contains_probability = False
+
+        for line in system_generator:
+            
+
+
+            total_starcount += 1
+
+
+        total_starcount = system_generator(self)
+        self.grid_options["total_starcount"] = total_starcount
+
+
     ###################################################
     # Ensemble functions
     ###################################################
@@ -637,44 +716,83 @@ class Population:
                 )
                 raise ValueError
 
-        #######################
-        # Dry run and getting starcount
-        self.grid_options["probtot"] = 0
+        # Check which type of population generation
+        if grid_options["population_type_options"] == "grid":
+            #######################
+            # Dry run and getting starcount
+            self.grid_options["probtot"] = 0
 
-        # Put in check
-        if len(self.grid_options["grid_variables"]) == 0:
-            print("Error: you havent defined any grid variables! Aborting")
-            raise ValueError
+            # Put in check
+            if len(self.grid_options["grid_variables"]) == 0:
+                print("Error: you havent defined any grid variables! Aborting")
+                raise ValueError
 
-        # Set up the grid code with a dry run option to see total probability
-        self.generate_grid_code(dry_run=True)
+            # Set up the grid code with a dry run option to see total probability
+            self.generate_grid_code(dry_run=True)
 
-        # Load the grid code
-        self.load_grid_function()
+            # Load the grid code
+            self.load_grid_function()
 
-        # Do a dry run
-        self.dry_run()
+            # Do a dry run
+            self.dry_run()
 
-        print(
-            "Total starcount for this run will be: {}".format(
-                self.grid_options["total_starcount"]
+            print(
+                "Total starcount for this run will be: {}".format(
+                    self.grid_options["total_starcount"]
+                )
             )
-        )
 
-        #######################
-        # Reset values and prepare the grid function
-        self.grid_options[
-            "probtot"
-        ] = 0  # To make sure that the values are reset. TODO: fix this in a cleaner way
-        self.grid_options[
-            "start_time_evolution"
-        ] = time.time()  # Setting start time of grid
+            #######################
+            # Reset values and prepare the grid function
+            self.grid_options[
+                "probtot"
+            ] = 0  # To make sure that the values are reset. TODO: fix this in a cleaner way
+            self.grid_options[
+                "start_time_evolution"
+            ] = time.time()  # Setting start time of grid
+
+            #
+            self.generate_grid_code(dry_run=False)
+
+            #
+            self.load_grid_function()
+
+        # Source file
+        elif grid_options["population_type_options"] == "source_file":
+            #######################
+            # Dry run and getting starcount
+            self.grid_options["probtot"] = 0
+
+            # Load the grid code
+            self.load_source_file_function()
+
+            # Do a dry run
+            self.dry_run_source_file()
+
+            print(
+                "Total starcount for this run will be: {}".format(
+                    self.grid_options["total_starcount"]
+                )
+            )
+
+            #######################
+            # Reset values and prepare the grid function
+            self.grid_options[
+                "probtot"
+            ] = 0  # To make sure that the values are reset. TODO: fix this in a cleaner way
+            self.grid_options[
+                "start_time_evolution"
+            ] = time.time()  # Setting start time of grid
+
+            #
+            self.load_source_file_function(dry_run=False)
+
+            #
+            self.load_grid_function()
+
+
 
-        #
-        self.generate_grid_code(dry_run=False)
 
-        #
-        self.load_grid_function()
 
         #######
 
@@ -1391,6 +1509,31 @@ class Population:
         # warning; dont use yet. not fully tested.
         """
 
+        # Check if there is no compiled grid yet. If not, lets try to build it first.
+        if not self.grid_options["system_generator"]:
+
+            ## check the settings:
+            if self.bse_options.get("ensemble", None):
+                if self.bse_options['ensemble'] == 1:
+                    if not self.bse_options["ensemble_defer"] == 1:
+                        verbose_print(
+                            "Error, if you want to run an ensemble in a population, the output needs to be deferred",
+                            self.grid_options["verbosity"],
+                            0,
+                        )
+                        raise ValueError
+
+            # Put in check
+            if len(self.grid_options["grid_variables"]) == 0:
+                print("Error: you havent defined any grid variables! Aborting")
+                raise ValueError
+
+            #
+            self.generate_grid_code(dry_run=False)
+
+            #
+            self.load_grid_function()
+
         if self.grid_options["system_generator"]:
             # Check if there is an output dir configured
             if self.custom_options.get("data_dir", None):
@@ -1435,7 +1578,7 @@ class Population:
                     file.write(binary_cmdline_string + "\n")
         else:
             print("Error. No grid function found!")
-            raise KeyError
+            raise ValueError
 
     def cleanup_defaults(self):
         """
diff --git a/binarycpython/utils/grid_options_defaults.py b/binarycpython/utils/grid_options_defaults.py
index ea33f57d41e981fb4514b7eca1025dec30e2a125..bbcda861e4d178674fbafee7950f126b404158c0 100644
--- a/binarycpython/utils/grid_options_defaults.py
+++ b/binarycpython/utils/grid_options_defaults.py
@@ -27,7 +27,7 @@ grid_options_defaults_dict = {
     # binary_c files
     ##########################
     "binary_c_executable": os.path.join(
-        os.environ["BINARY_C"], "binary_c-config"
+        os.environ["BINARY_C"], "binary_c"
     ),  # TODO: make this more robust
     "binary_c_shared_library": os.path.join(
         os.environ["BINARY_C"], "src", "libbinary_c.so"
@@ -69,7 +69,9 @@ grid_options_defaults_dict = {
     "population_type": "grid",  #
     "population_type_options": [
         "grid",
-    ],  # Available choices for type of population generation # TODO: fill later with monte carlo, source file etc
+        "source_file",
+    ],  # Available choices for type of population generation # TODO: fill later with monte carlo etc
+    "source_file_filename": None # filename for the source
     "count": 0,  # total count of systems
     "probtot": 0,  # total probability
     "weight": 1.0,  # weighting for the probability
diff --git a/tests/core/test_persistent_data.py b/tests/core/test_persistent_data.py
index 4ca955cccd0b3882d20a7f49f463225627b0389e..e5b4e251eccf42baedcaae3281fc2d8ab73fa36b 100644
--- a/tests/core/test_persistent_data.py
+++ b/tests/core/test_persistent_data.py
@@ -65,6 +65,8 @@ def test_return_persistent_data_memaddr():
     print("Binary_c output:")
     print(textwrap.indent(str(output), "\t"))
 
+    assert isinstance(output, int), "memory adress has to be an integer"
+    assert output != 0, "memory adress seems not to have a correct value"
 
 def test_passing_persistent_data_to_run_system():
     # Function to test the passing of the persistent data memoery adress, and having ensemble_defer = True
@@ -286,6 +288,12 @@ def test_adding_ensemble_output():
     and output on the second run
     """
 
+    #
+    # print(json.dumps(test_1_merged_dict, indent=4))
+    # print(json.dumps(test_2_json, indent=4))
+
+
+
     #
     assert inspect_dict(test_1_merged_dict, print_structure=False) == inspect_dict(
         test_2_json, print_structure=False
@@ -293,7 +301,7 @@ def test_adding_ensemble_output():
     # assert inspect_dict(test_1_merged_dict, print_structure=False) == inspect_dict(test_3_json, print_structure=False), assert_message_2
 
 
-def combine_with_empty_json():
+def test_combine_with_empty_json():
     argstring_1 = return_argstring(defer_ensemble=0)
     output_1 = binary_c_python_api.run_system(argstring=argstring_1)
     ensemble_jsons_1 = [
@@ -351,12 +359,20 @@ def test_free_and_json_output():
     # ensemble_jsons_1 = [line for line in output_1.splitlines() if line.startswith("ENSEMBLE_JSON")]
     # json_1 = json.loads(ensemble_jsons_1[0][len("ENSEMBLE_JSON "):], cls=binarycDecoder)
 
+def test_all():
+    test_return_persistent_data_memaddr()
+    test_passing_persistent_data_to_run_system()
+    test_full_ensemble_output()
+    test_adding_ensemble_output()
+    test_free_and_json_output()
+    test_combine_with_empty_json()
 
 ####
 if __name__ == "__main__":
     # test_return_persistent_data_memaddr()
     # test_passing_persistent_data_to_run_system()
     # test_full_ensemble_output()
-    # test_adding_ensemble_output()
-    test_free_and_json_output()
-    # combine_with_empty_json()
+    test_adding_ensemble_output()
+    # test_free_and_json_output()
+    # test_combine_with_empty_json()
+    print("Done")