mirror of
https://github.com/Richard-Sti/csiborgtools.git
synced 2024-12-22 12:38:02 +00:00
Direct distance sampling (#155)
* Update nb * Update dependency * Pass marg arg * Add mu sampling * Update imprts * Move cosmography to a ceparate module * Add mock void * Check Vext likelihoo * Add void mock * Add void mocks
This commit is contained in:
parent
34f997cd33
commit
76a7609f7f
8 changed files with 685 additions and 555 deletions
|
@ -18,4 +18,5 @@ from .flow_model import (PV_LogLikelihood, PV_validation_model, dist2redshift,
|
||||||
Observed2CosmologicalRedshift, predict_zobs, # noqa
|
Observed2CosmologicalRedshift, predict_zobs, # noqa
|
||||||
project_Vext, stack_pzosmo_over_realizations) # noqa
|
project_Vext, stack_pzosmo_over_realizations) # noqa
|
||||||
from .selection import ToyMagnitudeSelection # noqa
|
from .selection import ToyMagnitudeSelection # noqa
|
||||||
from .void_model import load_void_data, interpolate_void # noqa
|
from .void_model import (load_void_data, interpolate_void, select_void_h, # noqa
|
||||||
|
mock_void) # noqa
|
||||||
|
|
94
csiborgtools/flow/cosmography.py
Normal file
94
csiborgtools/flow/cosmography.py
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
# Copyright (C) 2024 Richard Stiskalek
|
||||||
|
# This program is free software; you can redistribute it and/or modify it
|
||||||
|
# under the terms of the GNU General Public License as published by the
|
||||||
|
# Free Software Foundation; either version 3 of the License, or (at your
|
||||||
|
# option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||||
|
# Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License along
|
||||||
|
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
"""Various cosmography functions for converting between distance indicators."""
|
||||||
|
from jax import numpy as jnp
|
||||||
|
|
||||||
|
from ..params import SPEED_OF_LIGHT
|
||||||
|
|
||||||
|
H0 = 100 # km / s / Mpc
|
||||||
|
|
||||||
|
|
||||||
|
def dist2redshift(dist, Omega_m, h=1.):
|
||||||
|
"""
|
||||||
|
Convert comoving distance to cosmological redshift if the Universe is
|
||||||
|
flat and z << 1.
|
||||||
|
"""
|
||||||
|
eta = 3 * Omega_m / 2
|
||||||
|
return 1 / eta * (1 - (1 - 2 * 100 * h * dist / SPEED_OF_LIGHT * eta)**0.5)
|
||||||
|
|
||||||
|
|
||||||
|
def redshift2dist(z, Omega_m):
|
||||||
|
"""
|
||||||
|
Convert cosmological redshift to comoving distance if the Universe is
|
||||||
|
flat and z << 1.
|
||||||
|
"""
|
||||||
|
q0 = 3 * Omega_m / 2 - 1
|
||||||
|
return SPEED_OF_LIGHT * z / (2 * H0) * (2 - z * (1 + q0))
|
||||||
|
|
||||||
|
|
||||||
|
def gradient_redshift2dist(z, Omega_m):
|
||||||
|
"""
|
||||||
|
Gradient of the redshift to comoving distance conversion if the Universe is
|
||||||
|
flat and z << 1.
|
||||||
|
"""
|
||||||
|
q0 = 3 * Omega_m / 2 - 1
|
||||||
|
return SPEED_OF_LIGHT / H0 * (1 - z * (1 + q0))
|
||||||
|
|
||||||
|
|
||||||
|
def distmod2dist(mu, Om0):
|
||||||
|
"""
|
||||||
|
Convert distance modulus to distance in `Mpc / h`. The expression is valid
|
||||||
|
for a flat universe over the range of 0.00001 < z < 0.1.
|
||||||
|
"""
|
||||||
|
term1 = jnp.exp((0.443288 * mu) + (-14.286531))
|
||||||
|
term2 = (0.506973 * mu) + 12.954633
|
||||||
|
term3 = ((0.028134 * mu) ** (
|
||||||
|
((0.684713 * mu)
|
||||||
|
+ ((0.151020 * mu) + (1.235158 * Om0))) - jnp.exp(0.072229 * mu)))
|
||||||
|
term4 = (-0.045160) * mu
|
||||||
|
return (-0.000301) + (term1 * (term2 - (term3 - term4)))
|
||||||
|
|
||||||
|
|
||||||
|
def distmod2dist_gradient(mu, Om0):
|
||||||
|
"""
|
||||||
|
Calculate the derivative of comoving distance in `Mpc / h` with respect to
|
||||||
|
the distance modulus. The expression is valid for a flat universe over the
|
||||||
|
range of 0.00001 < z < 0.1.
|
||||||
|
"""
|
||||||
|
term1 = jnp.exp((0.443288 * mu) + (-14.286531))
|
||||||
|
dterm1 = 0.443288 * term1
|
||||||
|
|
||||||
|
term2 = (0.506973 * mu) + 12.954633
|
||||||
|
dterm2 = 0.506973
|
||||||
|
|
||||||
|
term3 = ((0.028134 * mu)**(((0.684713 * mu) + ((0.151020 * mu) + (1.235158 * Om0))) - jnp.exp(0.072229 * mu))) # noqa
|
||||||
|
ln_base = jnp.log(0.028134) + jnp.log(mu)
|
||||||
|
exponent = 0.835733 * mu + 1.235158 * Om0 - jnp.exp(0.072229 * mu)
|
||||||
|
exponent_derivative = 0.835733 - 0.072229 * jnp.exp(0.072229 * mu)
|
||||||
|
dterm3 = term3 * ((1 / mu) * exponent + exponent_derivative * ln_base)
|
||||||
|
|
||||||
|
term4 = (-0.045160) * mu
|
||||||
|
dterm4 = -0.045160
|
||||||
|
|
||||||
|
return (dterm1 * (term2 - (term3 - term4))
|
||||||
|
+ term1 * (dterm2 - (dterm3 - dterm4)))
|
||||||
|
|
||||||
|
|
||||||
|
def distmod2redshift(mu, Om0):
|
||||||
|
"""
|
||||||
|
Convert distance modulus to redshift, assuming `h = 1`. The expression is
|
||||||
|
valid for a flat universe over the range of 0.00001 < z < 0.1.
|
||||||
|
"""
|
||||||
|
return jnp.exp(((0.461108 * mu) - ((0.022187 * Om0) + (((0.022347 * mu)** (12.631788 - ((-6.708757) * Om0))) + 19.529852)))) # noqa
|
|
@ -25,10 +25,11 @@ from abc import ABC, abstractmethod
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from astropy import units as u
|
from astropy import units as u
|
||||||
from astropy.coordinates import SkyCoord, angular_separation
|
|
||||||
from astropy.cosmology import FlatLambdaCDM, z_at_value
|
from astropy.cosmology import FlatLambdaCDM, z_at_value
|
||||||
|
from interpax import interp1d
|
||||||
from jax import jit
|
from jax import jit
|
||||||
from jax import numpy as jnp
|
from jax import numpy as jnp
|
||||||
|
from jax import vmap
|
||||||
from jax.scipy.special import erf, logsumexp
|
from jax.scipy.special import erf, logsumexp
|
||||||
from numpyro import factor, plate, sample
|
from numpyro import factor, plate, sample
|
||||||
from numpyro.distributions import MultivariateNormal, Normal, Uniform
|
from numpyro.distributions import MultivariateNormal, Normal, Uniform
|
||||||
|
@ -37,57 +38,19 @@ from tqdm import trange
|
||||||
|
|
||||||
from ..params import SPEED_OF_LIGHT
|
from ..params import SPEED_OF_LIGHT
|
||||||
from ..utils import fprint
|
from ..utils import fprint
|
||||||
|
from .cosmography import (dist2redshift, distmod2dist, distmod2dist_gradient,
|
||||||
|
distmod2redshift, gradient_redshift2dist)
|
||||||
from .selection import toy_log_magnitude_selection
|
from .selection import toy_log_magnitude_selection
|
||||||
from .void_model import interpolate_void, load_void_data
|
from .void_model import (angular_distance_from_void_axis, interpolate_void,
|
||||||
|
load_void_data)
|
||||||
|
|
||||||
H0 = 100 # km / s / Mpc
|
H0 = 100 # km / s / Mpc
|
||||||
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# JAX Flow model #
|
# Various flow utilities #
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
def dist2redshift(dist, Omega_m, h=1.):
|
|
||||||
"""
|
|
||||||
Convert comoving distance to cosmological redshift if the Universe is
|
|
||||||
flat and z << 1.
|
|
||||||
"""
|
|
||||||
eta = 3 * Omega_m / 2
|
|
||||||
return 1 / eta * (1 - (1 - 2 * 100 * h * dist / SPEED_OF_LIGHT * eta)**0.5)
|
|
||||||
|
|
||||||
|
|
||||||
def redshift2dist(z, Omega_m):
|
|
||||||
"""
|
|
||||||
Convert cosmological redshift to comoving distance if the Universe is
|
|
||||||
flat and z << 1.
|
|
||||||
"""
|
|
||||||
q0 = 3 * Omega_m / 2 - 1
|
|
||||||
return SPEED_OF_LIGHT * z / (2 * H0) * (2 - z * (1 + q0))
|
|
||||||
|
|
||||||
|
|
||||||
def gradient_redshift2dist(z, Omega_m):
|
|
||||||
"""
|
|
||||||
Gradient of the redshift to comoving distance conversion if the Universe is
|
|
||||||
flat and z << 1.
|
|
||||||
"""
|
|
||||||
q0 = 3 * Omega_m / 2 - 1
|
|
||||||
return SPEED_OF_LIGHT / H0 * (1 - z * (1 + q0))
|
|
||||||
|
|
||||||
|
|
||||||
def distmod2dist(mu, Om0):
|
|
||||||
"""
|
|
||||||
Convert distance modulus to distance in `Mpc / h`. The expression is valid
|
|
||||||
for a flat universe over the range of 0.00001 < z < 0.1.
|
|
||||||
"""
|
|
||||||
term1 = jnp.exp((0.443288 * mu) + (-14.286531))
|
|
||||||
term2 = (0.506973 * mu) + 12.954633
|
|
||||||
term3 = ((0.028134 * mu) ** (
|
|
||||||
((0.684713 * mu)
|
|
||||||
+ ((0.151020 * mu) + (1.235158 * Om0))) - jnp.exp(0.072229 * mu)))
|
|
||||||
term4 = (-0.045160) * mu
|
|
||||||
return (-0.000301) + (term1 * (term2 - (term3 - term4)))
|
|
||||||
|
|
||||||
|
|
||||||
def project_Vext(Vext_x, Vext_y, Vext_z, RA_radians, dec_radians):
|
def project_Vext(Vext_x, Vext_y, Vext_z, RA_radians, dec_radians):
|
||||||
"""Project the external velocity vector onto the line of sight."""
|
"""Project the external velocity vector onto the line of sight."""
|
||||||
cos_dec = jnp.cos(dec_radians)
|
cos_dec = jnp.cos(dec_radians)
|
||||||
|
@ -150,6 +113,37 @@ def upper_truncated_normal_logpdf(x, loc, scale, xmax):
|
||||||
return normal_logpdf(x, loc, scale) - jnp.log(norm)
|
return normal_logpdf(x, loc, scale) - jnp.log(norm)
|
||||||
|
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# LOS interpolation #
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
|
||||||
|
def interpolate_los(r, los, rgrid, method="cubic"):
|
||||||
|
"""
|
||||||
|
Interpolate the LOS field at a given radial distance.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
r : 1-dimensional array of shape `(n_gal, )`
|
||||||
|
Radial distances at which to interpolate the LOS field.
|
||||||
|
los : 3-dimensional array of shape `(n_sims, n_gal, n_steps)`
|
||||||
|
LOS field.
|
||||||
|
rmin, rmax : float
|
||||||
|
Minimum and maximum radial distances in the data.
|
||||||
|
order : int, optional
|
||||||
|
The order of the interpolation. Default is 1, can be 0.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
2-dimensional array of shape `(n_sims, n_gal)`
|
||||||
|
"""
|
||||||
|
# Vectorize over the inner loop (ngal) first, then the outer loop (nsim)
|
||||||
|
def f(rn, los_row):
|
||||||
|
return interp1d(rn, rgrid, los_row, method=method)
|
||||||
|
|
||||||
|
return vmap(vmap(f, in_axes=(0, 0)), in_axes=(None, 0))(r, los)
|
||||||
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Base flow validation #
|
# Base flow validation #
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
@ -232,17 +226,12 @@ class BaseFlowValidationModel(ABC):
|
||||||
rLG_grid *= h
|
rLG_grid *= h
|
||||||
rLG_min, rLG_max = rLG_grid.min(), rLG_grid.max()
|
rLG_min, rLG_max = rLG_grid.min(), rLG_grid.max()
|
||||||
rgrid_min, rgrid_max = 0, 250
|
rgrid_min, rgrid_max = 0, 250
|
||||||
fprint(f"setting radial grid from {rLG_min} to {rLG_max} Mpc.")
|
fprint(f"setting radial grid from {rLG_min} to {rLG_max} Mpc / h.")
|
||||||
rgrid_max *= h
|
rgrid_max *= h
|
||||||
|
|
||||||
# Get angular separation (in degrees) of each object from the model
|
# Get angular separation of each object from the model axis.
|
||||||
# axis.
|
phi = angular_distance_from_void_axis(RA, dec)
|
||||||
model_axis = SkyCoord(l=117, b=4, frame='galactic', unit='deg').icrs
|
phi = jnp.asarray(phi, dtype=jnp.float32)
|
||||||
coords = SkyCoord(ra=RA, dec=dec, unit='deg').icrs
|
|
||||||
|
|
||||||
phi = angular_separation(coords.ra.rad, coords.dec.rad,
|
|
||||||
model_axis.ra.rad, model_axis.dec.rad)
|
|
||||||
phi = jnp.asarray(phi * 180 / np.pi, dtype=jnp.float32)
|
|
||||||
|
|
||||||
if kind == "density":
|
if kind == "density":
|
||||||
void_grid = jnp.log(void_grid)
|
void_grid = jnp.log(void_grid)
|
||||||
|
@ -291,6 +280,12 @@ class BaseFlowValidationModel(ABC):
|
||||||
|
|
||||||
return self._los_velocity
|
return self._los_velocity
|
||||||
|
|
||||||
|
def log_los_density_at_r(self, r):
|
||||||
|
return interpolate_los(r, self.log_los_density(), self.r_xrange, )
|
||||||
|
|
||||||
|
def los_velocity_at_r(self, r):
|
||||||
|
return interpolate_los(r, self.los_velocity(), self.r_xrange, )
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def __call__(self, **kwargs):
|
def __call__(self, **kwargs):
|
||||||
pass
|
pass
|
||||||
|
@ -514,16 +509,16 @@ class PV_LogLikelihood(BaseFlowValidationModel):
|
||||||
Name of the catalogue.
|
Name of the catalogue.
|
||||||
void_kwargs : dict, optional
|
void_kwargs : dict, optional
|
||||||
Void data parameters. If `None` the data is not void data.
|
Void data parameters. If `None` the data is not void data.
|
||||||
with_num_dist_marginalisation : bool, optional
|
wo_num_dist_marginalisation : bool, optional
|
||||||
Whether to use numerical distance marginalisation, in which case
|
Whether to directly sample the distance without numerical
|
||||||
the tracers cannot be coupled by a covariance matrix. By default
|
marginalisation. in which case the tracers can be coupled by a
|
||||||
`True`.
|
covariance matrix. By default `False`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, los_density, los_velocity, RA, dec, z_obs, e_zobs,
|
def __init__(self, los_density, los_velocity, RA, dec, z_obs, e_zobs,
|
||||||
calibration_params, abs_calibration_params, mag_selection,
|
calibration_params, abs_calibration_params, mag_selection,
|
||||||
r_xrange, Omega_m, kind, name, void_kwargs=None,
|
r_xrange, Omega_m, kind, name, void_kwargs=None,
|
||||||
with_num_dist_marginalisation=True):
|
wo_num_dist_marginalisation=False):
|
||||||
if e_zobs is not None:
|
if e_zobs is not None:
|
||||||
e2_cz_obs = jnp.asarray((SPEED_OF_LIGHT * e_zobs)**2)
|
e2_cz_obs = jnp.asarray((SPEED_OF_LIGHT * e_zobs)**2)
|
||||||
else:
|
else:
|
||||||
|
@ -549,7 +544,7 @@ class PV_LogLikelihood(BaseFlowValidationModel):
|
||||||
values += [jnp.log(los_density), los_velocity]
|
values += [jnp.log(los_density), los_velocity]
|
||||||
|
|
||||||
# Density required only if not numerically marginalising.
|
# Density required only if not numerically marginalising.
|
||||||
if not with_num_dist_marginalisation:
|
if not wo_num_dist_marginalisation:
|
||||||
names += ["_los_density"]
|
names += ["_los_density"]
|
||||||
values += [los_density]
|
values += [los_density]
|
||||||
|
|
||||||
|
@ -561,12 +556,9 @@ class PV_LogLikelihood(BaseFlowValidationModel):
|
||||||
self.kind = kind
|
self.kind = kind
|
||||||
self.name = name
|
self.name = name
|
||||||
self.Omega_m = Omega_m
|
self.Omega_m = Omega_m
|
||||||
self.with_num_dist_marginalisation = with_num_dist_marginalisation
|
self.wo_num_dist_marginalisation = wo_num_dist_marginalisation
|
||||||
self.norm = - self.ndata * jnp.log(self.num_sims)
|
self.norm = - self.ndata * jnp.log(self.num_sims)
|
||||||
|
|
||||||
# TODO: Somewhere here prepare the interpolators in case of no
|
|
||||||
# numerical marginalisation.
|
|
||||||
|
|
||||||
if mag_selection is not None:
|
if mag_selection is not None:
|
||||||
self.mag_selection_kind = mag_selection["kind"]
|
self.mag_selection_kind = mag_selection["kind"]
|
||||||
|
|
||||||
|
@ -767,30 +759,20 @@ class PV_LogLikelihood(BaseFlowValidationModel):
|
||||||
else:
|
else:
|
||||||
raise ValueError(f"Unknown kind: `{self.kind}`.")
|
raise ValueError(f"Unknown kind: `{self.kind}`.")
|
||||||
|
|
||||||
# h = field_calibration_params["h"]
|
|
||||||
# ----------------------------------------------------------------
|
# ----------------------------------------------------------------
|
||||||
# 2. Log-likelihood of the true distance and observed redshifts.
|
# 2. Log-likelihood of the true distance and observed redshifts.
|
||||||
# The marginalisation of the true distance can be done numerically.
|
# The marginalisation of the true distance can be done numerically.
|
||||||
# ----------------------------------------------------------------
|
# ----------------------------------------------------------------
|
||||||
if self.with_num_dist_marginalisation:
|
if not self.wo_num_dist_marginalisation:
|
||||||
|
|
||||||
if field_calibration_params["sample_h"]:
|
if field_calibration_params["sample_h"]:
|
||||||
raise NotImplementedError("Sampling of h not implemented.")
|
raise NotImplementedError(
|
||||||
# Rescale the grid to account for the sampled H0. For distance
|
"Sampling of 'h' is not supported if numerically "
|
||||||
# modulus going from Mpc / h to Mpc implies larger numerical
|
"marginalising the true distance.")
|
||||||
# values, so there has to be a minus sign since h < 1.
|
|
||||||
# mu_xrange = self.mu_xrange - 5 * jnp.log(h)
|
|
||||||
|
|
||||||
# The redshift should also be boosted since now the object are
|
|
||||||
# further away?
|
|
||||||
|
|
||||||
# Actually, the redshift ought to remain the same?
|
|
||||||
else:
|
|
||||||
mu_xrange = self.mu_xrange
|
|
||||||
|
|
||||||
# Calculate p(r) (Malmquist bias). Shape is (ndata, nxrange)
|
# Calculate p(r) (Malmquist bias). Shape is (ndata, nxrange)
|
||||||
log_ptilde = log_ptilde_wo_bias(
|
log_ptilde = log_ptilde_wo_bias(
|
||||||
mu_xrange[None, :], mu[:, None], e2_mu[:, None],
|
self.mu_xrange[None, :], mu[:, None], e2_mu[:, None],
|
||||||
self.log_r2_xrange[None, :])
|
self.log_r2_xrange[None, :])
|
||||||
|
|
||||||
if self.is_void_data:
|
if self.is_void_data:
|
||||||
|
@ -832,56 +814,52 @@ class PV_LogLikelihood(BaseFlowValidationModel):
|
||||||
return ll0 + jnp.sum(logsumexp(ll, axis=0)) + self.norm
|
return ll0 + jnp.sum(logsumexp(ll, axis=0)) + self.norm
|
||||||
else:
|
else:
|
||||||
if field_calibration_params["sample_h"]:
|
if field_calibration_params["sample_h"]:
|
||||||
raise NotImplementedError("Sampling of h not implemented.")
|
raise NotImplementedError(
|
||||||
|
"Sampling of h is not yet implemented.")
|
||||||
raise NotImplementedError(
|
|
||||||
"Sampling of distance is not implemented. Work in progress.")
|
|
||||||
|
|
||||||
e_mu = jnp.sqrt(e2_mu)
|
e_mu = jnp.sqrt(e2_mu)
|
||||||
# True distance modulus, shape is `(n_data)``
|
# True distance modulus, shape is `(n_data)``
|
||||||
with plate("plate_mu", self.ndata):
|
with plate("plate_mu", self.ndata):
|
||||||
mu_true = sample("mu", Normal(mu, e_mu))
|
mu_true = sample("mu", Normal(mu, e_mu))
|
||||||
|
|
||||||
# True distance, shape is `(n_data)``
|
# True distance and redshift, shape is `(n_data)`.
|
||||||
r_true = distmod2dist(mu_true, self.Omega_m)
|
r_true = distmod2dist(mu_true, self.Omega_m)
|
||||||
# TODO:
|
z_true = distmod2redshift(mu_true, self.Omega_m)
|
||||||
z_true = None
|
|
||||||
|
|
||||||
if self.is_void_data:
|
if self.is_void_data:
|
||||||
raise NotImplementedError(
|
raise NotImplementedError(
|
||||||
"Void data not implemented yet for distance sampling.")
|
"Void data not implemented yet for distance sampling.")
|
||||||
else:
|
else:
|
||||||
# grid log(density), shape is `(n_sims, n_data, n_rad)`
|
# Grid log(density), shape is `(n_sims, n_data, n_rad)`
|
||||||
log_los_density_grid = self.los_density()
|
log_los_density_grid = self.log_los_density()
|
||||||
|
|
||||||
# TODO: Need to add the interpolators for these
|
|
||||||
# Densities and velocities at the true distances, shape is
|
# Densities and velocities at the true distances, shape is
|
||||||
# `(n_sims, n_data)`
|
# `(n_sims, n_data)`
|
||||||
log_density = None
|
log_density = self.log_los_density_at_r(r_true)
|
||||||
los_velocity = None
|
los_velocity = self.los_velocity_at_r(r_true)
|
||||||
|
|
||||||
alpha = distmod_params["alpha"]
|
alpha = distmod_params["alpha"]
|
||||||
|
|
||||||
# Check dimensions of all this
|
|
||||||
|
|
||||||
# Normalisation of p(mu), shape is `(n_sims, n_data, n_rad)`
|
# Normalisation of p(mu), shape is `(n_sims, n_data, n_rad)`
|
||||||
pnorm = (
|
pnorm = (
|
||||||
self.log_r2_xrange[None, None, :]
|
+ self.log_r2_xrange[None, None, :]
|
||||||
+ alpha * log_los_density_grid
|
+ alpha * log_los_density_grid
|
||||||
+ normal_logpdf(
|
+ normal_logpdf(
|
||||||
self.mu_xrange[None, :], mu[:, None], e_mu[:, None])[None, ...]) # noqa
|
self.mu_xrange[None, :], mu[:, None], e_mu[:, None])[None, ...]) # noqa
|
||||||
|
|
||||||
pnorm = jnp.exp(pnorm)
|
pnorm = jnp.exp(pnorm)
|
||||||
|
# Now integrate over the radial steps. Shape is `(nsims, ndata)`.
|
||||||
# Normalization of p(mu). Shape is now (nsims, ndata)
|
# No Jacobian here because I integrate over distance, not the
|
||||||
|
# distance modulus.
|
||||||
pnorm = simpson(pnorm, x=self.r_xrange, axis=-1)
|
pnorm = simpson(pnorm, x=self.r_xrange, axis=-1)
|
||||||
|
|
||||||
# TODO: There should be a Jacobian?
|
# Jacobian |dr / dmu|_(mu_true), shape is `(n_data)`.
|
||||||
|
jac = jnp.abs(distmod2dist_gradient(mu_true, self.Omega_m))
|
||||||
|
|
||||||
# Calculate unnormalized log p(mu). Shape is (nsims, ndata)
|
# Calculate unnormalized log p(mu). Shape is (nsims, ndata)
|
||||||
ll = (
|
ll = (
|
||||||
2 * (jnp.log(r_true) - self.log_r2_xrange_mean)[None, :]
|
+ jnp.log(jac)[None, :]
|
||||||
|
+ (2 * jnp.log(r_true) - self.log_r2_xrange_mean)[None, :]
|
||||||
+ alpha * log_density
|
+ alpha * log_density
|
||||||
+ normal_logpdf(mu_true, mu, e_mu)[None, :])
|
)
|
||||||
|
|
||||||
# Subtract the normalization. Shape remains (nsims, ndata)
|
# Subtract the normalization. Shape remains (nsims, ndata)
|
||||||
ll -= jnp.log(pnorm)
|
ll -= jnp.log(pnorm)
|
||||||
|
@ -933,7 +911,7 @@ def PV_validation_model(models, distmod_hyperparams_per_model,
|
||||||
# We sample the components of Vext with a uniform prior, which means
|
# We sample the components of Vext with a uniform prior, which means
|
||||||
# there is a |Vext|^2 prior, we correct for this so that the sampling
|
# there is a |Vext|^2 prior, we correct for this so that the sampling
|
||||||
# is effecitvely uniformly in magnitude of Vext and angles.
|
# is effecitvely uniformly in magnitude of Vext and angles.
|
||||||
if "Vext" in field_calibration_params:
|
if "Vext" in field_calibration_params and not field_calibration_hyperparams["no_Vext"]: # noqa
|
||||||
ll -= jnp.log(jnp.sum(field_calibration_params["Vext"]**2))
|
ll -= jnp.log(jnp.sum(field_calibration_params["Vext"]**2))
|
||||||
|
|
||||||
for n in range(len(models)):
|
for n in range(len(models)):
|
||||||
|
|
|
@ -20,6 +20,7 @@ from h5py import File
|
||||||
from ..params import SPEED_OF_LIGHT, simname2Omega_m
|
from ..params import SPEED_OF_LIGHT, simname2Omega_m
|
||||||
from ..utils import fprint, radec_to_galactic, radec_to_supergalactic
|
from ..utils import fprint, radec_to_galactic, radec_to_supergalactic
|
||||||
from .flow_model import PV_LogLikelihood
|
from .flow_model import PV_LogLikelihood
|
||||||
|
from .void_model import load_void_data, mock_void, select_void_h
|
||||||
|
|
||||||
H0 = 100 # km / s / Mpc
|
H0 = 100 # km / s / Mpc
|
||||||
|
|
||||||
|
@ -242,6 +243,25 @@ class DataLoader:
|
||||||
arr = np.empty(len(f["RA"]), dtype=dtype)
|
arr = np.empty(len(f["RA"]), dtype=dtype)
|
||||||
for key in f.keys():
|
for key in f.keys():
|
||||||
arr[key] = f[key][:]
|
arr[key] = f[key][:]
|
||||||
|
elif "IndranilVoidTFRMock" in catalogue:
|
||||||
|
# The name can be e.g. "IndranilVoidTFRMock_exp_34_0", where the
|
||||||
|
# first and second number are the LG observer index and random
|
||||||
|
# seed.
|
||||||
|
profile, rLG_index, seed = catalogue.split("_")[1:]
|
||||||
|
rLG_index = int(rLG_index)
|
||||||
|
seed = int(seed)
|
||||||
|
rLG, vrad_data = load_void_data(profile, "vrad")
|
||||||
|
h = select_void_h(profile)
|
||||||
|
print(f"Mock observed galaxies for LG observer with index "
|
||||||
|
f"{rLG_index} at {rLG[rLG_index] * h} Mpc / h and "
|
||||||
|
f"seed {seed}.")
|
||||||
|
mock_data = mock_void(vrad_data, rLG_index, profile, seed=seed)[0]
|
||||||
|
|
||||||
|
# Convert the dictionary to a structured array
|
||||||
|
dtype = [(key, np.float32) for key in mock_data.keys()]
|
||||||
|
arr = np.empty(len(mock_data["RA"]), dtype=dtype)
|
||||||
|
for key in mock_data.keys():
|
||||||
|
arr[key] = mock_data[key]
|
||||||
elif "UPGLADE" in catalogue:
|
elif "UPGLADE" in catalogue:
|
||||||
with File(catalogue_fpath, 'r') as f:
|
with File(catalogue_fpath, 'r') as f:
|
||||||
dtype = [(key, np.float32) for key in f.keys()]
|
dtype = [(key, np.float32) for key in f.keys()]
|
||||||
|
@ -354,8 +374,8 @@ def mask_fields(density, velocity, mask, return_none):
|
||||||
|
|
||||||
|
|
||||||
def get_model(loader, zcmb_min=None, zcmb_max=None, mag_selection=None,
|
def get_model(loader, zcmb_min=None, zcmb_max=None, mag_selection=None,
|
||||||
absolute_calibration=None, calibration_fpath=None,
|
wo_num_dist_marginalisation=False, absolute_calibration=None,
|
||||||
void_kwargs=None):
|
calibration_fpath=None, void_kwargs=None):
|
||||||
"""
|
"""
|
||||||
Get a model and extract the relevant data from the loader.
|
Get a model and extract the relevant data from the loader.
|
||||||
|
|
||||||
|
@ -369,9 +389,14 @@ def get_model(loader, zcmb_min=None, zcmb_max=None, mag_selection=None,
|
||||||
Maximum observed redshift in the CMB frame to include.
|
Maximum observed redshift in the CMB frame to include.
|
||||||
mag_selection : dict, optional
|
mag_selection : dict, optional
|
||||||
Magnitude selection parameters.
|
Magnitude selection parameters.
|
||||||
|
wo_num_dist_marginalisation : bool, optional
|
||||||
|
Whether to directly sample the distance without numerical
|
||||||
|
marginalisation. in which case the tracers can be coupled by a
|
||||||
|
covariance matrix. By default `False`.
|
||||||
add_absolute_calibration : bool, optional
|
add_absolute_calibration : bool, optional
|
||||||
Whether to add an absolute calibration for CF4 TFRs.
|
Whether to add an absolute calibration for CF4 TFRs.
|
||||||
calibration_fpath : str, optional
|
calibration_fpath : str, optional
|
||||||
|
Path to the file containing the absolute calibration of CF4 TFR.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
|
@ -418,7 +443,8 @@ def get_model(loader, zcmb_min=None, zcmb_max=None, mag_selection=None,
|
||||||
los_overdensity, los_velocity,
|
los_overdensity, los_velocity,
|
||||||
RA[mask], dec[mask], zCMB[mask], e_zCMB, calibration_params,
|
RA[mask], dec[mask], zCMB[mask], e_zCMB, calibration_params,
|
||||||
None, mag_selection, loader.rdist, loader._Omega_m, "SN",
|
None, mag_selection, loader.rdist, loader._Omega_m, "SN",
|
||||||
name=kind, void_kwargs=void_kwargs)
|
name=kind, void_kwargs=void_kwargs,
|
||||||
|
wo_num_dist_marginalisation=wo_num_dist_marginalisation)
|
||||||
elif "Pantheon+" in kind:
|
elif "Pantheon+" in kind:
|
||||||
keys = ["RA", "DEC", "zCMB", "mB", "x1", "c", "biasCor_m_b", "mBERR",
|
keys = ["RA", "DEC", "zCMB", "mB", "x1", "c", "biasCor_m_b", "mBERR",
|
||||||
"x1ERR", "cERR", "biasCorErr_m_b", "zCMB_SN", "zCMB_Group",
|
"x1ERR", "cERR", "biasCorErr_m_b", "zCMB_SN", "zCMB_Group",
|
||||||
|
@ -451,8 +477,9 @@ def get_model(loader, zcmb_min=None, zcmb_max=None, mag_selection=None,
|
||||||
los_overdensity, los_velocity,
|
los_overdensity, los_velocity,
|
||||||
RA[mask], dec[mask], zCMB[mask], e_zCMB[mask], calibration_params,
|
RA[mask], dec[mask], zCMB[mask], e_zCMB[mask], calibration_params,
|
||||||
None, mag_selection, loader.rdist, loader._Omega_m, "SN",
|
None, mag_selection, loader.rdist, loader._Omega_m, "SN",
|
||||||
name=kind, void_kwargs=void_kwargs)
|
name=kind, void_kwargs=void_kwargs,
|
||||||
elif kind in ["SFI_gals", "2MTF", "SFI_gals_masked"]:
|
wo_num_dist_marginalisation=wo_num_dist_marginalisation)
|
||||||
|
elif kind in ["SFI_gals", "2MTF", "SFI_gals_masked"] or "IndranilVoidTFRMock" in kind: # noqa
|
||||||
keys = ["RA", "DEC", "z_CMB", "mag", "eta", "e_mag", "e_eta"]
|
keys = ["RA", "DEC", "z_CMB", "mag", "eta", "e_mag", "e_eta"]
|
||||||
RA, dec, zCMB, mag, eta, e_mag, e_eta = (loader.cat[k] for k in keys)
|
RA, dec, zCMB, mag, eta, e_mag, e_eta = (loader.cat[k] for k in keys)
|
||||||
|
|
||||||
|
@ -467,7 +494,8 @@ def get_model(loader, zcmb_min=None, zcmb_max=None, mag_selection=None,
|
||||||
los_overdensity, los_velocity,
|
los_overdensity, los_velocity,
|
||||||
RA[mask], dec[mask], zCMB[mask], None, calibration_params, None,
|
RA[mask], dec[mask], zCMB[mask], None, calibration_params, None,
|
||||||
mag_selection, loader.rdist, loader._Omega_m, "TFR", name=kind,
|
mag_selection, loader.rdist, loader._Omega_m, "TFR", name=kind,
|
||||||
void_kwargs=void_kwargs)
|
void_kwargs=void_kwargs,
|
||||||
|
wo_num_dist_marginalisation=wo_num_dist_marginalisation)
|
||||||
elif "CF4_TFR_" in kind:
|
elif "CF4_TFR_" in kind:
|
||||||
# The full name can be e.g. "CF4_TFR_not2MTForSFI_i" or "CF4_TFR_i".
|
# The full name can be e.g. "CF4_TFR_not2MTForSFI_i" or "CF4_TFR_i".
|
||||||
band = kind.split("_")[-1]
|
band = kind.split("_")[-1]
|
||||||
|
@ -535,7 +563,8 @@ def get_model(loader, zcmb_min=None, zcmb_max=None, mag_selection=None,
|
||||||
los_overdensity, los_velocity,
|
los_overdensity, los_velocity,
|
||||||
RA[mask], dec[mask], z_obs[mask], None, calibration_params,
|
RA[mask], dec[mask], z_obs[mask], None, calibration_params,
|
||||||
abs_calibration_params, mag_selection, loader.rdist,
|
abs_calibration_params, mag_selection, loader.rdist,
|
||||||
loader._Omega_m, "TFR", name=kind, void_kwargs=void_kwargs)
|
loader._Omega_m, "TFR", name=kind, void_kwargs=void_kwargs,
|
||||||
|
wo_num_dist_marginalisation=wo_num_dist_marginalisation)
|
||||||
elif kind in ["CF4_GroupAll"]:
|
elif kind in ["CF4_GroupAll"]:
|
||||||
# Note, this for some reason works terribly.
|
# Note, this for some reason works terribly.
|
||||||
keys = ["RA", "DE", "Vcmb", "DMzp", "eDM"]
|
keys = ["RA", "DE", "Vcmb", "DMzp", "eDM"]
|
||||||
|
@ -556,7 +585,8 @@ def get_model(loader, zcmb_min=None, zcmb_max=None, mag_selection=None,
|
||||||
los_overdensity, los_velocity,
|
los_overdensity, los_velocity,
|
||||||
RA[mask], dec[mask], zCMB[mask], None, calibration_params, None,
|
RA[mask], dec[mask], zCMB[mask], None, calibration_params, None,
|
||||||
mag_selection, loader.rdist, loader._Omega_m, "simple",
|
mag_selection, loader.rdist, loader._Omega_m, "simple",
|
||||||
name=kind, void_kwargs=void_kwargs)
|
name=kind, void_kwargs=void_kwargs,
|
||||||
|
wo_num_dist_marginalisation=wo_num_dist_marginalisation)
|
||||||
else:
|
else:
|
||||||
raise ValueError(f"Catalogue `{kind}` not recognized.")
|
raise ValueError(f"Catalogue `{kind}` not recognized.")
|
||||||
|
|
||||||
|
|
|
@ -19,11 +19,44 @@ from os.path import join
|
||||||
from re import search
|
from re import search
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
from astropy.coordinates import SkyCoord, angular_separation
|
||||||
from jax import numpy as jnp
|
from jax import numpy as jnp
|
||||||
from jax import vmap
|
from jax import vmap
|
||||||
from jax.scipy.ndimage import map_coordinates
|
from jax.scipy.ndimage import map_coordinates
|
||||||
|
from scipy.interpolate import RegularGridInterpolator
|
||||||
from tqdm import tqdm
|
from tqdm import tqdm
|
||||||
|
|
||||||
|
from ..utils import galactic_to_radec
|
||||||
|
from ..params import SPEED_OF_LIGHT
|
||||||
|
from .cosmography import distmod2dist, distmod2redshift
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Basic void computations #
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
|
||||||
|
def angular_distance_from_void_axis(RA, dec):
|
||||||
|
"""
|
||||||
|
Calculate the angular distance of a galaxy from the void axis, all in
|
||||||
|
degrees.
|
||||||
|
"""
|
||||||
|
# Calculate the separation angle between the galaxy and the model axis.
|
||||||
|
model_axis = SkyCoord(l=117, b=4, frame='galactic', unit='deg').icrs
|
||||||
|
coords = SkyCoord(ra=RA, dec=dec, unit='deg').icrs
|
||||||
|
return angular_separation(
|
||||||
|
coords.ra.rad, coords.dec.rad,
|
||||||
|
model_axis.ra.rad, model_axis.dec.rad) * 180 / np.pi
|
||||||
|
|
||||||
|
|
||||||
|
def select_void_h(kind):
|
||||||
|
"""Select 'little h' for void profile `kind`."""
|
||||||
|
hs = {"mb": 0.7615, "gauss": 0.7724, "exp": 0.7725}
|
||||||
|
try:
|
||||||
|
return hs[kind]
|
||||||
|
except KeyError:
|
||||||
|
raise ValueError(f"Unknown void kind: `{kind}`.")
|
||||||
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# I/O of the void data #
|
# I/O of the void data #
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
@ -97,9 +130,9 @@ def interpolate_void(rLG, r, phi, data, rgrid_min, rgrid_max, rLG_min, rLG_max,
|
||||||
----------
|
----------
|
||||||
rLG : float
|
rLG : float
|
||||||
The observer's distance from the center of the void.
|
The observer's distance from the center of the void.
|
||||||
r : 1-dimensional array
|
r : 1-dimensional array of shape `(nsteps,)
|
||||||
The radial distances at which to interpolate the velocities.
|
The radial distances at which to interpolate the velocities.
|
||||||
phi : 1-dimensional array
|
phi : 1-dimensional array of shape `(ngal,)`
|
||||||
The angles at which to interpolate the velocities, in degrees,
|
The angles at which to interpolate the velocities, in degrees,
|
||||||
defining the galaxy position.
|
defining the galaxy position.
|
||||||
data : 3-dimensional array of shape (nLG, nrad, nphi)
|
data : 3-dimensional array of shape (nLG, nrad, nphi)
|
||||||
|
@ -114,7 +147,7 @@ def interpolate_void(rLG, r, phi, data, rgrid_min, rgrid_max, rLG_min, rLG_max,
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
vel : 2-dimensional array of shape (len(phi), len(r))
|
vel : 2-dimensional array of shape `(ngal, nsteps)`
|
||||||
"""
|
"""
|
||||||
nLG, nrad, nphi = data.shape
|
nLG, nrad, nphi = data.shape
|
||||||
|
|
||||||
|
@ -139,3 +172,106 @@ def interpolate_void(rLG, r, phi, data, rgrid_min, rgrid_max, rLG_min, rLG_max,
|
||||||
return map_coordinates(data, X, order=order, mode='nearest')
|
return map_coordinates(data, X, order=order, mode='nearest')
|
||||||
|
|
||||||
return vmap(interpolate_single_phi)(phi)
|
return vmap(interpolate_single_phi)(phi)
|
||||||
|
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Mock void data #
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
|
||||||
|
def mock_void(vrad_data, rLG_index, profile,
|
||||||
|
a_TF=-22.8, b_TF=-7.2, sigma_TF=0.1, sigma_v=100.,
|
||||||
|
mean_eta=0.069, std_eta=0.078, mean_e_eta=0.012,
|
||||||
|
mean_mag=10.31, std_mag=0.83, mean_e_mag=0.044,
|
||||||
|
bmin=None, add_malmquist=False, nsamples=2000, seed=42,
|
||||||
|
Om0=0.3175, verbose=False, **kwargs):
|
||||||
|
"""Mock 2MTF-like TFR data with void velocities."""
|
||||||
|
truths = {"a": a_TF, "b": b_TF, "e_mu": sigma_TF, "sigma_v": sigma_v,
|
||||||
|
"mean_eta": mean_eta, "std_eta": std_eta,
|
||||||
|
"mean_mag": mean_mag, "std_mag": std_mag,
|
||||||
|
}
|
||||||
|
|
||||||
|
gen = np.random.default_rng(seed)
|
||||||
|
|
||||||
|
# Sample the sky-distribution, either full-sky or mask out the Galactic
|
||||||
|
# plane.
|
||||||
|
l = gen.uniform(0, 360, size=nsamples) # noqa
|
||||||
|
if bmin is None:
|
||||||
|
b = np.arcsin(gen.uniform(-1, 1, size=nsamples))
|
||||||
|
else:
|
||||||
|
b = np.arcsin(gen.uniform(np.sin(np.deg2rad(bmin)), 1,
|
||||||
|
size=nsamples))
|
||||||
|
b[gen.rand(nsamples) < 0.5] *= -1
|
||||||
|
|
||||||
|
b = np.rad2deg(b)
|
||||||
|
|
||||||
|
RA, DEC = galactic_to_radec(l, b)
|
||||||
|
# Calculate the angular separation from the void axis, in degrees.
|
||||||
|
phi = angular_distance_from_void_axis(RA, DEC)
|
||||||
|
|
||||||
|
# Sample the linewidth of each galaxy from a Gaussian distribution to mimic
|
||||||
|
# the MNR procedure.
|
||||||
|
eta_true = gen.normal(mean_eta, std_eta, nsamples)
|
||||||
|
eta_obs = gen.normal(eta_true, mean_e_eta)
|
||||||
|
|
||||||
|
# Subtract the mean of the observed linewidths, so that they are
|
||||||
|
# centered around zero. For consistency subtract from both observed
|
||||||
|
# and true values.
|
||||||
|
eta_mean_sampled = np.mean(eta_obs)
|
||||||
|
eta_true -= eta_mean_sampled
|
||||||
|
eta_obs -= eta_mean_sampled
|
||||||
|
|
||||||
|
# Sample the magnitude from some Gaussian distribution to replicate MNR.
|
||||||
|
mag_true = gen.normal(mean_mag, std_mag, nsamples)
|
||||||
|
mag_obs = gen.normal(mag_true, mean_e_mag)
|
||||||
|
|
||||||
|
# Calculate the 'true' distance modulus and redshift from the TFR distance.
|
||||||
|
mu_TFR = mag_true - (a_TF + b_TF * eta_true)
|
||||||
|
if add_malmquist:
|
||||||
|
raise NotImplementedError("Malmquist bias not implemented yet.")
|
||||||
|
else:
|
||||||
|
mu_true = gen.normal(mu_TFR, sigma_TF)
|
||||||
|
|
||||||
|
# Convert the true distance modulus to true distance and cosmological
|
||||||
|
# redshift.
|
||||||
|
r = distmod2dist(mu_true, Om0)
|
||||||
|
zcosmo = distmod2redshift(mu_true, Om0)
|
||||||
|
|
||||||
|
# Little h of this void profile
|
||||||
|
h = select_void_h(profile)
|
||||||
|
|
||||||
|
# Extract the velocities for the galaxies from the grid for this LG
|
||||||
|
# index.
|
||||||
|
vrad_data_rLG = vrad_data[rLG_index]
|
||||||
|
|
||||||
|
r_grid = np.arange(0, 251) * h
|
||||||
|
phi_grid = np.arange(0, 181)
|
||||||
|
Vr = RegularGridInterpolator((r_grid, phi_grid), vrad_data_rLG,
|
||||||
|
fill_value=np.nan, bounds_error=False,
|
||||||
|
method="cubic")(np.vstack([r, phi]).T)
|
||||||
|
|
||||||
|
# The true redshift of the source.
|
||||||
|
zCMB_true = (1 + zcosmo) * (1 + Vr / SPEED_OF_LIGHT) - 1
|
||||||
|
zCMB_obs = gen.normal(zCMB_true, sigma_v / SPEED_OF_LIGHT)
|
||||||
|
|
||||||
|
sample = {"RA": RA,
|
||||||
|
"DEC": DEC,
|
||||||
|
"z_CMB": zCMB_obs,
|
||||||
|
"eta": eta_obs,
|
||||||
|
"mag": mag_obs,
|
||||||
|
"e_eta": np.ones(nsamples) * mean_e_eta,
|
||||||
|
"e_mag": np.ones(nsamples) * mean_e_mag,
|
||||||
|
"r": r,
|
||||||
|
"distmod_true": mu_true,
|
||||||
|
"distmod_TFR": mu_TFR}
|
||||||
|
|
||||||
|
# Apply a true distance cut to the mocks.
|
||||||
|
mask = r < np.max(r_grid)
|
||||||
|
for key in sample:
|
||||||
|
sample[key] = sample[key][mask]
|
||||||
|
|
||||||
|
if verbose and np.any(~mask):
|
||||||
|
print(f"Removed {(~mask).sum()} out of {mask.size} samples "
|
||||||
|
"due to the true distance cutoff.")
|
||||||
|
|
||||||
|
return sample, truths
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -88,7 +88,7 @@ def print_variables(names, variables):
|
||||||
|
|
||||||
|
|
||||||
def get_models(ksim, get_model_kwargs, mag_selection, void_kwargs,
|
def get_models(ksim, get_model_kwargs, mag_selection, void_kwargs,
|
||||||
verbose=True):
|
wo_num_dist_marginalisation, verbose=True):
|
||||||
"""Load the data and create the NumPyro models."""
|
"""Load the data and create the NumPyro models."""
|
||||||
paths = csiborgtools.read.Paths(**csiborgtools.paths_glamdring)
|
paths = csiborgtools.read.Paths(**csiborgtools.paths_glamdring)
|
||||||
folder = "/mnt/extraspace/rstiskalek/catalogs/"
|
folder = "/mnt/extraspace/rstiskalek/catalogs/"
|
||||||
|
@ -120,6 +120,8 @@ def get_models(ksim, get_model_kwargs, mag_selection, void_kwargs,
|
||||||
fpath = join(folder, "PV/CF4/CF4_TF-distances.hdf5")
|
fpath = join(folder, "PV/CF4/CF4_TF-distances.hdf5")
|
||||||
elif cat in ["CF4_GroupAll"]:
|
elif cat in ["CF4_GroupAll"]:
|
||||||
fpath = join(folder, "PV/CF4/CF4_GroupAll.hdf5")
|
fpath = join(folder, "PV/CF4/CF4_GroupAll.hdf5")
|
||||||
|
elif "IndranilVoidTFRMock" in cat:
|
||||||
|
fpath = None
|
||||||
else:
|
else:
|
||||||
raise ValueError(f"Unsupported catalogue: `{ARGS.catalogue}`.")
|
raise ValueError(f"Unsupported catalogue: `{ARGS.catalogue}`.")
|
||||||
|
|
||||||
|
@ -128,20 +130,13 @@ def get_models(ksim, get_model_kwargs, mag_selection, void_kwargs,
|
||||||
ksmooth=ARGS.ksmooth)
|
ksmooth=ARGS.ksmooth)
|
||||||
models[i] = csiborgtools.flow.get_model(
|
models[i] = csiborgtools.flow.get_model(
|
||||||
loader, mag_selection=mag_selection[i], void_kwargs=void_kwargs,
|
loader, mag_selection=mag_selection[i], void_kwargs=void_kwargs,
|
||||||
|
wo_num_dist_marginalisation=wo_num_dist_marginalisation,
|
||||||
**get_model_kwargs)
|
**get_model_kwargs)
|
||||||
|
|
||||||
fprint(f"num. radial steps is {len(loader.rdist)}")
|
fprint(f"num. radial steps is {len(loader.rdist)}")
|
||||||
return models
|
return models
|
||||||
|
|
||||||
|
|
||||||
def select_void_h(kind):
|
|
||||||
hs = {"mb": 0.7615, "gauss": 0.7724, "exp": 0.7725}
|
|
||||||
try:
|
|
||||||
return hs[kind]
|
|
||||||
except KeyError:
|
|
||||||
raise ValueError(f"Unknown void kind: `{kind}`.")
|
|
||||||
|
|
||||||
|
|
||||||
def get_harmonic_evidence(samples, log_posterior, nchains_harmonic, epoch_num):
|
def get_harmonic_evidence(samples, log_posterior, nchains_harmonic, epoch_num):
|
||||||
"""Compute evidence using the `harmonic` package."""
|
"""Compute evidence using the `harmonic` package."""
|
||||||
data, names = csiborgtools.dict_samples_to_array(samples)
|
data, names = csiborgtools.dict_samples_to_array(samples)
|
||||||
|
@ -243,7 +238,7 @@ def get_distmod_hyperparams(catalogue, sample_alpha, sample_mag_dipole):
|
||||||
"alpha_min": alpha_min, "alpha_max": alpha_max,
|
"alpha_min": alpha_min, "alpha_max": alpha_max,
|
||||||
"sample_alpha": sample_alpha
|
"sample_alpha": sample_alpha
|
||||||
}
|
}
|
||||||
elif catalogue in ["SFI_gals", "2MTF"] or "CF4_TFR" in catalogue:
|
elif catalogue in ["SFI_gals", "2MTF"] or "CF4_TFR" in catalogue or "IndranilVoidTFRMock" in catalogue: # noqa
|
||||||
return {"e_mu_min": 0.001, "e_mu_max": 1.0,
|
return {"e_mu_min": 0.001, "e_mu_max": 1.0,
|
||||||
"a_mean": -21., "a_std": 5.0,
|
"a_mean": -21., "a_std": 5.0,
|
||||||
"b_mean": -5.95, "b_std": 4.0,
|
"b_mean": -5.95, "b_std": 4.0,
|
||||||
|
@ -299,7 +294,7 @@ if __name__ == "__main__":
|
||||||
###########################################################################
|
###########################################################################
|
||||||
|
|
||||||
# `None` means default behaviour
|
# `None` means default behaviour
|
||||||
nsteps = 10_000
|
nsteps = 2_000
|
||||||
nburn = 2_000
|
nburn = 2_000
|
||||||
zcmb_min = None
|
zcmb_min = None
|
||||||
zcmb_max = 0.05
|
zcmb_max = 0.05
|
||||||
|
@ -313,8 +308,9 @@ if __name__ == "__main__":
|
||||||
sample_Vmag_vax = False
|
sample_Vmag_vax = False
|
||||||
sample_Vmono = False
|
sample_Vmono = False
|
||||||
sample_mag_dipole = False
|
sample_mag_dipole = False
|
||||||
|
wo_num_dist_marginalisation = False
|
||||||
absolute_calibration = None
|
absolute_calibration = None
|
||||||
calculate_harmonic = False if inference_method == "bayes" else True
|
calculate_harmonic = (False if inference_method == "bayes" else True) and (not wo_num_dist_marginalisation) # noqa
|
||||||
sample_h = True if absolute_calibration is not None else False
|
sample_h = True if absolute_calibration is not None else False
|
||||||
|
|
||||||
fname_kwargs = {"inference_method": inference_method,
|
fname_kwargs = {"inference_method": inference_method,
|
||||||
|
@ -341,6 +337,7 @@ if __name__ == "__main__":
|
||||||
"num_epochs": num_epochs,
|
"num_epochs": num_epochs,
|
||||||
"inference_method": inference_method,
|
"inference_method": inference_method,
|
||||||
"sample_mag_dipole": sample_mag_dipole,
|
"sample_mag_dipole": sample_mag_dipole,
|
||||||
|
"wo_dist_marg": wo_num_dist_marginalisation,
|
||||||
"absolute_calibration": absolute_calibration,
|
"absolute_calibration": absolute_calibration,
|
||||||
"sample_h": sample_h,
|
"sample_h": sample_h,
|
||||||
}
|
}
|
||||||
|
@ -358,7 +355,7 @@ if __name__ == "__main__":
|
||||||
"`IndranilVoid` does not have multiple realisations.")
|
"`IndranilVoid` does not have multiple realisations.")
|
||||||
|
|
||||||
profile = ARGS.simname.split("_")[-1]
|
profile = ARGS.simname.split("_")[-1]
|
||||||
h = select_void_h(profile)
|
h = csiborgtools.flow.select_void_h(profile)
|
||||||
rdist = np.arange(0, 165, 0.5)
|
rdist = np.arange(0, 165, 0.5)
|
||||||
void_kwargs = {"profile": profile, "h": h, "order": 1, "rdist": rdist}
|
void_kwargs = {"profile": profile, "h": h, "order": 1, "rdist": rdist}
|
||||||
else:
|
else:
|
||||||
|
@ -377,7 +374,7 @@ if __name__ == "__main__":
|
||||||
calibration_hyperparams = {"Vext_min": -3000, "Vext_max": 3000,
|
calibration_hyperparams = {"Vext_min": -3000, "Vext_max": 3000,
|
||||||
"Vmono_min": -1000, "Vmono_max": 1000,
|
"Vmono_min": -1000, "Vmono_max": 1000,
|
||||||
"beta_min": -10.0, "beta_max": 10.0,
|
"beta_min": -10.0, "beta_max": 10.0,
|
||||||
"sigma_v_min": 1.0, "sigma_v_max": 5000 if "IndranilVoid_" in ARGS.simname else 750., # noqa
|
"sigma_v_min": 1.0, "sigma_v_max": 1000 if "IndranilVoid_" in ARGS.simname else 750., # noqa
|
||||||
"h_min": 0.01, "h_max": 5.0,
|
"h_min": 0.01, "h_max": 5.0,
|
||||||
"no_Vext": False if no_Vext is None else no_Vext, # noqa
|
"no_Vext": False if no_Vext is None else no_Vext, # noqa
|
||||||
"sample_Vmag_vax": sample_Vmag_vax,
|
"sample_Vmag_vax": sample_Vmag_vax,
|
||||||
|
@ -420,7 +417,8 @@ if __name__ == "__main__":
|
||||||
print(f"{'Current simulation:':<20} {i + 1} ({ksim}) out of {len(ksim_iterator)}.") # noqa
|
print(f"{'Current simulation:':<20} {i + 1} ({ksim}) out of {len(ksim_iterator)}.") # noqa
|
||||||
|
|
||||||
fname_kwargs["nsim"] = ksim
|
fname_kwargs["nsim"] = ksim
|
||||||
models = get_models(ksim, get_model_kwargs, mag_selection, void_kwargs)
|
models = get_models(ksim, get_model_kwargs, mag_selection, void_kwargs,
|
||||||
|
wo_num_dist_marginalisation)
|
||||||
model_kwargs = {
|
model_kwargs = {
|
||||||
"models": models,
|
"models": models,
|
||||||
"field_calibration_hyperparams": calibration_hyperparams,
|
"field_calibration_hyperparams": calibration_hyperparams,
|
||||||
|
|
1
setup.py
1
setup.py
|
@ -11,6 +11,7 @@ INSTALL_REQ += [
|
||||||
"mpi4py",
|
"mpi4py",
|
||||||
"numba",
|
"numba",
|
||||||
"numpyro",
|
"numpyro",
|
||||||
|
"interpax"
|
||||||
"quadax",
|
"quadax",
|
||||||
"scikit-learn",
|
"scikit-learn",
|
||||||
"tqdm",
|
"tqdm",
|
||||||
|
|
Loading…
Reference in a new issue