diff --git a/binarycpython/utils/custom_logging_functions.py b/binarycpython/utils/custom_logging_functions.py
index 763b4f143732ab161643c0d6b5a012d596d3513b..18cad734f9385de3ba0addaa97bc04b2471704eb 100644
--- a/binarycpython/utils/custom_logging_functions.py
+++ b/binarycpython/utils/custom_logging_functions.py
@@ -1,9 +1,13 @@
+"""
+Module containing functions for the custom logging functionality.
+The functions here make it possible for the user to define binaryc output logs on runtime
+"""
+
 import os
 import textwrap
 import subprocess
 import socket
 import ctypes
-import random
 import uuid
 
 from binarycpython.utils.functions import temp_dir, remove_file
@@ -11,24 +15,23 @@ from binarycpython.utils.functions import temp_dir, remove_file
 
 def autogen_C_logging_code(logging_dict, verbose=0):
     """
-    Function that autogenerates PRINTF statements for binaryc. 
-    Input is a dictionary where the key is the header of that logging line and items which are lists of parameters
-    that will be put in that logging line
+    Function that autogenerates PRINTF statements for binaryc.
+    Input is a dictionary where the key is the header of that logging line
+    and items which are lists of parameters that will be put in that logging line
 
     Example::
-
-        {'MY_STELLAR_DATA': 
-            [
-                'model.time',
-                'star[0].mass',
-                'model.probability',
-                'model.dt'
-            ]
-        }
+    {'MY_STELLAR_DATA':
+        [
+            'model.time',
+            'star[0].mass',
+            'model.probability',
+            'model.dt'
+        ]
+    }
     """
 
     # Check if the input is of the correct form
-    if not type(logging_dict) == dict:
+    if not isinstance(logging_dict, dict):
         print("Error: please use a dictionary as input")
         return None
 
@@ -44,7 +47,7 @@ def autogen_C_logging_code(logging_dict, verbose=0):
         logging_dict_entry = logging_dict[key]
 
         # Check if item is of correct type:
-        if type(logging_dict_entry) == list:
+        if isinstance(logging_dict_entry, list):
 
             # Construct print statement
             code += 'Printf("{}'.format(key)
@@ -119,8 +122,8 @@ def binary_c_write_log_code(code, filename, verbose=0):
         print("Writing the custom logging code to {}".format(filePath))
 
     # Write again
-    with open(filePath, "w") as f:
-        f.write(code)
+    with open(filePath, "w") as file:
+        file.write(code)
 
 
 def from_binary_c_config(config_file, flag):
@@ -165,7 +168,6 @@ def return_compilation_dict(verbose=0):
         # TODO: build in check to see whether the file exists
     else:
         raise NameError("Envvar BINARY_C doesnt exist")
-        return None
 
     # TODO: make more options for the compiling
     cc = from_binary_c_config(BINARY_C_CONFIG, "cc")
@@ -195,14 +197,15 @@ def return_compilation_dict(verbose=0):
         "ld": "ld",  # 'ld': $Config{ld}, # default linker
         "debug": 0,
         "inc": "{} -I{}".format(bincincdirs, BINARY_C_SRC_DIR),
-        # inc => ' '.($Config{inc}//' ').' '.$bincincdirs." -I$srcdir ", # include the defaults plus # GSL and binary_c
+        # inc => ' '.($Config{inc}//' ').' '.$bincincdirs." -I$srcdir ",
+        #   include the defaults plus # GSL and binary_c
         # 'libname': libname, # libname is usually just binary_c corresponding to libbinary_c.so
         "libs": binclibs,
     }
 
     # set values with defaults. TODO: make other input possile.
     ld = defaults["ld"]
-    debug = defaults["debug"]
+    # debug = defaults["debug"]
     inc = defaults[
         "inc"
     ]  # = ($ENV{BINARY_GRID2_INC} // $defaults{inc}).' '.($ENV{BINARY_GRID2_EXTRAINC} // '');
@@ -211,7 +214,8 @@ def return_compilation_dict(verbose=0):
     ]  # = ($ENV{BINARY_GRID2_LIBS} // $defaults{libs}).' '.($ENV{BINARY_GRID2_EXTRALIBS}//'');
     ccflags = defaults[
         "ccflags"
-    ]  #  = $ENV{BINARY_GRID2_CCFLAGS} // ($defaults{ccflags}) . ($ENV{BINARY_GRID2_EXTRACCFLAGS} // '');
+    ]  #  = $ENV{BINARY_GRID2_CCFLAGS}
+       # // ($defaults{ccflags}) . ($ENV{BINARY_GRID2_EXTRACCFLAGS} // '');
 
     # you must define _SEARCH_H to prevent it being loaded twice
     ccflags += " -shared -D_SEARCH_H"
@@ -240,7 +244,6 @@ def return_compilation_dict(verbose=0):
 def compile_shared_lib(code, sourcefile_name, outfile_name, verbose=0):
     """
     Function to write the custom logging code to a file and then compile it.
-   
     TODO: nicely put in the -fPIC
     """
 
@@ -289,7 +292,7 @@ def compile_shared_lib(code, sourcefile_name, outfile_name, verbose=0):
 
 def create_and_load_logging_function(custom_logging_code, verbose=0):
     """
-    Function to automatically compile the shared library with the given 
+    Function to automatically compile the shared library with the given
     custom logging code and load it with ctypes
 
     returns:
@@ -328,7 +331,8 @@ def create_and_load_logging_function(custom_logging_code, verbose=0):
 
     if verbose > 0:
         print(
-            "loaded shared library for custom logging. custom_output_function is loaded in memory at {}".format(
+            "loaded shared library for custom logging. \
+            custom_output_function is loaded in memory at {}".format(
                 func_memaddr
             )
         )
diff --git a/binarycpython/utils/distribution_functions.py b/binarycpython/utils/distribution_functions.py
index f5f73e04e5360837a5d041e17cf66e2ff6e60b74..409c651fd08af96471e5a87e3fc8acb4926393c4 100644
--- a/binarycpython/utils/distribution_functions.py
+++ b/binarycpython/utils/distribution_functions.py
@@ -1,5 +1,16 @@
+"""
+Module containing the predefined distribution functions
+
+The user can use any of these distribution functions to
+generate probability distributions for sampling populations
+"""
+
+
 import math
-import binarycpython.utils.useful_funcs
+
+from binarycpython.utils.useful_funcs import (
+    calc_period_from_sep,
+)
 
 ###
 # File containing probability distributions
@@ -11,12 +22,11 @@ import binarycpython.utils.useful_funcs
 # TODO: make global constants stuff
 # TODO: make description of module submodule
 
-log_ln_converter = 1.0 / math.log(10.0)
+LOG_LN_CONVERTER = 1.0 / math.log(10.0)
 
-
-def flat(parameter):
+def flat():
     """
-    Dummt distribution function that returns 1
+    Dummy distribution function that returns 1
     """
 
     return 1
@@ -26,6 +36,7 @@ def number(value):
     """
     Dummy distribution function that returns the input
     """
+
     return value
 
 
@@ -59,21 +70,25 @@ def powerlaw(min_val, max_val, k, x):
         print("input value is out of bounds!")
         return 0
 
-    else:
-        const = powerlaw_constant(min_val, max_val, k)
+    powerlaw_const = powerlaw_constant(min_val, max_val, k)
 
-        # powerlaw
-        y = const * (x ** k)
-        # print(
-        #     "Power law from {} to {}: const = {}, y = {}".format(
-        #         min_val, max_val, const, y
-        #     )
-        # )
-        return y
+    # powerlaw
+    prob = powerlaw_const * (x ** k)
+    # print(
+    #     "Power law from {} to {}: const = {}, y = {}".format(
+    #         min_val, max_val, const, y
+    #     )
+    # )
+    return prob
 
 
 def calculate_constants_three_part_powerlaw(m0, m1, m2, m_max, p1, p2, p3):
-    # print("Initialising constants for the three-part powerlaw: m0={} m1={} m2={} m_max={} p1={} p2={} p3={}\n".format(m0, m1, m2, m_max, p1, p2, p3))
+    """
+    Function to calculate the constants for a three-part powerlaw
+    """
+
+    # print("Initialising constants for the three-part powerlaw: m0={} m1={} m2={}\
+    # m_max={} p1={} p2={} p3={}\n".format(m0, m1, m2, m_max, p1, p2, p3))
 
     array_constants_three_part_powerlaw = [0, 0, 0]
 
@@ -130,17 +145,17 @@ def three_part_powerlaw(M, M0, M1, M2, M_MAX, P1, P2, P3):
 
     #
     if M < M0:
-        p = 0  # Below lower bound
+        prob = 0  # Below lower bound
     elif M0 < M <= M1:
-        p = three_part_powerlaw_constants[0] * (M ** P1)  # Between M0 and M1
+        prob = three_part_powerlaw_constants[0] * (M ** P1)  # Between M0 and M1
     elif M1 < M <= M2:
-        p = three_part_powerlaw_constants[1] * (M ** P2)  # Between M1 and M2
+        prob = three_part_powerlaw_constants[1] * (M ** P2)  # Between M1 and M2
     elif M2 < M <= M_MAX:
-        p = three_part_powerlaw_constants[2] * (M ** P3)  # Between M2 and M_MAX
+        prob = three_part_powerlaw_constants[2] * (M ** P3)  # Between M2 and M_MAX
     else:
-        p = 0  # Above M_MAX
+        prob = 0  # Above M_MAX
 
-    return p
+    return prob
 
 
 def const(min_bound, max_bound, val=None):
@@ -149,12 +164,12 @@ def const(min_bound, max_bound, val=None):
     """
 
     if val:
-        if not (min_bound < val <= max_bound):
+        if not min_bound < val <= max_bound:
             print("out of bounds")
-            p = 0
-            return p
-    p = 1.0 / (min_bound - max_bound)
-    return p
+            prob = 0
+            return prob
+    prob = 1.0 / (min_bound - max_bound)
+    return prob
 
 
 def set_opts(opts, newopts):
@@ -168,29 +183,29 @@ def set_opts(opts, newopts):
     if newopts:
         for opt in newopts.keys():
             if opt in opts.keys():
-                opts[key] = newopts[key]
+                opts[opt] = newopts[opt]
 
-    return opt
+    return opts
 
 
 def gaussian(x, mean, sigma, gmin, gmax):
     """
     Gaussian distribution function. used for e..g Duquennoy + Mayor 1991
-    
+
     Input: location, mean, sigma, min and max:
     """
     # # location (X value), mean and sigma, min and max range
     # my ($x,$mean,$sigma,$gmin,$gmax) = @_;
 
     if (x < gmin) or (x > gmax):
-        p = 0
+        prob = 0
     else:
         # normalize over given range
         # TODO: add loading into global var
         normalisation = gaussian_normalizing_const(mean, sigma, gmin, gmax)
-        p = normalisation * gaussian_func(x, mean, sigma)
+        prob = normalisation * gaussian_func(x, mean, sigma)
 
-    return p
+    return prob
 
 
 def gaussian_normalizing_const(mean, sigma, gmin, gmax):
@@ -215,11 +230,11 @@ def gaussian_func(x, mean, sigma):
     """
     Function to evaluate a gaussian at a given point
     """
-    GAUSSIAN_PREFACTOR = 1.0 / math.sqrt(2.0 * math.pi)
+    gaussian_prefactor = 1.0 / math.sqrt(2.0 * math.pi)
 
     r = 1.0 / (sigma)
     y = (x - mean) * r
-    return GAUSSIAN_PREFACTOR * r * math.exp(-0.5 * y ** 2)
+    return gaussian_prefactor * r * math.exp(-0.5 * y ** 2)
 
 
 #####
@@ -229,9 +244,9 @@ def gaussian_func(x, mean, sigma):
 
 def Kroupa2001(m, newopts=None):
     """
-    Probability distribution function for kroupa 2001 IMF 
+    Probability distribution function for kroupa 2001 IMF
 
-    Input: Mass, (and optional: dict of new options. Input the  
+    Input: Mass, (and optional: dict of new options. Input the
         default = {'m0':0.1, 'm1':0.5, 'm2':1, 'mmax':100, 'p1':-1.3, 'p2':-2.3, 'p3':-2.3}
     """
 
@@ -245,9 +260,12 @@ def Kroupa2001(m, newopts=None):
         "p2": -2.3,
         "p3": -2.3,
     }
+
     value_dict = default.copy()
+
     if newopts:
         value_dict.update(newopts)
+
     return three_part_powerlaw(
         m,
         value_dict["m0"],
@@ -291,7 +309,9 @@ def ktg93(m, newopts):
     # }
 
     # set options
-    # opts = set_opts({'m0':0.1, 'm1':0.5, 'm2':1.0, 'mmax':80, 'p1':-1.3, 'p2':-2.2, 'p3':-2.7}, newopts)
+    # opts = set_opts({'m0':0.1, 'm1':0.5, 'm2':1.0, 'mmax':80, 'p1':-1.3, 'p2':-2.2, 'p3':-2.7},
+    # newopts)
+
     defaults = {
         "m0": 0.1,
         "m1": 0.5,
@@ -301,9 +321,11 @@ def ktg93(m, newopts):
         "p2": -2.2,
         "p3": -2.7,
     }
-    value_dict = default.copy()
+    value_dict = defaults.copy()
+
     if newopts:
         value_dict.update(newopts)
+
     return three_part_powerlaw(
         m,
         value_dict["m0"],
@@ -348,34 +370,36 @@ def imf_scalo1998(m):
 
 def imf_chabrier2003(m):
     """
-    # IMF of Chabrier 2003 PASP 115:763-795    
+    IMF of Chabrier 2003 PASP 115:763-795
     """
-    Chabrier_logmc = math.log10(0.079)
-    Chabrier_sigma2 = 0.69 * 0.69
-    Chabrier_A1 = 0.158
-    Chabrier_A2 = 4.43e-2
-    Chabrier_x = -1.3
+    chabrier_logmc = math.log10(0.079)
+    chabrier_sigma2 = 0.69 * 0.69
+    chabrier_a1 = 0.158
+    chabrier_a2 = 4.43e-2
+    chabrier_x = -1.3
     if m < 0:
         print("below bounds")
         raise ValueError
     if 0 < m < 1.0:
         A = 0.158
-        dm = math.log10(m) - Chabrier_logmc
-        p = Chabrier_A1 * math.exp(-(dm ** 2) / (2.0 * Chabrier_sigma2))
+        dm = math.log10(m) - chabrier_logmc
+        prob = chabrier_a1 * math.exp(-(dm ** 2) / (2.0 * chabrier_sigma2))
     else:
-        p = Chabrier_A2 * (m ** Chabrier_x)
-    p = p / (0.1202462 * m * math.log(10))
-    return p
+        prob = chabrier_a2 * (m ** chabrier_x)
+    prob = prob / (0.1202462 * m * math.log(10))
+    return prob
 
 
 ########################################################################
 # Binary fractions
 ########################################################################
 def Arenou2010_binary_fraction(m):
-    # Arenou 2010 function for the binary fraction as f(M1)
-    #
-    # GAIA-C2-SP-OPM-FA-054
-    # www.rssd.esa.int/doc_fetch.php?id=2969346
+    """
+    Arenou 2010 function for the binary fraction as f(M1)
+
+    GAIA-C2-SP-OPM-FA-054
+    www.rssd.esa.int/doc_fetch.php?id=2969346
+    """
 
     return 0.8388 * math.tanh(0.688 * m + 0.079)
 
@@ -385,14 +409,14 @@ def Arenou2010_binary_fraction(m):
 
 def raghavan2010_binary_fraction(m):
     """
-    Fit to the Raghavan 2010 binary fraction as a function of   
+    Fit to the Raghavan 2010 binary fraction as a function of
     spectral type (Fig 12). Valid for local stars (Z=Zsolar).
-    
-    The spectral type is converted  mass by use of the ZAMS 
+
+    The spectral type is converted  mass by use of the ZAMS
     effective temperatures from binary_c/BSE (at Z=0.02)
     and the new "long_spectral_type" function of binary_c
     (based on Jaschek+Jaschek's Teff-spectral type table).
-    
+
     Rob then fitted the result
     """
 
@@ -422,10 +446,10 @@ def duquennoy1991(x):
     return gaussian(x, 4.8, 2.3, -2, 12)
 
 
-def sana12(M1, M2, a, P, amin, amax, x0, x1, p):  # TODO: ? wtf. vague input
+def sana12(M1, M2, a, P, amin, amax, x0, x1, p): 
     """
     distribution of initial orbital periods as found by Sana et al. (2012)
-    which is a flat distribution in ln(a) and ln(P) respectively for stars 
+    which is a flat distribution in ln(a) and ln(P) respectively for stars
     * less massive than 15Msun (no O-stars)
     * mass ratio q=M2/M1<0.1
     * log(P)<0.15=x0 and log(P)>3.5=x1
@@ -434,6 +458,9 @@ def sana12(M1, M2, a, P, amin, amax, x0, x1, p):  # TODO: ? wtf. vague input
     arguments are M1, M2, a, Period P, amin, amax, x0=log P0, x1=log P1, p
 
     example args: 10, 5, ?, P, ?, ?, -2, 12, -0.55
+
+    # TODO: ? wtf. vague input
+    # TODO: Fix this function!
     """
 
     res = 0
@@ -443,11 +470,12 @@ def sana12(M1, M2, a, P, amin, amax, x0, x1, p):  # TODO: ? wtf. vague input
     else:
         p1 = 1.0 + p
 
-        # For more details see the LyX document of binary_c for this distribution where the variables and normalizations are given
+        # For more details see the LyX document of binary_c for this distribution
+        # where the variables and normalizations are given
         # we use the notation x=log(P), xmin=log(Pmin), x0=log(P0), ... to determine the
-        x = log_ln_converter * math.log(p)
-        xmin = log_ln_converter * math.log(calc_period_from_sep(m1, m2, amin))
-        xmin = log_ln_converter * math.log(calc_period_from_sep(m1, m2, amax))
+        x = LOG_LN_CONVERTER * math.log(p)
+        xmin = LOG_LN_CONVERTER * math.log(calc_period_from_sep(M1, M2, amin))
+        xmax = LOG_LN_CONVERTER * math.log(calc_period_from_sep(M1, M2, amax))
 
         # my $x0 = 0.15;
         # my $x1 = 3.5;
@@ -459,11 +487,11 @@ def sana12(M1, M2, a, P, amin, amax, x0, x1, p):  # TODO: ? wtf. vague input
         A2 = A1 * x1 ** p
 
         if x < x0:
-            res = 3.0 / 2.0 * log_ln_converter * A0
+            res = 3.0 / 2.0 * LOG_LN_CONVERTER * A0
         elif x > x1:
-            res = 3.0 / 2.0 * log_ln_converter * A2
+            res = 3.0 / 2.0 * LOG_LN_CONVERTER * A2
         else:
-            res = 3.0 / 2.0 * log_ln_converter * A1 * x ** p
+            res = 3.0 / 2.0 * LOG_LN_CONVERTER * A1 * x ** p
 
     return res
 
@@ -477,9 +505,11 @@ def sana12(M1, M2, a, P, amin, amax, x0, x1, p):  # TODO: ? wtf. vague input
 
 def flatsections(x, opts):
     """
-    
-    opts = list of dicts with settings for the flat sections
+    Function to generate flat distributions, possibly in multiple sections
+
+    opts: list of dicts with settings for the flat sections
     x: location to calculate the y value
+
     TODO: figure out why it has to be a list of dict. why not just 1
     """
 
@@ -488,7 +518,8 @@ def flatsections(x, opts):
 
     for opt in opts:
         dc = (opt["max"] - opt["min"]) * opt["height"]
-        # print("added flatsection ({}-{})*{} = {}\n".format(opt['max'], opt['min'], opt['height'], dc))
+        # print("added flatsection ({}-{})*{} = {}\n".format(
+        #   opt['max'], opt['min'], opt['height'], dc))
         c += dc
         if opt["min"] <= x <= opt["max"]:
             y = opt["height"]
diff --git a/binarycpython/utils/functions.py b/binarycpython/utils/functions.py
index 516235312a79cffe5d4a9255af09056a2214c230..1d06b1660d62780d66b4c579d83ccb5682b634b5 100644
--- a/binarycpython/utils/functions.py
+++ b/binarycpython/utils/functions.py
@@ -1,12 +1,18 @@
-import copy
+"""
+Module containing most of the utility functions for the binarycpython package
+
+Functions here are mostly functions used in other classes/functions, or
+useful functions for the user
+"""
+
 import json
 import os
-import h5py
 import tempfile
-
 from collections import defaultdict
 
+import h5py
 import numpy as np
+
 import binary_c_python_api
 
 
@@ -29,7 +35,8 @@ def remove_file(file, verbose=0):
 
 def temp_dir():
     """
-    Function to return the path the custom logging library shared object and script will be written to.
+    Function to return the path the custom logging library shared object
+    and script will be written to.
 
     Makes use of os.makedirs exist_ok which requires python 3.2+
     """
@@ -45,104 +52,108 @@ def temp_dir():
 
 def output_lines(output):
     """
-    Function that outputs the lines that were recieved from the binary_c run. 
+    Function that outputs the lines that were recieved from the binary_c run.
     """
     return output.splitlines()
 
 
 def parse_binary_c_version_info(version_info_string):
+    """
+    Function that parses the binary_c version info. Length function with a lot of branches
+    """
+
     version_info_dict = {}
 
-    for el in version_info_string.splitlines():
-        el = el.strip()
-        if el == "":
+    for line in version_info_string.splitlines():
+        line = line.strip()
+        if line == "":
             continue
-        if " is " in el:
-            split = el.split(" is ")
+        if " is " in line:
+            split = line.split(" is ")
             version_info_dict[split[0].strip()] = split[1].strip()
         else:
-            if el.startswith("Binary_c/nucsyn"):
-                version_info_dict["intro"] = el
-            elif el.startswith("Email"):
-                emails = el.split("Email ")[1].split(",")
+            if line.startswith("Binary_c/nucsyn"):
+                version_info_dict["intro"] = line
+            elif line.startswith("Email"):
+                emails = line.split("Email ")[1].split(",")
                 cleaned_emails = [email.strip() for email in emails]
                 version_info_dict["emails"] = cleaned_emails
-            elif el.startswith("DTlimit"):
-                split = el.split(" : ")
+            elif line.startswith("DTlimit"):
+                split = line.split(" : ")
                 version_info_dict[split[0]] = ": ".join(split[1:])
-            elif el.startswith("Version"):
-                split = el.split("Version ")
+            elif line.startswith("Version"):
+                split = line.split("Version ")
                 version_number = split[1]
                 version_info_dict["version_number"] = version_number
-            elif el.startswith("git URL"):
-                split = el.split("git URL ")
+            elif line.startswith("git URL"):
+                split = line.split("git URL ")
                 git_url = split[1]
                 version_info_dict["git_url"] = git_url
-            elif el.startswith("Build: "):
-                split = el.split("Build: ")
+            elif line.startswith("Build: "):
+                split = line.split("Build: ")
                 build = split[1]
                 version_info_dict["build"] = build
-            elif el.startswith("Compiled for "):
-                split = el.split("Compiled for ")
+            elif line.startswith("Compiled for "):
+                split = line.split("Compiled for ")
                 compiled_for = split[1]
                 version_info_dict["compiled_for"] = compiled_for
-            elif el.startswith("Stack limit "):
-                split = el.split("Stack limit ")
+            elif line.startswith("Stack limit "):
+                split = line.split("Stack limit ")
                 stack_limit = split[1]
                 version_info_dict["stack_limit"] = stack_limit
-            elif el.startswith("SVN URL "):
-                split = el.split("SVN URL ")
+            elif line.startswith("SVN URL "):
+                split = line.split("SVN URL ")
                 svn_url = split[1]
                 version_info_dict["svn_url"] = svn_url
-            elif el.startswith("git branch "):
-                split = el.split("git branch ")
+            elif line.startswith("git branch "):
+                split = line.split("git branch ")
                 git_branch = split[1]
                 version_info_dict["git_branch"] = git_branch
-            elif el.startswith("_SC_CLK_TCK"):
-                split = el.split(" = ")
+            elif line.startswith("_SC_CLK_TCK"):
+                split = line.split(" = ")
                 _SC_CLK_TCK = split[1]
                 version_info_dict["_SC_CLK_TCK"] = _SC_CLK_TCK
-            elif el.startswith("Random number mean "):
-                split = el.split("Random number mean ")
+            elif line.startswith("Random number mean "):
+                split = line.split("Random number mean ")
                 random_number_mean = split[1]
                 version_info_dict["Random number mean"] = random_number_mean
-            elif el.startswith("SVN revision "):
-                split = el.split("SVN revision ")
+            elif line.startswith("SVN revision "):
+                split = line.split("SVN revision ")
                 svn_revision = split[1]
                 version_info_dict["svn_revision"] = svn_revision
-            elif el.startswith("Size of :"):
-                split = el.split("Size of :")
+            elif line.startswith("Size of :"):
+                split = line.split("Size of :")
                 data_type_sizes = split[1]
                 version_info_dict["data_type_sizes"] = data_type_sizes
-            elif el.startswith("git revision "):
-                split = el.split("git revision ")
+            elif line.startswith("git revision "):
+                split = line.split("git revision ")
                 git_revision = split[1]
                 version_info_dict["git_revision"] = git_revision
-            elif el.startswith("BINARY_C_PRE_VERSION "):
-                split = el.split("BINARY_C_PRE_VERSION ")
+            elif line.startswith("BINARY_C_PRE_VERSION "):
+                split = line.split("BINARY_C_PRE_VERSION ")
                 binary_c_pre_version = split[1]
                 version_info_dict["binary_c_pre_version"] = binary_c_pre_version
-            elif el.startswith("Comenv accretion:"):
-                split = el.split("Comenv accretion:")
+            elif line.startswith("Comenv accretion:"):
+                split = line.split("Comenv accretion:")
                 comenv_accretion = split[1]
                 version_info_dict["comenv_accretion"] = comenv_accretion
-            elif el.startswith("Compiled in parameters:"):
-                split = el.split("Compiled in parameters:")
+            elif line.startswith("Compiled in parameters:"):
+                split = line.split("Compiled in parameters:")
                 compiled_in_parameters = split[1]
                 version_info_dict["compiled_in_parameters"] = compiled_in_parameters
-            elif el.startswith("__short__ is"):
-                split = el.split("__short__ is")
+            elif line.startswith("__short__ is"):
+                split = line.split("__short__ is")
                 short_type = split[1]
                 version_info_dict["short_type"] = short_type
             else:
-                print("Still found unmatched items!:\n{}".format(repr(el)))
+                print("Still found unmatched items!:\n{}".format(repr(line)))
 
     return version_info_dict
 
 
 def create_hdf5(data_dir, name):
     """
-    Function to create an hdf5 file from the contents of a directory: 
+    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
 
@@ -153,7 +164,7 @@ def create_hdf5(data_dir, name):
     # Create the file
     hdf5_filename = os.path.join(data_dir, "{}".format(name))
     print("Creating {}".format(hdf5_filename))
-    f = h5py.File(hdf5_filename, "w")
+    hdf5_file = h5py.File(hdf5_filename, "w")
 
     # Get content of data_dir
     content_data_dir = os.listdir(data_dir)
@@ -170,7 +181,7 @@ def create_hdf5(data_dir, name):
             settings_json = json.load(settings_file)
 
         # Create settings group
-        settings_grp = f.create_group("settings")
+        settings_grp = hdf5_file.create_group("settings")
 
         # Write version_string to settings_group
         settings_grp.create_dataset("used_settings", data=json.dumps(settings_json))
@@ -181,7 +192,7 @@ def create_hdf5(data_dir, name):
         print("Adding data to HDF5 file")
 
         # Create the data group
-        data_grp = f.create_group("data")
+        data_grp = hdf5_file.create_group("data")
 
         # Write the data to the file:
         # Make sure:
@@ -201,12 +212,13 @@ def create_hdf5(data_dir, name):
             data = np.loadtxt(full_path, skiprows=1)
             data_grp.create_dataset(base_name, data=data)
 
-        f.close()
+        hdf5_file.close()
 
 
-def get_help_super(print_help=False, return_dict=True, fail_silently=True):
+def get_help_super(print_help=False, 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.
+    Function that first runs get_help_all, and then per argument also run
+    the help function to get as much information as possible.
     """
 
     # Get help_all information
@@ -215,7 +227,7 @@ def get_help_super(print_help=False, return_dict=True, fail_silently=True):
     help_all_super_dict = help_all_dict.copy()
 
     # Loop over all sections and stuff
-    for section_name in help_all_dict.keys():
+    for section_name in help_all_dict:
         section = help_all_dict[section_name]
 
         for parameter_name in section["parameters"].keys():
@@ -251,17 +263,15 @@ def get_help_super(print_help=False, return_dict=True, fail_silently=True):
     if print_help:
         # TODO: make a pretty print
         print(json.dumps(help_all_super_dict, indent=4))
-        pass
 
-    if return_dict:
-        return help_all_super_dict
+    return help_all_super_dict
 
 
-def get_help_all(print_help=True, return_dict=False):
+def get_help_all(print_help=True):
     """
     Function that reads out the output of the help_all api call to binary_c
 
-    prints all the parameters and their descriptions.
+    print_help: bool, prints all the parameters and their descriptions.
 
     return_dict:  returns a dictionary
     """
@@ -303,10 +313,11 @@ def get_help_all(print_help=True, return_dict=False):
             split_params = params[0].strip().replace("\n ", " ").split("\n")
 
             # Process params and descriptions per section
-            for el in split_params:
-                split_param_info = el.split(" : ")
+            for split_param in split_params:
+                split_param_info = split_param.split(" : ")
                 if not len(split_param_info) == 3:
-                    # there are ocassions where the semicolon is used in the description text itself.
+                    # there are ocassions where the semicolon
+                    # is used in the description text itself.
                     if len(split_param_info) == 4:
                         split_param_info = [
                             split_param_info[0],
@@ -353,16 +364,14 @@ def get_help_all(print_help=True, return_dict=False):
                     )
                 )
 
-    # Loop over all the parameters an call the help() function on it. Takes a long time but this is for testing
+    # # Loop over all the parameters an call the help() function on it.
+    # # Takes a long time but this is for testing
     # for section in help_all_dict.keys():
     #     section_dict = help_all_dict[section]
     #     for param in section_dict['parameters'].keys():
     #         get_help(param)
 
-    if return_dict:
-        return help_all_dict
-    else:
-        return None
+    return help_all_dict
 
 
 def filter_arg_dict(arg_dict):
@@ -383,13 +392,13 @@ def filter_arg_dict(arg_dict):
 
 def create_arg_string(arg_dict, sort=False, filter_values=False):
     """
-    Function that creates the arg string
+    Function that creates the arg string for binary_c.
 
     Options:
-        sort: sort the order of the keys
-        filter_values: filters the input dict on keys that have NULL or `function` as value 
-
+        sort: sort the order of the keys.
+        filter_values: filters the input dict on keys that have NULL or `function` as value.
     """
+
     arg_string = ""
 
     if filter_values:
@@ -404,9 +413,10 @@ def create_arg_string(arg_dict, sort=False, filter_values=False):
 
 def get_defaults(filter_values=False):
     """
-    Function that calls the binaryc get args function and cast it into a dictionary
+    Function that calls the binaryc get args function and cast it into a dictionary.
+
     All the values are strings
-    
+
     filter_values: whether to filter out NULL and Function defaults.
     """
 
@@ -432,18 +442,18 @@ def get_arg_keys():
     return get_defaults().keys()
 
 
-def get_help(param_name="", print_help=True, return_dict=False, fail_silently=False):
+def get_help(param_name="", print_help=True, fail_silently=False):
     """
-    Function that returns the help info for a given parameter. 
+    Function that returns the help info for a given parameter.
 
     Binary_c will output things in the following order;
     - Did you mean?
     - binary_c help for variable
-    - default 
+    - default
     - available macros
 
     This function reads out that structure and catches the different components of this output
-    
+
     Will print a dict
 
     return_dict: wether to return the help info dictionary
@@ -459,76 +469,76 @@ def get_help(param_name="", print_help=True, return_dict=False, fail_silently=Fa
             )
         )
         return None
-    else:
-        if param_name in available_arg_keys:
-            help_info = binary_c_python_api.return_help(param_name)
-            cleaned = [el for el in help_info.split("\n") if not el == ""]
-
-            # Get line numbers
-            did_you_mean_nr = [
-                i for i, el in enumerate(cleaned) if el.startswith("Did you mean")
-            ]
-            parameter_line_nr = [
-                i for i, el in enumerate(cleaned) if el.startswith("binary_c help")
-            ]
-            default_line_nr = [
-                i for i, el in enumerate(cleaned) if el.startswith("Default")
-            ]
-            macros_line_nr = [
-                i for i, el in enumerate(cleaned) if el.startswith("Available")
-            ]
-
-            help_info_dict = {}
-
-            # Get alternatives
-            if did_you_mean_nr:
-                alternatives = cleaned[did_you_mean_nr[0] + 1 : parameter_line_nr[0]]
-                alternatives = [el.strip() for el in alternatives]
-                help_info_dict["alternatives"] = alternatives
-
-            # Information about the parameter
-            parameter_line = cleaned[parameter_line_nr[0]]
-            parameter_name = parameter_line.split(":")[1].strip().split(" ")[0]
-            parameter_value_input_type = (
-                " ".join(parameter_line.split(":")[1].strip().split(" ")[1:])
-                .replace("<", "")
-                .replace(">", "")
-            )
 
-            help_info_dict["parameter_name"] = parameter_name
-            help_info_dict["parameter_value_input_type"] = parameter_value_input_type
+    if param_name in available_arg_keys:
+        help_info = binary_c_python_api.return_help(param_name)
+        cleaned = [el for el in help_info.split("\n") if not el == ""]
+
+        # Get line numbers
+        did_you_mean_nr = [
+            i for i, el in enumerate(cleaned) if el.startswith("Did you mean")
+        ]
+        parameter_line_nr = [
+            i for i, el in enumerate(cleaned) if el.startswith("binary_c help")
+        ]
+        default_line_nr = [
+            i for i, el in enumerate(cleaned) if el.startswith("Default")
+        ]
+        macros_line_nr = [
+            i for i, el in enumerate(cleaned) if el.startswith("Available")
+        ]
+
+        help_info_dict = {}
+
+        # Get alternatives
+        if did_you_mean_nr:
+            alternatives = cleaned[did_you_mean_nr[0] + 1 : parameter_line_nr[0]]
+            alternatives = [el.strip() for el in alternatives]
+            help_info_dict["alternatives"] = alternatives
+
+        # Information about the parameter
+        parameter_line = cleaned[parameter_line_nr[0]]
+        parameter_name = parameter_line.split(":")[1].strip().split(" ")[0]
+        parameter_value_input_type = (
+            " ".join(parameter_line.split(":")[1].strip().split(" ")[1:])
+            .replace("<", "")
+            .replace(">", "")
+        )
 
-            description_line = " ".join(
-                cleaned[parameter_line_nr[0] + 1 : default_line_nr[0]]
-            )
-            help_info_dict["description"] = description_line
+        help_info_dict["parameter_name"] = parameter_name
+        help_info_dict["parameter_value_input_type"] = parameter_value_input_type
 
-            # Default:
-            default_line = cleaned[default_line_nr[0]]
-            default_value = default_line.split(":")[-1].strip()
+        description_line = " ".join(
+            cleaned[parameter_line_nr[0] + 1 : default_line_nr[0]]
+        )
+        help_info_dict["description"] = description_line
 
-            help_info_dict["default"] = default_value
+        # Default:
+        default_line = cleaned[default_line_nr[0]]
+        default_value = default_line.split(":")[-1].strip()
 
-            # Get Macros:
-            if macros_line_nr:
-                macros = cleaned[macros_line_nr[0] + 1 :]
-                help_info_dict["macros"] = macros
+        help_info_dict["default"] = default_value
 
-            if print_help:
-                for key in help_info_dict.keys():
-                    print("{}:\n\t{}".format(key, help_info_dict[key]))
+        # Get Macros:
+        if macros_line_nr:
+            macros = cleaned[macros_line_nr[0] + 1 :]
+            help_info_dict["macros"] = macros
 
-            if return_dict:
-                return help_info_dict
+        if print_help:
+            for key in help_info_dict:
+                print("{}:\n\t{}".format(key, help_info_dict[key]))
 
-        else:
-            if not fail_silently:
-                print(
-                    "{} is not a valid parameter name. Please choose from the following parameters:\n\t{}".format(
-                        param_name, list(available_arg_keys)
-                    )
+        return help_info_dict
+
+    else:
+        if not fail_silently:
+            print(
+                "{} is not a valid parameter name. Please choose from the \
+                following parameters:\n\t{}".format(
+                    param_name, list(available_arg_keys)
                 )
-            return None
+            )
+        return None
 
 
 def parse_output(output, selected_header):
@@ -539,17 +549,16 @@ def parse_output(output, selected_header):
     if the caught line contains output like 'example_header time=12.32 mass=0.94 ..'
     or if the line contains output like 'example_header 12.32 0.94'
 
-    You can give a 'selected_header' to catch any line that starts with that. 
+    You can give a 'selected_header' to catch any line that starts with that.
     Then the values will be put into a dictionary.
-    
+
     TODO: Think about exporting to numpy array or pandas instead of a defaultdict
     """
 
     value_dicts = []
-    val_lists = []
 
     # split output on newlines
-    for i, line in enumerate(output.split("\n")):
+    for line in output.split("\n"):
         # Skip any blank lines
         if not line == "":
             split_line = line.split()
@@ -563,20 +572,21 @@ def parse_output(output, selected_header):
             if header == selected_header:
                 # Check if the line contains '=' symbols:
                 value_dict = {}
-                if all("=" in el for el in values_list):
-                    for el in values_list:
-                        key, val = el.split("=")
+                if all("=" in value for value in values_list):
+                    for value in values_list:
+                        key, val = value.split("=")
                         value_dict[key.strip()] = val.strip()
                     value_dicts.append(value_dict)
                 else:
-                    if any("=" in el for el in values_list):
+                    if any("=" in value for value in values_list):
                         raise ValueError(
-                            "Caught line contains some = symbols but not all of them do. aborting run"
+                            "Caught line contains some = symbols but not \
+                            all of them do. aborting run"
                         )
-                    else:
-                        for i, val in enumerate(values_list):
-                            value_dict[i] = val
-                        value_dicts.append(value_dict)
+
+                    for j, val in enumerate(values_list):
+                        value_dict[j] = val
+                    value_dicts.append(value_dict)
 
     if len(value_dicts) == 0:
         print(
@@ -597,11 +607,11 @@ def parse_output(output, selected_header):
 
 def load_logfile(logfile):
     """
-    Function that parses the generated logfile of binary_c
+    Experimental function that parses the generated logfile of binary_c.
     """
 
-    with open(logfile, "r") as f:
-        logfile_data = f.readlines()
+    with open(logfile, "r") as file:
+        logfile_data = file.readlines()
 
     time_list = []
     m1_list = []
@@ -614,9 +624,9 @@ def load_logfile(logfile):
     rel_r2_list = []
     event_list = []
 
-    random_seed = logfile_data[0].split()[-2]
-    random_count = logfile_data[0].split()[-1]
-    probability = logfile_data[-1].split()
+    # random_seed = logfile_data[0].split()[-2]
+    # random_count = logfile_data[0].split()[-1]
+    # probability = logfile_data[-1].split()
 
     for line in logfile_data[1:-1]:
         split_line = line.split()
diff --git a/binarycpython/utils/grid.py b/binarycpython/utils/grid.py
index a7c75e57a655bacff09d0e59631911e3fa2a37af..190ff83d421817ea4bddfe9ad576fce3d85e429c 100644
--- a/binarycpython/utils/grid.py
+++ b/binarycpython/utils/grid.py
@@ -1,39 +1,44 @@
+"""
+Module containing the Population grid class object.
+
+Here all the functionality of a Population object is defined.
+
+Useful for the user to understand the functionality,
+but copying functionality isn't recommended except if you know what you are doing
+"""
+
 import os
 import copy
 import json
-import sys
 import datetime
 import time
-import random
-import inspect
+import argparse
+import importlib.util
 
-import numpy as np
-import multiprocessing as mp
+from pathos.helpers import mp as pathos_multiprocess
+# from pathos.multiprocessing import ProcessingPool as Pool
+from pathos.pools import _ProcessPool as Pool
 
-from pathos.multiprocessing import ProcessingPool as Pool
-
-import binary_c_python_api
-import binarycpython
 
 from binarycpython.utils.grid_options_defaults import grid_options_defaults_dict
 from binarycpython.utils.custom_logging_functions import (
     autogen_C_logging_code,
     binary_c_log_code,
     create_and_load_logging_function,
-    temp_dir,
 )
 from binarycpython.utils.functions import (
     get_defaults,
     parse_binary_c_version_info,
-    output_lines,
     remove_file,
     filter_arg_dict,
+    get_help_all,
 )
 
+import binary_c_python_api
+
 
 # Todo-list
 # TODO: add functionality to 'on-init' set arguments
-
 # 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
@@ -44,21 +49,29 @@ from binarycpython.utils.functions import (
 # TODO: change the grid_options dict structure so that there is room for descriptions
 # TODO: consider spreading the functions over more files.
 
-# 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
+# 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
+
 
+class Population():
+    """
+    Population Object. Contains all the necessary functions to set up, run and process a
+    population of systems
+    """
 
-class Population(object):
     def __init__(self):
         """
         Initialisation function of the population class
         """
 
         self.defaults = get_defaults()
+        self.cleaned_up_defaults = self.cleanup_defaults()
 
         # Different sections of options
         self.bse_options = (
             {}
-        )  # bse_options is just empty. Setting stuff will check against the defaults to see if the input is correct.
+        )   # bse_options is just empty.
+            # Setting stuff will check against the defaults to see if the input is correct.
         self.grid_options = grid_options_defaults_dict.copy()
         self.custom_options = {}
 
@@ -74,33 +87,40 @@ class Population(object):
 
     # General flow of generating the arguments for the binary_c call:
     # - user provides parameter and value via set (or manually but that is risky)
-    # - The parameter names of these input get compared to the parameter names in the self.defaults; with this, we know that its a valid
-    # parameter to give to binary_c.
+    # - The parameter names of these input get compared to the parameter names in the self.defaults;
+    #    with this, we know that its a valid parameter to give to binary_c.
     # - For a single system, the bse_options will be written as a arg line
-    # - For a population the bse_options will get copied to a temp_bse_options dict and updated with all the parameters generated by the grid
+    # - For a population the bse_options will get copied to a temp_bse_options dict and updated with
+    #   all the parameters generated by the grid
 
-    # I will NOT create the argument line by fully writing ALL the defaults and overriding user input, that seems not necessary
-    # because by using the get_defaults() function we already know for sure which parameter names are valid for the binary_c version
+    # I will NOT create the argument line by fully writing ALL the defaults and overriding user
+    # input, that seems not necessary because by using the get_defaults() function we already
+    # know for sure which parameter names are valid for the binary_c version
     # And because binary_c uses internal defaults, its not necessary to explicitly pass them.
-    # I do however suggest everyone to export the binary_c defaults to a file, so that you know exactly which values were the defaults.
-
-    # TODO: maybe make a set_bse option.
+    # I do however suggest everyone to export the binary_c defaults to a file, so that you know
+    # exactly which values were the defaults.
 
     def set_bse_option(self, key, arg):
+        """
+        Setter for the BSE options.
+        """
         self.bse_options[key] = arg
 
     def set(self, **kwargs):
         """
-        Function to set the values of the population. This is the preferred method to set values of functions, as it 
-        provides checks on the input. 
+        Function to set the values of the population. This is the preferred method to set values
+        of functions, as it provides checks on the input.
+
+        the bse_options will get populated with all the those that have a key that is present
+        in the self.defaults
+
+        the grid_options will get updated with all the those that have a key that is present
+        in the self.grid_options
 
-        the bse_options will get populated with all the those that have a key that is present in the self.defaults
-        the grid_options will get updated with all the those that have a key that is present in the self.grid_options
-        
         If neither of above is met; the key and the value get stored in a custom_options dict.
         """
 
-        for key in kwargs.keys():
+        for key in kwargs:
             # Filter out keys for the bse_options
             if key in self.defaults.keys():
                 if self.grid_options["verbose"] > 0:
@@ -115,20 +135,18 @@ class Population(object):
             # The of the keys go into a custom_options dict
             else:
                 print(
-                    "!! Key doesnt match previously known parameter: adding: {}={} to custom_options".format(
-                        key, kwargs[key]
-                    )
+                    "!! Key doesnt match previously known parameter: \
+                    adding: {}={} to custom_options".format(key, kwargs[key])
                 )
                 self.custom_options[key] = kwargs[key]
 
     def parse_cmdline(self):
         """
         Function to handle settings values via the command line:
+
         TODO: remove the need for --cmdline
         """
 
-        import argparse
-
         parser = argparse.ArgumentParser()
         parser.add_argument(
             "--cmdline",
@@ -179,57 +197,62 @@ class Population(object):
 
     def generate_population_arglines_file(self, output_file):
         """
-        Function to generate a file that contains all the argument lines that would be given to binary_c if the population had been run
+        Function to generate a file that contains all the argument lines that would be given to
+        binary_c if the population had been run
+
+        TODO: Fix this function
         """
 
         pass
 
     def add_grid_variable(
-        self,
-        name,
-        longname,
-        valuerange,
-        resolution,
-        spacingfunc,
-        probdist,
-        dphasevol,
-        parameter_name,
-        precode=None,
-        condition=None,
+            self,
+            name,
+            longname,
+            valuerange,
+            resolution,
+            spacingfunc,
+            probdist,
+            dphasevol,
+            parameter_name,
+            precode=None,
+            condition=None,
     ):
         """spec
         Function to add grid variables to the grid_options.
 
         TODO: Fix this complex function.
+        TODO: update the descriptiontext
 
-        The execution of the grid generation will be through a nested forloop, 
-        and will rely heavily on the eval() functionality of python. Which, in terms of safety is very bad, but in terms of flexibility is very good.
+        The execution of the grid generation will be through a nested forloop,
+        and will rely heavily on the eval() functionality of python. Which, in terms of safety is
+        very bad, but in terms of flexibility is very good.
 
-        name: 
+        name:
             name of parameter
-            example: name = 'lnm1'            
-        longname: 
+            example: name = 'lnm1'
+        longname:
             Long name of parameter
             example: longname = 'Primary mass'
-        range: 
+        range:
             Range of values to take
             example: range = [log($mmin),log($mmax)]
-        resolution: 
+        resolution:
             Resolution of the sampled range (amount of samples)
             example: resolution = $resolution->{m1}
-        spacingfunction: 
+        spacingfunction:
             Function determining how the range is sampled
             example: spacingfunction = "const(log($mmin),log($mmax),$resolution->{m1})"
-        precode: 
+        precode:
             # TODO: think of good description.
             example: precode = '$m1=exp($lnm1);'
-        probdist: 
+        probdist:
             FUnction determining the probability that gets asigned to the sampled parameter
             example: probdist = 'Kroupa2001($m1)*$m1'
-        dphasevol: 
+        dphasevol:
             part of the parameter space that the total probability is calculated with
             example: dphasevol = '$dlnm1'
-        condition: 
+        condition:
             condition that has to be met in order for the grid generation to continue
             example: condition = '$self->{_grid_options}{binary}==1'
         """
@@ -262,7 +285,7 @@ class Population(object):
         """
         Function that returns all the options that have been set.
 
-        Can be combined with json to make a nice file. 
+        Can be combined with json to make a nice file.
         """
 
         options = {
@@ -293,18 +316,16 @@ class Population(object):
         return self.defaults
 
     def return_all_info(
-        self,
-        include_population_settings=True,
-        include_binary_c_defaults=True,
-        include_binary_c_version_info=True,
-        include_binary_c_help_all=True,
+            self,
+            include_population_settings=True,
+            include_binary_c_defaults=True,
+            include_binary_c_version_info=True,
+            include_binary_c_help_all=True,
     ):
         """
         Function that returns all the information about the population and binary_c
         """
 
-        from binarycpython.utils.functions import get_help_all
-
         #
         all_info = {}
 
@@ -323,27 +344,29 @@ class Population(object):
             all_info["binary_c_version_info"] = binary_c_version_info
 
         if include_binary_c_help_all:
-            binary_c_help_all_info = get_help_all(print_help=False, return_dict=True)
+            binary_c_help_all_info = get_help_all(print_help=False)
             all_info["binary_c_help_all"] = binary_c_help_all_info
 
         return all_info
 
     def export_all_info(
-        self,
-        use_datadir=True,
-        outfile=None,
-        include_population_settings=True,
-        include_binary_c_defaults=True,
-        include_binary_c_version_info=True,
-        include_binary_c_help_all=True,
+            self,
+            use_datadir=True,
+            outfile=None,
+            include_population_settings=True,
+            include_binary_c_defaults=True,
+            include_binary_c_version_info=True,
+            include_binary_c_help_all=True,
     ):
         """
         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: 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
+
         TODO: theres flawed logic here. rewrite this part pls
         """
 
@@ -360,7 +383,7 @@ class Population(object):
         # Clean the all_info_dict: (i.e. transform the function objects to strings)
         if all_info_cleaned.get("population_settings", None):
             if all_info_cleaned["population_settings"]["grid_options"][
-                "parse_function"
+                    "parse_function"
             ]:
                 all_info_cleaned["population_settings"]["grid_options"][
                     "parse_function"
@@ -390,19 +413,20 @@ class Population(object):
             if self.grid_options["verbose"] > 0:
                 print("Writing settings to {}".format(settings_fullname))
             # if not outfile.endswith('json'):
-            with open(settings_fullname, "w") as f:
-                f.write(json.dumps(all_info_cleaned, indent=4))
+            with open(settings_fullname, "w") as file:
+                file.write(json.dumps(all_info_cleaned, indent=4))
 
         else:
             if self.grid_options["verbose"] > 0:
                 print("Writing settings to {}".format(outfile))
             # if not outfile.endswith('json'):
-            with open(outfile, "w") as f:
-                f.write(json.dumps(all_info_cleaned, indent=4))
+            with open(outfile, "w") as file:
+                file.write(json.dumps(all_info_cleaned, indent=4))
 
     def set_custom_logging(self):
         """
-        Function/routine to set all the custom logging so that the function memory pointer is known to the grid.
+        Function/routine to set all the custom logging so that the function memory pointer
+        is known to the grid.
         """
 
         # C_logging_code gets priority of C_autogen_code
@@ -451,12 +475,18 @@ class Population(object):
     def setup(self):
         """
         Function to set up the necessary stuff for the population evolution:
-        # TODO: Make other kinds of populations possible. i.e, read out type of grid, and set up accordingly
 
-        # TODO: make this function more general. Have it explicitly set the system_generator function
+        # TODO: Make other kinds of populations possible. i.e, read out type of grid,
+            and set up accordingly
 
+        # TODO: make this function more general. Have it explicitly set the system_generator
+            function
         """
 
+        if not self.grid_options["parse_function"]:
+            print("Error: No parse function set. Aborting run")
+            raise ValueError
+
         #######################
         ### Custom logging code:
         self.set_custom_logging()
@@ -505,7 +535,7 @@ class Population(object):
     def cleanup(self):
         """
         Function that handles all the cleaning up after the grid has been generated and/or run
-    
+
         - reset values to 0
         - remove grid file
         - unload grid function/module
@@ -559,8 +589,8 @@ class Population(object):
     def evolve_single(self, clean_up_custom_logging_files=True):
         """
         Function to run a single system
-        
-        The output of the run gets returned, unless a parse function is given to this function. 
+
+        The output of the run gets returned, unless a parse function is given to this function.
         """
 
         ### Custom logging code:
@@ -579,48 +609,51 @@ class Population(object):
             population=0,
         )
 
-        # TODO: add call to function that cleans up the temp customlogging dir, and unloads the loaded libraries.
+        # TODO: add call to function that cleans up the temp customlogging dir,
+        #   and unloads the loaded libraries.
         # TODO: make a switch to turn this off
+
         if clean_up_custom_logging_files:
             self.clean_up_custom_logging(evol_type="single")
 
         # Parse
         if self.grid_options["parse_function"]:
             return self.grid_options["parse_function"](self, out)
-        else:
-            return out
+        return out
 
     def evolve_population_mp(self):
         """
-        Function to evolve the population with multiprocessing approach. Using pathos to be able to include class-owned functions.
+        Function to evolve the population with multiprocessing approach.
+        Using pathos to be able to include class-owned functions.
         """
 
-        import multiprocessing as mp
-        from pathos.pools import _ProcessPool as Pool
-        from pathos.helpers import mp as pathos_multiprocess
-
-        # TODO: make further use of a queue to handle jobs or at least get information on the process ids etc
+        # TODO: make further use of a queue to handle jobs or at least
+        #   get information on the process ids etc
         # https://stackoverflow.com/questions/10190981/get-a-unique-id-for-worker-in-python-multiprocessing-pool
-        # https://stackoverflow.com/questions/8640367/python-manager-dict-in-multiprocessing/9536888 for muting values through dicts
+        # https://stackoverflow.com/questions/8640367/python-manager-dict-in-multiprocessing/9536888
+        #   for muting values through dicts
         # https://python-forum.io/Thread-Dynamic-updating-of-a-nested-dictionary-in-multiprocessing-pool
         # https://stackoverflow.com/questions/28740955/working-with-pathos-multiprocessing-tool-in-python-and
+
+        # TODO: make good example of how to deal with a result_dict
         manager = pathos_multiprocess.Manager()
         self.grid_options["result_dict"] = manager.dict()
 
         # Create pool
-        p = Pool(processes=self.grid_options["amt_cores"])
+        pool = Pool(processes=self.grid_options["amt_cores"])
 
         # Execute
         # TODO: calculate the chunksize value based on: total starcount and cores used.
-        r = list(
-            p.imap_unordered(
+        _ = list(
+            pool.imap_unordered(
                 self.evolve_system_mp, self.yield_system_mp(), chunksize=20
             )
         )
 
-        # Handle clean termination of the whole multiprocessing (making sure there are no zombie processes (https://en.wikipedia.org/wiki/Zombie_process))
-        p.close()
-        p.join()
+        # Handle clean termination of the whole multiprocessing (making sure there are no zombie
+        # processes (https://en.wikipedia.org/wiki/Zombie_process))
+        pool.close()
+        pool.join()
 
     def evolve_population_lin(self):
         """
@@ -644,9 +677,14 @@ class Population(object):
                 i + 1, self.grid_options["total_starcount"], full_system_dict
             )
 
+            if self.grid_options["parse_function"]:
+                self.grid_options["parse_function"](self, out)
+
+
     def evolve_population(self):
         """
-        Function to evolve populations. This is the main function. Handles the setting up, evolving and cleaning up of a population of stars.
+        Function to evolve populations. This is the main function. Handles the setting up, evolving
+        and cleaning up of a population of stars.
         """
 
         ##
@@ -655,10 +693,11 @@ class Population(object):
         self.setup()
 
         ##
-        # Evolve systems: via grid_options one can choose to do this linearly, or multiprocessing method.
+        # Evolve systems: via grid_options one can choose to do this linearly, or
+        # multiprocessing method.
         if (
-            self.grid_options["evolution_type"]
-            in self.grid_options["evolution_type_options"]
+                self.grid_options["evolution_type"]
+                in self.grid_options["evolution_type_options"]
         ):
             if self.grid_options["evolution_type"] == "mp":
                 self.evolve_population_mp()
@@ -666,7 +705,8 @@ class Population(object):
                 self.evolve_population_lin()
         else:
             print(
-                "Warning. you chose a wrong option for the grid evolution types. Please choose from the following: {}.".format(
+                "Warning. you chose a wrong option for the grid evolution types.\
+                Please choose from the following: {}.".format(
                     self.grid_options["evolution_type_options"]
                 )
             )
@@ -694,7 +734,8 @@ class Population(object):
         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(
+        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,
@@ -719,21 +760,22 @@ class Population(object):
     def generate_grid_code(self, dry_run=False):
         """
         Function that generates the code from which the population will be made.
-    
-        dry_run: when True, it will return the starcount at the end so that we know what the total amount of systems is.
+
+        dry_run: when True, it will return the starcount at the end so that we know
+        what the total amount of systems is.
 
         The phasevol values are handled by generating a second array
 
 
-        # DONE: make a generator for this.  
+        # DONE: make a generator for this.
         # TODO: Add correct logging everywhere
-        # TODO: add part to handle separation if orbital_period is added. Idea. use default values for orbital parameters and possibly overwrite those or something.
-        # TODO: add centering center left right for the spacing
+        # TODO: add part to handle separation if orbital_period is added. Idea. use default values
+        #   for orbital parameters and possibly overwrite those or something.
+        # TODO: add centering center left right for the spacing.
         # TODO: add sensible description to this function.
         # TODO: Check whether all the probability and phasevol values are correct.
 
         Results in a generated file that contains a system_generator function.
-
         """
 
         if self.grid_options["verbose"] > 0:
@@ -794,12 +836,12 @@ class Population(object):
 
         code_string += indent * depth + "# setting probability lists\n"
         # Prepare the probability
-        for el in sorted(
-            self.grid_options["grid_variables"].items(),
-            key=lambda x: x[1]["grid_variable_number"],
+        for grid_variable_el in sorted(
+                self.grid_options["grid_variables"].items(),
+                key=lambda x: x[1]["grid_variable_number"],
         ):
             # Make probabilities dict
-            grid_variable = el[1]
+            grid_variable = grid_variable_el[1]
             code_string += indent * depth + 'probabilities["{}"] = 0\n'.format(
                 grid_variable["parameter_name"]
             )
@@ -810,14 +852,14 @@ class Population(object):
         code_string += indent * depth + "\n"
         # Generate code
         print("Generating grid code")
-        for loopnr, el in enumerate(
-            sorted(
-                self.grid_options["grid_variables"].items(),
-                key=lambda x: x[1]["grid_variable_number"],
-            )
+        for loopnr, grid_variable_el in enumerate(
+                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]
+            print("Constructing/adding: {}".format(grid_variable_el[0]))
+            grid_variable = grid_variable_el[1]
 
             #################################################################################
             # Check condition and generate forloop
@@ -868,7 +910,8 @@ class Population(object):
                 + "\n"
             )
 
-            # TODO: Make clear that the phasevol only works good if you sample linearly in that thing.
+            # TODO: Make clear that the phasevol only works good
+            #   if you sample linearly in that thing.
             code_string += (
                 indent * depth
                 + "phasevol_{} = sampled_values_{}[1]-sampled_values_{}[0]".format(
@@ -880,7 +923,8 @@ class Population(object):
             # # Some print statement
             # code_string += (
             #     indent * depth
-            #     + "print('phasevol_{}:', phasevol_{})".format(grid_variable["name"], grid_variable["name"])
+            #     + "print('phasevol_{}:', phasevol_{})".format(grid_variable["name"],
+            #           grid_variable["name"])
             #     + "\n"
             # )
 
@@ -978,7 +1022,8 @@ class Population(object):
 
             # The final parts of the code, where things are returned, are within the deepest loop,
             # but in some cases code from a higher loop needs to go under it again
-            # SO I think its better to put an ifstatement here that checks whether this is the last loop.
+            # SO I think its better to put an ifstatement here that checks
+            # whether this is the last loop.
             if loopnr == len(self.grid_options["grid_variables"]) - 1:
 
                 #################################################################################
@@ -1050,16 +1095,17 @@ class Population(object):
 
         depth -= 1
         code_string += "\n"
-        # Write parts to write below the part that yield the results. this has to go in a reverse order:
+        # Write parts to write below the part that yield the results.
+        # this has to go in a reverse order:
         # Here comes the stuff that is put after the deepest nested part that calls returns stuff.
-        for loopnr, el in enumerate(
-            sorted(
-                self.grid_options["grid_variables"].items(),
-                key=lambda x: x[1]["grid_variable_number"],
-                reverse=True,
-            )
+        for loopnr, grid_variable_el in enumerate(
+                sorted(
+                    self.grid_options["grid_variables"].items(),
+                    key=lambda x: x[1]["grid_variable_number"],
+                    reverse=True,
+                )
         ):
-            grid_variable = el[1]
+            grid_variable = grid_variable_el[1]
             code_string += indent * (depth + 1) + "#" * 40 + "\n"
             code_string += (
                 indent * (depth + 1)
@@ -1110,16 +1156,16 @@ class Population(object):
         if self.grid_options["verbose"] > 0:
             print("Writing grid code to {}".format(gridcode_filename))
 
-        with open(gridcode_filename, "w") as f:
-            f.write(code_string)
+        with open(gridcode_filename, "w") as file:
+            file.write(code_string)
 
     def load_grid_function(self):
         """
+        TODO: Update this description
         Test function to run grid stuff. mostly to test the import
         """
 
         # Code to load the
-        import importlib.util
 
         if self.grid_options["verbose"] > 0:
             print(
@@ -1144,7 +1190,7 @@ class Population(object):
     def dry_run(self):
         """
         Function to dry run the grid and know how many stars it will run
-    
+
         Requires the grid to be built as a dry run grid
         """
 
@@ -1169,11 +1215,13 @@ class Population(object):
         # Calculate amount of time left
 
         # calculate amount of time passed
-        time_passed = time.time() - self.grid_options["start_time_evolution"]
+        # time_passed = time.time() - self.grid_options["start_time_evolution"]
 
         if run_number % print_freq == 0:
             binary_cmdline_string = self.return_argline(full_system_dict)
-            info_string = "{color_part_1} {text_part_1}{end_part_1}{color_part_2} {text_part_2}{end_part_2}".format(
+            info_string = "{color_part_1} \
+            {text_part_1}{end_part_1}{color_part_2} \
+            {text_part_2}{end_part_2}".format(
                 color_part_1="\033[1;32;41m",
                 text_part_1="{}/{}".format(run_number, total_systems),
                 end_part_1="\033[0m",
@@ -1204,18 +1252,23 @@ class Population(object):
     ###################################################
 
     def write_binary_c_calls_to_file(
-        self, output_dir=None, output_filename=None, include_defaults=False
+            self,
+            output_dir=None,
+            output_filename=None,
+            include_defaults=False
     ):
         """
-        Function that loops over the gridcode and writes the generated parameters to a file. In the form of a commandline call
+        Function that loops over the gridcode and writes the generated parameters to a file.
+        In the form of a commandline call
 
         Only useful when you have a variable grid as system_generator. MC wouldnt be that useful
 
-        Also, make sure that in this export there are the basic parameters like m1,m2,sep, orb-per, ecc, probability etc.
+        Also, make sure that in this export there are the basic parameters
+        like m1,m2,sep, orb-per, ecc, probability etc.
 
         On default this will write to the datadir, if it exists
 
-        # warning; dont use yet. not fully tested. 
+        # warning; dont use yet. not fully tested.
         """
 
         if self.grid_options["system_generator"]:
@@ -1229,8 +1282,7 @@ class Population(object):
                         "Error. No data_dir configured and you gave no output_dir. Aborting"
                     )
                     raise ValueError
-                else:
-                    binary_c_calls_output_dir = output_dir
+                binary_c_calls_output_dir = output_dir
 
             # check if theres a filename passed to the function
             if output_filename:
@@ -1245,11 +1297,11 @@ class Population(object):
             print("Writing binary_c calls to {}".format(binary_c_calls_full_filename))
 
             # Write to file
-            with open(binary_c_calls_full_filename, "w") as f:
+            with open(binary_c_calls_full_filename, "w") as file:
                 # Get defaults and clean them, then overwrite them with the set values.
                 if include_defaults:
                     # TODO: make sure that the defaults here are cleaned up properly
-                    cleaned_up_defaults = self.cleaned_up_defaults()
+                    cleaned_up_defaults = self.cleaned_up_defaults
                     full_system_dict = cleaned_up_defaults.copy()
                     full_system_dict.update(self.bse_options.copy())
                 else:
@@ -1260,21 +1312,23 @@ class Population(object):
                     full_system_dict.update(system)
 
                     binary_cmdline_string = self.return_argline(full_system_dict)
-                    f.write(binary_cmdline_string + "\n")
+                    file.write(binary_cmdline_string + "\n")
         else:
             print("Error. No grid function found!")
             raise KeyError
 
     def cleanup_defaults(self):
         """
-        Function to clean up the default values: 
-        
+        Function to clean up the default values:
+
         from a dictionary, removes the entries that have the following values:
-        - "NULL" 
+        - "NULL"
         - ""
         - "Function"
-        
-        Uses the function from utils.functions 
+
+        Uses the function from utils.functions
+
+        TODO: Rethink this functionality. seems a bit double, could also be just outside of the class
         """
 
         binary_c_defaults = self.return_binary_c_defaults().copy()
@@ -1284,13 +1338,15 @@ class Population(object):
 
     def clean_up_custom_logging(self, evol_type):
         """
-        Function to clean up the custom logging. 
-        Has two types: 
-            'single': 
-                - removes the compiled shared library (which name is stored in grid_options['custom_logging_shared_library_file'])
-                - TODO: unloads/frees the memory allocated to that shared library (which is stored in grid_options['custom_logging_func_memaddr'])
+        Function to clean up the custom logging.
+        Has two types:
+            'single':
+                - removes the compiled shared library
+                    (which name is stored in grid_options['custom_logging_shared_library_file'])
+                - TODO: unloads/frees the memory allocated to that shared library
+                    (which is stored in grid_options['custom_logging_func_memaddr'])
                 - sets both to None
-            'multiple': 
+            'multiple':
                 - TODO: make this and design this
         """
 
@@ -1312,7 +1368,8 @@ class Population(object):
         if evol_type == "population":
             if self.grid_options["verbose"] > 0:
                 print("Cleaning up the custom logging stuffs. type: population")
-            # TODO: make sure that these also work. not fully sure if necessary tho. whether its a single file, or a dict of files/memaddresses
+            # TODO: make sure that these also work. not fully sure if necessary tho.
+            #   whether its a single file, or a dict of files/memaddresses
 
     def increment_probtot(self, prob):
         """
@@ -1332,5 +1389,4 @@ class Population(object):
     #     Function to join the result dictionaries
     #     """
 
-
 ################################################################################################
diff --git a/binarycpython/utils/grid_options_defaults.py b/binarycpython/utils/grid_options_defaults.py
index 6e212d3997a377f0626a63a78363c1190c45b3d3..3719d0ffede5649ae2ec7889c8b3c89895ac6e39 100644
--- a/binarycpython/utils/grid_options_defaults.py
+++ b/binarycpython/utils/grid_options_defaults.py
@@ -1,5 +1,8 @@
+"""
+Module that contains the default options for the population gric code.
+"""
+
 import os
-import sys
 
 from binarycpython.utils.custom_logging_functions import temp_dir
 
@@ -30,14 +33,17 @@ grid_options_defaults_dict = {
     ##########################
     # Custom logging
     ##########################
-    "C_auto_logging": None,  # Should contain a dictionary where the kes are they headers and the values are lists of parameters that should be logged. This will get parsed by autogen_C_logging_code in custom_loggion_functions.py
+    "C_auto_logging": None,  # Should contain a dictionary where the kes are they headers
+        # and the values are lists of parameters that should be logged.
+        # This will get parsed by autogen_C_logging_code in custom_loggion_functions.py
     "C_logging_code": None,  # Should contain a string which holds the logging code.
     "custom_logging_func_memaddr": -1,  # Contains the custom_logging functions memory address
     "custom_logging_shared_library_file": None,
     ##########################
     # Store pre-loading:
     ##########################
-    "store_memaddr": -1,  # Contains the store object memory adress, useful for preloading. defaults to -1 and isnt used if thats the default then.
+    "store_memaddr": -1,  # Contains the store object memory adress, useful for preloading.
+        # defaults to -1 and isnt used if thats the default then.
     ##########################
     # Log args: logging of arguments
     ##########################
@@ -52,7 +58,8 @@ grid_options_defaults_dict = {
         "mp",
         "linear",
     ],  # available choices for type of population evolution
-    "system_generator": None,  # value that holds the function that generates the system (result of building the grid script)
+    "system_generator": None,  # value that holds the function that generates the system
+        # (result of building the grid script)
     "population_type": "grid",  #
     "population_type_options": [
         "grid",
@@ -136,7 +143,8 @@ grid_options_defaults_dict = {
     # condor_jobid=>'', # condor job id
     # condor_postpone_join=>0, # if 1, data is not joined, e.g. if you
     # # want to do it off the condor grid (e.g. with more RAM)
-    # condor_join_machine=>undef, # if defined then this is the machine on which the join command should be launched (must be sshable and not postponed)
+    # condor_join_machine=>undef, # if defined then this is the machine on which the join command
+        #should be launched (must be sshable and not postponed)
     # condor_join_pwd=>undef, # directory the join should be in
     # # (defaults to $ENV{PWD} if undef)
     # condor_memory=>1024, # in MB, the memory use (ImageSize) of the job
@@ -144,9 +152,11 @@ grid_options_defaults_dict = {
     # condor_snapshot_on_kill=>0, # if 1 snapshot on SIGKILL before exit
     # condor_load_from_snapshot=>0, # if 1 check for snapshot .sv file and load it if found
     # condor_checkpoint_interval=>0, # checkpoint interval (seconds)
-    # condor_checkpoint_stamp_times=>0, # if 1 then files are given timestamped names (warning: lots of files!), otherwise just store the lates
+    # condor_checkpoint_stamp_times=>0, # if 1 then files are given timestamped names
+        # (warning: lots of files!), otherwise just store the lates
     # condor_streams=>0, # stream stderr/stdout by default (warning: might cause heavy network load)
-    # condor_save_joined_file=>0, # if 1 then results/joined contains the results (useful for debugging, otherwise a lot of work)
+    # condor_save_joined_file=>0, # if 1 then results/joined contains the results
+        # (useful for debugging, otherwise a lot of work)
     # condor_requirements=>'', # used?
     #     # resubmit options : if the status of a condor script is
     #     # either 'finished','submitted','running' or 'crashed',
@@ -330,7 +340,8 @@ grid_options_defaults_dict = {
     #     sort_args=>0, # do not sort args
     # save_args=>0, # do not save args in a string
     # log_args_dir=>$tmp, # where to output the args files
-    # always_reopen_arg_files=>0, # if 1 then arg files are always closed and reopened (may cause a lot of disk I/O)
+    # always_reopen_arg_files=>0, # if 1 then arg files are always closed and reopened
+    #   (may cause a lot of disk I/O)
     # lazy_arg_sending=>1, # if 1, the previous args are remembered and
     # # only args that changed are sent (except M1, M2 etc. which always
     # # need sending)
diff --git a/binarycpython/utils/plot_functions.py b/binarycpython/utils/plot_functions.py
index 4d7a88b03db7d0f74eb7b218c1acd909cc7c286f..af5649f306f0c37dd252494dad9ff062979db4e9 100644
--- a/binarycpython/utils/plot_functions.py
+++ b/binarycpython/utils/plot_functions.py
@@ -1,32 +1,40 @@
 """
 Module that contains plotting routines for single systems.
 
-The idea to do this is to provide the user with some quick 
+The idea to do this is to provide the user with some quick
 commands to plot the evolution of a system
 
 There is no preloaded matplotlib rc, you should do that yourself
+
+TODO: This module is not finished yet.
 """
 
 import pandas as pd
 import numpy as np
 
-import matplotlib.pyplot as plt
+# import matplotlib.pyplot as plt
+
+from binarycpython.utils.functions import (
+    output_lines,
+)
+from binarycpython.utils.run_system_wrapper import run_system
+from binarycpython.utils.custom_logging_functions import binary_c_log_code
+
 from david_phd_functions.plotting.plot_functions import (
     plot_orbit,
     plot_masses,
     plot_HR_diagram,
 )
 
-from binarycpython.utils.functions import get_arg_keys, output_lines
-from binarycpython.utils.run_system_wrapper import run_system
-from binarycpython.utils.custom_logging_functions import binary_c_log_code
 
-# Define the custom_logging_strings. These are kept to the minimum necessary for each plotting routine.
+# Define the custom_logging_strings.
+# These are kept to the minimum necessary for each plotting routine.
 
-custom_logging_string_masses = ""
-custom_logging_string_orbit = ""
+CUSTOM_LOGGING_STRING_MASSES = ""
 
-custom_logging_string_HR_diagram = """
+CUSTOM_LOGGING_STRING_ORBIT = ""
+
+CUSTOM_LOGGING_STRING_HR_DIAGRAM = """
 Printf("HR_PLOTTING %30.12e %d %d %g %g %g %g %g %g\\n",
     //
     stardata->model.time, // 1
@@ -50,9 +58,9 @@ Printf("HR_PLOTTING %30.12e %d %d %g %g %g %g %g %g\\n",
 
 # Define the parse functions for the plotting routines
 def dummy():
+    """Placeholder"""
     pass
 
-
 def parse_function_hr_diagram(output):
     """
     Parsing function for the HR plotting routine
@@ -75,12 +83,12 @@ def parse_function_hr_diagram(output):
     ]
 
     # Go over the output.
-    for el in output_lines(output):
-        headerline = el.split()[0]
+    for line in output_lines(output):
+        headerline = line.split()[0]
 
         # Check the header and act accordingly
         if headerline == "HR_PLOTTING":
-            values = el.split()[1:]
+            values = line.split()[1:]
             values_list.append(values)
 
     df = pd.DataFrame(values_list)
@@ -98,12 +106,13 @@ def plot_system(plot_type, **kwargs):
     TODO: Complex Function!
     TODO: make sure this way of passing args works correctly.
     TODO: make the plotting specific keywords available via the inspect stuff
-    Function to plot the evolution of the system.  
+    Function to plot the evolution of the system.
 
     This goes (in general) via the following steps:
         - a preset custom logging for a specific plotting routine is loaded.
         - This is used for the run_system call
-        - The output of this run_system is loaded into a dataframe by parsing it with a corresponding parsing function
+        - The output of this run_system is loaded into a dataframe by
+            parsing it with a corresponding parsing function
         - The dataframe is passed to the plotting routine
         - plot is shown or returned.
 
@@ -111,11 +120,16 @@ def plot_system(plot_type, **kwargs):
 
     All keywords are considered kwargs, except for plot_type
     input:
-        plot_type: string input should be one of the following types: ['mass_evolution', 'orbit_evolution', 'hr_diagram'].
-            Input will be matched against this, and then go through a dictionary to pick the correct plotting function. 
-        return_fig: boolean whether to return the fig object instead of plotting the plot (makes so that you can customize it)
-        show_stellar_types: whether to plot the stellar type evolution on a second pane. This is not included in all the plotting routines.
-        Other input: other kwargs that are passed to run_system (inspect the docstring of run_system for more info)
+        plot_type: string input should be one of the following types:
+            ['mass_evolution', 'orbit_evolution', 'hr_diagram'].
+            Input will be matched against this,
+            and then go through a dictionary to pick the correct plotting function.
+        return_fig: boolean whether to return the fig object instead of plotting the plot
+            (makes so that you can customize it)
+        show_stellar_types: whether to plot the stellar type evolution on a second pane.
+            This is not included in all the plotting routines.
+        Other input: other kwargs that are passed to run_system
+            (inspect the docstring of run_system for more info)
     """
 
     # set defaults and options
@@ -125,32 +139,35 @@ def plot_system(plot_type, **kwargs):
     plot_types_dict = {
         "mass_evolution": {
             "plot_function": plot_masses,
-            "custom_logging_string": custom_logging_string_masses,
+            "custom_logging_string": CUSTOM_LOGGING_STRING_MASSES,
             "parse_function": dummy,
         },
         "orbit_evolution": {
             "plot_function": plot_orbit,
-            "custom_logging_string": custom_logging_string_orbit,
+            "custom_logging_string": CUSTOM_LOGGING_STRING_ORBIT,
             "parse_function": dummy,
         },
         "hr_diagram": {
             "plot_function": plot_HR_diagram,
-            "custom_logging_string": custom_logging_string_HR_diagram,
+            "custom_logging_string": CUSTOM_LOGGING_STRING_HR_DIAGRAM,
             "parse_function": parse_function_hr_diagram,
         },
     }
     plot_system_specific_keywords = ["plot_type", "show_plot", "show_stellar_types"]
 
     # First check on the plot_type input
-    if not plot_type in plot_types_dict.keys():
+    if not plot_type in plot_types_dict:
         print(
-            "Warning, the provided plot type is not known. Please choose one from the following:\n\t{}".format(
+            "Warning, the provided plot type is not known. \
+            Please choose one from the following:\n\t{}".format(
                 plot_types_dict.keys()
             )
         )
         raise ValueError
 
-    # First: check all the arguments. Chosen to not check all the keywords for run_system and binary_c specifically, but just to pick out the ones needed for this routine. run_system will handle the rest
+    # First: check all the arguments. Chosen to not check all the keywords for run_system
+    #   and binary_c specifically, but just to pick out the ones needed for this routine.
+    #   run_system will handle the rest
     run_system_arg_dict = {}
 
     for key in kwargs.keys():
@@ -163,7 +180,8 @@ def plot_system(plot_type, **kwargs):
         else:
             run_system_arg_dict[key] = kwargs[key]
 
-    # TODO: When a list of plot_types is passed, make it so that the strings are chained, and that the output of the binary_c call is handled by multiple parsers
+    # TODO: When a list of plot_types is passed, make it so that the strings are chained,
+    #   and that the output of the binary_c call is handled by multiple parsers
     custom_logging_code = binary_c_log_code(
         plot_types_dict[plot_type]["custom_logging_string"]
     )
diff --git a/binarycpython/utils/run_system_wrapper.py b/binarycpython/utils/run_system_wrapper.py
index 4237548dc3cb232d461a189074144508e5ca55c4..7b726892ee794ccb0ab5d70974d7947379d22f11 100644
--- a/binarycpython/utils/run_system_wrapper.py
+++ b/binarycpython/utils/run_system_wrapper.py
@@ -1,7 +1,10 @@
-import binary_c_python_api
+"""
+Module containing the utility function run_system,
+which handles a lot of things by analysing the passed kwargs
+"""
+
 
 from binarycpython.utils.functions import (
-    get_defaults,
     create_arg_string,
     get_arg_keys,
     remove_file,
@@ -10,29 +13,37 @@ from binarycpython.utils.functions import (
 from binarycpython.utils.custom_logging_functions import (
     create_and_load_logging_function,
 )
+import binary_c_python_api
 
 
 def run_system(**kwargs):
     """
-    Function that runs a system. Mostly as a useful utility function that handles all the setup of argument lists etc.
+    Function that runs a system.
+    Mostly as a useful utility function that handles all the setup of argument lists etc.
 
     All~ the arguments known to binary_c can be passed to this function as kwargs.
     Several extra arguments can be passed through the kwargs:
-        * custom_logging_code (string): Should contain a string containing the c-code for the shared library. 
+        * custom_logging_code (string):
+            Should contain a string containing the c-code for the shared library.
             If this is provided binary_c will use that custom logging code to output its data
-        * log_filename (string): Should contain name of the binary_c system logfile. 
-            Passing this will make sure that the filename gets written for a run (its default behaviour is NOT to write a logfile for a system)
-        * parse_function (function): should contain a function that parses the output. The parse function should take 1 required parameter: the output of the binaryc run
-            Passing this will call the parse_function by passing it the output of the binary_c call and returns what the parse_function returns
-    
+        * log_filename (string):
+            Should contain name of the binary_c system logfile.
+            Passing this will make sure that the filename gets written for a run
+            (its default behaviour is NOT to write a logfile for a system)
+        * parse_function (function):
+            should contain a function that parses the output.
+            The parse function should take 1 required parameter: the output of the binaryc run
+            Passing this will call the parse_function by passing it the output of the binary_c call
+            and returns what the parse_function returns
+
     examples:
         * run_system(M_1=10): will run a system with ZAMS mass 1 = 10
-        * run_system(M_1=10, log_filename="~/example_log.txt"): Will run a system and write the logfile to 
+        * run_system(M_1=10, log_filename="~/example_log.txt"): Will run a system
+            and write the logfile too
         * run_system(M_1=10, parse_function=fancy_parsing_function)
 
-    Todo: 
-        * Expand functionality.
-        * Notify user when an unknown keyword is passed
+    TODO: Expand functionality.
+    TODO: Notify user when an unknown keyword is passed.
     """
 
     # Load available arg keywords
@@ -48,7 +59,7 @@ def run_system(**kwargs):
     binary_c_args = {}
 
     # Check which binary_c arguments have been passed and put them into a dict
-    for key in kwargs.keys():
+    for key in kwargs:
         if key in available_binary_c_arg_keywords:
             binary_c_args[key] = kwargs[key]
 
@@ -88,5 +99,4 @@ def run_system(**kwargs):
 
     if "parse_function" in kwargs:
         return kwargs["parse_function"](output)
-    else:
-        return output
+    return output
diff --git a/binarycpython/utils/spacing_functions.py b/binarycpython/utils/spacing_functions.py
index 84aeecdf0d8018cc74f8961f436954dd784b8ac1..28fe7ebe27b2ff2562941d92d19e82d58a67644b 100644
--- a/binarycpython/utils/spacing_functions.py
+++ b/binarycpython/utils/spacing_functions.py
@@ -1,5 +1,14 @@
+"""
+Module containing the spacing functions for the binarycpython package
+"""
+
+
 import numpy as np
 
 
-def const(min, max, steps):
-    return np.linspace(min, max, steps)
+def const(min_bound, max_bound, steps):
+    """
+    Samples a range linearly. Uses numpy linspace.
+    """
+
+    return np.linspace(min_bound, max_bound, steps)
diff --git a/binarycpython/utils/stellar_types.py b/binarycpython/utils/stellar_types.py
index d18a63cf207f22823f1d00ac6dfaeb61191aa4c8..d7b2e3b788509e8faef65317e1e724832e18cdcb 100644
--- a/binarycpython/utils/stellar_types.py
+++ b/binarycpython/utils/stellar_types.py
@@ -1,4 +1,8 @@
-stellar_type_dict = {
+"""
+Module containing stellar type dicts
+"""
+
+STELLAR_TYPE_DICT = {
     0: "low mass main sequence",
     1: "Main Sequence",
     2: "Hertzsprung Gap",
@@ -17,7 +21,7 @@ stellar_type_dict = {
     15: "MASSLESS REMNANT",
 }
 
-stellar_type_dict_short = {
+STELLAR_TYPE_DICT_SHORT = {
     0: "LMMS",
     1: "MS",
     2: "HG",
diff --git a/binarycpython/utils/useful_funcs.py b/binarycpython/utils/useful_funcs.py
index cf1b5b444224bc2adad9d1e53da7e78f96d248ac..bda0da21239a098874acf74141b5bc3cbe5bf8d7 100644
--- a/binarycpython/utils/useful_funcs.py
+++ b/binarycpython/utils/useful_funcs.py
@@ -1,17 +1,19 @@
-############################################################
-# Collection of useful functions.
-
-# Part of this is copied/inspired by Robs
-# Rob's binary_stars module
-
-# Has functions to convert period to separation and vice versa.
-# calc_period_from_sep($m1,$m2,$sep) calculate the period given the separation.
-# calc_sep_from_period($m1,$m2,per) does the inverse.
-# M1,M2,separation are in solar units, period in days.
-# rzams($m,$z) gives you the ZAMS radius of a star
-# ZAMS_collision($m1,$m2,$e,$sep,$z) returns 1 if stars collide on the ZAMS
-###
+"""
+Collection of useful functions.
+
+Part of this is copied/inspired by Robs
+Rob's binary_stars module
+
+Has functions to convert period to separation and vice versa.
+calc_period_from_sep($m1,$m2,$sep) calculate the period given the separation.
+calc_sep_from_period($m1,$m2,per) does the inverse.
+M1,M2,separation are in solar units, period in days.
+rzams($m,$z) gives you the ZAMS radius of a star
+ZAMS_collision($m1,$m2,$e,$sep,$z) returns 1 if stars collide on the ZAMS
+
 # TODO: check whether these are correct
+"""
+import math
 
 AURSUN = 2.150445198804013386961742071435e02
 YEARDY = 3.651995478818308811241877265275e02
@@ -23,7 +25,7 @@ def calc_period_from_sep(M1, M2, sep):
     args : M1, M2, separation (Rsun)
     """
 
-    return YEARDY * (sep / AURSUN) * sqrt(sep / (AURSUN * (M1 + M2)))
+    return YEARDY * (sep / AURSUN) * math.sqrt(sep / (AURSUN * (M1 + M2)))
 
 
 def calc_sep_from_period(M1, M2, period):
@@ -41,7 +43,7 @@ def roche_lobe(q):
     """
 
     p = q ** (1.0 / 3.0)
-    return 0.49 * p * p / (0.6 * p * p + log(1.0 + p))
+    return 0.49 * p * p / (0.6 * p * p + math.log(1.0 + p))
 
 
 def ragb(m, z):
@@ -55,9 +57,10 @@ def ragb(m, z):
 
 def zams_collission(m1, m2, sep, e, z):
     """
-    # given m1,m2, separation and eccentricity (and metallicity)
-    # determine if two stars collide on the ZAMS
+    given m1,m2, separation and eccentricity (and metallicity)
+    determine if two stars collide on the ZAMS
     """
+
     # calculate periastron distance
     peri_distance = (1.0 - e) * sep
 
@@ -67,14 +70,14 @@ def zams_collission(m1, m2, sep, e, z):
 
     if r1 + r2 > peri_distance:
         return 1
-    else:
-        return 0
+    return 0
 
 
 def rzams(m, z):
     """
     Function to determine the radius of a ZAMS star as a function of m and z:
     """
+
     lzs = math.log10(z / 0.02)
 
     #
diff --git a/setup.py b/setup.py
index 086900e4bbdce83840ef56beafaf9a5681dfc834..9b2e77cac374002a061461364c90ea9819b6d60f 100644
--- a/setup.py
+++ b/setup.py
@@ -1,3 +1,7 @@
+"""
+Setup script for binarycpython
+"""
+
 from distutils.core import setup, Extension
 
 # from setuptools import find_packages
@@ -5,12 +9,12 @@ from distutils.core import setup, Extension
 import os
 import subprocess
 import re
-import sys
 
 GSL_DIR = os.getenv("GSL_DIR", None)
 if not GSL_DIR:
     print(
-        "Warning: GSL_DIR is not set, this might lead to errors along the installation if there is no other version of GSL in the include dirs"
+        "Warning: GSL_DIR is not set, this might lead to errors along the installation if\
+        there is no other version of GSL in the include dirs"
     )
 
 # TODO: write code to know exact parent directory of this file.
@@ -21,90 +25,90 @@ CWD = os.getcwd()
 ############################################################
 
 # binary_c must be installed.
-binary_c_config = os.environ["BINARY_C"] + "/binary_c-config"
+BINARY_C_CONFIG = os.environ["BINARY_C"] + "/binary_c-config"
 
-binary_c_incdirs = (
-    subprocess.run([binary_c_config, "incdirs_list"], stdout=subprocess.PIPE)
+BINARY_C_INCDIRS = (
+    subprocess.run([BINARY_C_CONFIG, "incdirs_list"], stdout=subprocess.PIPE, check=True)
     .stdout.decode("utf-8")
     .split()
 )
-binary_c_libdirs = (
-    subprocess.run([binary_c_config, "libdirs_list"], stdout=subprocess.PIPE)
+BINARY_C_LIBDIRS = (
+    subprocess.run([BINARY_C_CONFIG, "libdirs_list"], stdout=subprocess.PIPE, check=True)
     .stdout.decode("utf-8")
     .split()
 )
-binary_c_cflags = (
-    subprocess.run([binary_c_config, "cflags"], stdout=subprocess.PIPE)
+BINARY_C_CFLAGS = (
+    subprocess.run([BINARY_C_CONFIG, "cflags"], stdout=subprocess.PIPE, check=True)
     .stdout.decode("utf-8")
     .split()
 )
-# binary_c_cflags.remove('-fvisibility=hidden')
-binary_c_libs = (
-    subprocess.run([binary_c_config, "libs_list"], stdout=subprocess.PIPE)
+# BINARY_C_CFLAGS.remove('-fvisibility=hidden')
+BINARY_C_LIBS = (
+    subprocess.run([BINARY_C_CONFIG, "libs_list"], stdout=subprocess.PIPE, check=True)
     .stdout.decode("utf-8")
     .split()
 )
 
 # create list of tuples of defined macros
-binary_c_define_macros = []
-defines = (
-    subprocess.run([binary_c_config, "define_macros"], stdout=subprocess.PIPE)
+BINARY_C_DEFINE_MACROS = []
+DEFINES = (
+    subprocess.run([BINARY_C_CONFIG, "define_macros"], stdout=subprocess.PIPE, check=True)
     .stdout.decode("utf-8")
     .split()
 )
-lone = re.compile("^-D(.+)$")
-partner = re.compile("^-D(.+)=(.+)$")
+LONE = re.compile("^-D(.+)$")
+PARTNER = re.compile("^-D(.+)=(.+)$")
 
-for x in defines:
-    y = partner.match(x)
+for x in DEFINES:
+    y = PARTNER.match(x)
     if y:
-        binary_c_define_macros.extend([(y.group(1), y.group(2))])
+        BINARY_C_DEFINE_MACROS.extend([(y.group(1), y.group(2))])
     else:
-        y = lone.match(x)
+        y = LONE.match(x)
         if y:
-            binary_c_define_macros.extend([(y.group(1), None)])
+            BINARY_C_DEFINE_MACROS.extend([(y.group(1), None)])
 
 # add API header file
 API_h = os.environ["BINARY_C"] + "/src/API/binary_c_API.h"
-binary_c_define_macros.extend([("BINARY_C_API_H", API_h)])
+BINARY_C_DEFINE_MACROS.extend([("BINARY_C_API_H", API_h)])
 
 ############################################################
-# Setting all directories and libraries to their final values
+# Setting all directories and LIBRARIES to their final values
 ############################################################
-include_dirs = (
+INCLUDE_DIRS = (
     [os.environ["BINARY_C"] + "/src", os.environ["BINARY_C"] + "/src/API", "include",]
-    + binary_c_incdirs
+    + BINARY_C_INCDIRS
     + [os.path.join(GSL_DIR, "include")]
     if GSL_DIR
     else []
 )
 
-libraries = ["binary_c"] + binary_c_libs + ["binary_c_api"]
+LIBRARIES = ["binary_c"] + BINARY_C_LIBS + ["binary_c_api"]
 
-library_dirs = [
+LIBRARY_DIRS = [
     os.environ["BINARY_C"] + "/src",
     "./",
     os.path.join(CWD, "lib/"),
     # os.path.join(CWD, "binarycpython/core/"),
-] + binary_c_libdirs
+] + BINARY_C_LIBDIRS
 
-runtime_library_dirs = [
+RUNTIME_LIBRARY_DIRS = [
     os.environ["BINARY_C"] + "/src",
     "./",
     os.path.join(CWD, "lib/"),
     # os.path.join(CWD, "binarycpython/core/"),
-] + binary_c_libdirs
+] + BINARY_C_LIBDIRS
 
 # print('\n')
-# print("binary_c_config: ", str(binary_c_config) + "\n")
-# print("incdirs: ", str(include_dirs) + "\n")
-# print("binary_c_libs: ", str(binary_c_libs) + "\n")
-# print("libraries: ", str(libraries) + "\n")
-# print("library_dirs: ", str(library_dirs) + "\n")
-# print("runtime_library_dirs: ", str(runtime_library_dirs) + "\n")
-# print("binary_c_cflags: ", str(binary_c_cflags) + "\n")
+# print("BINARY_C_CONFIG: ", str(BINARY_C_CONFIG) + "\n")
+# print("incdirs: ", str(INCLUDE_DIRS) + "\n")
+# print("BINARY_C_LIBS: ", str(BINARY_C_LIBS) + "\n")
+# print("LIBRARIES: ", str(LIBRARIES) + "\n")
+# print("LIBRARY_DIRS: ", str(LIBRARY_DIRS) + "\n")
+# print("RUNTIME_LIBRARY_DIRS: ", str(RUNTIME_LIBRARY_DIRS) + "\n")
+# print("BINARY_C_CFLAGS: ", str(BINARY_C_CFLAGS) + "\n")
 # print("API_h: ", str(API_h) + "\n")
-# print("macros: ", str(binary_c_define_macros) + "\n")
+# print("macros: ", str(BINARY_C_DEFINE_MACROS) + "\n")
 # print('\n')
 
 ############################################################
@@ -112,15 +116,15 @@ runtime_library_dirs = [
 ############################################################
 # TODO: fix that this one also compiles the code itself
 
-binary_c_python_api_module = Extension(
+BINARY_C_PYTHON_API_MODULE = Extension(
     # name="binarycpython.core.binary_c",
     name="binary_c_python_api",
     sources=["src/binary_c_python.c"],
-    include_dirs=include_dirs,
-    libraries=libraries,
-    library_dirs=library_dirs,
-    runtime_library_dirs=runtime_library_dirs,
-    define_macros=[] + binary_c_define_macros,
+    INCLUDE_DIRS=INCLUDE_DIRS,
+    LIBRARIES=LIBRARIES,
+    LIBRARY_DIRS=LIBRARY_DIRS,
+    RUNTIME_LIBRARY_DIRS=RUNTIME_LIBRARY_DIRS,
+    define_macros=[] + BINARY_C_DEFINE_MACROS,
     extra_objects=[],
     extra_compile_args=[],
     language="C",
@@ -128,8 +132,9 @@ binary_c_python_api_module = Extension(
 
 
 def readme():
-    with open("README.md") as f:
-        return f.read()
+    """Opens readme file and returns content"""
+    with open("README.md") as file:
+        return file.read()
 
 
 ############################################################
@@ -139,9 +144,11 @@ def readme():
 setup(
     name="binarycpython",
     version="0.2",
-    description="This is a python API for binary_c by David Hendriks, Rob Izzard and collaborators. Based on the initial set up by Jeff andrews",
+    description="This is a python API for binary_c by David Hendriks, Rob Izzard and collaborators.\
+        Based on the initial set up by Jeff andrews",
     author=" David Hendriks, Robert Izzard and Jeff Andrews",
-    author_email="davidhendriks93@gmail.com/d.hendriks@surrey.ac.uk, r.izzard@surrey.ac.uk/rob.izzard@gmail.com andrews@physics.uoc.gr",
+    author_email="davidhendriks93@gmail.com/d.hendriks@surrey.ac.uk,\
+        r.izzard@surrey.ac.uk/rob.izzard@gmail.com andrews@physics.uoc.gr",
     long_description=readme(),
     url="https://gitlab.eps.surrey.ac.uk/ri0005/binary_c-python",
     license="",
@@ -158,5 +165,5 @@ setup(
     # package_data={
     #     'binarycpython.core': ['libbinary_c_api.so'],
     # },
-    ext_modules=[binary_c_python_api_module],  # binary_c must be loaded
+    ext_modules=[BINARY_C_PYTHON_API_MODULE],  # binary_c must be loaded
 )