diff --git a/binarycpython/utils/distribution_functions.py b/binarycpython/utils/distribution_functions.py index bc0eb313eeba67a94227cabd5ec025352a6b467d..caf505f5951662ce579fe771e694c48bd3f88dbe 100644 --- a/binarycpython/utils/distribution_functions.py +++ b/binarycpython/utils/distribution_functions.py @@ -20,6 +20,7 @@ Tasks: - TODO: make an n-part power law that's general enough to fix the three part and the 4 part """ +import functools import math import json @@ -134,7 +135,7 @@ def const( prob = 1.0 / (max_bound - min_bound) return prob - +@functools.lru_cache(maxsize=16) def powerlaw_constant( min_val: Union[int, float], max_val: Union[int, float], k: Union[int, float] ) -> Union[int, float]: @@ -202,7 +203,7 @@ def powerlaw( # ) return prob - +@functools.lru_cache(maxsize=16) def calculate_constants_three_part_powerlaw( m0: Union[int, float], m1: Union[int, float], @@ -322,7 +323,7 @@ def three_part_powerlaw( return prob - +@functools.lru_cache(maxsize=16) def gaussian_normalizing_const( mean: Union[int, float], sigma: Union[int, float], @@ -718,7 +719,7 @@ def sana12( """ res = 0 - if (M1 < 15) or (M2 / M1 < 0.1): + if (M1 < 15.0) or (M2 / M1 < 0.1): res = 1.0 / (math.log(amax) - math.log(amin)) else: p1 = 1.0 + p diff --git a/binarycpython/utils/grid.py b/binarycpython/utils/grid.py index 81ae2cae7534198a9f8cbeaf123b4f2a905b0b57..37e0bf0b9bf197e491472883b612fa5030f87a0b 100644 --- a/binarycpython/utils/grid.py +++ b/binarycpython/utils/grid.py @@ -340,10 +340,10 @@ class Population: parameter, type(value), type(old_value) ), self.grid_options["verbosity"], - 1, + 2, ) value = type(old_value)(value) - verbose_print("Success!", self.grid_options["verbosity"], 1) + verbose_print("Success!", self.grid_options["verbosity"], 2) except ValueError: verbose_print( @@ -1109,7 +1109,7 @@ class Population: verbose_print( "Queue produced system {}".format(system_number), self.grid_options["verbosity"], - 2, + 3, ) # Print current size @@ -1279,6 +1279,10 @@ class Population: persistent_data_memaddr = self.persistent_data_memory_dict[self.process_ID] # print("thread {}: persistent_data_memaddr: ".format(self.process_ID), persistent_data_memaddr) + # vb2 logging + if self.grid_options['verbosity'] >= 2: + self.vb2print(full_system_dict,binary_cmdline_string) + # Get results binary_c # print("running: {}".format(binary_cmdline_string)) out = _binary_c_bindings.run_system( @@ -1511,16 +1515,17 @@ class Population: # In some cases, the whole run crashes. To be able to figure out which system # that was on, we log each current system to a file (each thread has one). # Each new system overrides the previous - with open( - os.path.join( - self.grid_options["tmp_dir"], - "current_system", - "process_{}.txt".format(self.process_ID), - ), - "w", - ) as f: - binary_cmdline_string = self._return_argline(full_system_dict) - f.write(binary_cmdline_string) + if self.grid_options["log_args"]: + with open( + os.path.join( + self.grid_options["log_args_dir"], + "current_system", + "process_{}.txt".format(self.process_ID), + ), + "w", + ) as f: + binary_cmdline_string = self._return_argline(full_system_dict) + f.write(binary_cmdline_string) ############## # Running the system @@ -1613,7 +1618,7 @@ class Population: ID, self.persistent_data_memory_dict[self.process_ID] ), self.grid_options["verbosity"], - 2, + 3, ) ensemble_raw_output = ( @@ -1633,7 +1638,7 @@ class Population: verbose_print( "Process {}: Extracting ensemble info from raw string".format(ID), self.grid_options["verbosity"], - 2, + 3, ) ensemble_json["ensemble"] = extract_ensemble_json_from_string( @@ -2160,7 +2165,10 @@ class Population: key=lambda x: x[1]["grid_variable_number"], ) ): - print("Constructing/adding: {}".format(grid_variable_el[0])) + verbose_print( + "Constructing/adding: {}".format(grid_variable_el[0]), + self.grid_options['verbosity'], + 2) grid_variable = grid_variable_el[1] ######################### @@ -2357,16 +2365,21 @@ class Population: ) # Add condition failed action: - self._add_code( - 'print("Grid generator: Condition for {} not met!")'.format( - grid_variable["parameter_name"] + if self.grid_options['verbosity'] >= 3: + self._add_code( + 'print("Grid generator: Condition for {} not met!")'.format( + grid_variable["parameter_name"] + ) + + "\n", + "continue" + "\n", + mindent=1, ) - + "\n", - "continue" + "\n", - mindent=1, - ) - - # Add some white line + else: + self._add_code( + "continue" + "\n", + mindent=1, + ) + # Add some whitespace self._add_code("\n") # # Add debugging: @@ -2533,8 +2546,7 @@ class Population: self._increment_indent_depth(+1) self._add_code("\n", "#" * 40 + "\n", "if print_results:\n") self._add_code( - "print('Grid has handled {} stars'.format(_total_starcount))\n", - "print('with a total probability of {}'.format(self.grid_options['_probtot']))\n", + "print('Grid has handled {} stars with a total probability of {}'.format(_total_starcount,self.grid_options['_probtot']))\n", mindent=1, ) @@ -3567,9 +3579,9 @@ class Population: f.write(argstring + "\n") else: verbose_print( - "binary_c had 0 output. Which is strange. Make sure you mean to do this. If there is actually ensemble output being generated then its fine.", + "binary_c output nothing - this is strange. If there is ensemble output being generated then this is fine.", self.grid_options["verbosity"], - 2, + 3, ) def set_moe_di_stefano_settings(self, options=None): @@ -4348,7 +4360,7 @@ eccentricity3=0 verbose_print( "_calculate_multiplicity_fraction: Chosen not to use any multiplicity fraction.", self.grid_options["verbosity"], - 2, + 3, ) return 1 @@ -4364,7 +4376,7 @@ eccentricity3=0 verbose_print( "_calculate_multiplicity_fraction: Using Arenou 2010 to calculate multiplicity fractions", self.grid_options["verbosity"], - 2, + 3, ) binary_fraction = Arenou2010_binary_fraction(system_dict["M_1"]) @@ -4380,7 +4392,7 @@ eccentricity3=0 verbose_print( "_calculate_multiplicity_fraction: Using Rhagavan 2010 to calculate multiplicity fractions", self.grid_options["verbosity"], - 2, + 3, ) binary_fraction = raghavan2010_binary_fraction(system_dict["M_1"]) @@ -4406,7 +4418,7 @@ eccentricity3=0 verbose_print( "_calculate_multiplicity_fraction: Moecache is empty. It needs to be filled with the data for the interpolators. Loading the data now", self.grid_options["verbosity"], - 2, + 3, ) # Load the data @@ -4443,7 +4455,7 @@ eccentricity3=0 multiplicity_fraction_dict[system_dict["multiplicity"]], ), self.grid_options["verbosity"], - 2, + 3, ) return multiplicity_fraction_dict[system_dict["multiplicity"]] @@ -4553,3 +4565,10 @@ eccentricity3=0 self.grid_options["verbosity"], 1, ) + + def vb2print(self, system_dict, cmdline_string): + print("Running this system now on thread {ID}\n{blue}{cmdline}{reset}\n".format( + ID=self.process_ID, + blue=self.ANSI_colours["blue"], + cmdline=cmdline_string, + reset=self.ANSI_colours["reset"])) diff --git a/binarycpython/utils/spacing_functions.py b/binarycpython/utils/spacing_functions.py index 3eae711f1317b9bd95f1d55f9cea4d33720c550e..4ef7271526c0cd48eecb52ce38e60d5948acd7ac 100644 --- a/binarycpython/utils/spacing_functions.py +++ b/binarycpython/utils/spacing_functions.py @@ -14,7 +14,7 @@ import sys from binarycpython.utils.grid import Population -@functools.lru_cache(maxsize=128) +@functools.lru_cache(maxsize=16) def const( min_bound: Union[int, float], max_bound: Union[int, float], steps: int ) -> list: @@ -29,12 +29,38 @@ def const( Returns: np.linspace(min_bound, max_bound, steps+1) """ - return np.linspace(min_bound, max_bound, steps + 1) +############################################################ +@functools.lru_cache(maxsize=16) +def const_ranges(ranges) -> list: + """ + Samples a series of ranges linearly. + + Args: + ranges: a tuple of tuples passed to the const() spacing function. + + Returns: + numpy array of masses + + Example: + The following allocates 10 stars between 0.1 and 0.65, 20 stars between 0.65 + and 0.85, and 10 stars between 0.85 and 10.0 Msun. + + spacingfunc="const_ranges((({},{},{}),({},{},{}),({},{},{})))".format( + 0.1,0.65,10, + 0.65,0.85,20, + 0.85,10.0,10 + ), + + """ + + masses = np.empty(0) + for range in ranges: + masses = np.append(masses,const(*range)) + return np.unique(masses) ############################################################ -@functools.lru_cache(maxsize=128) def peak_normalized_gaussian_func( x: Union[int, float], mean: Union[int, float], sigma: Union[int, float] ) -> Union[int, float]: @@ -59,7 +85,7 @@ def peak_normalized_gaussian_func( ############################################################ -@functools.lru_cache(maxsize=128) +@functools.lru_cache(maxsize=16) def gaussian_zoom( min_bound: Union[int, float], max_bound: Union[int, float], @@ -102,9 +128,9 @@ def gaussian_zoom( if array[-1] != max_bound: array[-1] = max_bound - return array + return np.unique(array) -@functools.lru_cache(maxsize=128) +@functools.lru_cache(maxsize=16) def const_dt(self, dt=1000.0, dlogt=0.1, @@ -226,7 +252,6 @@ def const_dt(self, time = lifetime_population.grid_results['interpolation table m->t'][mass] data_table_mass_time.append( [ mass, time ] ) - # set up interpolators interpolator_time_mass = py_rinterpolate.Rinterpolate( table = data_table_time_mass, @@ -329,4 +354,4 @@ def const_dt(self, logtwas = logt # return the mass list as a numpy array - return np.array(mass_list) + return np.unique(np.array(mass_list))