LALInference 4.1.9.1-eeff03c
imrtgrutils.py
Go to the documentation of this file.
1"""
2Core python module for the IMR consistency test
3
4P. Ajith, Abhirup Ghosh, 2015-09-15
5
6$Id:$
7"""
8
9import numpy as np
10import scipy.ndimage.filters as filter
11from multiprocessing import Pool
12from functools import partial
13from . import nrutils as nr
14
15""" calculate the mass and spin of the final black hole using an NR-inspired fitting formula """
16def calc_final_mass_spin(m1, m2, chi1, chi2, chi1z, chi2z, phi12, fit_formula):
17 """ Calculate the mass and spin of the final black hole using an NR-inspired fitting formula.
18
19 inputs:
20 m1, m2: initial masses
21 chi1, chi2: initial spin magnitudes
22 chi1z, chi2z: z-components of the initial spins
23 phi12: in-plane angle between initial spins
24 fit_formula: fitting formula to be used for the calculation of final mass/spin
25
26 output:
27 mf, chif: final mass, final spin
28 """
29
30 tilt1 = np.arccos(chi1z/chi1)
31 tilt2 = np.arccos(chi2z/chi2)
32
33 if fit_formula == 'nospin_Pan2011':
34 chif = nr.bbh_final_spin_non_spinning_Panetal(m1, m2)
35 mf = nr.bbh_final_mass_non_spinning_Panetal(m1, m2)
36 elif fit_formula == 'nonprecspin_Healy2014':
37 chif = nr.bbh_final_spin_non_precessing_Healyetal(m1, m2, chi1z, chi2z, version="2014")
38 mf = nr.bbh_final_mass_non_precessing_Healyetal(m1, m2, chi1z, chi2z, version="2014", chif=chif)
39 elif fit_formula == 'nonprecspin_Husa2015':
40 chif = nr.bbh_final_spin_non_precessing_Husaetal(m1, m2, chi1z, chi2z)
41 mf = nr.bbh_final_mass_non_precessing_Husaetal(m1, m2, chi1z, chi2z)
42 elif fit_formula == 'bbh_average_fits_precessing':
43 mf_fits = ["UIB2016", "HL2016"]
44 chif_fits = ["UIB2016", "HBR2016", "HL2016"]
45 mf = nr.bbh_average_fits_precessing(m1, m2, chi1, chi2, tilt1, tilt2, 0, "Mf", mf_fits)
46 chif = nr.bbh_average_fits_precessing(m1, m2, chi1, chi2, tilt1, tilt2, phi12, "af", chif_fits)
47 else:
48 raise ValueError("unknown spin fit formula")
49 return mf, chif
50
51""" compute the integrand of P(dMf/Mfbar, dchif/chifbar). """
52def P_integrand(chif, Mf, v1, v2, P_Mfchif_i_interp_object, P_Mfchif_r_interp_object):
53
54 """ Compute the integrand of P(dMf/Mfbar, dchif/chifbar).
55
56 inputs:
57 chif: vector of values of final spin
58 Mf: vector of values of final mass
59 v1: dMf/Mfbar value
60 v2: dchif/chifbar value
61 P_Mfchif_i_interp_object: interpolation function of P_i(Mf, chif)
62 P_Mfchif_r_interp_object: interpolation function of P_r(Mf, chif)
63
64 output: integrand of P(dMf/Mfbar, dchif/chifbar)
65 """
66
67
68 Mf_mat, chif_mat = np.meshgrid(Mf, chif)
69
70 # Create dMf and dchif vectors corresponding to the given v1 and v2. These vectors have to be
71 # monotonically increasing in order to evaluate the interpolated prob densities. Hence, for
72 # v1, v2 < 0, flip them, evaluate the prob density (in column or row) and flip it back
73 dMf_i = (1.+v1/2.)*Mf
74 dchif_i = (1.+v2/2.)*chif
75
76 dMf_r = (1.-v1/2.)*Mf
77 dchif_r = (1.-v2/2.)*chif
78
79 if (1.+v1/2.) < 0.:
80 dMf_i = np.flipud(dMf_i)
81 if (1.+v2/2.) < 0.:
82 dchif_i = np.flipud(dchif_i)
83 P_i = P_Mfchif_i_interp_object(dMf_i, dchif_i)
84
85 if (1.+v1/2.) < 0.:
86 P_i = np.fliplr(P_i)
87 if (1.+v2/2.) < 0.:
88 P_i = np.flipud(P_i)
89
90 if (1.-v1/2.) < 0.:
91 dMf_r = np.flipud(dMf_r)
92 if (1.-v2/2.) < 0.:
93 dchif_r = np.flipud(dchif_r)
94 P_r = P_Mfchif_r_interp_object(dMf_r, dchif_r)
95
96 if (1.-v1/2.) < 0.:
97 P_r = np.fliplr(P_r)
98 if (1.-v2/2.) < 0.:
99 P_r = np.flipud(P_r)
100
101 return P_i*P_r*abs(Mf_mat*chif_mat), P_i, P_r
102
103""" compute P(dMf/Mfbar, dchif/chifbar). """
104def calc_sum(Mf, chif, v1, v2, P_Mfchif_i_interp_object, P_Mfchif_r_interp_object):
105
106 Pintg, P_i, P_r = P_integrand(chif, Mf, v1, v2, P_Mfchif_i_interp_object, P_Mfchif_r_interp_object)
107 return np.sum(Pintg)
108
109""" gaussian filter of histogram """
110def gf(P):
111 return filter.gaussian_filter(P, sigma=2.0)
112
113""" generate prior samples in (Mf, chif) assuming uniform prior in component masses """
114def calc_Mfchif_prior_samples(comp_mass_prior_min, comp_mass_prior_max, comp_spin_min, comp_spin_max, Mf_bins, chif_bins, fit_formula, spin_angle_dist, N_sampl, thread):
115
116 # generate random samples of the prior uniform in component masses
117 m1_pr = np.random.uniform(comp_mass_prior_min, comp_mass_prior_max, N_sampl)
118 m2_pr = np.random.uniform(comp_mass_prior_min, comp_mass_prior_max, N_sampl)
119
120 # generate samples of component spins, for non-precessing spins (aligned/anti-aligned with the orb ang momentum)
121 if spin_angle_dist == 'aligned':
122 chi1_pr = np.random.uniform(comp_spin_min, comp_spin_max, N_sampl)
123 chi2_pr = np.random.uniform(comp_spin_min, comp_spin_max, N_sampl)
124 # generate samples of component spins, for uninform spin magnitudes and isotropic spin directions (uniform in cos_tilt_angle)
125 elif spin_angle_dist == 'isotropic':
126 chi1_pr = np.random.uniform(comp_spin_min, comp_spin_max, N_sampl)*np.random.uniform(-1., 1., N_sampl)
127 chi2_pr = np.random.uniform(comp_spin_min, comp_spin_max, N_sampl)*np.random.uniform(-1., 1., N_sampl)
128
129 # return the corrresponding samples of prior in Mf, chif
130 return calc_final_mass_spin(m1_pr, m2_pr, chi1_pr, chi2_pr, fit_formula)
131
132""" calculate the prior distribution in (Mf, chif) assuming uniform prior in component masses """
133def calc_Mfchif_prior(comp_mass_prior_min, comp_mass_prior_max, comp_spin_min, comp_spin_max, Mf_bins, chif_bins, fit_formula, spin_angle_dist, N_sampl, num_threads):
134
135 # check inputs
136 if comp_mass_prior_min < 1. or comp_mass_prior_min > 1000.: raise ValueError("comp_mass_prior_min should be in the interval [1, 1000]")
137 if comp_mass_prior_max < 1. or comp_mass_prior_max > 1000.: raise ValueError("comp_mass_prior_max should be in the interval [1, 1000]")
138 if comp_mass_prior_max <= comp_mass_prior_min : raise ValueError("comp_mass_prior_max should be greater than comp_mass_prior_min")
139 if N_sampl < 1: raise ValueError("N_sampl should be greater than 1")
140 if comp_spin_max < comp_spin_min: raise ValueError("comp_spin_max should be greater than comp_spin_min")
141 if spin_angle_dist == 'aligned':
142 if comp_spin_min < -1. or comp_spin_min > 1.: raise ValueError("comp_spin_min should be in the interval [-1, 1] for the case of aligned spin distributions")
143 if comp_spin_max < -1. or comp_spin_max > 1.: raise ValueError("comp_spin_max should be in the interval [-1, 1] for the case of aligned spin distributions")
144 elif spin_angle_dist == 'isotropic':
145 if comp_spin_min < 0. or comp_spin_min > 1.: raise ValueError("comp_spin_min should be in the interval [0, 1] for the case of isotrpic spin distributions")
146 if comp_spin_max < 0. or comp_spin_max > 1.: raise ValueError("comp_spin_max should be in the interval [0, 1] for the case of isotrpic spin distributions")
147 else:
148 raise ValueError("spin_angle_dist should be 'aligned' or 'isotropic'")
149
150
151 # generate samples in Mf and chif corresponding to uniform samples in m1, m2. Parallelise the calculation over multiple threads
152 thread_vec = range(num_threads)
153 N_sampl = int(N_sampl/num_threads)
154 p = Pool(num_threads)
155 func = partial(calc_Mfchif_prior_samples, comp_mass_prior_min, comp_mass_prior_max, comp_spin_min, comp_spin_max, Mf_bins, chif_bins, fit_formula, spin_angle_dist, N_sampl)
156 final_params = p.map(func, thread_vec)
157 p.close()
158 p.join()
159
160 final_params = np.array(final_params)
161 final_params.reshape(N_sampl*num_threads, 2)
162 Mf_pr = np.ravel(final_params[:,0])
163 chif_pr = np.ravel(final_params[:,1])
164
165 # compute the 2D prior distribution in Mf and chif
166 P_Mfchif_pr, Mf_bins, chif_bins = np.histogram2d(Mf_pr, chif_pr, bins=(Mf_bins, chif_bins), density=True)
167
168 return P_Mfchif_pr.T
P_Mfchif_i_interp_object
compute the posterior of (delta_Mf/Mf, delta_chif/chif)
def calc_final_mass_spin(m1, m2, chi1, chi2, chi1z, chi2z, phi12, fit_formula)
calculate the mass and spin of the final black hole using an NR-inspired fitting formula Calculate th...
Definition: imrtgrutils.py:28
def calc_Mfchif_prior(comp_mass_prior_min, comp_mass_prior_max, comp_spin_min, comp_spin_max, Mf_bins, chif_bins, fit_formula, spin_angle_dist, N_sampl, num_threads)
Definition: imrtgrutils.py:133
def P_integrand(chif, Mf, v1, v2, P_Mfchif_i_interp_object, P_Mfchif_r_interp_object)
Compute the integrand of P(dMf/Mfbar, dchif/chifbar).
Definition: imrtgrutils.py:64
def calc_Mfchif_prior_samples(comp_mass_prior_min, comp_mass_prior_max, comp_spin_min, comp_spin_max, Mf_bins, chif_bins, fit_formula, spin_angle_dist, N_sampl, thread)
Definition: imrtgrutils.py:114
def calc_sum(Mf, chif, v1, v2, P_Mfchif_i_interp_object, P_Mfchif_r_interp_object)
Definition: imrtgrutils.py:104