Loading [MathJax]/extensions/TeX/AMSsymbols.js
LALInference 4.1.9.1-5e288d3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
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