diff --git a/binarycpython/utils/distribution_functions.py b/binarycpython/utils/distribution_functions.py
index 92e2ea41a128a46860452d37508f225e9fd5f62f..07ddd447de6868239badd50da8a3202fc408244d 100644
--- a/binarycpython/utils/distribution_functions.py
+++ b/binarycpython/utils/distribution_functions.py
@@ -1768,7 +1768,7 @@ def calc_e_integral(
 
 
 def calc_P_integral(
-    options, min_P, integrals_string, interpolator_name, mass_string, verbosity=0
+        options, min_logP, max_logP, integrals_string, interpolator_name, mass_string, verbosity=0
 ):
     """
     Function to calculate the P integral
@@ -1777,7 +1777,6 @@ def calc_P_integral(
     """
 
     global Moecache
-    max_logP = 10
 
     # Check if the dict exists
     if not Moecache.get(integrals_string, None):
@@ -1788,7 +1787,7 @@ def calc_P_integral(
         I = 0
         dlogP = 1e-3
 
-        for logP in np.arange(np.log10(min_P), max_logP, dlogP):
+        for logP in np.arange(min_logP, max_logP, dlogP):
             # Loop over all the values in the table, between the min and max P
             dp_dlogP = Moecache[interpolator_name].interpolate(
                 [np.log10(options[mass_string]), logP]
@@ -1799,8 +1798,8 @@ def calc_P_integral(
         # Set the integral value in the dict
         Moecache[integrals_string][options[mass_string]] = I
         verbose_print(
-            "\tM&S: calc_P_integral: min_P: {} integrals_string: {} interpolator_name: {} mass_string: {} mass: {} I: {}".format(
-                min_P,
+            "\tM&S: calc_P_integral: min_logP: {} integrals_string: {} interpolator_name: {} mass_string: {} mass: {} I: {}".format(
+                min_logP,
                 integrals_string,
                 interpolator_name,
                 mass_string,
@@ -1812,8 +1811,8 @@ def calc_P_integral(
         )
     else:
         verbose_print(
-            "\tM&S: calc_P_integral: Found cached value for min_P: {} integrals_string: {} interpolator_name: {} mass_string: {} mass: {} I: {}".format(
-                min_P,
+            "\tM&S: calc_P_integral: Found cached value for min_logP: {} integrals_string: {} interpolator_name: {} mass_string: {} mass: {} I: {}".format(
+                min_logP,
                 integrals_string,
                 interpolator_name,
                 mass_string,
@@ -2000,14 +1999,19 @@ def Moe_di_Stefano_2017_pdf(options, verbosity=0):
             options["sep"] = calc_sep_from_period(
                 options["M_1"], options["M_2"], options["P"]
             )
-            # TODO: add check for min_P with instant RLOF?
+            # TODO: add check for min_logP with instant RLOF?
             # TODO: Actually use the value above.
             # Total mass inner binary:
             options["M_1+M_2"] = options["M_1"] + options["M_2"]
 
         # Calculate P integral or use cached value
+
+        # get the periods from the Moecahe
+        min_logP = Moecache['logperiods'][0]
+        max_logP = Moecache['logperiods'][-1]
+
         calc_P_integral(
-            options, 1, "P_integrals", "rinterpolator_log10P", "M_1", verbosity
+            options, min_logP, max_logP, "P_integrals", "rinterpolator_log10P", "M_1", verbosity
         )
 
         # Set probabilty for P1
@@ -2125,7 +2129,13 @@ def Moe_di_Stefano_2017_pdf(options, verbosity=0):
 
             # TODO: Is this a correct assumption?
             max_sep = 10.0 * options["sep"] * (1.0 + options["ecc"])
-            min_P2 = calc_period_from_sep(options["M_1+M_2"], options["mmin"], max_sep)
+            min_P2 = calc_period_from_sep(options["M_1+M_2"],
+                                          options["mmin"],
+                                          max_sep)
+            min_logP2 = math.log10(min_P2)
+            #max_logP2 = 10.0
+            #min_logP = Moecache['logperiods'][0]
+            max_logP2 = Moecache['logperiods'][-1]
 
             if options["P2"] < min_P2:
                 # period is too short : system is not hierarchical
@@ -2152,7 +2162,8 @@ def Moe_di_Stefano_2017_pdf(options, verbosity=0):
                 # Check for cached value of P integral or calculate
                 calc_P_integral(
                     options,
-                    min_P2,
+                    min_logP2,
+                    max_logP2,
                     "P2_integrals",
                     "rinterpolator_log10P",
                     "M_1+M_2",
@@ -2243,7 +2254,8 @@ def Moe_di_Stefano_2017_pdf(options, verbosity=0):
                     # TODO: Make sure we use the correct period idea here.
                     calc_P_integral(
                         options,
-                        min_P2,
+                        min_logP2,
+                        max_logP2,
                         "P2_integrals",
                         "rinterpolator_log10P",
                         "M_1+M_2",
diff --git a/binarycpython/utils/functions.py b/binarycpython/utils/functions.py
index 41a0516557707bbf48820b5077465b31fc029b25..dbf90f1139e80be0a615ea21c6d9a199635f5b41 100644
--- a/binarycpython/utils/functions.py
+++ b/binarycpython/utils/functions.py
@@ -410,19 +410,19 @@ def subtract_dicts(dict_1: dict, dict_2: dict) -> dict:
 
 def get_moe_di_stefano_dataset(options, verbosity=0):
     """
-    Function to get the default moe and di Stefano dataset or accept a user input.
+    Function to get the default Moe and di Stefano dataset or accept a user input.
+
+    Returns a dict containing the (JSON) data.
     """
 
-    if not options.get("file", None):
-        verbose_print(
-            "Using the default Moe and de Stefano 2017 datafile",
-            verbosity,
-            1,
-        )
+    json_data = None
 
-        json_data = copy.deepcopy(moe_di_stefano_2017_data.moe_di_stefano_2017_data)
+    if "JSON" in options:
+        # use the JSON data passed in
+        json_data = options["JSON"]
 
-    else:
+    elif "file" in options:
+        # use the file passed in, if provided
         if not os.path.isfile(options["file"]):
             verbose_print(
                 "The provided 'file' Moe and de Stefano JSON file does not seem to exist at {}".format(
@@ -444,10 +444,19 @@ def get_moe_di_stefano_dataset(options, verbosity=0):
             # Read input data and Clean up the data if there are white spaces around the keys
             with open(options["file"], "r") as data_filehandle:
                 datafile_data = data_filehandle.read()
-            datafile_data = datafile_data.replace('" ', '"')
-            datafile_data = datafile_data.replace(' "', '"')
-            datafile_data = datafile_data.replace(' "', '"')
-            json_data = json.loads(datafile_data)
+                datafile_data = datafile_data.replace('" ', '"')
+                datafile_data = datafile_data.replace(' "', '"')
+                datafile_data = datafile_data.replace(' "', '"')
+                json_data = json.loads(datafile_data)
+
+    if not json_data:
+        # no JSON data or filename given, use the default 2017 dataset
+        verbose_print(
+            "Using the default Moe and de Stefano 2017 datafile",
+            verbosity,
+            1,
+        )
+        json_data = copy.deepcopy(moe_di_stefano_2017_data.moe_di_stefano_2017_data)
 
     return json_data
 
@@ -1905,10 +1914,15 @@ def update_dicts(dict_1: dict, dict_2: dict) -> dict:
 
     """
 
-    # Set up new dict
-    new_dict = OrderedDict()  # TODO: check if this still works
-
+    # Set up new dict of the same type as dict_1
     #
+    # Note: setting directly to OrderedDict fails in some cases
+    # so instead we take a (shallow) copy of dict_1 which will
+    # have the same type as dict_1, then clear it. (There must
+    # be a better way to do this...)
+    new_dict = dict_1.copy() # OrderedDict()  # TODO: check if this still works
+    new_dict.clear()
+
     keys_1 = dict_1.keys()
     keys_2 = dict_2.keys()
 
diff --git a/binarycpython/utils/grid.py b/binarycpython/utils/grid.py
index dae0c30d3882f58885ef16988f846dcabfd23808..d0edf56b43f0f0df5a87f5c3997c36a895711ae6 100644
--- a/binarycpython/utils/grid.py
+++ b/binarycpython/utils/grid.py
@@ -151,8 +151,9 @@ class Population:
         # Set the options that are passed at creation of the object
         self.set(**kwargs)
 
-        # Load M&s options
+        # Load Moe and di Stefano options
         self.grid_options["m&s_options"] = copy.deepcopy(moe_di_stefano_default_options)
+        self.custom_options["m&s_JSON_data"] = None
 
         # Write M&S options to a file. NOTE: not sure why i put this here anymore
         os.makedirs(
@@ -3745,30 +3746,33 @@ class Population:
 
     def set_moe_di_stefano_settings(self, options=None):
         """
-        Function to set user input configurations for the moe & di Stefano methods
+        Function to set user input configurations for the Moe & di Stefano methods
 
         If nothing is passed then we just use the default options
         """
 
-        if options:
-            # Take the option dictionary that was given and override.
-            options = update_dicts(self.grid_options["m&s_options"], options)
-            self.grid_options["m&s_options"] = copy.deepcopy(dict(options))
+        if not options:
+            options = {}
 
-            # Write options to a file
-            os.makedirs(
-                os.path.join(self.grid_options["tmp_dir"], "moe_distefano"),
-                exist_ok=True,
-            )
-            with open(
+
+        # Take the option dictionary that was given and override.
+        options = update_dicts(self.grid_options["m&s_options"], options)
+        self.grid_options["m&s_options"] = copy.deepcopy(options)
+
+        # Write options to a file
+        os.makedirs(
+            os.path.join(self.grid_options["tmp_dir"], "moe_distefano"),
+            exist_ok=True,
+        )
+        with open(
                 os.path.join(
                     os.path.join(self.grid_options["tmp_dir"], "moe_distefano"),
                     "moeopts.dat",
                 ),
                 "w",
-            ) as f:
-                f.write(json.dumps(self.grid_options["m&s_options"], indent=4))
-                f.close()
+        ) as f:
+            f.write(json.dumps(self.grid_options["m&s_options"], indent=4))
+            f.close()
 
     def _load_moe_di_stefano_data(self):
         """
@@ -3776,15 +3780,26 @@ class Population:
         """
 
         # Only if the grid is loaded and Moecache contains information
-        if (not self.grid_options["_loaded_ms_data"]) and not Moecache:
-            # Load the JSON data
-            json_data = get_moe_di_stefano_dataset(
-                self.grid_options["m&s_options"],
-                verbosity=self.grid_options["verbosity"],
-            )
+        if (not self.grid_options["_loaded_ms_data"]): # and not Moecache:
 
-            # entry of log10M1 is a list containing 1 dict. We can take the dict out of the list
-            json_data["log10M1"] = json_data["log10M1"][0]
+            if self.custom_options["m&s_JSON_data"]:
+                # Use the existing (perhaps modified) JSON data
+                json_data = self.custom_options["m&s_JSON_data"]
+
+            else:
+                # Load the JSON data from a file
+                json_data = get_moe_di_stefano_dataset(
+                    self.grid_options["m&s_options"],
+                    verbosity=self.grid_options["verbosity"],
+                )
+
+            # entry of log10M1 is a list containing 1 dict.
+            # We can take the dict out of the list
+            if isinstance(json_data["log10M1"], list):
+                json_data["log10M1"] = json_data["log10M1"][0]
+
+            # save this data in case we want to modify it later
+            self.custom_options["m&s_JSON_data"] = json_data
 
             # Get all the masses
             logmasses = sorted(json_data["log10M1"].keys())
@@ -3815,13 +3830,12 @@ class Population:
             logperiods = []
             for logmass in logmasses:
                 if not logperiods:
-                    logperiods = sorted(json_data["log10M1"][logmass]["logP"])
+                    logperiods = sorted(json_data["log10M1"][logmass]["logP"].keys())
                     dlog10P = float(logperiods[1]) - float(logperiods[0])
 
                 current_logperiods = sorted(json_data["log10M1"][logmass]["logP"])
-
                 if not (logperiods == current_logperiods):
-                    msg = "Period values are not consistent throughout the dataset"
+                    msg = "Period values are not consistent throughout the dataset\logperiods = " + ' '.join(str(x) for x in logperiods) + "\nCurrent periods = " + ' '.join(str(x) for x in current_logperiods)
                     verbose_print(
                         "\tMoe_di_Stefano_2017: {}".format(msg),
                         self.grid_options["verbosity"],
@@ -3832,7 +3846,6 @@ class Population:
                 ############################################################
                 # log10period binwidth : of course this assumes a fixed
                 # binwidth, so we check for this too.
-
                 for i in range(len(current_logperiods) - 1):
                     if not dlog10P == (
                         float(current_logperiods[i + 1]) - float(current_logperiods[i])
@@ -3845,6 +3858,10 @@ class Population:
                         )
                         raise ValueError(msg)
 
+            # save the logperiods list in the cache:
+            # this is used in the renormalization integration
+            Moecache['logperiods'] = logperiods
+
             # Write to file
             os.makedirs(
                 os.path.join(self.grid_options["tmp_dir"], "moe_distefano"),
@@ -3884,13 +3901,12 @@ class Population:
 
                 # Go over the periods
                 for logperiod in logperiods:
-                    # print("logperiod: {}".format(logperiod))
                     ############################################################
                     # distributions of binary and triple star fractions
                     # as a function of mass, period.
                     #
                     # Note: these should be per unit log10P, hence we
-                    # divide by $dlog10P
+                    # divide by dlog10P
 
                     if first:
                         first = 0
@@ -3923,6 +3939,7 @@ class Population:
                                 / dlog10P,
                             ]
                         )
+
                     Moecache["period_distributions"].append(
                         [
                             float(logmass),
@@ -4095,9 +4112,6 @@ class Population:
         ############################################################
         # always require M1, for all systems
         #
-
-        # TODO: put in option for the time-adaptive grid.
-
         # log-spaced m1 with given resolution
         self.add_grid_variable(
             name="lnm1",
@@ -4478,14 +4492,36 @@ eccentricity3=0
         Takes a dictionary as its only argument
         """
 
+        default_options = {
+            'apply settings' : True,
+            'setup grid' : True,
+            'load data' : True,
+            'clean cache' : False,
+            'clean load flag' : False,
+            'clean all' : False,
+            }
+        if not options:
+            options = {}
+        options = update_dicts(default_options,options)
+
+        # clean cache?
+        if options['clean all'] or options['clean cache']:
+            Moecache.clear()
+
+        if options['clean all'] or options['clean load flag']:
+            self.grid_options["_loaded_ms_data"] = False
+
         # Set the user input
-        self.set_moe_di_stefano_settings(options=options)
+        if options['apply settings']:
+            self.set_moe_di_stefano_settings(options=options)
 
         # Load the data
-        self._load_moe_di_stefano_data()
+        if options['load data']:
+            self._load_moe_di_stefano_data()
 
         # construct the grid here
-        self._set_moe_di_stefano_distributions()
+        if options['setup grid']:
+            self._set_moe_di_stefano_distributions()
 
     def _clean_interpolators(self):
         """
diff --git a/binarycpython/utils/grid_options_defaults.py b/binarycpython/utils/grid_options_defaults.py
index 3a1ff066d763ad352190a615d9e210534e8eebc2..5467f69abc61128b187f4dc3cccbb750eff78d5c 100644
--- a/binarycpython/utils/grid_options_defaults.py
+++ b/binarycpython/utils/grid_options_defaults.py
@@ -511,6 +511,11 @@ MIN_MASS_BINARY_C = float(
 
 # Default options for the Moe & di Stefano grid
 moe_di_stefano_default_options = {
+    # place holder for the JSON data to be used if a file
+    # isn't specified
+    "JSON" : None,
+
+    # resolution data
     "resolutions": {
         "M": [
             20,  # M1