From 3f98ca519e23e2971ff68900d7e30fb48100b8ad Mon Sep 17 00:00:00 2001
From: David Hendriks <davidhendriks93@gmail.com>
Date: Tue, 18 May 2021 12:28:19 +0100
Subject: [PATCH] working on M&S

---
 binarycpython/utils/distribution_functions.py | 38 +++++++++++---
 binarycpython/utils/functions.py              | 13 +++--
 binarycpython/utils/grid.py                   | 49 +++++++++++++++++--
 binarycpython/utils/grid_options_defaults.py  |  2 +
 4 files changed, 89 insertions(+), 13 deletions(-)

diff --git a/binarycpython/utils/distribution_functions.py b/binarycpython/utils/distribution_functions.py
index 79e0b3c89..63459057a 100644
--- a/binarycpython/utils/distribution_functions.py
+++ b/binarycpython/utils/distribution_functions.py
@@ -1113,7 +1113,7 @@ def Moe_de_Stefano_2017_multiplicity_fractions(options):
     # return array reference
     return result
 
-
+# @profile
 def build_q_table(options, m, p):
     ############################################################
     #
@@ -1138,12 +1138,13 @@ def build_q_table(options, m, p):
     # We should ignore those parts of the table and renormalize. If we are below the lowest value of qmin in the table we need to extrapolate the data
 
     # We can check if we have a cached value for this already:
-    # TODO: fix this cache check
+    # TODO: fix this cache check.
     incache = False
     if Moecache.get("rinterpolator_q_metadata", None):
-        if Moecache["rinterpolator_q_metadata"][m] == options[m]:
-            if Moecache["rinterpolator_q_metadata"] == options[p]:
+        if (Moecache["rinterpolator_q_metadata"][m]) and (Moecache["rinterpolator_q_metadata"][p]):
+            if (Moecache["rinterpolator_q_metadata"][m] == options[m]) and (Moecache["rinterpolator_q_metadata"][p] == options[p]):
                 incache = True
+        # print("INCACHE: {}".format(incache))
 
     #
     if not incache:
@@ -1167,7 +1168,7 @@ def build_q_table(options, m, p):
 
         qeps = 1e-8  # small number but such that qeps+1 != 1
         if qeps + 1 == 1.0:
-            printf("qeps (= {}) +1 == 1. Make qeps larger".format(qeps))
+            print("qeps (= {}) +1 == 1. Make qeps larger".format(qeps))
 
         if qmin >= qmax:
             # there may be NO binaries in this part of the parameter space:
@@ -1335,6 +1336,7 @@ def build_q_table(options, m, p):
                         else:
                             print("No other methods available")
                             raise ValueError
+
                         # TODO: consider implementing this
                         # elsif($method =~ /^(log)?poly(\d+)/)
                         # {
@@ -1393,10 +1395,30 @@ def build_q_table(options, m, p):
         for q in sorted(qdata.keys()):
             tmp_table.append([q, qdata[q]])
 
+        if Moecache.get("rinterpolator_q_given_{}_log10{}".format(m, p), None):
+            print("Present interpolator: {}".format(Moecache["rinterpolator_q_given_{}_log10{}".format(m, p)]))
+            print("Destroying present interpolator:")
+            interpolator = Moecache["rinterpolator_q_given_{}_log10{}".format(m, p)]
+            print(interpolator)
+            print(type(interpolator))
+            print(dir(interpolator))
+            x=Moecache["rinterpolator_q_given_{}_log10{}".format(m, p)].interpolate([0.5])
+            print("Interpolated a value q=0.5: {}".format(x))
+            Moecache["rinterpolator_q_given_{}_log10{}".format(m, p)].destroy()
+            print(interpolator)
+            print(type(interpolator))
+            print(dir(interpolator))
+            print("Present interpolator: {}".format(Moecache["rinterpolator_q_given_{}_log10{}".format(m, p)]))
+            x=Moecache["rinterpolator_q_given_{}_log10{}".format(m, p)].interpolate([0.5])
+            print("Interpolated a value q=0.5: {}".format(x))
+            # del Moecache["rinterpolator_q_given_{}_log10{}".format(m, p)]
+
+        print("CREATING A NEW TABLE Q table")
         # Make an interpolation table to contain our modified data
         q_interpolator = py_rinterpolate.Rinterpolate(
             table=tmp_table, nparams=1, ndata=1  # Contains the table of data  # q  #
         )
+        print("CREATed A NEW TABLE Q table")
         # TODO: build a check in here to see if the interpolator build was successful
 
         # print("Can renormalize?: {}".format(can_renormalize))
@@ -1434,7 +1456,10 @@ def build_q_table(options, m, p):
                     print("Error: > 1e-6 in q probability integral: {}".format(I))
 
         # set this new table in the cache
+        print("STORING Q INTERPOLATOR AS {}".format("rinterpolator_q_given_{}_log10{}".format(m, p)))
         Moecache["rinterpolator_q_given_{}_log10{}".format(m, p)] = q_interpolator
+        print("STORed Q INTERPOLATOR AS {}".format("rinterpolator_q_given_{}_log10{}".format(m, p)))
+
         if not Moecache.get("rinterpolator_q_metadata", None):
             Moecache["rinterpolator_q_metadata"] = {}
         Moecache["rinterpolator_q_metadata"][m] = options[m]
@@ -1756,7 +1781,8 @@ def Moe_de_Stefano_2017_pdf(options):
 
     print_info = 1
     if print_info:
-        print("Probability density")
+        # print("Probability density")
+
         if multiplicity == 1:
             print(
                 "M1={} q=N/A log10P=N/A ({}): {} -> {}\n".format(
diff --git a/binarycpython/utils/functions.py b/binarycpython/utils/functions.py
index 7bf7e1b81..3ded7b1d9 100644
--- a/binarycpython/utils/functions.py
+++ b/binarycpython/utils/functions.py
@@ -580,9 +580,9 @@ def parse_binary_c_version_info(version_info_string: str) -> dict:
         new_split = "".join(split_info[1:]).split(" is ")
         param_name = new_split[0]
         param_value = " is ".join(new_split[1:])
+
         # Sometimes the macros have extra information behind it. Needs an update in outputting by binary_c
         try:
-            print(param_name, param_type, param_value)
             macros_dict[param_name] = param_type_dict[param_type](param_value)
         except ValueError:
             macros_dict[param_name] = str(param_value)
@@ -1588,16 +1588,21 @@ def extract_ensemble_json_from_string(binary_c_output: str) -> dict:
         json dictionary with the parsed ENSEMBLE_JSON data
     """
 
-    json = None
+    json_dict = None
 
     try:
+        # If there is no output just return an empty dict:
+        if not binary_c_output:
+            json_dict = {}
+            return json_dict
+
         ensemble_jsons_strings = [
             line
             for line in binary_c_output.splitlines()
             if line.startswith("ENSEMBLE_JSON")
         ]
 
-        json = handle_ensemble_string_to_json(
+        json_dict = handle_ensemble_string_to_json(
             ensemble_jsons_strings[0][len("ENSEMBLE_JSON ") :]
         )
 
@@ -1614,7 +1619,7 @@ def extract_ensemble_json_from_string(binary_c_output: str) -> dict:
             0,
         )
 
-    return json
+    return json_dict
 
 
 class binarycDecoder(json.JSONDecoder):
diff --git a/binarycpython/utils/grid.py b/binarycpython/utils/grid.py
index 345f88fe0..00faa9021 100644
--- a/binarycpython/utils/grid.py
+++ b/binarycpython/utils/grid.py
@@ -692,6 +692,9 @@ class Population:
 
         If neither of the above is set, we continue without using HPC routines
         (that doesn't mean this cannot be run on a server with many cores)
+
+        Returns an dictionary containing the analytics of the run
+        TODO: change the way this is done. Slurm & CONDOR should probably do this different
         """
 
         # Just to make sure we don't have stuff from a previous run hanging around
@@ -728,6 +731,9 @@ class Population:
             "total_probability_weighted_mass_run": self.grid_options["_total_probability_weighted_mass_run"],
         }
 
+        # print(Moecache)
+        print(Moecache.keys())
+
         ##
         # Clean up code: remove files, unset values. This is placed in the general evolve function,
         # because that makes for easier control
@@ -876,6 +882,10 @@ class Population:
         pool.close()
         pool.join()
 
+        print("OUTSIDE THREAD")
+        print(Moecache.keys())
+        print("OUTSIDE THREAD")
+
         # Handle the results by merging all the dictionaries. How that merging happens exactly is
         # described in the merge_dicts description.
         combined_output_dict = {}
@@ -945,6 +955,15 @@ class Population:
         This function is called by _evolve_population_grid
         """
 
+
+
+
+        import tracemalloc
+        tracemalloc.start()
+        # ... start your application ...
+
+        snapshot1 = tracemalloc.take_snapshot()
+
         # set start timer
         start_process_time = datetime.datetime.now()
 
@@ -1055,6 +1074,7 @@ class Population:
                     # they match the keys known to binary_c.
                     # Won't do that every system cause that is a bit of a waste of computing time.
                     if localcounter == 0:
+                        # TODO: Put this someplace else and wrap in a functioncall
                         for key in full_system_dict.keys():
                             if not key in self.available_keys:
                                 # Deal with special keys
@@ -1075,9 +1095,10 @@ class Population:
                                     raise ValueError(msg)
                     
                     start_runtime_binary_c = time.time()
-                    # TODO: build flag to actually evolve the system
+
                     # Evolve the system
-                    self._evolve_system_mp(full_system_dict)
+                    if self.grid_options['_actually_evolve_system']:
+                        self._evolve_system_mp(full_system_dict)
 
                     end_runtime_binary_c = time.time()
 
@@ -1216,6 +1237,24 @@ class Population:
             0,
         )
 
+        print("INSIDE THREAD")
+        print(Moecache.keys())
+        for key in Moecache.keys():
+            print(key, Moecache[key])
+        print("")
+        print("INSIDE THREAD")
+
+
+        # ... call the function leaking memory ...
+        snapshot2 = tracemalloc.take_snapshot()
+
+        top_stats = snapshot2.compare_to(snapshot1, 'lineno')
+
+        print("[ Top 10 differences ]")
+        for stat in top_stats[:10]:
+            print(stat)
+
+
         return output_dict
 
     # Single system
@@ -1945,6 +1984,7 @@ class Population:
             # code_string += indent * (depth + 2) + "print('phasevol_lnm1: ',phasevol_lnm1); print('phasevol_multiplicity: ',phasevol_multiplicity);\n"
             # code_string += indent * (depth + 2) + "print(probabilities_list)\n"
             # code_string += indent * (depth + 2) + "print(parameter_dict)\n"
+            code_string += indent * (depth + 2) + "print('YOO IK GA LEKKER NOG EEN RONDJE')\n"
             code_string += indent * (depth + 2) + "yield(parameter_dict)\n"
 
         # If its a dry run, dont do anything with it
@@ -2981,6 +3021,7 @@ class Population:
                 ]
             )
 
+            print("Size multiplicity table: {}", len(Moecache["multiplicity_table"]))
             ############################################################
             # a small log10period which we can shift just outside the
             # table to force integration out there to zero
@@ -3045,6 +3086,7 @@ class Population:
                         / dlog10P,
                     ]
                 )
+                print("Size period_distributions table: {}", len(Moecache["period_distributions"]))
 
                 ############################################################
                 # distributions as a function of mass, period, q
@@ -3123,6 +3165,7 @@ class Population:
                     0.0,
                 ]
             )
+            print("Size period_distributions table: {}".format(len(Moecache["period_distributions"])))
 
         # Write to logfile
         with open("/tmp/moecache.json", "w") as cache_filehandle:
@@ -3243,7 +3286,7 @@ class Population:
                 resolution=options["resolutions"]["logP"][0],
                 probdist=1.0,
                 condition='(self.grid_options["multiplicity"] >= 2)',
-                branchpoint=1,
+                # branchpoint=1,
                 gridtype="centred",
                 dphasevol="({} * dlog10per)".format(LOG_LN_CONVERTER),
                 valuerange=[options["ranges"]["logP"][0], options["ranges"]["logP"][1]],
diff --git a/binarycpython/utils/grid_options_defaults.py b/binarycpython/utils/grid_options_defaults.py
index 45c4e017a..b40b674dd 100644
--- a/binarycpython/utils/grid_options_defaults.py
+++ b/binarycpython/utils/grid_options_defaults.py
@@ -33,6 +33,7 @@ grid_options_defaults_dict = {
     # "output_dir":
     "_commandline_input": "",
     "log_runtime_systems": 0,  # whether to log the runtime of the systems (1 file per thread. stored in the tmp_dir)
+    "_actually_evolve_system": True, # Whether to actually evolve the systems of just act as if. for testing. used in _process_run_population_grid
     ##########################
     # Execution log:
     ##########################
@@ -469,6 +470,7 @@ grid_options_descriptions = {
     "log_runtime_systems": "Whether to log the runtime of the systems . Each systems run by the thread is logged to a file and is stored in the tmp_dir. (1 file per thread). Don't use this if you are planning to run alot of systems. This is mostly for debugging and finding systems that take long to run. Integer, default = 0. if value is 1 then the systems are logged",
     "_total_mass_run": "To count the total mass that thread/process has ran",
     "_total_probability_weighted_mass_run": "To count the total mass * probability for each system that thread/process has ran",
+    "_actually_evolve_system": "Whether to actually evolve the systems of just act as if. for testing. used in _process_run_population_grid"
 }
 
 ###
-- 
GitLab