cosmic-popsynth 3.6.2__cp313-cp313-macosx_14_0_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
cosmic/test_utils.py ADDED
@@ -0,0 +1,198 @@
1
+ """Unit test for cosmic
2
+ """
3
+
4
+ __author__ = 'Katie Breivik <katie.breivik@gmail.com>'
5
+
6
+ from cosmic.sample import InitialBinaryTable
7
+ from cosmic.evolve import Evolve
8
+
9
+ import warnings
10
+
11
+ import os
12
+ import unittest
13
+ import numpy as np
14
+ import scipy.integrate
15
+ import pandas as pd
16
+ import scipy.special as special
17
+ import pytest
18
+
19
+ from cosmic import utils
20
+
21
+ f = np.linspace(0,1,10)
22
+ x = np.linspace(0,1,10)
23
+ y = np.random.uniform(0.1,0.2,10)
24
+ kstar_single = [[10], [11], [12], [13], [14]]
25
+ kstar_double = [10, 14]
26
+ k1_range = [10, 11, 12]
27
+ k2_range = [10, 11, 12]
28
+ k1_range_false = np.arange(0,12)
29
+ k2_range_false = np.arange(0,12)
30
+ x_dat = pd.DataFrame(np.vstack([10*x, 10*f]).T, columns=['x_dat', 'f_dat'])
31
+ x_sample = np.vstack([np.random.uniform(0, 1, 10), np.random.uniform(0, 1, 10)]).T
32
+ wrong_dict = {'test_wrong_dict' : False}
33
+ alive_dict = {'binary_state' : [0]}
34
+ noLISA_dict = {'binary_state' : [0]}
35
+ false_dict = {'binary_state' : [0,1,2]}
36
+ conv_dict_formation = {'pop_select' : 'formation'}
37
+ conv_dict_1_SN = {'pop_select' : '1_SN'}
38
+ conv_dict_2_SN = {'pop_select' : '2_SN'}
39
+ conv_dict_disruption = {'pop_select' : 'disruption'}
40
+ conv_dict_final_state = {'pop_select' : 'final_state'}
41
+ conv_dict_XRB_form = {'pop_select' : 'XRB_form'}
42
+ conv_dict_false = {'pop_select' : 'wrong'}
43
+ conv_lim_dict = {"sep" : [10, 5000]}
44
+
45
+ TEST_DATA_DIR = os.path.join(os.path.split(__file__)[0], 'data')
46
+ BPP_TEST = pd.read_hdf(os.path.join(TEST_DATA_DIR, 'utils_test.hdf'), key='bpp')
47
+ BCM_TEST = pd.read_hdf(os.path.join(TEST_DATA_DIR, 'utils_test.hdf'), key='bcm')
48
+
49
+ IBT = InitialBinaryTable.InitialBinaries(m1=[100.0, 11.8,10**1.5], m2=[85.0, 11.1,21], porb=[10000.0,2211.0,0.1], ecc=[0.65,0.55,0.0], tphysf=[13700.0,13700.0,13700.0], kstar1=[1,1,1], kstar2=[1,1,14], metallicity=[0.005,0.02,0.002], binfrac=[0.5,0.5,0.5])
50
+
51
+ IDL_TABULATE_ANSWER = 0.5
52
+ MASS_SUM_SINGLE = [41.0, 41.6, 42.0, 126.0, 316.0]
53
+ MASS_SUM_MULTIPLE = 301.0
54
+ X_TRANS_SUM = -2.7199038e-07
55
+ BW_KNUTH = 0.333
56
+ _KNOWN_METHODS = ['select_final_state',
57
+ 'binary_state']
58
+
59
+ class TestUtils(unittest.TestCase):
60
+ """`TestCase` for the utilities method
61
+ """
62
+ def test_filter_bin_state(self):
63
+ self.assertRaises(ValueError, utils.filter_bin_state, BCM_TEST, BPP_TEST, wrong_dict, kstar_double, kstar_double)
64
+
65
+ bcm_true, bin_state_fraction = utils.filter_bin_state(BCM_TEST, BPP_TEST, alive_dict, k1_range, k2_range)
66
+
67
+ self.assertTrue(bcm_true.tphys.all() >= 1.0)
68
+
69
+ bcm_false, bin_state_fraction = utils.filter_bin_state(BCM_TEST, BPP_TEST, false_dict, k1_range_false, k2_range_false)
70
+
71
+
72
+ def test_conv_select(self):
73
+ self.assertRaises(ValueError, utils.conv_select, BCM_TEST, BPP_TEST, [11], [11], wrong_dict, {})
74
+
75
+ conv, bin_nums = utils.conv_select(BCM_TEST, BPP_TEST, [11], [11], conv_dict_formation['pop_select'], {})
76
+ self.assertTrue(np.all(conv.sep >= 0))
77
+
78
+ conv, bin_nums = utils.conv_select(BCM_TEST, BPP_TEST, [13,14], range(0,15), conv_dict_1_SN['pop_select'], {})
79
+ self.assertEqual(len(conv), 0)
80
+
81
+ conv, bin_nums = utils.conv_select(BCM_TEST, BPP_TEST, [13,14], range(0,15), conv_dict_2_SN['pop_select'], {})
82
+ self.assertEqual(len(conv), 0)
83
+
84
+ conv, bin_nums = utils.conv_select(BCM_TEST, BPP_TEST, [13,14], range(0,15), conv_dict_disruption['pop_select'], {})
85
+ self.assertEqual(len(conv), 4)
86
+
87
+ conv, bin_nums = utils.conv_select(BCM_TEST, BPP_TEST, [11], [11], conv_dict_final_state['pop_select'], {})
88
+ self.assertEqual(len(conv), int(len(BCM_TEST)))
89
+
90
+ conv, bin_nums = utils.conv_select(BCM_TEST, BPP_TEST, [13,14], range(0,15), conv_dict_XRB_form['pop_select'], {})
91
+ self.assertEqual(len(conv), 0)
92
+
93
+ self.assertRaises(ValueError, utils.conv_select, BCM_TEST, BPP_TEST, [11], [11], false_dict, {})
94
+
95
+ def test_conv_lims(self):
96
+ conv, bin_nums = utils.conv_select(BCM_TEST, BPP_TEST, [11], [11], conv_dict_formation['pop_select'], conv_lim_dict)
97
+ self.assertTrue(conv.loc[conv.bin_num.isin(bin_nums)].sep.max() < conv_lim_dict["sep"][1])
98
+ self.assertTrue(conv.loc[conv.bin_num.isin(bin_nums)].sep.min() > conv_lim_dict["sep"][0])
99
+
100
+ def test_idl_tabulate(self):
101
+ # Give this custom integrator a simple integration
102
+ # of a line from x = 0 to 1 and y= 0 to 1
103
+ self.assertAlmostEqual(utils.idl_tabulate(x,f), IDL_TABULATE_ANSWER)
104
+
105
+ def test_idl_tabulate_Err(self):
106
+ # Force an error by sending in x = [0]
107
+ self.assertEqual(utils.idl_tabulate(np.array([0]),f), 0)
108
+
109
+ def test_min_max_mass_single_kstar(self):
110
+ # Send in a single typed binary with both components
111
+ # being the same type
112
+ for ii in range(len(kstar_single)):
113
+ m_list = utils.mass_min_max_select(kstar_single[ii], kstar_single[ii])
114
+ self.assertEqual(np.sum([m_list]), MASS_SUM_SINGLE[ii])
115
+
116
+ def test_min_max_mass_multiple_kstar(self):
117
+ # Send in a range of types for a binary for both components
118
+ m_list = utils.mass_min_max_select(kstar_double, kstar_double)
119
+ self.assertEqual(np.sum([m_list]), MASS_SUM_MULTIPLE)
120
+
121
+ def test_param_transform(self):
122
+ # Send in a range of numbers that should have a
123
+ # minimum of 0.0 and a maximum of 1.0 after transformation
124
+ self.assertTrue(np.min(utils.param_transform(f)) >= 0.0)
125
+ self.assertTrue(np.max(utils.param_transform(f)) <= 1.0)
126
+
127
+ def test_dat_transform(self):
128
+ # send in DataFrame of 10*x (defined above)
129
+ x_trans = utils.dat_transform(10*x_dat, ['x_dat', 'f_dat'])
130
+ self.assertTrue(np.max(special.expit(x_trans[0])) < 1)
131
+ self.assertTrue(np.min(special.expit(x_trans[0])) > 0)
132
+
133
+ def test_dat_un_transform(self):
134
+ # send in sampled data set, which will just be random
135
+ # between -inf to +inf and should be transformed to be between
136
+ # 0 and 10
137
+ x_un_trans = utils.dat_un_transform(special.logit(x_sample), x_dat, ['x_dat', 'f_dat'])
138
+ self.assertTrue(np.min(x_un_trans[0]) >= np.min(x_dat.x_dat))
139
+ self.assertTrue(np.max(x_un_trans[0]) <= np.max(x_dat.x_dat))
140
+
141
+ def test_binwidth_selector(self):
142
+ # Check that the Knuth's bw is selected properly
143
+ bw = utils.knuth_bw_selector(np.array([x]))
144
+ self.assertTrue(bw.round(3) == BW_KNUTH)
145
+
146
+ def test_error_check(self):
147
+ BSEDict = {'xi': 0.5, 'bhflag': 1, 'neta': 0.5, 'windflag': 3, 'rtmsflag' : 0, 'wdflag': 0, 'alpha1': 1.0, 'pts1': 0.05, 'pts3': 0.02, 'pts2': 0.01, 'epsnov': 0.001, 'hewind': 1.0, 'ck': 1000, 'bwind': 0.0, 'lambdaf': 0.5, 'mxns': 3.0, 'beta': -1.0, 'tflag': 1, 'acc2': 1.5, 'nsflag': 4, 'ceflag': 0, 'eddfac': 1.0, 'ifflag': 0, 'bconst': 3000, 'sigma': 265.0, 'gamma': -2.0, 'pisn': 45.0, 'natal_kick_array' :[[-100.0,-100.0,-100.0,-100.0,0.0], [-100.0,-100.0,-100.0,-100.0,0.0]], 'bhsigmafrac' : 1.0, 'polar_kick_angle' : 90, 'qcrit_array' : [0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0], 'cekickflag' : 2, 'cehestarflag' : 0, 'cemergeflag' : 0, 'ecsn' : 2.5, 'ecsn_mlow' : 1.4, 'aic' : 1, 'ussn' : 0, 'sigmadiv' :-20.0, 'qcflag' : 3, 'eddlimflag' : 0, 'fprimc_array' : [2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0], 'rembar_massloss' : 0.5, 'zsun' : 0.02, 'kickflag' : 1, 'grflag' : 1, 'acc_lim' : -1, 'don_lim' : -1}
148
+ filters = {'binary_state': [0], 'timestep_conditions' : 'dtp=None'}
149
+ convergence = {'convergence_params': ['mass_1', 'mass_2', 'sep', 'ecc'], 'pop_select': 'formation',\
150
+ 'match': -5.0, 'convergence_limits' : {"sep" : [0,1000]}, 'match' : -3.0,\
151
+ 'apply_convergence_limits' : True}
152
+ sampling = {'sampling_method': 'multidim', 'SF_start': '13700.0', 'SF_duration' : 0.0, 'metallicity': 0.02, 'keep_singles': False}
153
+ utils.error_check(BSEDict,filters,convergence,sampling)
154
+ utils.error_check(BSEDict)
155
+ assert 1==1
156
+
157
+ def test_warning_check(self):
158
+ with pytest.warns(UserWarning, match='At least one of your initial binaries is starting in Roche Lobe Overflow'):
159
+ utils.check_initial_conditions(IBT)
160
+
161
+ def test_no_RL_check_for_singles(self):
162
+ """Make sure you don't get a divide by zero error when checking for Roche Lobe Overflow"""
163
+ BSEDict = {'xi': 1.0, 'bhflag': 1, 'neta': 0.5, 'windflag': 3, 'wdflag': 1, 'alpha1': 1.0,
164
+ 'pts1': 0.001, 'pts3': 0.02, 'pts2': 0.01, 'epsnov': 0.001, 'hewind': 0.5,
165
+ 'ck': 1000, 'bwind': 0.0, 'lambdaf': 0.0, 'mxns': 3.0, 'beta': -1.0, 'tflag': 1,
166
+ 'acc2': 1.5, 'grflag': 1, 'remnantflag': 4, 'ceflag': 0, 'eddfac': 1.0,
167
+ 'ifflag': 0, 'bconst': 3000, 'sigma': 265.0, 'gamma': -2.0, 'pisn': 45.0,
168
+ 'natal_kick_array': [[-100.0, -100.0, -100.0, -100.0, 0.0],
169
+ [-100.0, -100.0, -100.0, -100.0, 0.0]], 'bhsigmafrac': 1.0,
170
+ 'polar_kick_angle': 90, 'qcrit_array': [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
171
+ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
172
+ 'cekickflag': 2, 'cehestarflag': 0, 'cemergeflag': 0, 'ecsn': 2.25,
173
+ 'ecsn_mlow': 1.6, 'aic': 1, 'ussn': 0, 'sigmadiv': -20.0, 'qcflag': 5,
174
+ 'eddlimflag': 0, 'fprimc_array': [2.0/21.0, 2.0/21.0, 2.0/21.0, 2.0/21.0,
175
+ 2.0/21.0, 2.0/21.0, 2.0/21.0, 2.0/21.0,
176
+ 2.0/21.0, 2.0/21.0, 2.0/21.0, 2.0/21.0,
177
+ 2.0/21.0, 2.0/21.0, 2.0/21.0, 2.0/21.0],
178
+ 'bhspinflag': 0, 'bhspinmag': 0.0, 'rejuv_fac': 1.0, 'rejuvflag': 0, 'htpmb': 1,
179
+ 'ST_cr': 1, 'ST_tide': 1, 'bdecayfac': 1, 'rembar_massloss': 0.5, 'kickflag' : 1,
180
+ 'zsun': 0.014, 'bhms_coll_flag': 0, 'don_lim': -1, 'acc_lim': -1,
181
+ 'rtmsflag': 0, 'wd_mass_lim': 1}
182
+
183
+ initial_binaries = InitialBinaryTable.sampler('independent', np.linspace(0, 15, 16), np.linspace(0, 15, 16),
184
+ binfrac_model=0.5, SF_start=10.0,
185
+ SF_duration=0.0, met=0.02, size=10,
186
+ primary_model='kroupa01', ecc_model='sana12', porb_model='sana12',
187
+ keep_singles=True)[0]
188
+
189
+ with warnings.catch_warnings():
190
+ warnings.simplefilter("error")
191
+ Evolve.evolve(initialbinarytable=initial_binaries, BSEDict=BSEDict)
192
+
193
+ def test_convert_kstar_evol_type(self):
194
+ # convert to string
195
+ bpp = utils.convert_kstar_evol_type(BPP_TEST)
196
+ # convert back and then make sure that it is the same
197
+ bpp = utils.convert_kstar_evol_type(BPP_TEST)
198
+ pd.testing.assert_frame_equal(bpp, BPP_TEST)