Coverage for pesummary/gw/conversions/nrutils.py: 52.0%
202 statements
« prev ^ index » next coverage.py v7.4.4, created at 2024-12-09 22:34 +0000
« prev ^ index » next coverage.py v7.4.4, created at 2024-12-09 22:34 +0000
1# Licensed under an MIT style license -- see LICENSE.md
3import numpy as np
4from pesummary.utils.utils import logger
5from pesummary.utils.decorators import bound_samples
7__author__ = ["Charlie Hoy <charlie.hoy@ligo.org>"]
9try:
10 from lalinference.imrtgr import nrutils
11 import lalsimulation
12 from lalsimulation import (
13 SimInspiralGetSpinFreqFromApproximant, SIM_INSPIRAL_SPINS_CASEBYCASE,
14 SIM_INSPIRAL_SPINS_FLOW
15 )
16except ImportError:
17 pass
19try:
20 from lalsimulation.nrfits.eval_fits import eval_nrfit as _eval_nrfit
21 NRSUR_MODULE = True
22except (ModuleNotFoundError, ImportError):
23 NRSUR_MODULE = False
25LPEAK_FITS = ["UIB2016", "Healyetal"]
26FINALMASS_FITS = ["UIB2016", "Healyetal"]
27FINALSPIN_FITS = ["UIB2016", "Healyetal", "HBR2016"]
29NRSUR_FITS = ["final_mass", "final_spin", "final_kick"]
30NRSUR_MODEL = "NRSur7dq4Remnant"
33def bbh_final_mass_non_spinning_Panetal(*args):
34 """Return the final mass of the BH resulting from the merger of a non
35 spinning BBH using the fit from Pan et al: Phys Rev D 84, 124052 (2011).
37 Parameters
38 ----------
39 mass_1: float/np.ndarray
40 float/array of masses for the primary object
41 mass_2: float/np.ndarray
42 float/array of masses for the secondary object
43 """
44 return nrutils.bbh_final_mass_non_spinning_Panetal(*args)
47@bound_samples(minimum=-1., maximum=1., logger_level="debug")
48def bbh_final_spin_non_spinning_Panetal(*args):
49 """Return the final spin of the BH resulting from the merger of a non
50 spinning BBH using the fit from Pan et al: Phys Rev D 84, 124052 (2011).
52 Parameters
53 ----------
54 mass_1: float/np.ndarray
55 float/array of masses for the primary object
56 mass_2: float/np.ndarray
57 float/array of masses for the secondary object
58 """
59 return nrutils.bbh_final_spin_non_spinning_Panetal(*args)
62@bound_samples(minimum=-1., maximum=1., logger_level="debug")
63def bbh_final_spin_non_precessing_Healyetal(*args, **kwargs):
64 """Return the final spin of the BH resulting from the merger of a BBH for an
65 aligned-spin system using the fit from Healy and Lousto: arXiv:1610.09713
67 Parameters
68 ----------
69 mass_1: float/np.ndarray
70 float/array of masses for the primary object
71 mass_2: float/np.ndarray
72 float/array of masses for the secondary object
73 spin_1z: float/np.ndarray
74 float/array of primary spin aligned with the orbital angular momentum
75 spin_2z: float/np.ndarray
76 float/array of secondary spin aligned with the orbital angular momentum
77 version: str, optional
78 version of the fitting coefficients you wish to use. Default are the
79 fits from 2016
80 """
81 if "version" not in kwargs.keys():
82 kwargs.update({"version": "2016"})
83 return nrutils.bbh_final_spin_non_precessing_Healyetal(*args, **kwargs)
86def bbh_final_mass_non_precessing_Healyetal(*args, **kwargs):
87 """Return the final mass of the BH resulting from the merger of a BBH for an
88 aligned-spin system using the fit from Healy et al. If no version specified,
89 the default fit is Healy and Lousto: arXiv:1610.09713
91 Parameters
92 ----------
93 mass_1: float/np.ndarray
94 float/array of masses for the primary object
95 mass_2: float/np.ndarray
96 float/array of masses for the secondary object
97 spin_1z: float/np.ndarray
98 float/array of primary spin aligned with the orbital angular momentum
99 spin_2z: float/np.ndarray
100 float/array of secondary spin aligned with the orbital angular momentum
101 version: str, optional
102 version of the fitting coefficients you wish to use. Default are the
103 fits from 2016
104 final_spin: float/np.ndarray, optional
105 float/array of precomputed final spins
106 """
107 chif = kwargs.pop("final_spin", None)
108 kwargs.update({"chif": chif})
109 if "version" not in kwargs.keys():
110 kwargs.update({"version": "2016"})
111 return nrutils.bbh_final_mass_non_precessing_Healyetal(*args, **kwargs)
114def bbh_final_mass_non_precessing_Husaetal(*args):
115 """Return the final mass of the BH resulting from the merge of a BBH for an
116 aligned-spin system using the fit from Husa et al: arXiv:1508.07250
118 Parameters
119 ----------
120 mass_1: float/np.ndarray
121 float/array of masses for the primary object
122 mass_2: float/np.ndarray
123 float/array of masses for the secondary object
124 spin_1z: float/np.ndarray
125 float/array of primary spin aligned with the orbital angular momentum
126 spin_2z: float/np.ndarray
127 float/array of secondary spin aligned with the orbital angular momentum
128 """
129 return nrutils.bbh_final_mass_non_precessing_Husaetal(*args)
132@bound_samples(minimum=-1., maximum=1., logger_level="debug")
133def bbh_final_spin_non_precessing_Husaetal(*args):
134 """Return the final spin of the BH resulting from the merger of a BBH for an
135 aligned-spin system using the fit from Husa et al: arXiv:1508.07250
137 Parameters
138 ----------
139 mass_1: float/np.ndarray
140 float/array of masses for the primary object
141 mass_2: float/np.ndarray
142 float/array of masses for the secondary object
143 spin_1z: float/np.ndarray
144 float/array of primary spin aligned with the orbital angular momentum
145 spin_2z: float/np.ndarray
146 float/array of secondary spin aligned with the orbital angular momentum
147 """
148 return nrutils.bbh_final_spin_non_precessing_Husaetal(*args)
151def bbh_final_mass_non_precessing_UIB2016(*args, **kwargs):
152 """Return the final mass of the BH resulting from the merger of a BBH for an
153 aligned-spin system using the fit from https://arxiv.org/abs/1611.00332
155 Parameters
156 ----------
157 mass_1: float/np.ndarray
158 float/array of masses for the primary object
159 mass_2: float/np.ndarray
160 float/array of masses for the secondary object
161 spin_1z: float/np.ndarray
162 float/array of primary spin aligned with the orbital angular momentum
163 spin_2z: float/np.ndarray
164 float/array of secondary spin aligned with the orbital angular momentum
165 version: str, optional
166 version of the fitting coefficients you wish to use
167 """
168 return nrutils.bbh_final_mass_non_precessing_UIB2016(*args, **kwargs)
171@bound_samples(minimum=-1., maximum=1., logger_level="debug")
172def bbh_final_spin_non_precessing_UIB2016(*args, **kwargs):
173 """Return the final spin of the BH resulting from the merger of a BBH for an
174 aligned-spin system using the fit from https://arxiv.org/abs/1611.00332
176 Parameters
177 ----------
178 mass_1: float/np.ndarray
179 float/array of masses for the primary object
180 mass_2: float/np.ndarray
181 float/array of masses for the secondary object
182 spin_1z: float/np.ndarray
183 float/array of primary spin aligned with the orbital angular momentum
184 spin_2z: float/np.ndarray
185 float/array of secondary spin aligned with the orbital angular momentum
186 version: str, optional
187 version of the fitting coefficients you wish to use
188 """
189 return nrutils.bbh_final_spin_non_precessing_UIB2016(*args, **kwargs)
192@bound_samples(minimum=-1., maximum=1., logger_level="debug")
193def bbh_final_spin_non_precessing_HBR2016(*args, **kwargs):
194 """Return the final spin of the BH resulting from the merger of a BBH for an
195 aligned-spin system using the fit from Hofmann, Barausse, and Rezzolla
196 ApJL 825, L19 (2016)
198 Parameters
199 ----------
200 mass_1: float/np.ndarray
201 float/array of masses for the primary object
202 mass_2: float/np.ndarray
203 float/array of masses for the secondary object
204 spin_1z: float/np.ndarray
205 float/array of primary spin aligned with the orbital angular momentum
206 spin_2z: float/np.ndarray
207 float/array of secondary spin aligned with the orbital angular momentum
208 version: str, optional
209 version of the fitting coefficients you wish to use
210 """
211 return nrutils.bbh_final_spin_non_precessing_HBR2016(*args, **kwargs)
214@bound_samples(maximum=1., logger_level="debug")
215def _bbh_final_spin_precessing_using_non_precessing_fit(
216 mass_1, mass_2, spin_1z, spin_2z, fit
217):
218 """Return the final spin of a BH results from the merger of a BH for a
219 precessing system using non_precessing fits
221 Parameters
222 ----------
223 mass_1: float/np.ndarray
224 float/array of masses for the primary object
225 mass_2: float/np.ndarray
226 float/array of masses for the secondary object
227 spin_1z: float/np.ndarray
228 float/array of primary spin aligned with the orbital angular momentum
229 spin_2z: float/np.ndarray
230 float/array of secondary spin aligned with the orbital angular momentum
231 fit: str
232 name of the NR fit you wish to use
233 """
234 return nrutils.bbh_final_spin_precessing(
235 mass_1, mass_2, np.abs(spin_1z), np.abs(spin_2z),
236 0.5 * np.pi * (1 - np.sign(spin_1z)),
237 0.5 * np.pi * (1 - np.sign(spin_2z)),
238 np.zeros_like(mass_1), fit
239 )
242def bbh_final_spin_Panetal(*args):
243 """Return the final spin of the BH resulting from the merger of a BBH for a
244 precessing system using the fit from Pan et al: Phys Rev D 84, 124052 (2011)
246 Parameters
247 ----------
248 mass_1: float/np.ndarray
249 float/array of masses for the primary object
250 mass_2: float/np.ndarray
251 float/array of masses for the secondary object
252 spin_1z: float/np.ndarray
253 float/array of primary spin aligned with the orbital angular momentum
254 spin_2z: float/np.ndarray
255 float/array of secondary spin aligned with the orbital angular momentum
256 """
257 return _bbh_final_spin_precessing_using_non_precessing_fit(*args, "Pan2011")
260def bbh_final_spin_precessing_Healyetal(*args):
261 """Return the final spin of the BH resulting from the merger of a BBH for a
262 precessing using the fit from Healy et al. If no version specified,
263 the default fit is Healy and Lousto: arXiv:1610.09713
265 Parameters
266 ----------
267 mass_1: float/np.ndarray
268 float/array of masses for the primary object
269 mass_2: float/np.ndarray
270 float/array of masses for the secondary object
271 spin_1z: float/np.ndarray
272 float/array of primary spin aligned with the orbital angular momentum
273 spin_2z: float/np.ndarray
274 float/array of secondary spin aligned with the orbital angular momentum
275 """
276 return _bbh_final_spin_precessing_using_non_precessing_fit(*args, "HL2016")
279def bbh_final_spin_precessing_UIB2016(*args):
280 """Return the final spin of the BH resulting from the merger of a BBH for a
281 precessing using the fit from David Keitel, Xisco Jimenez Forteza,
282 Sascha Husa, Lionel London et al. arxiv:1612.09566v1
284 Parameters
285 ----------
286 mass_1: float/np.ndarray
287 float/array of masses for the primary object
288 mass_2: float/np.ndarray
289 float/array of masses for the secondary object
290 spin_1z: float/np.ndarray
291 float/array of primary spin aligned with the orbital angular momentum
292 spin_2z: float/np.ndarray
293 float/array of secondary spin aligned with the orbital angular momentum
294 """
295 return _bbh_final_spin_precessing_using_non_precessing_fit(*args, "UIB2016")
298@bound_samples(maximum=1., logger_level="debug")
299def _bbh_final_spin_precessing_projected(
300 mass_1, mass_2, a_1, a_2, tilt_1, tilt_2, phi_12, function=None
301):
302 """Project the precessing spins along the orbital angular momentum and
303 calculate the final spin of the BH with an aligned-spin fit from the
304 literature augmenting it with the leading contribution from the in-plane
305 spins
307 Parameters
308 ----------
309 mass_1: float/np.ndarray
310 float/array of masses for the primary object
311 mass_2: float/np.ndarray
312 float/array of masses for the secondary object
313 a_1: float/np.ndarray
314 float/array of primary spin magnitudes
315 a_2: float/np.ndarray
316 float/array of secondary spin magnitudes
317 tilt_1: float/np.ndarray
318 float/array of primary spin tilt angle from the orbital angular momentum
319 tilt_2: float/np.ndarray
320 float/array of secondary spin tilt angle from the orbital angular
321 momentum
322 phi_12: float/np.ndarray
323 float/array of samples for the angle between the in-plane spin
324 components
325 """
326 spin_1z = a_1 * np.cos(tilt_1)
327 spin_2z = a_2 * np.cos(tilt_2)
328 final_spin_aligned = function(mass_1, mass_2, spin_1z, spin_2z)
329 final_spin_aligned_squared = final_spin_aligned * final_spin_aligned
330 total_mass = mass_1 + mass_2
332 a_1perp = mass_1 * mass_1 * a_1 * np.sin(tilt_1)
333 a_2perp = mass_2 * mass_2 * a_2 * np.sin(tilt_2)
334 a_perp_squared = (
335 a_1perp * a_1perp + a_2perp * a_2perp
336 + 2. * a_1perp * a_2perp * np.cos(phi_12)
337 )
338 return (final_spin_aligned_squared + a_perp_squared / (total_mass)**4.)**0.5
341def bbh_final_spin_precessing_projected_Healyetal(*args):
342 """Return the final spin of the BH calculated from projected spins using
343 the fit from Healy and Lousto: arXiv:1610.09713 augmenting it with the
344 leading contribution from the in-plane spins
346 Parameters
347 ----------
348 mass_1: float/np.ndarray
349 float/array of masses for the primary object
350 mass_2: float/np.ndarray
351 float/array of masses for the secondary object
352 a_1: float/np.ndarray
353 float/array of primary spin magnitudes
354 a_2: float/np.ndarray
355 float/array of secondary spin magnitudes
356 tilt_1: float/np.ndarray
357 float/array of primary spin tilt angle from the orbital angular momentum
358 tilt_2: float/np.ndarray
359 float/array of secondary spin tilt angle from the orbital angular
360 momentum
361 phi_12: float/np.ndarray
362 float/array of samples for the angle between the in-plane spin
363 components
364 """
365 return _bbh_final_spin_precessing_projected(
366 *args, function=bbh_final_spin_precessing_Healyetal
367 )
370def bbh_final_spin_precessing_projected_UIB2016(*args):
371 """Return the final spin of the BH calculated from projected spins using
372 the fit by David Keitel, Xisco Jimenez Forteza, Sascha Husa, Lionel London
373 et al. arxiv:1612.09566v1 augmenting it with the leading contribution from
374 the in-plane spins
376 Parameters
377 ----------
378 mass_1: float/np.ndarray
379 float/array of masses for the primary object
380 mass_2: float/np.ndarray
381 float/array of masses for the secondary object
382 a_1: float/np.ndarray
383 float/array of primary spin magnitudes
384 a_2: float/np.ndarray
385 float/array of secondary spin magnitudes
386 tilt_1: float/np.ndarray
387 float/array of primary spin tilt angle from the orbital angular momentum
388 tilt_2: float/np.ndarray
389 float/array of secondary spin tilt angle from the orbital angular
390 momentum
391 phi_12: float/np.ndarray
392 float/array of samples for the angle between the in-plane spin
393 components
394 """
395 return _bbh_final_spin_precessing_projected(
396 *args, function=bbh_final_spin_precessing_UIB2016
397 )
400@bound_samples(maximum=1., logger_level="debug")
401def bbh_final_spin_precessing_HBR2016(*args, **kwargs):
402 """Return the final spin of the BH resulting from the merger of a BBH for a
403 precessing system using the fit from Hofmann, Barausse, and Rezzolla ApJL
404 825, L19 (2016)
406 Parameters
407 ----------
408 mass_1: float/np.ndarray
409 float/array of masses for the primary object
410 mass_2: float/np.ndarray
411 float/array of masses for the secondary object
412 a_1: float/np.ndarray
413 float/array of primary spin magnitudes
414 a_2: float/np.ndarray
415 float/array of secondary spin magnitudes
416 tilt_1: float/np.ndarray
417 float/array of primary spin tilt angle from the orbital angular momentum
418 tilt_2: float/np.ndarray
419 float/array of secondary spin tilt angle from the orbital angular
420 momentum
421 phi_12: float/np.ndarray
422 float/array of samples for the angle between the in-plane spin
423 components
424 version: str, optional
425 version of the fitting coefficients you wish to use
426 """
427 return nrutils.bbh_final_spin_precessing_HBR2016(*args, **kwargs)
430def bbh_peak_luminosity_non_precessing_T1600018(*args):
431 """Return the peak luminosity (in units of 10^56 ergs/s) of an aligned-spin
432 BBH using the fit by Sascha Husa, Xisco Jimenez Forteza, David Keitel
433 [LIGO-T1500598] using 5th order in chieff
435 Parameters
436 ----------
437 mass_1: float/np.ndarray
438 float/array of masses for the primary object
439 mass_2: float/np.ndarray
440 float/array of masses for the secondary object
441 spin_1z: float/np.ndarray
442 float/array of primary spin aligned with the orbital angular momentum
443 spin_2z: float/np.ndarray
444 float/array of secondary spin aligned with the orbital angular momentum
445 """
446 return nrutils.bbh_peak_luminosity_non_precessing_T1600018(*args)
449def bbh_peak_luminosity_non_precessing_UIB2016(*args):
450 """Return the peak luminosity (in units of 10^56 ergs/s) of an aligned-spin
451 BBH using the fit by David Keitel, Xisco Jimenez Forteza, Sascha Husa,
452 Lionel London et al. arxiv:1612.09566v1
454 Parameters
455 ----------
456 mass_1: float/np.ndarray
457 float/array of masses for the primary object
458 mass_2: float/np.ndarray
459 float/array of masses for the secondary object
460 spin_1z: float/np.ndarray
461 float/array of primary spin aligned with the orbital angular momentum
462 spin_2z: float/np.ndarray
463 float/array of secondary spin aligned with the orbital angular momentum
464 """
465 return nrutils.bbh_peak_luminosity_non_precessing_UIB2016(*args)
468def bbh_peak_luminosity_non_precessing_Healyetal(*args):
469 """Return the peak luminosity (in units of 10^56 ergs/s) of an aligned-spin
470 BBH using the fit from Healy and Lousto: arXiv:1610.09713
472 Parameters
473 ----------
474 mass_1: float/np.ndarray
475 float/array of masses for the primary object
476 mass_2: float/np.ndarray
477 float/array of masses for the secondary object
478 spin_1z: float/np.ndarray
479 float/array of primary spin aligned with the orbital angular momentum
480 spin_2z: float/np.ndarray
481 float/array of secondary spin aligned with the orbital angular momentum
482 """
483 return nrutils.bbh_peak_luminosity_non_precessing_Healyetal(*args)
486class PeakLuminosityFits(object):
487 UIB2016 = bbh_peak_luminosity_non_precessing_UIB2016
488 Healyetal = bbh_peak_luminosity_non_precessing_Healyetal
489 T1600018 = bbh_peak_luminosity_non_precessing_T1600018
492class FinalMassFits(object):
493 Panetal = bbh_final_mass_non_spinning_Panetal
494 Healyetal = bbh_final_mass_non_precessing_Healyetal
495 Husaetal = bbh_final_mass_non_precessing_Husaetal
496 UIB2016 = bbh_final_mass_non_precessing_UIB2016
499class FinalSpinFits(object):
500 Panetal = bbh_final_spin_non_spinning_Panetal
501 Healyetal = bbh_final_spin_non_precessing_Healyetal
502 Husaetal = bbh_final_spin_non_precessing_Husaetal
503 UIB2016 = bbh_final_spin_non_precessing_UIB2016
504 HBR2016 = bbh_final_spin_non_precessing_HBR2016
507class FinalSpinPrecessingFits(object):
508 Healyetal = bbh_final_spin_precessing_projected_Healyetal
509 UIB2016 = bbh_final_spin_precessing_projected_UIB2016
510 HBR2016 = bbh_final_spin_precessing_HBR2016
513def _bbh_average_quantity(
514 *args, fits=None, cls=None, quantity=None, return_fits_used=False
515):
516 """Average the result from multiple fits
518 Parameters
519 ----------
520 *args: tuple
521 tuple of arguments for the fitting functions
522 fits: list
523 list of fits that you wish to use
524 cls: class
525 class which maps a string to a given fitting function
526 quantity: str
527 quantity that you are combining results for
528 return_fits_used: Bool, optional
529 if True, return the fits that were used to calculate the average
530 """
531 data, used_fits = [], []
532 for fit in fits:
533 if hasattr(cls, fit):
534 function = getattr(cls, fit)
535 used_fits.append(str(function).replace("<", "").replace(">", ""))
536 data.append(function(*args))
537 logger.info(
538 "Averaging the {} from the following fits: {}".format(
539 quantity, ", ".join(used_fits)
540 )
541 )
542 if return_fits_used:
543 return np.mean(data, axis=0), used_fits
544 return np.mean(data, axis=0)
547def bbh_final_mass_average(*args, fits=FINALMASS_FITS, return_fits_used=False):
548 """Return the final mass averaged across multiple fits
550 Parameters
551 ----------
552 mass_1: float/np.ndarray
553 float/array of masses for the primary object
554 mass_2: float/np.ndarray
555 float/array of masses for the secondary object
556 spin_1z: float/np.ndarray
557 float/array of primary spin aligned with the orbital angular momentum
558 spin_2z: float/np.ndarray
559 float/array of secondary spin aligned with the orbital angular momentum
560 fits: list, optional
561 list of fits that you wish to use
562 return_fits_used: Bool, optional
563 if True, return the fits that were used to calculate the average
564 """
565 return _bbh_average_quantity(
566 *args, fits=fits, cls=FinalMassFits, quantity="final mass",
567 return_fits_used=return_fits_used
568 )
571def bbh_final_spin_average_non_precessing(
572 *args, fits=FINALSPIN_FITS, return_fits_used=False
573):
574 """Return the final spin averaged across multiple non-precessing fits
576 Parameters
577 ----------
578 mass_1: float/np.ndarray
579 float/array of masses for the primary object
580 mass_2: float/np.ndarray
581 float/array of masses for the secondary object
582 spin_1z: float/np.ndarray
583 float/array of primary spin aligned with the orbital angular momentum
584 spin_2z: float/np.ndarray
585 float/array of secondary spin aligned with the orbital angular momentum
586 fits: list, optional
587 list of fits that you wish to use
588 return_fits_used: Bool, optional
589 if True, return the fits that were used to calculate the average
590 """
591 return _bbh_average_quantity(
592 *args, fits=fits, cls=FinalSpinFits, quantity="final spin",
593 return_fits_used=return_fits_used
594 )
597def bbh_final_spin_average_precessing(
598 *args, fits=FINALSPIN_FITS, return_fits_used=False
599):
600 """Return the final spin averaged across multiple fits
602 Parameters
603 ----------
604 mass_1: float/np.ndarray
605 float/array of masses for the primary object
606 mass_2: float/np.ndarray
607 float/array of masses for the secondary object
608 a_1: float/np.ndarray
609 float/array of primary spin magnitudes
610 a_2: float/np.ndarray
611 float/array of secondary spin magnitudes
612 tilt_1: float/np.ndarray
613 float/array of primary spin tilt angle from the orbital angular momentum
614 tilt_2: float/np.ndarray
615 float/array of secondary spin tilt angle from the orbital angular
616 momentum
617 phi_12: float/np.ndarray
618 float/array of samples for the angle between the in-plane spin
619 components
620 fits: list, optional
621 list of fits that you wish to use
622 return_fits_used: Bool, optional
623 if True, return the fits that were used to calculate the average
624 """
625 return _bbh_average_quantity(
626 *args, fits=fits, cls=FinalSpinPrecessingFits, quantity="final spin",
627 return_fits_used=return_fits_used
628 )
631def bbh_peak_luminosity_average(*args, fits=LPEAK_FITS, return_fits_used=False):
632 """Return the peak luminosity (in units of 10^56 ergs/s) averaged across
633 multiple fits.
635 Parameters
636 ----------
637 mass_1: float/np.ndarray
638 float/array of masses for the primary object
639 mass_2: float/np.ndarray
640 float/array of masses for the secondary object
641 spin_1z: float/np.ndarray
642 float/array of primary spin aligned with the orbital angular momentum
643 spin_2z: float/np.ndarray
644 float/array of secondary spin aligned with the orbital angular momentum
645 fits: list, optional
646 list of fits that you wish to use
647 return_fits_used: Bool, optional
648 if True, return the fits that were used to calculate the average
649 """
650 return _bbh_average_quantity(
651 *args, fits=fits, cls=PeakLuminosityFits, quantity="peak luminosity",
652 return_fits_used=return_fits_used
653 )
656def eval_nrfit(*args, **kwargs):
657 from contextlib import contextmanager
658 import ctypes
659 import io
660 import os
661 import sys
662 import tempfile
664 libc = ctypes.CDLL(None)
665 c_stdout = ctypes.c_void_p.in_dll(libc, 'stdout')
667 @contextmanager
668 def stdout_redirector(stream):
669 original_stdout_fd = sys.stdout.fileno()
671 def _redirect_stdout(to_fd):
672 """Redirect stdout to the given file descriptor."""
673 libc.fflush(c_stdout)
674 sys.stdout.close()
675 os.dup2(to_fd, original_stdout_fd)
676 sys.stdout = io.TextIOWrapper(os.fdopen(original_stdout_fd, 'wb'))
678 saved_stdout_fd = os.dup(original_stdout_fd)
679 try:
680 tfile = tempfile.TemporaryFile(mode='w+b')
681 _redirect_stdout(tfile.fileno())
682 yield
683 _redirect_stdout(saved_stdout_fd)
684 tfile.flush()
685 tfile.seek(0, io.SEEK_SET)
686 stream.write(tfile.read())
687 finally:
688 tfile.close()
689 os.close(saved_stdout_fd)
691 f = io.BytesIO()
692 with stdout_redirector(f):
693 NRSurrogate_kwargs = kwargs.copy()
694 approximant = kwargs.get("approximant", None)
695 f_low = kwargs.get("f_low", None)
696 f_ref = kwargs.get("f_ref", None)
697 spinfreq_enum = SimInspiralGetSpinFreqFromApproximant(
698 getattr(lalsimulation, approximant)
699 )
700 if spinfreq_enum == SIM_INSPIRAL_SPINS_CASEBYCASE:
701 raise ValueError(
702 "Unable to evolve spins as '{}' does not have a set frequency "
703 "at which the spins are defined".format(approximant)
704 )
705 f_start = float(np.where(
706 np.array(spinfreq_enum == SIM_INSPIRAL_SPINS_FLOW), f_low, f_ref
707 ))
708 NRSurrogate_kwargs["f_ref"] = f_start
709 NRSurrogate_kwargs.pop("f_low")
710 NRSurrogate_kwargs.pop("approximant")
711 data = _eval_nrfit(*args, **NRSurrogate_kwargs)
712 return data
715def NRSur_fit(
716 mass_1, mass_2, a_1, a_2, tilt_1, tilt_2, phi_12, phi_jl, theta_jn, phi_ref,
717 f_low=20., f_ref=20., model=NRSUR_MODEL, fits=NRSUR_FITS, return_fits_used=False,
718 approximant=None, **kwargs
719):
720 """Return the NR fits based on a chosen NRSurrogate model
722 Parameters
723 ----------
724 mass_1: float/np.ndarray
725 float/array of masses for the primary object. In units of solar mass
726 mass_2: float/np.ndarray
727 float/array of masses for the secondary object. In units of solar mass
728 a_1: float/np.ndarray
729 float/array of primary spin magnitudes
730 a_2: float/np.ndarray
731 float/array of secondary spin magnitudes
732 tilt_1: float/np.ndarray
733 float/array of primary spin tilt angle from the orbital angular momentum
734 tilt_2: float/np.ndarray
735 float/array of secondary spin tilt angle from the orbital angular
736 momentum
737 phi_12: float/np.ndarray
738 float/array of samples for the angle between the in-plane spin
739 components
740 phi_jl: float/np.ndarray
741 float/array of samples for the azimuthal angle of the orbital angular momentum
742 around the total orbital angular momentum
743 theta_jn: float/np.ndarray
744 float/array of samples for the angle between the total angular momentum and
745 the line of sight
746 phi_ref: float/np.ndarray
747 float/array of samples for the reference phase used in the analysis
748 f_low: float
749 the low frequency cut-off used in the analysis
750 f_ref: float/np.ndarray, optional
751 the reference frequency used in the analysis
752 model: str, optional
753 NRSurrogate model that you wish to use for the calculation
754 fits: list, optional
755 list of fits that you wish to evaluate
756 approximant: str, optional
757 The approximant that was used to generate the posterior samples
758 kwargs: dict, optional
759 optional kwargs that are passed directly to the
760 `lalsimulation.nrfits.eval_fits.eval_nrfit` function
761 """
762 from lal import MSUN_SI, C_SI
763 from .spins import component_spins
764 from .utils import magnitude_from_vector
765 from pesummary.utils.utils import iterator
766 import copy
768 if not NRSUR_MODULE:
769 raise ImportError(
770 "Unable to import `lalsimulation.nrfits.eval_fits`. This is likely "
771 "due to the installed version of lalsimulation. Please update."
772 )
774 fits_map = {
775 "final_mass": "FinalMass", "final_spin": "FinalSpin",
776 "final_kick": "RecoilKick"
777 }
778 inverse_fits_map = {item: key for key, item in fits_map.items()}
779 description = "Evaluating NRSurrogate fit for {}".format(", ".join(fits))
780 converted_fits = copy.deepcopy(fits)
781 for fit, conversion in fits_map.items():
782 if fit in converted_fits:
783 ind = fits.index(fit)
784 converted_fits[ind] = conversion
786 spins = np.array(
787 component_spins(
788 theta_jn, phi_jl, tilt_1, tilt_2, phi_12, a_1, a_2, mass_1, mass_2,
789 f_ref, phi_ref
790 )
791 )
792 a_1_vec = np.array([spins.T[1], spins.T[2], spins.T[3]]).T
793 a_2_vec = np.array([spins.T[4], spins.T[5], spins.T[6]]).T
794 mass_1 *= MSUN_SI
795 mass_2 *= MSUN_SI
796 try:
797 _fits = [
798 eval_nrfit(
799 mass_1[num], mass_2[num], a_1_vec[num], a_2_vec[num], model,
800 converted_fits, f_low=f_low, f_ref=f_ref[num],
801 approximant=approximant, extra_params_dict=kwargs
802 ) for num in iterator(
803 range(len(mass_1)), desc=description, tqdm=True, total=len(mass_1),
804 logger=logger
805 )
806 ]
807 except ValueError as e:
808 base = (
809 "Failed to generate remnant quantities with the NRSurrogate "
810 "remnant model. {}"
811 )
812 if "symbol not found" in str(e):
813 raise NameError(
814 base.format(
815 "This could be because the 'LAL_DATA_PATH' has not been "
816 "set."
817 )
818 )
819 raise ValueError(base.format(""))
820 nr_fits = {key: np.array([dic[key] for dic in _fits]) for key in _fits[0]}
821 if fits_map["final_mass"] in nr_fits.keys():
822 nr_fits[fits_map["final_mass"]] = np.array(
823 [final_mass[0] for final_mass in nr_fits[fits_map["final_mass"]]]
824 ) / MSUN_SI
825 if fits_map["final_kick"] in nr_fits.keys():
826 nr_fits[fits_map["final_kick"]] *= C_SI / 1000
827 final_kick_abs = magnitude_from_vector(
828 nr_fits[fits_map["final_kick"]]
829 )
830 nr_fits[fits_map["final_kick"]] = final_kick_abs
831 if fits_map["final_spin"] in nr_fits.keys():
832 final_spin_abs = magnitude_from_vector(
833 nr_fits[fits_map["final_spin"]]
834 )
835 nr_fits[fits_map["final_spin"]] = final_spin_abs
836 return {
837 key if key not in inverse_fits_map.keys() else inverse_fits_map[key]:
838 item for key, item in nr_fits.items()
839 }