"""
A collection of 2-D separable (i.e. independent) population models involving basis splines
"""
import jax.numpy as jnp
from ...distributions import powerlaw_pdf
from ..parametric.parametric import plpeak_primary_pdf
from .single import BSplineChiEffective
from .single import BSplineChiPrecess
from .single import BSplineMass
from .single import BSplineRatio
from .single import BSplineSpinMagnitude
from .single import BSplineSpinTilt
[docs]
class BSplineIIDSpinMagnitudes(object):
r"""A B-Spline model for the spin magnitude of both binary components assuming
they are independently and identically distributed (IID),
.. math::
p(a_1, a_2 \mid \mathbf{c}) = p(a_1 \mid \mathbf{c}) p(a_2 \mid \mathbf{c}),
where :math:`\mathbf{c}` is a vector of the ``n_splines`` basis spline coefficients.
Parameters
----------
n_splines : int
Number of basis functions, i.e., the number of degrees of freedom of the spline model.
a1, a2 : array_like
Primary and secondary component spin magnitude parameter estimation samples for basis evaluation.
a1_inj, a2_inj : array_like
Primary and secondary component spin magnitude injection samples for basis evaluation.
**kwargs : dict, optional
Additional keyword arguments to pass to the basis spline model.
"""
[docs]
def __init__(
self,
n_splines,
a1,
a2,
a1_inj,
a2_inj,
**kwargs,
):
self.primary_model = BSplineSpinMagnitude(
n_splines=n_splines,
a=a1,
a_inj=a1_inj,
**kwargs,
)
self.secondary_model = BSplineSpinMagnitude(
n_splines=n_splines,
a=a2,
a_inj=a2_inj,
**kwargs,
)
[docs]
def __call__(self, coefs, pe_samples=True):
"""Evaluate the joint probability density over the parameter estimation or injection samples.
Use flag `pe_samples` to specify which samples are being evaluated (parameter estimation or injection).
Parameters
----------
coefs : array_like
Spline coefficients.
pe_samples : bool, default=True
If `True`, design matrix is evaluated across parameter estimation samples.
If `False`, design matrix is evaluated across injection samples.
Returns
-------
array_like
Joint probability density for parameter estimation or injection samples.
"""
p_a1 = self.primary_model(coefs, pe_samples=pe_samples)
p_a2 = self.secondary_model(coefs, pe_samples=pe_samples)
return p_a1 * p_a2
[docs]
class BSplineIndependentSpinMagnitudes(object):
r"""A B-Spline model for the spin magnitudes of the primary and secondary components assuming
they are independently distributed,
.. math::
p(a_1, a_2 \mid \mathbf{c}_1, \mathbf{c}_2) = p(a_1 \mid \mathbf{c}_1) p(a_2 \mid \mathbf{c}_2),
where :math:`\mathbf{c}_1, \mathbf{c}_2` are vectors of the ``n_splines1``, ``n_splines2`` basis
spline coefficients for the primary and secondary component spin magnitudes, respectively.
Parameters
----------
n_splines1, n_splines2 : int
Number of basis functions, i.e., the number of degrees of freedom, of the
primary and secondary component spline models.
a1, a2 : array_like
Primary and secondary component spin magnitude parameter estimation samples for basis evaluation.
a1_inj, a2_inj : array_like
Primary and secondary component spin magnitude injection samples for basis evaluation.
kwargs1, kwargs2 : dict, optional
Additional keyword arguments to pass to the basis spline model for the primary and secondary components.
**kwargs : dict, optional
Additional keyword arguments to pass to both basis spline models.
"""
[docs]
def __init__(
self,
n_splines1,
n_splines2,
a1,
a2,
a1_inj,
a2_inj,
kwargs1={},
kwargs2={},
**kwargs,
):
self.primary_model = BSplineSpinMagnitude(
n_splines=n_splines1,
a=a1,
a_inj=a1_inj,
**kwargs1,
**kwargs,
)
self.secondary_model = BSplineSpinMagnitude(
n_splines=n_splines2,
a=a2,
a_inj=a2_inj,
**kwargs2,
**kwargs,
)
[docs]
def __call__(self, pcoefs, scoefs, pe_samples=True):
"""Evaluate the joint probability density over the parameter estimation or injection samples.
Use flag `pe_samples` to specify which samples are being evaluated (parameter estimation or injection).
Parameters
----------
pcoefs, scoefs : array_like
Spline coefficients for the (p)rimary and (s)econdary components.
pe_samples : bool, default=True
If `True`, design matrix is evaluated across parameter estimation samples.
If `False`, design matrix is evaluated across injection samples.
Returns
-------
array_like
Joint probability density for parameter estimation or injection samples.
"""
p_a1 = self.primary_model(pcoefs, pe_samples=pe_samples)
p_a2 = self.secondary_model(scoefs, pe_samples=pe_samples)
return p_a1 * p_a2
[docs]
class BSplineIIDSpinTilts(object):
"""A B-Spline model for the (cosine of) spin tilts of both binary components assuming
they are independently and identically distributed (IID),
.. math::
p(\cos{t_1}, \cos{t_2} \mid \mathbf{c}) = p(\cos{t_1} \mid \mathbf{c}) p(\cos{t_2} \mid \mathbf{c}),
where :math:`\mathbf{c}` is a vector of the ``n_splines`` basis spline coefficients.
Parameters
----------
n_splines1 : int
Number of basis functions, i.e., the number of degrees of freedom of the spline model.
ct1, ct2 : array_like
Primary and secondary component spin cosine tilt parameter estimation samples for basis evaluation.
ct1_inj, ct2_inj : array_like
Primary and secondary component spin cosine tilt injection samples for basis evaluation.
**kwargs : dict, optional
Additional keyword arguments to pass to the basis spline model.
"""
[docs]
def __init__(
self,
n_splines,
ct1,
ct2,
ct1_inj,
ct2_inj,
**kwargs,
):
self.primary_model = BSplineSpinTilt(
n_splines=n_splines,
ct=ct1,
ct_inj=ct1_inj,
**kwargs,
)
self.secondary_model = BSplineSpinTilt(
n_splines=n_splines,
ct=ct2,
ct_inj=ct2_inj,
**kwargs,
)
[docs]
def __call__(self, coefs, pe_samples=True):
"""Evaluate the joint probability density over the parameter estimation or injection samples.
Use flag `pe_samples` to specify which samples are being evaluated (parameter estimation or injection).
Parameters
----------
coefs : array_like
Spline coefficients.
pe_samples : bool, default=True
If `True`, design matrix is evaluated across parameter estimation samples.
If `False`, design matrix is evaluated across injection samples.
Returns
-------
array_like:
Joint probability density for parameter estimation or injection samples.
"""
p_ct1 = self.primary_model(coefs, pe_samples=pe_samples)
p_ct2 = self.secondary_model(coefs, pe_samples=pe_samples)
return p_ct1 * p_ct2
[docs]
class BSplineIndependentSpinTilts(object):
"""A B-Spline model for the (cosine of) spin tilts of the primary and secondary components assuming
they are independently distributed,
.. math::
p(\cos{t_1}, \cos{t_2} \mid \mathbf{c}_1, \mathbf{c}_2) = p(\cos{t_1} \mid \mathbf{c}_1) p(\cos{t_2} \mid \mathbf{c}_2),
where :math:`\mathbf{c}_1, \mathbf{c}_2` are vectors of the ``n_splines1``, ``n_splines2`` basis
spline coefficients for the primary and secondary component cosine spin tilts, respectively.
Parameters
----------
n_splines1, n_splines2 : int
Number of basis functions, i.e., the number of degrees of freedom, of the
primary and secondary component spline models.
ct1, ct2 : array_like
Primary and secondary component spin cosine tilt parameter estimation samples for basis evaluation.
ct1_inj, ct2_inj : array_like
Primary and secondary component spin cosine tilt injection samples for basis evaluation.
kwargs1, kwargs2 : dict, optional
Additional keyword arguments to pass to the basis spline model for the primary and secondary components.
**kwargs : dict, optional
Additional keyword arguments to pass to both basis spline models.
"""
[docs]
def __init__(
self,
n_splines1,
n_splines2,
ct1,
ct2,
ct1_inj,
ct2_inj,
kwargs1={},
kwargs2={},
**kwargs,
):
self.primary_model = BSplineSpinTilt(
n_splines=n_splines1,
ct=ct1,
ct_inj=ct1_inj,
**kwargs1,
**kwargs,
)
self.secondary_model = BSplineSpinTilt(
n_splines=n_splines2,
ct=ct2,
ct_inj=ct2_inj,
**kwargs2,
**kwargs,
)
[docs]
def __call__(self, pcoefs, scoefs, pe_samples=True):
"""Evaluate the joint probability density over the parameter estimation or injection samples.
Use flag `pe_samples` to specify which samples are being evaluated (parameter estimation or injection).
Parameters
----------
pcoefs, scoefs : array_like
Spline coefficients for the (p)rimary and (s)econdary components.
pe_samples : bool, default=True
If `True`, design matrix is evaluated across parameter estimation samples.
If `False`, design matrix is evaluated across injection samples.
Returns
-------
array_like
Joint probability density for parameter estimation or injection samples.
"""
p_ct1 = self.primary_model(pcoefs, pe_samples=pe_samples)
p_ct2 = self.secondary_model(scoefs, pe_samples=pe_samples)
return p_ct1 * p_ct2
[docs]
class BSplinePrimaryPowerlawRatio(object):
r"""A B-Spline model in primary mass and a powerlaw model in mass ratio,
.. math::
p(m_1, q \mid \mathbf{c}, \beta) = p(m_1 \mid \mathbf{c}) p(q \mid \beta, m_1, m_{\mathrm{min}}),
where :math:`\mathbf{c}` is a vector of the ``n_splines`` basis spline coefficients, and
:math:`\beta` is the powerlaw slope of the mass ratio distribution.
See Also
--------
gwinferno.distributions.powerlaw_pdf : Powerlaw probability density function.
Parameters
----------
n_splines : int
Number of basis functions, i.e., the number of degrees of freedom of the spline model.
m1 : array_like
Primary component mass parameter estimation samples for basis evaluation.
m1_inj : array_like
Primary component mass injection samples for basis evaluation.
mmin : float, default=2
Minimum component mass, setting lower bounds on the primary mass and mass ratio (:math:`q>m_\mathrm{min}/m_1`).
mmax : float, default=100
Maximum component mass, setting the upper bound on the primary mass.
**kwargs : dict, optional
Additional keyword arguments to pass to the basis spline model.
"""
[docs]
def __init__(
self,
n_splines,
m1,
m1_inj,
mmin=2,
mmax=100,
**kwargs,
):
self.primary_model = BSplineMass(
n_splines,
m1,
m1_inj,
mmin=mmin,
mmax=mmax,
**kwargs,
)
[docs]
def __call__(self, m1, q, beta, mmin, coefs, pe_samples=True):
"""Evaluate the joint probability density over the parameter estimation or injection samples.
Use flag `pe_samples` to specify which samples are being evaluated (parameter estimation or injection).
Parameters
----------
m1, q : array_like
Primary masses and mass ratios for computing joint probability density.
mmin : float
Minimum component mass, setting lower bounds on the primary mass and mass ratio (:math:`q>m_\mathrm{min}/m_1`).
coefs (array_like):
Spline coefficients.
pe_samples : bool, default=True
If `True`, design matrix is evaluated across parameter estimation samples.
If `False`, design matrix is evaluated across injection samples.
Returns
-------
array_like
Joint probability density for parameter estimation or injection samples.
"""
p_m1 = self.primary_model(coefs, pe_samples=pe_samples)
p_q = powerlaw_pdf(q, beta, mmin / m1, 1)
return p_m1 * p_q
[docs]
class PLPeakPrimaryBSplineRatio(object):
r"""A powerlaw + gaussian peak primary mass model and B-Spline model in mass ratio.
.. math::
p(m_1, q \mid \mathbf{c}, \alpha, \mu_\mathrm{peak}, \sigma_\mathrm{peak}, f_\mathrm{peak}) =
p(m_1 \mid \alpha, \mu_\mathrm{peak}, \sigma_\mathrm{peak}, f_\mathrm{peak}) p(q \mid \mathbf{c}, m_1, m_{\mathrm{min}}),
where :math:`\mathbf{c}` is a vector of the ``n_splines`` basis spline coefficients,
:math:`\alpha` is the powerlaw slope of the primary component mass distribution, :math:`\mu_\mathrm{peak}` and
:math:`\sigma_\mathrm{peak}` the mean and standard deviation of the peak in mass, and :math:`f_\mathrm{peak}`
is the mixing fraction between the powerlaw and peak in mass.
See Also
--------
gwinferno.models.parametric.parametric.plpeak_primary_pdf : Powerlaw+Peak primary mass model density.
Parameters
----------
n_splines : int
Number of basis functions, i.e., the number of degrees of freedom of the spline model.
q : array_like
Mass ratio parameter estimation samples for basis evaluation.
q_inj : array_like
Mass ratio injection samples for basis evaluation.
**kwargs : dict, optional
Additional keyword arguments to pass to the basis spline model.
"""
[docs]
def __init__(
self,
n_splines,
q,
q_inj,
**kwargs,
):
self.ratio_model = BSplineRatio(
n_splines,
q,
q_inj,
**kwargs,
)
[docs]
def __call__(self, m1, alpha, mmin, mmax, peak_mean, peak_sd, peak_frac, coefs, pe_samples=True):
"""Evaluate the joint probability density over the parameter estimation or injection samples.
Use flag `pe_samples` to specify which samples are being evaluated (parameter estimation or injection).
Parameters
----------
m1 : array_like
Primary masses for computing joint probability density.
alpha : float
Powerlaw slope of the primary mass distribution.
mmin : float
Minimum component mass, the lower bound on the primary mass.
mmax : float
Maximum component mass, the upper bound on the primary mass.
peak_mean : float
Mean of the peak in mass.
peak_sd : float
Standard deviation of the peak in mass.
peak_frac : float
Fraction of binaries in the peak in mass.
coefs : array_like
Spline coefficients.
pe_samples : bool, default=True
If `True`, design matrix is evaluated across parameter estimation samples.
If `False`, design matrix is evaluated across injection samples.
Returns
-------
array_like
Joint probability density for parameter estimation or injection samples.
"""
p_q = self.ratio_model(coefs, pe_samples=pe_samples)
p_m1 = plpeak_primary_pdf(m1, alpha, mmin, mmax, peak_mean, peak_sd, peak_frac)
return p_m1 * p_q
[docs]
class BSplinePrimaryBSplineRatio(object):
r"""B-Spline models for the primary mass and mass ratio,
.. math::
p(m_1, q \mid \mathbf{c}_m, \mathbf{c}_q) = p(m_1 \mid \mathbf{c}_m) p(q \mid \mathbf{c}_q),
where :math:`\mathbf{c}_m` and :math:`\mathbf{c}_q` are vectors of the ``n_splines_m`` and ``n_splines_q``
basis spline coefficients for the primary mass and mass ratio, respectively.
Parameters
----------
n_splines_m, n_splines_q : int
Number of basis functions, i.e., the number of degrees of freedom, of the
primary component mass and mass ratio spline models.
m1 : array_like
Primary component mass parameter estimation samples for basis evaluation.
m1_inj : array_like
Primary component mass injection samples for basis evaluation.
q : array_like
Mass ratio parameter estimation samples for basis evaluation.
q_inj : array_like
Mass ratio injection samples for basis evaluation.
mmax : float, default=100
Maximum component mass.
m1min : float, default=3
Minimum primary component mass.
m2min : float, default=3
Minimum secondary component mass, setting lower bound on the mass ratio (:math:`q>m_{2,\mathrm{min}}/m_\mathrm{max}`).
kwargs_m, kwargs_q : dict, optional
Additional keyword arguments to pass to the basis spline models for the primary component mass and mass ratio.
**kwargs : dict, optional
Additional keyword arguments to pass to both basis spline models.
"""
[docs]
def __init__(
self,
n_splines_m,
n_splines_q,
m1,
m1_inj,
q,
q_inj,
mmax=100.0,
m1min=3.0,
m2min=3.0,
kwargs_m={},
kwargs_q={},
**kwargs,
):
self.primary_model = BSplineMass(
n_splines_m,
m1,
m1_inj,
mmin=m1min,
mmax=mmax,
**kwargs_m,
**kwargs,
)
self.ratio_model = BSplineRatio(
n_splines_q,
q,
q_inj,
qmin=m2min / mmax,
**kwargs_q,
**kwargs,
)
[docs]
def __call__(self, mcoefs, qcoefs, pe_samples=True):
"""Evaluate the joint probability density over the parameter estimation or injection samples.
Use flag `pe_samples` to specify which samples are being evaluated (parameter estimation or injection).
Parameters
----------
mcoefs, qcoefs : array_like
Spline coefficients for the primary component mass and mass ratio.
pe_samples : bool, default=True
If `True`, design matrix is evaluated across parameter estimation samples.
If `False`, design matrix is evaluated across injection samples.
Returns
-------
array_like
Joint probability density for parameter estimation or injection samples.
"""
return self.ratio_model(qcoefs, pe_samples=pe_samples) * self.primary_model(mcoefs, pe_samples=pe_samples)
[docs]
class BSplineIIDComponentMasses(object):
r"""B-Spline model for the masses of both binary components assuming they are independently and identically distributed (IID),
with an optional pairing term as a powerlaw in mass ratio.
.. math::
p(m_1, m_2 \mid \mathbf{c}, \beta) = p(m_1 \mid \mathbf{c}) p(m_2 \mid \mathbf{c}) \left(\frac{m_2}{m_1}\right)^\beta,
where :math:`\mathbf{c}` is a vector of the ``n_splines`` basis spline coefficients.
Parameters
----------
n_splines : int
Number of basis functions, i.e., the number of degrees of freedom, of the spline model.
m1, m2 : array_like
Primary and secondary component mass parameter estimation samples for basis evaluation.
m1_inj, m2_inj : array_like
Primary and secondary component mass injection samples for basis evaluation.
mmin : float, default=2
Minimum component mass.
mmax : float, default=100
Maximum component mass.
**kwargs : dict, optional
Additional keyword arguments to pass to the basis spline model.
"""
[docs]
def __init__(
self,
n_splines,
m1,
m2,
m1_inj,
m2_inj,
mmin=2,
mmax=100,
**kwargs,
):
self.primary_model = BSplineMass(
n_splines=n_splines,
m=m1,
m_inj=m1_inj,
mmin=mmin,
mmax=mmax,
**kwargs,
)
self.secondary_model = BSplineMass(
n_splines=n_splines,
m=m2,
m_inj=m2_inj,
mmin=mmin,
mmax=mmax,
**kwargs,
)
self.qs = [m2_inj / m1_inj, m2 / m1]
[docs]
def __call__(self, coefs, beta=0, pe_samples=True):
"""Evaluate the joint probability density over the parameter estimation or injection samples.
Use flag `pe_samples` to specify which samples are being evaluated (parameter estimation or injection).
Parameters
----------
coefs : array_like
Spline coefficients.
beta : float, default=0
Mass ratio powerlaw slope.
pe_samples : bool, default=True
If `True`, design matrix is evaluated across parameter estimation samples.
If `False`, design matrix is evaluated across injection samples.
Returns
-------
array_like
Joint probability density for parameter estimation or injection samples.
"""
p_m1 = self.primary_model(coefs, pe_samples=pe_samples)
p_m2 = self.secondary_model(coefs, pe_samples=pe_samples)
dim = 1 if pe_samples else 0
return jnp.where(
jnp.less(self.qs[dim], 0) | jnp.greater(self.qs[dim], 1),
0,
p_m1 * p_m2,
) * jnp.power(self.qs[dim], beta)
[docs]
class BSplineIndependentComponentMasses(object):
r"""A B-Spline model for the masses of the primary and secondary components assuming
they are independently distributed, with an optional pairing term as a powerlaw in mass ratio,
.. math::
p(m_1, m_2 \mid \mathbf{c}_1, \mathbf{c}_2, \beta) = p(m_1 \mid \mathbf{c}_1) p(m_2 \mid \mathbf{c}_2) \left(\frac{m_2}{m_1}\right)^\beta,
where :math:`\mathbf{c}_1` and :math:`\mathbf{c}_2` are vectors of the ``n_splines1`` and ``n_splines2``
basis spline coefficients for the primary and secondary component masses, respectively.
Parameters
----------
n_splines1, n_splines2 : int
Number of basis functions, i.e., the number of degrees of freedom, of the
primary and secondary component spline models.
m1, m2 : array_like
Primary and secondary component mass parameter estimation samples for basis evaluation.
m1_inj, m2_inj : array_like
Primary and secondary component mass injection samples for basis evaluation.
mmin1, mmax1 : float, default=2, 100
Minimum and maximum primary component mass.
mmin2, mmax2 : float, default=2, 100
Minimum and maximum secondary component mass.
kwargs1, kwargs2 : dict, optional
Additional keyword arguments to pass to the basis spline model for the primary and secondary components.
**kwargs : dict, optional
Additional keyword arguments to pass to both basis spline models.
"""
[docs]
def __init__(
self,
n_splines1,
n_splines2,
m1,
m2,
m1_inj,
m2_inj,
mmin1=2,
mmax1=100,
mmin2=2,
mmax2=100,
kwargs1={},
kwargs2={},
**kwargs,
):
self.primary_model = BSplineMass(
n_splines=n_splines1,
m=m1,
m_inj=m1_inj,
mmin=mmin1,
mmax=mmax1,
**kwargs1,
**kwargs,
)
self.secondary_model = BSplineMass(
n_splines=n_splines2,
m=m2,
m_inj=m2_inj,
mmin=mmin2,
mmax=mmax2,
**kwargs2,
**kwargs,
)
self.qs = [m2_inj / m1_inj, m2 / m1]
[docs]
def __call__(self, pcoefs, scoefs, beta=0, pe_samples=True):
"""Evaluate the joint probability density over the parameter estimation or injection samples.
Use flag `pe_samples` to specify which samples are being evaluated (parameter estimation or injection).
Parameters
----------
pcoefs, scoefs : array_like
Spline coefficients for the (p)rimary and (s)econdary components.
beta : float, default=0
Mass ratio powerlaw slope.
pe_samples : bool, default=True
If `True`, design matrix is evaluated across parameter estimation samples.
If `False`, design matrix is evaluated across injection samples.
Returns
-------
array_like
Joint probability density for parameter estimation or injection samples.
"""
p_m1 = self.primary_model(pcoefs, pe_samples=pe_samples)
p_m2 = self.secondary_model(scoefs, pe_samples=pe_samples)
dim = 1 if pe_samples else 0
return p_m1 * p_m2 * self.qs[dim] ** beta
[docs]
class BSplineEffectiveSpinDims(object):
r"""B-Spline models for the effective spin (:math:`\chi_\mathrm{eff}`) and
effective precession (:math:`\chi_\mathrm{p}`) of binaries,
.. math::
p(\chi_\mathrm{eff}, \chi_\mathrm{p} \mid \mathbf{c}_\mathrm{eff}, \mathbf{c}_\mathrm{p}) = p(\chi_\mathrm{eff} \mid \mathbf{c}_\mathrm{eff}) p(\chi_\mathrm{p} \mid \mathbf{c}_\mathrm{p}),
where :math:`\mathbf{c}_\mathrm{eff}` and :math:`\mathbf{c}_\mathrm{p}` are vectors of the ``n_splines_e``
and ``n_splines_p`` basis spline coefficients for the effective spin and effective precession, respectively.
Parameters
----------
n_splines_e, n_splines_p : int
Number of basis functions, i.e., the number of degrees of freedom, of the
(e)ffective spin and effective (p)recession spline models.
chieff, chip : array_like
Effective spin and effective precession parameter estimation samples for basis evaluation.
chieff_inj, chip_inj : array_like
Effective spin and effective precession injection samples for basis evaluation.
kwargs_e, kwargs_p : dict, optional
Additional keyword arguments to pass to the basis spline models for the effective spin and effective precession.
**kwargs : dict, optional
Additional keyword arguments to pass to both basis spline models.
"""
[docs]
def __init__(
self,
n_splines_e,
n_splines_p,
chieff,
chip,
chieff_inj,
chip_inj,
kwargs_e={},
kwargs_p={},
**kwargs,
):
self.chi_eff_model = BSplineChiEffective(
n_splines_e,
chieff,
chieff_inj,
**kwargs_e,
**kwargs,
)
self.chi_p_model = BSplineChiPrecess(
n_splines_p,
chip,
chip_inj,
**kwargs_p,
**kwargs,
)
[docs]
def __call__(self, ecoefs, pcoefs, pe_samples=True):
"""Evaluate the joint probability density over the parameter estimation or injection samples.
Use flag `pe_samples` to specify which samples are being evaluated (parameter estimation or injection).
Parameters
----------
ecoefs, pcoefs : array_like
Spline coefficients for the effective spin and effective precession.
pe_samples : bool, default=True
If `True`, design matrix is evaluated across parameter estimation samples.
If `False`, design matrix is evaluated across injection samples.
Returns
-------
array_like
Joint probability density for parameter estimation or injection samples.
"""
p_chieff = self.chi_eff_model(ecoefs, pe_samples=pe_samples)
p_chip = self.chi_p_model(pcoefs, pe_samples=pe_samples)
return p_chieff * p_chip