From 02a0c09fd30ff9f5e0491e5abfe200ec187caa72 Mon Sep 17 00:00:00 2001
From: dh00601 <dh00601@surrey.ac.uk>
Date: Wed, 29 Dec 2021 20:12:07 +0000
Subject: [PATCH] adding more tests

---
 badges/test_coverage.svg                      |   4 +-
 binarycpython/tests/main.py                   |  21 +-
 binarycpython/tests/test_distributions.py     | 801 -----------------
 .../test__distribution_functions.py           | 828 ++++++++++++++++++
 .../test__grid_options_defaults.py}           |   0
 .../test__hpc_functions.py}                   |   0
 .../test__spacing_functions.py}               |   0
 binarycpython/tests/tmp_functions.py          | 488 ++++++-----
 .../_distribution_functions.py                |   2 +-
 .../_grid_options_defaults.py                 |   6 +-
 setup.py                                      |   1 +
 11 files changed, 1109 insertions(+), 1042 deletions(-)
 delete mode 100644 binarycpython/tests/test_distributions.py
 create mode 100644 binarycpython/tests/tests_population_extensions/test__distribution_functions.py
 rename binarycpython/tests/{test_grid_options_defaults.py => tests_population_extensions/test__grid_options_defaults.py} (100%)
 rename binarycpython/tests/{test_hpc_functions.py => tests_population_extensions/test__hpc_functions.py} (100%)
 rename binarycpython/tests/{test_spacing_functions.py => tests_population_extensions/test__spacing_functions.py} (100%)

diff --git a/badges/test_coverage.svg b/badges/test_coverage.svg
index 0644a48b3..6198a7284 100644
--- a/badges/test_coverage.svg
+++ b/badges/test_coverage.svg
@@ -15,7 +15,7 @@
     <g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
         <text x="31.5" y="15" fill="#010101" fill-opacity=".3">coverage</text>
         <text x="31.5" y="14">coverage</text>
-        <text x="80" y="15" fill="#010101" fill-opacity=".3">26%</text>
-        <text x="80" y="14">26%</text>
+        <text x="80" y="15" fill="#010101" fill-opacity=".3">27%</text>
+        <text x="80" y="14">27%</text>
     </g>
 </svg>
diff --git a/binarycpython/tests/main.py b/binarycpython/tests/main.py
index 58f4d14a1..b293970ea 100755
--- a/binarycpython/tests/main.py
+++ b/binarycpython/tests/main.py
@@ -20,7 +20,6 @@ from binarycpython.tests.test_custom_logging import (
     test_return_compilation_dict,
     test_create_and_load_logging_function
 )
-# from binarycpython.tests.test_distributions import *
 from binarycpython.tests.test_functions import (
     test_verbose_print,
     test_temp_dir,
@@ -39,12 +38,11 @@ from binarycpython.tests.test_functions import (
 
 )
 # from binarycpython.tests.test_grid import *
-# from binarycpython.tests.test_hpc_functions import *
 from binarycpython.tests.test_plot_functions import (
     test_color_by_index,
     test_plot_system,
 )
-# from binarycpython.tests.test_run_system_wrapper import *
+from binarycpython.tests.test_run_system_wrapper import *
 # from binarycpython.tests.test_spacing_functions import *
 from binarycpython.tests.test_useful_funcs import (
     test_calc_period_from_sep,
@@ -57,5 +55,22 @@ from binarycpython.tests.test_useful_funcs import (
 # from binarycpython.tests.test_grid_options_defaults import *
 from binarycpython.tests.test_stellar_types import *
 
+
+
+
+
+
+# from binarycpython.tests.test_hpc_functions import *
+from binarycpython.tests.tests_population_extensions.test__distribution_functions import (
+    test_flat,
+    test_number,
+    test_const
+)
+
+
+
+
+
+
 if __name__ == "__main__":
     unittest.main()
diff --git a/binarycpython/tests/test_distributions.py b/binarycpython/tests/test_distributions.py
deleted file mode 100644
index 85d08e346..000000000
--- a/binarycpython/tests/test_distributions.py
+++ /dev/null
@@ -1,801 +0,0 @@
-"""
-Module containing the unittests for the distribution functions. 
-"""
-
-import unittest
-
-from binarycpython.utils.distribution_functions import *
-from binarycpython.utils.useful_funcs import calc_sep_from_period
-from binarycpython.utils.functions import Capturing, temp_dir
-
-TMP_DIR = temp_dir("tests", "test_distributions")
-
-
-class TestDistributions(unittest.TestCase):
-    """
-    Unittest class
-
-    # https://stackoverflow.com/questions/17353213/init-for-unittest-testcase
-    """
-
-    def __init__(self, *args, **kwargs):
-        """
-        init
-        """
-        super(TestDistributions, self).__init__(*args, **kwargs)
-
-        self.mass_list = [0.1, 0.2, 1, 10, 15, 50]
-        self.logper_list = [-2, -0.5, 1.6, 2.5, 5.3, 10]
-        self.q_list = [0.01, 0.2, 0.4, 0.652, 0.823, 1]
-        self.per_list = [10 ** logper for logper in self.logper_list]
-
-        self.tolerance = 1e-5
-
-    def test_setopts(self):
-        with Capturing() as output:
-            self._test_setopts()
-
-    def _test_setopts(self):
-        """
-        Unittest for function set_opts
-        """
-
-        default_dict = {"m1": 2, "m2": 3}
-        output_dict_1 = set_opts(default_dict, {})
-        self.assertTrue(output_dict_1 == default_dict)
-
-        new_opts = {"m1": 10}
-        output_dict_2 = set_opts(default_dict, new_opts)
-        updated_dict = default_dict.copy()
-        updated_dict["m1"] = 10
-
-        self.assertTrue(output_dict_2 == updated_dict)
-
-    def test_flat(self):
-        with Capturing() as output:
-            self._test_flat()
-
-    def _test_flat(self):
-        """
-        Unittest for the function flat
-        """
-
-        output_1 = flat()
-
-        self.assertTrue(isinstance(output_1, float))
-        self.assertEqual(output_1, 1.0)
-
-    def test_number(self):
-        with Capturing() as output:
-            self._test_number()
-
-    def _test_number(self):
-        """
-        Unittest for function number
-        """
-
-        input_1 = 1.0
-        output_1 = number(input_1)
-
-        self.assertEqual(input_1, output_1)
-
-    def test_const(self):
-        with Capturing() as output:
-            self._test_const()
-
-    def _test_const(self):
-        """
-        Unittest for function const
-        """
-
-        output_1 = const(min_bound=0, max_bound=2)
-        self.assertEqual(
-            output_1, 0.5, msg="Value should be 0.5, but is {}".format(output_1)
-        )
-
-        output_2 = const(min_bound=0, max_bound=2, val=3)
-        self.assertEqual(
-            output_2, 0, msg="Value should be 0, but is {}".format(output_2)
-        )
-
-    def test_powerlaw(self):
-        with Capturing() as output:
-            self._test_powerlaw()
-
-    def _test_powerlaw(self):
-        """
-        unittest for the powerlaw test
-        """
-
-        perl_results = [
-            0,
-            0,
-            1.30327367546194,
-            0.00653184128064016,
-            0.00257054805572128,
-            0.000161214690242696,
-        ]
-        python_results = []
-        input_lists = []
-
-        for mass in self.mass_list:
-            input_lists.append(mass)
-            python_results.append(powerlaw(1, 100, -2.3, mass))
-
-        # GO over the results and check whether they are equal (within tolerance)
-        for i in range(len(python_results)):
-            msg = "Error: Value perl: {} Value python: {} for mass, per: {}".format(
-                perl_results[i], python_results[i], str(input_lists[i])
-            )
-            self.assertLess(np.abs(python_results[i] - perl_results[i]), self.tolerance)
-
-        # extra test for k = -1
-        self.assertRaises(ValueError, powerlaw, 1, 100, -1, 10)
-
-    def test_three_part_power_law(self):
-        with Capturing() as output:
-            self._test_three_part_power_law()
-
-    def _test_three_part_power_law(self):
-        """
-        unittest for three_part_power_law
-        """
-
-        perl_results = [
-            10.0001044752901,
-            2.03065220596677,
-            0.0501192469795434,
-            0.000251191267451594,
-            9.88540897458207e-05,
-            6.19974072148769e-06,
-        ]
-        python_results = []
-        input_lists = []
-
-        for mass in self.mass_list:
-            input_lists.append(mass)
-            python_results.append(
-                three_part_powerlaw(mass, 0.08, 0.1, 1, 300, -1.3, -2.3, -2.3)
-            )
-
-        # GO over the results and check whether they are equal (within tolerance)
-        for i in range(len(python_results)):
-            msg = "Error: Value perl: {} Value python: {} for mass, per: {}".format(
-                perl_results[i], python_results[i], str(input_lists[i])
-            )
-            self.assertLess(
-                np.abs(python_results[i] - perl_results[i]), self.tolerance, msg=msg
-            )
-
-        # Extra test:
-        # M < M0
-        self.assertTrue(
-            three_part_powerlaw(0.05, 0.08, 0.1, 1, 300, -1.3, -2.3, -2.3) == 0,
-            msg="Probability should be zero as M < M0",
-        )
-
-    def test_Kroupa2001(self):
-        with Capturing() as output:
-            self._test_Kroupa2001()
-
-    def _test_Kroupa2001(self):
-        """
-        unittest for three_part_power_law
-        """
-
-        perl_results = [
-            0,  # perl value is actually 5.71196495365248
-            2.31977861075353,
-            0.143138195684851,
-            0.000717390363216896,
-            0.000282322598503135,
-            1.77061658757533e-05,
-        ]
-        python_results = []
-        input_lists = []
-
-        for mass in self.mass_list:
-            input_lists.append(mass)
-            python_results.append(Kroupa2001(mass))
-
-        # GO over the results and check whether they are equal (within tolerance)
-        for i in range(len(python_results)):
-            msg = "Error: Value perl: {} Value python: {} for mass: {}".format(
-                perl_results[i], python_results[i], str(input_lists[i])
-            )
-            self.assertLess(
-                np.abs(python_results[i] - perl_results[i]), self.tolerance, msg=msg
-            )
-
-        # Extra tests:
-        self.assertEqual(
-            Kroupa2001(10, newopts={"mmax": 300}),
-            three_part_powerlaw(10, 0.1, 0.5, 1, 300, -1.3, -2.3, -2.3),
-        )
-
-    def test_ktg93(self):
-        with Capturing() as output:
-            self._test_ktg93()
-
-    def _test_ktg93(self):
-        """
-        unittest for three_part_power_law
-        """
-
-        perl_results = [
-            0,  # perl value is actually 5.79767807698379 but that is not correct
-            2.35458895566605,
-            0.155713799148675,
-            0.000310689875361984,
-            0.000103963454405194,
-            4.02817276824841e-06,
-        ]
-        python_results = []
-        input_lists = []
-
-        for mass in self.mass_list:
-            input_lists.append(mass)
-            python_results.append(ktg93(mass))
-
-        # GO over the results and check whether they are equal (within tolerance)
-        for i in range(len(python_results)):
-            msg = "Error: Value perl: {} Value python: {} for mass: {}".format(
-                perl_results[i], python_results[i], str(input_lists[i])
-            )
-            self.assertLess(
-                np.abs(python_results[i] - perl_results[i]), self.tolerance, msg=msg
-            )
-
-        # extra test:
-        self.assertEqual(
-            ktg93(10, newopts={"mmax": 300}),
-            three_part_powerlaw(10, 0.1, 0.5, 1, 300, -1.3, -2.2, -2.7),
-        )
-
-    def test_imf_tinsley1980(self):
-        with Capturing() as output:
-            self._test_imf_tinsley1980()
-
-    def _test_imf_tinsley1980(self):
-        """
-        Unittest for function imf_tinsley1980
-        """
-
-        m = 1.2
-        self.assertEqual(
-            imf_tinsley1980(m),
-            three_part_powerlaw(m, 0.1, 2.0, 10.0, 80.0, -2.0, -2.3, -3.3),
-        )
-
-    def test_imf_scalo1986(self):
-        with Capturing() as output:
-            self._test_imf_scalo1986()
-
-    def _test_imf_scalo1986(self):
-        """
-        Unittest for function imf_scalo1986
-        """
-
-        m = 1.2
-        self.assertEqual(
-            imf_scalo1986(m),
-            three_part_powerlaw(m, 0.1, 1.0, 2.0, 80.0, -2.35, -2.35, -2.70),
-        )
-
-    def test_imf_scalo1998(self):
-        with Capturing() as output:
-            self._test_imf_scalo1998()
-
-    def _test_imf_scalo1998(self):
-        """
-        Unittest for function imf_scalo1986
-        """
-
-        m = 1.2
-        self.assertEqual(
-            imf_scalo1998(m),
-            three_part_powerlaw(m, 0.1, 1.0, 10.0, 80.0, -1.2, -2.7, -2.3),
-        )
-
-    def test_imf_chabrier2003(self):
-        with Capturing() as output:
-            self._test_imf_chabrier2003()
-
-    def _test_imf_chabrier2003(self):
-        """
-        Unittest for function imf_chabrier2003
-        """
-
-        input_1 = 0
-        self.assertRaises(ValueError, imf_chabrier2003, input_1)
-
-        masses = [0.1, 0.2, 0.5, 1, 2, 10, 15, 50]
-        perl_results = [
-            5.64403964849588,
-            2.40501495673496,
-            0.581457346702825,
-            0.159998782068074,
-            0.0324898485372181,
-            0.000801893469684309,
-            0.000315578044662863,
-            1.97918170035704e-05,
-        ]
-        python_results = [imf_chabrier2003(m) for m in masses]
-
-        # GO over the results and check whether they are equal (within tolerance)
-        for i in range(len(python_results)):
-            msg = "Error: Value perl: {} Value python: {} for mass: {}".format(
-                perl_results[i], python_results[i], str(masses[i])
-            )
-            self.assertLess(
-                np.abs(python_results[i] - perl_results[i]), self.tolerance, msg=msg
-            )
-
-    def test_duquennoy1991(self):
-        with Capturing() as output:
-            self._test_duquennoy1991()
-
-    def _test_duquennoy1991(self):
-        """
-        Unittest for function duquennoy1991
-        """
-
-        self.assertEqual(duquennoy1991(4.2), gaussian(4.2, 4.8, 2.3, -2, 12))
-
-    def test_gaussian(self):
-        with Capturing() as output:
-            self._test_gaussian()
-
-    def _test_gaussian(self):
-        """
-        unittest for three_part_power_law
-        """
-
-        perl_results = [
-            0.00218800520299544,
-            0.0121641269671571,
-            0.0657353455837751,
-            0.104951743573429,
-            0.16899534495487,
-            0.0134332780385336,
-        ]
-        python_results = []
-        input_lists = []
-
-        for logper in self.logper_list:
-            input_lists.append(logper)
-            python_results.append(gaussian(logper, 4.8, 2.3, -2.0, 12.0))
-
-        # GO over the results and check whether they are equal (within tolerance)
-        for i in range(len(python_results)):
-            msg = "Error: Value perl: {} Value python: {} for logper: {}".format(
-                perl_results[i], python_results[i], str(input_lists[i])
-            )
-            self.assertLess(
-                np.abs(python_results[i] - perl_results[i]), self.tolerance, msg=msg
-            )
-
-        # Extra test:
-        self.assertTrue(
-            gaussian(15, 4.8, 2.3, -2.0, 12.0) == 0,
-            msg="Probability should be 0 because the input period is out of bounds",
-        )
-
-    def test_Arenou2010_binary_fraction(self):
-        with Capturing() as output:
-            self._test_Arenou2010_binary_fraction()
-
-    def _test_Arenou2010_binary_fraction(self):
-        """
-        unittest for three_part_power_law
-        """
-
-        perl_results = [
-            0.123079723518677,
-            0.178895136157746,
-            0.541178340047153,
-            0.838798485820276,
-            0.838799998443204,
-            0.8388,
-        ]
-        python_results = []
-        input_lists = []
-
-        for mass in self.mass_list:
-            input_lists.append(mass)
-            python_results.append(Arenou2010_binary_fraction(mass))
-
-        # GO over the results and check whether they are equal (within tolerance)
-        for i in range(len(python_results)):
-            msg = "Error: Value perl: {} Value python: {} for mass: {}".format(
-                perl_results[i], python_results[i], str(input_lists[i])
-            )
-            self.assertLess(
-                np.abs(python_results[i] - perl_results[i]), self.tolerance, msg=msg
-            )
-
-    def test_raghavan2010_binary_fraction(self):
-        with Capturing() as output:
-            self._test_raghavan2010_binary_fraction()
-
-    def _test_raghavan2010_binary_fraction(self):
-        """
-        unittest for three_part_power_law
-        """
-
-        perl_results = [0.304872297931597, 0.334079955706623, 0.41024, 1, 1, 1]
-        python_results = []
-        input_lists = []
-
-        for mass in self.mass_list:
-            input_lists.append(mass)
-            python_results.append(raghavan2010_binary_fraction(mass))
-
-        # GO over the results and check whether they are equal (within tolerance)
-        for i in range(len(python_results)):
-            msg = "Error: Value perl: {} Value python: {} for mass: {}".format(
-                perl_results[i], python_results[i], str(input_lists[i])
-            )
-            self.assertLess(
-                np.abs(python_results[i] - perl_results[i]), self.tolerance, msg=msg
-            )
-
-    def test_Izzard2012_period_distribution(self):
-        with Capturing() as output:
-            self._test_Izzard2012_period_distribution()
-
-    def _test_Izzard2012_period_distribution(self):
-        """
-        unittest for three_part_power_law
-        """
-
-        perl_results = [
-            0,
-            0.00941322840619318,
-            0.0575068231479569,
-            0.0963349886047932,
-            0.177058537292581,
-            0.0165713385659234,
-            0,
-            0.00941322840619318,
-            0.0575068231479569,
-            0.0963349886047932,
-            0.177058537292581,
-            0.0165713385659234,
-            0,
-            0.00941322840619318,
-            0.0575068231479569,
-            0.0963349886047932,
-            0.177058537292581,
-            0.0165713385659234,
-            0,
-            7.61631504133159e-09,
-            0.168028727846997,
-            0.130936282216512,
-            0.0559170865520968,
-            0.0100358604460285,
-            0,
-            2.08432736869149e-21,
-            0.18713622563288,
-            0.143151383185002,
-            0.0676299576972089,
-            0.0192427864870784,
-            0,
-            1.1130335685003e-24,
-            0.194272603987661,
-            0.14771508552257,
-            0.0713078479280884,
-            0.0221093965810181,
-        ]
-        python_results = []
-        input_lists = []
-
-        for mass in self.mass_list:
-            for per in self.per_list:
-                input_lists.append([mass, per])
-
-                python_results.append(Izzard2012_period_distribution(per, mass))
-
-        # GO over the results and check whether they are equal (within tolerance)
-        for i in range(len(python_results)):
-            msg = "Error: Value perl: {} Value python: {} for mass, per: {}".format(
-                perl_results[i], python_results[i], str(input_lists[i])
-            )
-            self.assertLess(
-                np.abs(python_results[i] - perl_results[i]), self.tolerance, msg=msg
-            )
-
-    def test_flatsections(self):
-        with Capturing() as output:
-            self._test_flatsections()
-
-    def _test_flatsections(self):
-        """
-        unittest for three_part_power_law
-        """
-
-        perl_results = [
-            1.01010101010101,
-            1.01010101010101,
-            1.01010101010101,
-            1.01010101010101,
-            1.01010101010101,
-            1.01010101010101,
-        ]
-        python_results = []
-        input_lists = []
-
-        for q in self.q_list:
-            input_lists.append(q)
-            python_results.append(
-                flatsections(q, [{"min": 0.01, "max": 1.0, "height": 1.0}])
-            )
-
-        # GO over the results and check whether they are equal (within tolerance)
-        for i in range(len(python_results)):
-            msg = "Error: Value perl: {} Value python: {} for q: {}".format(
-                perl_results[i], python_results[i], str(input_lists[i])
-            )
-            self.assertLess(
-                np.abs(python_results[i] - perl_results[i]), self.tolerance, msg=msg
-            )
-
-    def test_sana12(self):
-        with Capturing() as output:
-            self._test_sana12()
-
-    def _test_sana12(self):
-        """
-        unittest for three_part_power_law
-        """
-
-        perl_results = [
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.481676471294883,
-            0.481676471294883,
-            0.131020615300798,
-            0.102503482445846,
-            0.0678037785559114,
-            0.066436408359805,
-            0.481676471294883,
-            0.481676471294883,
-            0.131020615300798,
-            0.102503482445846,
-            0.0678037785559114,
-            0.066436408359805,
-            0.481676471294883,
-            0.481676471294883,
-            0.131020615300798,
-            0.102503482445846,
-            0.0678037785559114,
-            0.066436408359805,
-            0.481676471294883,
-            0.481676471294883,
-            0.131020615300798,
-            0.102503482445846,
-            0.0678037785559114,
-            0.066436408359805,
-            0.481676471294883,
-            0.481676471294883,
-            0.131020615300798,
-            0.102503482445846,
-            0.0678037785559114,
-            0.066436408359805,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.121764808010258,
-            0.481676471294883,
-            0.481676471294883,
-            0.131020615300798,
-            0.102503482445846,
-            0.0678037785559114,
-            0.066436408359805,
-            0.481676471294883,
-            0.481676471294883,
-            0.131020615300798,
-            0.102503482445846,
-            0.0678037785559114,
-            0.066436408359805,
-            0.481676471294883,
-            0.481676471294883,
-            0.131020615300798,
-            0.102503482445846,
-            0.0678037785559114,
-            0.066436408359805,
-            0.481676471294883,
-            0.481676471294883,
-            0.131020615300798,
-            0.102503482445846,
-            0.0678037785559114,
-            0.066436408359805,
-            0.481676471294883,
-            0.481676471294883,
-            0.131020615300798,
-            0.102503482445846,
-            0.0678037785559114,
-            0.066436408359805,
-        ]
-        python_results = []
-        input_lists = []
-
-        for mass in self.mass_list:
-            for q in self.q_list:
-                for per in self.per_list:
-                    mass_2 = mass * q
-
-                    sep = calc_sep_from_period(mass, mass_2, per)
-                    sep_min = calc_sep_from_period(mass, mass_2, 10 ** 0.15)
-                    sep_max = calc_sep_from_period(mass, mass_2, 10 ** 5.5)
-
-                    input_lists.append([mass, mass_2, per])
-
-                    python_results.append(
-                        sana12(
-                            mass, mass_2, sep, per, sep_min, sep_max, 0.15, 5.5, -0.55
-                        )
-                    )
-
-        # GO over the results and check whether they are equal (within tolerance)
-        for i in range(len(python_results)):
-            msg = "Error: Value perl: {} Value python: {} for mass, mass2, per: {}".format(
-                perl_results[i], python_results[i], str(input_lists[i])
-            )
-            self.assertLess(
-                np.abs(python_results[i] - perl_results[i]), self.tolerance, msg=msg
-            )
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/binarycpython/tests/tests_population_extensions/test__distribution_functions.py b/binarycpython/tests/tests_population_extensions/test__distribution_functions.py
new file mode 100644
index 000000000..556bff92a
--- /dev/null
+++ b/binarycpython/tests/tests_population_extensions/test__distribution_functions.py
@@ -0,0 +1,828 @@
+"""
+Module containing the unittests for the distribution functions. 
+"""
+
+import unittest
+import numpy as np
+
+from binarycpython.utils.useful_funcs import calc_sep_from_period
+from binarycpython.utils.functions import Capturing, temp_dir
+
+from binarycpython.utils.grid import Population
+
+TMP_DIR = temp_dir("tests", "test_distributions")
+
+MASS_LIST = [0.1, 0.2, 1, 10, 15, 50]
+LOGPER_LIST = [-2, -0.5, 1.6, 2.5, 5.3, 10]
+Q_LIST = [0.01, 0.2, 0.4, 0.652, 0.823, 1]
+PER_LIST = [10 ** logper for logper in LOGPER_LIST]
+TOLERANCE = 1e-5
+
+class test_flat(unittest.TestCase):
+    """
+    Class for unit test of flat
+    """
+
+    def test_flat(self):
+        with Capturing() as output:
+            self._test_flat()
+
+    def _test_flat(self):
+        """
+        Unittest for the function flat
+        """
+
+        distribution_functions_pop = Population()
+
+        output_1 = distribution_functions_pop.flat()
+
+        self.assertTrue(isinstance(output_1, float))
+        self.assertEqual(output_1, 1.0)
+
+
+class test_number(unittest.TestCase):
+    """
+    Class for unit test of number
+    """
+
+    def test_number(self):
+        with Capturing() as output:
+            self._test_number()
+
+    def _test_number(self):
+        """
+        Unittest for function number
+        """
+
+        distribution_functions_pop = Population()
+
+        input_1 = 1.0
+        output_1 = distribution_functions_pop.number(input_1)
+
+        self.assertEqual(input_1, output_1)
+
+
+class test_const(unittest.TestCase):
+    """
+    Class for unit test of number
+    """
+
+    def test_const(self):
+        with Capturing() as output:
+            self._test_const()
+
+    def _test_const(self):
+        """
+        Unittest for function const
+        """
+
+        distribution_functions_pop = Population()
+
+        output_1 = distribution_functions_pop.const_distribution(min_bound=0, max_bound=2)
+        self.assertEqual(
+            output_1, 0.5, msg="Value should be 0.5, but is {}".format(output_1)
+        )
+
+        output_2 = distribution_functions_pop.const_distribution(min_bound=0, max_bound=2, val=3)
+        self.assertEqual(
+            output_2, 0, msg="Value should be 0, but is {}".format(output_2)
+        )
+
+
+class test_powerlaw(unittest.TestCase):
+    """
+    Class for unit test of powerlaw
+    """
+
+    def test_powerlaw(self):
+        with Capturing() as output:
+            self._test_powerlaw()
+
+    def _test_powerlaw(self):
+        """
+        unittest for the powerlaw test
+        """
+
+        distribution_functions_pop = Population()
+
+        perl_results = [
+            0,
+            0,
+            1.30327367546194,
+            0.00653184128064016,
+            0.00257054805572128,
+            0.000161214690242696,
+        ]
+        python_results = []
+        input_lists = []
+
+        for mass in MASS_LIST:
+            input_lists.append(mass)
+            python_results.append(distribution_functions_pop.powerlaw(1, 100, -2.3, mass))
+
+        # GO over the results and check whether they are equal (within tolerance)
+        for i in range(len(python_results)):
+            msg = "Error: Value perl: {} Value python: {} for mass, per: {}".format(
+                perl_results[i], python_results[i], str(input_lists[i])
+            )
+            self.assertLess(np.abs(python_results[i] - perl_results[i]), TOLERANCE)
+
+        # extra test for k = -1
+        self.assertRaises(ValueError, distribution_functions_pop.powerlaw, 1, 100, -1, 10)
+
+
+# class test_three_part_power_law(unittest.TestCase):
+#     """
+#     Class for unit test of three_part_power_law
+#     """
+
+#     def test_three_part_power_law(self):
+#         with Capturing() as output:
+#             self._test_three_part_power_law()
+
+#     def _test_three_part_power_law(self):
+#         """
+#         unittest for three_part_power_law
+#         """
+
+#         distribution_functions_pop = Population()
+
+#         perl_results = [
+#             10.0001044752901,
+#             2.03065220596677,
+#             0.0501192469795434,
+#             0.000251191267451594,
+#             9.88540897458207e-05,
+#             6.19974072148769e-06,
+#         ]
+#         python_results = []
+#         input_lists = []
+
+#         for mass in MASS_LIST:
+#             input_lists.append(mass)
+#             python_results.append(
+#                 distribution_functions_pop.three_part_powerlaw(mass, 0.08, 0.1, 1, 300, -1.3, -2.3, -2.3)
+#             )
+
+#         # GO over the results and check whether they are equal (within tolerance)
+#         for i in range(len(python_results)):
+#             msg = "Error: Value perl: {} Value python: {} for mass, per: {}".format(
+#                 perl_results[i], python_results[i], str(input_lists[i])
+#             )
+#             self.assertLess(
+#                 np.abs(python_results[i] - perl_results[i]), TOLERANCE, msg=msg
+#             )
+
+#         # Extra test:
+#         # M < M0
+#         self.assertTrue(
+#             distribution_functions_pop.three_part_powerlaw(0.05, 0.08, 0.1, 1, 300, -1.3, -2.3, -2.3) == 0,
+#             msg="Probability should be zero as M < M0",
+#         )
+
+
+# class test_Kroupa2001(unittest.TestCase):
+#     """
+#     Class for unit test of Kroupa2001
+#     """
+
+#     def test_Kroupa2001(self):
+#         with Capturing() as output:
+#             self._test_Kroupa2001()
+
+#     def _test_Kroupa2001(self):
+#         """
+#         unittest for three_part_power_law
+#         """
+
+#         distribution_functions_pop = Population()
+
+#         perl_results = [
+#             0,  # perl value is actually 5.71196495365248
+#             2.31977861075353,
+#             0.143138195684851,
+#             0.000717390363216896,
+#             0.000282322598503135,
+#             1.77061658757533e-05,
+#         ]
+#         python_results = []
+#         input_lists = []
+
+#         for mass in MASS_LIST:
+#             input_lists.append(mass)
+#             python_results.append(distribution_functions_pop.Kroupa2001(mass))
+
+#         # GO over the results and check whether they are equal (within tolerance)
+#         for i in range(len(python_results)):
+#             msg = "Error: Value perl: {} Value python: {} for mass: {}".format(
+#                 perl_results[i], python_results[i], str(input_lists[i])
+#             )
+#             self.assertLess(
+#                 np.abs(python_results[i] - perl_results[i]), TOLERANCE, msg=msg
+#             )
+
+#         # Extra tests:
+#         self.assertEqual(
+#             distribution_functions_pop.Kroupa2001(10, newopts={"mmax": 300}),
+#             distribution_functions_pop.three_part_powerlaw(10, 0.1, 0.5, 1, 300, -1.3, -2.3, -2.3),
+#         )
+
+# class TestDistributions(unittest.TestCase):
+#     """
+#     Unittest class
+
+#     # https://stackoverflow.com/questions/17353213/init-for-unittest-testcase
+#     """
+
+#     def __init__(self, *args, **kwargs):
+#         """
+#         init
+#         """
+#         super(TestDistributions, self).__init__(*args, **kwargs)
+
+#     def test_ktg93(self):
+#         with Capturing() as output:
+#             self._test_ktg93()
+
+#     def _test_ktg93(self):
+#         """
+#         unittest for three_part_power_law
+#         """
+
+#         perl_results = [
+#             0,  # perl value is actually 5.79767807698379 but that is not correct
+#             2.35458895566605,
+#             0.155713799148675,
+#             0.000310689875361984,
+#             0.000103963454405194,
+#             4.02817276824841e-06,
+#         ]
+#         python_results = []
+#         input_lists = []
+
+#         for mass in self.mass_list:
+#             input_lists.append(mass)
+#             python_results.append(ktg93(mass))
+
+#         # GO over the results and check whether they are equal (within tolerance)
+#         for i in range(len(python_results)):
+#             msg = "Error: Value perl: {} Value python: {} for mass: {}".format(
+#                 perl_results[i], python_results[i], str(input_lists[i])
+#             )
+#             self.assertLess(
+#                 np.abs(python_results[i] - perl_results[i]), self.tolerance, msg=msg
+#             )
+
+#         # extra test:
+#         self.assertEqual(
+#             ktg93(10, newopts={"mmax": 300}),
+#             three_part_powerlaw(10, 0.1, 0.5, 1, 300, -1.3, -2.2, -2.7),
+#         )
+
+#     def test_imf_tinsley1980(self):
+#         with Capturing() as output:
+#             self._test_imf_tinsley1980()
+
+#     def _test_imf_tinsley1980(self):
+#         """
+#         Unittest for function imf_tinsley1980
+#         """
+
+#         m = 1.2
+#         self.assertEqual(
+#             imf_tinsley1980(m),
+#             three_part_powerlaw(m, 0.1, 2.0, 10.0, 80.0, -2.0, -2.3, -3.3),
+#         )
+
+#     def test_imf_scalo1986(self):
+#         with Capturing() as output:
+#             self._test_imf_scalo1986()
+
+#     def _test_imf_scalo1986(self):
+#         """
+#         Unittest for function imf_scalo1986
+#         """
+
+#         m = 1.2
+#         self.assertEqual(
+#             imf_scalo1986(m),
+#             three_part_powerlaw(m, 0.1, 1.0, 2.0, 80.0, -2.35, -2.35, -2.70),
+#         )
+
+#     def test_imf_scalo1998(self):
+#         with Capturing() as output:
+#             self._test_imf_scalo1998()
+
+#     def _test_imf_scalo1998(self):
+#         """
+#         Unittest for function imf_scalo1986
+#         """
+
+#         m = 1.2
+#         self.assertEqual(
+#             imf_scalo1998(m),
+#             three_part_powerlaw(m, 0.1, 1.0, 10.0, 80.0, -1.2, -2.7, -2.3),
+#         )
+
+#     def test_imf_chabrier2003(self):
+#         with Capturing() as output:
+#             self._test_imf_chabrier2003()
+
+#     def _test_imf_chabrier2003(self):
+#         """
+#         Unittest for function imf_chabrier2003
+#         """
+
+#         input_1 = 0
+#         self.assertRaises(ValueError, imf_chabrier2003, input_1)
+
+#         masses = [0.1, 0.2, 0.5, 1, 2, 10, 15, 50]
+#         perl_results = [
+#             5.64403964849588,
+#             2.40501495673496,
+#             0.581457346702825,
+#             0.159998782068074,
+#             0.0324898485372181,
+#             0.000801893469684309,
+#             0.000315578044662863,
+#             1.97918170035704e-05,
+#         ]
+#         python_results = [imf_chabrier2003(m) for m in masses]
+
+#         # GO over the results and check whether they are equal (within tolerance)
+#         for i in range(len(python_results)):
+#             msg = "Error: Value perl: {} Value python: {} for mass: {}".format(
+#                 perl_results[i], python_results[i], str(masses[i])
+#             )
+#             self.assertLess(
+#                 np.abs(python_results[i] - perl_results[i]), self.tolerance, msg=msg
+#             )
+
+#     def test_duquennoy1991(self):
+#         with Capturing() as output:
+#             self._test_duquennoy1991()
+
+#     def _test_duquennoy1991(self):
+#         """
+#         Unittest for function duquennoy1991
+#         """
+
+#         self.assertEqual(duquennoy1991(4.2), gaussian(4.2, 4.8, 2.3, -2, 12))
+
+#     def test_gaussian(self):
+#         with Capturing() as output:
+#             self._test_gaussian()
+
+#     def _test_gaussian(self):
+#         """
+#         unittest for three_part_power_law
+#         """
+
+#         perl_results = [
+#             0.00218800520299544,
+#             0.0121641269671571,
+#             0.0657353455837751,
+#             0.104951743573429,
+#             0.16899534495487,
+#             0.0134332780385336,
+#         ]
+#         python_results = []
+#         input_lists = []
+
+#         for logper in self.logper_list:
+#             input_lists.append(logper)
+#             python_results.append(gaussian(logper, 4.8, 2.3, -2.0, 12.0))
+
+#         # GO over the results and check whether they are equal (within tolerance)
+#         for i in range(len(python_results)):
+#             msg = "Error: Value perl: {} Value python: {} for logper: {}".format(
+#                 perl_results[i], python_results[i], str(input_lists[i])
+#             )
+#             self.assertLess(
+#                 np.abs(python_results[i] - perl_results[i]), self.tolerance, msg=msg
+#             )
+
+#         # Extra test:
+#         self.assertTrue(
+#             gaussian(15, 4.8, 2.3, -2.0, 12.0) == 0,
+#             msg="Probability should be 0 because the input period is out of bounds",
+#         )
+
+#     def test_Arenou2010_binary_fraction(self):
+#         with Capturing() as output:
+#             self._test_Arenou2010_binary_fraction()
+
+#     def _test_Arenou2010_binary_fraction(self):
+#         """
+#         unittest for three_part_power_law
+#         """
+
+#         perl_results = [
+#             0.123079723518677,
+#             0.178895136157746,
+#             0.541178340047153,
+#             0.838798485820276,
+#             0.838799998443204,
+#             0.8388,
+#         ]
+#         python_results = []
+#         input_lists = []
+
+#         for mass in self.mass_list:
+#             input_lists.append(mass)
+#             python_results.append(Arenou2010_binary_fraction(mass))
+
+#         # GO over the results and check whether they are equal (within tolerance)
+#         for i in range(len(python_results)):
+#             msg = "Error: Value perl: {} Value python: {} for mass: {}".format(
+#                 perl_results[i], python_results[i], str(input_lists[i])
+#             )
+#             self.assertLess(
+#                 np.abs(python_results[i] - perl_results[i]), self.tolerance, msg=msg
+#             )
+
+#     def test_raghavan2010_binary_fraction(self):
+#         with Capturing() as output:
+#             self._test_raghavan2010_binary_fraction()
+
+#     def _test_raghavan2010_binary_fraction(self):
+#         """
+#         unittest for three_part_power_law
+#         """
+
+#         perl_results = [0.304872297931597, 0.334079955706623, 0.41024, 1, 1, 1]
+#         python_results = []
+#         input_lists = []
+
+#         for mass in self.mass_list:
+#             input_lists.append(mass)
+#             python_results.append(raghavan2010_binary_fraction(mass))
+
+#         # GO over the results and check whether they are equal (within tolerance)
+#         for i in range(len(python_results)):
+#             msg = "Error: Value perl: {} Value python: {} for mass: {}".format(
+#                 perl_results[i], python_results[i], str(input_lists[i])
+#             )
+#             self.assertLess(
+#                 np.abs(python_results[i] - perl_results[i]), self.tolerance, msg=msg
+#             )
+
+#     def test_Izzard2012_period_distribution(self):
+#         with Capturing() as output:
+#             self._test_Izzard2012_period_distribution()
+
+#     def _test_Izzard2012_period_distribution(self):
+#         """
+#         unittest for three_part_power_law
+#         """
+
+#         perl_results = [
+#             0,
+#             0.00941322840619318,
+#             0.0575068231479569,
+#             0.0963349886047932,
+#             0.177058537292581,
+#             0.0165713385659234,
+#             0,
+#             0.00941322840619318,
+#             0.0575068231479569,
+#             0.0963349886047932,
+#             0.177058537292581,
+#             0.0165713385659234,
+#             0,
+#             0.00941322840619318,
+#             0.0575068231479569,
+#             0.0963349886047932,
+#             0.177058537292581,
+#             0.0165713385659234,
+#             0,
+#             7.61631504133159e-09,
+#             0.168028727846997,
+#             0.130936282216512,
+#             0.0559170865520968,
+#             0.0100358604460285,
+#             0,
+#             2.08432736869149e-21,
+#             0.18713622563288,
+#             0.143151383185002,
+#             0.0676299576972089,
+#             0.0192427864870784,
+#             0,
+#             1.1130335685003e-24,
+#             0.194272603987661,
+#             0.14771508552257,
+#             0.0713078479280884,
+#             0.0221093965810181,
+#         ]
+#         python_results = []
+#         input_lists = []
+
+#         for mass in self.mass_list:
+#             for per in self.per_list:
+#                 input_lists.append([mass, per])
+
+#                 python_results.append(Izzard2012_period_distribution(per, mass))
+
+#         # GO over the results and check whether they are equal (within tolerance)
+#         for i in range(len(python_results)):
+#             msg = "Error: Value perl: {} Value python: {} for mass, per: {}".format(
+#                 perl_results[i], python_results[i], str(input_lists[i])
+#             )
+#             self.assertLess(
+#                 np.abs(python_results[i] - perl_results[i]), self.tolerance, msg=msg
+#             )
+
+#     def test_flatsections(self):
+#         with Capturing() as output:
+#             self._test_flatsections()
+
+#     def _test_flatsections(self):
+#         """
+#         unittest for three_part_power_law
+#         """
+
+#         perl_results = [
+#             1.01010101010101,
+#             1.01010101010101,
+#             1.01010101010101,
+#             1.01010101010101,
+#             1.01010101010101,
+#             1.01010101010101,
+#         ]
+#         python_results = []
+#         input_lists = []
+
+#         for q in self.q_list:
+#             input_lists.append(q)
+#             python_results.append(
+#                 flatsections(q, [{"min": 0.01, "max": 1.0, "height": 1.0}])
+#             )
+
+#         # GO over the results and check whether they are equal (within tolerance)
+#         for i in range(len(python_results)):
+#             msg = "Error: Value perl: {} Value python: {} for q: {}".format(
+#                 perl_results[i], python_results[i], str(input_lists[i])
+#             )
+#             self.assertLess(
+#                 np.abs(python_results[i] - perl_results[i]), self.tolerance, msg=msg
+#             )
+
+#     def test_sana12(self):
+#         with Capturing() as output:
+#             self._test_sana12()
+
+#     def _test_sana12(self):
+#         """
+#         unittest for three_part_power_law
+#         """
+
+#         perl_results = [
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.481676471294883,
+#             0.481676471294883,
+#             0.131020615300798,
+#             0.102503482445846,
+#             0.0678037785559114,
+#             0.066436408359805,
+#             0.481676471294883,
+#             0.481676471294883,
+#             0.131020615300798,
+#             0.102503482445846,
+#             0.0678037785559114,
+#             0.066436408359805,
+#             0.481676471294883,
+#             0.481676471294883,
+#             0.131020615300798,
+#             0.102503482445846,
+#             0.0678037785559114,
+#             0.066436408359805,
+#             0.481676471294883,
+#             0.481676471294883,
+#             0.131020615300798,
+#             0.102503482445846,
+#             0.0678037785559114,
+#             0.066436408359805,
+#             0.481676471294883,
+#             0.481676471294883,
+#             0.131020615300798,
+#             0.102503482445846,
+#             0.0678037785559114,
+#             0.066436408359805,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.121764808010258,
+#             0.481676471294883,
+#             0.481676471294883,
+#             0.131020615300798,
+#             0.102503482445846,
+#             0.0678037785559114,
+#             0.066436408359805,
+#             0.481676471294883,
+#             0.481676471294883,
+#             0.131020615300798,
+#             0.102503482445846,
+#             0.0678037785559114,
+#             0.066436408359805,
+#             0.481676471294883,
+#             0.481676471294883,
+#             0.131020615300798,
+#             0.102503482445846,
+#             0.0678037785559114,
+#             0.066436408359805,
+#             0.481676471294883,
+#             0.481676471294883,
+#             0.131020615300798,
+#             0.102503482445846,
+#             0.0678037785559114,
+#             0.066436408359805,
+#             0.481676471294883,
+#             0.481676471294883,
+#             0.131020615300798,
+#             0.102503482445846,
+#             0.0678037785559114,
+#             0.066436408359805,
+#         ]
+#         python_results = []
+#         input_lists = []
+
+#         for mass in self.mass_list:
+#             for q in self.q_list:
+#                 for per in self.per_list:
+#                     mass_2 = mass * q
+
+#                     sep = calc_sep_from_period(mass, mass_2, per)
+#                     sep_min = calc_sep_from_period(mass, mass_2, 10 ** 0.15)
+#                     sep_max = calc_sep_from_period(mass, mass_2, 10 ** 5.5)
+
+#                     input_lists.append([mass, mass_2, per])
+
+#                     python_results.append(
+#                         sana12(
+#                             mass, mass_2, sep, per, sep_min, sep_max, 0.15, 5.5, -0.55
+#                         )
+#                     )
+
+#         # GO over the results and check whether they are equal (within tolerance)
+#         for i in range(len(python_results)):
+#             msg = "Error: Value perl: {} Value python: {} for mass, mass2, per: {}".format(
+#                 perl_results[i], python_results[i], str(input_lists[i])
+#             )
+#             self.assertLess(
+#                 np.abs(python_results[i] - perl_results[i]), self.tolerance, msg=msg
+#             )
+
+
+if __name__ == "__main__":
+    unittest.main()
diff --git a/binarycpython/tests/test_grid_options_defaults.py b/binarycpython/tests/tests_population_extensions/test__grid_options_defaults.py
similarity index 100%
rename from binarycpython/tests/test_grid_options_defaults.py
rename to binarycpython/tests/tests_population_extensions/test__grid_options_defaults.py
diff --git a/binarycpython/tests/test_hpc_functions.py b/binarycpython/tests/tests_population_extensions/test__hpc_functions.py
similarity index 100%
rename from binarycpython/tests/test_hpc_functions.py
rename to binarycpython/tests/tests_population_extensions/test__hpc_functions.py
diff --git a/binarycpython/tests/test_spacing_functions.py b/binarycpython/tests/tests_population_extensions/test__spacing_functions.py
similarity index 100%
rename from binarycpython/tests/test_spacing_functions.py
rename to binarycpython/tests/tests_population_extensions/test__spacing_functions.py
diff --git a/binarycpython/tests/tmp_functions.py b/binarycpython/tests/tmp_functions.py
index a5dcbeecb..6fc3ab08f 100644
--- a/binarycpython/tests/tmp_functions.py
+++ b/binarycpython/tests/tmp_functions.py
@@ -90,264 +90,288 @@ from binarycpython.utils.ensemble import (
 
 
 
-class test_inspect_dict(unittest.TestCase):
-    """
-    Unittests for function inspect_dict
-    """
-
-    def test_compare_dict(self):
-        with Capturing() as output:
-            self._test_compare_dict()
-
-    def _test_compare_dict(self):
-        """
-        Test checking if inspect_dict returns the correct structure by comparing it to known value
-        """
-
-        input_dict = {
-            "int": 1,
-            "float": 1.2,
-            "list": [1, 2, 3],
-            "function": os.path.isfile,
-            "dict": {"int": 1, "float": 1.2},
-        }
-        output_dict = inspect_dict(input_dict)
-        compare_dict = {
-            "int": int,
-            "float": float,
-            "list": list,
-            "function": os.path.isfile.__class__,
-            "dict": {"int": int, "float": float},
-        }
-        self.assertTrue(compare_dict == output_dict)
-
-    def test_compare_dict_with_print(self):
-        with Capturing() as output:
-            self._test_compare_dict_with_print()
-
-    def _test_compare_dict_with_print(self):
-        """
-        Test checking output is printed
-        """
-
-        input_dict = {
-            "int": 1,
-            "float": 1.2,
-            "list": [1, 2, 3],
-            "function": os.path.isfile,
-            "dict": {"int": 1, "float": 1.2},
-        }
-        output_dict = inspect_dict(input_dict, print_structure=True)
-
-
-class test_merge_dicts(unittest.TestCase):
-    """
-    Unittests for function merge_dicts
-    """
-
-    def test_empty(self):
-        with Capturing() as output:
-            self._test_empty()
-
-    def _test_empty(self):
-        """
-        Test merging an empty dict
-        """
-
-        input_dict = {
-            "int": 1,
-            "float": 1.2,
-            "list": [1, 2, 3],
-            "function": os.path.isfile,
-            "dict": {"int": 1, "float": 1.2},
-        }
-        dict_2 = {}
-        output_dict = merge_dicts(input_dict, dict_2)
-        self.assertTrue(output_dict == input_dict)
-
-    def test_unequal_types(self):
-        with Capturing() as output:
-            self._test_unequal_types()
-
-    def _test_unequal_types(self):
-        """
-        Test merging unequal types: should raise valueError
-        """
-
-        dict_1 = {"input": 10}
-        dict_2 = {"input": "hello"}
-
-        self.assertRaises(ValueError, merge_dicts, dict_1, dict_2)
-
-    def test_bools(self):
-        with Capturing() as output:
-            self._test_bools()
-
-    def _test_bools(self):
-        """
-        Test merging dict with booleans
-        """
-
-        dict_1 = {"bool": True}
-        dict_2 = {"bool": False}
-        output_dict = merge_dicts(dict_1, dict_2)
-
-        self.assertTrue(isinstance(output_dict["bool"], bool))
-        self.assertTrue(output_dict["bool"])
-
-    def test_ints(self):
-        with Capturing() as _:
-            self._test_ints()
-
-    def _test_ints(self):
-        """
-        Test merging dict with ints
-        """
-
-        dict_1 = {"int": 2}
-        dict_2 = {"int": 1}
-        output_dict = merge_dicts(dict_1, dict_2)
-
-        self.assertTrue(isinstance(output_dict["int"], int))
-        self.assertEqual(output_dict["int"], 3)
-
-    def test_floats(self):
-        with Capturing() as output:
-            self._test_floats()
-
-    def _test_floats(self):
-        """
-        Test merging dict with floats
-        """
-
-        dict_1 = {"float": 4.5}
-        dict_2 = {"float": 4.6}
-        output_dict = merge_dicts(dict_1, dict_2)
-
-        self.assertTrue(isinstance(output_dict["float"], float))
-        self.assertEqual(output_dict["float"], 9.1)
-
-    def test_lists(self):
-        with Capturing() as output:
-            self._test_lists()
-
-    def _test_lists(self):
-        """
-        Test merging dict with lists
-        """
-
-        dict_1 = {"list": [1, 2]}
-        dict_2 = {"list": [3, 4]}
-        output_dict = merge_dicts(dict_1, dict_2)
-
-        self.assertTrue(isinstance(output_dict["list"], list))
-        self.assertEqual(output_dict["list"], [1, 2, 3, 4])
-
-    def test_dicts(self):
-        with Capturing() as _:
-            self._test_dicts()
+# class test_inspect_dict(unittest.TestCase):
+#     """
+#     Unittests for function inspect_dict
+#     """
+
+#     def test_compare_dict(self):
+#         with Capturing() as output:
+#             self._test_compare_dict()
+
+#     def _test_compare_dict(self):
+#         """
+#         Test checking if inspect_dict returns the correct structure by comparing it to known value
+#         """
+
+#         input_dict = {
+#             "int": 1,
+#             "float": 1.2,
+#             "list": [1, 2, 3],
+#             "function": os.path.isfile,
+#             "dict": {"int": 1, "float": 1.2},
+#         }
+#         output_dict = inspect_dict(input_dict)
+#         compare_dict = {
+#             "int": int,
+#             "float": float,
+#             "list": list,
+#             "function": os.path.isfile.__class__,
+#             "dict": {"int": int, "float": float},
+#         }
+#         self.assertTrue(compare_dict == output_dict)
+
+#     def test_compare_dict_with_print(self):
+#         with Capturing() as output:
+#             self._test_compare_dict_with_print()
+
+#     def _test_compare_dict_with_print(self):
+#         """
+#         Test checking output is printed
+#         """
+
+#         input_dict = {
+#             "int": 1,
+#             "float": 1.2,
+#             "list": [1, 2, 3],
+#             "function": os.path.isfile,
+#             "dict": {"int": 1, "float": 1.2},
+#         }
+#         output_dict = inspect_dict(input_dict, print_structure=True)
+
+
+# class test_merge_dicts(unittest.TestCase):
+#     """
+#     Unittests for function merge_dicts
+#     """
+
+#     def test_empty(self):
+#         with Capturing() as output:
+#             self._test_empty()
+
+#     def _test_empty(self):
+#         """
+#         Test merging an empty dict
+#         """
+
+#         input_dict = {
+#             "int": 1,
+#             "float": 1.2,
+#             "list": [1, 2, 3],
+#             "function": os.path.isfile,
+#             "dict": {"int": 1, "float": 1.2},
+#         }
+#         dict_2 = {}
+#         output_dict = merge_dicts(input_dict, dict_2)
+#         self.assertTrue(output_dict == input_dict)
+
+#     def test_unequal_types(self):
+#         with Capturing() as output:
+#             self._test_unequal_types()
 
-    def _test_dicts(self):
-        """
-        Test merging dict with dicts
-        """
+#     def _test_unequal_types(self):
+#         """
+#         Test merging unequal types: should raise valueError
+#         """
 
-        dict_1 = {"dict": {"same": 1, "other_1": 2.0}}
-        dict_2 = {"dict": {"same": 2, "other_2": [4.0]}}
-        output_dict = merge_dicts(dict_1, dict_2)
+#         dict_1 = {"input": 10}
+#         dict_2 = {"input": "hello"}
 
-        self.assertTrue(isinstance(output_dict["dict"], dict))
-        self.assertEqual(
-            output_dict["dict"], {"same": 3, "other_1": 2.0, "other_2": [4.0]}
-        )
+#         self.assertRaises(ValueError, merge_dicts, dict_1, dict_2)
 
-    def test_unsupported(self):
-        with Capturing() as output:
-            self._test_unsupported()
+#     def test_bools(self):
+#         with Capturing() as output:
+#             self._test_bools()
 
-    def _test_unsupported(self):
-        """
-        Test merging dict with unsupported types. should raise ValueError
-        """
+#     def _test_bools(self):
+#         """
+#         Test merging dict with booleans
+#         """
 
-        dict_1 = {"new": dummy("david")}
-        dict_2 = {"new": dummy("gio")}
+#         dict_1 = {"bool": True}
+#         dict_2 = {"bool": False}
+#         output_dict = merge_dicts(dict_1, dict_2)
 
-        # output_dict = merge_dicts(dict_1, dict_2)
-        self.assertRaises(ValueError, merge_dicts, dict_1, dict_2)
+#         self.assertTrue(isinstance(output_dict["bool"], bool))
+#         self.assertTrue(output_dict["bool"])
 
+#     def test_ints(self):
+#         with Capturing() as _:
+#             self._test_ints()
 
-class test_binaryc_json_serializer(unittest.TestCase):
-    """
-    Unittests for function binaryc_json_serializer
-    """
+#     def _test_ints(self):
+#         """
+#         Test merging dict with ints
+#         """
 
-    def test_not_function(self):
-        with Capturing() as output:
-            self._test_not_function()
+#         dict_1 = {"int": 2}
+#         dict_2 = {"int": 1}
+#         output_dict = merge_dicts(dict_1, dict_2)
 
-    def _test_not_function(self):
-        """
-        Test passing an object that doesnt get turned in to a string
-        """
+#         self.assertTrue(isinstance(output_dict["int"], int))
+#         self.assertEqual(output_dict["int"], 3)
 
-        stringo = "hello"
-        output = binaryc_json_serializer(stringo)
-        self.assertTrue(stringo == output)
+#     def test_floats(self):
+#         with Capturing() as output:
+#             self._test_floats()
 
-    def test_function(self):
-        with Capturing() as output:
-            self._test_function()
+#     def _test_floats(self):
+#         """
+#         Test merging dict with floats
+#         """
 
-    def _test_function(self):
-        """
-        Test passing an object that gets turned in to a string: a function
-        """
+#         dict_1 = {"float": 4.5}
+#         dict_2 = {"float": 4.6}
+#         output_dict = merge_dicts(dict_1, dict_2)
 
-        string_of_function = str(os.path.isfile)
-        output = binaryc_json_serializer(os.path.isfile)
-        self.assertTrue(string_of_function == output)
+#         self.assertTrue(isinstance(output_dict["float"], float))
+#         self.assertEqual(output_dict["float"], 9.1)
 
+#     def test_lists(self):
+#         with Capturing() as output:
+#             self._test_lists()
 
-class test_handle_ensemble_string_to_json(unittest.TestCase):
-    """
-    Unittests for function handle_ensemble_string_to_json
-    """
+#     def _test_lists(self):
+#         """
+#         Test merging dict with lists
+#         """
 
-    def test_1(self):
-        with Capturing() as _:
-            self._test_1()
+#         dict_1 = {"list": [1, 2]}
+#         dict_2 = {"list": [3, 4]}
+#         output_dict = merge_dicts(dict_1, dict_2)
 
-    def _test_1(self):
-        """
-        Test passing string representation of a dictionary.
-        """
+#         self.assertTrue(isinstance(output_dict["list"], list))
+#         self.assertEqual(output_dict["list"], [1, 2, 3, 4])
 
-        _ = str(os.path.isfile)
-        input_string = '{"ding": 10, "list_example": [1,2,3]}'
-        output_dict = handle_ensemble_string_to_json(input_string)
+#     def test_dicts(self):
+#         with Capturing() as _:
+#             self._test_dicts()
 
-        self.assertTrue(isinstance(output_dict, dict))
-        self.assertTrue(output_dict["ding"] == 10)
-        self.assertTrue(output_dict["list_example"] == [1, 2, 3])
+#     def _test_dicts(self):
+#         """
+#         Test merging dict with dicts
+#         """
 
+#         dict_1 = {"dict": {"same": 1, "other_1": 2.0}}
+#         dict_2 = {"dict": {"same": 2, "other_2": [4.0]}}
+#         output_dict = merge_dicts(dict_1, dict_2)
 
-class test_AutoVivicationDict(unittest.TestCase):
-    """
-    Unittests for AutoVivicationDict
-    """
+#         self.assertTrue(isinstance(output_dict["dict"], dict))
+#         self.assertEqual(
+#             output_dict["dict"], {"same": 3, "other_1": 2.0, "other_2": [4.0]}
+#         )
 
-    def test_add(self):
-        """
-        Tests to see if the adding is done correctly
-        """
+#     def test_unsupported(self):
+#         with Capturing() as output:
+#             self._test_unsupported()
 
-        result_dict = AutoVivificationDict()
+#     def _test_unsupported(self):
+#         """
+#         Test merging dict with unsupported types. should raise ValueError
+#         """
+
+#         dict_1 = {"new": dummy("david")}
+#         dict_2 = {"new": dummy("gio")}
+
+#         # output_dict = merge_dicts(dict_1, dict_2)
+#         self.assertRaises(ValueError, merge_dicts, dict_1, dict_2)
 
-        result_dict["a"]["b"]["c"] += 10
 
-        self.assertEqual(result_dict["a"]["b"]["c"], 10)
-        result_dict["a"]["b"]["c"] += 10
-        self.assertEqual(result_dict["a"]["b"]["c"], 20)
+# class test_binaryc_json_serializer(unittest.TestCase):
+#     """
+#     Unittests for function binaryc_json_serializer
+#     """
+
+#     def test_not_function(self):
+#         with Capturing() as output:
+#             self._test_not_function()
+
+#     def _test_not_function(self):
+#         """
+#         Test passing an object that doesnt get turned in to a string
+#         """
+
+#         stringo = "hello"
+#         output = binaryc_json_serializer(stringo)
+#         self.assertTrue(stringo == output)
+
+#     def test_function(self):
+#         with Capturing() as output:
+#             self._test_function()
+
+#     def _test_function(self):
+#         """
+#         Test passing an object that gets turned in to a string: a function
+#         """
+
+#         string_of_function = str(os.path.isfile)
+#         output = binaryc_json_serializer(os.path.isfile)
+#         self.assertTrue(string_of_function == output)
+
+
+# class test_handle_ensemble_string_to_json(unittest.TestCase):
+#     """
+#     Unittests for function handle_ensemble_string_to_json
+#     """
+
+#     def test_1(self):
+#         with Capturing() as _:
+#             self._test_1()
+
+#     def _test_1(self):
+#         """
+#         Test passing string representation of a dictionary.
+#         """
+
+#         _ = str(os.path.isfile)
+#         input_string = '{"ding": 10, "list_example": [1,2,3]}'
+#         output_dict = handle_ensemble_string_to_json(input_string)
+
+#         self.assertTrue(isinstance(output_dict, dict))
+#         self.assertTrue(output_dict["ding"] == 10)
+#         self.assertTrue(output_dict["list_example"] == [1, 2, 3])
+
+
+# class test_AutoVivicationDict(unittest.TestCase):
+#     """
+#     Unittests for AutoVivicationDict
+#     """
+
+#     def test_add(self):
+#         """
+#         Tests to see if the adding is done correctly
+#         """
+
+#         result_dict = AutoVivificationDict()
+
+#         result_dict["a"]["b"]["c"] += 10
+
+#         self.assertEqual(result_dict["a"]["b"]["c"], 10)
+#         result_dict["a"]["b"]["c"] += 10
+#         self.assertEqual(result_dict["a"]["b"]["c"], 20)
+
+
+# class test_setopts(unittest.TestCase):
+#     """
+#     Unit test class for setopts
+#     """
+
+#     def test_setopts(self):
+#         with Capturing() as output:
+#             self._test_setopts()
+
+#     def _test_setopts(self):
+#         """
+#         Unittest for function set_opts
+#         """
+
+#         default_dict = {"m1": 2, "m2": 3}
+#         output_dict_1 = set_opts(default_dict, {})
+#         self.assertTrue(output_dict_1 == default_dict)
 
+#         new_opts = {"m1": 10}
+#         output_dict_2 = set_opts(default_dict, new_opts)
+#         updated_dict = default_dict.copy()
+#         updated_dict["m1"] = 10
 
+#         self.assertTrue(output_dict_2 == updated_dict)
\ No newline at end of file
diff --git a/binarycpython/utils/population_extensions/_distribution_functions.py b/binarycpython/utils/population_extensions/_distribution_functions.py
index 4f849fb92..29f041344 100644
--- a/binarycpython/utils/population_extensions/_distribution_functions.py
+++ b/binarycpython/utils/population_extensions/_distribution_functions.py
@@ -140,7 +140,7 @@ class distribution_functions:
         return powerlaw_const
 
     @cachetools.cachedmethod(
-        lambda self: self.caches["distribution_functions.powerlaw_constant"]
+        lambda self: self.caches["population_extensions._distribution_functions.powerlaw_constant"]
     )
     def powerlaw_constant(
         self,
diff --git a/binarycpython/utils/population_extensions/_grid_options_defaults.py b/binarycpython/utils/population_extensions/_grid_options_defaults.py
index 6eac46ebe..779f7590c 100644
--- a/binarycpython/utils/population_extensions/_grid_options_defaults.py
+++ b/binarycpython/utils/population_extensions/_grid_options_defaults.py
@@ -205,13 +205,13 @@ class grid_options_defaults:
                 # set above
                 #
                 # if n is None, no cache is set up
-                "distribution_functions.powerlaw_constant": (0, "NoCache", "1,100,-2"),
-                "distribution_functions.calculate_constants_three_part_powerlaw": (
+                "_distribution_functions.powerlaw_constant": (0, "NoCache", "1,100,-2"),
+                "_distribution_functions.calculate_constants_three_part_powerlaw": (
                     16,
                     "FIFOCache",
                     "0.1,0.5,1,100,-1.3,-2.3,-2.3",
                 ),
-                "distribution_functions.gaussian_normalizing_const": (
+                "_distribution_functions.gaussian_normalizing_const": (
                     16,
                     "FIFOCache",
                     "1.0,1.0,-10.0,+10.0",
diff --git a/setup.py b/setup.py
index c54c74531..f58d473c9 100644
--- a/setup.py
+++ b/setup.py
@@ -259,6 +259,7 @@ setup(
         "binarycpython.utils",
         "binarycpython.utils.population_extensions",
         "binarycpython.tests",
+        "binarycpython.tests.tests_population_extensions",
     ],
     install_requires=[
         "astropy",
-- 
GitLab