diff --git a/INSTALL.rst b/INSTALL.rst new file mode 100644 index 000000000..ca598b5ba --- /dev/null +++ b/INSTALL.rst @@ -0,0 +1,94 @@ +Installation +++++++++++++ + +Dependencies +------------ +If installed via pip, ARES' dependencies will be built automatically. + +But, in case you're curious, the core dependencies are: + +- [numpy](http://www.numpy.org/) +- [scipy](http://www.scipy.org/) +- [matplotlib](http://matplotlib.org/) +- [h5py](http://www.h5py.org/) + +and the optional dependencies are: + +- [camb](https://camb.readthedocs.io/en/latest/) +- [hmf](https://github.com/steven-murray/hmf) +- [astropy](https://www.astropy.org/) +- [dust_extinction](https://dust-extinction.readthedocs.io/en/stable/index.html) +- [dust_attenuation](https://dust-extinction.readthedocs.io/en/stable/index.html) +- [mpi4py](http://mpi4py.scipy.org) +- [pymp](https://github.com/classner/pymp) +- [progressbar2](http://progressbar-2.readthedocs.io/en/latest/) +- [setuptools](https://pypi.python.org/pypi/setuptools) +- [mpmath](http://mpmath.googlecode.com/svn-history/r1229/trunk/doc/build/setup.html) +- [shapely](https://pypi.python.org/pypi/Shapely) +- [descartes](https://pypi.python.org/pypi/descartes) + +If you'd like to build the documentation locally, you'll need: + +- [numpydoc](https://numpydoc.readthedocs.io/en/latest/) +- [nbsphinx](https://nbsphinx.readthedocs.io/en/0.8.8/) + +and if you'd like to run the test suite locally, you'll want: + +- [pytest](https://docs.pytest.org/en/7.1.x/) +- [pytest-cov](https://pytest-cov.readthedocs.io/en/latest/) + +which are all pip-installable. + +Note: ARES has been tested only with Python 2.7.x and Python 3.7.x. + +External datasets: stellar population synthesis (SPS) models +------------------------------------------------------------ +As discussed in the `README `_, ARES relies on many external datasets. The `ares init` command builds a minimal install, including some cosmological initial conditions, a single metallicity, :math:`Z=0.004`, constant star formation rate, single-star stellar population synthesis model from BPASS version 1.0, and a high redshift lookup table for the Tinker et al. 2010 halo mass function generated with `hmf `. + +There are many more external datasets that can be downloaded easily using the ARES CLI. For example, to fetch the complete set of BPASS v1 models (all metallicities, constant star formation and simple stellar populations, single star and binaries), you can do + +``` +ares download bpass_v1 +``` + +There are now newer versions of BPASS, which must be downloaded by hand. To download BPASS v2 models, navigate to `this page `_ and download the desired models in the ``$HOME/.ares/bpass_v2`` directory. If you initialized ARES with a different path (via the `--path` flag; see `README `` to ``ares init``, and setup a symbolic link that points from ``$HOME/.ares`` to this new location. -``` -ares download bc03 -``` +Note that ``ares init`` sets up a minimal ARES installation with only the most oft-used external datasets. For more information about what is needed for broader applications, see [this page](INSTALL.rst). -The examples within the documentation should say whether they require any non-standard lookup tables that, e.g., cannot be downloaded automatically using `ares download`. Please keep an eye out for that -- if you don't see any special instructions, and you're getting `IOError` or `OSError` or the like, do reach out. +## Quick Examples -Last note on this front. If you are running ARES on a machine with a very small quota in the `$HOME` directory, our trick of hiding lookup tables in `$HOME/.ares` will cause problems. A quick solution to this is to move the contents of `$HOME/.ares` somewhere else with plenty of disk space, and then make the file `$HOME/.ares` a symbolic link that points to this new folder. Probably we should add a flag to the CLI that can re-direct downloads to a user-supplied location to automate this hack in the future. +To generate a math:`z=6` luminosity function, you can do -## Pre-processing +```python +import ares +import numpy as np +import matplotlib.pyplot as plt -Not only do some ARES calculations rely on external datasets, they often benefit from using slightly-modified versions of those datasets. For example, the spectral resolution of the BPASS models is 1 Angstrom, which is much better than we need for most ARES modeling. So, many examples use "degraded" BPASS models, which just smooth the standard BPASS SEDs with a tophat of some width, generally 10 Angstroms. To do this SED degradation, we also use the ARES CLI: +pars = ares.util.ParameterBundle('mirocha2020:legacy') +pop = ares.populations.GalaxyPopulation(**pars) -```python -import os -from ares.util import cli as ares_cli +bins, phi = pop.get_uvlf(z=6, bins=np.arange(-25, -10, 0.1)) -ares_cli.generate_lowres_sps(f"{os.environ.get('HOME')}/.ares/bpass_v2/BPASSv2_imf135_300/OUTPUT_CONT", degrade_to=10) -ares_cli.generate_lowres_sps(f"{os.environ.get('HOME')}/.ares/bpass_v2/BPASSv2_imf135_300/OUTPUT_POP", degrade_to=10) +plt.semilogy(bins, phi) ``` -Once again, this kind of information should be included in our examples, so please check there for instructions if you get errors indicative of missing files. +Note: if the plot doesn't appear automatically, set ``interactive: True`` in your matplotlibrc file or type: -## Quick Examples +```python +plt.show() +``` To generate a model for the global 21-cm signal, simply type: ```python -import ares - -pars = ares.util.ParameterBundle('global_signal:basic') # Parameters -sim = ares.simulations.Simulation(**pars) # Initialize a simulation object +pars = ares.util.ParameterBundle('global_signal:basic') +sim = ares.simulations.Simulation(**pars) gs = sim.get_21cm_gs() ``` You can examine the contents of ``gs.history``, a dictionary which contains -the redshift evolution of all IGM physical quantities, or use some built-in -analysis routines: +the redshift evolution of all properties of the intergalactic medium, or use some built-in analysis routines: ```python gs.Plot21cmGlobalSignal() ``` -If the plot doesn't appear automatically, set ``interactive: True`` in your matplotlibrc file or type: - -```python -import matplotlib.pyplot as plt -plt.show() -``` - -To generate a quick luminosity function, you could do - -```python -pars = ares.util.ParameterBundle('mirocha2017:base').pars_by_pop(0, 1) -pop = ares.populations.GalaxyPopulation(**pars) - -bins, phi = pop.get_uvlf(z=6, bins=np.arange(-25, -10, 0.1)) - -plt.semilogy(bins, phi) -``` - If you're a pre-version-1.0 ARES user, most of this will look familiar, except these days we're running all models (21-cm, near-infrared background, etc.) through the `ares.simulations.Simulation` interface rather than specific classes. There's also a lot more consistency in call sequences, e.g., we adopt the convention of naming commonly-used functions and attributes as `get_` and `tab_`. A much longer list of v1 convention changes can be found in [Pull Request 61](https://github.com/mirochaj/ares/pull/61). - -## Contributors - -Primary author: [Jordan Mirocha](https://sites.google.com/site/jordanmirocha/home) - -Additional contributions / corrections / suggestions from: - -.. hlist:: - :columns: 3 - - * Geraint Harker - * Jason Sun - * Keith Tauscher - * Jacob Jost - * Greg Salvesen - * Adrian Liu - * Saurabh Singh - * Rick Mebane - * Krishma Singal - * Donald Trinh - * Omar Ruiz Macias - * Arnab Chakraborty - * Madhurima Choudhury - * Saul Kohn - * Aurel Schneider - * Kristy Fu - * Garett Lopez - * Ranita Jana - * Daniel Meinert - * Henri Lamarre - * Matteo Leo - * Emma Klemets - * Felix Bilodeau-Chagnon - * Venno Vipp - * Oscar Hernandez - * Joshua Hibbard - * Trey Driskell - * Judah Luberto - * Paul La Plante diff --git a/THANKS.rst b/THANKS.rst new file mode 100644 index 000000000..733615fc9 --- /dev/null +++ b/THANKS.rst @@ -0,0 +1,38 @@ +:orphan: + +Acknowledgements +---------------- +ARES has benefited from many helpful contributions, corrections, and suggestions over the years from: + +.. hlist:: + :columns: 3 + + * Geraint Harker + * Jason Sun + * Keith Tauscher + * Jacob Jost + * Greg Salvesen + * Adrian Liu + * Saurabh Singh + * Rick Mebane + * Krishma Singal + * Donald Trinh + * Omar Ruiz Macias + * Arnab Chakraborty + * Madhurima Choudhury + * Saul Kohn + * Aurel Schneider + * Kristy Fu + * Garett Lopez + * Ranita Jana + * Daniel Meinert + * Henri Lamarre + * Matteo Leo + * Emma Klemets + * Felix Bilodeau-Chagnon + * Venno Vipp + * Oscar Hernandez + * Joshua Hibbard + * Trey Driskell + * Judah Luberto + * Paul La Plante diff --git a/ares/analysis/MultiPhaseMedium.py b/ares/analysis/MultiPhaseMedium.py index 77cf6294f..fc943e700 100644 --- a/ares/analysis/MultiPhaseMedium.py +++ b/ares/analysis/MultiPhaseMedium.py @@ -15,7 +15,6 @@ import matplotlib.pyplot as pl from ..util.Stats import get_nu from ..util.Pickling import read_pickle_file -from scipy.misc import derivative from ..physics.Constants import * from scipy.integrate import cumulative_trapezoid from scipy.interpolate import interp1d diff --git a/ares/analysis/TurningPoints.py b/ares/analysis/TurningPoints.py index 55802d94b..a1ab31b0f 100644 --- a/ares/analysis/TurningPoints.py +++ b/ares/analysis/TurningPoints.py @@ -11,8 +11,8 @@ """ import numpy as np +import numdifftools as nd from ..util import ParameterFile -from scipy.misc import derivative from scipy.optimize import minimize from ..physics.Constants import nu_0_mhz from ..util.Math import central_difference @@ -204,10 +204,10 @@ def is_stopping_point(self, z, dTb): else: # Compute curvature at turning point (mK**2 / MHz**2) nuTP = nu_0_mhz / (1. + zTP) - d2 = float(derivative(lambda zz: splev(zz, Bspl_fit1), - x0=float(zTP), n=2, dx=1e-4, order=5) * nu_0_mhz**2 / nuTP**4) + d2 = float(nd.Derivative(lambda zz: splev(zz, Bspl_fit1), + n=2, step=1e-4, order=5)(float(zTP))) - self.turning_points[TP] = (zTP, TTP, d2) + self.turning_points[TP] = (zTP, TTP, d2 * nu_0_mhz**2 / nuTP**4) break diff --git a/ares/core/ChemicalNetwork.py b/ares/core/ChemicalNetwork.py index a21e4bd98..e7f4ee84f 100644 --- a/ares/core/ChemicalNetwork.py +++ b/ares/core/ChemicalNetwork.py @@ -13,7 +13,7 @@ import copy, sys import numpy as np -from scipy.misc import derivative +import numdifftools as nd from ..util.Warnings import solver_error from ..physics.RateCoefficients import RateCoefficients from ..physics.Constants import k_B, sigma_T, m_e, c, s_per_myr, erg_per_ev, h @@ -638,8 +638,8 @@ def Jacobian(self, t, q, args): # pragma: no cover # Add in any parametric modifications? if self.exotic_heating: - J[-1,-1] += derivative(self.grid._exotic_func(z=z) * to_temp, z, - dx=0.05) + # need step=0.05? + J[-1,-1] += nd.Derivative(lambda z: self.grid._exotic_func(z=z) * to_temp)(z) return J diff --git a/ares/core/SpectralSynthesis.py b/ares/core/SpectralSynthesis.py index 30aaffedb..1ff732b01 100644 --- a/ares/core/SpectralSynthesis.py +++ b/ares/core/SpectralSynthesis.py @@ -16,9 +16,9 @@ from ..util import ProgressBar from ..util import ParameterFile from scipy.optimize import curve_fit -from scipy.interpolate import interp1d +from scipy.integrate import trapezoid from ..physics.Cosmology import Cosmology -from scipy.interpolate import RectBivariateSpline +from scipy.interpolate import interp1d, RectBivariateSpline from ..physics.Constants import s_per_myr, c, h_p, erg_per_ev, flux_AB, \ lam_LL, lam_LyA @@ -1193,7 +1193,6 @@ def get_lum(self, x=1600., sfh=None, tarr=None, zarr=None, window=1, else: _ages, _SFR = self._oversample_sfh(ages, sfh[0:i+1], i) - # `_ages` and `ages` are in Myr, _dt here is in years _dt = np.abs(np.diff(_ages) * 1e6) # `_ages` is in order of old to young. @@ -1270,14 +1269,14 @@ def get_lum(self, x=1600., sfh=None, tarr=None, zarr=None, window=1, # the SFH is a smooth function and not a series of constant # SFRs. Doesn't really matter in practice, though. if not do_all_time: - Lhist = np.trapz(Lall, dx=_dt, axis=1) + Lhist = trapezoid(Lall, dx=_dt, axis=1) else: - Lhist[:,i] = np.trapz(Lall, dx=_dt, axis=1) + Lhist[:,i] = trapezoid(Lall, dx=_dt, axis=1) else: if not do_all_time: - Lhist = np.trapz(Lall, dx=_dt) + Lhist = trapezoid(Lall, dx=_dt) else: - Lhist[i] = np.trapz(Lall, dx=_dt) + Lhist[i] = trapezoid(Lall, dx=_dt) ## # In this case, we only need one iteration of this loop. @@ -1322,6 +1321,8 @@ def get_lum(self, x=1600., sfh=None, tarr=None, zarr=None, window=1, tau = kappa * Sd + print('hi', x, idnum, tau[izobs]) + clear = rand > fcov block = ~clear diff --git a/ares/data/bc03_2013.py b/ares/data/bc03_2013.py index 779f80b4c..517e75982 100644 --- a/ares/data/bc03_2013.py +++ b/ares/data/bc03_2013.py @@ -64,10 +64,7 @@ def _kwargs_to_fn(**kwargs): path += f"/{kwargs['source_imf']}/" # All files share this prefix - if kwargs['source_stellar_lib'] == 'stelib': - fn = 'bc2003_hr_stelib' - else: - fn = 'bc2003_lr_BaSeL' + fn = 'bc2003_hr_stelib' Z = kwargs['source_Z'] iZ = list(mvals).index(Z) diff --git a/ares/data/mirocha2025.py b/ares/data/mirocha2023.py similarity index 67% rename from ares/data/mirocha2025.py rename to ares/data/mirocha2023.py index 0c52b605b..a4dcdfca4 100644 --- a/ares/data/mirocha2025.py +++ b/ares/data/mirocha2023.py @@ -15,27 +15,22 @@ # NIRB 'tau_approx': 0,#'neutral', - 'tau_clumpy': 1, # 1 = all < 912A photons gone, 2 = all < 1216A gone, - # can also set to 'madau1995' for more detailed model. + 'tau_clumpy': 2, 'cosmology_id': 'best', 'cosmology_name': 'planck_TTTEEE_lowl_lowE', 'cosmological_Mmin': None, 'first_light_redshift': 15, - 'final_redshift': 6e-3, + 'final_redshift': 5e-3, 'tau_redshift_bins': 100, 'halo_dlnk': 0.05, 'halo_lnk_min': -9., 'halo_lnk_max': 11., - - #'interpolate_cosmology_in_z': True, } -basic_settings = setup.copy() - centrals_sf = \ { 'pop_use_lum_cache': True, @@ -66,7 +61,7 @@ 'pop_sfh': 'constant+ssp', 'pop_ssp': (False, True), - 'pop_age': (100., 4e3), + 'pop_age': (100., 2.5e3), 'pop_Z': (0.02, 0.02), # placeholder, really 'pop_binaries': False, @@ -201,7 +196,7 @@ 'pq_func_par1[1]': 3e12, 'pq_func_par2[1]': 1.6, 'pq_func_par3[1]': 0.2, - 'pq_func_par4[1]': 1e10, # Mh anchor + 'pq_func_par4[1]': 1e10, # Mh anchor 'pq_func_par5[1]': 0.6, # scales (1-a) term 'pq_func_par6[1]': 0., # scales (1-a) term 'pq_func_par7[1]': 0, # scales (1-a) term @@ -219,10 +214,10 @@ 'pq_func_par19[1]': 0.0, 'pq_func_par20[1]': 0.0, # Extension! - 'pq_func_par21[1]': 0.0, # Turn-over mass - 'pq_func_par22[1]': 0.0, # upturn - 'pq_func_par23[1]': 0.0, # upturn - 'pq_func_par24[1]': 0.0, # evolution in turn-over mass + 'pq_func_par21[1]': 0.0, + 'pq_func_par22[1]': 0.0, + 'pq_func_par23[1]': 0.0, + 'pq_func_par24[1]': 0.0, 'pq_func_par25[1]': 0.0, 'pq_func_par26[1]': 0.0, } @@ -235,14 +230,13 @@ centrals_q['pop_ssfr'] = None centrals_q['pop_sfr'] = None centrals_q['pop_ssp'] = True -centrals_q['pop_age'] = 5e3 +centrals_q['pop_age'] = 1e4 centrals_q['pop_Z'] = 0.02 centrals_q['pop_fstar'] = 'link:fstar:0' centrals_q['pop_focc'] = 'link:focc:0' centrals_q['pop_nebular'] = 0 centrals_q['pop_focc_inv'] = True centrals_q['pop_scatter_sfh'] = 'pop_scatter_sfh{0}' - centrals_q['pop_sys_method'] = 'separate' centrals_q['pop_sys_mstell_now'] = 'pop_sys_mstell_now{0}' centrals_q['pop_sys_mstell_a'] = 'pop_sys_mstell_a{0}' @@ -271,26 +265,14 @@ ihl_scaled['pop_include_2h'] = True ihl_scaled['pop_include_shot'] = False ihl_scaled['pop_Mmin'] = 1e10 -#ihl_scaled['pop_Mmax'] = 1e15 +ihl_scaled['pop_Mmax'] = 1e14 ihl_scaled['pop_Tmin'] = None -# These numbers are Purcell-like -ihl_tanh = ihl_scaled.copy() -ihl_tanh['pq_func[50]'] = 'logtanh_abs' -ihl_tanh['pq_func_par0[50]'] = 0.7 -ihl_tanh['pq_func_par1[50]'] = 0.0 -ihl_tanh['pq_func_par2[50]'] = 13.6 -ihl_tanh['pq_func_par3[50]'] = -1. -ihl_tanh['pq_val_ceil[50]'] = 0.99 - -ihl_tanh_zevol = ihl_tanh.copy() - -#ihl_b19 = ihl_scaled.copy() -#ihl_b19['pq_func_par0[50]'] = 0.01 -#ihl_b19['pq_func_par1[50]'] = 1e12 -#ihl_b19['pq_func_par2[50]'] = 0.7 -#ihl_b19['pq_val_ceil[50]'] = 0.99 -#ihl_b19['pq_val_floor[50]{4}'] = 3e-3 +ihl_b19 = ihl_scaled.copy() +ihl_b19['pq_func_par0[50]'] = 0.01 +ihl_b19['pq_func_par1[50]'] = 1e12 +ihl_b19['pq_func_par2[50]'] = 0.7 +ihl_b19['pq_val_ceil[50]'] = 0.99 ihl_p24 = ihl_scaled.copy() ihl_p24['pq_func_par0[50]'] = 0.13 @@ -312,14 +294,6 @@ ihl_p07['pq_func_par3[50]'] = -1. ihl_p07['pq_val_ceil[50]'] = 0.99 -ihl_b19 = ihl_scaled.copy() -ihl_b19['pq_func[50]'] = 'logtanh_abs' -ihl_b19['pq_func_par0[50]'] = 0.7 -ihl_b19['pq_func_par1[50]'] = 3e-3 -ihl_b19['pq_func_par2[50]'] = 14.1 -ihl_b19['pq_func_par3[50]'] = -0.8 -ihl_b19['pq_val_ceil[50]'] = 0.99 - satellites_sf = centrals_sf.copy() satellites_sf['pop_focc'] = 'link:focc:0' satellites_sf['pop_focc_inv'] = False @@ -351,15 +325,14 @@ satellites_q['pop_include_1h'] = True satellites_q['pop_include_2h'] = True satellites_q['pop_include_shot'] = True -satellites_q['pop_fstar'] = 'link:fstar:1' +satellites_q['pop_fstar'] = 'link:fstar:0' satellites_q['pop_ssfr'] = None -#satellites_q['pop_scatter_sfh'] = 'pop_scatter_sfh{0}' -#satellites_q['pop_scatter_smhm'] = 'pop_scatter_smhm{1}' +satellites_q['pop_scatter_sfh'] = 'pop_scatter_sfh{0}' satellites_q['pop_sfh'] = 'ssp' satellites_q['pop_aging'] = True satellites_q['pop_ssp'] = True -satellites_q['pop_age'] = 5e3 +satellites_q['pop_age'] = 1e4 satellites_q['pop_Z'] = 0.02 # @@ -416,20 +389,20 @@ dust_x = {} dust_x['pop_dust_template_extension{0}'] = 'pq[40]' -dust_x['pq_func[40]{0}'] = 'pl_evolB13' -dust_x['pq_func_var[40]{0}'] = 'wave' -dust_x['pq_func_var2[40]{0}'] = '1+z' -dust_x['pq_func_par0[40]{0}'] = 1 -dust_x['pq_func_par1[40]{0}'] = 5500 -dust_x['pq_func_par2[40]{0}'] = 0.0 -dust_x['pq_func_par3[40]{0}'] = 0 # norm -dust_x['pq_func_par4[40]{0}'] = 0 # slope -dust_x['pq_func_par5[40]{0}'] = 0 # norm -dust_x['pq_func_par6[40]{0}'] = 0 # slope -dust_x['pq_func_par7[40]{0}'] = 0 # norm -dust_x['pq_func_par8[40]{0}'] = 0 # slope -dust_x['pq_func_par9[40]{0}'] = 0 # slope -dust_x['pq_func_par10[40]{0}'] = 0 # slope +dust_x['pq_func{0}[40]'] = 'pl_evolB13' +dust_x['pq_func_var{0}[40]'] = 'wave' +dust_x['pq_func_var2{0}[40]'] = '1+z' +dust_x['pq_func_par0{0}[40]'] = 1 +dust_x['pq_func_par1{0}[40]'] = 5500 +dust_x['pq_func_par2{0}[40]'] = 0.0 +dust_x['pq_func_par3{0}[40]'] = 0 # norm +dust_x['pq_func_par4{0}[40]'] = 0 # slope +dust_x['pq_func_par5{0}[40]'] = 0 # norm +dust_x['pq_func_par6{0}[40]'] = 0 # slope +dust_x['pq_func_par7{0}[40]'] = 0 # norm +dust_x['pq_func_par8{0}[40]'] = 0 # slope +dust_x['pq_func_par9{0}[40]'] = 0 # slope +dust_x['pq_func_par10{0}[40]'] = 0 # slope for par in dust.keys(): setup[par + '{0}'] = dust[par] @@ -462,60 +435,6 @@ 'pq_func_par20[4]{0}': 0.0, # high } -dust_dplx = \ -{ - 'pq_func[4]{0}': 'dplx_evolB13', - 'pq_func_var[4]{0}': 'Mh', - 'pq_func_var2[4]{0}': '1+z', - 'pq_func_par0[4]{0}': 0.0, - 'pq_func_par1[4]{0}': 1e12, - 'pq_func_par2[4]{0}': 0.2, - 'pq_func_par3[4]{0}': 0., - 'pq_func_par4[4]{0}': 1e10, # normalization pinned to this Mh - 'pq_func_par5[4]{0}': 0, # norm - 'pq_func_par6[4]{0}': 0, # peak - 'pq_func_par7[4]{0}': 0, # low - 'pq_func_par8[4]{0}': 0, # high - 'pq_func_par9[4]{0}': 0.0, # norm - 'pq_func_par10[4]{0}': 0.0, # peak - 'pq_func_par11[4]{0}': 0.0, # low - 'pq_func_par12[4]{0}': 0.0, # high - 'pq_func_par13[4]{0}': 0.0, # norm - 'pq_func_par14[4]{0}': 0.0, # peak - 'pq_func_par15[4]{0}': 0.0, # low - 'pq_func_par16[4]{0}': 0.0, # high - 'pq_func_par17[4]{0}': 0.0, # norm - 'pq_func_par18[4]{0}': 0.0, # peak - 'pq_func_par19[4]{0}': 0.0, # low - 'pq_func_par20[4]{0}': 0.0, # high - # Extension! - 'pq_func_par21[4]{0}': 5.0, # evolution done in log10(Mturn), hence default > 0 - 'pq_func_par22[4]{0}': 0.0, - 'pq_func_par23[4]{0}': 0.0, - 'pq_func_par24[4]{0}': 0.0, - 'pq_func_par25[4]{0}': 0.0, - 'pq_func_par26[4]{0}': 0.0, -} - -dust_linlog = \ -{ - 'pq_func[4]{0}': 'linlog_evolB13', - 'pq_func_var[4]{0}': 'Ms', - 'pq_func_var2[4]{0}': '1+z', - 'pq_func_par0[4]{0}': 0.5, - 'pq_func_par1[4]{0}': 10, # log10(Mstell/Msun) we pin to - 'pq_func_par2[4]{0}': 0.1, # slope - # Start evol params - 'pq_func_par3[4]{0}': 0., # norm (1 - a) - 'pq_func_par4[4]{0}': 0, # slope (1 - a) - 'pq_func_par5[4]{0}': 0, # norm log(1+z) - 'pq_func_par6[4]{0}': 0, # slope log(1+z) - 'pq_func_par7[4]{0}': 0, # norm z - 'pq_func_par8[4]{0}': 0, # slope z - 'pq_func_par9[4]{0}': 0.0, # norm a - 'pq_func_par10[4]{0}': 0.0, # slope a -} - base_centrals = setup.copy() # This results in a Z14-like amount of IHL @@ -566,7 +485,7 @@ ihl['pop_zdead{4}'] = 0 # SED info -ihl['pop_sed{4}'] = 'bc03_2013' +ihl['pop_sed{4}'] = 'bc03' ihl['pop_rad_yield{4}'] = 'from_sed' ihl['pop_sed_degrade{4}'] = None#10 @@ -591,6 +510,7 @@ ihl['pop_ssp{4}'] = True ihl['pop_age{4}'] = 1e4 ihl['pop_Z{4}'] = 0.02 +ihl['pop_scatter_sfh{4}'] = 'pop_scatter_sfh{0}' mzr = \ { @@ -638,7 +558,6 @@ smhm_Q['pq_func_par20[10]{1}'] = 0.0 smhm_Q['pq_val_ceil[10]{1}'] = 1 -setup_centrals = setup.copy() setup.update(subhalos) ## @@ -662,6 +581,7 @@ subhalos_sfr_ext['pq_func_var[6]{2}'] = 'Mh' subhalos_sfr_ext['pq_func_var2[6]{2}'] = '1+z' + for i in range(0, 27): subhalos_sfr_ext['pq_func_par%i[6]{2}' % i] = setup['pq_func_par%i[1]{0}' % i] @@ -697,28 +617,9 @@ (3970, 0.159 * 0.44e41), # H-epsilon (3727, 0.71e41), # [O II] (1.87e4, 1.27e41 * 0.123), # [P-alpha] - (3.28e4, lsun * 10**6.6)] # 3.3 micron PAH (Lai+ 2020) + (3.3e4, lsun * 10**6.6)] # 3.3 micron PAH (Lai+ 2020) lines['pop_lum_per_sfr_at_wave{2}'] = lines['pop_lum_per_sfr_at_wave{0}'] -lines_wprof = {} -lines_wprof['pop_lum_per_sfr_at_wave{0}'] = \ - [ - (1216., 1.21e42), # Ly-a - (6563, 1.27e41), # H-alpha - (5007, 1.32e41), # [O III] - (4861, 0.44e41), # H-beta - (4340, 0.468 * 0.44e41), # H-gamma - (4102, 0.259 * 0.44e41), # H-delta - (3970, 0.159 * 0.44e41), # H-epsilon - (3727, 0.71e41), # [O II] - (1.87e4, 1.27e41 * 0.123), # [P-alpha] - (3.28e4, 0.505 * lsun * 10**6.6, 0.0301e4), # 3.3 micron PAH (Lai+ 2020) - (3.28e4, 0.495 * lsun * 10**6.6, 0.1028e4), - (3.40e4, 0.08592 * lsun * 10**6.6, 0.0301e4), - (3.48e4, 0.17205 * lsun * 10**6.6, 0.0555e4)] - -lines_wprof['pop_lum_per_sfr_at_wave{2}'] = lines_wprof['pop_lum_per_sfr_at_wave{0}'] - no_lines = \ { 'pop_lum_per_sfr_at_wave{0}': None, @@ -752,88 +653,59 @@ # Need to be careful with this _base = \ { -'pq_func_par0[0]{0}': 7.2815e-05, -'pq_func_par1[0]{0}': 1.4430e+12, -'pq_func_par2[0]{0}': 1.3226e+00, -'pq_func_par3[0]{0}': -2.5893e-01, -'pq_func_par0[10]{1}': 1.0534e-03, -'pq_func_par1[10]{1}': 3.2164e+11, -'pq_func_par2[10]{1}': 1.0233e+00, -'pq_func_par3[10]{1}': -4.9251e-01, -'pq_func_par5[0]{0}': -1.5774e+00, -'pq_func_par9[0]{0}': 1.0673e+00, -'pq_func_par6[0]{0}': -3.8390e-01, -'pq_func_par10[0]{0}': 2.6777e-01, -'pq_func_par7[0]{0}': -1.5361e+00, -'pq_func_par11[0]{0}': 5.0344e-01, -'pq_func_par8[0]{0}': -3.3829e+00, -'pq_func_par12[0]{0}': 1.7435e+00, -'pq_func_par5[10]{1}': -1.2436e-01, -'pq_func_par9[10]{1}': -1.0433e+00, -'pq_func_par6[10]{1}': 1.7571e+00, -'pq_func_par10[10]{1}': -4.1490e-01, -'pq_func_par7[10]{1}': 3.4618e+00, -'pq_func_par11[10]{1}': 3.3509e+00, -'pq_func_par8[10]{1}': -1.9147e+00, -'pq_func_par12[10]{1}': 1.8761e+00, -'pq_func_par0[2]{0}': 2.4117e-01, -'pq_func_par1[2]{0}': 9.7025e-01, -'pq_func_par2[2]{0}': 1.2994e+01, -'pq_func_par3[2]{0}': -3.9922e-01, -'pq_func_par4[2]{0}': -3.7360e+00, -'pq_func_par8[2]{0}': -4.7217e+00, -'pq_func_par5[2]{0}': 2.3421e+00, -'pq_func_par9[2]{0}': 1.3401e+00, -'pq_func_par6[2]{0}': 3.2989e+00, -'pq_func_par10[2]{0}': -4.8534e+00, -'pq_func_par7[2]{0}': -6.7647e-02, -'pq_func_par11[2]{0}': -4.5169e+00, -'pq_func_par0[1]{0}': 3.7837e-04, -'pq_func_par1[1]{0}': 4.1900e+11, -'pq_func_par2[1]{0}': 2.3168e+00, -'pq_func_par3[1]{0}': 1.9083e-02, -'pq_func_par5[1]{0}': -5.3792e-01, -'pq_func_par9[1]{0}': 1.2113e+00, -'pq_func_par6[1]{0}': 6.0217e-01, -'pq_func_par10[1]{0}': -1.1771e-01, -'pq_func_par7[1]{0}': -2.9937e-01, -'pq_func_par11[1]{0}': -2.4585e-01, -'pq_func_par8[1]{0}': -9.9456e-01, -'pq_func_par12[1]{0}': 7.8243e-01, -'pq_func_par0[4]{0}': 2.0465e-01, -'pq_func_par1[4]{0}': 5.9843e+11, -'pq_func_par2[4]{0}': 5.1163e-01, -'pq_func_par3[4]{0}': -6.2534e-01, -'pq_func_par5[4]{0}': 8.1619e-02, -'pq_func_par9[4]{0}': 2.3364e-02, -'pq_func_par6[4]{0}': -1.3702e+00, -'pq_func_par10[4]{0}': 4.9983e-01, -'pq_func_par7[4]{0}': 2.5034e+00, -'pq_func_par11[4]{0}': -1.1455e+00, -'pq_func_par8[4]{0}': 1.2596e+00, -'pq_func_par12[4]{0}': -2.3796e-01, -'pop_scatter_sfh{0}': 1.2728e-01, -'pop_sfr_below_ms{1}': 5.4408e+02, -'pop_sys_mstell_now{0}': -3.0761e-02, -'pop_sys_mstell_a{0}': -1.1592e-02, -'pop_sys_sfr_now{0}': 1.0303e-02, -'pop_sys_sfr_a{0}': 9.5621e-03, +'pq_func_par0[0]{0}': 6.1764e-05, +'pq_func_par1[0]{0}': 9.1754e+11, +'pq_func_par2[0]{0}': 1.4473e+00, +'pq_func_par3[0]{0}': -5.5587e-01, +'pq_func_par5[0]{0}': -1.0034e+00, +'pq_func_par6[0]{0}': 5.8955e-01, +'pq_func_par7[0]{0}': -6.7433e-01, +'pq_func_par8[0]{0}': 1.6365e-01, +'pq_func_par0[2]{0}': 2.4506e-01, +'pq_func_par1[2]{0}': 8.2420e-01, +'pq_func_par2[2]{0}': 1.2364e+01, +'pq_func_par3[2]{0}': -2.0167e-01, +'pq_func_par4[2]{0}': -1.0386e-01, +'pq_func_par8[2]{0}': 3.6803e-01, +'pq_func_par5[2]{0}': -6.5620e-01, +'pq_func_par9[2]{0}': 6.3437e-01, +'pq_func_par6[2]{0}': -2.3490e+00, +'pq_func_par10[2]{0}': 1.0774e+00, +'pq_func_par7[2]{0}': 5.3345e-01, +'pq_func_par11[2]{0}': -2.8394e-01, +'pq_func_par0[1]{0}': 4.2053e-04, +'pq_func_par1[1]{0}': 2.7720e+11, +'pq_func_par2[1]{0}': 2.3336e+00, +'pq_func_par3[1]{0}': 4.9890e-01, +'pq_func_par5[1]{0}': -2.8294e+00, +'pq_func_par9[1]{0}': 1.9135e+00, +'pq_func_par6[1]{0}': 2.5113e+00, +'pq_func_par10[1]{0}': -1.0102e+00, +'pq_func_par7[1]{0}': -5.7024e-01, +'pq_func_par11[1]{0}': -8.2598e-02, +'pq_func_par8[1]{0}': -1.2234e+00, +'pq_func_par12[1]{0}': 6.7375e-01, +'pq_func_par0[4]{0}': 1.1055e+00, +'pq_func_par2[4]{0}': 8.7996e-03, +'pq_func_par5[4]{0}': -2.3831e-01, +'pq_func_par6[4]{0}': 8.9493e-02, +'pop_scatter_sfh{0}': 1.4846e-01, +'pop_sfr_below_ms{1}': 1.4333e+03, +'pop_sys_mstell_now{0}': -4.2003e-02, +'pop_sys_mstell_a{0}': 9.3474e-02, +'pop_sys_sfr_now{0}': 2.1676e-01, +'pop_sys_sfr_a{0}': 1.3600e-02, } -sed_modeling = \ -{ - 'pop_lum_tab{0}': f"{HOME}/.ares/ares_ebl_data/ares_2025_07_01_smhm_diff_b13_2222_focc_erf_b13_2222_sfr_b13_2222_sc_dustMh_dpl_b13_2222_c00_sats_1_fit_smf_1_ssfr_1_uvlf_b15_o18_p25_w18_1.75_3.75_4_beta_1_ms_1b_s07_1_cts_0_clst_0_sys_1_sedtab_pop_0_mzr_0_obs_T0_12_1.0_alpha_0.00.hdf5", - 'pop_lum_tab{1}': f"{HOME}/.ares/ares_ebl_data/ares_2025_07_01_smhm_diff_b13_2222_focc_erf_b13_2222_sfr_b13_2222_sc_dustMh_dpl_b13_2222_c00_sats_1_fit_smf_1_ssfr_1_uvlf_b15_o18_p25_w18_1.75_3.75_4_beta_1_ms_1b_s07_1_cts_0_clst_0_sys_1_sedtab_pop_1_bb_544_obs_T0_12_1.0_alpha_0.00.hdf5", - 'pop_lum_tab{2}': f"{HOME}/.ares/ares_ebl_data/ares_2025_07_01_smhm_diff_b13_2222_focc_erf_b13_2222_sfr_b13_2222_sc_dustMh_dpl_b13_2222_c00_sats_1_fit_smf_1_ssfr_1_uvlf_b15_o18_p25_w18_1.75_3.75_4_beta_1_ms_1b_s07_1_cts_0_clst_0_sys_1_sedtab_pop_0_mzr_0_obs_T0_12_1.0_alpha_0.00.hdf5", - 'pop_lum_tab{3}': f"{HOME}/.ares/ares_ebl_data/ares_2025_07_01_smhm_diff_b13_2222_focc_erf_b13_2222_sfr_b13_2222_sc_dustMh_dpl_b13_2222_c00_sats_1_fit_smf_1_ssfr_1_uvlf_b15_o18_p25_w18_1.75_3.75_4_beta_1_ms_1b_s07_1_cts_0_clst_0_sys_1_sedtab_pop_1_bb_544_obs_T0_12_1.0_alpha_0.00.hdf5", -} +#setup = base.copy() +#base.update(_base) -no_sed_modeling = \ +sed_modeling = \ { - 'pop_lum_tab{0}': None, - 'pop_lum_tab{1}': None, - 'pop_lum_tab{2}': None, - 'pop_lum_tab{3}': None, + 'pop_lum_tab{0}': f"{HOME}/.ares/ares_ebl_data/ares_base_seds_acen_beta_0.hdf5", + 'pop_lum_tab{1}': f"{HOME}/.ares/ares_ebl_data/ares_base_seds_qcen_beta_0.hdf5", + 'pop_lum_tab{2}': f"{HOME}/.ares/ares_ebl_data/ares_base_seds_acen_beta_0.hdf5", + 'pop_lum_tab{3}': f"{HOME}/.ares/ares_ebl_data/ares_base_seds_qcen_beta_0.hdf5", } sys_b13 = \ @@ -843,28 +715,3 @@ 'pop_sys_method{2}': "b13", 'pop_sys_method{3}': "b13", } - -scatter_flex = \ -{ - 'pop_scatter_sfh{0}': 0, - 'pop_scatter_sfh{1}': 0, - 'pop_scatter_sfh{2}': 0, - 'pop_scatter_sfh{3}': 0, - 'pop_scatter_sfr{0}': 0., - 'pop_scatter_smhm{0}': 0., - 'pop_scatter_smhm{1}': 0., -} - -# 'base' model has: -# (i) different SMHM for star-forming and quiescent sources -# (ii) DPL SFR-Mh relation -# (iii) DPL Dust-Mh relation -# (iv) systematics not identical to B13 -# (v) satellites == centrals at given (sub)halo mass - -base = setup.copy() -base.update(smhm_Q) -base.update(dust_dplx) -base.update(_base) -base.update(sed_modeling) -#base.update(lines_wprof) \ No newline at end of file diff --git a/ares/data/page2025.py b/ares/data/page2025.py deleted file mode 100644 index 9311d031c..000000000 --- a/ares/data/page2025.py +++ /dev/null @@ -1,30 +0,0 @@ -""" -page2025.py - -Page et al. 2025, MNRAS, 536, 518P - -https://arxiv.org/abs/2501.06075 -https://ui.adsabs.harvard.edu/abs/2025MNRAS.536..518P/abstract -""" - -import numpy as np - -redshifts = [0.5] - -magbins = np.arange(-20.72, -17.42, 0.3) - -# error bars are (+/-) - -data = \ -{ - 0.5: {'M': magbins, - 'phi': np.array([-4.57, -4.27, -3.97, -3.66, -3.15, -2.97, -2.76, -2.61, - -2.42, -2.35, -2.13]), - 'err': np.array([(0.52, 0.76), (0.37, 0.45), (0.25, 0.28), (0.17, 0.18), (0.09, 0.10), - (0.08, 0.08), (0.07, 0.07), (0.05, 0.06), (0.06, 0.06), (0.09, 0.09), - (0.14, 0.15)]), - }, -} - -units = {'lf': 'log10'} - diff --git a/ares/data/weibel2024.py b/ares/data/weibel2024.py deleted file mode 100644 index 794f8de78..000000000 --- a/ares/data/weibel2024.py +++ /dev/null @@ -1,88 +0,0 @@ -""" -Weibel et al., 2024, MNRAS, 533, 1808 -""" - -import numpy as np - -info = \ -{ - 'reference':'Weibel et al., 2024, MNRAS, 533, 1808', - 'data': 'Tables 2 and 3', - 'imf': ('Kroupa', (None, None)), - 'link': "https://ui.adsabs.harvard.edu/abs/2024MNRAS.533.1808W/abstract", -} - -redshifts = [4, 5, 6, 7, 8, 9] - -ULIM = -1e10 - -fits = {} - -# Table 1 -tmp_data = {} -tmp_data['smf_tot'] = \ -{ - 4: {'M': list(10**np.arange(7.75, 12.25, 0.5)), - 'phi': [-1.57, -1.97, -2.38, -2.74, -3.17, -3.68, -4.23, -4.78, -5.91], - 'err': [(0.10, 0.12), (0.06, 0.06), (0.04, 0.05), (0.06, 0.06), (0.07, 0.08), - (0.09, 0.11), (0.14, 0.19), (0.19, 0.31), (0.54, 1.13)], - }, - 5: {'M': list(10**np.arange(8.25, 12.25, 0.5)), - 'phi': [-2.00, -2.38, -2.89, -3.35, -4.04, -4.87, -5.80, -5.87], - 'err': [(0.09, 0.12), (0.06, 0.07), (0.08, 0.10), (0.10, 0.13), (0.14, 0.19), - (0.23, 0.43), (0.54, 2.55), (0.55, np.inf)], - }, - 6: {'M': list(10**np.arange(8.25, 12.25, 0.5)), - 'phi': [-2.24, -2.65, -3.26, -3.85, -4.44, -5.26, -5.38, -5.82], - 'err': [(0.12, 0.17), (0.09, 0.11), (0.11, 0.15), (0.15, 0.21), (0.20, 0.35), - (0.35, np.inf), (0.42, np.inf), (0.56, np.inf)], - }, - 7: {'M': list(10**np.arange(8.25, 12.25, 0.5)), - 'phi': [-2.40, -2.70, -3.35, -3.96, -4.35, -4.78, -5.38, -5.69], - 'err': [(0.15, 0.24), (0.14, 0.20), (0.14, 0.21), (0.19, 0.33), (0.25, 0.58), - (0.38, np.inf), (0.43, np.inf), (0.55, np.inf)], - }, - 8: {'M': list(10**np.arange(8.75, 12.25, 0.5)), - 'phi': [-3.00, -3.64, -4.09, -4.33, -4.78, -5.54, -5.66], - 'err': [(0.18, 0.28), (0.19, 0.33), (0.24, 0.55), (0.30, 1.39), (0.45, np.inf), - (0.57, np.inf), (0.56, np.inf)], - }, - 9: {'M': list(10**np.arange(8.75, 12.25, 0.5)), - 'phi': [-3.39, -3.81, -4.35, -4.79, -5.27, -5.61, -5.61], - 'err': [(0.25, 0.64), (0.24, 0.52), (0.31, 1.54), (0.40, np.inf), (0.54, np.inf), - (0.64, np.inf), (0.61, np.inf)], - }, - - -} - - -units = {'smf_tot': 'log10', 'smf': 'log10'} - -data = {} -data['smf_tot'] = {} -for group in ['smf_tot']: - - for key in tmp_data[group]: - - if key not in tmp_data[group]: - continue - - subdata = tmp_data[group] - - mask = [] - for element in subdata[key]['err']: - if element == ULIM: - mask.append(1) - else: - mask.append(0) - - mask = np.array(mask) - - data[group][key] = {} - data[group][key]['M'] = np.ma.array(subdata[key]['M'], mask=mask) - data[group][key]['phi'] = np.ma.array(subdata[key]['phi'], mask=mask) - data[group][key]['err'] = tmp_data[group][key]['err'] - -# Make `smf` and `smf_tot` interchangeable -data['smf'] = data['smf_tot'] diff --git a/ares/data/williams2018.py b/ares/data/williams2018.py index 0146879d9..5b820431e 100644 --- a/ares/data/williams2018.py +++ b/ares/data/williams2018.py @@ -86,15 +86,10 @@ def get_Reff(z, Ms, quiescent=False, cosm=None): if quiescent: B_H = 3.8e-4 * np.exp(np.log10(Ms)*0.71) - 0.11 - if type(Ms) in [int, float]: - if Ms >= 10**9.75: - Beta_H = 1.38e12 * np.exp(-2.87 * np.log10(Ms)) - 1.21 - else: - Beta_H = -0.19 + if Ms >= 10**9.75: + Beta_H = 1.38e12 * np.exp(-2.87 * np.log10(Ms)) - 1.21 else: - Beta_H = -0.19 * np.ones_like(Ms) - Beta_H[Ms >= 10**9.75] = 1.38e12 *\ - np.exp(-2.87 * np.log10(Ms[Ms >= 10**9.75])) - 1.21 + Beta_H = -0.19 else: B_H = 0.23 * np.log10(Ms) - 1.61 Beta_H = -0.08 * np.log10(Ms) + 0.25 diff --git a/ares/data/wyder2005.py b/ares/data/wyder2005.py deleted file mode 100644 index d6aa1fc7d..000000000 --- a/ares/data/wyder2005.py +++ /dev/null @@ -1,44 +0,0 @@ -""" - -wyder2005.py - -Wyder et al., 2005, ApJL, 619, L15 - -https://ui.adsabs.harvard.edu/abs/2005ApJ...619L..15W/abstract -https://arxiv.org/abs/astro-ph/0411364 - -Note: this was all plot-digitized from their Fig. 3. - -""" - -import numpy as np - -info = \ -{ - 'reference': 'Wyder et al., 2005, ApJL, 619, L15', - 'data': 'Table 3', -} - -redshifts = [(0, 0.1)] -units = {'lf': 'log10'} -wavelength = 1530, 2310 -bands = 'fuv', 'nuv' -ULIM = -1e10 - -data = \ - {'lf_fuv': {(0, 0.1): {'M': [-19.91, -19.54, -18.99, -18.52, -18.05, -17.55, - -17.09, -16.54, -16.04, -15.55, -15.08, -14.61, -14.01, -13.54, -13.05, -12.01], - 'phi': [-5.308, -4.117, -3.568, -3.162, -2.808, -2.602, -2.52, -2.542, -2.295, - -2.198, -2.132, -2.19, -2.041, -2.072, -1.9, -1.331], - 'err': [(0.304, 0.696), (0.112, 0.176), (0.057, 0.069), (0.037, 0.045), (0.031, 0.033), - (0.03, 0.038), (0.03, 0.054), (0.052, 0.066), (0.06, 0.063), (0.07, 0.081), - (0.101, 0.109), (0.14, 0.204), (0.146, 0.239), (0.201, 0.392), (0.233, 0.527), - (0.236, 0.573)]}}, - 'lf_nuv': {(0, - 0.1): {'M': [-20.02, -19.45, -19.0, -18.52, -18.06, -17.55, -17.06, -16.54, -16.08, - -15.58, -15.08, -14.51, -13.91, -13.57, -13.02, -12.36, -11.77], - 'phi': [-4.504, -3.673, -3.237, -2.883, -2.678, -2.426, -2.37, -2.409, -2.243, -2.107, -2.1, -1.993, -2.086, -2.032, -1.766, -1.8, -1.432], - 'err': [(0.211, 0.473), (0.083, 0.105), (0.046, 0.059), (0.028, 0.043), (0.026, 0.037), - (0.03, 0.035), (0.043, 0.039), (0.052, 0.052), (0.062, 0.071), (0.08, 0.09), - (0.101, 0.118), (0.133, 0.189), (0.179, 0.307), (0.199, 0.392), (0.237, 0.535), - (0.297, 4.206), (0.299, 4.575)]}}} diff --git a/ares/inference/ModelFit.py b/ares/inference/ModelFit.py index 3978040e1..fdc4525c8 100644 --- a/ares/inference/ModelFit.py +++ b/ares/inference/ModelFit.py @@ -23,7 +23,7 @@ import numpy as np from ..util import get_hash -from ..util.WorkerPools import MPIPool +from ..util.MPIPool import MPIPool from ..physics.Constants import nu_0_mhz from ..util.Warnings import not_a_restart from ..util.ParameterFile import par_info diff --git a/ares/obs/DustExtinction.py b/ares/obs/DustExtinction.py index 2f043c578..046d4d47c 100644 --- a/ares/obs/DustExtinction.py +++ b/ares/obs/DustExtinction.py @@ -69,6 +69,9 @@ def method(self): @cached_property def is_template(self): is_templ = self.pf['pop_dust_template'] is not None + if is_templ: + assert have_dustext, \ + "Use of `pop_dust_template` requires `dustextinction` package!" return is_templ @cached_property @@ -101,7 +104,8 @@ def get_filename(self): @property def _dustext_instance(self): if not hasattr(self, '_dustext_instance_'): - assert have_dustext, "Need dust_extinction package for this!" + assert have_dustext, \ + "Use of `pop_dust_template` requires `dustextinction` package!" mth1, curve = self.method.split(':') self._dustext_instance_ = WD01(curve) diff --git a/ares/obs/Survey.py b/ares/obs/Survey.py index d43d9edf8..2a1c23fa8 100644 --- a/ares/obs/Survey.py +++ b/ares/obs/Survey.py @@ -194,15 +194,14 @@ def _read_wfc(self, filters=None): data = {} for fn in os.listdir(path): - # Mac OS creates a bunch of ._wfc_* files. Argh. - if not fn.startswith('wfc_'): + if not fn.startswith('ACS_WFC'): continue if fn.endswith('tar.gz'): continue # Full name of the filter, e.g., F606W - fname = fn.split('wfc_')[1].split('.dat')[0] + fname = fn.split('.')[1] # Do we care about this filter? If not, move along. if filters is not None: diff --git a/ares/phenom/ParameterizedQuantity.py b/ares/phenom/ParameterizedQuantity.py index d84324381..bf1026992 100644 --- a/ares/phenom/ParameterizedQuantity.py +++ b/ares/phenom/ParameterizedQuantity.py @@ -1124,67 +1124,6 @@ def __call__(self, **kwargs): return y -class DoublePowerLawPlusGaussEvolvingAsB13(BasePQ): - def __call__(self, **kwargs): - x = kwargs[self.x] - - z = self.get_var2(kwargs['z']) - - # Need scale factor - a = 1. / (1. + z) - - # Basic idea here is to have parameters that dictate - # low-z, medium-z, and high-z behaviour, e.g., - # log10(f_star,10) = p[0] + p[5] * (1 - a) \ - # + p[9] * np.log(1 + z) + p[13] * z - - logp0 = np.log10(self.args[0]) + self.args[5] * (1 - a) \ - + self.args[9] * np.log(1 + z) \ - + self.args[13] * z \ - + self.args[17] * a - - p0 = 10**logp0 - - logp1 = np.log10(self.args[1]) + self.args[6] * (1 - a) \ - + self.args[10] * np.log(1 + z) \ - + self.args[14] * z \ - + self.args[18] * a - - p1 = 10**logp1 - - normcorr = (((self.args[4] / p1)**-self.args[2] \ - + (self.args[4] / p1)**-self.args[3])) - - s1 = self.args[2] + self.args[7] * (1 - a) \ - + self.args[11] * np.log(1 + z) \ - + self.args[15] * z \ - + self.args[19] * a - - s2 = self.args[3] + self.args[8] * (1 - a) \ - + self.args[12] * np.log(1 + z) \ - + self.args[16] * z \ - + self.args[20] * a - - # This is to conserve memory. - xx = x / p1 - y = xx**-s1 - y += xx**-s2 - np.divide(1., y, out=y) - - y *= normcorr * p0 - - mpeak = np.log10(self.args[21]) - - amp = self.args[22] + self.args[24] * (1 - a) \ - + self.args[25] * np.log(1 + z) \ - + self.args[26] * z - - width = self.args[23] - - y *= (1. + amp * np.exp(-(np.log10(x) - mpeak)**2 / 2 / width**2)) - - return y - class Okamoto(BasePQ): def __call__(self, **kwargs): x = kwargs[self.x] @@ -1300,33 +1239,6 @@ def __call__(self, **kwargs): y = p0 + self.args[2] * (np.log10(x) - self.args[1]) return y -class LinLogEvolvingAsB13(BasePQ): - def __call__(self, **kwargs): - if self.x == "1+z": - x = 1. + kwargs["z"] - else: - x = kwargs[self.x] - - z = self.get_var2(kwargs['z']) - - # Need scale factor - a = 1. / (1. + z) - - # Recall that p1 is the mass that we're pinning normalization to - p0 = self.args[0] + self.args[3] * (1 - a) \ - + self.args[5] * np.log(1 + z) \ - + self.args[7] * z \ - + self.args[9] * a - - p2 = self.args[2] + self.args[4] * (1 - a) \ - + self.args[6] * np.log(1 + z) \ - + self.args[8] * z \ - + self.args[10] * a - - y = p0 + p2 * (np.log10(x) - self.args[1]) - - return y - class LogLinearEvolvingNorm(BasePQ): def __call__(self, **kwargs): if self.x == "1+z": @@ -1405,8 +1317,6 @@ def __init__(self, **kwargs): self.func = DoublePowerLawEvolvingAsB13(**kwargs) elif kwargs["pq_func"] == "dplx_evolB13": self.func = DoublePowerLawExtendedEvolvingAsB13(**kwargs) - elif kwargs["pq_func"] == "dpl+gauss_evolB13": - self.func = DoublePowerLawPlusGaussEvolvingAsB13(**kwargs) elif kwargs["pq_func"] == "exp": self.func = Exponential(**kwargs) elif kwargs["pq_func"] in ["normal", "gaussian"]: @@ -1467,8 +1377,6 @@ def __init__(self, **kwargs): self.func = LinLog(**kwargs) elif kwargs["pq_func"] in ["linlog_evolN"]: self.func = LinLogEvolvingNorm(**kwargs) - elif kwargs["pq_func"] in ["linlog_evolB13"]: - self.func = LinLogEvolvingAsB13(**kwargs) elif kwargs["pq_func"] in ["loglin_evolN"]: raise NotImplemented('help') elif kwargs["pq_func"] in ["p_linear"]: diff --git a/ares/phenom/Tanh21cm.py b/ares/phenom/Tanh21cm.py index 5a864f42e..4b26ef29d 100644 --- a/ares/phenom/Tanh21cm.py +++ b/ares/phenom/Tanh21cm.py @@ -12,8 +12,8 @@ import time import numpy as np +import numdifftools as nd from ..util import ParameterFile -from scipy.misc import derivative from ..physics import Hydrogen, Cosmology from ..physics.Constants import k_B, J21_num, nu_0_mhz from ..physics.RateCoefficients import RateCoefficients @@ -52,7 +52,7 @@ def __init__(self, **kwargs): self.hydr = Hydrogen(cosm=self.cosm, **kwargs) def dTgas_dz(self, z): - return derivative(self.cosm.Tgas, x0=z) + return nd.Derivative(self.cosm.Tgas)(z) def electron_density(self, z): return np.interp(z, self.cosm.thermal_history['z'], diff --git a/ares/physics/Cosmology.py b/ares/physics/Cosmology.py index 697926ee4..610d1c3f0 100644 --- a/ares/physics/Cosmology.py +++ b/ares/physics/Cosmology.py @@ -12,7 +12,7 @@ import os import numpy as np -from scipy.misc import derivative +import numdifftools as nd from scipy.optimize import fsolve from scipy.integrate import quad, ode from functools import cached_property @@ -43,7 +43,7 @@ def __init__(self, pf=None, **kwargs): # Load "raw" cosmological parameters ######################################################################## - if self.pf['cosmology_name'] != 'user': + if self.pf['cosmology_name'] not in ['user', None]: self._load_cosmology() else: self.omega_m_0 = self.pf['omega_m_0'] @@ -480,7 +480,7 @@ def cooling_rate(self, z, T=None): ##s #func = lambda zz: np.interp(zz, self.inits['z'], self.inits['Tk']) - dTdz = derivative(self._Tgas_CosmoRec, z, dx=1e-2) + dTdz = nd.Derivative(self._Tgas_CosmoRec)(z) xe = np.interp(z, self.inits['z'], self.inits['xe']) @@ -501,7 +501,7 @@ def cooling_rate(self, z, T=None): return dTdz + xe_cool * mult else: - return derivative(self.Tgas, z) + return nd.Derivative(self.Tgas)(z) def log_cooling_rate(self, z): if self.pf['approx_thermal_history'] == 'exp': @@ -576,21 +576,8 @@ def get_hubble(self, z): def get_lightcone_boundaries(self, zlim, Lbox, rtol=1e-6): """ - Determine line-of-sight bins in both redshift and cMpc. - - Parameters - ---------- - zlim : tuple - Redshift range of interest. - Lbox : int, float - Co-eval box size in cMpc / h. - - Returns - ------- - A tuple containing (chunk edges in redshift, chunk midpoints in redshift, - chunk edges in comoving Mpc [NOT cMpc / h, despite input `Lbox` - being in cMpc/h!]). - + Based on size of co-eval cubes (in Mpc/h), and redshift limits, + determine all of the sub-intervals in redshift along line of sight. """ zarr = np.linspace(0.001, 10, 1000) @@ -741,15 +728,6 @@ def _tab_deg_per_cmpc(self): self._tab_deg_per_cmpc_ = angl return self._tab_deg_per_cmpc_ - @property - def _tab_deg_per_pmpc(self): - if not hasattr(self, '_tab_deg_per_pmpc_'): - # arcmin / Mpc -> deg / Mpc - angl = np.array([self._get_angle_from_length_comoving(z, 1) \ - for z in self.tab_z]) - self._tab_deg_per_cmpc_ = angl - return self._tab_deg_per_cmpc_ - @cached_property def _tab_dist_los_co(self): return np.array([self._get_dist_los_comoving(0, _z_) \ @@ -850,19 +828,10 @@ def _tab_ang_from_co(self): return np.array([self._get_angle_from_length_comoving(_z_, 1) \ for _z_ in self.tab_z]) - @cached_property - def _tab_ang_from_prop(self): - return np.array([self._get_angle_from_length_proper(_z_, 1) \ - for _z_ in self.tab_z]) - def _get_angle_from_length_comoving(self, z, R): f = lambda ang: self.get_length_comoving_from_angle(z, ang) - R return fsolve(f, x0=0.1)[0] - def _get_angle_from_length_proper(self, z, R): - f = lambda ang: self.get_length_proper_from_angle(z, ang) - R - return fsolve(f, x0=0.1)[0] - def get_angle_from_length_comoving(self, z, R): if self.interpolate and R == 1: return np.interp(z, self.tab_z, self._tab_ang_from_co) @@ -870,10 +839,7 @@ def get_angle_from_length_comoving(self, z, R): return self._get_angle_from_length_comoving(z, R) def get_angle_from_length_proper(self, z, R): - if self.interpolate and R == 1: - return np.interp(z, self.tab_z, self._tab_ang_from_prop) - else: - return self.get_angle_from_length_comoving(z, R / (1. + z)) + return self.get_angle_from_length_comoving(z, R / (1. + z)) def get_length_comoving_from_angle(self, z, angle): """ diff --git a/ares/physics/ExcursionSet.py b/ares/physics/ExcursionSet.py index 555715e92..6307df2d1 100644 --- a/ares/physics/ExcursionSet.py +++ b/ares/physics/ExcursionSet.py @@ -13,11 +13,10 @@ import numpy as np from .Constants import rho_cgs from .Cosmology import Cosmology +from scipy.interpolate import interp1d from ..util.Math import central_difference from ..util.ParameterFile import ParameterFile -from scipy.integrate import quad -from scipy.interpolate import interp1d -from scipy.misc import derivative +from scipy.integrate import quad, trapezoid two_pi = 2. * np.pi four_pi = 4. * np.pi @@ -172,7 +171,7 @@ def Variance(self, z, R): # #return quad(interp, np.log(self.tab_k.min()), np.log(self.tab_k.max()))[0] - return np.trapz(D * np.abs(W)**2, x=np.log(self.tab_k)) + return trapezoid(D * np.abs(W)**2, x=np.log(self.tab_k)) def CollapsedFraction(self): pass diff --git a/ares/physics/HaloMassFunction.py b/ares/physics/HaloMassFunction.py index 7d52880d6..8893a137c 100644 --- a/ares/physics/HaloMassFunction.py +++ b/ares/physics/HaloMassFunction.py @@ -18,9 +18,8 @@ from types import FunctionType from functools import cached_property import numpy as np -from scipy.misc import derivative from scipy.optimize import fsolve -from scipy.integrate import cumtrapz, simps +from scipy.integrate import cumulative_trapezoid, simpson from scipy.interpolate import ( UnivariateSpline, RectBivariateSpline, @@ -423,14 +422,14 @@ def _get_ngtm_mgtm_from_dndm(self): mf_func = InterpolatedUnivariateSpline(np.log(m), np.log(dndlnm), k=1) mf = mf_func(m_upper) - int_upper_n = simps(np.exp(mf), dx=m_upper[2] - m_upper[1], even='first') - int_upper_m = simps(np.exp(m_upper + mf), dx=m_upper[2] - m_upper[1], even='first') + int_upper_n = simpson(np.exp(mf), dx=m_upper[2] - m_upper[1], even='first') + int_upper_m = simpson(np.exp(m_upper + mf), dx=m_upper[2] - m_upper[1], even='first') else: int_upper_n = 0 int_upper_m = 0 - ngtm_ = np.concatenate((cumtrapz(dndlnm[::-1], dx=np.log(m[1]) - np.log(m[0]))[::-1], np.zeros(1))) - mgtm_ = np.concatenate((cumtrapz(m[::-1] * dndlnm[::-1], dx=np.log(m[1]) - np.log(m[0]))[::-1], np.zeros(1))) + ngtm_ = np.concatenate((cumulative_trapezoid(dndlnm[::-1], dx=np.log(m[1]) - np.log(m[0]))[::-1], np.zeros(1))) + mgtm_ = np.concatenate((cumulative_trapezoid(m[::-1] * dndlnm[::-1], dx=np.log(m[1]) - np.log(m[0]))[::-1], np.zeros(1))) ngtm.append(ngtm_ + int_upper_n) mgtm.append(mgtm_ + int_upper_m) @@ -573,7 +572,7 @@ def _load_hmf(self): x=np.log(self.tab_M)) self.tab_ngtm[i,:] = ( ngtm_0 - - cumtrapz( + - cumulative_trapezoid( self.tab_dndm[i] * self.tab_M, x=np.log(self.tab_M), initial=0.0, @@ -581,7 +580,7 @@ def _load_hmf(self): ) self.tab_mgtm[i,:] = ( mgtm_0 - - cumtrapz( + - cumulative_trapezoid( self.tab_dndm[i] * self.tab_M**2, x=np.log(self.tab_M), initial=0.0, @@ -619,7 +618,7 @@ def _pars_transfer(self): p = camb.CAMBparams() p.set_matter_power(**_transfer_pars) - self._pars_transfer_ = {'camb_params': p} + self._pars_transfer_ = {'camb_params': p, 'extrapolate_with_eh': True} return self._pars_transfer_ @@ -684,14 +683,6 @@ def tab_M_e(self): logM = np.log10(self.tab_M) return 10**bin_c2e(logM) - @cached_property - def tab_log10M_e(self): - return np.log10(self.tab_M_e) - - @cached_property - def tab_log10M(self): - return np.log10(self.tab_M) - @cached_property def dlnm(self): lnM = np.log(self.tab_M) @@ -731,21 +722,6 @@ def tab_dndlnm_sub(self): return self._tab_dndlnm_sub - @property - def tab_ngtm_sub(self): - if not hasattr(self, '_tab_dndlnm_sub'): - tab_dndlnm_sub = self.tab_dndlnm_sub - self._tab_dndlnm_sub = np.zeros([self.halos.tab_M.size]*2) - - m = self.halos.tab_M - for i, Mc in enumerate(self.halos.tab_M): - dndm = self.sim.pops[0].halos.tab_dndlnm_sub[iM,:] / Mc - self._tab_dndlnm_sub[i,:] = \ - cumulative_trapezoid(dndm[-1::-1] * m[-1::-1], - x=-np.log(m[-1::-1]), initial=0)[-1::-1] - - return self._tab_dndlnm_sub - @cached_property def tab_dndlnm(self): return self.tab_M * self.tab_dndm @@ -869,11 +845,11 @@ def generate_hmf(self, save_MAR=True): self._MF.update(z=z) # Undo little h for all main quantities - self.tab_dndm[i] = self._MF.dndm.copy() * self.cosm.h70**4 - self.tab_mgtm[i] = self._MF.rho_gtm.copy() * self.cosm.h70**2 - self.tab_ngtm[i] = self._MF.ngtm.copy() * self.cosm.h70**3 + self.tab_dndm[i] = self._MF.dndm * self.cosm.h70**4 + self.tab_mgtm[i] = self._MF.rho_gtm * self.cosm.h70**2 + self.tab_ngtm[i] = self._MF.ngtm * self.cosm.h70**3 - self.tab_ps_lin[i] = self._MF.power.copy() / self.cosm.h70**3 + self.tab_ps_lin[i] = self._MF.power / self.cosm.h70**3 self.tab_growth[i] = self._MF.growth_factor * 1. pb.update(i) @@ -905,6 +881,7 @@ def generate_hmf(self, save_MAR=True): tmp7 = np.zeros_like(self.tab_growth) nothing = MPI.COMM_WORLD.Allreduce(self.tab_growth, tmp7) self.tab_growth = tmp7 + ## # Done! ## @@ -945,7 +922,6 @@ def generate_mar(self): self.tab_traj = MM - if size > 1: # pragma: no cover tmp = np.zeros_like(self.tab_traj) nothing = MPI.COMM_WORLD.Allreduce(self.tab_traj, tmp) @@ -1376,11 +1352,6 @@ def get_Rvir(self, z, M, mu=0.6): and collapse redshift. Equation 24 in Barkana & Loeb (2001). - - Returns - ------- - Virial radius in kpc (we eliminate little h here). - """ return ( @@ -1768,4 +1739,4 @@ def save_hmf(self, fn=None, clobber=False, destination=None, fmt='hdf5', print('# Wrote {!s}.'.format(fn)) - return + return fn diff --git a/ares/physics/HaloModel.py b/ares/physics/HaloModel.py index 6fd13a37a..955203aa1 100644 --- a/ares/physics/HaloModel.py +++ b/ares/physics/HaloModel.py @@ -9,13 +9,11 @@ import numpy as np import scipy.special as sp from scipy.integrate import quad -from functools import cached_property from ..data import ARES from ..util.ProgressBar import ProgressBar from .HaloMassFunction import HaloMassFunction -from .Constants import c, cm_per_mpc -from scipy.integrate import cumulative_trapezoid +from .Constants import rho_cgs, c, cm_per_mpc from ..util.Math import get_cf_from_ps_tab, get_cf_from_ps_func try: @@ -78,9 +76,6 @@ def _dc_nfw(self, c): return c** 3. / (4. * np.pi) / (np.log(1 + c) - c / (1 + c)) def get_rho_nfw(self, z, Mh, r, truncate=True): - """ - Return the density at radius `r` for an NFW halo with mass `Mh` at `z`. - """ con = self.get_concentration(z, Mh) rvir = self.get_Rvir_from_Mh(Mh) @@ -165,7 +160,6 @@ def tab_Sigma_nfw(self): if os.path.exists(fn): with h5py.File(fn, 'r') as f: self._tab_Sigma_nfw = np.array(f[('tab_Sigma_nfw')]) - self._tab_Sigma_nfw_cdf = np.array(f[('tab_Sigma_nfw_cdf')]) if self.pf['verbose'] and rank == 0: print(f"# Loaded {fn}.") @@ -176,12 +170,6 @@ def tab_Sigma_nfw(self): return self._tab_Sigma_nfw - @property - def tab_Sigma_nfw_cdf(self): - if not hasattr(self, '_tab_Sigma_nfw_cdf'): - poke = self.tab_Sigma_nfw - return self._tab_Sigma_nfw_cdf - def get_u_isl(self, z, Mh, k, rmax=1e2): """ Normalized Fourier transform of an r^-2 profile. @@ -274,7 +262,7 @@ def ModulationFactor(self, z0, z=None, r=None, lc=False): return ans def _get_ps_integrals(self, k, iz, prof1, prof2, lum1, lum2, mmin1, mmin2, - focc1, focc2, term, mmax1=np.inf, mmax2=np.inf, weight_by_mass=True): + focc1, focc2, term): """ Compute integrals over profile, weighted by bias, dndm, etc., needed for halo model. @@ -288,8 +276,7 @@ def _get_ps_integrals(self, k, iz, prof1, prof2, lum1, lum2, mmin1, mmin2, integ1 = []; integ2 = [] for _k in k: _integ1, _integ2 = self._integrate_over_prof(_k, iz, - prof1, prof2, lum1, lum2, mmin1, mmin2, focc1, focc2, term, - mmax1, mmax2, weight_by_mass=weight_by_mass) + prof1, prof2, lum1, lum2, mmin1, mmin2, focc1, focc2, term) integ1.append(_integ1) integ2.append(_integ2) @@ -297,13 +284,12 @@ def _get_ps_integrals(self, k, iz, prof1, prof2, lum1, lum2, mmin1, mmin2, integ2 = np.array(integ2) else: integ1, integ2 = self._integrate_over_prof(k, iz, - prof1, prof2, lum1, lum2, mmin1, mmin2, focc1, focc2, term, - mmax1, mmax2, weight_by_mass=weight_by_mass) + prof1, prof2, lum1, lum2, mmin1, mmin2, focc1, focc2, term) return integ1, integ2 def _integrate_over_prof(self, k, iz, prof1, prof2, lum1, lum2, mmin1, - mmin2, focc1, focc2, term, mmax1, mmax2, weight_by_mass=True): + mmin2, focc1, focc2, term): """ Compute integrals over profile, weighted by bias, dndm, etc., needed for halo model. @@ -322,90 +308,69 @@ def _integrate_over_prof(self, k, iz, prof1, prof2, lum1, lum2, mmin1, for iM in np.arange(self.tab_M.size)]) bias = self.tab_bias[iz] - rho_bar = self.cosm.mean_density0 + rho_bar = self.cosm.rho_m_z0 * rho_cgs dndlnm = self.tab_dndlnm[iz] - if weight_by_mass: - weight = self.tab_M / rho_bar - else: - weight = 1. - - if (mmin1 is None) and (mmax1 is None) and (lum1 is None): + if (mmin1 is None) and (lum1 is None): fcoll1 = 1. # Small halo correction. Make use of Cooray & Sheth Eq. 71 - _integrand = dndlnm * weight * bias + _integrand = dndlnm * (self.tab_M / rho_bar) * bias corr1 = 1. - np.trapz(_integrand, x=np.log(self.tab_M)) elif lum1 is not None: corr1 = 0.0 fcoll1 = 1. else: - if mmin1 is None: - mmin1 = 0 - fcoll1 = self.tab_fcoll[iz,np.argmin(np.abs(mmin1-self.tab_M))] - - if np.isfinite(mmax1): - fcoll1 -= self.tab_fcoll[iz,np.argmin(np.abs(mmax1-self.tab_M))] - corr1 = 0.0 - if (mmin2 is None) and (mmax2 is None) and (lum2 is None): + if (mmin2 is None) and (lum2 is None): fcoll2 = 1.#self.mgtm[iz,0] / rho_bar - _integrand = dndlnm * weight * bias + _integrand = dndlnm * (self.tab_M / rho_bar) * bias corr2 = 1. - np.trapz(_integrand, x=np.log(self.tab_M)) elif lum2 is not None: corr2 = 0.0 fcoll2 = 1. else: - if mmin2 is None: - mmin2 = 0 fcoll2 = self.tab_fcoll[iz,np.argmin(np.abs(mmin2-self.tab_M))] - if np.isfinite(mmax2): - fcoll2 -= self.tab_fcoll[iz,np.argmin(np.abs(mmax2-self.tab_M))] - corr2 = 0.0 ok = self.tab_fcoll[iz] > 0 - if mmin1 is None: - mmin1 = 0 - if mmin2 is None: - mmin2 = 0 - - ok1 = np.logical_and(self.tab_M >= mmin1, self.tab_M < mmax1) - ok2 = np.logical_and(self.tab_M >= mmin2, self.tab_M < mmax2) - # If luminosities passed, then we must cancel out a factor of halo # mass that generally normalizes the integrand. if lum1 is None: - weight1 = weight / fcoll1 + weight1 = self.tab_M + norm1 = rho_bar * fcoll1 else: weight1 = lum1 + norm1 = 1. if lum2 is None: - weight2 = weight / fcoll2 + weight2 = self.tab_M + norm2 = rho_bar * fcoll2 else: weight2 = lum2 + norm2 = 1. ## # Are we doing the 1-h or 2-h term? if term == 1: integrand = dndlnm * focc1 * weight1 * weight2 \ - * p1 * p2 + * p1 * p2 / norm1 / norm2 - result = np.trapz(integrand[ok], x=np.log(self.tab_M[ok==1])) + result = np.trapz(integrand[ok==1], x=np.log(self.tab_M[ok==1])) return result, None elif term == 2: - integrand1 = dndlnm * focc1 * weight1 * p1 * bias - integrand2 = dndlnm * focc2 * weight2 * p2 * bias + integrand1 = dndlnm * focc1 * weight1 * p1 * bias / norm1 + integrand2 = dndlnm * focc2 * weight2 * p2 * bias / norm2 - integral1 = np.trapz(integrand1[ok*ok1], - x=np.log(self.tab_M[ok*ok1]), axis=0) - integral2 = np.trapz(integrand2[ok*ok2], - x=np.log(self.tab_M[ok*ok2]), axis=0) + integral1 = np.trapz(integrand1[ok==1], x=np.log(self.tab_M[ok==1]), + axis=0) + integral2 = np.trapz(integrand2[ok==1], x=np.log(self.tab_M[ok==1]), + axis=0) return integral1 + corr1, integral2 + corr2 @@ -452,8 +417,7 @@ def _get_ps_lin(self, k, iz): return ps_lin def get_ps_1h(self, z, k=None, prof1=None, prof2=None, lum1=None, lum2=None, - mmin1=None, mmin2=None, mmax1=np.inf, mmax2=np.inf, focc1=1, focc2=1, - ztol=1e-3, weight_by_mass=True): + mmin1=None, mmin2=None, focc1=1, focc2=1, ztol=1e-3): """ Compute 1-halo term of power spectrum. """ @@ -461,24 +425,14 @@ def get_ps_1h(self, z, k=None, prof1=None, prof2=None, lum1=None, lum2=None, iz, k, prof1, prof2 = self._prep_for_ps(z, k, prof1, prof2, ztol) integ1, none = self._get_ps_integrals(k, iz, prof1, prof2, - lum1, lum2, mmin1, mmin2, focc1, focc2, 1, - mmax1, mmax2, weight_by_mass=weight_by_mass) + lum1, lum2, mmin1, mmin2, focc1, focc2, term=1) return integ1 def get_ps_2h(self, z, k=None, prof1=None, prof2=None, lum1=None, lum2=None, - mmin1=None, mmin2=None, mmax1=np.inf, mmax2=np.inf, focc1=1, focc2=1, - ztol=1e-3, weight_by_mass=True): + mmin1=None, mmin2=None, focc1=1, focc2=1, ztol=1e-3): """ Get 2-halo term of power spectrum. - - Parameters - ---------- - z : int, float - Redshift of interest. - k : np.ndarray, int, float - k-mode(s) of interest [h/cMpc] - """ iz, k, prof1, prof2 = self._prep_for_ps(z, k, prof1, prof2, ztol) @@ -486,54 +440,38 @@ def get_ps_2h(self, z, k=None, prof1=None, prof2=None, lum1=None, lum2=None, ps_lin = self._get_ps_lin(k, iz) # Cannot return unmodified P_lin unless no L's or Mmin's passed! - if self.pf['halo_ps_linear'] and weight_by_mass: - if (lum1 is None) and (lum2 is None) and \ - (mmin1 is None) and (mmin2 is None) and \ - (np.isinf(mmax1) and np.isinf(mmax2)): + if self.pf['halo_ps_linear']: + if (lum1 is None) and (lum2 is None) and (mmin1 is None) and (mmin2 is None): return ps_lin integ1, integ2 = self._get_ps_integrals(k, iz, prof1, prof2, - lum1, lum2, mmin1, mmin2, focc1, focc2, 2, mmax1, mmax2, - weight_by_mass=weight_by_mass) + lum1, lum2, mmin1, mmin2, focc1, focc2, term=2) ps = integ1 * integ2 * ps_lin return ps def get_ps_shot(self, z, k=None, lum1=None, lum2=None, mmin1=None, mmin2=None, - mmax1=np.inf, mmax2=np.inf, focc1=1, focc2=1, ztol=1e-3, - weight_by_mass=True): + focc1=1, focc2=1, ztol=1e-3): """ Compute the shot noise term quickly. """ iz, k, _prof1_, _prof2_ = self._prep_for_ps(z, k, None, None, ztol) - # Identify contributing halos - if mmin1 is None: - mmin1 = 0 - - ok = np.logical_and(self.tab_M >= mmin1, self.tab_M < mmax1) - - if (lum1 is None) and weight_by_mass: - rho = self.cosm.mean_density0 #* self.tab_fcoll[iz,0] - - # If no luminosities are supplied, we assume it's the halo power - # spectrum that's of interest, in case we need to weight by the mass - # (squared) divided by the cosmic mean density (squared) if lum1 is None: - lum1 = self.tab_M / rho if weight_by_mass else 1 + lum1 = 1 if lum2 is None: - lum2 = self.tab_M / rho if weight_by_mass else 1 + lum2 = 1 dndlnm = self.tab_dndlnm[iz] integrand = dndlnm * focc1 * lum1 * lum2 - shot = np.trapz(integrand[ok==1], x=np.log(self.tab_M[ok==1]), axis=0) + shot = np.trapz(integrand, x=np.log(self.tab_M), axis=0) return shot def get_ps_mm(self, z, k=None, prof1=None, prof2=None, lum1=None, lum2=None, - mmin1=None, mmin2=None, mmax1=np.inf, mmax2=np.inf, ztol=1e-3): + mmin1=None, mmin2=None, ztol=1e-3): """ Return total power spectrum as sum of 1h and 2h terms. """ @@ -541,11 +479,9 @@ def get_ps_mm(self, z, k=None, prof1=None, prof2=None, lum1=None, lum2=None, if self.pf['halo_ps_linear']: ps_1h = 0 else: - ps_1h = self.get_ps_1h(z, k, prof1, prof2, lum1, lum2, mmin1, mmin2, - mmax1, mmax2, ztol) + ps_1h = self.get_ps_1h(z, k, prof1, prof2, lum1, lum2, mmin1, mmin2, ztol) - ps_2h = self.get_ps_2h(z, k, prof1, prof2, lum1, lum2, mmin1, mmin2, - mmax1, mmax2, ztol) + ps_2h = self.get_ps_2h(z, k, prof1, prof2, lum1, lum2, mmin1, mmin2, ztol) return ps_1h + ps_2h @@ -1030,9 +966,9 @@ def tab_prefix_surf(self): zstr = self.get_table_zstr() - Rall = self.tab_R_nfw - Rmi, Rma = np.log10(self.tab_R_nfw.min()), np.log10(self.tab_R_nfw.max()) - dlogR = np.diff(np.log10(self.tab_R_nfw))[0] + # Hard-coded for now, change this. + Rmi, Rma = -3, 1 + dlogR = 0.05 logMsize = (self.pf['halo_logMmax'] - self.pf['halo_logMmin']) \ / self.pf['halo_dlogM'] @@ -1048,6 +984,8 @@ def tab_prefix_surf(self): % (self.pf['halo_cmr'], logMsize, M1, M2, zstr, Rmi, Rma, dlogR) + + def tab_prefix_ps(self, with_size=True): """ What should we name this table? @@ -1429,13 +1367,6 @@ def generate_halo_prof(self, format='hdf5', clobber=False, checkpoint=True, return - @cached_property - def tab_R_nfw(self): - Rmi, Rma = -3, 1 - dlogR = 0.25 - R = 10**np.arange(Rmi, Rma+dlogR, dlogR) - return R - def get_halo_surface_dens(self, z, Mh, R): model_nfw = lambda MM, rr: self.get_rho_nfw(z, Mh=MM, r=rr, truncate=False) @@ -1470,16 +1401,15 @@ def generate_halo_surface_dens(self, format='hdf5', clobber=False, print(f"# Will save to {fn}.") # Hard-coded for now, change this. - R = self.tab_R_nfw + Rmi, Rma = -3, 1 + dlogR = 0.25 + R = 10**np.arange(Rmi, Rma+dlogR, dlogR) shape = (self.tab_z.size, self.tab_M.size, R.size) self._tab_sigma_nfw = np.zeros(shape) if self._tab_sigma_nfw.nbytes / 1e9 > 8: print(f"WARNING: Size of profile table projected to be >8 GB!") - # Also do CDF while we're at it - self._tab_sigma_nfw_cdf = np.zeros_like(self._tab_sigma_nfw) - pb = ProgressBar(len(self.tab_z), 'Sigma(z|M,R)', use=rank==0) pb.start() @@ -1506,11 +1436,6 @@ def generate_halo_surface_dens(self, format='hdf5', clobber=False, for jj, _R_ in enumerate(R): self._tab_sigma_nfw[i,ii,jj] = Sigma(_R_) - self._tab_sigma_nfw_cdf[i,ii,:] = \ - cumulative_trapezoid(self._tab_sigma_nfw[i,ii,:], - x=R, initial=0) \ - / np.trapz(self._tab_sigma_nfw[i,ii,:], x=R) - pb.finish() if size > 1: @@ -1519,17 +1444,12 @@ def generate_halo_surface_dens(self, format='hdf5', clobber=False, nothing = MPI.COMM_WORLD.Allreduce(self._tab_sigma_nfw, tmp) self._tab_sigma_nfw = tmp - tmp = np.zeros(shape) - nothing = MPI.COMM_WORLD.Allreduce(self._tab_sigma_nfw_cdf, tmp) - self._tab_sigma_nfw_cdf = tmp - # So only root processor writes to disk if rank > 0: return with h5py.File(fn, 'w') as f: f.create_dataset('tab_Sigma_nfw', data=self._tab_sigma_nfw) - f.create_dataset('tab_Sigma_nfw_cdf', data=self._tab_sigma_nfw_cdf) f.create_dataset('tab_R', data=R) f.create_dataset('tab_M', data=self.tab_M) f.create_dataset('tab_z', data=self.tab_z) diff --git a/ares/physics/RateCoefficients.py b/ares/physics/RateCoefficients.py index c55fcab5a..2238a6ad0 100644 --- a/ares/physics/RateCoefficients.py +++ b/ares/physics/RateCoefficients.py @@ -12,7 +12,7 @@ """ import numpy as np -from scipy.misc import derivative +import numdifftools as nd from ..util.Math import interp1d from ..util.Math import central_difference @@ -71,7 +71,7 @@ def _dCollisionalIonizationRate(self): if not hasattr(self, '_dCollisionalIonizationRate_'): self._dCollisionalIonizationRate_ = {} for i, absorber in enumerate(self.grid.absorbers): - tmp = derivative(lambda T: self.CollisionalIonizationRate(i, T), self.Tarr) + tmp = nd.Derivative(lambda T: self.CollisionalIonizationRate(i, T))(self.Tarr) self._dCollisionalIonizationRate_[i] = interp1d(self.Tarr, tmp, kind=self.interp_rc) @@ -132,7 +132,7 @@ def _dRadiativeRecombinationRate(self): if not hasattr(self, '_dRadiativeRecombinationRate_'): self._dRadiativeRecombinationRate_ = {} for i, absorber in enumerate(self.grid.absorbers): - tmp = derivative(lambda T: self.RadiativeRecombinationRate(i, T), self.Tarr) + tmp = nd.Derivative(lambda T: self.RadiativeRecombinationRate(i, T))(self.Tarr) self._dRadiativeRecombinationRate_[i] = interp1d(self.Tarr, tmp, kind=self.interp_rc) @@ -161,7 +161,7 @@ def DielectricRecombinationRate(self, T): def _dDielectricRecombinationRate(self): if not hasattr(self, '_dDielectricRecombinationRate_'): self._dDielectricRecombinationRate_ = {} - tmp = derivative(lambda T: self.DielectricRecombinationRate(T), self.Tarr) + tmp = nd.Derivative(lambda T: self.DielectricRecombinationRate(T))(self.Tarr) self._dDielectricRecombinationRate_ = interp1d(self.Tarr, tmp, kind=self.interp_rc) @@ -197,7 +197,7 @@ def _dCollisionalIonizationCoolingRate(self): if not hasattr(self, '_dCollisionalIonizationCoolingRate_'): self._dCollisionalIonizationCoolingRate_ = {} for i, absorber in enumerate(self.grid.absorbers): - tmp = derivative(lambda T: self.CollisionalExcitationCoolingRate(i, T), self.Tarr) + tmp = nd.Derivative(lambda T: self.CollisionalExcitationCoolingRate(i, T))(self.Tarr) self._dCollisionalIonizationCoolingRate_[i] = interp1d(self.Tarr, tmp, kind=self.interp_rc) @@ -233,7 +233,7 @@ def _dCollisionalExcitationCoolingRate(self): if not hasattr(self, '_dCollisionalExcitationCoolingRate_'): self._dCollisionalExcitationCoolingRate_ = {} for i, absorber in enumerate(self.grid.absorbers): - tmp = derivative(lambda T: self.CollisionalExcitationCoolingRate(i, T), self.Tarr) + tmp = nd.Derivative(lambda T: self.CollisionalExcitationCoolingRate(i, T))(self.Tarr) self._dCollisionalExcitationCoolingRate_[i] = interp1d(self.Tarr, tmp, kind=self.interp_rc) @@ -272,7 +272,7 @@ def _dRecombinationCoolingRate(self): if not hasattr(self, '_dRecombinationCoolingRate_'): self._dRecombinationCoolingRate_ = {} for i, absorber in enumerate(self.grid.absorbers): - tmp = derivative(lambda T: self.RecombinationCoolingRate(i, T), self.Tarr) + tmp = nd.Derivative(lambda T: self.RecombinationCoolingRate(i, T))(self.Tarr) self._dRecombinationCoolingRate_[i] = interp1d(self.Tarr, tmp, kind=self.interp_rc) @@ -300,7 +300,7 @@ def DielectricRecombinationCoolingRate(self, T): @property def _dDielectricRecombinationCoolingRate(self): if not hasattr(self, '_dDielectricRecombinationCoolingRate_'): - tmp = derivative(lambda T: self.DielectricRecombinationCoolingRate(T), self.Tarr) + tmp = nd.Derivative(lambda T: self.DielectricRecombinationCoolingRate(T))(self.Tarr) self._dDielectricRecombinationCoolingRate_ = interp1d(self.Tarr, tmp, kind=self.interp_rc) diff --git a/ares/physics/SecondaryElectrons.py b/ares/physics/SecondaryElectrons.py index fae14409a..8df53da56 100644 --- a/ares/physics/SecondaryElectrons.py +++ b/ares/physics/SecondaryElectrons.py @@ -43,15 +43,11 @@ def __init__(self, method=0): def _load_data(self): - if not ARES: - raise IOError('Must set $ARES environment variable!') - if os.path.exists(os.path.join(ARES, prefix, 'secondary_electron_data.hdf5')): self.fn = os.path.join(ARES, prefix, 'secondary_electron_data.hdf5') have_hdf5_file = True else: - self.fn = os.path.join(ARES, prefix, 'secondary_electron_data.pkl') - have_hdf5_file = False + raise IOError("Did not find secondary_electron_data.hdf5") if have_h5py and have_hdf5_file: f = h5py.File(self.fn, 'r') diff --git a/ares/populations/Composite.py b/ares/populations/Composite.py index de9488661..81e4f80a3 100644 --- a/ares/populations/Composite.py +++ b/ares/populations/Composite.py @@ -111,15 +111,12 @@ def BuildPopulationInstances(self): #print('hi empty', self.pops[i]) continue + #print('hi', i, entry, to_quantity[i], self.pops[i]) + for j, element in enumerate(entry): if j == 0: tmp = self.pfs[i].copy() - # Confusing behavior. 11/05/2024. - # By defining `element_hard=element*1` here, we often - # get recursion errors, but simply by moving it to within - # if/else blocks below, all seems well. Hmmm... - if to_quantity[i][j] in ['sfrd', 'emissivity']: if self.pops[i] is None: self.pops[i] = GalaxyAggregate(pf=self.pf.pfs[i], @@ -152,19 +149,16 @@ def BuildPopulationInstances(self): if self.pops[i] is None: self.pops[i] = GalaxyCohort(pf=self.pf.pfs[i], cosm=self._cosm_, **tmp) - - element_hard = element * 1 if tmp[f'pop_{to_quantity[i][j]}_inv']: self.pops[i]._get_focc = lambda **kw: \ - 1. - self.pops[element_hard].get_focc(**kw) + 1. - self.pops[element].get_focc(**kw) else: - self.pops[i]._get_focc = self.pops[element_hard].get_focc + self.pops[i]._get_focc = self.pops[element].get_focc elif to_quantity[i][j] in ['fsurv']: + element_hard = 1 * element if self.pops[i] is None: self.pops[i] = GalaxyCohort(pf=self.pf.pfs[i], cosm=self._cosm_, **tmp) - - element_hard = element * 1 if tmp[f'pop_{to_quantity[i][j]}_inv']: self.pops[i]._get_fsurv = lambda **kw: \ 1. - self.pops[element_hard].get_fsurv(**kw) diff --git a/ares/populations/GalaxyCohort.py b/ares/populations/GalaxyCohort.py index 2af4ae47b..cce021a83 100644 --- a/ares/populations/GalaxyCohort.py +++ b/ares/populations/GalaxyCohort.py @@ -14,19 +14,19 @@ import h5py import numbers import numpy as np +import numdifftools as nd from inspect import ismethod from types import FunctionType from ..util import ProgressBar from ..obs.Survey import Survey from ..analysis import ModelSet -from scipy.misc import derivative from scipy.optimize import fsolve from functools import cached_property from ..util.Misc import numeric_types, get_band_edges from scipy.integrate import quad, simpson, cumulative_trapezoid, ode from .GalaxyAggregate import GalaxyAggregate from .Population import normalize_sed, complex_sfhs -from ..util.Stats import bin_c2e, bin_e2c, lognormal +from ..util.Stats import bin_c2e, bin_e2c from scipy.interpolate import RectBivariateSpline, LinearNDInterpolator from ..util.Math import central_difference, interp1d_wrapper, interp1d from ..physics.Constants import s_per_yr, g_per_msun, cm_per_mpc, G, m_p, \ @@ -42,18 +42,26 @@ size = 1 try: - from astropy.modeling.models import Sersic1D + import pymp + have_pymp = True except ImportError: - pass - + have_pymp = False + + class DummyPyMP(object): + def xrange(self, start, stop): + yield range(start, stop) + small_dz = 1e-8 -ztol = 1e-2 +ztol = 1e-4 +#z0 = 9. # arbitrary tiny_phi = 1e-18 #_sed_tab_attributes = ['Nion', 'Nlw', 'rad_yield', 'L1600_per_sfr', # 'L_per_sfr', 'sps-toy'] -gauss = lambda x, args: args[0] * np.exp(-(x - args[1])**2 / 2. / args[2]**2) +def lognormal(x, mu, sigma): + return np.exp(-0.5 * (x - mu)**2 / sigma**2) \ + / np.sqrt(2. * np.pi) / sigma class GalaxyCohort(GalaxyAggregate): """ @@ -335,84 +343,9 @@ def get_gas_mass(self, z, Mh=None): func = self._get_function('pop_gas_fraction') return func(z=z, Mh=Mh) * Mh * self.cosm.fbaryon - def get_size(self, z, Ms=None): - """ - Return the half-light radius in kpc for galaxy at redshift `z` with stellar mass `Ms`. - """ - if Ms is None: - Mh = self.halos.tab_M - Ms = self.get_smhm(z=z, Mh=Mh) * Mh - + def get_size(self, z, Ms): func = self._get_function('pop_msr') return func(z=z, Ms=Ms) - - def get_light_fraction_in_aperture(self, z, ap=2.): - """ - Figure out how much light comes from central region of resolved source. - - .. note :: This requires `pop_msr` and `pop_profile_info`. - - Parameters - ---------- - z : int, float - Redshift of interest. - ap : int, float - Aperture [diameter in arcseconds]. - - - """ - Mh = self.halos.tab_M - Ms = self.get_smhm(z=z, Mh=Mh) * Mh - Rkpc = self.get_size(z=z, Ms=Ms) - - # Much faster to interpolate from table than generate angle/pMpc - # on the fly. Interpolant automatically used if provided R is 1 - arcsec_per_pmpc = 60 * self.cosm.get_angle_from_length_proper( - z, 1. - ) - R_sec = arcsec_per_pmpc * Rkpc * 1e-3 - - # `R_sec` is the angular size of each galaxy in the model in arcsec. - # Note: the size is defined as the stellar half-light radius. - - # Sersic indices and position angles - pop_s = 'sfg' if self.is_star_forming else 'qg' - - # First, identify redshift interval to use. - zoptions = self.pf['pop_profile_info'][f'{pop_s}_z'] - z1, z2 = np.array(zoptions).T - - # Make sure `iz` gets redshift within appropriate window - iz = np.argmin(np.abs(z - z1)) - if z < z1[iz]: - iz -= 1 - - # If provided redshift is > max redshift in profile_info, just use - # highest available redshift. - if z > z2.max(): - iz = -1 - - key = zoptions[iz] - - # Axis ratios first - ba_loc, ba_scale = self.pf['pop_profile_info'][f'{pop_s}_ba'][key] - ellip_loc = 1 - ba_loc - - # Now Sersic indices - n_loc, n_scale = self.pf['pop_profile_info'][f'{pop_s}_n'][key] - - ## - # Have to do this in 2-D to be precise. - # Generate light profile - #f_fib = [] - #for i in range(Ms.size): - - # VERY ROUGH FOR NOW - # Just assuming face-on, that the "full light radius" is 2x the half-light radius R_sec - # pi * R_ap**2 / (pi * R_eff**2) - frac = (ap / R_sec / 2.)**2 - - return np.minimum(frac, 1.) def get_field(self, z, field): """ @@ -707,6 +640,7 @@ def _get_focc(self): @_get_focc.setter def _get_focc(self, value): + #print('setting _get_focc', self.id_num) self._get_focc_ = value def get_focc(self, z, Mh): @@ -768,7 +702,6 @@ def get_sfrd(self, z): if not hasattr(self, '_func_sfrd'): func = interp1d(self.halos.tab_z, self.tab_sfrd_total, kind=self.pf['pop_interp_sfrd']) - self._func_sfrd = func return self._func_sfrd(z) @@ -779,7 +712,7 @@ def get_freturn(self, t): """ return 0.05 * np.log(1. + t / 1.4) - def get_smd(self, z, mass_return=False, single_z=False): + def get_smd(self, z, mass_return=False): """ Compute stellar mass density (SMD) at redshift `z`. @@ -834,15 +767,6 @@ def get_smd(self, z, mass_return=False, single_z=False): tasc = self.halos.tab_t[-1::-1] zasc = self.halos.tab_z[-1::-1] - if single_z: - iz = np.argmin(np.abs(z - zasc)) - - smd_of_z = self.get_sfrd(zasc[0:iz]) \ - * (1 - self.get_freturn(tasc[iz] - tasc[0:iz])) - - return np.trapz(smd_of_z, x=tasc[0:iz] * 1e6) - - # `zasc` is redshift in ascending time order smd_ret = [] for i, _t_ in enumerate(tasc): @@ -870,9 +794,9 @@ def get_smd(self, z, mass_return=False, single_z=False): return self._func_smd[mass_return](z) def get_mar(self, z, Mh): - MAR = np.maximum(self.get_mass_accretion_rate(z, Mh), 0.) + MGR = np.maximum(self.MGR(z, Mh), 0.) eta = self.eta(z, Mh) - return eta * MAR + return eta * MGR @property def eta(self): @@ -890,7 +814,7 @@ def eta(self): @property def _tab_eta(self): - """ + r""" Correction factor for MAR. \eta(z) \int_{M_{\min}}^{\infty} \dot{M}_{\mathrm{acc}}(z,M) n(z,M) dM @@ -1052,9 +976,9 @@ def get_mstell_obs(self, **kwargs): The error is defined as: - error = \log_{10} [Observed mass] - \log_{10} [True mass] + error = log10[Observed mass] - log10[True mass] - i.e., the true mass is the \log_{10} [Observed mass] - this error. + i.e., the true mass is the log10[Observed mass] - this error. """ @@ -1087,9 +1011,9 @@ def get_sfr_sys(self, **kwargs): The error is defined as: - error = \log_{10} [Observed SFR] - \log_{10} [True SFR] + error = log10 [Observed SFR] - log10[True SFR] - i.e., the true SFR is the \log_{10} [Observed SFR] - this error. + i.e., the true SFR is the log10 [Observed SFR] - this error. """ @@ -1129,8 +1053,7 @@ def get_sfr_obs(self, **kwargs): def get_sfr(self, **kwargs): """ - Get star formation rate at redshift `z` in a halo of mass `Mh`, - both supplied as keyword arguments. + Get star formation rate at redshift z in a halo of mass Mh. Parameters ---------- @@ -1152,11 +1075,7 @@ def get_sfr(self, **kwargs): return self._get_sfr(**kwargs) z = kwargs['z'] - - if 'Mh' in kwargs: - Mh = kwargs['Mh'] - else: - Mh = None + Mh = kwargs['Mh'] # User may have supplied a function for SFR(z, Mh) directly. if self.pf['pop_sfr'] is not None: @@ -1251,8 +1170,7 @@ def get_zindex(self, z): iz = np.argmin(np.abs(z - self.halos.tab_z)) - # redshift is in ascending order always - if z < self.halos.tab_z[iz]: + if z > self.halos.tab_z[iz]: iz -= 1 return iz @@ -1297,7 +1215,7 @@ def get_emissivity(self, z, x=None, band=None, units='eV', ## # Handle case with scatter separately. - if self.pf['pop_scatter_sfh'] == self.pf['pop_scatter_sfr'] == 0: + if self.pf['pop_scatter_sfh'] == 0: L1 = self.get_lum(z1, x=x, band=band, units=units, units_out=units_out, total_sat=True) L2 = self.get_lum(z2, x=x, band=band, units=units, @@ -1313,38 +1231,33 @@ def get_emissivity(self, z, x=None, band=None, units='eV', integ2 = L2 * self.halos.tab_dndlnm[iz+1,:] \ * self.tab_focc[iz+1,:] + rhoL1 = np.trapz(integ1[ok1==1], dx=self.halos.dlnm) rhoL2 = np.trapz(integ2[ok2==1], dx=self.halos.dlnm) - else: - assert units_out.lower().startswith('erg/s/hz'), \ - "Sorry: only how to do this with erg/s/hz units right now." + assert units_out.lower().startswith('erg/s/hz') ## # Just use get_lf. # This is forced to be in units of 'erg/s/Hz' internally. - # The `use_logL=False` setting means the LF returned - # will be dn/dL, and the `bins` will - # be L (as opposed to dn/dlog10L and log10L, with `use_logL=True`) + # These LFs are dn/dlnL bins1, phi1 = self.get_lf(z1, x=x, use_mags=False, units=units, - use_logL=False, band=band) - + band=band) if np.all(phi1[phi1.mask==0] == 0): rhoL1 = 0 else: - # One factor of bins1 to get integrated luminosity, one from integrating over logL - rhoL1 = np.trapz(phi1 * bins1**2, x=np.log(bins1)) + rhoL1 = np.trapz(phi1 * bins1, x=np.log(bins1)) if z == z1: return rhoL1 bins2, phi2 = self.get_lf(z2, x=x, use_mags=False, units=units, - use_logL=False, band=band) + band=band) if np.all(phi2[phi2.mask==0] == 0): rhoL2 = 0 else: - rhoL2 = np.trapz(phi2 * bins2**2, x=np.log(bins2)) + rhoL2 = np.trapz(phi2 * bins2, x=np.log(bins2)) if z == z2: return rhoL2 @@ -1358,14 +1271,6 @@ def get_emissivity(self, z, x=None, band=None, units='eV', if (rhoL1 == 0) or (rhoL2 == 0): return 0.5 * max(rhoL1, rhoL2) - if (rhoL1 < 0) and (rhoL2 < 0): - print(f"! PROBLEM: both emissivities < 0 at z={z}! Setting to 0.") - return 0.0 - - if (rhoL1 < 0) or (rhoL2 < 0): - print(f"! WARNING: We've got a negative emissivity at z={z}, band={band}. Using positive one.") - return max(rhoL1, rhoL2) - ## # Interpolate to input z log10rhoL = np.log10(rhoL1) \ @@ -1429,7 +1334,7 @@ def get_smf(self, z, bins=None, units='dex', use_tabs=True): def get_mf(self, z, bins=None, units='dex', mass='stellar', use_tabs=True): """ - Return stellar mass function, dn/dlog10(Mstell). + Return stellar mass function. Parameters ---------- @@ -1469,14 +1374,12 @@ def get_mf(self, z, bins=None, units='dex', mass='stellar', use_tabs=True): logMh_e = bin_c2e(logMh) if mass == 'stellar': - if use_tabs: fstar = self.tab_fstar[iz,:] else: fstar = self.get_sfe(z=z, Mh=self.halos.tab_M) Ms_c = fstar * self.halos.tab_M - logMc = np.log10(Ms_c) fstar_e = self.get_sfe(z=z, Mh=10**logMh_e) Ms_e = fstar_e * 10**logMh_e @@ -1484,6 +1387,8 @@ def get_mf(self, z, bins=None, units='dex', mass='stellar', use_tabs=True): dlog10mdlog10M = np.diff(logMh_e) / np.diff(logMs_e) + logMc = np.log10(Ms_c) + elif mass == 'gas': Mg_c = self.get_gas_mass(z=z, Mh=self.halos.tab_M) Mg_e = self.get_gas_mass(z=z, Mh=10**logMh_e) @@ -1494,10 +1399,13 @@ def get_mf(self, z, bins=None, units='dex', mass='stellar', use_tabs=True): else: raise NotImplementedError('help') - # Get central abundance + #x = np.log(self.halos.tab_M) if self.halos.dlnm is None else None + #dx = self.halos.dlog10m + + ## + # Extra step if we're dealing with satellites dndlnm = self.halos.tab_dndlnm[iz,:] - # Centrals are relatively easy, just be careful about scatter if self.is_central_pop: if use_tabs: dndlnm = dndlnm * self.tab_focc[iz,:] @@ -1506,37 +1414,26 @@ def get_mf(self, z, bins=None, units='dex', mass='stellar', use_tabs=True): ## # More complicated if we have scatter - if (self.pf['pop_scatter_sfh'] > 0) or \ - (self.pf['pop_scatter_smhm'] > 0): - - if (self.pf['pop_scatter_sfh'] > 0): - sigma = self.pf['pop_scatter_sfh'] - else: - sigma = self.pf['pop_scatter_smhm'] - - mu = np.log(Ms_c) + if self.pf['pop_scatter_sfh'] > 0: + sigma = self.pf['pop_scatter_sfh'] + mu = np.log10(Ms_c) - # This is dn/dln(Mstell) - pdf = lognormal(mu[None,:], mu[:,None], sigma) + # This is essentially dn/dlog10Mstell + pdf = lognormal(bin_c[None,:], mu[:,None], sigma) - # Integrating over PDF, dn/dln(Mstell), so convert - # halo abundance to dlog10Mstell first (divide by ln(10)). - integrand = (dndlnm[ok==1,None] * np.log(10.)) \ - * dlog10mdlog10M[ok==1,None] * pdf[ok==1,:] - - # Reminder 7/18: slicing pdf with ok==1 in both axes here - # caused problems... - - # Integrate over halo mass (or ) axis - phi_tot = np.trapz(integrand, x=np.log(Ms_c[ok==1]), axis=0) + # Integrating over PDF, dn/dlog10Mstell, so convert + # halo abundance to dlog10Mstell first. + integrand = dndlnm[ok==1,None] * np.log(10.) \ + * dlog10mdlog10M[ok==1,None] * pdf[ok==1] + # Integrate over halo mass axis + phi_tot = np.trapz(integrand, + x=np.log10(Ms_c[ok==1]), axis=0) - return bin_c, np.interp(bin_c, np.log10(Ms_c), phi_tot) + return bins, phi_tot else: pdf = 1 sigma = 0 - ## - # Extra step if we're dealing with satellites else: if use_tabs: fsurv = self.tab_fsurv[iz,:] @@ -1551,21 +1448,16 @@ def get_mf(self, z, bins=None, units='dex', mass='stellar', use_tabs=True): # Need to sum up all subhalos over central population #dndlog10m_c = self.halos.tab_dndlnm[iz,:] #* np.log(10.) - if (self.pf['pop_scatter_sfh'] > 0) or \ - (self.pf['pop_scatter_smhm'] > 0): - - if (self.pf['pop_scatter_sfh'] > 0): - sigma = self.pf['pop_scatter_sfh'] - else: - sigma = self.pf['pop_scatter_smhm'] + if self.pf['pop_scatter_sfh'] > 0: + sigma = self.pf['pop_scatter_sfh'] # Ms_c is really Ms_sat if we're a satellite pop. - mu = np.log(Ms_c) + mu = np.log10(Ms_c) # Log-normal distribution of stellar mass at given # halo mass, need to integrate over. # Arguments are just: x, mu, sigma - pdf = lognormal(mu[None,:], mu[:,None], sigma) + pdf = lognormal(bin_c[None,:], mu[:,None], sigma) else: sigma = 0 pdf = 1. @@ -1597,22 +1489,22 @@ def get_mf(self, z, bins=None, units='dex', mass='stellar', use_tabs=True): # function of subhalo mass if sigma > 0: # Get integrand as dn/dlog10(Mstell) - integrand = (dndlnm_sat * np.log(10)) * dlog10mdlog10M + integrand = dndlnm_sat * np.log(10) * dlog10mdlog10M # Integrate over halo mass axis phi_tot = np.trapz(integrand[ok==1,None] * pdf[ok==1,:], - x=np.log(Ms_c[ok==1]), axis=0) + x=np.log10(Ms_c[ok==1]), axis=0) - return bin_c, np.interp(bin_c, np.log10(Ms_c[ok==1]), phi_tot[ok==1]) + return bins, phi_tot else: # dndlnm = dndlnm_sat ## # Convert to [per mass unit] of our choosing. - phi = (dndlnm * np.log(10.)) * dlog10mdlog10M + phi = dndlnm * np.log(10.) * dlog10mdlog10M if bins is not None: - return bin_c, np.interp(bin_c, logMc, phi) + return bins, np.interp(bins, logMc, phi) else: return logMc, phi @@ -1682,167 +1574,12 @@ def get_surface_density(self, z, maglim=None, dz=1., dtheta=1., x=1600., else: return mags, cgal - def get_pdf_mstell(self, z, log10M=None): - if not hasattr(self, '_cache_pdf_mstell'): - self._cache_pdf_mstell = {} - - if z in self._cache_pdf_mstell.keys(): - return self._cache_pdf_mstell[z] - - if log10M is None: - lnM = np.log(10**np.log10(self.get_mstell_obs(z=z, Mh=self.halos.tab_M))) - else: - lnM = np.log(10**log10M) - - pdf = lognormal(lnM[None,:], lnM[:,None], self.pf['pop_scatter_smhm']) - - self._cache_pdf_mstell[z] = pdf - - return pdf - - def _get_x_sequence(self, z, bin, x='mstell', use_tabs=True): - """ - Analogous to `get_main_sequence` but more general. Basically, do the - annoying work of averaging some field `x` taking into account the - potential for scatter in SFR, stellar mass, etc. - """ - pass - - def get_main_sequence(self, z, bin, use_tabs=True): - """ - Return mean SFR of galaxies in provided log10(stellar mass / msun) `bin`. - - This routine exists to handle the non-trivial case when we have scatter - in SFR and/or Mstell in a given halo mass bin. It integrates over the - PDF(s) of these quantites weighted by the abundance of galaxies in a - given bin. - - Returns - ------- - Star formation rate [Msun/yr; observed] in the provided stellar mass bin - (also assumed to be 'observed'). - """ - iz = self.get_zindex(z) - dndlnm = self.halos.tab_dndlnm[iz] - # Recall: dndlog10x = dndlnx / np.log(10.) - dndlog10m = dndlnm * np.log(10.) - # [note that log(10) won't matter: will cancel in the end anyways] - - # Bin centers - binc = 0.5 * (bin[0] + bin[1]) - - # Halo masses, bin centers and edges (in log10) - Mh = self.halos.tab_M - logMh = self.halos.tab_log10M - logMh_e = self.halos.tab_log10M_e - - # Get mean relations - sfr = self.get_sfr_obs(z=z, Mh=Mh) - Ms = self.get_mstell_obs(z=z, Mh=Mh) - - if self.pf['pop_scatter_sfh'] > 0: - assert self.pf['pop_scatter_sfr'] == self.pf['pop_scatter_smhm'] == 0,\ - "SFH scatter OR (SFR and SMHM scatter) allowed, not both!" - - return np.interp(binc, np.log10(Ms), sfr).squeeze() - - # SFR, SMHM, fQ - if use_tabs: - fstar = self.tab_fstar[iz,:] - focc = self.tab_focc[iz,:] - else: - fstar = self.get_sfe(z=z, Mh=Mh) - focc = self.get_focc(z=z, Mh=Mh) - - - # Need log10 of each - log10M = np.log10(Ms) - log10SFR = np.log10(sfr) - - # Halo mass bin corresponding to mean relation - log10Mh_bar = np.interp(binc, log10M, np.log10(Mh)) - - # Get stellar mass bin edges and centers - Ms_c = fstar * self.halos.tab_M - fstar_e = self.get_sfe(z=z, Mh=10**logMh_e) - Ms_e = fstar_e * 10**logMh_e - logMs_e = np.log10(Ms_e) - - # dlogMh/dlogMstell - dlog10mdlog10M = np.diff(logMh_e) / np.diff(logMs_e) - - # Shorthand - sigma_m = self.pf['pop_scatter_smhm'] - sigma_sfr = self.pf['pop_scatter_sfr'] - - if sigma_m == sigma_sfr == 0: - return np.interp(float(binc), log10M, sfr) - - log10Mmin = np.log10(self.get_Mmin(z)) - - # 2-D PDF: (, Mstell) - # In other words, pdf[0] is the probability distribution of stellar mass - # for an object in halo 0, with mean stellar mass Ms[0] - pdf_m = self.get_pdf_mstell(z, log10M=log10M).copy() - # We make a copy to avoid nulling out all elements upon successive - # iterations (via `ok` mask below) - - # Null out contributions from stellar masses outside the bin of interest - ok = np.logical_and(log10M >= bin[0], log10M < bin[1]) - pdf_m[:,ok==0] = 0 - #pdf_sfr[:,ok==0] = 0 - - # First: determine mean SFR in this halo mass bin - sfr_bin = sfr * np.exp(0.5 * sigma_sfr**2) - - integrand = dndlog10m[:,None] * dlog10mdlog10M[:,None] \ - * focc[:,None] * pdf_m[:,:] - - norm = 0.0 - mainseq = 0.0 - for i, logM in enumerate(np.log10(self.halos.tab_M)): - if logM < log10Mmin: - continue - - # Skip elements way far away from mean relation to save time. - if (logM < (log10Mh_bar - 3 * sigma_m)) or \ - (logM > (log10Mh_bar + 3 * sigma_m)): - continue - - # Then: integrate over stellar mass PDF. - # `pdf_m` above, buried in `integrand`, is dn/dlnMstell, hence integral over np.log(Ms) - mainseq += np.trapz(sfr_bin[i] * integrand[i,:], x=np.log(Ms)) - - norm += np.trapz(integrand[i,:], x=log10M) - - ## - # Rare, but we do occasionally request very low or very high mass - # bins, for which there may not actually be any galaxies. Need to - # check to avoid divide by zero error. - if norm == 0: - return 0. - - return mainseq / norm - def get_sfr_mean(self, z, Mh): - if (self.pf['pop_scatter_sfh'] > 0): - sigma = self.pf['pop_scatter_sfh'] - elif (self.pf['pop_scatter_sfr'] > 0): - sigma = self.pf['pop_scatter_sfr'] - else: - sigma = 0 - - return self.get_sfr(z=z, Mh=Mh) * np.exp(0.5 * sigma**2) - + return self.get_sfr(z=z, Mh=Mh) \ + * np.exp(0.5 * self.pf['pop_scatter_sfh']**2) def get_mstell_mean(self, z, Mh): - if (self.pf['pop_scatter_sfh'] > 0): - sigma = self.pf['pop_scatter_sfh'] - elif (self.pf['pop_scatter_smhm'] > 0): - sigma = self.pf['pop_scatter_smhm'] - else: - sigma = 0 - - return self.get_smhm(z=z, Mh=Mh) * Mh * np.exp(0.5 * sigma**2) + return self.get_smhm(z=z, Mh=Mh) * Mh \ + * np.exp(0.5 * self.pf['pop_scatter_sfh']**2) def get_number_counts(self, bins, zmin=0, zmax=10, x=1600., units='Angstroms', window=1, absolute=False, cam=None, filters=None, @@ -2002,16 +1739,8 @@ def _get_lf_mags(self, z, bins=None, x=1600., use_tabs=True, else: bins_abs = bins - try: - phi_of_x = np.interp(bins_abs, x_phi[ok==1][-1::-1][ix+1:], - phi[ok==1][-1::-1][ix+1:], left=0, right=0) - except ValueError: - print(f"Getting 'array of samples points empty' error.") - print(bins_abs) - print(x_phi) - print(phi) - - return bins, tiny_phi * np.ones_like(bins) + phi_of_x = np.interp(bins_abs, x_phi[ok==1][-1::-1][ix+1:], + phi[ok==1][-1::-1][ix+1:], left=0, right=0) return bins, phi_of_x @@ -2021,7 +1750,7 @@ def get_uvlf(self, z, bins, use_mags=True, wave=1600., window=1., window=window, absolute=absolute) def get_lf(self, z, bins=None, use_tabs=True, - use_mags=True, use_logL=True, x=1600., units='Angstrom', window=1., + use_mags=True, x=1600., units='Angstrom', window=1., absolute=True, raw=False, nebular_only=False, band=None, cam=None, filters=None, dlam=20, presets=None): """ @@ -2038,8 +1767,7 @@ def get_lf(self, z, bins=None, use_tabs=True, Bin (centers) at which to compute LF. use_mags : bool If True, will return luminosity function vs. AB magnitudes, - otherwise will use luminosities. Assumes that the user-supplied - `bins` are AB magnitudes as well. + otherwise will use luminosities. absolute : bool If True and use_mags==True, returns LF at absolute AB magnitudes, otherwise will use apparent mags. @@ -2085,40 +1813,13 @@ def get_lf(self, z, bins=None, use_tabs=True, window=window, absolute=absolute, cam=cam, filters=filters, dlam=dlam) else: - # By default, we compute dn/dlnL. - _lum_, dndlnL = self._get_lf_lum(z, x=x, + # By default, we compute dn/dL + bins, phi_of_x = self._get_lf_lum(z, x=x, use_tabs=use_tabs, units=units, window=window, raw=raw, nebular_only=nebular_only, band=band) - - # phi is dn/dlnL. Default is to return log10(L), but might need to convert to dn/dL - # if user provides use_logL=False. - # Recall dndlog10x = dndlnx / np.log(10.) - if use_logL: - _x_ = np.log10(_lum_) - phi = dndlnL * np.log(10.) - else: - _x_ = _lum_ - dndL = dndlnL / _lum_ - phi = dndL - - ok = _x_.mask==0 - - bins_was_None = False - if bins is None: - bins_was_None = True - bins = _x_ - - if not np.any(ok): - phi_of_x = tiny_phi * np.ones_like(bins) - phi_of_x = np.ma.array(phi_of_x, mask=~ok) - elif bins_was_None: - phi_of_x = np.ma.array(phi, mask=ok==0) - else: - xgt0 = np.logical_and(_x_ > 0, ok==1) - phi_of_x = np.interp(bins, _x_[xgt0==1], phi[xgt0==1], - left=0, right=0) - phi_of_x = np.ma.array(phi_of_x) + #raise NotImplemented('needs fixing') + #phi_of_x = self._get_uvlf_lum(bins, z, wave=wave, window=window) ## # Might need to apply dust correction if using empirical approach. @@ -2152,34 +1853,11 @@ def get_uvlf(self, z, bins): return self.get_lf(z, bins, use_mags=True, x=1600, units='Angstroms', absolute=True) - def get_bias(self, z, limit, wave=1600., cut_in_mass=False, absolute=False, - cut_in_flux=False): + def get_bias(self, z, limit, wave=1600., cut_in_flux=False, + cut_in_mass=False, absolute=False): """ Compute linear bias of galaxies brighter than (or more massive than) some cut-off. - - Parameters - ---------- - z : int, float - Redshift of interest. - limit : int, float - This parameter controls either the limiting magnitude or the - limiting halo mass, depending on the value of `cut_in_mass`. - By default, our approach is to use apparent magnitudes in order to - connect to observations more explicitly. For example, `limit=26.5` - is a Roman-like magnitude cut on the galaxy population. - cut_in_mass : bool - If True, then `limit` is assumed to be a halo mass in Msun. - absolute : bool - Whether `limit` magnitudes are absolute or apparent AB mags. - cut_in_flux : bool - Not currently implement. Might be useful for comparing with - specroscopic surveys which often report sensitivities as a - limiting line luminosity in [erg/s/cm^2]. - - Returns - ------- - """ iz = np.argmin(np.abs(z - self.halos.tab_z)) @@ -2197,7 +1875,6 @@ def get_bias(self, z, limit, wave=1600., cut_in_mass=False, absolute=False, else: ok = tab_M >= limit else: - _filt, mags = self.get_mags(z, x=wave, absolute=absolute) ok = np.logical_and(mags <= limit, np.isfinite(mags)) integ_top = tab_b[ok==1] * tab_n[ok==1] * tab_f[ok==1] @@ -2556,13 +2233,11 @@ def get_transmission(self, z, x, units='Angstroms', band=None, if use_tabs: iz = self.get_zindex(z) smhm = self.tab_fstar[iz,:] - Ms = self.get_mstell(z=z, Mh=self.halos.tab_M) - sfr = self.get_sfr(z=z, Mh=self.halos.tab_M) + Ms = self.get_mstell_obs(z=z, Mh=self.halos.tab_M) Av = self.tab_Av[iz,:] else: - Ms = self.get_mstell(z=z, Mh=self.halos.tab_M) - sfr = self.get_sfr(z=z, Mh=self.halos.tab_M) - Av = self.get_Av(z=z, Ms=Ms, SFR=sfr, Mh=self.halos.tab_M) + Ms = self.get_mstell_obs(z=z, Mh=self.halos.tab_M) + Av = self.get_Av(z=z, Ms=Ms) #Av = self.get_Av(z=z, Ms=Ms) Sd = None @@ -2618,26 +2293,6 @@ def get_lum_sat_tot(self, z, Lsat, use_tabs=True): return Lh - @cached_property - def _tab_norm_lines(self): - self._tab_norm_lines_ = np.zeros(len(self.pf['pop_lum_per_sfr_at_wave'])) - for i, line_info in enumerate(self.pf['pop_lum_per_sfr_at_wave']): - - if len(line_info) == 2: - _wave_, _lum_ = line_info - _width_ = None - self._tab_norm_lines_[i] = 1 - continue - - _wave_, _lum_, _width_ = line_info - - gint = quad(lambda xx: gauss(xx, [1, _wave_, _width_]), - _wave_-5*_width_, _wave_+5*_width_)[0] - - self._tab_norm_lines_[i] = _lum_ / gint - - return self._tab_norm_lines_ - def _get_lum_lines_per_sfr(self, z, x, band, units, units_out): """ If the user has provided scaling relationships between line luminosity @@ -2659,8 +2314,6 @@ def _get_lum_lines_per_sfr(self, z, x, band, units, units_out): if band[0] > band[1]: band = band[::-1] - - wave = np.mean(self.src.get_ang_from_x(band, units=units)) # Save deal for `x` elif x is not None: wave = self.src.get_ang_from_x(x, units=units) @@ -2670,41 +2323,19 @@ def _get_lum_lines_per_sfr(self, z, x, band, units, units_out): # Loop over provided emission lines, determine if any lie in the # requested wavelength range. - for i, line_info in enumerate(self.pf['pop_lum_per_sfr_at_wave']): - - if len(line_info) == 2: - _wave_, _lum_ = line_info - _width_ = None - else: - _wave_, _lum_, _width_ = line_info - - if _width_ is not None: - # This is the only case where we should be allowed to "double count" - # hence the incrementing below (L_lines += ) - - # Need to figure out fraction of total emission that's - # emitted in the supplied band. - A = self._tab_norm_lines[i] - - if (x is not None): - conv = 1. / (c * 1e8 / wave**2) if 'hz' in units_out.lower() \ - else 1. - # This will be in erg/s/SFR/Ang given _tab_norm_lines - # integral over wavelength, so we have to convert to - # erg/s/SFR/Hz - L_lines += gauss(wave, [A, _wave_, _width_]) * conv - else: - lo = gauss(band[0], [A, _wave_, _width_]) - hi = gauss(band[1], [A, _wave_, _width_]) - - # Just do a trapezoid - L_lines += 0.5 * (band[1] - band[0]) * (lo + hi) + for (_wave_, _lum_) in self.pf['pop_lum_per_sfr_at_wave']: - elif (band is not None): - # units_out is irrelevant in this case because we're integrating - # over `band` + if (band is not None): if (band[0] <= _wave_ <= band[1]): - L_lines = _lum_ + if 'erg/s/A' in units_out: + dlam = (max(band) - min(band)) + dnu = None + L_lines = _lum_ #/ dlam + #raise NotImplementedError('should deprecate this') + else: + dlam = None + dnu = (c * 1e8 / min(band)) - (c * 1e8 / max(band)) + L_lines = _lum_ #/ dnu else: continue elif (x is not None) and (abs(wave - _wave_) < R): @@ -2743,18 +2374,13 @@ def _get_lum_stellar_pop(self, z, x=1600, use_tabs=True, try: if use_tabs: iz = self.get_zindex(z) - sfr = self.tab_sfr[iz,:] - Ms = self.tab_fstar[iz,:] * self.halos.tab_M - #sfr = 10**(np.log10(self.tab_sfr[iz,:]) \ - # + self.get_sfr_sys(z=z, Mh=None)) - #Ms = 10**(np.log10(self.tab_fstar[iz,:] * self.halos.tab_M) \ - # + self.get_mstell_sys(z=z, Mh=None)) + sfr = 10**(np.log10(self.tab_sfr[iz,:]) \ + + self.get_sfr_sys(z=z, Mh=None)) + Ms = 10**(np.log10(self.tab_fstar[iz,:] * self.halos.tab_M) \ + + self.get_mstell_sys(z=z, Mh=None)) else: - sfr = self.get_sfr(z=z, Mh=self.halos.tab_M) - Ms = self.get_mstell(z=z, Mh=self.halos.tab_M) - #sfr = self.get_sfr_obs(z=z, Mh=self.halos.tab_M) - #Ms = self.get_mstell_obs(z=z, Mh=self.halos.tab_M) - + sfr = self.get_sfr_obs(z=z, Mh=self.halos.tab_M) + Ms = self.get_mstell_obs(z=z, Mh=self.halos.tab_M) except Exception as e: print(e) Ms = None @@ -2782,21 +2408,6 @@ def _get_lum_stellar_pop(self, z, x=1600, use_tabs=True, Lh = sfr * lum_per_sfr return Lh - elif self.pf['pop_lum_per_mass']: - # Assumed to be erg/s/Msun bolometric - lum_per_mass = self.pf['pop_lum_per_mass'] - - Lbol = Ms * lum_per_mass - - # Need to introduce SED modulation here - wave = self.src.get_ang_from_x(x, units=units) - - if units_out.lower() == 'erg/s/hz': - pass - else: - raise ValueError(f'unknown units={units_out}') - - return Lbol # or lookup table, in which case we need to interpolate elif self.pf['pop_lum_tab'] is not None: @@ -2843,6 +2454,7 @@ def _get_lum_stellar_pop(self, z, x=1600, use_tabs=True, return 10**np.interp(np.log10(Mh), np.log10(self.halos.tab_M), np.log10(Lh), left=0, right=0) + ## # Loop over components (most often just one) and determine L Lh = np.zeros_like(self.halos.tab_M, dtype=np.float64) @@ -2936,13 +2548,6 @@ def _get_lum_stellar_pop(self, z, x=1600, use_tabs=True, # We're definining f_ihl = L_ihl / (L_ihl + L_cen) _Lh_ *= (fihl / (1. - fihl)) - if (self.pf['pop_ihl_suppression'] is not None) or \ - (self.pf['pop_ihl_mask'] is not None): - fsupp = self.tab_fmask_ihl[iz,:] - #fsupp = self.get_ihl_suppression(z=z, - # Mh=self.halos.tab_M) - _Lh_ *= (1 - fsupp) - else: Ls = Ms * L_sfr _Lh_= self.get_lum_sat_tot(z, Ls, use_tabs=use_tabs) @@ -3100,19 +2705,11 @@ def get_lum(self, z, x=1600, use_tabs=True, cached_result = self._cache_L(*kwtup) if (cached_result is not None): - print('using cache') return cached_result ## # Have options for stars or BHs - if self.pf['pop_lum_func'] is not None: - Lh = self.pf['pop_lum_func'](z=z, Mh=self.halos.tab_M if Mh is None else Mh, - x=x, units=units, - units_out=units_out, band=band, pf=self.pf) - # Assume user has done all the legwork? Could later - # use same dust as host galaxies. - include_dust_transmission = False - elif self.pf['pop_star_formation']: + if self.pf['pop_star_formation']: Lh = self._get_lum_stellar_pop(z, x=x, use_tabs=use_tabs, band=band, window=window, units=units, units_out=units_out, load=load, raw=raw, @@ -3155,7 +2752,7 @@ def get_lum(self, z, x=1600, use_tabs=True, if (type(T) in numeric_types) or (T.size == 1): T = float(T) * np.ones_like(Lh) - if np.all(T == 1): + if np.all(T==1): pass elif np.all(T == 0): return np.zeros_like(Lh) @@ -3183,126 +2780,27 @@ def _get_Av(self): def _get_Av(self, value): self._get_Av_ = value - def get_Av(self, z, Ms=None, SFR=None, Mh=None): + def get_Av(self, z, Ms): """ Get visual extinction. """ if hasattr(self, '_get_Av_'): - return self._get_Av_(z=z, Ms=Ms, SFR=SFR, Mh=Mh) + return self._get_Av_(z=z, Ms=Ms) func = self._get_function('pop_Av') - return func(z=z, Ms=Ms, SFR=SFR, Mh=Mh) + return func(z=z, Ms=Ms) @cached_property def tab_Av(self): arr = np.zeros((self.halos.tab_z.size, self.halos.tab_M.size)) for i, z in enumerate(self.halos.tab_z): - Ms = self.get_mstell(z=z, Mh=self.halos.tab_M) - sfr = self.get_sfr(z=z, Mh=self.halos.tab_M) - arr[i,:] = self.get_Av(z, Ms=Ms, SFR=sfr, Mh=self.halos.tab_M) + Ms = self.get_mstell_obs(z=z, Mh=self.halos.tab_M) + arr[i,:] = self.get_Av(z, Ms) return arr - @cached_property - def tab_fmask_ihl(self): - self._tab_fmask_ihl = np.zeros((self.halos.tab_z.size, self.halos.tab_M.size)) - for i, z, in enumerate(self.halos.tab_z): - self._tab_fmask_ihl[i,:] = self.get_ihl_suppression(z=z, - Mh=self.halos.tab_M) - return self._tab_fmask_ihl - - def get_ihl_suppression(self, z, Mh): - """ - This function returns the fraction of IHL emission lost to masking. - """ - - # Option #1: suppression due to random loss of pixels from - # masking foreground/background galaxies. Probably shouldn't do this... - # Mkk will take care of this effect in practice, no? - if self.pf['pop_ihl_suppression'] is not None: - - n_per_deg, pix = self.pf['pop_ihl_suppression'] - - pix_per_deg = 3600.**2 / pix**2 - - fmask = np.ones_like(Mh) * n_per_deg / pix_per_deg - return np.minimum(1, fmask) - - # Option #2: loss of pixels would contribute to IHL but have - # subhalos in them that have been masked out. - elif (self.pf['pop_ihl_mask'] is not None): - - # Need to figure out how many satellites are brighter than mag - # cut as a function of Mh. - - # The value of this parameter is a list of two-element tuples, - # each element containing: - # (1) the occupation fraction, i.e., the fraction of (sub)halos that - # host a satellite, and (2) the fraction of those satellites bright - # enough to be masked out. It's a list because we can have - # different kinds of satellites. - # All of these quantities are (self.halos.tab_z, self.halos.tab_M) - - # To determine IHL suppression, we're going to compute the total - # projected area that's masked out, i.e., the integral over the - # number of sources * their projected size. For now we'll ignore - # the fact that we're probably masking out more "core IHL" since - # massive subhalos are likely centrally concentrated. - # We're also hard-coding a reasonable size in pixels for now. - - iz = self.get_zindex(z) - - # Shape of dndlnm_sub (centrals, satellites) - dndlnm_sub = self.halos.tab_dndlnm_sub[:,:] #/ self.halos.tab_M[:,None] - - num_mask = np.zeros_like(self.halos.tab_M) - for (focc, fmask) in self.pf['pop_ihl_mask']: - - # Need to integrate number of subhalos per central that will - # be masked. - ok = self.halos.tab_M >= self.get_Mmin(z) - for j, Mc in enumerate(self.halos.tab_M): - if not ok[j]: - continue - - _num = np.trapz( - dndlnm_sub[j,ok==1] * focc[iz,ok==1] * fmask[iz,ok==1], - x=np.log(self.halos.tab_M[ok==1])) - - num_mask += _num - - - # First, we compute the Virial radius of all halos and convert that - # to number of pixels. - # Then, we compute the suppression factor as the mask pixel density - # divided by the number of pixels for each source. - - # [kpc -> Mpc] - Rvir_mpc = self.halos.get_Rvir(z, M=self.halos.tab_M) / 1e3 - - # Convert Rvir to angle, convert from arcmin to arcsec - Rvir_ang = [self.cosm.get_angle_from_length_comoving(z, RR) * 60 \ - for RR in Rvir_mpc] - - # Area of central halos vs. mass in arcsec**2 - area_per_halo = 4 * np.pi * np.array(Rvir_ang)**2 - - # Assume for now that subhalos are all the same size - # (measured in pixels for now) - area_per_subh = self.pf['pop_ihl_mask_pix']**2 - - # - _flost = num_mask * area_per_subh / area_per_halo - flost = np.minimum(_flost, 1) - - # Ultimately, we're returning the fraction of IHL lost to masking. - return flost - - else: - return np.zeros_like(Mh) - def get_ihl(self, z, Mh): func = self._get_function('pop_ihl') return func(z=z, Mh=Mh) @@ -3461,23 +2959,9 @@ def tab_lum(self): return None # Read from file - if self.pf['pop_lum_tab_prefix'] is None: - fn = self.pf['pop_lum_tab'] - assert type(fn) is str - else: - fn = f"{self.pf['pop_lum_tab_prefix']}_sedtab" - T0 = self.pf['pop_lum_tab_T0'] - alpha = self.pf['pop_lum_tab_T0_alpha'] - if self.is_star_forming: - fn += f'pop_{self.is_quiescent}_mzr_{0:.0f}_obs' - fn += f'_T0_12_{T0:.1f}_alpha_{alpha:.2f}.hdf5' + assert type(self.pf['pop_lum_tab']) == str - else: - bb = self.pf['pop_sfr_below_ms{1}'] - fn += f'pop_{self.is_quiescent}_bb_{bb:.0f}_obs' - fn += f'_T0_12_{T0:.1f}_alpha_{alpha:.2f}.hdf5' - - with h5py.File(fn, 'r') as f: + with h5py.File(self.pf['pop_lum_tab'], 'r') as f: self._tab_lum_z = np.array(f[('z')]) self._tab_lum_Ms = np.array(f[('Ms')]) self._tab_lum_waves = np.array(f[('waves')]) @@ -3487,7 +2971,7 @@ def tab_lum(self): self._tab_lum[np.isinf(self._tab_lum)] = 0 if self.pf['verbose']: - print(f"# Loaded {fn}.") + print(f"# Loaded {self.pf['pop_lum_tab']}.") return self._tab_lum @@ -3625,8 +3109,12 @@ def _get_mask_general(self): tmp_mask[i,np.logical_and(Lh>0, Lh= self.get_Mmin(z), self.halos.tab_M < self.get_Mmax(z)) - - mask = np.logical_not(ok) #if self.pf['pop_halos'] is None: # Mh = self.halos.tab_M @@ -3794,7 +3278,7 @@ def _get_lf_lum(self, z, x=1600., window=1, raw=False, ## # Continue with standard approach. - iz = self.get_zindex(z) + iz = np.argmin(np.abs(z - self.halos.tab_z)) if abs(z - self.halos.tab_z[iz]) < ztol: dndm = self.halos.tab_dndm[iz,:] @@ -3806,13 +3290,11 @@ def _get_lf_lum(self, z, x=1600., window=1, raw=False, if self.is_central_pop: dndm = dndm * focc else: - dndm_func = interp1d(self.halos.tab_z, - self.halos.tab_dndm[:,:], + dndm_func = interp1d(self.halos.tab_z, self.halos.tab_dndm[:,:], axis=0, kind=self.pf['pop_interp_lf']) dndm = dndm_func(z) focc = self.get_focc(z=z, Mh=self.halos.tab_M) - if self.is_central_pop: dndm = dndm * focc @@ -3825,11 +3307,12 @@ def _get_lf_lum(self, z, x=1600., window=1, raw=False, # Figure out dM/dlogL factor. # Add a ghost zone to the low-L end of Lh. # Should we just compute L at bin edges in the future? + #Lh[Lh==0] = 1e-20 dL = np.diff(Lh) lnL = np.log(Lh) dlnL = np.diff(lnL) dlog10L = np.diff(np.log10(Lh)) - dmdlnL = np.diff(self.halos.tab_M_e) \ + dMh_dlnL = np.diff(self.halos.tab_M_e) \ / np.concatenate(([dlnL.min()], np.abs(dlnL))) dMh_dlog10L = np.diff(self.halos.tab_M_e) \ / np.concatenate(([dlog10L.min()], np.abs(dlog10L))) @@ -3837,19 +3320,17 @@ def _get_lf_lum(self, z, x=1600., window=1, raw=False, dlog10LdL = np.concatenate(([dlog10L[0]], np.abs(dlog10L))) \ / np.concatenate(([[dL[0]], np.abs(dL)])) - ## - # Central pops first if self.is_central_pop: - if (self.pf['pop_scatter_sfh'] > 0) or (self.pf['pop_scatter_sfr'] > 0): + #sigma_sfh = self.pf['pop_scatter_sfr'] + #sigma = self.pf['pop_scatter_sfh'] + if self.pf['pop_scatter_sfh'] > 0: + #_dx = self.halos.dlog10m - dndlnL = np.abs(dndm * dmdlnL) - if (self.pf['pop_scatter_sfh'] > 0): - sigma = self.pf['pop_scatter_sfh'] - else: - sigma = self.pf['pop_scatter_sfr'] - xx = mu = np.log(Lh) + dndlog10L = dndm * dMh_dlog10L + sigma = self.pf['pop_scatter_sfh'] + xx = mu = np.log10(Lh) xx[Lh==0] = 0 mu[Lh==0] = 0 @@ -3858,16 +3339,21 @@ def _get_lf_lum(self, z, x=1600., window=1, raw=False, # Arguments are just: x, mu, sigma pdf = lognormal(xx[None,:], mu[:,None], sigma) - # Integrate over halo mass (or really, ) axis + # Integrate over halo mass axis + _ok = np.logical_and(ok, Lh>0) - phi_tot = np.trapz(dndlnL[_ok==1,None] * pdf[_ok==1,:], x=lnL[_ok==1], - axis=0) + dndL = dndlog10L * dlog10LdL + phi_tot = np.trapz(dndlog10L[_ok==1,None] * pdf[_ok==1,:], + x=np.log10(Lh[_ok==1]), axis=0) + + mask = np.logical_not(ok) lum = np.ma.array(Lh, mask=mask) phi = np.ma.array(phi_tot, mask=mask, fill_value=-np.inf) - # Remember: phi is dn/dlnL - return lum, phi + # phi is dn/dlog10L, need to convert to dn/dlnL + # Recall dndlog10x = dndlnx / np.log(10.) + return lum, phi / np.log(10.) ## # Extra step if we're dealing with satellites @@ -3907,16 +3393,13 @@ def _get_lf_lum(self, z, x=1600., window=1, raw=False, #dndlog10L = dndlog10L_c * dndm_sub[:,i] * dMh_dlog10L[i] \ # * focc[i] * fsurv[i] - dndlog10L_sat[i] = np.trapz(integrand[ok==1], dx=self.halos.dlnm) + dndlog10L_sat[i] = np.trapz(integrand[ok==1], + dx=self.halos.dlnm) # - if (self.pf['pop_scatter_sfh'] > 0) or (self.pf['pop_scatter_sfr'] > 0): - if (self.pf['pop_scatter_sfh'] > 0): - sigma = self.pf['pop_scatter_sfh'] - else: - sigma = self.pf['pop_scatter_sfr'] - - xx = mu = np.log(Lh) + if self.pf['pop_scatter_sfh'] > 0: + sigma = self.pf['pop_scatter_sfh'] + xx = mu = np.log10(Lh) # Log-normal distribution of luminosity at given # halo mass, need to integrate over. @@ -3926,30 +3409,36 @@ def _get_lf_lum(self, z, x=1600., window=1, raw=False, ## # OK, we now know the number of subhalos globally as a # function of subhalo mass - + dndlog10L = dndlog10L_sat + _ok = np.logical_and(ok, Lh>0) # Integrate over halo mass axis - phi_tot = np.trapz(dndlog10L_sat[_ok==1,None] * pdf[_ok==1], - x=np.log(Lh[_ok==1]), axis=0) + phi_tot = np.trapz(dndlog10L[_ok==1,None] * pdf[_ok==1], + x=np.log10(Lh[_ok==1]), axis=0) mask = np.logical_not(ok) lum = np.ma.array(Lh, mask=mask) phi = np.ma.array(phi_tot, mask=mask, fill_value=-np.inf) - # Already in dn/dlog10(Mstell,sat) - return lum, phi + # Convert back to dn/dlnL from dn/dlog10L + return lum, phi / np.log(10.) else: ## # Replace dndm dndm = dndlog10L_sat / dMh_dlog10L - ## - # If we made it here, there's no scatter. Life is a bit easier. - # Still could be centrals or satellites but that's encoded in `dndm`. + # Only return stuff above Mmin + Mmin = self.get_Mmin(z) + Mmax = self.pf['pop_lf_Mmax'] + + phi_of_L = dndm * dMh_dlnL - phi_of_L = dndm * dmdlnL + above_Mmin = self.halos.tab_M >= Mmin + below_Mmax = self.halos.tab_M <= Mmax + ok = np.logical_and(above_Mmin, below_Mmax) + mask = self.mask = np.logical_not(ok) lum = np.ma.array(Lh, mask=mask) phi = np.ma.array(phi_of_L, mask=mask, fill_value=tiny_phi) @@ -4454,8 +3943,7 @@ def get_ssfr(self, z, Ms): else: _Ms = self.get_fstar(z=z, Mh=self.halos.tab_M) \ * self.halos.tab_M - Mh = np.interp(Ms, _Ms, self.halos.tab_M, - right=self.halos.tab_M.max()) + Mh = np.interp(Ms, _Ms, self.halos.tab_M, right=np.nan) return self.get_sfr(z=z, Mh=Mh) / Ms else: @@ -4490,7 +3978,7 @@ def tab_ssfr(self): @property def tab_sfr(self): """ - SFR tabulated as a function of redshift and halo mass. + SFR as a function of redshift and halo mass. ..note:: Units are Msun/yr. @@ -4993,10 +4481,9 @@ def get_smhm(self, **kwargs): if self.pf['pop_sfr_model'] in ['smhm-func']: return self.get_fstar(**kwargs) else: - return -np.inf + raise NotImplemented('help') def get_sfe(self, **kwargs): - """ Just a wrapper around `get_fstar`. """ return self.get_fstar(**kwargs) def get_fstar(self, **kwargs): @@ -5005,6 +4492,7 @@ def get_fstar(self, **kwargs): .. note :: Takes keyword arguments only (see below). + Parameters ---------- z : int, float @@ -5012,9 +4500,6 @@ def get_fstar(self, **kwargs): Mh : int, float, np.ndarray Halo mass(es) in Msun. - Returns - ------- - Star formation efficiency (dimensionless) as a function of halo mass. """ @@ -5332,7 +4817,7 @@ def _SAM_1z_jac(self, z, y): # pragma: no cover # Eq. 1: halo mass. _y1p = lambda _Mh: self.MGR(z, _Mh) * dtdz - y1p = derivative(_y1p, Mh) + y1p = nd.Derivative(_y1p)(Mh) # Eq. 2: gas mass if self.pf['pop_sfr'] is None: @@ -6599,7 +6084,7 @@ def get_ps_obs(self, scale, wave_obs1, wave_obs2=None, include_shot=True, pb = ProgressBar(scale.shape[0], use=use_pb and self.pf['progress_bar'], - name=f'p(k,{name}; pop #{self.id_num})') + name=f'p(k,{name})') pb.start() self._ps_obs_integrand = np.zeros((scale.size, zarr.size)) diff --git a/ares/populations/GalaxyEnsemble.py b/ares/populations/GalaxyEnsemble.py index f6d33df9d..358b9df8a 100644 --- a/ares/populations/GalaxyEnsemble.py +++ b/ares/populations/GalaxyEnsemble.py @@ -513,7 +513,7 @@ def generate_halo_histories(self): @property def histories(self): if not hasattr(self, '_histories'): - self._histories = self.generate_galaxy_histories() + self._histories = self.RunSAM() return self._histories @histories.setter @@ -538,16 +538,7 @@ def histories(self, value): self._histories = value - def get_histories(self): - """ - Return the entire growth histories for all halos for many quanties. - - The returned variable is a dictionary, with several fields that are - hopefully - """ - return self.histories - - def generate_galaxy_histories(self): + def RunSAM(self): """ Run models. If deterministic, will just return pre-determined histories. Otherwise, will do some time integration. @@ -665,7 +656,7 @@ def _TabulateEmissivity(self, x=None, band=None, units='Angstroms'): if (band is not None) and (x is not None): raise ValueError("You're being confusing! Supply `x` OR `band`") - hist = self.get_histories() + hist = self.histories tab = np.zeros_like(zarr) for i, z in enumerate(zarr): @@ -1477,10 +1468,10 @@ def _gen_prescribed_galaxy_histories(self, zstop=0): 'Mh': Mh, 'Mg': Mg, 'Z': Z, - #'bursty': zeros_like_Mh, + 'bursty': zeros_like_Mh, 'pos': pos, #'imf': np.zeros((Mh.shape[0], self.tab_imf_mc.size)), - #'Nsn': zeros_like_Mh, + 'Nsn': zeros_like_Mh, } if 'flags' in halos.keys(): @@ -2490,7 +2481,8 @@ def get_lum(self, z, x=1600., units='Angstroms', units_out='erg/s/Hz', window=window, load=load, units_out=units_out) ## - # Note: in this case, no additional transmission effects. + # Note: in this case, no additional transmission effects in this + # case. ## # Otherwise, doing our usual: stellar emission only. @@ -2505,20 +2497,6 @@ def get_lum(self, z, x=1600., units='Angstroms', units_out='erg/s/Hz', + " machinery is to allow for Charlot & Fall (2000)-like \n" \ + " approaches where reddening is age-dependent." - ## - # Check that we're not applying IGM transmission for ionizing - # photons. In this case, we're probably modeling reionization and - # so really want the ionizing luminosity BEFORE attenuation. - if include_igm_transmission: - if band is not None: - _band = self.src.get_ang_from_x(band, units=units) - assert np.all(np.array(_band) > 912), \ - "Should set include_igm_transmission=False for ionizing emission!" - else: - _x = self.src.get_ang_from_x(x, units=units) - assert np.all(_x > 912), \ - "Should set include_igm_transmission=False for ionizing emission!" - L = self.synth.get_lum(x=x, units=units, zobs=z, hist=self.histories, extras=self.extras, idnum=idnum, window=window, load=load, band=band, units_out=units_out) @@ -2828,28 +2806,32 @@ def get_lf(self, z, bins=None, use_mags=True, x=1600., units='Angstroms', Parameters ---------- + z: int, float Redshift of interest. use_mags : boolean if True: returns bin centers in AB magnitudes, whether absolute or apparent depends on value of `absolute` parameter. if False: returns bin centers in log(L / Lsun) + x : int, float Wavelength in Angstroms to be looked at. If wave > 3e5, then the luminosity function comes from the dust in the galaxies. + window : int Can alternatively retrive the average luminosity at specified wavelength after smoothing intrinsic spectrum with a boxcar window of this width (in pixels). + band : tuple Can alternatively request the average luminosity in some wavelength interval (again, rest wavelengths in Angstrom). + total_IR : boolean if False: returns luminosity function at the given wavelength if True: returns the total infrared luminosity function for wavelengths between 8 and 1000 microns. - Note: if True, ignores wave and band keywords, and always returns - in log(L / Lsun) + Note: if True, ignores wave and band keywords, and always returns in log(L / Lsun) """ if total_IR: @@ -2970,8 +2952,8 @@ def get_lf(self, z, bins=None, use_mags=True, x=1600., units='Angstroms', phi = hist / dbin relerr = abs(np.sum(phi * dbin) - N) / N - #assert relerr < 1e-2, \ - # "Error in number of galaxies! rel_err={:.5f}".format(relerr) + assert relerr < 1e-2, \ + "Error in number of galaxies! rel_err={:.5f}".format(relerr) #self._cache_lf_[(z, wave)] = x, phi @@ -3777,9 +3759,12 @@ def load(self): fn_hist = path + pref + '.' + suffix else: - # Check to see if parameters match - if self.pf['verbose']: - print("Should check that HMF parameters match!") + pass + # Check to see if parameters match. + # This is effectively handled now given how we name files + # with the cosmology_name and z/M dimensions/ranges. + #if self.pf['verbose']: + # print("Should check that HMF parameters match!") # Read output if type(fn_hist) is str: diff --git a/ares/populations/GalaxyPopulation.py b/ares/populations/GalaxyPopulation.py index 158b6ea86..772517f20 100644 --- a/ares/populations/GalaxyPopulation.py +++ b/ares/populations/GalaxyPopulation.py @@ -70,7 +70,7 @@ def GalaxyPopulation(pf=None, cosm=None, **kwargs): model = 'sfe-func' if model in ['sfe-func', 'sfr-func', 'mlf-func', 'sfe-tab', 'sfr-tab', - 'uvlf', '21cmfast', 'smhm-func', 'quiescent', 'lum-func']: + 'uvlf', '21cmfast', 'smhm-func', 'quiescent']: return GalaxyCohort(pf=pf, **kwargs) elif model in ['fcoll', 'sfrd-func', 'sfrd-class']: return GalaxyAggregate(pf=pf, **kwargs) diff --git a/ares/populations/Halo.py b/ares/populations/Halo.py index 5019666c6..23d35b1a8 100644 --- a/ares/populations/Halo.py +++ b/ares/populations/Halo.py @@ -101,7 +101,7 @@ def _init_fcoll(self, return_fcoll=False): self.pf['pop_fcoll'], self.pf['pop_dfcolldz'] @property - def get_mass_accretion_rate(self): + def MGR(self): """ Mass growth rate of halos of mass M at redshift z. @@ -129,7 +129,7 @@ def get_mass_accretion_rate(self): def MGR_integrated(self, z, source=None): """ The integrated DM accretion rate. -p + Parameters ---------- z : int, float diff --git a/ares/populations/Population.py b/ares/populations/Population.py index 5041e6b49..e6373a0a5 100644 --- a/ares/populations/Population.py +++ b/ares/populations/Population.py @@ -311,7 +311,8 @@ def is_sam(self): @property def is_diffuse(self): - return self.pf['pop_ihl'] is not None + return (self.pf['pop_ihl'] is not None) or \ + (self.pf['pop_include_1h'] and not self.pf['pop_include_shot']) @property def is_src_radio(self): @@ -527,9 +528,7 @@ def is_emissivity_scalable(self): if not hasattr(self, '_is_emissivity_scalable'): - if (self.pf['pop_scatter_sfh'] > 0) or \ - (self.pf['pop_scatter_sfr'] > 0) or \ - (self.pf['pop_scatter_smhm'] > 0): + if self.pf['pop_scatter_sfh'] > 0: self._is_emissivity_scalable = False return self._is_emissivity_scalable @@ -1175,7 +1174,7 @@ def get_sersic_cog(self, rmax, n): def tab_sersic_n(self): return np.arange(0.3, 6.25, 0.05) - def get_sersic_r_containing_lightfrac(self, frac, n): + def get_sersic_rmax(self, frac, n): """ Return the radius containing `frac` per-cent of the total surface brightness for a Sersic profile of index `n`. @@ -1273,11 +1272,10 @@ def get_tab_emissivity(self, z, E, use_pbar=True): pb = ProgressBar(z.size*len(E), use=self.pf['progress_bar'] * use_pbar, - name=f"ehat(z,{E.min():.2f} z: @@ -393,361 +328,342 @@ def get_zindex(self, z): return iz - def get_seed_kwargs(self, layer, logmlim, popid): + def get_catalog(self, zlim=None, logmlim=(11,12), popid=0, verbose=True): """ - Deterministically adjust the random seeds for the given redshift layer, - mass range, and population. + Get a galaxy catalog in (RA, DEC, redshift) coordinates. + + .. note :: This is essentially a wrapper around `_get_catalog_from_coeval`, + i.e., we're just figuring out how many chunks are needed along the + line of sight and re-generating the relevant cubes. Parameters ---------- - layer : int - ID number for given co-eval redshift `layer`. + zlim : tuple + Restrict redshift range to be between: + + zlim[0] <= z < zlim[1]. + logmlim : tuple - Min/mass log10(halo mass / Msun) range of interest. - popid : int - Population ID number. + Restrict halo mass range to be between: + + 10**logmlim[0] <= Mh/Msun 10**logmlim[1] Returns ------- - Dictionary of random seeds to use for halo masses, positions, - occupation, orientation, Sersic index.... + A tuple containing (ra, dec, redshift, ) """ + if zlim is None: + zlim = self.zlim - if not hasattr(self, '_seeds'): - # ARES ID, ARES parent ID, str representation of popid (e.g., '2a') - pid, pid_par, pid_str = get_pop_info(popid) - - fmh = int(logmlim[0] + (logmlim[1] - logmlim[0]) / 0.1) + zmin, zmax = zlim + mmin, mmax = 10**np.array(logmlim) - ze, zmid, Re = self.get_domain_info(zlim=self.zlim, Lbox=self.Lbox) + # Version of Lbox in actual cMpc + L = self.Lbox / self.sim.cosm.h70 - seed_rho = self.seed_rho \ - * np.arange(1, len(zmid)+1) - seed_mh = self.seed_halo_mass \ - * np.arange(1, len(zmid)+1) * fmh - seed_xyz = self.seed_halo_pos \ - * np.arange(1, len(zmid)+1) * fmh - seed_focc = self.seed_halo_occ \ - * np.arange(1, len(zmid)+1) * fmh + # First, get full domain info + ze, zmid, Re = self.get_domain_info(zlim=self.zlim, Lbox=self.Lbox) + Rc = bin_e2c(Re) + dz = np.diff(ze) - # These seeds uniquely determine the locations and masses - # of star-forming and quiescent centrals. - self._seeds = {'seed_box': seed_rho, - 'seed': seed_mh, 'seed_pos': seed_xyz, - 'seed_occ': seed_focc} + # Deterministically adjust the random seeds for the given mass range + # and redshift range. + #fmh = int(logmlim[0] + (logmlim[1] - logmlim[0]) / 0.1) - ## - # [optional] resolved galaxies - # Need `popid` here to ensure we use different seeds for the - # surface brightness profiles of quiescent galaxies. - if self.seed_profile is not None: - seed_prof = (self.seed_profile + popid) \ - * np.arange(1, len(zmid)+1) * fmh - self._seeds['seed_profile'] = seed_prof + # Figure out if we're getting the catalog of a single chunk + chunk_id = None + for i, Rlo in enumerate(zmid): + zlo, zhi = ze[i:i+2] - ## - # [optional] seeds for satellites - if self.seed_sats is not None: - seed_sats = self.seed_sats \ - * np.arange(1, len(zmid)+1) * fmh - self._seeds['seed_sats'] = seed_sats + if (zlo == zlim[0]) and (zhi == zlim[1]): + chunk_id = i + break - i = layer - # Done - return {key:self._seeds[key][i] for key in self._seeds.keys()} + ## + # Setup random seeds for random rotations and translations + np.random.seed(self.seed_rot) + r_rot = np.random.randint(0, high=4, size=(len(Re)-1)*3).reshape( + len(Re)-1, 3 + ) - def _get_flux_catalog(self, zlim, logmlim, red, Mh, channel, pid): - """ - Compute flux from catalog of sources in given redshift range. + np.random.seed(self.seed_tra) + r_tra = np.random.rand(len(Re)-1, 3) - Parameters - ---------- - zlim : tuple - Redshift range in which to sum fluxes. This is probably the - boundaries of a co-eval chunk. - red : np.ndarray - Redshifts of galaxies in catalog. - Mh : np.ndarray - Halo masses [Msun] of galaxies in catalog. - channel : tuple - Spectral channel edges in microns. + ## + # Print-out information about FOV + # arcmin / Mpc -> deg / Mpc + theta_zmin = self.sim.cosm.get_angle_from_length_comoving(zmin, 1) * L / 60. + theta_zmax = self.sim.cosm.get_angle_from_length_comoving(zmax, 1) * L / 60. - Returns - ------- - An array of fluxes corresponding to the halos in `red` and `Mh`, the - units are erg/s/cm^2/Angstrom. + pbar = ProgressBar(Rc.size, name=f"lc(z>={zmin},z<{zmax})", + use=chunk_id is None) + pbar.start() - """ - zlo, zhi = zlim - zsub_lo = 1 * zlo + ct = 0 + zlo = zmin * 1. + for i, Rlo in enumerate(Re[0:-1]): + pbar.update(i) - flux = np.zeros_like(Mh) - while zsub_lo < zhi: + zlo, zhi = ze[i:i+2] - zsub_hi = min(zsub_lo + self.dz_max, zhi) + if chunk_id is not None: + if i != chunk_id: + continue - zsub_mid = np.mean([zsub_lo, zsub_hi]) + if (zhi <= zlim[0]) or (zlo >= zlim[1]): + continue - band = channel[0] * 1e4 / (1. + zsub_mid), \ - channel[1] * 1e4 / (1. + zsub_mid) + seed_kwargs = self.get_seed_kwargs(i, logmlim) - okzsub = np.logical_and(red >= zsub_lo, red < zsub_hi) + # Contains (x, y, z, mass) + # Note that x, y, z are in cMpc / h units, not actual cMpc. + halos = self.get_halo_population(z=zmid[i], + mmin=mmin, mmax=mmax, verbose=verbose, popid=popid, + **seed_kwargs) - _flux_ = self.sim.pops[pid].get_lum(zsub_mid, x=None, - Mh=Mh[okzsub==1], units='Ang', - units_out='erg/s/Ang', band=tuple(band)) + if (type(halos[0]) != np.ndarray) and (halos[0] is None): + ra = dec = red = mass = None + continue - # Frequency "squashing", i.e., our 'per Angstrom' interval is - # different in the observer frame by a factor of 1+z. - corr = 1. / 4. / np.pi \ - / (np.interp(zsub_mid, self.tab_z, self.tab_dL) * cm_per_mpc)**2 - flux[okzsub==1] = _flux_ * corr / (1. + zsub_mid) + if (halos[0].size == 0): + ra = dec = red = mass = None + continue - zsub_lo += self.dz_max + # Might change later if we do domain decomposition + x0 = y0 = z0 = 0.0 + dx = dy = dz = self.Lbox - return flux + ## + # Perform random flips and translations here + if self.apply_rotations: - def _get_size_catalog(self, zlim, logmlim, red, Mh, pid): - """ - Return sizes and surface brightness profile info for a galaxy catalog. + _x_, _y_, _z_, _m_ = halos - Parameters - ---------- - zlim : tuple - Redshift range in which to sum fluxes. - red : np.ndarray - Redshifts of galaxies in catalog. - Mh : np.ndarray - Halo masses [Msun] of galaxies in catalog. + # Put positions in space centered on (0,0,0), i.e., + # [(-0.5 * dx, 0.5 * dx), (-0.5 * dy, 0.5 * dy), etc.] + # not [(x0,x0+dx), (y0,y0+dy), (z0,z0+dz)] + _x = _x_ - (x0 + 0.5 * dx) + _y = _y_ - (y0 + 0.5 * dy) + _z = _z_ - (z0 + 0.5 * dz) - Returns - ------- - A tuple containing the: - - Half-light radii of galaxies (in arcseconds) - - sersic indices - - ellipcities - - position angles + # This is just the format required by Rotation below. + _view = np.array([_x, _y, _z]).T - """ - Ms = self.sim.pops[pid].get_smhm(z=red, Mh=Mh) * Mh - Rkpc = self.pops[pid].get_size(z=red, Ms=Ms) + # Loop over axes + for k in range(3): - # Much faster to interpolate from table than generate angle/pMpc - # on the fly. Interpolant automatically used if provided R is 1 - arcsec_per_pmpc = 60 * self.sim.cosm.get_angle_from_length_proper( - red, 1. - ) - R_sec = arcsec_per_pmpc * Rkpc * 1e-3 + # Force new viewing angles to be orthogonal to box faces + r = r_rot[i,k] + _theta = angles_90[r] * np.pi / 180. - zlo, zhi = zlim - zall = self.get_redshift_layers(zlim=self.zlim) + axis = np.zeros(3) + axis[k] = 1 - ## - # Make sure `zlim` is in provided redshift layers. - # This is mostly to prevent users from doing something they shouldn't. - ilayer = np.argmin(np.abs(zlim[0] - zall[:,0])) + rot = Rotation.from_rotvec(_theta * axis) + _view = rot.apply(_view) - seed_kw = self.get_seed_kwargs(ilayer, logmlim, pid) + # Read in our new 'view' of the catalog, undo the shift + # so we're back in [(x0,x0+dx), (y0,y0+dy), (z0,z0+dz)] region. + _x, _y, _z = _view.T + _x += (0.5 * dx) + _y += (0.5 * dy) + _z += (0.5 * dz) - # `R_sec` is the angular size of each galaxy in the model in arcsec. - # Note: the size is defined as the stellar half-light radius. + halos = [_x, _y, _z, _m_] - # Uniform for now. - np.random.seed(seed_kw['seed_profile']) + else: + pass - # Sersic indices and position angles - pop_s = 'sfg' if self.pops[pid].is_star_forming else 'qg' + ## + # Random translations + if self.apply_translations: + _x_, _y_, _z_, _m_ = halos - # First, identify redshift interval to use. - zoptions = self.profile_info[f'{pop_s}_z'] - z1, z2 = np.array(zoptions).T + # Put positions in space centered on (0,0,0), i.e., + # [(-0.5 * dx, 0.5 * dx), (-0.5 * dy, 0.5 * dy), etc.] + # not [(x0,x0+dx), (y0,y0+dy), (z0,z0+dz)] + _x = _x_.copy() + _y = _y_.copy() + _z = _z_.copy() - # Make sure `iz` gets redshift within appropriate window - iz = np.argmin(np.abs(zlo - z1)) - if zlo < z1[iz]: - iz -= 1 + _x += r_tra[i,0] * dx + overx = _x > dx + _x[overx] = _x[overx] - dx - # If provided redshift is > max redshift in profile_info, just use - # highest available redshift. - if zlo > z2.max(): - iz = -1 + _y += r_tra[i,1] * dy + overy = _y > dy + _y[overy] = _y[overy] - dy - key = zoptions[iz] + _z += r_tra[i,2] * dz + overz = _z > dz + _z[overz] = _z[overz] - dz - # Axis ratios first - ba_loc, ba_scale = self.profile_info[f'{pop_s}_ba'][key] + halos = [_x, _y, _z, _m_] - ba_trunc_lo = 0.1 - ba_trunc_hi = 1 - ba_t_lo = (ba_trunc_lo - ba_loc) / ba_scale - ba_t_hi = (ba_trunc_hi - ba_loc) / ba_scale + else: + pass - rv_ba = truncnorm(ba_t_lo, ba_t_hi, loc=ba_loc, scale=ba_scale) - b_over_a = rv_ba.rvs(size=Rkpc.size) + ## + # Convert to (ra, dec, redshift) coordinates. + # Note: the conversion from cMpc/h to cMpc occurs inside + # _get_catalog_from_coeval here: + _ra, _de, _red = self._get_catalog_from_coeval(halos, zlo=zlo) + _m = halos[-1] + + okr = np.logical_and(_ra < 0.5 * theta_zmin, + _ra > -0.5 * theta_zmin) + okd = np.logical_and(_de < 0.5 * theta_zmin, + _de > -0.5 * theta_zmin) + ok = np.logical_and(okr, okd) + + # Cache intermediate outputs too! + #self._cache_cats[(zlo, zhi, mmin)] = \ + # _ra[ok==1], _de[ok==1], _red[ok==1], _m[ok==1] + + #_ra, _de, _red, _m = self._cache_cats[(zlo, zhi, mmin)] + + if ct == 0: + ra = _ra.copy() + dec = _de.copy() + red = _red.copy() + mass = _m.copy() + else: + ra = np.hstack((ra, _ra)) + dec = np.hstack((dec, _de)) + red = np.hstack((red, _red)) + mass = np.hstack((mass, _m)) - # Now Sersic indices - n_loc, n_scale = self.profile_info[f'{pop_s}_n'][key] + ct += 1 - n_trunc_lo = 0.2 - n_trunc_hi = 7 - n_t_lo = (n_trunc_lo - n_loc) / n_scale - n_t_hi = (n_trunc_hi - n_loc) / n_scale + del _ra, _de, _red, halos, okr, okd, ok, _m + if self.apply_rotations or self.apply_translations: + del _x, _x_, _y, _y_, _z, _z_, _m_ - rv_n = truncnorm(n_t_lo, n_t_hi, loc=n_loc, scale=n_scale) - nsers = rv_n.rvs(size=Rkpc.size) + if self.mem_concious: + gc.collect() - # Ellipticity = 1 - b/a - ellip = 1 - b_over_a + pbar.finish() - pa = np.random.random(size=Rkpc.size) * 360 + #self._cache_cats[(zmin, zmax, mmin)] = ra, dec, red, mass - return R_sec, nsers, ellip, pa + return ra, dec, red, mass - def _get_postage_stamp_pix(self, R, psize): + def _get_catalog_from_coeval(self, halos, zlo=0.2): """ - Determine the pixel indices for a postage stamp image. + Make a catalog in lightcone coordinates (RA, DEC, redshift). - Parameters - ---------- - R : int, float - Size of object in pixels. - psize : int, float - Size of postage stamp in units of `R`, which is probably a - half-light radius or virial radius. + .. note :: RA and DEC output in degrees. - Returns - ------- - Essentially the results of a meshgrid call, with a third quantity - that indicates the radius of the postage stamp in number of pixels. """ - if not hasattr(self, '_cache_pstamp_pix_'): - self._cache_pstamp_pix_ = {} + xmpc, ympc, zmpc, mass = halos - # Determine how big of a postage stamp image to make in - # number of pixels (just scale R_eff by `psize`) - # (Force to be odd) - _r_ = np.ceil(psize * R) - if _r_ % 2 == 0: - _r_ += 1 + # Shift coordinates to +/- 0.5 * Lbox + xmpc = (xmpc - 0.5 * self.Lbox) / self.sim.cosm.h70 + ympc = (ympc - 0.5 * self.Lbox) / self.sim.cosm.h70 - # Load from cache if possible. numpy's `meshgrid` can be slow. - if _r_ in self._cache_pstamp_pix_: - return self._cache_pstamp_pix_[_r_] + # Don't shift zmpc at all, z0 is the front face of the box - # Pixel coordinates - xy = np.arange(-_r_, _r_ + 1, 1, dtype=int) - xx, yy = np.meshgrid(xy, xy, indexing='ij') + # First, get redshifts + #if not self.sim.cosm.interpolate: + # zarr = np.arange(0, 10, 0.01) + # #dofz = self._mf.cosmo.comoving_distance(zarr).to_value() + # #angl = self._mf.cosmo.arcsec_per_kpc_comoving(zarr).to_value() + # dofz = np.array([self.sim.cosm.get_dist_los_comoving(0, z) \ + # for z in zarr]) / cm_per_mpc + # # arcmin / Mpc -> deg / Mpc + # angl = np.array([self.sim.cosm.get_length_comoving_from_angle(z, 1) \ + # for z in zarr]) / 60. - self._cache_pstamp_pix_[_r_] = xx, yy, _r_ + # Move the front edge of the box to redshift `z0` + # Will automatically use interpolation under the hood in `cosm` + # if interpolate_cosmology_in_z=True. + d0 = self.sim.cosm.get_dist_los_comoving(0, zlo) / cm_per_mpc - return xx, yy, _r_ - - def _get_ihl_postage_stamp(self, _r_, Rarr, Rtab, Stab, iM): - """ - Because the projected NFW profile is tabulated, we use this simple - wrapper to first check if we've already interpolated to a postage - stamp of size `_r_` - """ - if not hasattr(self, '_cache_ihl_pstamp_'): - self._cache_ihl_pstamp_ = {} + # Translate LOS distances to redshifts. + #if self.sim.cosm.interpolate: + # red = np.interp(zmpc / self.sim.cosm.h70 + d0, + # self.sim.cosm._tab_dR_co / cm_per_mpc, + # self.sim.cosm.tab_z) + # deg_per_mpc = np.interp(zmpc / self.sim.cosm.h70 + d0, + # self.sim.cosm._tab_dR_co / cm_per_mpc, + # self.sim.cosm._tab_deg_per_cmpc / 60.) + #else: + dofz = self.sim.cosm._tab_dist_los_co / cm_per_mpc + angl = self.sim.cosm._tab_ang_from_co / 60. + red = np.interp(zmpc / self.sim.cosm.h70 + d0, dofz, + self.sim.cosm.tab_z) - if (_r_, iM) in self._cache_ihl_pstamp_: - return self._cache_ihl_pstamp_[(_r_, iM)] + # Conversion from physical to angular coordinates + deg_per_mpc = np.interp(zmpc / self.sim.cosm.h70 + d0, dofz, angl) - I = np.interp(np.log10(Rarr), np.log10(Rtab), Stab[iM,:]) + ra = xmpc * deg_per_mpc + dec = ympc * deg_per_mpc - self._cache_ihl_pstamp_[(_r_, iM)] = I + return ra, dec, red - return I + def thin_sample(self, max_sources=None): - def _get_postage_stamp_slices(self, pstamp, buffer, i, j): - nx, ny = pstamp.shape - - # OK, now we need to figure out how to slot this postage - # stamp into the entire image. Mostly just tedium like - # worrying about sources near the edge of the frame. - - # `i` and `j` refer to pixels in the full frame image - # Here, we're figuring out the chunk of the full frame - # into which we'll drop our postage stamp - slcx = slice(max(i-(nx-1)//2, 0), i+(nx-1)//2 + 1) - slcy = slice(max(j-(ny-1)//2, 0), j+(ny-1)//2 + 1) - # i.e., this is where we're sticking the postage stamp - # If we're unlucky and near the edge, we need to also - # slice the `pstamp`. - - # If source spills off x-axis, adjust postage stamp - # accordingly (i.e., remove a few columns) - if (slcx.start == 0): - xlo = abs(i-(nx-1)//2) - else: - xlo = 0 - if (slcx.stop > buffer.shape[0]): - xhi = -(slcx.stop - buffer.shape[0]) - else: - xhi = None - - if (slcy.start == 0): - ylo = abs(j-(ny-1)//2) - else: - ylo = 0 + if (max_sources is not None): + if (ct == 0) and (max_sources >= Mh.size): + # In this case, we can accommodate all the galaxies in + # the catalog, so don't do anything yet. + pass + else: + # Flag entries until we hit target. + # This is not efficient but oh well. + for h in range(Mh.size): + ok[h] = 0 - if (slcy.stop > buffer.shape[1]): - yhi = -(slcy.stop - buffer.shape[1]) - else: - yhi = None + if ok.sum() == max_sources: + break - slcx2 = slice(xlo, xhi) - slcy2 = slice(ylo, yhi) + # This will be the final iteration. + if ct + ok.sum() == max_sources: + self._hit_max_sources = True - return slcx, slcy, slcx2, slcy2 + #def get_base_dir(self, fov, pix): + # """ + # Generate the name for the root directory where all mocks for a given + # model will go. - def get_pix_mesh(self, fov, pix, in_mpc=0): - """ - Get - """ - if not hasattr(self, '_cache_pix_mesh_'): - self._cache_pix_mesh_ = {} + # Our model is: - if not in_mpc: - if (fov, pix, in_mpc) in self._cache_pix_mesh_.keys(): - return self._cache_pix_mesh_[(fov, pix, in_mpc)] + # ->_fov__pix__L_N/ + # -> README - ra_e, ra_c, dec_e, dec_c = self.get_pixels(fov, pix=pix) - pix_deg = pix / 3600. + # Inside this directory, there will be many subdirectories: one for each + # spectral channel of interest. + # There will also be a series of .fits (or .hdf5) files, which represent + # "final" maps, i.e., those that are summed over redshift and mass chunks, + # and also summed over all source populations. - rr, dd = np.meshgrid(ra_c / pix_deg, dec_c / pix_deg, - indexing='ij') + # """ - self._cache_pix_mesh_[(fov, pix, in_mpc)] = rr, dd - return rr, dd - ## - # Slightly harder case + # s = '{}/{}_fov_{:.1f}_pix_{:.1f}_L{:.0f}_N{:.0f}'.format(path, + # self.prefix, fov, pix, self.Lbox, self.dims) - mpc_per_arcmin = self.sim.cosm.get_angle_from_length_comoving(zmid, - pix / 60.) + # if suffix is None: + # print("# WARNING: might be worth providing `suffix` as additional identifier.") + # else: + # s += f'_{self.model_name}' - rr, dd = np.meshgrid(ra_c * 60 * mpc_per_arcmin, - dec_c * 60 * mpc_per_arcmin, - indexing='ij') + # return s - #@njit(parallel=True) + #@profile def get_map(self, fov, pix, channel, logmlim, zlim, popid=0, - include_galaxy_sizes=False, null_beyond_size=np.inf, size_cut=0.5, dlam=20., - use_pbar=True, verbose=False, wave_units='um', - logmlim_sats=(11,15), buffer=None, nthreads=None, batch_size=10, - postage_stamp=5, **kwargs): + include_galaxy_sizes=False, size_cut=0.5, dlam=20., + use_pbar=True, verbose=False, max_sources=None, buffer=None, **kwargs): """ - Get a map for a single channel, redshift layer, mass layer, and + Get a map for a single channel, redshift chunk, mass chunk, and source population. .. note :: To get a 'full' map, containing contributions from multiple - redshift and mass layers, and potentially populations, see the + redshift and mass chunks, and potentially populations, see the wrapper routine `generate_maps`. Parameters @@ -761,10 +677,6 @@ def get_map(self, fov, pix, channel, logmlim, zlim, popid=0, zlim : tuple, list, np.ndarray Optional redshift range. If None, will include all objects in the catalog. - postage_stamp : int, float - If provided, and `include_galaxy_sizes==True`, this is the size of - image (in units of R_eff) on which we'll create each galaxy's - surface brightness profile, to then by slotted into the full image. Returns ------- @@ -775,26 +687,21 @@ def get_map(self, fov, pix, channel, logmlim, zlim, popid=0, """ pix_deg = pix / 3600. + #sr_per_pix = pix_deg**2 / sqdeg_per_std assert fov * 3600 / pix % 1 == 0, \ "FOV must be integer number of pixels wide!" # In degrees if type(fov) in numeric_types: - fov_2d = np.array([fov]*2) - else: - fov_2d = fov - - assert np.diff(fov_2d) == 0, "Only square FOVs allowed right now." + fov = np.array([fov]*2) - zall = self.get_redshift_layers(zlim=self.zlim) + assert np.diff(fov) == 0, "Only square FOVs allowed right now." - ## - # Make sure `zlim` is in provided redshift layers. - # This is mostly to prevent users from doing something they shouldn't. - ilayer = np.argmin(np.abs(zlim[0] - zall[:,0])) + zall = self.get_redshift_chunks(zlim=self.zlim) + assert zlim in zall - assert np.allclose(zlim, zall[ilayer]) + ichunk = zall.index(zlim) # Figure out the edges of the domain in RA and DEC (degrees) # Pixel coordinates @@ -802,375 +709,209 @@ def get_map(self, fov, pix, channel, logmlim, zlim, popid=0, Npix = [ra_c.size, dec_c.size] - # Unpack popid more [as of March 2025] - # (id number in ARES, parent ID number [if satellite], name as str) - pid, pid_par, pid_str = get_pop_info(popid) - - zlo, zhi = zlim - zmid = np.mean([zlo, zhi]) - - seed_kw = self.get_seed_kwargs(ilayer, logmlim, pid) - # Initialize empty map img = buffer + #if buffer is not None: + # img = buffer + #elif save_intermediate: + # img = np.zeros([len(zall)] + Npix, dtype=np.float64) + #else: + # img = np.zeros([1] + Npix, dtype=np.float64) ## - # First, check for a pre-existing catalog in this channel. - fn_cat_ch = self.get_cat_fn(fov, pix, channel, popid, - logmlim=logmlim, zlim=(zlo, zhi), wave_units=wave_units) - - if os.path.exists(fn_cat_ch): - - ra, dec, red, flux = self._load_cat(fn_cat_ch) - - # Figure out what pixel each source is in - ra_bin = np.searchsorted(ra_e, ra, side='right') - dec_bin = np.searchsorted(dec_e, dec, side='right') - ra_ind = ra_bin - 1 - de_ind = dec_bin - 1 - - # Internally, these fluxes are always in - # erg/s/cm^2/Ang, but then integrated over channel. - # Will need channel width in Hz to recover specific - # intensities averaged over band. - nu = c * 1e4 / np.mean(channel) - dnu = c * 1e4 * (channel[1] - channel[0]) / np.mean(channel)**2 - - _dat = self._get_flux_catalog(zlayer, logmlim, _red, _Mh, - channel, pid) - flux *= 1. / (self.get_map_norm(cat_units) / dnu) - else: - # Run fresh if we didn't find anything - ra, dec, red, Mh, parents = self.get_catalog_halos( - zlim=(zlo, zhi), logmlim=logmlim, popid=popid, verbose=verbose, - satellites=self.sim.pops[pid].is_satellite_pop, - logmlim_sats=logmlim_sats) - - # Could be empty layers for very massive halos and/or early times. - if ra is None: - return #None, None, None - - # Correct for field position. Always (0,0) for log-normal boxes, - # may not be for halo catalogs from sims. - ra -= self.fxy[0] - dec -= self.fxy[1] + # Might take awhile. + #pb = ProgressBar(len(zall), + # name="img(z; Mh>={:.1f}, Mh<{:.1f})".format(logmlim[0], logmlim[1]), + # use=use_pbar) + #pb.start() - ## - # Figure out which bin each galaxy is in. - # Slightly faster than np.digitize - ra_bin = np.searchsorted(ra_e, ra, side='right') - dec_bin = np.searchsorted(dec_e, dec, side='right') - mask_ra = np.logical_or(ra_bin == 0, ra_bin == Npix[0]+1) - mask_de = np.logical_or(dec_bin == 0, dec_bin == Npix[1]+1) - ra_ind = ra_bin - 1 - de_ind = dec_bin - 1 - - # Mask out galaxies that aren't in our desired image plane. - okp = np.logical_not(np.logical_or(mask_ra, mask_de)) - - # Filter out galaxies outside specified redshift range. - # [usually don't do this within layer, but hey, functionality there] - if zlim is not None: - okz = np.logical_and(red >= zlo, red < zhi) - ok = np.logical_and(okp, okz) - else: - okz = None - ok = okp - - # May have empty layers, e.g., very massive halos and/or very - # high redshifts. - if not np.any(ok): - return #None, None, None - - ## - # Isolate OK entries. - ra = ra[ok==1] - dec = dec[ok==1] - red = red[ok==1] - Mh = Mh[ok==1] - ra_ind = ra_ind[ok==1] - de_ind = de_ind[ok==1] - - # Need to filter `parents` also - if self.sim.pops[pid].is_satellite_pop: - parents = parents[ok==1] - else: - # parents is None in this case - pass + # Track max_sources + _hit_max_sources = False - # Shape of (ra, dec, red) is just (Ngalaxies) + ct = 0 - # Get flux from each object. Units = erg/s/cm^2/Ang. - flux = self._get_flux_catalog((zlo, zhi), logmlim, red, Mh, channel, pid) + zlo, zhi = zlim ## - # Need some extra info to do more sophisticated modeling... - ## - mpc_per_arcmin = self.sim.cosm.get_angle_from_length_comoving(zmid, 1) - - resolved_sources = False - - # Extended emission from IHL - if self.sim.pops[pid].is_diffuse and include_galaxy_sizes: - resolved_sources = True - - Rall = self.sim.pops[0].halos.tab_R_nfw - Rvir = self.sim.pops[0].halos.get_Rvir(zmid, Mh) / 1e3 # kpc->Mpc - _iz = np.argmin(np.abs(zmid - self.sim.pops[pid].halos.tab_z)) - - # Remaining dimensions (Mh, R) - Sall = self.sim.pops[pid].halos.tab_Sigma_nfw[_iz,:,:] - Mall = self.sim.pops[pid].halos.tab_M + # Loop over redshift chunks and assemble image. + #for _iz_, (zlo, zhi) in enumerate(zall): - R_pix = R_X = Rvir * 60 / mpc_per_arcmin / pix + # if _hit_max_sources: + # break - # Pixel coordinates in RA and DEC - if postage_stamp is None: - rr, dd = np.meshgrid(ra_c * 60 * mpc_per_arcmin, - dec_c * 60 * mpc_per_arcmin, - indexing='ij') + # if (zhi <= zlim[0]) or (zlo >= zlim[1]): + # continue + _z_ = np.mean([zlo, zhi]) - elif include_galaxy_sizes: - resolved_sources = True + # if save_intermediate: + # iz = _iz_ + # else: + # iz = 0 - assert self.profile_info is not None, \ - "Must supply `profile_info` at initialization!" + seed_kw = self.get_seed_kwargs(ichunk, logmlim) - R_sec, nsers, ellip, pa = self._get_size_catalog(zlim, logmlim, - red, Mh, pid) + ra, dec, red, Mh = self.get_catalog(zlim=(zlo, zhi), + logmlim=logmlim, popid=popid, verbose=verbose) - Rvir = self.sim.pops[0].halos.get_Rvir(zmid, Mh) / 1e3 # kpc->Mpc + # Could be empty chunks for very massive halos and/or early times. + if ra is None: + return #None, None, None - ## - # Next, impose effective stopping criterion in size where we - # stop painting on Sersic profiles and just dump all photons - # in a single pixel. - # - - # Will paint anything with a half-light radius greater than a pixel - if size_cut == 0.5: - R_X = R_sec - # General option: paint anything with size, defined as the - # radius containing `size_cut` fraction of the light, that - # exceeds a pixel. - elif size_cut == 1: - R_X = np.inf # ensures detailed model for every galaxy + ## + # Figure out which bin each galaxy is in. + ra_bin = np.digitize(ra, bins=ra_e) + dec_bin = np.digitize(dec, bins=dec_e) + mask_ra = np.logical_or(ra_bin == 0, ra_bin == Npix[0]+1) + mask_de = np.logical_or(dec_bin == 0, dec_bin == Npix[1]+1) + ra_ind = ra_bin - 1 + de_ind = dec_bin - 1 + + # Mask out galaxies that aren't in our desired image plane. + okp = np.logical_not(np.logical_or(mask_ra, mask_de)) + + # Filter out galaxies outside specified redshift range. + # [usually don't do this within chunk, but hey, functionality there] + if zlim is not None: + okz = np.logical_and(red >= zlo, red < zhi) + ok = np.logical_and(okp, okz) + else: + okz = None + ok = okp + + # For debugging and tests, we can dramatically limit the + # number of sources. Thin out the herd here. + if (max_sources is not None): + if (ct == 0) and (max_sources >= Mh.size): + # In this case, we can accommodate all the galaxies in + # the catalog, so don't do anything yet. + pass else: - # e.g., if size_cut == 0.9, we'll find the radius containing - # 90% of the light for a given galaxy, and if that radius is - # bigger than a pixel, we'll model its profile. - rcut = [self.sim.pops[pid].get_sersic_r_containing_lightfrac( - size_cut, nsers[h]) for h in range(R_sec.size)] - - # `rcut` is in units of the half-light radius, so we need - # to multiply by `R_sec` to obtain the size in arcseconds. - R_X = np.array(rmax) * R_sec + # Flag entries until we hit target. + # This is not efficient but oh well. + for h in range(Mh.size): + ok[h] = 0 - ## - # R_X here is still in arcseconds, will get converted to pixels - # below. + if ok.sum() == max_sources: + break - # Size in degrees - R_deg = R_sec / 3600. - # Size in pixels (`pix_deg` is the pixel scale in degrees) - R_pix = R_deg / pix_deg + # This will be the final iteration. + if ct + ok.sum() == max_sources: + _hit_max_sources = True - # R_X is the threshold size of an object we'll model in detail. - # - R_X /= (3600 * pix_deg) - - # All in degrees - x0, y0 = ra, dec - a, b = R_deg, R_deg - - # Pixel coordinates in RA and DEC - if postage_stamp is None: - rr, dd = np.meshgrid(ra_c / pix_deg, dec_c / pix_deg, - indexing='ij') + #if self.verbose: + # print("Masked fraction: {:.5f}".format((ok.size - ok.sum()) / float(ok.size))) - ## - # Shorthand for later - x_0 = ra / pix_deg - y_0 = dec / pix_deg - theta = pa * np.pi / 180. + # May have empty chunks, e.g., very massive halos and/or very + # high redshifts. + if not np.any(ok): + return #None, None, None - b_n = gammaincinv(2. * nsers, 0.5) - a, b = R_pix, (1 - ellip) * R_pix - cos_theta, sin_theta = np.cos(theta), np.sin(theta) - # + # Increment counter + ct += ok.sum() ## - # Accelerated approach if not doing resolved sources - if (not resolved_sources): - _flux_ = None - _img_, _xe_, _ye_ = np.histogram2d(ra, dec, - bins=(ra_e, dec_e), weights=flux) - - # Recall that `img` is a buffer to be incremented - img += _img_ - else: + # Isolate OK entries. + ra = ra[ok==1] + dec = dec[ok==1] + red = red[ok==1] + Mh = Mh[ok==1] + ra_ind = ra_ind[ok==1] + de_ind = de_ind[ok==1] + + # Get geometrical dilution factor + corr = 1. / 4. / np.pi \ + / (np.interp(red, self.tab_z, self.tab_dL) * cm_per_mpc)**2 + + # Get flux from each object. Units = erg/s/cm^2/Ang. + # Already accounting for geometrical dilution but provided at + # rest wavelengths, so must divide by (1+z) to get flux in observer + # frame. + + # Find bounding wavelength range to limit memory consumption, i.e., + # don't grab rest-frame SED outside of range needed by observer. + # This really only helps if the user has instituted a cut in + # redshift that eliminates a significant fraction of any chunk. + _zlo = zlim[0] if zlim is not None else red.min() + _zhi = zlim[1] if zlim is not None else red.max() + _wlo = channel[0] * 1e4 / (1. + min(red.max(), _zhi)) + _whi = channel[1] * 1e4 / (1. + max(red.min(), _zlo)) + + # [waves] = Angstroms rest-frame, [seds] = erg/s/A. + # Shape of seds is (N galaxies, N wavelengths) + # Shape of (ra, dec, red) is just (Ngalaxies) + #waves = np.arange(_wlo, _whi+dlam, dlam) + + x = np.array([np.mean(channel) * 1e4 / (1. + _z_)]) + band = (channel[0] * 1e4 / (1. + _z_), channel[1] * 1e4 / (1. + _z_)) + #dfreq = (c * 1e8 / min(band)) - (c * 1e4 / max(band)) + #dlam = band[1] - band[0] + # Need to supply band or window? + # Note: NOT using get_spec_obs because every object has a + # slightly different redshift, want more precise fluxes. + + seds = self.sim.pops[popid].get_lum(_z_, x, Mh=Mh, units='Ang', + units_out='erg/s/Ang', band=tuple(band)) + + # `owaves` is still in Angstroms + #owaves = waves[None,:] * (1. + red[:,None]) + + # Frequency "squashing", i.e., our 'per Angstrom' interval is + # different in the observer frame by a factor of 1+z. + #flux = corr[:,None] * seds[:,:] / (1. + red[:,None]) + flux = seds * corr / (1. + red) - ## - # Actually sum fluxes from all objects in image plane. - for h in range(ra.size): - - # Where this galaxy lives in pixel coordinates - i, j = ra_ind[h], de_ind[h] - - # Grab the flux - _flux_ = flux[h] - - # HERE: account for fact that galaxies aren't point sources. - # [optional] - if self.sim.pops[pid].is_diffuse and include_galaxy_sizes and (R_X[h] >= 1): - # Interpolate between tabulated solutions. - iM = np.argmin(np.abs(Mh[h] - Mall)) - - if postage_stamp is not None: - xx, yy, _r_ = self._get_postage_stamp_pix(R_pix[h], postage_stamp) - - # This is in pixels, need to convert to cMpc before - # interpolating - Rarr = np.sqrt(xx**2 + yy**2) * (pix / 60.) \ - * mpc_per_arcmin - - I = self._get_ihl_postage_stamp(_r_, Rarr, Rall, Sall, iM) - - # OK, now need to drop into full image - slcx, slcy, slcx2, slcy2 = \ - self._get_postage_stamp_slices(I, img, i, j) - - else: - # Image of distances from halo center - r0 = ra_c[i] * 60 * mpc_per_arcmin - d0 = dec_c[j] * 60 * mpc_per_arcmin - Rarr = np.sqrt((rr - r0)**2 + (dd - d0)**2) - - # In Msun/cMpc^3 - I = np.interp(np.log10(Rarr), np.log10(Rall), Sall[iM,:]) - - # Optional: hard cut at large radius. - I[Rarr >= null_beyond_size * Rvir[h]] = 0 - - tot = I.sum() - - if postage_stamp is not None: - img[slcx,slcy] += _flux_ * I[slcx2,slcy2] \ - / I[slcx2,slcy2].sum() - elif tot == 0: - img[i,j] += _flux_ - else: - img[:,:] += _flux_ * I / tot - - elif include_galaxy_sizes and (R_X[h] >= 1): - - if postage_stamp is not None: - - xx, yy, _r_ = self._get_postage_stamp_pix(R_pix[h], postage_stamp) - - # This is in pixels, need to convert to cMpc before - # interpolating - Rarr = np.sqrt(xx**2 + yy**2) * (pix / 60.) \ - * mpc_per_arcmin - - # Put galaxies at the center of the postage stamp, hence - # no (xx - x_0) factors, just xx - x_maj = xx * cos_theta[h] + yy * sin_theta[h] - x_min = -xx * sin_theta[h] + yy * cos_theta[h] - #z = np.sqrt((x_maj / a) ** 2 + (x_min / b) ** 2) - zsq = (x_maj / a[h])**2 + (x_min / b[h])**2 - - # Fractional contribution to total flux - pstamp = np.exp(-b_n[h] * (zsq**(1. / nsers[h] / 2.) - 1)) - - slcx, slcy, slcx2, slcy2 = \ - self._get_postage_stamp_slices(pstamp, img, i, j) - - I = pstamp - - else: - Rarr = np.sqrt((rr - x_0[h])**2 + (dd - y_0[h])**2) - - x_maj = (rr - x_0[h]) * cos_theta[h] \ - + (dd - y_0[h]) * sin_theta[h] - x_min = -(rr - x_0[h]) * sin_theta[h] \ - + (dd - y_0[h]) * cos_theta[h] - #z = np.sqrt((x_maj / a) ** 2 + (x_min / b) ** 2) - zsq = (x_maj / a[h])**2 + (x_min / b[h])**2 - - # Fractional contribution to total flux - I = np.exp(-b_n[h] * (zsq**(1. / nsers[h] / 2.) - 1)) - - # Optional: hard cut at large radius. - I[Rarr >= null_beyond_size * Rvir[h]] = 0 - - # Get total flux - tot = I.sum() - - if postage_stamp is not None: - img[slcx,slcy] += _flux_ * pstamp[slcx2,slcy2] \ - / pstamp[slcx2,slcy2].sum() - elif tot == 0 or R_X[h] < 1: - img[i,j] += _flux_ - else: - img[:,:] += _flux_ * I / tot - - ## - # Otherwise just add flux to single pixel - else: - img[i,j] += _flux_ - - ## - # Clear out some memory sheesh - del flux, _flux_, ra, dec, red, Mh, ok, okp, okz, ra_ind, de_ind, \ - mask_ra, mask_de - if self.mem_concious: - gc.collect() - - def _get_map_from_cat(self, fov, pix, ra, dec, red, flux, pid, - include_galaxy_sizes): ## # Need some extra info to do more sophisticated modeling... ## - raise NotImplemented('help') - - ra_e, ra_c, dec_e, dec_c = self.get_pixels(fov, pix=pix) - - # Extended emission from IHL - if self.sim.pops[pid].is_diffuse and include_galaxy_sizes: + # Extended emission from IHL, satellites + if (not self.sim.pops[popid].is_central_pop): Rmi, Rma = -3, 1 dlogR = 0.25 Rall = 10**np.arange(Rmi, Rma+dlogR, dlogR) - _iz = np.argmin(np.abs(zmid - self.sim.pops[pid].halos.tab_z)) + if max_sources == 1: + + Sall = self.sim.pops[popid].halos.get_halo_surface_dens( + _z_, Mh[0], Rall + ) + + Sall = np.array([Sall]) + + Mall = Mh + else: + _iz = np.argmin(np.abs(_z_ - self.sim.pops[popid].halos.tab_z)) - # Remaining dimensions (Mh, R) - Sall = self.sim.pops[pid].halos.tab_Sigma_nfw[_iz,:,:] - Mall = self.sim.pops[pid].halos.tab_M + # Remaining dimensions (Mh, R) + Sall = self.sim.pops[popid].halos.tab_Sigma_nfw[_iz,:,:] + Mall = self.sim.pops[popid].halos.tab_M - mpc_per_arcmin = self.sim.cosm.get_angle_from_length_comoving(zmid, + mpc_per_arcmin = self.sim.cosm.get_angle_from_length_comoving(_z_, pix / 60.) rr, dd = np.meshgrid(ra_c * 60 * mpc_per_arcmin, - dec_c * 60 * mpc_per_arcmin, - indexing='ij') + dec_c * 60 * mpc_per_arcmin) elif include_galaxy_sizes: - assert self.profile_info is not None, \ - "Must supply `profile_info` at initialization!" + Ms = self.sim.pops[popid].get_smhm(z=red, Mh=Mh) * Mh + Rkpc = self.pops[popid].get_size(z=red, Ms=Ms) - R_sec, nsers, ellip, pa = self._get_size_catalog(zlim, logmlim, - red, Mh, pid) + R_sec = np.zeros_like(Rkpc) + for kk in range(red.size): + R_sec[kk] = self.sim.cosm.get_angle_from_length_proper(red[kk], Rkpc[kk] * 1e-3) + R_sec *= 60. - ## - # Next, impose effective stopping criterion in size where we - # stop painting on Sersic profiles and just dump all photons - # in a single pixel. - # + # Uniform for now. + np.random.seed(seed_kw['seed_nsers']) + nsers = np.random.random(size=Rkpc.size) * 5.9 + 0.3 + np.random.seed(seed_kw['seed_pa']) + pa = np.random.random(size=Rkpc.size) * 360 + + # Ellipticity = 1 - b/a + ellip = np.random.random(size=Rkpc.size) # Will paint anything half-light radius greater than a pixel if size_cut == 0.5: @@ -1179,8 +920,13 @@ def _get_map_from_cat(self, fov, pix, ra, dec, red, flux, pid, # radius containing `size_cut` fraction of the light, that # exceeds a pixel. else: - rmax = [self.sim.pops[pid].get_sersic_rmax(size_cut, - nsers[h]) for h in range(R_sec.size)] + rarr = np.logspace(-1, 1.5, 500) + #cog_sfg = [self.sim.pops[popid].get_sersic_cog(r, + # n=nsers[h]) \ + # for r in rarr] + + rmax = [self.sim.pops[popid].get_sersic_rmax(size_cut, + nsers[h]) for h in range(Rkpc.size)] R_X = np.array(rmax) * R_sec @@ -1196,8 +942,7 @@ def _get_map_from_cat(self, fov, pix, ra, dec, red, flux, pid, x0, y0 = ra, dec a, b = R_deg, R_deg - rr, dd = np.meshgrid(ra_c / pix_deg, dec_c / pix_deg, - indexing='ij') + rr, dd = np.meshgrid(ra_c / pix_deg, dec_c / pix_deg) ## # Actually sum fluxes from all objects in image plane. @@ -1214,7 +959,7 @@ def _get_map_from_cat(self, fov, pix, ra, dec, red, flux, pid, # HERE: account for fact that galaxies aren't point sources. # [optional] - if self.sim.pops[pid].is_diffuse and include_galaxy_sizes: + if not self.sim.pops[popid].is_central_pop: # Image of distances from halo center r0 = ra_c[i] * 60 * mpc_per_arcmin @@ -1235,8 +980,6 @@ def _get_map_from_cat(self, fov, pix, ra, dec, red, flux, pid, else: img[:,:] += _flux_ * I / tot - #print(f"doing IHL, _flux_={_flux_}, tot={tot}") - elif include_galaxy_sizes and R_X[h] >= 1: model_SB = Sersic2D(amplitude=1., r_eff=R_pix[h], @@ -1248,15 +991,6 @@ def _get_map_from_cat(self, fov, pix, ra, dec, red, flux, pid, I = model_SB(rr, dd) tot = I.sum() - ## - # Test: null flux from beyond 4 R_e - #dr = np.sqrt((rr - ra[h] / pix_deg)**2 \ - # + (dd - dec[h] / pix_deg)**2) - #beyond_edges = dr > 8 * R_pix[h] - #I[beyond_edges==1] = 0 - - #print('hi', h, R_pix[h], I.sum()) - if tot == 0: img[i,j] += _flux_ else: @@ -1269,13 +1003,13 @@ def _get_map_from_cat(self, fov, pix, ra, dec, red, flux, pid, ## # Clear out some memory sheesh - del flux, _flux_, ra, dec, red, Mh, ok, okp, okz, ra_ind, de_ind, \ - mask_ra, mask_de + del seds, flux, _flux_, ra, dec, red, Mh, ok, okp, okz, ra_ind, de_ind, \ + mask_ra, mask_de, corr if self.mem_concious: gc.collect() - def get_output_dir(self, fov, pix, zlim, logmlim=None, force_chunk=False): - fn = f"{self.base_dir}/fov_{fov:.1f}"#/pix_{pix:.1f}" + def get_output_dir(self, fov, pix, zlim, logmlim=None): + fn = f"{self.base_dir}/fov_{fov:.1f}/pix_{pix:.1f}" fn += f"/box_{self.Lbox:.0f}/dim_{self.dims:.0f}" fn += f"/{self.model_name}" fn += f"/zmin_{self.zmin:.3f}" @@ -1283,17 +1017,9 @@ def get_output_dir(self, fov, pix, zlim, logmlim=None, force_chunk=False): # Need directory for zmax, logmlim range final = (zlim[0] == self.zlim[0]) and (zlim[1] == self.zlim[1]) - # [new] Check if this redshift range spans more than one layer. - # BUT: don't count if final=True, since the definition of final - # is 100% of the layers - all_zchunks = self.get_redshift_layers(self.zlim) - ilo = np.argmin(np.abs(zlim[0] - all_zchunks[:,0])) - ihi = np.argmin(np.abs(zlim[1] - all_zchunks[:,1])) - is_chunk = (force_chunk or (ihi > ilo)) and (not final) - # - if final or is_chunk: - fn += f"/zmax_{self.zlim[1]:.3f}" + if final: + fn += f"/zmax_{zlim[1]:.3f}" if logmlim is not None: fn += f"/m_{logmlim[0]:.2f}_{logmlim[1]:.2f}" else: @@ -1301,56 +1027,36 @@ def get_output_dir(self, fov, pix, zlim, logmlim=None, force_chunk=False): if logmlim is not None: fn += f'/m_{logmlim[0]:.2f}_{logmlim[1]:.2f}' - # - if is_chunk: - fn += f'/z_{zlim[0]:.3f}_{zlim[1]:.3f}' - # Everything should exist up to the m_??.??_??.?? subdirectory if not os.path.exists(fn): - path = Path(fn) - path.mkdir(parents=True) + os.mkdir(fn) return fn def get_map_fn(self, fov, pix, channel, popid, logmlim=None, zlim=None, - fmt='fits', wave_units='um', force_chunk=False, - include_galaxy_sizes=False): + fmt='fits'): """ - Return filename expected for map with given properties. + """ save_dir = self.get_output_dir(fov=fov, pix=pix, - zlim=zlim, logmlim=logmlim, force_chunk=force_chunk) - - pid, pid_parent, pid_str = get_pop_info(popid) - - fn = f'{save_dir}/map_{channel[0]:.3f}_{channel[1]:.3f}_{wave_units}_pop_{pid_str}' + zlim=zlim, logmlim=logmlim) - if include_galaxy_sizes: - if popid in [4, '4']: - fn += '_prof_nfw' - else: - fn += '_prof_sers' - else: - fn += '_prof_delt' + fn = '{}/map_{:.3f}_{:.3f}_pop_{:.0f}'.format(save_dir, + channel[0], channel[1], popid) return fn + '.' + fmt def get_cat_fn(self, fov, pix, channel, popid, logmlim=None, zlim=None, - fmt='fits', wave_units='um'): + fmt='fits'): """ - Return filename expected for catalog with given properties. + """ save_dir = self.get_output_dir(fov=fov, pix=pix, zlim=zlim, logmlim=logmlim) - pid, pid_parent, pid_str = get_pop_info(popid) - - if type(channel) in [tuple, list, np.ndarray]: - fn = f'{save_dir}/cat_{channel[0]:.3f}_{channel[1]:.3f}_{wave_units}_pop_{pid_str}' - else: - fn = f'{save_dir}/cat_{channel}_pop_{pid_str}' + fn = f'{save_dir}/cat_{channel}_pop_{popid:.0f}' return fn + '.' + fmt @@ -1372,7 +1078,7 @@ def get_README(self, fov, pix, zlim=None, logmlim=None, hdr += "# Note: all wavelengths here are in microns.\n" hdr += "#" * 78 hdr += "\n" - hdr += "# channel name; central wavelength; " + hdr += "# channel name [optional]; central wavelength; " hdr += "channel lower edge; channel upper edge; " hdr += "population ID; filename \n" @@ -1393,72 +1099,10 @@ def generate_lightcone(self, fov, pix, channels): """ pass - def _filter_by_fov(self, ok): - """ - - """ - - ids_in = np.arange(ok.size, dtype=int) - ids_out = [] - - ct = 0 - for id in ids_in: - if ok[id]: - ids_out.append((id, ct)) - else: - continue - - ct += 1 - - ids_out = np.array(ids_out, dtype=int) - - return ids_out - - def _refresh_sat_ids(self, ids_in, ids_out, parents_in): - """ - Initially we record the parent ID of satellites as the index of the - parent in a particular layer BEFORE any FoV filtering. After filtering, - we must adjust the indices accordingly. This routine figures out the - mapping between indices before and after FoV filtering. - - Parameters - ---------- - ids_in : np.ndarray - Indices of central halos BEFORE filtering on FoV. - ids_out : np.ndarray - Final indices of central halos. - parents_in : np.ndarray - Indices corresponding to parent ID of each satellite BEFORE - the FoV filter. - - Returns - ------- - Tuple containing: (new parent IDs AFTER FoV filter, mask indicating which - centrals in original catalog were filtered out by FoV cut). Note that - the length of these two arrays will be different anytime some > 0 - number of halos are filtered out by the FoV cut. - """ - - p_out = [] - cen_ok = [] - for i, p_in in enumerate(parents_in): - # Means that the parent of this satellite ended up outside the FoV - if p_in not in ids_in: - cen_ok.append(0) - continue - - i_out = np.argwhere(p_in == ids_in).squeeze() - new_id = ids_out[i_out] - p_out.append(new_id) - cen_ok.append(1) - - return np.array(p_out, dtype=int), np.array(cen_ok) - def generate_cats(self, fov, pix, channels, logmlim, dlogm=0.5, zlim=None, include_galaxy_sizes=False, dlam=20, path='.', channel_names=None, - suffix=None, fmt='fits', hdr={}, wave_units='um', - cat_units='uJy', keep_layers=False, logmlim_sats=(11,15), - include_pops=[0], clobber=False, verbose=False, dryrun=False, + suffix=None, fmt='fits', hdr={}, max_sources=None, cat_units='uJy', + include_pops=None, clobber=False, verbose=False, dryrun=False, use_pbar=True, **kwargs): """ Generate galaxy catalogs. @@ -1481,10 +1125,11 @@ def generate_cats(self, fov, pix, channels, logmlim, dlogm=0.5, zlim=None, zlim=self.zlim, logmlim=logmlim) # At least save halo mass since we get it for free. - if (channels is None): + if (channels is None) or (channels == ['Mh']): + run_phot = False channels = ['Mh'] - # Override cat_units - cat_units = 'Msun' + else: + run_phot = True if channel_names is None: channel_names = channels @@ -1499,19 +1144,22 @@ def generate_cats(self, fov, pix, channels, logmlim, dlogm=0.5, zlim=None, if zlim is None: zlim = self.zlim + if include_pops is None: + include_pops = range(0, len(self.sim.pops)) + assert fov * 3600 / pix % 1 == 0, \ "FOV must be integer number of pixels wide!" npix = int(fov * 3600 / pix) - zlayers = self.get_redshift_layers(self.zlim) + zchunks = self.get_redshift_chunks(self.zlim) zcent, ze, Re = self.get_domain_info(self.zlim) - mlayers = self.get_mass_layers(logmlim, dlogm) + mchunks = self.get_mass_chunks(logmlim, dlogm) - all_layers = self.get_layers(channels, logmlim, dlogm=dlogm, + all_chunks = self.get_layers(channels, logmlim, dlogm=dlogm, include_pops=include_pops, channel_names=channel_names) # Progress bar - pb = ProgressBar(len(all_layers), + pb = ProgressBar(len(all_chunks), name="cat(Mh>={:.1f}, Mh<{:.1f}, z>={:.3f}, z<{:.3f})".format( logmlim[0], logmlim[1], zlim[0], zlim[1]), use=use_pbar) @@ -1520,48 +1168,22 @@ def generate_cats(self, fov, pix, channels, logmlim, dlogm=0.5, zlim=None, ## # Start doing work. ct = 0 - tracker = {0: np.zeros((len(zlayers), len(mlayers)), dtype=int), - 1: np.zeros((len(zlayers), len(mlayers)), dtype=int)} - - Nlayers = len(zlayers) * len(mlayers) - tracker_flat = {0: [None] * Nlayers, 1: [None] * Nlayers} - tracker_flat[0][0] = 0 - tracker_flat[1][0] = 0 ra = [] dec = [] red = [] dat = [] - parh = [] - for h, layer in enumerate(all_layers): - - # Unpack info about this layer - popid, channel, chname, zlayer, mlayer = layer - - # Just used for file naming - field_names = ['ra', 'dec', 'z', channel] - field_units = ['deg', 'deg', '', cat_units] - - # Retrieve info about population: - # ARES ID, parent ID (in ARES), `popid` as string - pid, pid_par, pid_str = get_pop_info(popid) - - # Short-hand needed below - zlo, zhi = zlayer + for h, chunk in enumerate(all_chunks): - # Get number of z layer - iz = np.digitize(zlayer.mean(), bins=zlayers[:,0]) - 1 + # Unpack info about this chunk + popid, channel, chname, zchunk, mchunk = chunk - # Get number of M layer - im = np.argmin(np.abs(mlayer[0] - mlayers[:,0])) - - izm = iz * len(mlayers) + im + # Get number of z chunk + iz = zchunks.index(zchunk) # See if we already finished this map. - # Note that if this file exists, it's guaranteed that the - # corresponding ra, dec, and redshift catalogs are done too. fn = self.get_cat_fn(fov, pix, channel, popid, - logmlim=mlayer, zlim=zlayer, wave_units=wave_units) + logmlim=mchunk, zlim=zchunk) pb.update(h) @@ -1581,285 +1203,123 @@ def generate_cats(self, fov, pix, channels, logmlim, dlogm=0.5, zlim=None, else: # Get basic halo properties - _ra, _dec, _red, _Mh, _parents = \ - self.get_catalog_halos(zlim=zlayer, - logmlim=mlayer, popid=popid, verbose=verbose, - satellites=self.sim.pops[pid].is_satellite_pop, - logmlim_sats=logmlim_sats) - - # Should be able to cache this, no? Just until we get - # to the next redshift and/or mass bin? - # Or, read from catalog? I/O can be slow... - - # Could be empty layers for very massive halos and/or early times. - if (_ra is None) or (len(_ra) == 0): + _ra, _dec, _red, _Mh = self.get_catalog(zlim=zchunk, + logmlim=mchunk, popid=popid, verbose=verbose) + + # Could be empty chunks for very massive halos and/or early times. + if _ra is None: # You might think: let's `continue` to the next iteration! # BUT, if we do that, and we're really unlucky and this - # happens on the last layer of work for a given channel, + # happens on the last chunk of work for a given channel, # then no checkpoint will be written below :/ # Hence the use of `pass` here intead. - if (izm < Nlayers - 1): - tracker_flat[pid_par][izm+1] = tracker_flat[pid_par][izm] - - tracker[pid_par][iz,im] = 0 - - _parents = [] + pass else: - - # Correct for field position. Always (0,0) for log-normal boxes, - # may not be for halo catalogs from sims. - _ra -= self.fxy[0] - _dec -= self.fxy[1] - # Hack out galaxies outside our requested lightcone. ok = np.logical_and(np.abs(_ra) < fov / 2., np.abs(_dec) < fov / 2.) + # Limit number of sources, just for testing. + if (max_sources is not None): + if (ct == 0) and (max_sources >= _Mh.size): + # In this case, we can accommodate all the galaxies in + # the catalog, so don't do anything yet. + pass + else: + # Flag entries until we hit target. + # This is not efficient but oh well. + for _h in range(_Mh.size): + ok[_h] = 0 + + if ok.sum() == max_sources: + break + + # This will be the final iteration. + if ct + ok.sum() == max_sources: + self._hit_max_sources = True + + # Isolate OK entries. _ra = _ra[ok==1] _dec = _dec[ok==1] _red = _red[ok==1] _Mh = _Mh[ok==1] - # Handle satellites - if self.sim.pops[pid].is_satellite_pop: - if ok.sum(): - _parents = _parents[ok==1] - - _ra_c, _dec_c, _red_c, _Mh_c, _parents_c = \ - self.get_catalog_halos(zlim=zlayer, - logmlim=mlayer, popid=popid, verbose=verbose) - - # Problem: `_parents` are indices generated within - # each layer, need to be incremented so that - # elements point to the right central in the - # FINAL halo catalog. So, we need to increment by - # the number of halos up to but NOT including - # this layer. - - ok_c = np.logical_and(np.abs(_ra_c) < fov / 2., - np.abs(_dec_c) < fov / 2.) - - tracker[pid_par][iz,im] = ok_c.sum() - - if izm == 0: - Ncen = 0 - else: - Ncen = tracker_flat[pid_par][izm] + ct += ok.sum() - # Prep for next iteration - if (izm < Nlayers - 1) and (tracker_flat[pid_par][izm+1] is None): - tracker_flat[pid_par][izm+1] = ok_c.sum() \ - + tracker_flat[pid_par][izm] + ra.extend(list(_ra)) + dec.extend(list(_dec)) + red.extend(list(_red)) - if ok_c.sum(): - ids_in, ids_out = self._filter_by_fov(ok_c).T + ## + # Unpack channel info + # Could be name of field, e.g., 'Mh', 'SFR', 'Mstell', + # photometric info, e.g., ('roman', 'F087'), + # or special quantities like Ly-a EW or luminosity. + # Note: if pops[popid] is a GalaxyEnsemble object + if channel in ['Mh', 'Ms', 'SFR']: + _dat = _Mh + elif channel.lower().startswith('ew'): + raise NotImplemented('help') + else: + cam, filt = channel.split('_') - # Need to worry about satellites being ok - # but their centrals being not OK. - _parents, cen_ok = \ - self._refresh_sat_ids(ids_in, ids_out, _parents) + _filt, mags = self.sim.pops[popid].get_mags(zcent[iz], + absolute=False, cam=cam, filters=[filt], + Mh=_Mh) - if not np.all(cen_ok): - _ra = _ra[cen_ok==1] - _dec = _dec[cen_ok==1] - _red = _red[cen_ok==1] - _Mh = _Mh[cen_ok==1] + if cat_units == 'mags': + _dat = np.atleast_1d(mags.squeeze()) + elif 'jy' in cat_units.lower(): + flux = 3631. * 10**(mags / -2.5) - if ok_c.sum() > 0: - _parents += Ncen + if cat_units.lower() == 'jy': + _dat = np.atleast_1d(flux.squeeze()) + elif cat_units.lower() in ['microjy', 'ujy']: + _dat = np.atleast_1d(1e6 * flux.squeeze()) else: - _parents = _ra = _dec = _red = _Mh = [] - - # Done dealing with scenario in which >0 satellites - # are (at least initially) `ok`. - else: - # This means there aren't any satellites - # in the FoV. - _parents = _ra = _dec = _red = _Mh = [] - if (izm < Nlayers - 1): - tracker_flat[pid_par][izm+1] = \ - tracker_flat[pid_par][izm] - tracker[pid_par][iz,im] = 0 - - ## - # Done with satellites - if len(_parents) != len(_ra): - print('wtf', popid, izm, len(_parents), len(_ra)) - input('') - - ct += ok.sum() - - if len(_ra) > 0: - ra.extend(list(_ra)) - dec.extend(list(_dec)) - red.extend(list(_red)) - - if self.sim.pops[pid].is_satellite_pop: - parh.extend(list(_parents)) - - if len(_parents) != len(_ra): - print('wtf 2', popid, izm, len(_parents), len(_ra)) - input('') - - ## - # Unpack channel info - # Could be name of field, e.g., 'Mh', 'SFR', 'Mstell', - # photometric info, e.g., ('roman', 'F087'), - # or special quantities like Ly-a EW or luminosity. - # Note: if pops[popid] is a GalaxyEnsemble object - if type(channel) in [tuple, list, np.ndarray]: - # Internally, these fluxes are always in - # erg/s/cm^2/Ang, but then integrated over channel. - # Will need channel width in Hz to recover specific - # intensities averaged over band. - nu = c * 1e4 / np.mean(channel) - dnu = c * 1e4 * (channel[1] - channel[0]) / np.mean(channel)**2 - - _dat = self._get_flux_catalog(zlayer, logmlim, _red, _Mh, - channel, pid) - _dat *= self.get_map_norm(cat_units) / dnu - elif channel in ['Mh']: - _dat = _Mh - elif channel in ['parents']: - _dat = _parents - elif channel.lower().startswith('ew'): - raise NotImplemented('help') - elif channel.lower() == 'sfr': - _dat = self.sim.pops[pid].get_sfr(z=_red, Mh=_Mh) - elif channel.lower() in ['ms', 'mstell']: - raise NotImplemented('help') - elif channel.lower() in ['ellip', 'nsers', 'pa', 'r50']: - R_sec, nsers, ellip, pa = self._get_size_catalog(zlim, - logmlim, _red, _Mh, pid) - - _dat_dict = {'r50': R_sec, 'nsers': nsers, - 'ellip': ellip, 'pa': pa} - - _dat = _dat_dict[channel.lower()] + raise NotImplemented('help') else: - cam, filt = channel.split('_') - - raise NotImplemented('do we need to do this anymore?') - - ## - # Once again, in general need to sub-cycle through z - # to preserve accuracy. - zsub_lo = 1 * zlo - - mags = np.inf * np.ones(_Mh.size) - while zsub_lo < zhi: + raise NotImplemented('Unrecognized `cat_units`.') - zsub_hi = min(zsub_lo + self.dz_max, zhi) - - zsub_mid = np.mean([zsub_lo, zsub_hi]) - - okzsub = np.logical_and(_red >= zsub_lo, - _red < zsub_hi) - - _filt, out = \ - self.sim.pops[pid].get_mags(zsub_mid, - absolute=False, cam=cam, filters=[filt], - Mh=_Mh[okzsub==1]) + ## + # Save + self.save_cat(fn, (_ra, _dec, _red, _dat), + channel, zchunk, mchunk, + fov, pix=pix, fmt=fmt, hdr=hdr, + cat_units=cat_units, + clobber=clobber, verbose=verbose) - # There's a meaningless second dimension here - # because get_mags can report mags for multiple - # filters at once, we're just not doing that here. - mags[okzsub==1] = out[:,0] - zsub_lo += self.dz_max - if cat_units == 'mags': - _dat = np.atleast_1d(mags.squeeze()) - elif 'jy' in cat_units.lower(): - flux = 3631. * 10**(mags / -2.5) - - if cat_units.lower() == 'jy': - _dat = np.atleast_1d(flux.squeeze()) - elif cat_units.lower() in ['microjy', 'ujy']: - _dat = np.atleast_1d(1e6 * flux.squeeze()) - else: - raise NotImplemented('help') - else: - raise NotImplemented('Unrecognized `cat_units`.') - - ## - # Save - if keep_layers: - - for ff, field in enumerate([_ra, _dec, _red, _dat]): - # e.g., `parents` field for centrals is None - if field in [[], None]: - continue - - fn_ff = self.get_cat_fn(fov, pix, field_names[ff], - popid, logmlim=mlayer, zlim=zlayer, - wave_units=wave_units) - self.save_cat(fn_ff, field, field_names[ff], - zlayer, mlayer, fov, pix=pix, fmt=fmt, hdr=hdr, - cat_units=field_units[ff], - clobber=clobber, verbose=verbose) - - ## - # This is just because all datasets will be arrays if - # they contain entries. If there are no entries, _dat - # will be either an empty list or None. The latter - # case is what we're trying to avoid here since - # len(None) = error. - if (type(_dat) == np.ndarray): - dat.extend(list(_dat)) - else: - pass - ## - # len(_ra) == 0, i.e., no halos to do anything with - else: - pass + dat.extend(list(_dat)) # End of else block that generates new catalog if one isn't found. - # Back to level of loop over layers of work. + # Back to level of loop over chunks of work. ## - # Figure out if we're done with all the layers - if h == len(all_layers) - 1: - done_w_chan_or_pop = True + # Figure out if we're done with all the chunks + if h == len(all_chunks) - 1: + done_w_chan = True else: - done_w_chan_or_pop = np.logical_or( - channel != all_layers[h+1][1], - popid != all_layers[h+1][0]) + done_w_chan = channel != all_chunks[h+1][1] # If we're done with this channel, save file containing # full redshift and mass range. - # Only reason we do np.all here is because a spectral channel will - # be a 2-element tuple. - if np.all(done_w_chan_or_pop): - #_fn = self.get_cat_fn(fov, pix, channel, popid, - # logmlim=logmlim, zlim=self.zlim, fmt=fmt) - - - for ff, field in enumerate([ra, dec, red, dat]): - # e.g., `parents` field for centrals is None - if field in [[], None]: - continue - - if field_names[ff] == 'parents': - if len(field) != len(ra): - print('wtf 3', popid, logmlim, len(parents), len(ra)) - input('') - - _fn_ff = self.get_cat_fn(fov, pix, field_names[ff], popid, - logmlim=logmlim, zlim=self.zlim, fmt=fmt, wave_units=wave_units) + if done_w_chan: + _fn = self.get_cat_fn(fov, pix, channel, popid, + logmlim=logmlim, zlim=self.zlim, fmt=fmt) - self.save_cat(_fn_ff, field, - field_names[ff], self.zlim, logmlim, - fov, pix=pix, fmt=fmt, hdr=hdr, cat_units=field_units[ff], - clobber=clobber, verbose=verbose) + self.save_cat(_fn, (ra, dec, red, dat), + channel, self.zlim, logmlim, + fov, pix=pix, fmt=fmt, hdr=hdr, cat_units=cat_units, + clobber=clobber, verbose=verbose) - del ra, dec, red, dat, parh + del ra, dec, red, dat dat = [] ra = [] dec = [] red = [] - parh = [] pb.finish() @@ -1867,229 +1327,80 @@ def generate_cats(self, fov, pix, channels, logmlim, dlogm=0.5, zlim=None, # Done return - def get_layers(self, channels, logmlim, dlogm=0.5, include_pops=[0], + def get_layers(self, channels, logmlim, dlogm=0.5, include_pops=None, channel_names=None): """ Take a list of channels, populations, and bounds in halo mass, - and construct a list of layers of work to do of the form: + and construct a list of chunks of work to do of the form: - all_layers = [ - (popid, channel, chname, zlayer, mlayer), - (popid, channel, chname, zlayer, mlayer), - (popid, channel, chname, zlayer, mlayer), - (popid, channel, chname, zlayer, mlayer), + all_chunks = [ + (popid, channel, chname, zchunk, mchunk), + (popid, channel, chname, zchunk, mchunk), + (popid, channel, chname, zchunk, mchunk), + (popid, channel, chname, zchunk, mchunk), ... ] Basically this allows us to 'flatten' a series of for loops over - spectral channels, populations, redshift, and mass layers into + spectral channels, populations, redshift, and mass chunks into a single loop. Just unpack as, e.g., - >>> all_layers = self.get_layers(channels, logmlim, dlogm=dlogm, + >>> all_chunks = self.get_layers(channels, logmlim, dlogm=dlogm, >>> include_pops=include_pops) - >>> for layer in all_layers: - >>> popid, channel, chname, zlayer, mlayer = layer + >>> for chunk in all_chunks: + >>> popid, channel, chname, zchunk, mchunk = chunk >>> """ - zlayers = self.get_redshift_layers(self.zlim) - mlayers = self.get_mass_layers(logmlim, dlogm) - players = include_pops + if include_pops is None: + include_pops = range(0, len(self.sim.pops)) + + zchunks = self.get_redshift_chunks(self.zlim) + mchunks = self.get_mass_chunks(logmlim, dlogm) + pchunks = include_pops if channel_names is None: channel_names = [None] * len(channels) - all_layers = [] - for h, popid in enumerate(players): + + all_chunks = [] + for h, popid in enumerate(pchunks): for i, channel in enumerate(channels): - for j, zlayer in enumerate(zlayers): + for j, zchunk in enumerate(zchunks): # Option to limit redshift range. - zlo, zhi = zlayer - - for k, mlayer in enumerate(mlayers): - all_layers.append((popid, channel, channel_names[i], - zlayer, mlayer)) - - return all_layers - - def _check_for_corrupted_files(self, fov, pix, channels, logmlim, dlogm, - include_pops, channel_names=None, include_galaxy_sizes=False): - """ - When running on a cluster, occasionally we get really unlucky and an - output file will be corrupted, (probably) because we hit the wallclock - time limit on the job while the file is being written. This routine - does a cursory check that pre-existing files all have the same size, as - a quick-and-dirty way of rooting out corrupted files. - """ - - - # Assemble list of map layers to run. - all_layers = self.get_layers(channels, logmlim, dlogm=dlogm, - include_pops=include_pops, channel_names=channel_names) - - all_zlayers = np.array(self.get_redshift_layers(self.zlim)) - all_mlayers = np.array(self.get_mass_layers(logmlim, dlogm)) - - # Check status before we start - all_sizes = np.zeros(len(all_layers)) - all_fn = [] - - for h, layer in enumerate(all_layers): - - # Unpack info about this layer - popid, channel, chname, zlayer, mlayer = layer - - # See if we already finished this map. - fn = self.get_map_fn(fov, pix, channel, popid, - logmlim=mlayer, zlim=zlayer, - include_galaxy_sizes=include_galaxy_sizes) - - all_fn.append(fn) - - if not os.path.exists(fn): - continue - - all_sizes[h] = os.path.getsize(fn) - - - # Find - usizes = np.unique(all_sizes) - - if len(usizes) > 2: - print(f"! WARNING: evidence for corrupted file(s)!") - should_be = usizes.max() - - probs = [] - for h, fn in enumerate(all_fn): - if all_sizes[h] in [0, should_be]: - continue - - probs.append(fn) - - print(f"! Problem file for layer={h}: {fn}.") - - ## - # Consistent with failed write as job is killed - if len(probs) == 1: - #os.remove(probs[0]) - print(f"! Removed corrupted file {fn}.") - else: - raise IOError('! {len(probs)} corrupted files detected. Help?') + zlo, zhi = zchunk - elif np.all(all_sizes == 0): - # Means this is the first time the mock is being run. - pass - else: - ## - # Made it here? All good - print(f"! No corrupted files detected! All {len(all_layers)} layers look good.") - - def get_map_norm(self, map_units, pix=None): - """ - Remember: we're using cgs units internally. This method determines the - conversion factor to user's favorite `map_units` (within reason). + for k, mchunk in enumerate(mchunks): + all_chunks.append((popid, channel, channel_names[i], + zchunk, mchunk)) - Parameters - ---------- - map_units : str - Current options are 'si' (nW/m^2/sr^1), 'cgs' (erg/s/cm^2), - or 'MJy/sr'. Case insensitive. - pix : int, float - Pixel scale [arcseconds]. This is just in here because we are - generating fluxes *per pixel* first and so much convert to - per solid angle units. + return all_chunks - Returns - ------- - Normalization factor, i.e., if you multiply by this number it will - convert intensities *from* cgs *to* `map_units`. - """ - if (map_units.lower() == 'si') or ('nw/m^2' in map_units.lower()): - # aka (1e2)^2 / 0.01 = 1e6 - f_norm = cm_per_m**2 / erg_per_s_per_nW - elif map_units.lower() == 'cgs': - f_norm = 1. - elif 'mjy' in map_units.lower() : - # 1 MJy = 1e6 Jy = 1e6 * 1e-23 erg/s/cm^2/sr -> 1e17 MJy / cgs units - f_norm = 1e17 - elif 'ujy' in map_units.lower() : - # 1 micro-Jy = 1e-6 Jy = 1e-6 * 1e-23 erg/s/cm^2/sr -> 1e29 uJy / cgs units - f_norm = 1e29 - else: - raise ValueErorr(f"Unrecognized option `map_units={map_units}`") - - if pix is not None: - pix_deg = pix / 3600. - if '/sr' in map_units.lower(): - sr_per_pix = pix_deg**2 / sqdeg_per_std - f_norm /= sr_per_pix - - return f_norm - - def _check_chunks(self, keep_chunks): - """ - Go through user-provided `keep_chunks`, check to see that their demands - can be met, and offer up slightly modified chunk edges if they've - strayed from what's actually available. We'll also return a list of - custom redshift layers that are needed in order to construct the - desired chunks in post processing. - - Returns - ------- - Tuple containing: (keep_chunks -> closest available redshifts, - bounding indices of redshift layers in chunks, - list of custom redshift layers needed to be able to construct - the requested chunks) - - - - """ - - if keep_chunks is None: - return None, None, None - - zlayers = self.get_redshift_layers(self.zlim) - - chunks_edges = [] - chunks_edges_ids = [] - zlayers_minimal = [] - - for (zlo, zhi) in keep_chunks: - - i = np.argmin(np.abs(zlo - zlayers[:,0])) - j = np.argmin(np.abs(zhi - zlayers[:,1])) - - zlayers_minimal.extend(list(np.arange(i,j+1))) - - chunks_edges.append((zlayers[i,0], zlayers[j,1])) - chunks_edges_ids.append((i, j)) - - return chunks_edges, chunks_edges_ids, list(np.sort(zlayers_minimal)) - - def convert_chan_to_micron(self, channel, wave_units='um'): + def generate_maps(self, fov, pix, channels, logmlim, dlogm=0.5, + include_galaxy_sizes=False, size_cut=0.9, dlam=20, + suffix=None, fmt='fits', hdr={}, map_units='MJy/sr', channel_names=None, + include_pops=None, clobber=False, max_sources=None, + keep_layers=True, use_pbar=False, verbose=False, dryrun=False, **kwargs): """ + Write maps in one or more spectral channels to disk. - """ + Naming convention is: - if wave_units == 'um': - return channel - elif wave_units == 'ghz': - lam_obs = c * 1e4 / np.array(channel) / 1e9 - return tuple(lam_obs[-1::-1]) + "_" where other stuff is: - def generate_maps(self, fov, pix, channels, logmlim, dlogm=1, - include_galaxy_sizes=False, null_beyond_size=np.inf, size_cut=0.5, dlam=20, - suffix=None, fmt='fits', hdr={}, map_units='MJy/sr', channel_names=None, - include_pops=[0], clobber=False, wave_units='um', - load_if_found=True, keep_layers_custom_z=None, keep_layers=False, - keep_chunks=None, use_pbar=False, verbose=False, dryrun=False, - logmlim_sats=(11,15), - postage_stamp=5, nthreads=None, **kwargs): + + _ch__ + + _pix_ + + _fov_ + + _L + + _N + + _z__ + + _M__ + + - """ - Write maps in one or more spectral channels to disk. + The user is encouraged to add descriptive `prefix` and `suffix` that + will be prepended/appended to this string. Parameters ---------- @@ -2105,18 +1416,6 @@ def generate_maps(self, fov, pix, channels, logmlim, dlogm=1, dlogm : float To limit memory consumption, only generate halos in a log10(mass) bin this wide at a time. - include_galaxy_sizes : bool - If True, use empirical mass-size relations to paint on galaxy - surface brightness profiles (assume Sersic). Relies on parameter - `pop_msr`, a function of argument `z` and `Ms`. - size_cut : float - It is computationally expensive to generate galaxy sizes. So, for - sufficiently small galaxies, we revert to the point source treatment. - `size_cut` determines when we revert -- if size_cut=0.5, it means - that any galaxy with half-light radius >= 1 pixel will be modeled - in detail. If `size_cut=0.9`, it means any galaxy whose 90%-light - radius is bigger than a pixel will be modeled. Bigger numbers mean - more expensive calculations. zlim : tuple Boundaries of lightcone used to create map in redshift. dlam : int, float @@ -2127,16 +1426,6 @@ def generate_maps(self, fov, pix, channels, logmlim, dlogm=1, calculation, e.g., [0] would just include the first population, typically star-forming galaxies, while [0, 1] would include the first two (ID number 1 is usually quiescent centrals). - keep_layers : bool - If True, individual mass and redshift 'layers' will be saved to - disk in the `checkpoints` subdirectory. This can get heavy for - big mocks -- see next parameter for another option. - keep_layers_custom_z : list - If provided, this is a list of individual layers to save (i.e., - not all of them). Note that these need to be integers for now, so - you have to kind of know what you're doing. See the method - `get_redshift_layers` to reveal the co-eval redshift layers - that are available. Returns ------- @@ -2149,14 +1438,6 @@ def generate_maps(self, fov, pix, channels, logmlim, dlogm=1, # Create root directory if it doesn't already exist. self.build_directory_structure(fov, pix, dryrun=False) - # Must do this after building the directory tree otherwise - # we'll get errors. - if not clobber: - self._check_for_corrupted_files(fov, pix, channels, - logmlim=logmlim, dlogm=dlogm, - include_pops=include_pops, channel_names=channel_names, - include_galaxy_sizes=include_galaxy_sizes) - ## # Initialize a README file / see what's in it. README = self.get_README(fov=fov, pix=pix, zlim=self.zlim, @@ -2182,101 +1463,69 @@ def generate_maps(self, fov, pix, channels, logmlim, dlogm=1, #if zlim is None: zlim = self.zlim + if include_pops is None: + include_pops = range(0, len(self.sim.pops)) + assert fov * 3600 / pix % 1 == 0, \ "FOV must be integer number of pixels wide!" npix = int(fov * 3600 / pix) - # Converts from cgs [internal units] to `map_units` - f_norm = self.get_map_norm(map_units, pix) - - # Assemble list of map layers to run. - all_layers = self.get_layers(channels, logmlim, dlogm=dlogm, - include_pops=include_pops, channel_names=channel_names) - - all_zlayers = np.array(self.get_redshift_layers(self.zlim)) - all_mlayers = np.array(self.get_mass_layers(logmlim, dlogm)) - - # Users can keep custom chunks (i.e., sums over layers) - if keep_chunks is not None: - assert keep_layers, "Must set keep_layers=True to `keep_chunks`." - chunks_edges, chunks_edges_ids, chunks_zlayers_needed = \ - self._check_chunks(keep_chunks) + ## + # Remember: using cgs units internally. Compute conversion factor to + # users favorite units (within reason). + # 1 Jy = 1e-23 erg/s/cm^2/sr + if (map_units.lower() == 'si') or ('nw/m^2' in map_units.lower()): + # aka (1e2)^2 / 0.01 = 1e6 + f_norm = cm_per_m**2 / erg_per_s_per_nW + elif map_units.lower() == 'cgs': + f_norm = 1. + elif 'mjy' in map_units.lower(): + # 1 MJy = 1e6 Jy = 1e6 * 1e-23 erg/s/cm^2/sr = 1e17 MJy / cgs units + f_norm = 1e17 else: - chunk_edges = chunk_edges_ids = chunks_zlayers_needed = None + raise ValueErorr(f"Unrecognized option `map_units={map_units}`") - # User can custom define subset of redshift layers to save - # (this is a computational choice: saving all can be ~TBs of images) - if keep_layers: - if (keep_layers_custom_z == None): - _keep_layers_custom = list(np.arange(0, len(all_zlayers))) - else: - _keep_layers_custom = list(keep_layers_custom_z) + if '/sr' in map_units.lower(): + sr_per_pix = pix_deg**2 / sqdeg_per_std + f_norm /= sr_per_pix - # Make sure we save the layers needed to build provided chunks - if keep_chunks is not None: - for layer_id in chunks_zlayers_needed: - if layer_id not in _keep_layers_custom: - _keep_layers_custom.append(layer_id) - if verbose: - print(f"! Added layer {layer_id} to list of layers to keep.") + # Assemble list of map layers to run. + all_chunks = self.get_layers(channels, logmlim, dlogm=dlogm, + include_pops=include_pops, channel_names=channel_names) - _keep_layers_custom = list(np.sort(_keep_layers_custom)) - else: - if keep_layers_custom_z is not None: - raise ValueError('You set keep_layers_custom_z but not keep_layers! Set latter to True (probably).') + all_zchunks = np.array(self.get_redshift_chunks(self.zlim)) + all_mchunks = np.array(self.get_mass_chunks(logmlim, dlogm)) - # Array telling us which layers were already done and which + # Array telling us which chunks were already done and which # we ran from scratch so at the end we know whether to update # the channel maps. # Recall that if we changed zmax, final maps will go in a new # subdirectory. status_done_pre = np.zeros((len(include_pops), len(channels), - len(all_zlayers), len(all_mlayers))) + len(all_zchunks), len(all_mchunks))) status_done_now = status_done_pre.copy() - ## # Check status before we start - for h, layer in enumerate(all_layers): + for h, chunk in enumerate(all_chunks): - # Unpack info about this layer - popid, channel, chname, zlayer, mlayer = layer + # Unpack info about this chunk + popid, channel, chname, zchunk, mchunk = chunk - # Identify indices of each (channel, z, m) layer + # Identify indices of each (channel, z, m) chunk ichan = np.argmin(np.abs(channel[0] - channels[:,0])) - iz = np.argmin(np.abs(zlayer[0] - all_zlayers[:,0])) - im = np.argmin(np.abs(mlayer[0] - all_mlayers[:,0])) - ip = include_pops.index(popid) - - if np.all(status_done_pre[ip,ichan,:,:]) == 1: - continue - - # Check first for final map. - fn = self.get_map_fn(fov, pix, channel, popid, - logmlim=logmlim, zlim=self.zlim, - wave_units=wave_units, - include_galaxy_sizes=include_galaxy_sizes) - - if os.path.exists(fn) and (not clobber): - status_done_pre[ip,ichan,:,:] = 1 - print(f"! Final map for popid={ip} and channel={channel} exists.") - continue + iz = np.argmin(np.abs(zchunk[0] - all_zchunks[:,0])) + im = np.argmin(np.abs(mchunk[0] - all_mchunks[:,0])) # See if we already finished this map. fn = self.get_map_fn(fov, pix, channel, popid, - logmlim=mlayer, zlim=zlayer, wave_units=wave_units, - include_galaxy_sizes=include_galaxy_sizes) + logmlim=mchunk, zlim=zchunk) if os.path.exists(fn) and (not clobber): - status_done_pre[ip,ichan,iz,im] = 1 - - ## - # If all maps done, exit. - if np.all(status_done_pre == 1): - return + status_done_pre[popid,ichan,iz,im] = 1 # Progress bar - pb = ProgressBar(len(all_layers), + pb = ProgressBar(len(all_chunks), name="img(Mh>={:.1f}, Mh<{:.1f}, z>={:.3f}, z<{:.3f})".format( logmlim[0], logmlim[1], zlim[0], zlim[1]), use=use_pbar) @@ -2286,40 +1535,34 @@ def generate_maps(self, fov, pix, channels, logmlim, dlogm=1, cimg = np.zeros([npix]*2) if verbose: - print(f"# Generating {len(all_layers)} individual map layers...") + print(f"# Generating {len(all_chunks)} individual map layers...") ## # Start doing work. - # The way this works is we treat each layer: (z, M, pop, lambda) + # The way this works is we treat each chunk: (z, M, pop, lambda) # separately. We'll keep a running tally of the "final" flux in any # given channel map as we go, and only create a new buffer when we # finish all the work for a single channel and a given population. - for h, layer in enumerate(all_layers): - - # Unpack info about this layer - popid, channel, chname, zlayer, mlayer = layer + for h, chunk in enumerate(all_chunks): - # Unpack popid more [as of March 2025] - # (id number in ARES, parent ID number [if satellite], name as str) - pid, pid_par, pid_str = get_pop_info(popid) + # Unpack info about this chunk + popid, channel, chname, zchunk, mchunk = chunk - # Identify indices of each (channel, z, m) layer + # Identify indices of each (channel, z, m) chunk ichan = np.argmin(np.abs(channel[0] - channels[:,0])) - iz = np.argmin(np.abs(zlayer[0] - all_zlayers[:,0])) - im = np.argmin(np.abs(mlayer[0] - all_mlayers[:,0])) - ip = include_pops.index(popid) + iz = np.argmin(np.abs(zchunk[0] - all_zchunks[:,0])) + im = np.argmin(np.abs(mchunk[0] - all_mchunks[:,0])) - # Can only move on if ALL layers are already done, otherwise - # it means the user has added z or m layers since the last run, + # Can only move on if ALL chunks are already done, otherwise + # it means the user has added z or m chunks since the last run, # and so the final channel map (saved into new subdirectory # to reflect new zmax, logmlim range) must be incremented. - if np.all(status_done_pre[ip,ichan,:,:]): - continue + #if np.all(status_done_pre[popid,ichan,:,:]): + # continue # See if we already finished this map. fn = self.get_map_fn(fov, pix, channel, popid, - logmlim=mlayer, zlim=zlayer, wave_units=wave_units, - include_galaxy_sizes=include_galaxy_sizes) + logmlim=mchunk, zlim=zchunk) pb.update(h) @@ -2327,12 +1570,10 @@ def generate_maps(self, fov, pix, channels, logmlim, dlogm=1, print(f"# Dry run: would run map {fn}") continue - chan_mic = self.convert_chan_to_micron(channel, wave_units) - # Will need channel width in Hz to recover specific intensities # averaged over band. - nu = c * 1e4 / np.mean(chan_mic) - dnu = c * 1e4 * (chan_mic[1] - chan_mic[0]) / np.mean(chan_mic)**2 + nu = c * 1e4 / np.mean(channel) + dnu = c * 1e4 * (channel[1] - channel[0]) / np.mean(channel)**2 # What buffer should we increment? if (not keep_layers): @@ -2343,85 +1584,65 @@ def generate_maps(self, fov, pix, channels, logmlim, dlogm=1, ran_new = True if os.path.exists(fn) and (not clobber): # Load map - if load_if_found: - _buffer, _hdr = self._load_map(fn) + _buffer, _hdr = self._load_map(fn) - # Might need to adjust units before incrementing - if _hdr['BUNIT'] == map_units: - _buffer *= (f_norm / dnu)**-1. - else: - raise NotImplemented('help') + if _hdr['BUNIT'] == map_units: + _buffer *= (f_norm / dnu)**-1. + else: + raise NotImplemented('help') - # Increment map for this z layer - cimg += _buffer + # Might need to adjust units before incrementing + #buffer += _buffer + # Increment map for this z chunk + cimg += _buffer - if verbose: - print(f"# Loaded map {fn}.") - else: - print(f"# Elected not to load {fn} since load_if_found=False.") - print(f"# Be sure to re-run `generate_maps` once all checkpoints are done with load_if_found=True.") + if verbose: + print(f"# Loaded map {fn}.") ran_new = False else: if verbose: print(f"# Generating map {fn}...") - # Make sure user gave us info needed to generate surface - # brightness profiles. Note that IHL is exempt from this as - # we only have one option (projected NFW treatment). - if include_galaxy_sizes and (not self.sim.pops[pid].is_diffuse): - assert self.sim.pops[pid].pf['pop_msr'] is not None, \ - "Must provide `pop_msr` if include_galaxy_sizes=True!" - # Generate map -> buffer # Internal flux units are cgs [erg/s/cm^2/Hz/sr] # but get_map returns a channel-integrated flux, erg/s/cm^2/sr - self.get_map(fov, pix, chan_mic, - logmlim=mlayer, zlim=zlayer, popid=popid, - wave_units=wave_units, + self.get_map(fov, pix, channel, + logmlim=mchunk, zlim=zchunk, popid=popid, include_galaxy_sizes=include_galaxy_sizes, - null_beyond_size=null_beyond_size, size_cut=size_cut, dlam=dlam, use_pbar=False, - logmlim_sats=logmlim_sats, - buffer=buffer, nthreads=nthreads, verbose=verbose, - postage_stamp=postage_stamp, + max_sources=max_sources, + buffer=buffer, verbose=verbose, **kwargs) - status_done_now[ip,ichan,iz,im] = 1 + status_done_now[popid,ichan,iz,im] = 1 - # Save every mass layer within every redshift layer if the user + # Save every mass chunk within every redshift chunk if the user # says so. if keep_layers and ran_new: + _fn = self.get_map_fn(fov, pix, channel, popid, + logmlim=mchunk, zlim=zchunk, + fmt=fmt) + self.save_map(_fn, buffer * f_norm / dnu, + channel, zchunk, logmlim, fov, + pix=pix, fmt=fmt, hdr=hdr, map_units=map_units, + verbose=verbose, clobber=clobber) - if iz in _keep_layers_custom: - _fn = self.get_map_fn(fov, pix, channel, popid, - logmlim=mlayer, zlim=zlayer, wave_units=wave_units, - fmt=fmt, include_galaxy_sizes=include_galaxy_sizes) - self.save_map(_fn, buffer * f_norm / dnu, - channel, zlayer, logmlim, fov, - pix=pix, fmt=fmt, hdr=hdr, map_units=map_units, - verbose=verbose, clobber=clobber) - - # Increment map for this z layer - # (a new `cimg` gets created later once full mass range is done) - #if ran_new: + # Increment map for this z chunk cimg += buffer - #else: - # Already incremented above after loaded - # pass ## # Otherwise, figure out what (if anything) needs to be # written to disk now. done_w_chan = np.all( - status_done_pre[ip,ichan,:,:] + - status_done_now[ip,ichan,:,:] + status_done_pre[popid,ichan,:,:] + + status_done_now[popid,ichan,:,:] ) # This probably means our re-run only added channels, not - # z layers or mass layers. - was_done_already = np.all(status_done_pre[ip,ichan,:,:] == 1) \ + # z chunks or mass chunks. + was_done_already = np.all(status_done_pre[popid,ichan,:,:] == 1) \ and (not clobber) ## @@ -2432,7 +1653,7 @@ def generate_maps(self, fov, pix, channels, logmlim, dlogm=1, # disk, but we do need to clear 'cimg' since the next iteration # will be a new channel. - # Also: for mass layers, we might run, e.g., (11,12) in one call, + # Also: for mass chunks, we might run, e.g., (11,12) in one call, # (12,13) next, and then later decide to do (11,13), in which case # all the work is done already *except* creating the final # channel map. That's why below we'll either write the final map @@ -2440,18 +1661,16 @@ def generate_maps(self, fov, pix, channels, logmlim, dlogm=1, # an output file. # Filename for the final channel map - # (note use of self.zlim, not zlayer, and logmlim, not mlayer) + # (note use of self.zlim, not zchunk, and logmlim, not mchunk) _fn = self.get_map_fn(fov, pix, channel, popid, - logmlim=logmlim, zlim=self.zlim, fmt=fmt, wave_units=wave_units, - include_galaxy_sizes=include_galaxy_sizes) + logmlim=logmlim, zlim=self.zlim, fmt=fmt) _fn_exists = os.path.exists(_fn) # If we're done with the channel and population, time to write # a final "channel map". Afterward, we'll zero-out `cimg` to be # incremented starting on the next iteration. - if done_w_chan and ((not was_done_already) or (not _fn_exists)) \ - and load_if_found: + if done_w_chan and ((not was_done_already) or (not _fn_exists)): self.save_map(_fn, cimg * f_norm / dnu, channel, self.zlim, logmlim, fov, @@ -2479,8 +1698,8 @@ def generate_maps(self, fov, pix, channels, logmlim, dlogm=1, write_README = False # channel name [optional]; central wavelength (microns); channel lower edge (microns) ; channel upper edge (microns) ; filename - s_ch = f'{chname}; {np.mean(channel):.6f}; ' - s_ch += f'{channel[0]:.5f}; {channel[1]:.6f}; ' + s_ch = f'{chname}; {np.mean(channel):.5f}; ' + s_ch += f'{channel[0]:.5f}; {channel[1]:.5f}; ' s_ch += f'{popid}; {_fn} \n' ## @@ -2488,8 +1707,6 @@ def generate_maps(self, fov, pix, channels, logmlim, dlogm=1, if write_README: with open(f'{base_dir}/README', 'a') as f: f.write(s_ch) - elif done_w_chan and ((not was_done_already) or (not _fn_exists)): - print(f"! Done with map {_fn} but did not write because load_if_found=False.") ## # Need to zero-out channel map if done with channel, regardless @@ -2501,162 +1718,17 @@ def generate_maps(self, fov, pix, channels, logmlim, dlogm=1, ## # Next task - # All done. pb.finish() - ## - # Stitch together z slices? - self.post_process_z_layers(fov, pix, channels, - logmlim=logmlim, dlogm=dlogm, - clobber=clobber, channel_names=channel_names, - include_pops=include_pops, verbose=verbose, - map_units=map_units, - include_galaxy_sizes=include_galaxy_sizes, - keep_layers=keep_layers, - keep_layers_custom_z=keep_layers_custom_z, - keep_chunks=keep_chunks) - return - def post_process_z_layers(self, fov, pix, channels, logmlim, dlogm=1, - clobber=False, include_pops=[0], verbose=True, channel_names=None, - keep_layers=False, keep_layers_custom_z=None, keep_chunks=None, - include_galaxy_sizes=False, - map_units='MJy/sr', hdr={}, fmt='fits'): - """ - If we decided to save redshift layers, we may still need to sum - together the individual mass layers. - - .. note :: Generalize this to automatically sum over source populations - as well? - - """ - - if (not keep_layers) and (keep_chunks is None): - return - - chunks_edges_z, chunks_edges_ids, chunks_zlayers_needed = \ - self._check_chunks(keep_chunks) - - # Full list of map layers to run. - all_layers = self.get_layers(channels, logmlim, dlogm=dlogm, - include_pops=include_pops, channel_names=channel_names) - - all_zlayers = np.array(self.get_redshift_layers(self.zlim)) - all_mlayers = np.array(self.get_mass_layers(logmlim, dlogm)) - - # User can custom define subset of redshift layers to save - # (this is a computational choice: saving all can be ~TBs of images) - if (keep_layers_custom_z == None): - _keep_layers_custom = list(np.arange(0, len(all_zlayers))) - else: - _keep_layers_custom = list(keep_layers_custom_z) - - # A few last things we need - f_norm = self.get_map_norm(map_units, pix) - npix = int(fov * 3600 / pix) - - ## - # loop through redshift layers of interest - for ichan, channel in enumerate(channels): - - nu = c * 1e4 / np.mean(channel) - dnu = c * 1e4 * (channel[1] - channel[0]) / np.mean(channel)**2 - - for popid in include_pops: - - for iz in _keep_layers_custom: - - cimg = np.zeros([npix, npix]) - for im, mlayer in enumerate(all_mlayers): - - # See if we already finished this map. - fn = self.get_map_fn(fov, pix, channel, popid, - logmlim=mlayer, zlim=all_zlayers[iz], - wave_units=wave_units, - include_galaxy_sizes=include_galaxy_sizes) - - _buffer, _hdr = self._load_map(fn) - - # Might need to adjust units before incrementing - if _hdr['BUNIT'] == map_units: - _buffer *= (f_norm / dnu)**-1. - else: - raise NotImplemented('help') - - # Increment map for this z layer - cimg += _buffer - - ## - # Done with mass slices. Save redshift slice. - _fn = self.get_map_fn(fov, pix, channel, popid, - logmlim=logmlim, zlim=all_zlayers[iz], - wave_units=wave_units, - include_galaxy_sizes=include_galaxy_sizes) - - self.save_map(_fn, cimg * f_norm / dnu, - channel, all_zlayers[iz], logmlim, fov, - pix=pix, fmt=fmt, hdr=hdr, map_units=map_units, - verbose=verbose, clobber=clobber) - - if chunks_edges_ids is None: - continue - - ## - # Now, [optionally] sum over redshift layers to form 'chunks' - # like "EoR", "cosmic noon", etc. - for k, chunk_edge_id in enumerate(chunks_edges_ids): - - cimg = np.zeros([npix, npix]) - for iz in range(chunk_edge_id[0], chunk_edge_id[1]+1): - # Load z layer summed over mass (`logmlim` is whole range) - fn = self.get_map_fn(fov, pix, channel, popid, - logmlim=logmlim, wave_units=wave_units, - zlim=all_zlayers[iz], - include_galaxy_sizes=include_galaxy_sizes) - - _buffer, _hdr = self._load_map(fn) - - # Might need to adjust units before incrementing - if _hdr['BUNIT'] == map_units: - _buffer *= (f_norm / dnu)**-1. - else: - raise NotImplemented('help') - - # Increment map for this z layer - cimg += _buffer - - ## - # Done with mass slices. Save redshift slice. - _fn = self.get_map_fn(fov, pix, channel, popid, - logmlim=logmlim, zlim=chunks_edges_z[k], - wave_units=wave_units, - force_chunk=True, include_galaxy_sizes=include_galaxy_sizes) - - self.save_map(_fn, cimg * f_norm / dnu, - channel, chunks_edges_z[k], logmlim, fov, - pix=pix, fmt=fmt, hdr=hdr, map_units=map_units, - verbose=verbose, clobber=clobber) - def save_cat(self, fn, cat, channel, zlim, logmlim, fov, pix=1, fmt='fits', hdr={}, clobber=False, verbose=False, cat_units=''): """ Save galaxy catalog. - - Parameters - ---------- - fn : str - Output filename. - cat : np.array - 1-D Array containing the quantity to be saved. - channel : str - Name of the field being saved. - """ - - # Should just figure out `fmt` from filename in future - assert fn.endswith(fmt) + ra, dec, red, X = cat if os.path.exists(fn) and (not clobber): if verbose: @@ -2665,10 +1737,10 @@ def save_cat(self, fn, cat, channel, zlim, logmlim, fov, pix=1, fmt='fits', if fmt == 'hdf5': with h5py.File(fn, 'w') as f: - #f.create_dataset('ra', data=ra) - #f.create_dataset('dec', data=dec) - #f.create_dataset('z', data=red) - f.create_dataset(channel, data=cat) + f.create_dataset('ra', data=ra) + f.create_dataset('dec', data=dec) + f.create_dataset('z', data=red) + f.create_dataset(channel, data=X) # Save hdr grp = f.create_group('hdr') @@ -2676,19 +1748,19 @@ def save_cat(self, fn, cat, channel, zlim, logmlim, fov, pix=1, fmt='fits', grp.create_dataset(key, data=hdr[key]) elif fmt == 'fits': - #col1 = fits.Column(name='ra', format='D', unit='deg', array=ra) - #col2 = fits.Column(name='dec', format='D', unit='deg', array=dec) - #col3 = fits.Column(name='z', format='D', unit='', array=red) - if type(channel) in [list, tuple, np.ndarray]: - col4 = fits.Column(name='flux', format='D', unit=cat_units, - array=np.array(cat, dtype=float)) - else: - col4 = fits.Column(name=channel, format='D', unit=cat_units, - array=np.array(cat, dtype=float)) - coldefs = fits.ColDefs([col4]) + col1 = fits.Column(name='ra', format='D', unit='deg', array=ra) + col2 = fits.Column(name='dec', format='D', unit='deg', array=dec) + col3 = fits.Column(name='z', format='D', unit='', array=red) + + col4 = fits.Column(name=channel, format='D', unit=cat_units, array=X) + coldefs = fits.ColDefs([col1, col2, col3, col4]) hdu = fits.BinTableHDU.from_columns(coldefs) - hdu.writeto(fn, overwrite=clobber) + + if os.path.exists(fn) and (not clobber): + print(f"# {fn} exists and clobber=False. Moving on.") + else: + hdu.writeto(fn, overwrite=clobber) else: raise NotImplemented(f'Unrecognized `fmt` option "{fmt}"') @@ -2728,6 +1800,8 @@ def save_map(self, fn, img, channel, zlim, logmlim, fov, pix=1, fmt='fits', print(f"# Wrote {fn}.") elif fmt == 'fits': + from astropy.io import fits + hdr = fits.Header(hdr) #_hdr.update(hdr) #hdr = _hdr @@ -2794,44 +1868,18 @@ def _load_map(self, fn): with h5py.File(fn, 'r') as f: img = np.array(f[('ebl')]) elif fmt == 'fits': - - if self.verbose: - print(f"! Attempting to load {fn}...") - - t1 = time.time() + from astropy.io import fits with fits.open(fn) as hdu: # In whatever `map_units` user supplied. img = hdu[0].data hdr = hdu[0].header - - t2 = time.time() - print(f"! Loaded {fn} [took {(t2-t1):.2f} sec].") - else: raise NotImplementedError(f'No support for fmt={fmt}!') return img, hdr - def _load_cat(self, fn, skip_pos=False): - """ - Load a catalog from disk. - - Parameters - ---------- - fn : str - Filename. - skip_pos : bool - If True, will not (re-)load (ra, dec, z) from file. This an be - advantageous for big catalogs if you already have the galaxy - positions loaded in memory. - - Returns - ------- - A tuple containing (ra, dec, redshift, catalog, catalog_units), unless - skip_pos==True, in which case it will just be (catalog, catalog_units). - """ + def _load_cat(self, fn): if fn.endswith('hdf5'): - raise NotImplemented('hdf5 option needs updating') with h5py.File(fn, 'r') as f: ra = np.array(f[('ra')]) dec = np.array(f[('dec')]) @@ -2839,35 +1887,24 @@ def _load_cat(self, fn, skip_pos=False): X = np.array(f[('Mh')]) Xunit = None elif fn.endswith('fits'): - with fits.open(fn) as f: data = f[1].data - - # Determine field name from column header - name = data.columns[0].name - X = np.array(data[name], dtype=float) - Xunit = f[1].header['TUNIT1'] - - out = [] - for field in ['ra', 'dec', 'z']: - if skip_pos or name in ['ra', 'dec', 'z']: - break - - with fits.open(fn.replace(name, field)) as f: - data = np.array(f[1].data, dtype=float) - - out.append(data) - - out.extend([X, Xunit]) - + ra = data['ra'] + dec = data['dec'] + red = data['z'] + + # Hack for now. + name = data.columns[3].name + X = data[name] + Xunit = f[1].header['TUNIT4'] else: raise NotImplemented('Unrecognized file format `{}`'.format( fn[fn.rfind('.'):])) - return tuple(out) + return ra, dec, red, X, Xunit def read_maps(self, fov, channels, pix=1, logmlim=None, dlogm=0.5, - prefix=None, suffix=None, save_dir=None, keep_layers=False, fmt='fits'): + prefix=None, suffix=None, save_dir=None, keep_layers=True, fmt='fits'): """ Assemble an array of maps. """ @@ -2878,11 +1915,11 @@ def read_maps(self, fov, channels, pix=1, logmlim=None, dlogm=0.5, save_dir = '.' npix = int(fov * 3600 / pix) - zlayers = self.get_redshift_layers(self.zlim) - mlayers = self.get_mass_layers(logmlim, dlogm) + zchunks = self.get_redshift_chunks(self.zlim) + mchunks = self.get_mass_chunks(logmlim, dlogm) if keep_layers: - layers = np.zeros((len(channels), len(zlayers), len(mlayers), npix, npix)) + layers = np.zeros((len(channels), len(zchunks), len(mchunks), npix, npix)) else: layers = np.zeros((len(channels), npix, npix)) @@ -2891,9 +1928,9 @@ def read_maps(self, fov, channels, pix=1, logmlim=None, dlogm=0.5, Nloaded = 0 for i, channel in enumerate(channels): - for j, (zlo, zhi) in enumerate(zlayers): + for j, (zlo, zhi) in enumerate(zchunks): - for k, (mlo, mhi) in enumerate(mlayers): + for k, (mlo, mhi) in enumerate(mchunks): fn = self.get_fn(fov, channel, pix=pix, zlim=(zlo, zhi), prefix=prefix, suffix=suffix, @@ -2916,4 +1953,4 @@ def read_maps(self, fov, channels, pix=1, logmlim=None, dlogm=0.5, if Nloaded == 0: raise IOError("Did not find any files! Are prefix, suffix, and save_dir set appropriately?") - return channels, zlayers, mlayers, ra_c, dec_c, layers + return channels, zchunks, mchunks, ra_c, dec_c, layers diff --git a/ares/realizations/LogNormal.py b/ares/realizations/LogNormal.py index 7246688b0..3653f0923 100644 --- a/ares/realizations/LogNormal.py +++ b/ares/realizations/LogNormal.py @@ -14,41 +14,23 @@ import numpy as np from ..util import ProgressBar from .LightCone import LightCone -from ..util.Misc import get_pop_info -from functools import cached_property +from scipy.integrate import cumulative_trapezoid from scipy.interpolate import interp1d from ..util.Stats import bin_c2e, bin_e2c from ..physics.Constants import cm_per_mpc -from scipy.integrate import cumulative_trapezoid try: import powerbox as pbox except ImportError: pass -#try: -# from numba import njit, prange -# -# @njit -# def _interp_linear(xx, x, y): -# return np.interp(xx, x, y) -# -# @njit -# def _trapz(x, y): -# return np.trapz(y, x=x) -#except ImportError: -# pass - - class LogNormal(LightCone): # pragma: no cover def __init__(self, model_name, Lbox=256, dims=128, zmin=0.05, zmax=2, verbose=True, seed_rho=None, seed_halo_mass=None, seed_halo_pos=None, seed_halo_occ=None, - seed_rot=None, seed_trans=None, seed_profile=None, seed_sats=None, + seed_rot=None, seed_trans=None, seed_pa=None, seed_nsers=None, apply_rotations=False, apply_translations=False, bias_model=0, bias_params=None, bias_replacement=1, bias_within_bin=False, - randomise_in_cell=True, base_dir='ares_mock', mem_concious=0, - distribute_sats_spatially=True, profile_info=None, - dz_max=0.01, lightcone_max_evol=np.inf, **kwargs): + randomise_in_cell=True, base_dir='ares_mock', mem_concious=1, **kwargs): """ Initialize a galaxy population from log-normal density fields generated from the matter power spectrum. @@ -60,11 +42,8 @@ def __init__(self, model_name, Lbox=256, dims=128, zmin=0.05, zmax=2, verbose=Tr dims : int Number of grid points in each dimension, so total number of grid elements per co-eval cube is dims**3. - zmin, zmax : int, float - Defines domain size along line of sight, zmin <= z < zmax. - dz_max : float - Will sub-sample along the line of sight direction in `dz_max` sized - redshift increments, e.g., when computing fluxes from sources. + zlim : tuple + Defines domain size along line of sight, zlim[0] <= z < zlim[1]. kwargs : dictionary Set of parameters that defines an ares.simulations.Simulation. @@ -74,25 +53,17 @@ def __init__(self, model_name, Lbox=256, dims=128, zmin=0.05, zmax=2, verbose=Tr self.zmin = zmin self.zmax = zmax self.zlim = (zmin, zmax) - self.dz_max = dz_max - self.lightcone_max_evol = lightcone_max_evol self.seed_rho = seed_rho self.seed_halo_mass = seed_halo_mass self.seed_halo_pos = seed_halo_pos self.seed_halo_occ = seed_halo_occ self.seed_rot = seed_rot self.seed_tra = seed_trans - self.seed_profile = seed_profile - self.profile_info = profile_info - self.seed_sats = seed_sats + self.seed_pa = seed_pa + self.seed_nsers = seed_nsers self.apply_rotations = apply_rotations self.apply_translations = apply_translations - self.distribute_sats_spatially = distribute_sats_spatially - - # Only used for NbodySimLC models - self.zlayers = None - self.fxy = (0., 0.) self.bias_model = bias_model self.bias_params = bias_params self.bias_replacement = bias_replacement @@ -118,12 +89,35 @@ def __init__(self, model_name, Lbox=256, dims=128, zmin=0.05, zmax=2, verbose=Tr print(f"# Overriding user-supplied zlim slightly to accommodate box size.") print(f"# Old zlim=({zmin:.3f},{zmax:.3f})") print(f"# New zlim=({self.zlim[0]:.3f},{self.zlim[1]:.3f})") - print(f"# Number of co-eval layers: {zmid.size}") + print(f"# Number of co-eval chunks: {zmid.size}") - ## - # Initialize caches here to avoid repeated hasattr calls - self._cache_subhalo_cdf_ = {} - self._cache_mgtm_ = {} + def get_seed_kwargs(self, chunk, logmlim): + # Deterministically adjust the random seeds for the given mass range + # and redshift range. + fmh = int(logmlim[0] + (logmlim[1] - logmlim[0]) / 0.1) + + ze, zmid, Re = self.get_domain_info(zlim=self.zlim, Lbox=self.Lbox) + + if not hasattr(self, '_seeds'): + self._seeds = self.seed_rho * np.arange(1, len(zmid)+1) + self._seeds_hm = self.seed_halo_mass * np.arange(1, len(zmid)+1) * fmh + self._seeds_hp = self.seed_halo_pos * np.arange(1, len(zmid)+1) * fmh + self._seeds_ho = self.seed_halo_occ * np.arange(1, len(zmid)+1) * fmh + + if self.seed_nsers is not None: + self._seeds_nsers = self.seed_nsers * np.arange(1, len(zmid)+1) * fmh + else: + self._seeds_nsers = [None] * len(zmid) + if self.seed_pa is not None: + self._seeds_pa = self.seed_pa * np.arange(1, len(zmid)+1) * fmh + else: + self._seeds_pa = [None] * len(zmid) + + i = chunk + return {'seed_box': self._seeds[i], + 'seed': self._seeds_hm[i], 'seed_pos': self._seeds_hp[i], + 'seed_occ': self._seeds_ho[i], + 'seed_nsers': self._seeds_nsers[i], 'seed_pa': self._seeds_pa[i]} def get_fov_from_L(self, z, Lbox): """ @@ -174,12 +168,12 @@ def get_memory_estimate(self, zlim=None, logmlim=None, Lbox=None, dims=None): mem_z = [] # Memory for each redshift separately mem_c = [] # Cumulative for i, z in enumerate(zmid): - iz = np.argmin(np.abs(self.halos.tab_z - z)) - ok = np.logical_and(self.halos.tab_M >= mmin, - self.halos.tab_M < mmax) + iz = np.argmin(np.abs(self.sim.pops[0].halos.tab_z - z)) + ok = np.logical_and(self.sim.pops[0].halos.tab_M >= mmin, + self.sim.pops[0].halos.tab_M < mmax) - m = self.halos.tab_M[ok==1] - dndm = self.halos.tab_dndm[iz,ok==1] + m = self.sim.pops[0].halos.tab_M[ok==1] + dndm = self.sim.pops[0].halos.tab_dndm[iz,ok==1] nall = cumulative_trapezoid(dndm * m, x=np.log(m), initial=0.0) nbar = np.trapz(dndm * m, x=np.log(m)) \ @@ -224,13 +218,16 @@ def get_nbar(self, z, mmin, mmax=np.inf, fov=None, dz=None): """ - iz = np.argmin(np.abs(self.halos.tab_z - z)) - ok = np.logical_and(self.halos.tab_M >= mmin, - self.halos.tab_M < mmax) + iz = np.argmin(np.abs(self.sim.pops[0].halos.tab_z - z)) + ok = np.logical_and(self.sim.pops[0].halos.tab_M >= mmin, + self.sim.pops[0].halos.tab_M < mmax) - m = self.halos.tab_M - dndlnm = self.halos.tab_dndlnm[iz,:] - nbar = np.trapz(dndlnm[ok==1], x=np.log(m[ok==1])) + m = self.sim.pops[0].halos.tab_M[ok==1] + dndm = self.sim.pops[0].halos.tab_dndm[iz,ok==1] + + nall = cumulative_trapezoid(dndm * m, x=np.log(m), initial=0.0) + nbar = np.trapz(dndm * m, x=np.log(m)) \ + - np.exp(np.interp(np.log(mmin), np.log(m), np.log(nall))) # Correct for FOV if (fov is not None) and (dz is not None): @@ -259,66 +256,17 @@ def get_ps_mm(self, z, k): if z in self._cache_ps: return self._cache_ps[z](k) - iz = np.argmin(np.abs(self.halos.tab_z - z)) + iz = np.argmin(np.abs(self.sim.pops[0].halos.tab_z - z)) - power = interp1d(self.halos.tab_k_lin, - self.halos.tab_ps_lin[iz,:], kind='cubic') + power = interp1d(self.sim.pops[0].halos.tab_k_lin, + self.sim.pops[0].halos.tab_ps_lin[iz,:], kind='cubic') self._cache_ps[z] = power return power(k) - def get_density_field(self, z, seed=None, lightcone_corr=False): - """ - This is a wrapper around `get_box` that will optionally perform a - lightcone correction, i.e., account for the fact that for sufficiently - large boxes there will be evolution in P(k) along the line of sight. - """ - - if not lightcone_corr: - return self.get_box(z=z, seed=seed).delta_x() - - ## - # If operating within a larger calculation (probably the case), - # we need to be more careful. First, check how much P(k) evolves - # over a single co-eval cube, and then generate two realizations if - # necessary to form an interpolant along the line of sight. - # First, get full domain info - ze, zmid, Re = self.get_domain_info(zlim=self.zlim, Lbox=self.Lbox) - zlayers = self.get_redshift_layers(zlim=self.zlim) - - iz = np.argmin(np.abs(z - zmid)) - if z < zlayers[iz,0]: - iz -= 1 - - zlo, zhi = zlayers[iz,:] - - # Just use a large-scale mode - kbig = 1e-3 - - Plo = self.get_ps_mm(zlo, kbig) - Phi = self.get_ps_mm(zhi, kbig) - - if np.abs(Plo - Phi) / Plo < self.lightcone_max_evol: - return self.get_box(z=z, seed=seed).delta_x() - - ## - box_lo = self.get_box(z=zlo, seed=seed).delta_x() - box_hi = self.get_box(z=zhi, seed=seed).delta_x() - - # Need redshifts of each voxel along LoS. - Lpix = self.Lbox / float(self.dims) - zpix_e, zpix_c, zpix_Re = \ - self.sim.cosm.get_lightcone_boundaries((zlo, zhi), Lpix) - - # Need to replace z-axis - new_box = np.zeros_like(box_lo) - for i, zz in enumerate(zpix_c): - func = interp1d([zlo, zhi], - np.array([box_lo[:,:,i], box_hi[:,:,i]]), axis=0) - new_box[:,:,i] = func(zz) - - return new_box + def get_density_field(self, z, seed=None): + return self.get_box(z=z, seed=seed) def get_box(self, z, seed=None): """ @@ -327,7 +275,7 @@ def get_box(self, z, seed=None): Returns ------- powerbox.powerbox.LogNormalPowerBox object, attribute `delta_x()` can - be used to retrieve the box itself (in little delta). + be used to retrieve the box itself. """ if not hasattr(self, '_cache_box'): @@ -353,8 +301,7 @@ def get_box(self, z, seed=None): return pb - def get_halo_positions(self, z, N, delta_x, m=None, seed=None, - bias_model=None): + def get_halo_positions(self, z, N, delta_x, m=None, seed=None): """ Generate a set of halo positions. @@ -367,10 +314,7 @@ def get_halo_positions(self, z, N, delta_x, m=None, seed=None, volume. If bias_model == 1, this is the actual number, i.e., assumes we have already done a Poisson draw given . - delta_x : np.ndarray - Halo (over-)density on a 3-D grid. - m : np.ndarray - Array of halo masses [Msun] + Returns ------- @@ -386,21 +330,14 @@ def get_halo_positions(self, z, N, delta_x, m=None, seed=None, # Will modify this in subsequent steps. pvox = np.array([x.ravel() for x in X]).T - # This is sneaky don't worry about it - if bias_model is not None: - _bias_model_ = bias_model - else: - _bias_model_ = self.bias_model - # This is the same thing that powerbox is doing in # `create_discrete_sample`, just trying to have a unified call # sequence for other options here. - if _bias_model_ == 0: + if self.bias_model == 0: n = N / (self.Lbox / self.sim.cosm.h70)**3 - # Expected number of halos in each cell, just scaling mean number - # (over whole box) by 1+delta and voxel volume + # Expected number of halos in each cell n_exp = n * (1. + delta_x) * (self.dx / self.sim.cosm.h70)**3 # Actual number after Poisson draw @@ -413,12 +350,12 @@ def get_halo_positions(self, z, N, delta_x, m=None, seed=None, # In this case, we're increasing the probability that halos are drawn # from overdensities in a potentially halo mass dependent way. - elif _bias_model_ == 1: + elif self.bias_model == 1: n_act = m.size ivox = np.arange(pvox.shape[0]) - delta_flat = delta_x.ravel() + rho_flat = delta_x.ravel() # Right now, alpha(m) = p0 * (m / 1e12)**p1 p0, p1 = self.bias_params @@ -431,7 +368,7 @@ def get_halo_positions(self, z, N, delta_x, m=None, seed=None, pos = np.zeros((m.size, 3)) for h, _m_ in enumerate(m): - P_of_rho = (1+delta_flat)**alpha[h] + P_of_rho = (1+rho_flat)**alpha[h] P_of_rho /= np.sum(P_of_rho) # replace=True means a given voxel can house multiple halos. @@ -455,17 +392,12 @@ def get_halo_positions(self, z, N, delta_x, m=None, seed=None, # Compute "biasing probability" for entire mass bin. lo, hi = m.min(), m.max() mbin = 10**np.mean(np.log10([lo, hi])) - - # This is the HALOGEN approach alpha = p0 * (mbin / 1e12)**p1 - P_of_rho = (1. + delta_flat)**alpha + P_of_rho = (1. + rho_flat)**alpha P_of_rho /= np.sum(P_of_rho) # Take a random draw with probability set by density. - # `ivox` contains the flattened coordinates of each pixel - # as does `P_of_rho`. Passing in `m.size` sets number of - # draws. i = np.random.choice(ivox, p=P_of_rho, replace=self.bias_replacement, size=m.size) @@ -485,696 +417,44 @@ def get_halo_positions(self, z, N, delta_x, m=None, seed=None, # Done return pos - @property - def _cache_subhalo_cdf(self): - return self._cache_subhalo_cdf_ - - @property - def _cache_mgtm(self): - return self._cache_mgtm_ - - @cached_property - def halos(self): - pop0 = self.sim.pops[0] - halos = pop0.halos - # Returning the hidden attribute here means we'll skip hasattr's - return pop0._halos - - def get_halo_masses(self, z, N, logmlim=(11, 15), seed=None, - subhalos=False, Mc=None, iz=None, iM=None): - """ - Draw halos from a model halo mass function. - - Parameters - ---------- - z : int, float - Redshift. - N : int - Number of halos to draw. - mmin : float - Minimum mass [Msun]. - mmax : float - Maximum mass [Msun] - subhalos : bool - If True, draw from subhalo mass function. In this case, must - also provide central halo mass via `Mc`. - Mc : float - Central halo mass [Msun]. Only applicable if `subhalos`=True. - iz : int - Index in redshift array. - iM : int - Index in halo mass array. - - """ + def get_halo_masses(self, z, N, mmin=1e11, mmax=np.inf, seed=None): # Grab dn/dm and construct CDF to randomly sampled HMF. - if (iz is None) and (iM is None): - if subhalos: - iz = None - iM = np.argmin(np.abs(Mc - self.halos.tab_M)) - else: - iz = np.argmin(np.abs(self.halos.tab_z - z)) - iM = None - - if subhalos: - key_id = (iz, iM, logmlim, subhalos) - else: - key_id = (iM, logmlim, subhalos) - - if key_id in self._cache_subhalo_cdf.keys(): - m, cdf = self._cache_subhalo_cdf[key_id] - else: - - # Don't bother with m << mmin halos - mmin = 10**logmlim[0] - mmax = 10**logmlim[1] - - # Compute CDF - if key_id in self._cache_mgtm: - m, dndm, ngtm, ntot = self._cache_mgtm[key_id] - else: - ok = np.logical_and(self.halos.tab_M >= mmin, - self.halos.tab_M < mmax) - - m = self.halos.tab_M[ok==1] - - if subhalos: - assert Mc is not None, "Must provide `Mc` if subhalos=True!" - - # We only keep dn/dlnM for some reason, convert to dn/dm - dndm = self.halos.tab_dndlnm_sub[iM,ok==1] / m - - #ngtm = cumulative_trapezoid(dndm[-1::-1] * m[-1::-1], x=-np.log(m[-1::-1]), - # initial=0)[-1::-1] - - ngtm = self.halos.tab_ngtm_sub[iM,ok==1] #\ - #- self.sim.pops[0].halos.tab_ngtm_sub[iM,immax] - #nltm = ngtm[0] - else: - dndm = self.halos.tab_dndm[iz,ok==1] - ngtm = self.halos.tab_ngtm[iz,ok==1] + # Don't bother with m << mmin halos + iz = np.argmin(np.abs(self.sim.pops[0].halos.tab_z - z)) + ok = np.logical_and(self.sim.pops[0].halos.tab_M >= mmin, + self.sim.pops[0].halos.tab_M < mmax) - ntot = np.trapz(dndm * m, x=np.log(m)) - self._cache_mgtm[key_id] = m, dndm, ngtm, ntot + m = self.sim.pops[0].halos.tab_M[ok==1] + dndm = self.sim.pops[0].halos.tab_dndm[iz,ok==1] - nltm = ntot - ngtm - cdf = nltm / ntot + # Compute CDF + ngtm = cumulative_trapezoid(dndm[-1::-1] * m[-1::-1], x=-np.log(m[-1::-1]), + initial=0)[-1::-1] - self._cache_subhalo_cdf[key_id] = m, cdf + ntot = np.trapz(dndm * m, x=np.log(m)) + nltm = ntot - ngtm + cdf = nltm / ntot # Assign halo masses according to HMF. - if seed is not None: - np.random.seed(seed) - + np.random.seed(seed) r = np.random.rand(N) + #mass = np.exp(np.interp(np.log(r), np.log(cdf), np.log(m))) mass = np.exp(np.interp(r, cdf, np.log(m))) - #mass = np.exp(_interp_linear(r, cdf, np.log(m))) - - return mass - - def get_prof_params(self, num, seed): - """ - Return arrays of Sersic indices, positions angles, and ellipticies. - - Parameters - ---------- - num : int - Number of galaxies to draw. - seed : int - Random seed. Should be determined in LightCone class using the - get_seed_kwargs function for a given co-eval redshift layer. - - Returns - ------- - Tuple with three elements: (sersic index, position angle [deg], - ellipticity = 1 - b / a). - """ - # Uniform for now. - np.random.seed(seed) - - # Sersic indices and position angles - nsers = np.random.random(size=num) * 5.9 + 0.3 - pa = np.random.random(size=num) * 360 - - # Ellipticity = 1 - b/a - ellip = np.random.random(size=num) - - return nsers, pa, ellip - - def get_catalog_halos(self, zlim=None, logmlim=(11,12), popid=0, verbose=True, - satellites=False, logmlim_sats=None, max_sources=None, - lightcone_corr=False): - """ - Get a halo catalog in (RA, DEC, redshift) coordinates. - - .. note :: This is essentially a wrapper around `_get_catalog_from_coeval`, - i.e., we're just figuring out how many layers are needed along the - line of sight and re-generating the relevant cubes. - - Parameters - ---------- - zlim : tuple - Restrict redshift range to be between: - - zlim[0] <= z < zlim[1] - - logmlim : tuple - Restrict halo mass range to be between: - - 10**logmlim[0] <= Mh/Msun 10**logmlim[1] - - Returns - ------- - A tuple containing (ra, dec, redshift, halo mass). - - """ - - pid, pid_par, pid_str = get_pop_info(popid) - - if logmlim_sats is None: - logmlim_sats = logmlim - - if zlim is None: - zlim = self.zlim - - zmin, zmax = zlim - mmin, mmax = 10**np.array(logmlim) - - # Version of Lbox in actual cMpc - L = self.Lbox / self.sim.cosm.h70 - - # First, get full domain info - ze, zmid, Re = self.get_domain_info(zlim=self.zlim, Lbox=self.Lbox) - Rc = bin_e2c(Re) - dz = np.diff(ze) - - # Deterministically adjust the random seeds for the given mass range - # and redshift range. - #fmh = int(logmlim[0] + (logmlim[1] - logmlim[0]) / 0.1) - - # Figure out if we're getting the catalog of a single layer - layer_id = None - for i, Rlo in enumerate(zmid): - zlo, zhi = ze[i:i+2] - - if (zlo == zlim[0]) and (zhi == zlim[1]): - layer_id = i - break - - ## - # Setup random seeds for random rotations and translations - np.random.seed(self.seed_rot) - r_rot = np.random.randint(0, high=4, size=(len(Re)-1)*3).reshape( - len(Re)-1, 3 - ) - - np.random.seed(self.seed_tra) - r_tra = np.random.rand(len(Re)-1, 3) - - ## - # Print-out information about FOV - # arcmin / Mpc -> deg / Mpc - theta_zmin = self.sim.cosm.get_angle_from_length_comoving(zmin, 1) * L / 60. - theta_zmax = self.sim.cosm.get_angle_from_length_comoving(zmax, 1) * L / 60. - - pbar = ProgressBar(Rc.size, name=f"lc(z>={zmin},z<{zmax})", - use=layer_id is None) - pbar.start() - - # Keep running tally of sources - ct = 0 - # Track max_sources - _hit_max_sources = False - - # Track parent halos of satellites - parents = None - - zlo = zmin * 1. - for i, Rlo in enumerate(Re[0:-1]): - pbar.update(i) - - zlo, zhi = ze[i:i+2] - - if layer_id is not None: - if i != layer_id: - continue - - if (zhi <= zlim[0]) or (zlo >= zlim[1]): - continue - - if _hit_max_sources: - break - - seed_kwargs = self.get_seed_kwargs(i, logmlim, pid) - - ## - # Optional: lightcone correction - need_corr = False - if lightcone_corr: - # Use lightcone_max_evol parameter to determine how much - # to sub-sample. Restrict attention to range of halo masses - # for which we expect 1 /per box. - tol = self.lightcone_max_evol - - izmi = np.argmin(np.abs(self.sim.pops[0].halos.tab_z - zmid[i])) - Mh = self.sim.pops[0].halos.tab_M - ngtm = self.sim.pops[0].halos.tab_ngtm[izmi,:] - mmax = np.interp(10., ngtm[-1::-1] * L**3, Mh[-1::-1]) - imax = np.argmin(np.abs(Mh - mmax)) - - okm = np.logical_and(Mh >= mmin, Mh < mmax) - izlo = np.argmin(np.abs(self.sim.pops[0].halos.tab_z - zlo)) - izhi = np.argmin(np.abs(self.sim.pops[0].halos.tab_z - zhi)) - hmf_lo = self.sim.pops[0].halos.tab_dndlnm[izlo,okm==1] - hmf_hi = self.sim.pops[0].halos.tab_dndlnm[izhi,okm==1] - err = np.abs(hmf_hi - hmf_lo) / hmf_hi - - need_corr = np.any(err > tol) - - # How many chunks do we need? - N = 2 - dz = zhi - zlo - while np.any(err > tol): - zsub_e = np.linspace(zlo, zhi, N+1) - zsub = bin_e2c(zsub_e) - - err_prev = err.copy() - - hmfs = [] - err = np.zeros(okm.sum()) - for ll, _z_ in enumerate(zsub_e): - _i_ = np.argmin(np.abs(self.sim.pops[0].halos.tab_z - _z_)) - hmfs.append(self.sim.pops[0].halos.tab_dndlnm[_i_,okm==1]) - - if ll == 0: - continue - - _err = np.abs(hmfs[ll] - hmfs[ll-1]) / hmfs[ll] - err = np.maximum(err, _err) - - N += 1 - - if np.allclose(err, err_prev) and self.verbose*verbose: - print(f"HMF evolution along LoS reached minimum with N={N}") - break - - print(f"! Will sub-cycle in {N} intervals from ({zlo}, {zhi})") - ## - # Need to map these redshift intervals to cMpc / h units - - - # Contains (x, y, z, mass) - # Note that x, y, z are in cMpc / h units, not actual cMpc. - # The values thus run from 0 to Lbox. - if not need_corr: - halos = self.get_halo_population(z=zmid[i], - mmin=mmin, mmax=mmax, verbose=verbose, popid=popid, - **seed_kwargs) - else: - # In this case, generate the halo population in segments. - # The density field will automatically be LC-corrected - # so we just need to handle sub-cycling over a few redshifts - ra = []; dec = []; red = []; mass = [] - for ll, _z_ in enumerate(zsub): - _halos = self.get_halo_population(z=zmid[i], - mmin=mmin, mmax=mmax, verbose=verbose, popid=popid, - zsub=_z_, lightcone_corr=1, **seed_kwargs) - - # Convert to lightcone coordinates to slice on redshift - _ra, _de, _red = \ - self._get_catalog_from_coeval(_halos, zlo=zlo) - - # Select only objects in the right sub-interval - oksub = np.logical_and(_red >= zsub_e[ll], _red < zsub_e[ll+1]) - - # Cut out halos outside zsub_e[ll], zsub_e[ll+1] - _x_, _y_, _z_, _m_ = _halos - - # Note that (x, y, z) here are still [0, Lbox], - # but we constructed `oksub` from the redshifts properly. - ra.extend(_x_[oksub==1]) - dec.extend(_y_[oksub==1]) - red.extend(_z_[oksub==1]) - mass.extend(_m_[oksub==1]) - - halos = np.array(ra), np.array(dec), np.array(red), np.array(mass)#np.array([ra, dec, red, mass]).T - - if (type(halos[0]) != np.ndarray) and (halos[0] is None): - ra = dec = red = mass = None - continue - - if (halos[0].size == 0): - ra = dec = red = mass = None - continue - - ## - # Convert to (ra, dec, redshift) coordinates. - # Note: the conversion from cMpc/h to cMpc occurs inside - # _get_catalog_from_coeval here: - _ra, _de, _red = self._get_catalog_from_coeval(halos, zlo=zlo) - _m = halos[-1] - - # Note that halos outside the specific FoV and redshift - # range are filtered out at a higher level in LightCone.get_catalog - - ## - # For satellites: one more step before moving to next layer. - if satellites: - - ra_s, dec_s, red_s, mass_s, par_id = \ - self.get_catalog_subhalos(_ra, _de, _red, _m, - popid=popid, logmlim=logmlim_sats, - seed=seed_kwargs['seed_sats'] + pid_par, - distribute_in_space=self.distribute_sats_spatially) - - # Replace info about central with satellite info - _ra, _de, _red, _m = ra_s, dec_s, red_s, mass_s - - # Need to hack off satellites that end up outside the FoV - - - # Save results - if ct == 0: - ra = _ra.copy() - dec = _de.copy() - red = _red.copy() - mass = _m.copy() - - if satellites: - parents = par_id.copy() - - else: - ra = np.hstack((ra, _ra)) - dec = np.hstack((dec, _de)) - red = np.hstack((red, _red)) - mass = np.hstack((mass, _m)) - - if satellites: - parents = np.hstack((parents, par_id)) - - ct += 1 - - del _ra, _de, _red, halos, _m - if self.apply_rotations or self.apply_translations: - del _x, _x_, _y, _y_, _z, _z_, _m_ - - if satellites: - del ra_s, dec_s, red_s, mass_s, par_id - - if self.mem_concious: - gc.collect() - - ## - # Done with this co-eval layer - - pbar.finish() - #self._cache_cats[(zmin, zmax, mmin)] = ra, dec, red, mass - return ra, dec, red, mass, parents + #if np.any(np.isnan(mass)): + # print('hey wtf', r[np.argwhere(np.isnan(mass))], r.min(), r.max(), + # np.interp(r[np.argwhere(np.isnan(mass))], cdf, m)) - def get_catalog_subhalos(self, ra_c, dec_c, red_c, mass_c, popid, - logmlim=(11,15), seed=None, distribute_in_space=True): - """ - Get a catalog of satellite galaxies for input central catalog. - - Parameters - ---------- - ra_c : np.ndarray - Right ascension of all central halos [deg]. - dec_c : np.ndarray - Declination of all central halos [deg]. - red_c : np.ndarray - Redshifts of all central halos. - mass_c : np.ndarray - Masses of all central halos [Msun]. - pid_c : np.ndarray - - distribute_in_space : bool - If True, will position subhalos randomly in proportion to the - projected NFW density profile. If False, subhalos will be placed at - the location of their parent central. This is really just an option - implemented for sanity checks. - - """ - - pid, pid_par, pid_str = get_pop_info(popid) - - ## - # All we're going to do is randomly distribute satellites in - # mass according to the subhalo mass function and in space - # using an NFW profile. - - # First, grab a few things we need. This is 2-D (Mc, Msat) - hmf_sub = self.halos.tab_dndlnm_sub - - ok_sub = np.logical_and(self.halos.tab_M >= 10**logmlim[0], - self.halos.tab_M < 10**logmlim[1]) - - # Expected number of subhalos vs. central halo mass. - # Just need to do this once per `logmlim`. - Nexp = np.trapz(hmf_sub[:,ok_sub==1], - x=np.log(self.halos.tab_M[ok_sub==1]), axis=1) - - # Array of radial separations [cMpc] - d = self.sim.halos.tab_R_nfw - - ## - # Just loop to start. Could truncate based on where expected - # number of satellites is effectively zero. - Nc = len(mass_c) - - ## - # Reproducibility is important. - # Make seeds for halo position and mass sampling. - # Note that this is done in a slightly different way from centrals. - # Instead of providing seeds for everything by hand, we use one seed - # to deterministically create seeds for the masses and positions - # of all subhalos for each central. - np.random.seed(seed) - # Recall that max allowed seed value is 2**32 - 1 - # Providing some margin here since we scale below. - seeds_num = np.random.randint(0, high=2**30, size=Nc) - seeds_pos = np.random.randint(0, high=2**30, size=Nc) - seeds_mass = np.random.randint(0, high=2**30, size=Nc) - seeds_occ = np.random.randint(0, high=2**30, size=Nc) - - # Do we really need a new seed for each central? - # It is surprisingly expensive to call np.seed on each iteration - - # Determine closest mass and redshift bins for projected density profile - iM = np.searchsorted(self.halos.tab_M_e, mass_c, - side='right') - 1 - iz = np.searchsorted(self.halos.tab_z, red_c, - side='right') - 1 - - mpc_per_deg = \ - self.sim.cosm.get_length_comoving_from_angle(red_c, 60.) - - ra = [] - dec = [] - red = [] - mass = [] - par_id = [] - for i in range(Nc): - - # Remaining dimension: halos.tab_R_nfw - Sigma = self.halos.tab_Sigma_nfw[iz[i],iM[i],:] - - Nsat_exp = int(Nexp[iM[i]]) - - # Note that some Nexp==0 objects should statistically end up - # with one or even a few satellites, but this should be a really - # small effect and at the moment (at least) not SUs well spent. - if Nsat_exp == 0: - continue - - # Poisson random draw to determine actual number of subhalos, - # given expected number. - #np.random.seed(seeds_num[i]) - Nsat_act_tot = np.random.poisson(Nsat_exp) - - if Nsat_act_tot == 0: - continue - - # Outsources sampling over sub-halo MF - _m = self.get_halo_masses(red_c[i], Nsat_act_tot, - logmlim=logmlim, #seed=seeds_mass[i], - subhalos=True, Mc=mass_c[i], iz=iz[i], iM=iM[i]) - - ## - # Apply occupation fraction - _x, _y, _z, _m = self._filter_by_focc((None, None, None, _m), - red_c[i], None, popid) - - if _m is None: - continue - - Nsat_act = len(_m) - - mass.extend(list(_m)) - - ## - # Now, do positions. Do in 2-D or 3-D? - if distribute_in_space: - - cdf = self.halos.tab_Sigma_nfw_cdf[iz[i],iM[i],:] - - #np.random.seed(seeds_pos[i]) - r = np.random.rand(Nsat_act) - - # Radial displacement of all satellites in cMpc - r_proj_mpc = np.exp(np.interp(r, cdf, np.log(d))) - #r_proj_mpc = np.exp(_interp_linear(r, cdf, np.log(d))) - - r_proj_deg = r_proj_mpc / mpc_per_deg[i] - - # Need to turn into RA and DEC - # Randomly choose an angle - #np.random.seed(seeds_pos[i] * 2) - theta = np.random.rand(Nsat_act) * 2 * np.pi - - # Then convert to x and y displacements - x_deg = np.cos(theta) * r_proj_deg - y_deg = np.sin(theta) * r_proj_deg - - else: - x_deg = y_deg = 0 - - # Save progress - ra.extend(list(ra_c[i] + x_deg)) - dec.extend(list(dec_c[i] + y_deg)) - - ## - # Make some dynamical argument to shift redshifts? - # Someday, sure. For now, just put at same exact z as central. - red.extend([red_c[i]] * Nsat_act) - - # Save index for the parent halo. - par_id.extend([i] * Nsat_act) - - # - #pbar.finish() - - return np.array(ra), np.array(dec), np.array(red), np.array(mass), \ - np.array(par_id, dtype=int) - - def _get_catalog_from_coeval(self, halos, zlo): - """ - Make a catalog in lightcone coordinates (RA, DEC, redshift). - - .. note :: RA and DEC output in degrees. - - """ - - # Right now, in [0, Lbox / h] units. - xmpc, ympc, zmpc, mass = halos - - # Shift coordinates to +/- 0.5 * Lbox - xmpc = (xmpc - 0.5 * self.Lbox) / self.sim.cosm.h70 - ympc = (ympc - 0.5 * self.Lbox) / self.sim.cosm.h70 - - # Move the front edge of the box to redshift `zlo` - # Will automatically use interpolation under the hood in `cosm` - # if interpolate_cosmology_in_z=True. - d0 = self.sim.cosm.get_dist_los_comoving(0, zlo) / cm_per_mpc - - # Translate LOS distances to redshifts. - - # Distance from z=0 to z - dofz = self.sim.cosm._tab_dist_los_co / cm_per_mpc - # - angl = self.sim.cosm._tab_ang_from_co / 60. - # Determine redshift by interpolating distance along z - red = np.interp((zmpc / self.sim.cosm.h70) + d0, dofz, - self.sim.cosm.tab_z) - - # Conversion from physical to angular coordinates - deg_per_mpc = np.interp((zmpc / self.sim.cosm.h70) + d0, dofz, angl) - - ra = xmpc * deg_per_mpc - dec = ympc * deg_per_mpc - - return ra, dec, red - - def _filter_by_focc(self, cat, z, seed_occ, popid): - """ - Take a raw catalog of halos and thin according to occupation fraction. - - Parameters - ---------- - cat : tuple - Contains (x, y, redshift, mass), where x and y can be co-eval box - coordinates or RA and DEC. - z : int, float - Redshift - N : - """ - - _x, _y, _z, mass = cat - N = len(mass) - - # ARES ID, parent ID [if applicable], ID str (user supplied; just -> str) - pid, pid_par, pid_str = get_pop_info(popid) - - ## - # Apply occupation fraction here? - if self.sim.pops[pid].pf['pop_focc'] != 1: - - np.random.seed(seed_occ) - - r = np.random.rand(N) - focc = self.sim.pops[pid].get_focc(z=z, Mh=mass) - - ok = np.ones(N) - ok[r > focc] = 0 - - # For satellites, positions are determined after this step - if _x is None: - pass - else: - _x = _x[ok==1] - _y = _y[ok==1] - _z = _z[ok==1] - - mass = mass[ok==1] - - # Don't really need to see this anymore. - #if verbose: - # print(f"# Applied occupation fraction cut for pop #{popid} at z={z:.2f} in {np.log10(mmin):.1f}-{np.log10(mmax):.1f} mass range.") - # print(f"# [reduced number of halos by {100*(1-ok.sum()/float(ok.size)):.2f}%]") - - if ok.sum() == 0: - return None, None, None, None - else: - focc = r = ok = None - - del focc, ok, r - if self.mem_concious: - gc.collect() - - return _x, _y, _z, mass + return mass def get_halo_population(self, z, seed=None, seed_box=None, seed_pos=None, seed_occ=None, mmin=1e11, mmax=np.inf, randomise_in_cell=True, popid=0, - verbose=True, call_gc=False, apply_focc=True, zsub=None, lightcone_corr=False, **_kw_): + verbose=True, call_gc=False, **_kw_): """ Get a realization of a halo population. - Parameters - ---------- - z : int, float - Redshift, will be used to identify co-eval cube. - seed : int - Random seed for halo masses. - seed_box : int - Random seed for density field. - seed_pos : int - Random seed for halo positions. - seed_occ : int - Random seed for halo occupation. - zsub : - Returns ------- Tuple containing (x, y, z, mass), where x, y, and z are halo positions @@ -1182,18 +462,10 @@ def get_halo_population(self, z, seed=None, seed_box=None, seed_pos=None, """ - if zsub is None: - zsub = z - - # Unpack popid more [as of March 2025] - # (id number in ARES, parent ID number [if satellite], name as str) - pid, pid_par, pid_str = get_pop_info(popid) - - rho = self.get_density_field(z=z, seed=seed_box, - lightcone_corr=lightcone_corr) + pb = self.get_box(z=z, seed=seed_box) # Get mean halo abundance in #/cMpc^3 [note: this is *not* (cMpc/h)^-3] - nbar = self.get_nbar(zsub, mmin=mmin, mmax=mmax) + nbar = self.get_nbar(z, mmin=mmin, mmax=mmax) # Compute expected number of halos in volume h = self.sim.cosm.h70 @@ -1203,12 +475,11 @@ def get_halo_population(self, z, seed=None, seed_box=None, seed_pos=None, # in each voxel independently. Then, generate the appropriate number # of halo masses. if self.bias_model == 0: - pos = self.get_halo_positions(zsub, Nexp, rho, seed=seed_pos) + pos = self.get_halo_positions(z, Nexp, pb.delta_x(), seed=seed_pos) Nact = pos.shape[0] # Draw halo masses from HMF - - mass = self.get_halo_masses(zsub, Nact, logmlim=tuple(np.log10([mmin, mmax])), + mass = self.get_halo_masses(z, Nact, mmin=mmin, mmax=mmax, seed=seed) # In this case, we need to know the masses of halos before we generate @@ -1216,24 +487,20 @@ def get_halo_population(self, z, seed=None, seed_box=None, seed_pos=None, # number of halos in the box, *then* generate their masses, *then* # generate their positions (which are effectivley mass-dependent). elif self.bias_model == 1: - # First generate positions the easy way just to force this method - # to have the same number of halos - pos = self.get_halo_positions(z, Nexp, rho, seed=seed_pos, bias_model=0) # Actual number is a Poisson draw - Nact = pos.shape[0]#np.random.poisson(Nexp) + Nact = np.random.poisson(Nexp) # Draw halo masses from HMF - - mass = self.get_halo_masses(zsub, Nact, logmlim=tuple(np.log10([mmin, mmax])), + mass = self.get_halo_masses(z, Nact, mmin=mmin, mmax=mmax, seed=seed) - pos = self.get_halo_positions(zsub, Nact, rho, m=mass, + pos = self.get_halo_positions(z, Nact, pb.delta_x(), m=mass, seed=seed_pos) else: raise NotImplemented('help') # `pos` is in [0, Lbox / h] domain in each dimension - _x, _y, _z = pos.T + _x, _y, _z = pos.T#(pos.T / h) #- 0.5 * (self.Lbox / h) N = _x.size if N == 0: @@ -1248,7 +515,7 @@ def get_halo_population(self, z, seed=None, seed_box=None, seed_pos=None, # do a quick check that the number smaller than 2x sqrt(mean). Note # that occassionally we might get a bigger difference here, hence the # warning instead of raising an exception. - if (Nerr > 2 * np.sqrt(Nexp)) and (err > 0.2) and self.verbose: + if (Nerr > 2 * np.sqrt(Nexp)) and (err > 0.2): print(f"# WARNING: Error in halo density is {err*100:.0f}% for m in [{np.log10(mmin):.1f},{np.log10(mmax):.1f}]") print(f"# (expected {Nexp:.2f} halos, got {Nact:.0f})") print("# Might be small box issue, but could be OK for massive halos.") @@ -1257,12 +524,33 @@ def get_halo_population(self, z, seed=None, seed_box=None, seed_pos=None, raise ValueError("help") ## - # Apply occupation fraction cut - if apply_focc: - _x, _y, _z, mass = self._filter_by_focc((_x, _y, _z, mass), - z, seed_occ, popid) + # Apply occupation fraction here? + if self.sim.pops[popid].pf['pop_focc'] != 1: + + np.random.seed(seed_occ) + + r = np.random.rand(N) + focc = self.sim.pops[popid].get_focc(z=z, Mh=mass) + + ok = np.ones(N) + ok[r > focc] = 0 + + _x = _x[ok==1] + _y = _y[ok==1] + _z = _z[ok==1] + mass = mass[ok==1] + + if verbose: + print(f"# Applied occupation fraction cut for pop #{popid} at z={z:.2f} in {np.log10(mmin):.1f}-{np.log10(mmax):.1f} mass range.") + print(f"# [reduced number of halos by {100*(1-ok.sum()/float(ok.size)):.2f}%]") + + if ok.sum() == 0: + return None, None, None, None + else: + focc = r = ok = None + + del focc, ok, r, pos + if self.mem_concious: + gc.collect() - ## - # Sort by mass? Otherwise will essentially be in order of pixels as - # determined by np.ravel. That's what we're going with. return _x, _y, _z, mass diff --git a/ares/realizations/NbodySim.py b/ares/realizations/NbodySim.py index c9ad2137f..fd4864543 100644 --- a/ares/realizations/NbodySim.py +++ b/ares/realizations/NbodySim.py @@ -14,7 +14,6 @@ import numpy as np from ..util import ProgressBar from .LightCone import LightCone -from scipy.integrate import cumtrapz from ..simulations import Simulation from scipy.interpolate import interp1d from ..util.Stats import bin_c2e, bin_e2c @@ -25,7 +24,7 @@ except ImportError: pass -class NbodySimCoeval(LightCone): # pragma: no cover +class NbodySim(LightCone): # pragma: no cover def __init__(self, model_name, Lbox=256, dims=128, zmin=0.05, zmax=2, verbose=True, base_dir='ares_mock', seed_rot=None, seed_trans=None, mem_concious=1, apply_rotations=False, apply_translations=False, **kwargs): diff --git a/ares/realizations/NbodySimLC.py b/ares/realizations/NbodySimLC.py deleted file mode 100644 index 659950b66..000000000 --- a/ares/realizations/NbodySimLC.py +++ /dev/null @@ -1,232 +0,0 @@ -""" - -NbodySim.py - -Author: Jordan Mirocha -Affiliation: Jet Propulsion Laboratory -Created on: Sat Dec 3 14:28:58 PST 2022 - -Description: - -""" - -import os -import gc -import numpy as np -from ..util import ProgressBar -from .LightCone import LightCone -from scipy.integrate import cumtrapz -from ..simulations import Simulation -from scipy.interpolate import interp1d -from ..util.Stats import bin_c2e, bin_e2c -from ..physics.Constants import cm_per_mpc - -try: - import powerbox as pbox -except ImportError: - pass - -class NbodySim(LightCone): # pragma: no cover - def __init__(self, model_name, catalog, verbose=True, base_dir='nbody_mock', - fxy=None, fov=None, Lbox=999, dims=999, mem_concious=False, - seed_halo_occ=None, seed_nsers=None, seed_pa=None, dz_max=0.1, - zmin=0.07, zmax=1.4, zchunks=None, include_satellites=0, - seed_profile=None, seed_sats=None, profile_info=None, **kwargs): - """ - Initialize a galaxy population from a simulated halo lightcone. - - Parameters - ---------- - catalog : tuple - - First element: Filename prefix. - Second element: indices in each output file corresponding to - (RA, DEC, z, log10(Mhalo/Msun)). - Third element: Array of redshift chunks at which we have - saved the catalog. - fov : tuple - Can restrict sky area to patch from fov[0] <= RA < fov[1] and - fov[2] <= DEC < fov[3]. If None, will return whole dataset. - """ - - self.verbose = verbose - self.kwargs = kwargs - self.base_dir = base_dir - self.model_name = model_name - self.fxy = fxy - self.fov = fov - self.Lbox = Lbox - self.dims = dims - self.mem_concious = mem_concious - self.zmin = zmin - self.zmax = zmax - self.dz_max = dz_max - self.zlim = zmin, zmax - self.zlayers = zchunks - - self.include_satellites = include_satellites - - x, y = self.fxy - self.fbox = x - 0.5 * fov, x + 0.5 * fov, \ - y - 0.5 * fov, y + 0.5 * fov - self.seed_halo_occ = seed_halo_occ - self.seed_nsers = seed_nsers - self.seed_pa = seed_pa - - # No need for these -- N-body sim does it for us - self.seed_rho = -np.inf - self.seed_halo_mass = -np.inf - self.seed_halo_pos = -np.inf - - # Profiles and satellites - self.seed_profile = seed_profile - self.profile_info = profile_info - self.seed_sats = seed_sats - - self.prefix, self.indices, self.zchunks = catalog - - def get_halo_population(self): - raise NotImplemented('No analog for this in NbodySimLC approach.') - - def get_catalog_halos(self, zlim=None, logmlim=None, popid=0, - seed_occ=None, verbose=True, satellites=False, logmlim_sats=None): - """ - Get a galaxy catalog in (RA, DEC, redshift) coordinates. - - Parameters - ---------- - zlim : tuple - Restrict redshift range to be between: - - zlim[0] <= z < zlim[1]. - - logmlim : tuple - Restrict halo mass range to be between: - - 10**logmlim[0] <= Mh/Msun 10**logmlim[1] - - Returns - ------- - A tuple containing (ra, dec, redshift, ) - - """ - - ## - # First, figure out bounding redshift chunks. - if zlim is not None: - zlo, zhi = zlim - ilo = np.digitize(zlo, self.zchunks[:,0]) - 1 - ihi = np.digitize(zhi, self.zchunks[:,0]) - 1 - else: - zlo, zhi = self.zchunks[0,0], self.zchunks[-1,-1] - ilo = 0 - ihi = self.zchunks.shape[0] - 1 - - ## - # Read at least one chunk. Implies that supplied `zlim` is smaller than - # our chunks, so ilo==ihi. - ihi = max(ihi, ilo+1) - - # Loop over chunks, read-in data - N = 0 - data = None - for i in range(ilo, ihi+1): - - if i > len(self.zchunks) - 1: - break - - z1, z2 = self.zchunks[i] - z = np.mean([z1, z2]) - - fn = f"{self.prefix}_{z1:.2f}_{z2:.2f}.txt" - - ## - # Hack out galaxies outsize `zlim`. - # `data` will be (number of halos, number of fields saved) - _data = np.loadtxt(fn, usecols=self.indices) - - numh = _data.shape[0] - - if verbose: - print(f"! Loaded {fn}. {numh:.1e} halos.") - - ## - # Isolate halos in requested mass range. - if logmlim is not None: - okM = np.logical_and(_data[:,-1] >= logmlim[0], - _data[:,-1] < logmlim[1]) - else: - okM = 1 - ## - # Isolate halos in right z range. - # (should be all except potentially at edges of domain). - if zlim is not None: - okz = np.logical_and(_data[:,-2] >= zlim[0], - _data[:,-2] < zlim[1]) - else: - okz = 1 - - ## - # [optional] isolate halos in desired sky region. - if self.fov is not None: - okp = np.logical_and(_data[:,0] >= self.fbox[0], - _data[:,0] < self.fbox[1]) - okp*= np.logical_and(_data[:,1] >= self.fbox[2], - _data[:,1] < self.fbox[3]) - else: - okp = 1 - - if self.include_satellites and satellites: - okc = 1 - else: - # 0 for centrals! - okc = np.logical_not(np.loadtxt(fn, usecols=[4], unpack=True)) - - ## - # Apply occupation fraction cut - if self.sim.pops[popid].pf['pop_focc'] != 1: - seed_kwargs = self.get_seed_kwargs(i, logmlim, popid) - - np.random.seed(seed_kwargs['seed_occ']) - - r = np.random.rand(numh) - focc = self.sim.pops[popid].get_focc(z=z, Mh=10**_data[:,3]) - - oko = np.ones(numh) - oko[r > focc] = 0 - - if verbose: - print(f"# Applied occupation fraction cut for pop #{popid} at z={z:.2f} in {logmlim[0]:.1f}-{logmlim[1]:.1f} mass range.") - print(f"# [reduced number of halos by {100*(1-oko.sum()/float(oko.size)):.2f}%]") - - else: - oko = 1 - - ok = okM*okz*okp*okc*oko - - if not np.any(ok): - continue - - ## - # Append to any previous chunk's data. - if data is None: - data = _data[ok==1,:].copy() - else: - data = np.vstack((_data[ok==1,:], data)) - - - ## - # Possible to not get any hits - if data is None: - return None, None, None, None - - ## - # Return transpose, so users can run, e.g., - # >>> ra, dec, z, logm = .get_catalog() - # First, need to 10** the halo masses. - _x_, _y_, _z_, _m_ = data.T - - # MiceCAT uses h=0.7 - data = np.array([_x_, _y_, _z_, 10**_m_ / 0.7]) - - return data diff --git a/ares/realizations/__init__.py b/ares/realizations/__init__.py index e19d338bf..30bb087e4 100644 --- a/ares/realizations/__init__.py +++ b/ares/realizations/__init__.py @@ -1,2 +1,2 @@ from ares.realizations.LogNormal import LogNormal -from ares.realizations.NbodySimLC import NbodySim +from ares.realizations.NbodySim import NbodySim diff --git a/ares/simulations/Simulation.py b/ares/simulations/Simulation.py index 410a7aa69..964a6844f 100644 --- a/ares/simulations/Simulation.py +++ b/ares/simulations/Simulation.py @@ -132,7 +132,7 @@ def get_ebl(self, wave_units='mic', flux_units='SI', pops=None, data = {} if not self.background_intensity._run_complete: - self.background_intensity.run()#include_pops=pops) + self.background_intensity.run() for i in range(len(self.pops)): if i in data: @@ -172,8 +172,8 @@ def get_ebl(self, wave_units='mic', flux_units='SI', pops=None, return data def get_ebl_ps(self, scales, waves, waves2=None, wave_units='mic', - scale_units='ell', flux_units='SI', pops=None, - include_inter_pop=True, cache_ipop_mtx=None, **kwargs): + scale_units='ell', flux_units='SI', dimensionless=False, pops=None, + include_inter_pop=True, **kwargs): """ Compute power spectrum of EBL at some observed wavelength(s). @@ -217,17 +217,11 @@ def get_ebl_ps(self, scales, waves, waves2=None, wave_units='mic', Returns ------- - Tuple containing (scales, waves, total power spectrum, PS by pop). + Tuple containing (scales, 2 pi / scales or l*l(+1), + waves, power spectra). - Note the total power spectrum is a 2-D array with shape - (len(scales), len(waves)), while the final "PS by pop" array is 4-D, - as it saves separately all of the constituent terms, and is thus - (len(pops), len(pops), len(scales), len(waves)). So, the - element [0,0] encodes the PS of star-forming galaxies x star-forming - galaxies, [1,1] is quiescent galaxies x quiescent galaxies, and so on. - - Saves as attributes - ------------------- + Note that the power spectra are return as 2-D arrays with shape + (len(scales), len(waves)) """ @@ -247,6 +241,22 @@ def get_ebl_ps(self, scales, waves, waves2=None, wave_units='mic', "If `waves` is 2-D, must have shape (num waves, 2)." waves_is_2d = True + # Prep scales + if scale_units.lower() in ['l', 'ell']: + scales_inv = np.sqrt(scales * (scales + 1)) + # Squared below hence the sqrt here. + else: + if scale_units.lower().startswith('deg'): + scale_rad = scales * (np.pi / 180.) + elif scale_units.lower() == 'arcmin': + scale_rad = (scales / 60.) * (np.pi / 180.) + elif scale_units.lower() == 'arcsec': + scale_rad = (scales / 3600.) * (np.pi / 180.) + else: + raise NotImplemented(f"Don't recognize `scale_units`={scale_units}") + + scales_inv = 2 * np.pi / scale_rad + if wave_units.lower().startswith('mic'): pass else: @@ -258,7 +268,7 @@ def get_ebl_ps(self, scales, waves, waves2=None, wave_units='mic', if waves2 is None: waves2 = waves - #ps = np.zeros((len(self.pops), len(scales), len(waves))) + ps = np.zeros((len(self.pops), len(scales), len(waves))) px = np.zeros((len(self.pops), len(self.pops), len(scales), len(waves))) # Save contributing pieces @@ -285,24 +295,12 @@ def get_ebl_ps(self, scales, waves, waves2=None, wave_units='mic', if j not in pops: continue - # First, check for cache. This is a pro move. - if (cache_ipop_mtx is not None) and include_inter_pop: - _px, _pz = cache_ipop_mtx - _npops = _px.shape[0] - # If we're covered by the cache, use it - if i < _npops: - px[i,j,:,:] = _px[i,j,:,:].copy() - ps_z[i,j,:,:,:] = _pz[i,j,:,:,:].copy() - continue - for k, wave in enumerate(waves): - # Will default to 1h + 2h + shot if j == i: - px[i,i,:,k] = pop.get_ps_obs(scales, + ps[i,:,k] = pop.get_ps_obs(scales, wave_obs1=wave, wave_obs2=waves2[k], scale_units=scale_units, **kwargs) - #px[i,i,:,k] = ps[i,:,k].copy() ps_z[i,i,:,k,:] = pop._ps_obs_integrand.copy() continue @@ -321,98 +319,36 @@ def get_ebl_ps(self, scales, waves, waves2=None, wave_units='mic', #if hasattr(pop.halos, '_tab_u_nfw'): # del pop.halos._tab_u_nfw - - self.px_natu = px.copy() - self.pz_natu = ps_z.copy() + ## + # Increment `ps` with cross terms. + # Convention is that fluctuations for population `i` includes + # all crosses with + ps += px.sum(axis=1) ## # Modify PS units before return if flux_units.lower() == 'si': - #ps *= cm_per_m**4 / erg_per_s_per_nW**2 + ps *= cm_per_m**4 / erg_per_s_per_nW**2 px *= cm_per_m**4 / erg_per_s_per_nW**2 ps_z *= cm_per_m**4 / erg_per_s_per_nW**2 elif flux_units.lower() == 'mjy': - #ps *= 1e17 + ps *= 1e17 px *= 1e17 ps_z *= 1e17 - ptot = px.sum(axis=0).sum(axis=0) - if pops is None: hist = self.history # poke - self._history['ps_nirb'] = scales, waves, ptot, px + self._history['ps_nirb'] = scales, scales_inv, waves, ps + if dimensionless: + ps *= scales_inv[None,:,None]**2 / 2. / np.pi + px *= scales_inv[None,:,None]**2 / 2. / np.pi + + self.ps_auto = ps self.ps_cross = px self.ps_zall = ps_z - return scales, waves, ptot, px - - def get_number_counts(self, wave, magbins, window=201, zbins=None, zmax=None, nsub=10., pops=None): - """ - Determine number counts (per deg^2) summed over all source populations. - - Parameters - ---------- - wave : int, float - Observed wavelength of interest [Angstroms]. - magbins : np.ndarray - Array of AB magnitude bins (centers) at which to compute counts. - - Returns - ------- - Counts (np.ndarray) in number / deg^2 in provided `magbins`. - - """ - - if zbins is not None: - tot = np.zeros((magbins.size, zbins.shape[0], len(self.pops))) - else: - tot = np.zeros_like(magbins) - - for i, pop in enumerate(self.pops): - - if pops is not None: - if i not in pops: - continue - - # No IHL here - if (pop.is_emission_extended) and (not pop.is_satellite_pop): - continue - - ## - # Can keep redshift axis if we want. - if zbins is not None: - for j, zbin in enumerate(zbins): - dz = (zbin[1] - zbin[0]) / nsub - num = pop.get_number_counts(magbins, x=wave, - window=window, dlam=10, - zbin=dz, zmin=zbin[0], zmax=zbin[1]) - - tot[:,j,i] = num - - continue - - ## - # Otherwise, lump everything together. - if zmax is None: - zmax = pop.zform - - num_hiz = pop.get_number_counts(magbins, x=wave, - window=window, dlam=10, - zbin=0.1, zmin=2., zmax=zmax) - - num_midz = pop.get_number_counts(magbins, x=wave, - window=window, dlam=10, - zbin=0.01, zmin=0.05, zmax=2) - - num_lowz = pop.get_number_counts(magbins, x=wave, - window=window, dlam=10, - zbin=0.001, zmin=0.006, zmax=0.05) - - tot += num_midz + num_lowz + num_hiz - - return tot - + return scales, scales_inv, waves, ps @property def pops(self): diff --git a/ares/sources/Galaxy.py b/ares/sources/Galaxy.py index 969937187..06c34b2f8 100644 --- a/ares/sources/Galaxy.py +++ b/ares/sources/Galaxy.py @@ -109,24 +109,10 @@ def get_sfr(self, t, tobs, **kwargs): sfr = 0 else: pass - elif sfh == 'exp_decl_quench': - norm = kwargs['norm'] - tau = kwargs['tau'] - tq = kwargs['tq'] - - sfr = norm * np.exp(-t / tau) - if type(sfr) == np.ndarray: - sfr[t > tq] = 0 - else: - if t > tq: - sfr = 0 - else: - pass elif sfh == 'exp_rise': - #norm = kwargs['norm'] + norm = kwargs['norm'] tau = kwargs['tau'] - sfr = kwargs['norm'] * np.exp(-tobs / tau) * np.exp(t / tau) - + sfr = norm * np.exp(-self.tH / tau) * np.exp(t / tau) elif sfh == 'const': norm = kwargs['norm'] if 't0' in kwargs: @@ -159,55 +145,19 @@ def get_sfr(self, t, tobs, **kwargs): ## # Null SFR for times after time of observation! - # Need to be careful here: we're actually going to keep the SFR - # one grid point beyond (lower than) tobs, so that later when - # we interpolate to tobs we'll get a non-zero value. This is - # important for validating that we get the right SFR out of our - # optimization procedure. In short, it'd be easier to do - # `sfr[t > tobs] = 0` but it'll screw things up one step down - # the road from here. - # Note: `t` is descending, i.e., t[0] should be near the Hubble - # time at z=0, t[-1] very high redshift. - if type(sfr) == np.ndarray: - sfr[t > tobs] = 0 - else: - if t > tobs: - return 0 - else: - return sfr - - return sfr - + # Be careful: if time tobs provided is between grid points, we might + # if type(sfr) == np.ndarray: k = np.argmin(np.abs(t - tobs)) - #print('hey cmon', tobs, k, t[k], t.size, t[0], t[-1], t.max()) - - # Ignore this if at edge of array (i.e., tobs=t since Big Bang) - # In this case there are no array elements that need nulling. + # Ignore this is at edge of array (i.e., tobs=t since Big Bang) if k == 0: pass - # If this closest grid point to tobs is at later times than tobs - # we're OK and need not take any further action - elif tobs < t[k]: - pass + elif t[k] < tobs: + k -= 1 else: - #assert tobs > t[k] - # If the closest grid point we found is still - while k > 0: - k -= 1 - - if tobs < t[k]: - break - #else: - # k -= 2 - - - #print('k after modification', k) - + k -= 2 sfr[t > t[k]] = 0 - - else: if t > tobs: sfr = 0 @@ -220,9 +170,8 @@ def _get_freturn(self, t): """ return 0.05 * np.log(1. + t / 1.4) - def get_kwargs(self, t, mass, sfr, disp=False, mtol=0.01, tau_guess=1e3, - sfh=None, mass_return=False, tarr=None, xtol=0.01, ftol=0.01, - direct_integration=False, past_ms=None, **kwargs): + def get_kwargs(self, t, mass, sfr, disp=False, mtol=0.05, tau_guess=1e3, + sfh=None, mass_return=False, tarr=None, **kwargs): """ Determine the free parameters of a model needed to produce stellar mass `mass` and star formation rate `sfr` at time `t` [since Big Bang / Myr]. @@ -249,13 +198,8 @@ def get_kwargs(self, t, mass, sfr, disp=False, mtol=0.01, tau_guess=1e3, / (10**logtau * (np.exp(t / 10**logtau) - 1.)) func = lambda logtau: np.abs(np.log10(f_sSFR(logtau) / (sfr / mass))) - best = fmin(func, np.log10(tau_guess), - disp=disp, full_output=disp, ftol=ftol, xtol=xtol) - - if disp: - best, fval, niter, neval, dunno = best - - tau = 10**best[0] + tau = 10**fmin(func, np.log10(tau_guess), + disp=disp, full_output=disp, ftol=0.01, xtol=0.001)[0] # Can analytically solve for normalization once tau in hand. norm = sfr / np.exp(-t / tau) @@ -270,41 +214,49 @@ def get_kwargs(self, t, mass, sfr, disp=False, mtol=0.01, tau_guess=1e3, ## # Refine if mass_return is on. if mass_return: + def func(pars): + logA, logtau = pars + sfr0 = self.get_sfr(t, t, norm=10**logA, tau=10**logtau, + sfh=sfh, **kwargs) + dSFR = np.log10(sfr0 / sfr) + + mhist = self.get_mass(tarr, t, norm=10**logA, tau=10**logtau, + mass_return=True, sfh=sfh, **kwargs) + + if not np.all(np.diff(tarr) > 0): + _mass = 10**np.interp(np.log10(t), np.log10(tarr[-1::-1]), + np.log10(mhist[-1::-1])) + else: + _mass = 10**np.interp(np.log10(t), np.log10(tarr), + np.log10(mhist)) - def _get_sfh(tt, pars): - norm = 10**pars[0] - tau = 10**pars[1] - return norm * np.exp(-tt / tau) - - def _get_mass(pars): - norm = 10**pars[0] - tau = 10**pars[1] - _mass = 1e6 * quad(lambda tt: _get_sfh(tt, pars) * (1 - self._get_freturn(t - tt)), - 0, t)[0] - return _mass - - def _penalty(pars): - norm = 10**pars[0] - tau = 10**pars[1] - - _mass = _get_mass(pars) - _sfr = _get_sfh(t, pars) - dMst = np.log10(_mass / mass) - dSFR = np.log10(_sfr / sfr) return abs(dSFR) + abs(dMst) - best = fmin(_penalty, [np.log10(norm), np.log10(tau)], - disp=disp, full_output=disp, ftol=ftol, xtol=xtol) + best = fmin(func, [np.log10(norm), np.log10(tau)], + disp=disp, full_output=disp, ftol=0.0001, xtol=0.0001) - if disp: - best, fval, niter, neval, dunno = best - norm, tau = 10**best - _mass = _get_mass(best) - _sfr = _get_sfh(t, best) + mhist = self.get_mass(tarr, t, norm=norm, tau=tau, + mass_return=True, sfh=sfh, **kwargs) + shist = self.get_sfr(tarr, t, norm=norm, tau=tau, + sfh=sfh, **kwargs) + + if not np.all(np.diff(tarr) > 0): + _mass = 10**np.interp(np.log10(t), np.log10(tarr[-1::-1]), + np.log10(mhist[-1::-1])) + _sfr = 10**np.interp(np.log10(t), np.log10(tarr[-1::-1]), + np.log10(shist[-1::-1])) + else: + _mass = 10**np.interp(np.log10(t), np.log10(tarr), + np.log10(mhist)) + _sfr = 10**np.interp(np.log10(t), np.log10(tarr), + np.log10(shist)) + + + ## # Save to dict kw = {'norm': norm, 'tau': tau, 'sfh': 'exp_decl'} @@ -316,7 +268,7 @@ def _penalty(pars): / (10**logtau * (np.exp(t / 10**logtau) - np.exp(t0 / 10**logtau))) func = lambda logtau: np.abs(np.log10(f_sSFR(logtau) / (sfr / mass))) tau = 10**fmin(func, np.log10(tau_guess), - disp=disp, full_output=disp, ftol=ftol, xtol=xtol)[0] + disp=disp, full_output=disp, ftol=0.01, xtol=0.001)[0] # Can analytically solve for normalization once tau in hand. norm = sfr / np.exp(-t / tau) @@ -352,10 +304,7 @@ def func(pars): return abs(dSFR) + abs(dMst) best = fmin(func, [np.log10(norm), np.log10(tau)], - disp=disp, full_output=disp, ftol=ftol, xtol=xtol) - - if disp: - best, fval, niter, neval, dunno = best + disp=disp, full_output=disp, ftol=0.0001, xtol=0.0001) norm, tau = 10**best @@ -380,188 +329,115 @@ def func(pars): kw['sfh'] = 'exp_decl_trunc' kw['t0'] = t0 - elif sfh == 'exp_decl_quench': - assert past_ms is not None, "Must provide `past_ms` for exp_decl_quench model!" - assert 'tq' in kwargs, "Must provide `tq` for exp_decl_quench model!" - - tq = kwargs['tq'] - # This is like doing a normal exp_decl model except we're hunting for a galaxy - # on the main sequence at some time in the past, t_quench, rather than t_obs. - - # For first guess with no mass loss, can just assume mass now is mass then. - _sfr = np.interp(mass, past_ms[0], past_ms[1]) - # Note: `sfr` will be None for this case - - # Note `tq`` here instead of `t` - # This is just for a guess at tau remember, hence use of `mass`. + elif sfh == 'exp_rise': f_sSFR = lambda logtau: 1e-6 \ - / (10**logtau * (np.exp(tq / 10**logtau) - 1.)) - func = lambda logtau: np.abs(np.log10(f_sSFR(logtau) / (_sfr / mass))) - - best = fmin(func, np.log10(tau_guess), - disp=disp, full_output=disp, ftol=ftol, xtol=xtol) - - if disp: - best, fval, niter, neval, dunno = best - - tau = 10**best[0] + / (10**logtau * (1 - np.exp(-t / 10**logtau))) + func = lambda logtau: np.abs(np.log10(f_sSFR(logtau) / (sfr / mass))) + tau = 10**fmin(func, np.log10(tau_guess), + disp=disp, full_output=disp, ftol=0.001, xtol=0.001)[0] # Can analytically solve for normalization once tau in hand. - norm = _sfr / np.exp(-t / tau) + norm = sfr / np.exp(t / tau) / np.exp(-self.tH / tau) - # Stellar mass = A * tau * (1 - e^(-t / tau)) - # For rising history, mass = A * tau * (e^(t / tau) - 1) - _mass = 1e6 * norm * tau * (1 - np.exp(-t / tau)) + _sfr = sfr - print('tau guess', tau) - print('norm', norm) - print('_sfr', _sfr) - print('_mass', _mass) - print('mass', mass) + _mass = 1e6 * norm * np.exp(-self.tH / tau) * \ + tau * (np.exp(t / tau) - 1) ## # Refine if mass_return is on. if mass_return: + def func(pars): + logA, logtau = pars + sfr0 = self.get_sfr(t, t, norm=10**logA, tau=10**logtau, + sfh=sfh, **kwargs) + dSFR = np.log10(sfr0 / sfr) - # This is basically the same as the exp_decl history except we're - # going to evaluate whether the past_ms=(mstell, SFR) jive with the main - # sequence provided AND whether the present mass jives with what the user set - - def _get_sfh(tt, pars): - if tt > tq: - return 0 - - norm = 10**pars[0] - tau = 10**pars[1] - - return norm * np.exp(-tt / tau) - - def _get_mass(pars, tobs): - norm = 10**pars[0] - tau = 10**pars[1] - _mass = 1e6 * quad(lambda tt: _get_sfh(tt, pars) * (1 - self._get_freturn(tobs - tt)), - 0, tobs)[0] - return _mass - - def _penalty(pars): - norm = 10**pars[0] - tau = 10**pars[1] - - _mass_now = _get_mass(pars, t) - _mass_then = _get_mass(pars, tq) - _sfr_then = _get_sfh(tq, pars) - - _mass_then_from_ms = np.interp(_sfr_then, past_ms[1], past_ms[0]) - _sfr_then_from_ms = np.interp(_mass_then, past_ms[0], past_ms[1]) - - dMst = np.log10(_mass_now / mass) \ - + np.log10(_mass_then / _mass_then_from_ms) - dSFR = np.log10(_sfr_then / _sfr_then_from_ms) - - #print(f'mass now v then: {_mass_now:.2e} v {_mass_then:.2e}') - - #print('hey', pars, np.log10(_mass_now / mass), np.log10(_mass_then / _mass_then_from_ms), dSFR) - - return abs(dSFR) + abs(dMst) - - best = fmin(_penalty, [np.log10(norm), np.log10(tau)], - disp=disp, full_output=disp, ftol=ftol, xtol=xtol) + mhist = self.get_mass(tarr, t, norm=10**logA, tau=10**logtau, + mass_return=True, sfh=sfh, **kwargs) - if disp: - best, fval, niter, neval, dunno = best - - norm, tau = 10**best + if not np.all(np.diff(tarr) > 0): + _mass = 10**np.interp(np.log10(t), np.log10(tarr[-1::-1]), + np.log10(mhist[-1::-1])) + else: + _mass = 10**np.interp(np.log10(t), np.log10(tarr), + np.log10(mhist)) - # These are used to check for convergence - _mass = _get_mass(best, t) - _mass_then = _get_mass(best, tq) + dMst = np.log10(_mass / mass) - _sfr = _get_sfh(tq, best) - sfr = np.interp(_mass_then, past_ms[0], past_ms[1]) - ## - # Save to dict - kw = {'norm': norm, 'tau': tau, 'sfh': 'exp_decl_quench', 'tq': tq} + return abs(dSFR) + abs(dMst) - elif sfh == 'exp_rise': - # In limit of no mass return, can analytically determine tau. - # Usually we allow mass return in which case we'll use this as - # an initial guess to the iterative solver. - f_sSFR = lambda logtau: 1e-6 \ - / (10**logtau * (1 - np.exp(-t / 10**logtau))) - func = lambda logtau: np.abs(np.log10(f_sSFR(logtau) / (sfr / mass))) - tau = 10**fmin(func, np.log10(tau_guess), - disp=disp, full_output=disp, ftol=ftol, xtol=xtol)[0] + ## + # Run minimization + best = fmin(func, [np.log10(norm), np.log10(tau)], + disp=disp, full_output=disp, ftol=0.001, xtol=0.001) - # Can analytically solve for normalization once tau in hand. - #norm = sfr / np.exp(t / tau) / np.exp(-tobs / tau) + norm, tau = 10**best - _sfr = sfr + mhist = self.get_mass(tarr, t, norm=norm, tau=tau, + mass_return=True, sfh=sfh, **kwargs) + shist = self.get_sfr(tarr, t, norm=norm, tau=tau, + sfh=sfh, **kwargs) - #_mass = 1e6 * norm * np.exp(-tobs / tau) * \ - # tau * (np.exp(t / tau) - 1) - _mass = tau * sfr + if not np.all(np.diff(tarr) > 0): + _mass = 10**np.interp(np.log10(t), np.log10(tarr[-1::-1]), + np.log10(mhist[-1::-1])) + _sfr = 10**np.interp(np.log10(t), np.log10(tarr[-1::-1]), + np.log10(shist[-1::-1])) + else: + _mass = 10**np.interp(np.log10(t), np.log10(tarr), + np.log10(mhist)) + _sfr = 10**np.interp(np.log10(t), np.log10(tarr), + np.log10(shist)) - ## - # Refine if mass_return is on. - if mass_return: - - def _get_mass(tau): - _sfh = lambda tt: sfr * np.exp(-t / tau) * np.exp(tt / tau) - _mass = 1e6 * quad(lambda tt: _sfh(tt) * (1 - self._get_freturn(t - tt)), 0, t)[0] - return _mass - - def _penalty(pars): - tau = 10**pars[0] - _mass = _get_mass(tau) - dMst = np.log10(_mass / mass) - - # No penalty for SFR -- guaranteed by construction. - return abs(dMst) - # - best = fmin(_penalty, [np.log10(tau)], - disp=disp, full_output=disp, ftol=ftol, xtol=xtol) - tau = 10**best[0] - kw['tau'] = tau - _mass = _get_mass(tau) - # Fools get_sfr routine into doing an exponential rise! kw['tau'] = tau - kw['norm'] = sfr - + kw['norm'] = norm kw['sfh'] = 'exp_rise' elif sfh == 'const': - # Not quite analytic due to mass return - # but we'll use quad to avoid use of `tarr` which - # can introduce numerical errors. if mass_return: + _kw = kwargs.copy() - # Can just do this at high precision numerically - # Remember: we're solving for t_0, i.e., when star - # formation began - def func(pars): - log10t0 = pars[0] - t0 = 10**log10t0 + # Means this is a fallback option + if 't0' in _kw: + del _kw['t0'] - dt = t - t0 + def func(pars): + logt0 = pars[0] + mhist = self.get_mass(tarr, t, norm=sfr, t0=10**logt0, + mass_return=True, sfh=sfh, **_kw) - _mass = sfr * 1e6 * quad(lambda tt: 1 - self._get_freturn(tt - t0), - t0, t)[0] + if not np.all(np.diff(tarr) > 0): + _mass = 10**np.interp(np.log10(t), np.log10(tarr[-1::-1]), + np.log10(mhist[-1::-1])) + else: + _mass = 10**np.interp(np.log10(t), np.log10(tarr), + np.log10(mhist)) dMst = np.log10(_mass / mass) -# + return abs(dMst) - best = fmin(func, [np.log10(0.5 * t)], - disp=disp, full_output=disp, ftol=ftol, xtol=xtol) + best = fmin(func, [np.log10(t*0.5)], + disp=disp, full_output=disp, ftol=0.001, xtol=0.001) t0 = 10**best[0] + mhist = self.get_mass(tarr, t, norm=sfr, t0=t0, + mass_return=True, sfh=sfh, **_kw) + + if not np.all(np.diff(tarr) > 0): + _mass = 10**np.interp(np.log10(t), np.log10(tarr[-1::-1]), + np.log10(mhist[-1::-1])) + else: + _mass = 10**np.interp(np.log10(t), np.log10(tarr), + np.log10(mhist)) + kw['norm'] = sfr kw['t0'] = t0 kw['sfh'] = 'const' kw['tau'] = np.inf - else: kw['norm'] = sfr kw['tau'] = np.inf @@ -592,10 +468,7 @@ def func(pars): return abs(dSFR) + abs(dMst) best = fmin(func, [1, np.log10(tau_guess)], - disp=disp, full_output=disp, ftol=ftol, xtol=xtol) - - if best: - best, fval, niter, neval, dunno = best + disp=disp, full_output=disp, ftol=0.01, xtol=0.01) norm, tau = 10**best @@ -632,10 +505,7 @@ def func(pars): ## # Run minimization best = fmin(func, [np.log10(norm), np.log10(tau)], - disp=disp, full_output=disp, ftol=ftol, xtol=xtol) - - if disp: - best, fval, niter, neval, dunno = best + disp=disp, full_output=disp, ftol=0.001, xtol=0.001) norm, tau = 10**best @@ -663,18 +533,13 @@ def func(pars): else: raise NotImplemented("help!") - # Just keep so we don't have to recompute later. - kw['sfr_obs'] = _sfr - kw['mass_obs'] = _mass - ## - # Check stellar mass -- if way above/below requested `mass`, then the + # Check stellar mass -- if way above requested `mass`, then the # requested history is inadequate. Switch to something else, potentially. merr = abs(np.log10(_mass / mass)) serr = abs(np.log10(_sfr / sfr)) - if (merr <= mtol) and (serr <= mtol): - print(f"* Found acceptable solution with kw={kw}") + if (merr < mtol) and (serr < mtol): return kw # If we're not allowing a fallback option in the event that this @@ -688,65 +553,29 @@ def func(pars): return kw - low_or_high_m = 'low' if _mass < mass else 'high' - low_or_high_sfr = 'low' if _sfr < sfr else 'high' - - if np.isnan(merr) or np.isnan(serr): - - print("WARNING: NaN in mass and/or SFR ratio:") - print(f"Mass requested: {mass:.3e}") - print(f"Mass recovered: {_mass:.3e}") - - print(f"SFR requested: {sfr:.3e}") - print(f"SFR recovered: {_sfr:.3e}") - - print(kw) - - ## - # If we're here, we're exploring fallback options. - print(f"! Summary of recoveries for sfh={sfh}: kw={kw}") - print(f"! Retrieved mass is {low_or_high_m} by {np.log10(_mass / mass):.5f} dex (mtol={mtol}).") - print(f"! Retrieved SFR is {low_or_high_sfr} by {np.log10(_sfr / sfr):.5f} dex (stol={mtol}).") - - # If we already tried our fallback option, try a constant SFR as a last resort. - # Should always work. - if (kw['sfh'] != self.pf['source_sfh']): - if self.pf['source_fallback_last_resort']: - #print("Double fail?") - #print(err, np.log10(_mass), np.log10(mass), sfr, kw) - #input('enter>') - sfh_fall = 'const' - else: - print(f"Failing on sfh={kw['sfh']}, not allowing last resort try.") - return kw + if kw['sfh'] != self.pf['source_sfh']: + #print("Double fail?") + #print(err, np.log10(_mass), np.log10(mass), sfr, kw) + #input('enter>') + sfh_fall = 'const' else: sfh_fall = self.pf['source_sfh_fallback'] - - print(f"! Let's try this again with sfh={sfh_fall}...") - kw = self.get_kwargs(t, mass, sfr, disp=disp, - tau_guess=1, + ## + # If we're here, we're exploring fallback options. + print(f"Retrieved mass is off by {merr:.3f} relative to mtol.") + print(f"Let's try this again with sfh={sfh_fall}...") + kw = self.get_kwargs(t, mass, sfr, disp=disp, tau_guess=tau_guess, mtol=mtol, sfh=sfh_fall, mass_return=mass_return, tarr=tarr, - ftol=ftol, xtol=xtol, **kwargs) return kw - def get_mass(self, t, tobs, mass_return=False, direct_integration=0, **kwargs): + def get_mass(self, t, tobs, mass_return=False, **kwargs): """ Return stellar mass for a given SFH model, integrate analytically when possible. """ - if direct_integration: - if 't0' in kwargs: - t0 = kwargs['t0'] - else: - t0 = 0 - - sfr = lambda tt: self.get_sfr(tt, tobs, direct_integration=1, **kwargs) - #return np.array([quad(func, t0, tt) for tt in t]) - return quad(lambda tt: sfr(tt) * (1 - self._get_freturn(tobs - tt)), t0, tobs)[0] * 1e6 - if 'sfh' in kwargs: sfh = kwargs['sfh'] else: @@ -807,7 +636,7 @@ def get_mass(self, t, tobs, mass_return=False, direct_integration=0, **kwargs): raise NotImplemented('help') def get_spec(self, zobs, t=None, sfh=None, mass=None, sfr=None, waves=None, - tau_guess=1e3, use_pbar=True, hist={}, units_out='erg/s/Hz', tobs=None, **kwargs): + tau_guess=1e3, use_pbar=True, hist={}, units_out='erg/s/Hz', **kwargs): """ Return the rest-frame spectrum of a galaxy at observed redshift, `zobs`. @@ -861,7 +690,7 @@ def get_spec(self, zobs, t=None, sfh=None, mass=None, sfr=None, waves=None, # General case: synthesize SED if perform_synthesis: spec = self.synth.get_spec_rest(sfh=sfh_asc, tarr=tasc, - waves=waves, zobs=zobs, tobs=tobs, load=False, use_pbar=use_pbar, + waves=waves, zobs=zobs, load=False, use_pbar=use_pbar, hist=hist, units_out=units_out) return spec diff --git a/ares/sources/Source.py b/ares/sources/Source.py index 130aacdad..d4bb4c241 100644 --- a/ares/sources/Source.py +++ b/ares/sources/Source.py @@ -454,7 +454,7 @@ def get_ang_from_x(self, x, units='eV'): else: out = h_p * c / erg_per_ev / np.array(xout) / 1e-8 - # Check for order change, since get_ev_from_x always returns in + # Check for order change, since get_ev_from_x aways returns in # ascending energy. Want to match input order of `x`. # In other words, match order of input `x` unless we're converting # from wavelength to energy. diff --git a/ares/sources/SynthesisModel.py b/ares/sources/SynthesisModel.py index a7c9bc560..41d71b5a6 100644 --- a/ares/sources/SynthesisModel.py +++ b/ares/sources/SynthesisModel.py @@ -364,8 +364,8 @@ def _cache_L(self, kwds): if not hasattr(self, '_cache_L_'): self._cache_L_ = {} - #if kwds in self._cache_L_: - # return self._cache_L_[kwds] + if kwds in self._cache_L_: + return self._cache_L_[kwds] return None @@ -454,8 +454,6 @@ def get_lum_per_sfr_of_t(self, x=1600., window=1, band=None, yield_UV[i] = data[i1,i] * dlam \ / (self.tab_energies_c[i1] * erg_per_ev) else: - # Multiplying by wavelength here just prepares for - # integral over log(wavelength). if 'erg' in units_out.lower(): integrand = data[i1:i0,i] * self.tab_waves_c[i1:i0] else: @@ -464,6 +462,8 @@ def get_lum_per_sfr_of_t(self, x=1600., window=1, band=None, yield_UV[i] = np.trapz(integrand, x=np.log(self.tab_waves_c[i1:i0])) + + else: wave = self.get_ang_from_x(x, units=units) j = np.argmin(np.abs(wave - self.tab_waves_c)) @@ -511,7 +511,7 @@ def get_lum_per_sfr_of_t(self, x=1600., window=1, band=None, # else: # erg / sec / Hz / (Msun / yr) - #self._cache_L_[kwds] = yield_UV + self._cache_L_[kwds] = yield_UV return yield_UV @@ -544,9 +544,9 @@ def get_lum_per_sfr(self, x=1600., window=1, Z=None, age=None, band=None, Number of wavelength bins over which to average Units are - `units_out` / (Msun / yr) + erg / s / Hz / (Msun / yr) or - `units_out` / Msun + erg / s / Hz / Msun """ diff --git a/ares/util/WorkerPools.py b/ares/util/MPIPool.py similarity index 65% rename from ares/util/WorkerPools.py rename to ares/util/MPIPool.py index 069c63b57..04144d2a6 100644 --- a/ares/util/WorkerPools.py +++ b/ares/util/MPIPool.py @@ -18,13 +18,6 @@ rank = 0 size = 1 -try: - import pymp - have_pymp = True -except ImportError: - have_pymp = False - - class MPIPool(object): # pragma: no cover def __init__(self, comm=None, master=0): @@ -114,58 +107,7 @@ def stop(self): for worker in self.workers: self.comm.send(None, worker, 0) -class WorkerPool(object): - def __init__(self, nthreads=None): - self.nthreads = nthreads - - @property - def pool(self): - if not hasattr(self, '_pool_'): - assert have_pymp, "Need pymp if nthreads != 0 or None." - pymp.config.num_threads = self.nthreads - self._pool_ = pymp.Parallel(self.nthreads) - self._pool_.__enter__() - if self.is_pymp_pool and self.thread_num == 1: - print(f"* Initialized pymp worker pool with {self.nthreads} threads") - return self._pool_ - - def done(self, exc_t=None, exc_val=None, exc_tb=None): - if self.is_pymp_pool: - self.pool.__exit__(exc_t, exc_val, exc_tb) - else: - pass - - @property - def is_pymp_pool(self): - if not hasattr(self, '_is_pymp_pool'): - if self.nthreads not in [0, 1, None]: - self._is_pymp_pool = True - else: - self._is_pymp_pool = False - - return self._is_pymp_pool - - @property - def thread_num(self): - if not hasattr(self, '_thread_num'): - if self.is_pymp_pool: - self._thread_num = self.pool.thread_num - else: - self._thread_num = 1 - - return self._thread_num - - def xrange(self, N): - if self.is_pymp_pool: - return self.pool.xrange(0, N) - else: - return range(0, N) - def get_buffer(self, shape, dtype): - if self.is_pymp_pool: - return pymp.shared.array(shape, dtype=dtype) - else: - return np.zeros(shape, dtype=dtype) #if __name__ == '__main__': # # pool = Pool(MPI.COMM_WORLD) diff --git a/ares/util/Misc.py b/ares/util/Misc.py index e4bc547a9..c8fb89422 100644 --- a/ares/util/Misc.py +++ b/ares/util/Misc.py @@ -17,49 +17,8 @@ from .Stats import bin_e2c from ..physics.Constants import c, erg_per_ev, h_p, E_LL, E_LyA -letters = list('abcdef') numeric_types = [int, float, np.int64, np.int32, np.float64, np.float32] -def get_pop_info(popid): - """ - Parse `popid`, as we (as of March 2025) allow non-integer IDs. - - Parameters - ---------- - popid : int, str, tuple - For old-school ARES calculations (burn), this would just be an integer - used to index some ares.simulations.Simulation.pops list. Now, we can - pass things like '2a', which generally means 'satellite galaxies that - belong to population 0' (the 'a' maps back to pop 0, 'b' to pop 1, etc). - This is a little confusing mixing numbers and letters, but I think it's - less confusing than indicating '2a' as '20', or requiring users to - provide a tuple, e.g., (2, 0) or (2, 'a'). - - Returns - ------- - Tuple containing (ARES popid, parent popid [if applicable], pop name as str). - - """ - - # In this case, 'classic' behavior: just an integer, i.e., - # central galaxies. - if (type(popid) == int) or popid.isnumeric(): - return int(popid), int(popid), str(popid) - - if type(popid) == tuple: - assert popid[1] < popid[0] - if type(popid[1]) == str: - s = letters.index(popid[1]) - else: - s = letters[popid[1]] - - return popid[0], popid[1], f'{int(popid[0])}{s}' - - if type(popid) == str: - return int(popid[0]), int(letters.index(popid[1])), popid - - raise NotImplemented('help') - def get_cmd_line_kwargs(argv): cmd_line_kwargs = {} @@ -452,58 +411,3 @@ def get_field_from_catalog(field, pos, Lbox, dims=512, mesh=None, hist /= mesh**3 return bin_e2c(xe), hist - -class WorkerPool(object): - def __init__(self, nthreads=None): - self.nthreads = nthreads - - @property - def pool(self): - if not hasattr(self, '_pool_'): - assert have_pymp, "Need pymp if nthreads != 0 or None." - pymp.config.num_threads = self.nthreads - self._pool_ = pymp.Parallel(self.nthreads) - self._pool_.__enter__() - if self.is_pymp_pool and self.thread_num == 1: - print("* Initialized pymp worker pool with {} threads".format( - self.nthreads - )) - return self._pool_ - - def done(self, exc_t=None, exc_val=None, exc_tb=None): - if self.is_pymp_pool: - self.pool.__exit__(exc_t, exc_val, exc_tb) - else: - pass - - @property - def is_pymp_pool(self): - if not hasattr(self, '_is_pymp_pool'): - if self.nthreads not in [0, 1, None]: - self._is_pymp_pool = True - else: - self._is_pymp_pool = False - - return self._is_pymp_pool - - @property - def thread_num(self): - if not hasattr(self, '_thread_num'): - if self.is_pymp_pool: - self._thread_num = self.pool.thread_num - else: - self._thread_num = 0 - - return self._thread_num - - def xrange(self, N): - if self.is_pymp_pool: - return self.pool.xrange(0, N) - else: - return range(0, N) - - def get_buffer(self, shape, dtype): - if self.is_pymp_pool: - return pymp.shared.array(shape, dtype=dtype) - else: - return np.zeros(shape, dtype=dtype) diff --git a/ares/util/SetDefaultParameterValues.py b/ares/util/SetDefaultParameterValues.py index 5df78a526..2f6b24290 100644 --- a/ares/util/SetDefaultParameterValues.py +++ b/ares/util/SetDefaultParameterValues.py @@ -506,8 +506,6 @@ def PopulationParameters(): "pop_sfr_model": 'fcoll', # or sfrd-func, sfrd-tab, sfe-func, sfh-tab, rates, - "pop_lum_func": None, - "pop_ham_z": None, # Mass accretion rate @@ -538,9 +536,6 @@ def PopulationParameters(): "pop_centrals": True, "pop_ihl": None, - "pop_ihl_mask": None, - "pop_ihl_mask_pix": 6, - "pop_ihl_suppression": None, "pop_focc": 1.0, "pop_focc_inv": False, @@ -569,7 +564,6 @@ def PopulationParameters(): # For synthesis models "pop_Z": 0.02, "pop_imf": 2.35, - "pop_stellar_lib": 'stelib', # only applies to BC03 models "pop_tracks": None, "pop_tracks_fn": None, "pop_stellar_aging": False, @@ -599,7 +593,6 @@ def PopulationParameters(): "pop_sfh": 'const', "pop_sfh_degrade": 1, "pop_sfh_fallback": None, - "pop_fallback_last_resort": False, "pop_age_definition": None, @@ -880,7 +873,6 @@ def PopulationParameters(): "pop_fox": 0.03, "pop_msr": None, - "pop_profile_info": None, "pop_dust_holes": 'big', "pop_dust_yield": None, # Mdust = dust_yield * metal mass @@ -918,16 +910,11 @@ def PopulationParameters(): "pop_calib_wave": 1600, "pop_calib_lum": None, "pop_lum_per_sfr": None, - "pop_lum_per_mass": None, - + "pop_lum_per_sfr_off_wave": 1, "pop_lum_per_sfr_at_wave": None, "pop_lum_corr": None, "pop_lum_tab": None, - "pop_lum_tab_prefix": None, - "pop_lum_tab_T0": 1, - "pop_lum_tab_T0_alpha": 0, - "pop_calib_Z": None, # not implemented @@ -1060,7 +1047,6 @@ def SourceParameters(): "source_Z": 0.02, "source_imf": 2.35, "source_imf_Mmax": 300, - "source_stellar_lib": 'stelib', "source_tracks": 'Padova1994', "source_tracks_fn": None, "source_stellar_aging": False, @@ -1077,7 +1063,6 @@ def SourceParameters(): "source_prof_1h": None, "source_ssp": False, # a.k.a., continuous SF "source_sfh": 'const', - "source_fallback_last_resort": False, "source_sfh_axes": None, "source_sfh_fallback": None, @@ -1368,7 +1353,8 @@ def CosmologyParameters(): 'relativistic_species': 3.04, "approx_highz": False, "cosmology_id": 'best', - "cosmology_name": 'planck_TTTEEE_lowl_lowE', # Can pass 'named cosmologies' + # Can pass 'named cosmologies', e.g., planck_TTTEEE_lowl_lowE + "cosmology_name": 'planck_TTTEEE_lowl_lowE', "cosmology_number": None, "path_to_CosmoRec": None, "interpolate_cosmology_in_z": False, @@ -1454,7 +1440,7 @@ def ControlParameters(): "cosmological_ics": False, "load_sim": False, - "cosmological_Mmin": ['filtering', 'tegmark'], + "cosmological_Mmin": None, #['filtering', 'tegmark'], # Timestepping "max_timestep": 1.0, diff --git a/ares/util/Stats.py b/ares/util/Stats.py index 4dbe16a9c..c593956d2 100644 --- a/ares/util/Stats.py +++ b/ares/util/Stats.py @@ -530,31 +530,3 @@ def bin_samples(x, y, xbin_c, weights=None, limits=False, percentile=None, else: return quantify_scatter(x, y, xbin_c, weights=weights, method_std='std', inclusive=inclusive) - -def lognormal(x, mu, sigma): - """ - This is dP/dlnx. Sometimes you'll see an extra factor of x in the denominator, but remember: - - (i) dn/dlog10x = dn/dlnx / ln(10.) - (ii) dn/dlnx = x * dn/dx - - So if you see an extra factor of x in the denominator elsewhere, you're seeing dn/dx. - - If you integrate this function from -inf to inf, you should obtain 0. - - Parameters - ---------- - x : int, float, array - Independent variable [really ln(x)]. - mu : int, float, array - Mean of log-normal in ln(x). - sigma : int, float - Width of distribution. - - Returns - ------- - PDF, i.e., dn/dlnx. - - """ - return np.exp(-0.5 * (x - mu)**2 / sigma**2) \ - / np.sqrt(2. * np.pi) / sigma \ No newline at end of file diff --git a/ares/util/cli.py b/ares/util/cli.py index 560a61aaa..fef62c634 100644 --- a/ares/util/cli.py +++ b/ares/util/cli.py @@ -10,6 +10,7 @@ import re import sys import gzip +import glob import shutil import pickle import tarfile @@ -20,6 +21,7 @@ import numpy as np import h5py +from pathlib import Path from .Math import smooth from . import ParameterBundle from .. import __version__ @@ -32,6 +34,16 @@ from ..simulations import RaySegment +try: + import gdown +except ImportError: + pass + +def _mv_bpass(parent_dir): + os.makedirs(f"{parent_dir}/SEDS", exist_ok=True) + for fn in glob.glob(f"{parent_dir}/sed.bpass.constant.nocont.sin.z0??.deg100"): + shutil.move(fn, f"{parent_dir}/SEDS/") + # define helper function def read_FJS10(parent_dir): E_th = [13.6, 24.6, 54.4] @@ -111,11 +123,6 @@ def read_FJS10(parent_dir): return -# define data sources -_bpass_v1_links = [ - f"sed_bpass_z{zval}_tar.gz" for zval in ["001", "004", "008", "020", "040"] -] - _bc03_orig_links = [] for imf in ['chabrier', 'salpeter']: for tracks in ['padova_1994', 'padova_2000', 'geneva_1994']: @@ -134,7 +141,7 @@ def gunzip_files(parent_dir): with open(filename[:-3], 'wb') as f_out: shutil.copyfileobj(f_in, f_out) - print(f"# Unzipped {parent_dir}/{filename}.") + print(f"! Unzipped {parent_dir}/{filename}.") def unpack_files(parent_dir): for fn in os.listdir(parent_dir): @@ -154,10 +161,10 @@ def unpack_files(parent_dir): with open(full_path[:-3], 'wb') as f_out: shutil.copyfileobj(f_in, f_out) else: - #print(f"# Unrecognized file format: {full_path}.") + #print(f"! Unrecognized file format: {full_path}.") continue - print(f"# Unpacked {full_path}.") + print(f"! Unpacked {full_path}.") def unpack_bc03(parent_dir): @@ -172,42 +179,54 @@ def unpack_bc03_2013(parent_dir): for imf in os.listdir(f"{path}/{tracks}"): unpack_files(f"{path}/{tracks}/{imf}") +def unpack_bpass_v1(parent_dir): + path = f"{ARES}/bpass_v1/" + for Zstr in ['z001', 'z004', 'z008', 'z020', 'z040']: + with tarfile.open(f"{path}/sed_bpass_{Zstr}_tar.gz") as f: + f.extractall(parent_dir) + # Auxiliary data downloads # Format: [URL, file1, file2, ..., file to run when done] aux_data = { + "halos_tests": [ + "https://drive.google.com/file/d/1k8YG1Z02WQ-bUFqBB6C7W4eb_huwMKxz/view?usp=sharing", + "halos_tests.tar.gz", + None, + ], "halos": [ - "https://www.dropbox.com/s/8df7rsskr616lx5/halos.tar.gz?dl=1", + "https://drive.google.com/file/d/1sglCEiO6HrpQJWKcwmBNvRl1lyUQWfNO/view?usp=sharing", "halos.tar.gz", None, ], "inits": [ - "https://www.dropbox.com/s/c6kwge10c8ibtqn/inits.tar.gz?dl=1", + "https://drive.google.com/file/d/1RHz-MJ7DD6W7H0TG_kLvFSrZYWBgqgwm/view?usp=sharing", "inits.tar.gz", None, ], "optical_depth": [ - "https://www.dropbox.com/s/ol6240qzm4w7t7d/tau.tar.gz?dl=1", + "https://drive.google.com/file/d/1CNuMWQGfVNuz0hmg3KFqduN5u3bVUoEj/view?usp=sharing", "tau.tar.gz", None, ], "secondary_electrons": [ - "https://www.dropbox.com/s/jidsccfnhizm7q2/elec_interp.tar.gz?dl=1", + "https://drive.google.com/file/d/1IMxyvPKDS0JiLQ79EDwgMYrSH6umlTPZ/view?usp=sharing", "elec_interp.tar.gz", read_FJS10, ], "starburst99": [ - "http://www.stsci.edu/science/starburst99/data", "data.tar.gz", None + "http://www.stsci.edu/science/starburst99/data", + "data.tar.gz", + None ], "bpass_v1": [ - "http://bpass.auckland.ac.nz/2/files" - ] + _bpass_v1_links + [None], + "https://drive.google.com/file/d/1iuqKkcjh4fBF8MQS9XtDJvoSb9O9dCI9/view?usp=sharing", + "bpass_v1.tar.gz", + unpack_bpass_v1, + ], "bpass_v1_tests": [ - "https://www.dropbox.com/s/8l69msro6n06hjx/sed_degraded.tar.gz?dl=1", - "sed_degraded.tar.gz", + "https://drive.google.com/file/d/1U5d3cm57Kz_EndkcXkscJForGAvq7jkk/view?usp=drive_link", + 'bpass_v1_tests.tar.gz', None], - "bpass_v1_stars": [ - "http://bpass.auckland.ac.nz/1/files", "starsmodels_tar.gz", None - ], "bc03": [ "https://www.bruzual.org/bc03/Original_version_2003" ] + _bc03_orig_links + [unpack_bc03], @@ -250,8 +269,12 @@ def unpack_bc03_2013(parent_dir): None, ], "wfc": [ - "https://www.dropbox.com/s/zv8qomgka9fkiek/wfc.tar.gz?dl=1", - "wfc.tar.gz", + "http://svo2.cab.inta-csic.es/svo/theory/fps3/getdata.php?format=ascii&id=HST/", + 'ACS_WFC.F435W', + 'ACS_WFC.F606W', + 'ACS_WFC.F775W', + 'ACS_WFC.F814W', + 'ACS_WFC.F850LP', None, ], "hsc": [ @@ -345,34 +368,28 @@ def unpack_bc03_2013(parent_dir): } # define which files are needed for which things -datasets = { - "extra": [ - "nircam", - "irac", - "roman", - "edges", - "bpass_v1_stars", - ], +dataset_groups = { "tests": [ "inits", "secondary_electrons", - "halos", + "halos_tests", "wfc", "wfc3", "planck", "bpass_v1_tests", "optical_depth", ], - "test_files": [ - "inits.tar.gz", - "elec_interp.tar.gz", - "halos.tar.gz", - "IR.zip", - "wfc.tar.gz", - aux_data["planck"][1], - "sed_degraded.tar.tz", - "tau.tar.gz", - ], + # Don't think test_files ever gets used, covered by 'tests' above + #"test_files": [ + # "inits.tar.gz", + # "elec_interp.tar.gz", + # "halos_tests.tar.gz", + # "IR.zip", + # "wfc.tar.gz", + # aux_data["planck"][1], + # "bpass_v1_tests.tar.gz", + # "tau.tar.gz", + #], "photometry": [ "nircam", "irac", @@ -383,6 +400,12 @@ def unpack_bc03_2013(parent_dir): "spherex", "wfc", "wfc3", + ], + "basics": [ + "inits", + "halos", + "bpass_v1", + "bc03_2013", ] } @@ -490,7 +513,7 @@ def generate_hmf_tables(path, **kwargs): "halo_tmin": 30.0, "halo_tmax": 13.7e3, # Myr - # Cosmology + # Cosmology: just set parameter values by hand. "cosmology_id": "best", "cosmology_name": "planck_TTTEEE_lowl_lowE", } @@ -502,10 +525,12 @@ def generate_hmf_tables(path, **kwargs): halos.info try: - halos.save_hmf(fmt="hdf5", clobber=False) + fn = halos.save_hmf(fmt="hdf5", clobber=False) except IOError as err: print(err) - return + fn = None + + return fn def generate_halo_histories(path, fn_hmf): """ @@ -545,7 +570,7 @@ def generate_halo_histories(path, fn_hmf): grp[key].read_direct(buff) cosmo_pars[key] = buff[0] - print(f"Read cosmology from {fn_hmf}") + print(f"# Read cosmology from {fn_hmf}") pars.update(cosmo_pars) @@ -569,7 +594,7 @@ def generate_halo_histories(path, fn_hmf): fn = "{}.hdf5".format(pref) if not os.path.exists(fn): - print("# Running new trajectories...") + print("! Running new trajectories...") zall, hist = pop.get_histories() with h5py.File(fn, "w") as h5f: @@ -579,10 +604,10 @@ def generate_halo_histories(path, fn_hmf): continue h5f.create_dataset(key, data=hist[key]) - print("# Wrote {}".format(fn)) + print("! Wrote {}".format(fn)) else: - print("# File {} exists. Exiting.".format(fn)) - return + print("! File {} exists. Exiting.".format(fn)) + return fn def make_halos(path): """ @@ -734,6 +759,9 @@ def make_lowres_sps(path): generate_lowres_sps(path, degrade_to=100) def generate_simpl_seds(path, **kwargs): + + make_data_dir(path) + # go to path os.chdir(path) @@ -761,7 +789,7 @@ def generate_simpl_seds(path, **kwargs): def_kwargs['source_alpha']) if os.path.exists(fn): - print("{!s} already exists.".format(fn)) + print("! {!s} already exists.".format(fn)) return src = BlackHole(**def_kwargs) @@ -807,7 +835,7 @@ def generate_csfh_tab(path, **kwargs): with open(fn, 'wb') as f: pickle.dump({'t': tarr, 'waves': waves, 'data': data.T}, f) #np.savetxt(fn, data.T) - print(f"# Wrote {fn}") + print(f"! Wrote {fn}") def generate_rt1d_tabs(path, **kwargs): @@ -848,7 +876,8 @@ def make_data_dir(path=ARES): None """ if not os.path.exists(path): - os.mkdir(path) + _path = Path(path) + _path.mkdir(parents=True) return @@ -871,8 +900,8 @@ def clean_files(args): # figure out what to delete if args.dataset.lower() == "all": dsets = available_dsets - elif args.dataset.lower() in datasets: - dsets = datasets[args.dataset.lower()] + elif args.dataset.lower() in dataset_groups: + dsets = dataset_groups[args.dataset.lower()] elif args.dataset.lower() not in available_dsets: raise ValueError( f"dataset {args.dataset} is not available. Possible options are: " @@ -895,7 +924,14 @@ def clean_files(args): return def _do_download(full_path, dl_link): + # Files from Google Drive need special treatment + if 'drive' in dl_link: + gdown.download(dl_link, full_path, fuzzy=1) + return + + # Otherwise, can use urlretrieve try: + print(f"Downloading {dl_link} to {full_path}.") urlretrieve(dl_link, full_path) print(f"Downloaded {dl_link} to {full_path}.") except (URLError, HTTPError) as error: @@ -938,14 +974,14 @@ def download_files(args): full_path = os.path.join(args.path, dset, aux_data[dset][1]) if os.path.exists(full_path): if args.fresh: - print(f"Running in dry-run mode; would re-download {full_path}") + print(f"! Running in dry-run mode; would re-download {full_path}") else: print( - f"{full_path} already exists; rerun with --fresh to " + f"! {full_path} already exists; rerun with --fresh to " "force download" ) else: - print(f"Running in dry-run mode; would download {full_path}") + print(f"! Running in dry-run mode; would download {full_path}") else: for dset in dsets: @@ -962,6 +998,10 @@ def download_files(args): # Loop over [potentially] several files to download for _fn in to_dl: + if args.only is not None: + if args.only not in _fn: + continue + full_path = os.path.join(parent_dir, _fn) # Dropbox links are complete, in that the name of the file we @@ -977,7 +1017,7 @@ def download_files(args): _do_download(full_path, _fn_dl) else: print( - f"{full_path} already exists; rerun with --fresh to " + f"! {full_path} already exists; rerun with --fresh to " "force download" ) else: @@ -1053,11 +1093,72 @@ def generate_data(args): make_simpl(path) elif dset == "rt1d": make_rt1d(path) - elif dset == "bpass_v1": + elif dset in ["bpass_v1"]: make_lowres_sps(path + '/SEDS') return +def init_ares(args): + """ + This is a bundle of pre-processing steps to simplify things for first-time + users. + """ + + make_data_dir(args.path) + + ## + # Add some verbosity to remind users to symlink to $HOME/.ares + # if they've provided --path + if args.path != ARES: + print("\n") + print(f"!"*78) + print(f"! You have supplied a non-standard path to ARES input data. That's OK!") + print(f"! Just be sure to make $HOME/.ares a symbolic link to the provided path, e.g.,") + print(f"! ") + print(f"! > ln -s {args.path} {ARES}") + print(f"!") + print(f"!"*78) + + ## + # Tell user about how much space this will take and how long. + print("") + print(f"!"*78) + print(f"! This initialization will take a few minutes and ~500 MB of disk space.") + print(f"! A complete set of ancillary data used by ARES for broader applications") + print(f"! can take several GB of space, so if your $HOME quota is small, <= 10 GB,") + print(f"! it is probably a good idea to run `ares init` with the ") + print(f"! `--path` flag set. See the README for more details.") + print(f"!"*78) + + print(f"! Beginning ARES initialization...") + + args.dataset = 'inits' + download_files(args) + + ## + # Need to manually add `dataset` to `args` object + args.dataset = 'bpass_v1' + args.only = '004' + + # Download only the basics: cosmological initial conditions, + # BPASS v1 (default for EoR things), BC03 (default for EBL things) + download_files(args) + + # Pre-processing: hmf generation, SED degradation, what else? + + # Smooth BPASS v1 spectra to 10 Angstrom resolution since the native + # 1 A resolution is overkill for most things we do. + generate_lowres_sps(f"{args.path}/bpass_v1/SEDS", degrade_to=10, + exact_files=['sed.bpass.constant.nocont.sin.z004']) + + ## Generate default HMFs. + make_data_dir(f"{args.path}/halos") + generate_hmf_tables(f"{args.path}/halos") + generate_halo_histories( + f"{args.path}/halos", + "halo_mf_Tinker10_logM_1000_6-16_t_971_30-1000.hdf5", + ) + def config_clean_subparser(subparser): """ Add the subparser for the "clean" sub-command. @@ -1120,10 +1221,17 @@ def config_download_subparser(subparser): help="dataset to download", default="all", ) + sp.add_argument( + "--only", + help="limit downloads to files containing this sub-string", + action="store_true", + default=None, + ) sp.add_argument( "--fresh", help="whether to force a new download or not", action="store_true", + default=False, ) sp.set_defaults(func=download_files) @@ -1167,6 +1275,49 @@ def config_generate_subparser(subparser): return +def config_init_subparser(subparser): + """ + Add the subparser for the "init" sub-command. + + Parameters + ---------- + subparser : ArgumentParser subparser object + The subparser object to add sub-command options to. + + Returns + ------- + None + """ + doc = """ + Initialize ARES for basic usage. + """ + hlp = "download and pre-process files needed by ARES " + sp = subparser.add_parser( + "init", + description=doc, + help=hlp, + ) + sp.add_argument( + "--fresh", + help="whether to force a new download or not", + action="store_true", + ) + sp.add_argument( + "--only", + default=None, + help="limit downloads to files containing this sub-string", + action="store_true", + ) + sp.add_argument( + "-p", + "--path", + default=ARES, + help="path to download files to. Defaults to ~/.ares", + ) + sp.set_defaults(func=init_ares) + + return + # make the base parser def generate_parser(): """ @@ -1210,6 +1361,7 @@ def generate_parser(): config_clean_subparser(sub_parsers) config_download_subparser(sub_parsers) config_generate_subparser(sub_parsers) + config_init_subparser(sub_parsers) return ap diff --git a/docs/conf.py b/docs/conf.py index 27e5bcdef..e45821601 100755 --- a/docs/conf.py +++ b/docs/conf.py @@ -26,8 +26,7 @@ # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = ['sphinx.ext.autodoc', 'sphinx.ext.mathjax', - 'sphinx.ext.viewcode', 'numpydoc', 'nbsphinx', 'm2r2', - 'lxml', 'lxml_html_clean'] + 'sphinx.ext.viewcode', 'numpydoc', 'nbsphinx', 'm2r2'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] @@ -43,7 +42,7 @@ # General information about the project. project = u'ares' -copyright = u'2025, Jordan Mirocha' +copyright = u'2015, Jordan Mirocha' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the diff --git a/docs/example_grid.rst b/docs/example_grid.rst new file mode 100644 index 000000000..145c55193 --- /dev/null +++ b/docs/example_grid.rst @@ -0,0 +1,240 @@ +:origin: + +Simple Parameter Study: 2-D Model Grid +====================================== +Often we want to study how the 21-cm signal changes over a range of parameters. We can do so using the ModelGrid class, and use numpy arrays to represent the range of values we’re interested in. + +Before we start, the few usual imports: + +:: + + import ares + import numpy as np + import matploblib.pyplot as pl + +Efficient Example: :math:`tanh` model for the global 21-cm signal +----------------------------------------------------------------- +Before we run a set of models, we need to decide what quantities we’d like to save. For a detailed description of how to do this in general cases, check out :doc:`example_inline_analysis`. + +For now, let’s save the redshift and brightness temperature of the global 21-cm emission maximum, which we dub "Turning Point D", and the CMB optical depth, + +:: + + blobs_scalar = ['z_D', 'dTb_D', 'tau_e'] + +in addition to the ionization, thermal, and global 21-cm histories at redshifts between 5 and 20 (at :math:`\Delta z = 1` increments), + +:: + + blobs_1d = ['cgm_h_2', 'igm_Tk', 'dTb'] + blobs_1d_z = np.arange(5, 21) + +.. note :: For a complete listing of ideas for 1-D blobs see :doc:`fields`. + +Now, we’ll make a dictionary full of parameters that will get passed to every global 21-cm signal calculation. In addition to the blobs, we’ll set ``tanh_model=True`` to speed things up (see next section regarding physical models), and ``problem_type=101``: + +:: + + base_pars = \ + { + 'problem_type': 101, + 'tanh_model': True, + 'blob_names': [blobs_scalar, blobs_1d], + 'blob_ivars': [None, [('z', blobs_1d_z)]], + 'blob_funcs': None, + } + +and create the ``ModelGrid`` instance, + +:: + + mg = ares.inference.ModelGrid(**base_pars) + +At this point we have yet to specify which parameters will define the axes of the model grid. Since we set ``tanh_model=True``, we have 9 parameters to choose from: a step height, step width, and step redshift for the Ly-:math:`\alpha`, thermal, and ionization histories: + +* Ly-:math:`\alpha` history parameters: ``tanh_J0``, ``tanh_Jz0``, ``tanh_Jdz``. +* Thermal history parameters: ``tanh_T0``, ``tanh_Tz0``, ``tanh_Tdz``. +* Ionization history parameters: ``tanh_x0``, ``tanh_xz0``, ``tanh_xdz``. + +The Ly-:math:`\alpha` step height, ``tanh_J0``, must be provided in units of :math:`J_{21} = 10^{-21} \mathrm{erg} \ \mathrm{s}^{-1} \ \mathrm{cm}^{-2} \ \mathrm{Hz}^{-1} \ \mathrm{sr}^{-1}`, while the temperature step height is assumed to be in Kelvin. The ionization step height should not exceed unity -- in fact it's safe to assume ``tanh_x0=1`` (we know that reionization *ends*!). See `Harker et al. (2016) `_ for more information about the *tanh* model. + +Let’s take the reionization redshift, ``tanh_xz0``, and duration, ``tanh_xdz``, and sample them over a reasonable redshift interval with a spacing of :math:`\Delta z = 0.1` + +:: + + z0 = np.arange(6, 12.2, 0.2) + dz = np.arange(0.2, 8.2, 0.2) + +Now, we just set the ``axes`` attribute to a dictionary containing the array of values for each parameter: + +:: + + mg.axes = {'tanh_xz0': z0, 'tanh_xdz': dz} + +To run, + +:: + + mg.run('test_2d_grid', clobber=True, save_freq=100) + +To speed things up, you could increase the grid spacing. Or, execute the above in parallel as a Python script (assuming you have MPI and mpi4py installed). + + .. note:: If the model grid doesn’t finish running, that’s OK! Simply + re-execute the above command with ``restart=True`` as an + additional keyword argument and it will pick up where it left off. + +To analyze the results, create an analysis instance, + +:: + + anl = ares.analysis.ModelSet('test_2d_grid') + +and, for example, plot the 2-d parameter space with points color-coded by ``tau_e``, + +:: + + ax1 = anl.Scatter(anl.parameters, c='tau_e', fig=1) + pl.savefig('tanh_2d_tau.png') + +.. figure:: https://www.dropbox.com/s/ooslry1h8ing2mm/ares_tanh_2d_tau.png?raw=1 + :align: center + :width: 600 + + Models in a 2-D parameter space of the :math:`tanh` reionization parameters, with points color-coded by the CMB optical depth, :math:`\tau_e`. + +or instead, the position of the emission maximum with the same color coding: + +:: + + ax2 = anl.Scatter(['z_D', 'dTb_D'], c='tau_e', fig=2) + pl.savefig('tanh_2d_D.png') + +.. figure:: https://www.dropbox.com/s/8oafsmw1vr15you/ares_tanh_2d_D.png?raw=1 + :align: center + :width: 600 + + Models in a 2-D parameter space of the :math:`tanh` reionization parameters, with points color-coded by the CMB optical depth. + +.. note :: In general, you may want to save ``'z_C'`` and ``'dTb_C'``, i.e., the location of the global 21-cm absorption feature. But, in this case since we've only varied parameters of the ionization history, that point will not change and so saving it as a blob is unnecessary. + +See :doc:`example_grid_analysis` for more information. + +Accessing the Data Directly +--------------------------- +If you'd like to access the data directly for further manipulation, you'll be looking at the following attributes of the ``ModelSet`` class: + +* ``chain``, which is a 2-D array with dimensions (number of models, number dimensions). +* ``get_blob``, which is a function that can be used to read-in blobs from disk. + +.. note :: The ``chain`` attribute is referred to as such because is analogous to an MCMC chain, but rather than random samples of the posterior distribution, it represents "samples" on a structured mesh. + +For example, to retrieve the samples of the ``test_2d_grid`` dataset above, you could do: + +:: + + # Just the names of the axes + x, y = anl.parameters + + xdata, ydata = anl.chain[:,0], anl.chain[:,1] + +or equivalently, + +:: + + xdata, ydata = anl.chain.T + +And to plot the samples, + +:: + + import matplotlib.pyplot as pl + + pl.scatter(xdata, ydata) + pl.xlabel(x) + pl.ylabel(y) + +To extract blobs, you could do : + +:: + + QHII = anl.get_blob('cgm_h_2') + + print QHII.shape + +Notice that the first dimension of ``QHII`` is the same as the first dimension of ``chain`` -- just the number of samples in the ModelGrid. The second dimension, however, is different. Now, rather than representing the dimensionality of the parameter space, it represents the dimensionality of this particular blob. Why 16 elements? Because our blobs were setup such that the quantities ``cgm_h_2``, ``igm_Tk``, and ``dTb`` were recorded at all redshifts in ``np.arange(5, 21)``, which has 16 elements. + +So, we could for example color-code the points in our previous plot by the volume-averaged ionization fraction at :math:`z=10` by doing: + +:: + + pl.scatter(xdata, ydata, c=QHII[:,5], edgecolors='none') + +If you forget the properties of a blob, you can type + +:: + + group, element, nd, shape = anl.blob_info('cgm_h_2') + +which returns the index of blob group, index of the element within that group, dimensionality of the blob, and the shape of blob. This can be useful, for example, to automatically figure out the independent variables for a blob: + +:: + + # Should be 10 (redshift of interest above) + anl.blob_ivars[i][5] + +All of the built-in analysis routines are structured so that you don't have to think about these things on a regular basis if you don't want to! + +More Expensive Models +--------------------- +Setting ``tanh_model=True`` sped things up considerably in the previous example. In general, you can run grids varying any *ARES* parameters you like, just know that physical models (i.e., those with ``tanh_model=False``) generally take a few seconds each, whereas the :math:`tanh` model takes much less than a second for one model. + +For example, to repeat the previous exercise for a physical model, you could replace this commands: + +:: + + z0 = np.arange(6, 12, 0.1) + dz = np.arange(0.1, 8.1, 0.1) + mg.axes = {'tanh_xz0': z0, 'tanh_xdz': dz} + +with (for example) + +:: + + fX = np.logspace(-1, 1, 21) + Tmin = np.logspace(3, 5, 21) + mg.axes = {'fX': z0, 'Tmin': dz} + +In some cases -- e.g., when ``Tmin`` or ``pop_Tmin`` is an axis of the model grid -- load-balancing can be very advantageous. Just execute the following command before running the grid: + +:: + + mg.LoadBalance(method=1, par='Tmin') # or 'pop_Tmin' + +The ``method=1`` setting assigns all models with common ``Tmin`` values to the same processor. This helps because *ARES* knows that it need only generate lookup tables for :math:`df_{\mathrm{coll}} / dz` (which determines the star formation rate density in the simplest models) once per value of ``Tmin``, which means you save a little bit of runtime at the outset of each calculation. + +There is also a ``method=2`` option for load balancing, which is advantageous if the runtime of individual models is strongly correlated with a given parameter. In this case, the models will be sorted such that each processor gets a (roughly) equal share of the models for each value of the input ``par``. It helps to imagine the grid points of our 2-D parameter space color-coded by processor ID number: the resulting image for ``method=2`` is simply the transpose of the image you'd get for ``method=1``. + +If the edges of your parameter space correspond to rather extreme +models you might find that the calculations grind to a halt. This can be a big problem because you'll end up with one or more processors spinning their wheels while the rest of the processors continue. One way of dealing with this is to set an "alarm" that will be tripped if the runtime of a particular model exceeds some user-defined value. For example, before running a model grid, you might set: + +:: + + mg.timeout = 60 + +to limit calculations to 60 seconds or less. Models that trip this alarm will be recorded in the ``*fail*.pkl`` files so that you can look back later and (hopefully) figure out why they took so long. + +.. note :: This tends to happen because the ionization and/or heating rates + are very large, which drives the time-step to very small values. However, + in these circumstances the temperature and/or ionized fraction are + typically exceedingly large, at which point the 21-cm signal is zero and + need not be tracked any longer. As a result, terminating such calculations + before completion rarely has an important impact on the results. + +.. warning :: This may not work on all operating systems for unknown reasons. + Let me know if you get a mysterious crash when using the ``timeout`` + feature. + + + + + diff --git a/docs/example_mc_sampling.rst b/docs/example_mc_sampling.rst new file mode 100644 index 000000000..458479d9c --- /dev/null +++ b/docs/example_mc_sampling.rst @@ -0,0 +1,94 @@ +Monte-Carlo Sampling Higher Dimensional Spaces +============================================== +For one- or two-dimensional parameter studies, a gridded search of parameter space (as in :doc:`example_grid`) is a reasonable approach. However, as the dimensionality grows, things quickly get out of hand. As a result, it can sometimes be advantageous to run Monte Carlo simulations instead, sampling more sparsely (but more efficiently) a high-dimensional space. + +You can do this in *ARES* using the ``ModelSample`` class, which is just a wrapper around the ``ModelGrid`` class. As a result, the problem setup is very similar to that in :doc:`example_grid`, and that structure of the output data are identical, which means the routines documented in :doc:`example_grid_analysis` translate as well. + +Before we start, the few usual imports: + +:: + + import ares + import numpy as np + +Our "go-to" Efficient Example: :math:`tanh` model for the global 21-cm signal +----------------------------------------------------------------------------- +To facilitate a comparison between the model grid results, let's start by choosing the same blobs as in :doc:`example_grid`: + +:: + + blobs_scalar = ['z_D', 'dTb_D', 'tau_e'] + blobs_1d = ['cgm_h_2', 'igm_Tk', 'dTb'] + blobs_1d_z = np.arange(5, 21) + + base_pars = \ + { + 'problem_type': 101, + 'tanh_model': True, + 'blob_names': [blobs_scalar, blobs_1d], + 'blob_ivars': [None, [('z', blobs_1d_z)]], + 'blob_funcs': None, + } + +Now, instead of creating a ``ModelGrid`` instance, we make a ``ModelSample`` instance: + +:: + + mc = ares.inference.ModelSample(**base_pars) + +At this point we have yet to specify which parameters will to sample. Because we are now doing Monte Carlo simulations, we must define the *distributions* from which to draw samples in each parameter of interest, rather than the grid of values to sample. To do this we need Keith Tauscher's `distpy ` package, which is used in MCMC calculations (e.g., :doc:`example_mcmc_gs`) as well: + +:: + + from distpy import DistributionSet + + ps = DistributionSet() + +Now, let's study the same parameters as :doc:`example_grid` with one addition: the duration of "reheating": + +:: + + from distpy import UniformDistribution + + # Draw samples from a uniform distribution between supplied (min, max) values for each parameter + ps.add_distribution(UniformDistribution(6, 12), 'tanh_xz0') + ps.add_distribution(UniformDistribution(0.1, 8), 'tanh_xdz') + ps.add_distribution(UniformDistribution(0.1, 8), 'tanh_Tdz') + + # Give distributions to the ModelSample instance + mc.prior_set = ps + +.. note :: You can also draw samples from a Gaussian (via ``GaussianPrior``), a truncated Gaussian (``TruncatedGaussianPrior``), and many more. See ares.inference.Priors for a complete listing. + +One last thing: we must specify how many random samples to draw: + +:: + + mc.N = 2e3 # Number of models to run + +Finally, to run it: + +:: + + mc.run('test_3d_mc', clobber=True, save_freq=100) + +To analyze the results, create an analysis instance, + +:: + + anl = ares.analysis.ModelSet('test_3d_mc') + +and, for example, plot the 2-d parameter space with points color-coded by ``tau_e`` + +:: + + anl.Scatter(['tanh_xz0', 'tanh_xdz'], c='tau_e', edgecolors='none') + +Now that we have also varied the thermal history through ``tanh_Tdz``, we can look at the interplay between reionization and reheating in setting the emission maximum of the global signal, e.g., + +:: + + anl.Scatter(['tanh_xdz', 'tanh_Tdz'], c='dTb_D', edgecolors='none', fig=2) + +See :doc:`example_grid_analysis` for more information. + diff --git a/docs/examples.rst b/docs/examples.rst index e858414f8..9e75fe98c 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -22,6 +22,7 @@ These examples show how to work with source populations individually, i.e., not examples/example_galaxies_demo examples/example_pop_popIII examples/example_pop_dusty + * :doc:`example_edges` Parameter Studies and Inference ------------------------------- diff --git a/docs/examples/example_grid.ipynb b/docs/examples/example_grid.ipynb new file mode 100644 index 000000000..659f647bb --- /dev/null +++ b/docs/examples/example_grid.ipynb @@ -0,0 +1,894 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "d93e09d8", + "metadata": {}, + "source": [ + "# Simple Parameter Study: 2-D Model Grid" + ] + }, + { + "cell_type": "markdown", + "id": "58a32790", + "metadata": {}, + "source": [ + "Often we want to study how the 21-cm signal changes over a range of parameters. We can do so using the ModelGrid class, and use numpy arrays to represent the range of values we’re interested in.\n", + "\n", + "Before we start, the few usual imports:" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "56c02bec", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Populating the interactive namespace from numpy and matplotlib\n" + ] + } + ], + "source": [ + "%pylab inline\n", + "import ares\n", + "import numpy as np\n", + "import matplotlib.pyplot as pl" + ] + }, + { + "cell_type": "markdown", + "id": "394b32db", + "metadata": {}, + "source": [ + "## Efficient Example: *tanh* model for the global 21-cm signal" + ] + }, + { + "cell_type": "markdown", + "id": "7b0599f7", + "metadata": {}, + "source": [ + "Before we run a set of models, we need to decide what quantities we’d like to save. For a detailed description of how to do this in general cases, check out [Inline Analysis](../example_inline_analyis).\n", + "\n", + "For now, let’s save the redshift and brightness temperature of the global 21-cm emission maximum, which we dub \"Turning Point D\", and the CMB optical depth,\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "79e2d07a", + "metadata": {}, + "outputs": [], + "source": [ + "blobs_scalar = ['z_D', 'dTb_D', 'tau_e']" + ] + }, + { + "cell_type": "markdown", + "id": "e1aafaec", + "metadata": {}, + "source": [ + "in addition to the ionization, thermal, and global 21-cm histories at redshifts between 5 and 20 (at $\\Delta z = 1$ increments)," + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "35846762", + "metadata": {}, + "outputs": [], + "source": [ + "blobs_1d = ['cgm_h_2', 'igm_Tk', 'dTb']\n", + "blobs_1d_z = np.arange(5, 21)" + ] + }, + { + "cell_type": "markdown", + "id": "1ef1a76b", + "metadata": {}, + "source": [ + "**NOTE:** For a complete listing of ideas for 1-D blobs see the [Fields Listing](../fields.html)." + ] + }, + { + "cell_type": "markdown", + "id": "04a9a7bf", + "metadata": {}, + "source": [ + "Now, we’ll make a dictionary full of parameters that will get passed to every global 21-cm signal calculation. In addition to the blobs, we’ll set ``tanh_model=True`` to speed things up (see next section regarding physical models), and ``problem_type=101``: " + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "01619742", + "metadata": {}, + "outputs": [], + "source": [ + "base_pars = \\\n", + "{\n", + " 'problem_type': 101,\n", + " 'tanh_model': True,\n", + " 'blob_names': [blobs_scalar, blobs_1d],\n", + " 'blob_ivars': [None, [('z', blobs_1d_z)]],\n", + " 'blob_funcs': None,\n", + "}" + ] + }, + { + "cell_type": "markdown", + "id": "f1572fe2", + "metadata": {}, + "source": [ + "and create the ``ModelGrid`` instance, " + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "d536d567", + "metadata": {}, + "outputs": [], + "source": [ + "mg = ares.inference.ModelGrid(**base_pars)" + ] + }, + { + "cell_type": "markdown", + "id": "f73083c6", + "metadata": {}, + "source": [ + "At this point we have yet to specify which parameters will define the axes of the model grid. Since we set ``tanh_model=True``, we have 9 parameters to choose from: a step height, step width, and step redshift for the Ly-$\\alpha$, thermal, and ionization histories:\n", + "\n", + "* Ly-$\\alpha$ history parameters: ``tanh_J0``, ``tanh_Jz0``, ``tanh_Jdz``.\n", + "* Thermal history parameters: ``tanh_T0``, ``tanh_Tz0``, ``tanh_Tdz``.\n", + "* Ionization history parameters: ``tanh_x0``, ``tanh_xz0``, ``tanh_xdz``.\n", + "\n", + "The Ly-$\\alpha$ step height, ``tanh_J0``, must be provided in units of $J_{21} = 10^{-21} \\mathrm{erg} \\ \\mathrm{s}^{-1} \\ \\mathrm{cm}^{-2} \\ \\mathrm{Hz}^{-1} \\ \\mathrm{sr}^{-1}$, while the temperature step height is assumed to be in Kelvin. The ionization step height should not exceed unity -- in fact it's safe to assume ``tanh_x0=1`` (we know that reionization *ends*!). See [Harker et al. (2016)]( ) for more information about the *tanh* model.\n", + "\n", + "Let’s take the reionization redshift, ``tanh_xz0``, and duration, ``tanh_xdz``, and sample them over a reasonable redshift interval with a spacing of $\\Delta z = 0.2$," + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "a6d2cb42", + "metadata": {}, + "outputs": [], + "source": [ + "z0 = np.arange(6, 12.2, 0.2)\n", + "dz = np.arange(0.2, 8.2, 0.2)" + ] + }, + { + "cell_type": "markdown", + "id": "7db41716", + "metadata": {}, + "source": [ + "Now, we just set the ``axes`` attribute to a dictionary containing the array of values for each parameter:" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "a75d5cd2", + "metadata": {}, + "outputs": [], + "source": [ + "mg.axes = {'tanh_xz0': z0, 'tanh_xdz': dz}" + ] + }, + { + "cell_type": "markdown", + "id": "74945871", + "metadata": {}, + "source": [ + "To run," + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "c4dd8ac8", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + "grid: N/A% | | ETA: --:--:-- " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Starting 1240-element model grid.\n", + "Running 1240-element model grid.\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "grid: 8% |### | ETA: 0:02:38 " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Checkpoint #1: Tue Feb 8 14:50:36 2022\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "grid: 16% |####### | ETA: 0:02:26 " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Checkpoint #2: Tue Feb 8 14:50:51 2022\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "grid: 24% |########### | ETA: 0:02:12 " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Checkpoint #3: Tue Feb 8 14:51:05 2022\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "grid: 32% |############### | ETA: 0:01:58 " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Checkpoint #4: Tue Feb 8 14:51:19 2022\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "grid: 40% |################### | ETA: 0:01:44 " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Checkpoint #5: Tue Feb 8 14:51:33 2022\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "grid: 48% |####################### | ETA: 0:01:31 " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Checkpoint #6: Tue Feb 8 14:51:49 2022\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "grid: 56% |########################### | ETA: 0:01:17 " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Checkpoint #7: Tue Feb 8 14:52:03 2022\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "grid: 64% |############################### | ETA: 0:01:03 " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Checkpoint #8: Tue Feb 8 14:52:18 2022\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "grid: 72% |################################## | ETA: 0:00:48 " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Checkpoint #9: Tue Feb 8 14:52:32 2022\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "grid: 80% |###################################### | ETA: 0:00:34 " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Checkpoint #10: Tue Feb 8 14:52:48 2022\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "grid: 88% |########################################## | ETA: 0:00:20 " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Checkpoint #11: Tue Feb 8 14:53:04 2022\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "grid: 96% |############################################## | ETA: 0:00:05 " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Checkpoint #12: Tue Feb 8 14:53:20 2022\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "grid: 100% |################################################| Time: 0:03:03 \n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Processor 0: Wrote test_2d_grid.*.pkl (Tue Feb 8 14:53:26 2022)\n", + "Calculation complete: Tue Feb 8 14:53:26 2022\n", + "Elapsed time (min) : 3.06\n" + ] + } + ], + "source": [ + "mg.run('test_2d_grid', clobber=True, save_freq=100)" + ] + }, + { + "cell_type": "markdown", + "id": "c5b875e7", + "metadata": {}, + "source": [ + "To speed things up, you could increase the grid spacing. Or, execute the above in parallel as a Python script (assuming you have MPI and mpi4py installed).\n", + "\n", + "**NOTE:** If the model grid doesn’t finish running, that’s OK! Simply re-execute the above command with ``restart=True`` as an additional keyword argument and it will pick up where it left off.\n", + "\n", + "To analyze the results, create an analysis instance, " + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "afbd3cfa", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "############################################################################\n", + "## Analysis: Model Set ##\n", + "############################################################################\n", + "## ---------------------------------------------------------------------- ##\n", + "## Basic Information ##\n", + "## ---------------------------------------------------------------------- ##\n", + "## path : ./ ##\n", + "## prefix : test_2d_grid ##\n", + "## N-d : 2 ##\n", + "## ---------------------------------------------------------------------- ##\n", + "## param #00: tanh_xz0 ##\n", + "## param #01: tanh_xdz ##\n", + "############################################################################\n", + "\n" + ] + } + ], + "source": [ + "anl = ares.analysis.ModelSet('test_2d_grid')" + ] + }, + { + "cell_type": "markdown", + "id": "fb4f032f", + "metadata": {}, + "source": [ + "and, for example, plot the 2-d parameter space with points color-coded by ``tau_e``," + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "8c4f57a2", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "# Loaded test_2d_grid.000.blob_0d.tau_e.pkl\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "ax1 = anl.Scatter(anl.parameters, c='tau_e', fig=1)" + ] + }, + { + "cell_type": "markdown", + "id": "9c13d221", + "metadata": {}, + "source": [ + "or instead, the position of the emission maximum with the same color coding:" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "5d95cd28", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "# Loaded test_2d_grid.000.blob_0d.z_D.pkl\n", + "# Loaded test_2d_grid.000.blob_0d.dTb_D.pkl\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "ax2 = anl.Scatter(['z_D', 'dTb_D'], c='tau_e', fig=2)" + ] + }, + { + "cell_type": "markdown", + "id": "4e00b14d", + "metadata": {}, + "source": [ + "**NOTE:** In general, you may want to save ``'z_C'`` and ``'dTb_C'``, i.e., the location of the global 21-cm absorption feature. But, in this case since we've only varied parameters of the ionization history, that point will not change and so saving it as a blob is unnecessary. \n", + " \n", + "See :doc:`example_grid_analysis` for more information." + ] + }, + { + "cell_type": "markdown", + "id": "22b32572", + "metadata": {}, + "source": [ + "## Accessing the Data Directly" + ] + }, + { + "cell_type": "markdown", + "id": "454700fe", + "metadata": {}, + "source": [ + "If you'd like to access the data directly for further manipulation, you'll be looking at the following attributes of the ``ModelSet`` class:\n", + "\n", + "* ``chain``, which is a 2-D array with dimensions (number of models, number dimensions).\n", + "* ``get_blob``, which is a function that can be used to read-in blobs from disk.\n", + "\n", + "**NOTE:** The ``chain`` attribute is referred to as such because is analogous to an MCMC chain, but rather than random samples of the posterior distribution, it represents \"samples\" on a structured mesh.\n", + "\n", + "For example, to retrieve the samples of the ``test_2d_grid`` dataset above, you could do:" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "783faf20", + "metadata": {}, + "outputs": [], + "source": [ + "# Just the names of the axes\n", + "x, y = anl.parameters \n", + " \n", + "xdata, ydata = anl.chain[:,0], anl.chain[:,1]" + ] + }, + { + "cell_type": "markdown", + "id": "3cf469e1", + "metadata": {}, + "source": [ + "or equivalently," + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "09e64c06", + "metadata": {}, + "outputs": [], + "source": [ + "xdata, ydata = anl.chain.T" + ] + }, + { + "cell_type": "markdown", + "id": "3bd844d1", + "metadata": {}, + "source": [ + "And to plot the samples," + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "4358eb10", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Text(0, 0.5, 'tanh_xdz')" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "pl.scatter(xdata, ydata)\n", + "pl.xlabel(x)\n", + "pl.ylabel(y)" + ] + }, + { + "cell_type": "markdown", + "id": "30f94e35", + "metadata": {}, + "source": [ + "To extract blobs, you could do" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "41e3b655", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "# Loaded test_2d_grid.000.blob_1d.cgm_h_2.pkl\n", + "(1240, 16)\n" + ] + } + ], + "source": [ + "QHII = anl.get_blob('cgm_h_2')\n", + "print(QHII.shape)" + ] + }, + { + "cell_type": "markdown", + "id": "6e950b1c", + "metadata": {}, + "source": [ + "Notice that the first dimension of ``QHII`` is the same as the first dimension of ``chain`` -- just the number of samples in the ModelGrid. The second dimension, however, is different. Now, rather than representing the dimensionality of the parameter space, it represents the dimensionality of this particular blob. Why 16 elements? Because our blobs were setup such that the quantities ``cgm_h_2``, ``igm_Tk``, and ``dTb`` were recorded at all redshifts in ``np.arange(5, 21)``, which has 16 elements.\n", + "\n", + "So, we could for example color-code the points in our previous plot by the volume-averaged ionization fraction at :math:`z=10` by doing:" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "b4046135", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "pl.scatter(xdata, ydata, c=QHII[:,5], edgecolors='none')" + ] + }, + { + "cell_type": "markdown", + "id": "247329ef", + "metadata": {}, + "source": [ + "If you forget the properties of a blob, you can type" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "5f018853", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 0 1 (16,)\n" + ] + } + ], + "source": [ + "group, element, nd, shape = anl.blob_info('cgm_h_2')\n", + "print(group, element, nd, shape)" + ] + }, + { + "cell_type": "markdown", + "id": "7c9a56a8", + "metadata": {}, + "source": [ + "which returns the index of blob group, index of the element within that group, dimensionality of the blob, and the shape of blob. This can be useful, for example, to automatically figure out the independent variables for a blob:" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "6a7a563f", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "10" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Should be 10 (redshift of interest above)\n", + "anl.blob_ivars[group][element][5]" + ] + }, + { + "cell_type": "markdown", + "id": "c86f3eda", + "metadata": {}, + "source": [ + "All of the built-in analysis routines are structured so that you don't have to think about these things on a regular basis if you don't want to! " + ] + }, + { + "cell_type": "markdown", + "id": "e54e8128", + "metadata": {}, + "source": [ + "## More Expensive Models" + ] + }, + { + "cell_type": "markdown", + "id": "62d38430", + "metadata": {}, + "source": [ + "Setting ``tanh_model=True`` sped things up considerably in the previous example. In general, you can run grids varying any *ARES* parameters you like, just know that physical models (i.e., those with ``tanh_model=False``) generally take a few seconds each, whereas the $tanh$ model takes much less than a second for one model.\n", + "\n", + "For example, to repeat the previous exercise for a physical model, you could replace this commands:" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "a8e66daa", + "metadata": {}, + "outputs": [], + "source": [ + "z0 = np.arange(6, 12, 0.1)\n", + "dz = np.arange(0.1, 8.1, 0.1)\n", + "mg.axes = {'tanh_xz0': z0, 'tanh_xdz': dz}" + ] + }, + { + "cell_type": "markdown", + "id": "d5bd3c0c", + "metadata": {}, + "source": [ + "with (for example)" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "43e84f33", + "metadata": {}, + "outputs": [], + "source": [ + "fX = np.logspace(-1, 1, 21)\n", + "Tmin = np.logspace(3, 5, 21)\n", + "mg.axes = {'fX': z0, 'Tmin': dz}" + ] + }, + { + "cell_type": "markdown", + "id": "3646c560", + "metadata": {}, + "source": [ + "In some cases -- e.g., when ``Tmin`` or ``pop_Tmin`` is an axis of the model grid -- load-balancing can be very advantageous. Just execute the following command before running the grid:" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "02dcfcdb", + "metadata": {}, + "outputs": [], + "source": [ + "mg.LoadBalance(method=1, par='Tmin') # or 'pop_Tmin'" + ] + }, + { + "cell_type": "markdown", + "id": "1f3f8743", + "metadata": {}, + "source": [ + "The ``method=1`` setting assigns all models with common ``Tmin`` values to the same processor. This helps because *ARES* knows that it need only generate lookup tables for $df_{\\mathrm{coll}} / dz$ (which determines the star formation rate density in the simplest models; see [this example](example_gs_standard)) once per value of ``Tmin``, which means you save a little bit of runtime at the outset of each calculation.\n", + " \n", + "There is also a ``method=2`` option for load balancing, which is advantageous if the runtime of individual models is strongly correlated with a given parameter. In this case, the models will be sorted such that each processor gets a (roughly) equal share of the models for each value of the input ``par``. It helps to imagine the grid points of our 2-D parameter space color-coded by processor ID number: the resulting image for ``method=2`` is simply the transpose of the image you'd get for ``method=1``.\n", + "\n", + "If the edges of your parameter space correspond to rather extreme \n", + "models you might find that the calculations grind to a halt. This can be a big problem because you'll end up with one or more processors spinning their wheels while the rest of the processors continue. One way of dealing with this is to set an \"alarm\" that will be tripped if the runtime of a particular model exceeds some user-defined value. For example, before running a model grid, you might set:" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "321b5dff", + "metadata": {}, + "outputs": [], + "source": [ + "mg.timeout = 60 " + ] + }, + { + "cell_type": "markdown", + "id": "dddb1223", + "metadata": {}, + "source": [ + "to limit calculations to 60 seconds or less. Models that trip this alarm will be recorded in the ``*fail*.pkl`` files so that you can look back later and (hopefully) figure out why they took so long.\n", + "\n", + "**NOTE:** This tends to happen because the ionization and/or heating rates are very large, which drives the time-step to very small values. However, in these circumstances the temperature and/or ionized fraction are typically exceedingly large, at which point the 21-cm signal is zero and need not be tracked any longer. As a result, terminating such calculations \n", + "before completion rarely has an important impact on the results.\n", + "\n", + "**WARNING:** This may not work on all operating systems for unknown reasons. Let me know if you get a mysterious crash when using the ``timeout`` feature." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/examples/example_grid_analysis.ipynb b/docs/examples/example_grid_analysis.ipynb new file mode 100644 index 000000000..aebeaee07 --- /dev/null +++ b/docs/examples/example_grid_analysis.ipynb @@ -0,0 +1,607 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "9b618b47", + "metadata": {}, + "source": [ + "# Analyzing Model Grids / Monte Carlo Simulations" + ] + }, + { + "cell_type": "markdown", + "id": "5d5b7c8b", + "metadata": {}, + "source": [ + "Once you have a model grid in hand, there are a slew of built-in analysis \n", + "routines that you might consider using. For the rest of this example,\n", + "we'll assume you have completed the [Example 2-D Grid](example_grid), and have the associated set of files\n", + "with prefix ``test_2d_grid``. \n", + "\n", + "To begin, initialize an instance of the analysis class, ``ModelSet``: " + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "a9ac1d8b", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "############################################################################\n", + "## Analysis: Model Set ##\n", + "############################################################################\n", + "## ---------------------------------------------------------------------- ##\n", + "## Basic Information ##\n", + "## ---------------------------------------------------------------------- ##\n", + "## path : ./ ##\n", + "## prefix : test_2d_grid ##\n", + "## N-d : 2 ##\n", + "## ---------------------------------------------------------------------- ##\n", + "## param #00: tanh_xz0 ##\n", + "## param #01: tanh_xdz ##\n", + "############################################################################\n", + "\n" + ] + } + ], + "source": [ + "import ares\n", + "\n", + "anl = ares.analysis.ModelSet('test_2d_grid')" + ] + }, + { + "cell_type": "markdown", + "id": "12c08f1f", + "metadata": {}, + "source": [ + "First, let's verify that we've surveyed the part of parameter space we \n", + "intended to: " + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "28bdf997", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAWMAAAERCAYAAACuKMYrAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8QVMy6AAAACXBIWXMAAAsTAAALEwEAmpwYAAAdYElEQVR4nO2df7RdZXnnP18uEQIKWLiIRAJMhVAZ14i5I60/aQUyRbCROHVUxAo1dC1htVawspwpS6WDDB2rzsgaAmptEW0LCGv8AaXSztjRGb0xgkLN4FCrBqVXKzDRICE888feYW6Sm7zn7HvOed+d9/tZK4t7933OeZ/PJXnuvu93n7MVERhjjMnLPrkbMMYY42FsjDFF4GFsjDEF4GFsjDEF4GFsjDEF4GFsjDEFsG/uBrpy2GGHxTHHHJO7DWOMGYr169f/MCKmdz7e22F8zDHHMDs7m7sNY4wZCkn/sNBxb1MYY0wBeBgbY0wBeBgbY0wBeBgbY0wBeBgbY0wBZLuaQtIvAscB9wFfjYjHxrneLRs2cdXtG3ngoS0cechSLlm1gtUnLctWU2JPdrNbaT311a0LyvEWmpJeCVwObAAOBC6NiPuGeY6ZmZkY9NK2WzZs4tKbv86WrduePLZ0yRRXnP3cJ7+Jk6wpsSe72a20nvrqlkLS+oiY2fn4xLcpJB0KvAV4XUS8EXgEeJ6kwyXtP441r7p94w7fPIAtW7dx1e0bs9SU2JPd7FZaT31160qObYrHgaXACZK+A5wCTAOvAu6XdEVE/GShB0paC6wFWL58+cALPvDQluTxSdaU2JPd7FZaT31168rEz4wj4mHgg8ClwF8CH42Is4DrgGcBz97DY9dFxExEzExP7/Jqwt1y5CFLk8cnWVNiT3azW2k99dWtK1mupoiIG4FTgS/Q7BsTEXcCTwOOHvV6l6xawZIp7XBsyZS4ZNWKLDUl9mQ3u5XWU1/dupLtaoqI+LGkO4Ffl/QYsD9wLHD3eBZMfD7pmhJ7slu6psSe7JauybHekOS+zvhLNGfG76QJ9d4UEd8e9SJX3b6RrU/s+B3b+kTssjE/qZoSe7Kb3Urrqa9uXcn6rm0R8RDwQUkfpbnM7pFxrFN7oGA3u6VqSuypr25dyX1mDEBE/N9xDWJwoGA3u6VqSuypr25dKWIYj5vaAwW72c1u5Qd4VQxjwIGC3UZTU2JPdkvX5FhvSKoYxrUHCnazm93KD/CqGMa1Bwp2s1uqpsSe+urWlSqGce2Bgt3slqopsae+unWlimFce6BgN7vZzQFeOdQeKNhtNDUl9mS3dE2O9YakimFce6BgN7vZzQFeEdQeKNjNbqmaEnvqq1tXqhjGtQcKdrNbqqbEnvrq1pUqhnHtgYLd7GY3B3jlUHugYLfR1JTYk93SNTnWG5IqhnHtgYLd7GY3B3hFUHugYDe7pWpK7Kmvbl2pYhjXHijYzW6pmhJ76qtbV7IOY0lHSFK6cnHUHijYzW52c4C3WyStAj4FHDWRBWsPFOw2mpoSe7JbuibHekOSZRhLOh24Engm8LZxr1d7oGA3u9nNAd4uSDoVuBp4PXAc8AuSXjrgY9dKmpU0Ozc3N/CatQcKdrNbqqbEnvrq1pUcZ8ZTwLkRcQ9wILAROBEgtX8cEesiYiYiZqanpwdesPZAwW52S9WU2FNf3boy8WEcEbdHxBcl7dPeHfozwGWSnhsRI9p92ZHaAwW72c1uDvB2S0Q80f73NmAdcKYaxtNT7YGC3UZTU2JPdkvX5FhvSEq5zvgu4BXAPtuH9CipPVCwm93s5gBvICLiJuABxnSZW+2Bgt3slqopsae+unUl+zDeHtpFxK9HxLfHsUbtgYLd7JaqKbGnvrp1JfswHldoN5/aAwW72c1uDvDKofZAwW6jqSmxJ7ula3KsNyRVDOPaAwW72c1uDvCKoPZAwW52S9WU2FNf3bpSxTCuPVCwm91SNSX21Fe3rlQxjGsPFOxmN7s5wCuH2gMFu42mpsSe7JauybHekFQxjGsPFOxmN7s5wCuC2gMFu9ktVVNiT31160oVw7j2QMFudkvVlNhTX926UsUwrj1QsJvd7OYArxxqDxTsNpqaEnuyW7omx3pDUsUwrj1QsJvd7OYArwhqDxTsZrdUTYk99dWtK1UM49oDBbvZLVVTYk99detK1mEs6cBJrFN7oGA3u9nNAd5ukfRrwJWSDp/IgrUHCnYbTU2JPdktXZNjvSHJMowlvQy4Erg1Iv5x3OvVHijYzW52Kz/A23fRz9CNlcB1EXGHpCOBE4FHgG9GxMO7e5CktcBagOXLlw+8WO2Bgt3slqopsae+unUl1zbF4/M+vhE4D7gQ+JCkp+/uQRGxLiJmImJmenp64MVqDxTsZrdUTYk99dWtK7mG8Z3AmyV9Erg2Il4LXAZsBl4w6sUuWbWCpUumdji2dMnULhvzk6opsSe72a20nvrq1pUswzgivgFcDJwMHNseux+YAgY/5R2Q1SctY83KZUw1N6JmSmLNymWsPmlZlpoSe7Kb3Urrqa9uXcl5advnaM6Gz5F0vqTzgZOAL416oVs2bOKm9ZvY1t6IelsEN63fxC0bNmWpKbEnu9mttJ766taVbMM4Ih6PiD8BXg38PPAc4E0R8X9GvdZVt29ky9ZtOxzbsnXbLinppGpK7Mludiutp766dSXX1RRPEhFfBb46zjVqT3ftZrdUTYk99dWtK345dIaaEnuym91K66mvbl2pYhjX/vJMu9nNbn45dDnU/vJMu42mpsSe7JauybHekFQxjGt/eabd7Ga38l8OXcUwrj1QsJvdUjUl9tRXt65UMYxrDxTsZrdUTYk99dWtK1UM49oDBbvZzW4O8Mqh9kDBbqOpKbEnu6Vrcqw3JFUM49oDBbvZzW4O8Iqg9kDBbnZL1ZTYU1/dulLFMK49ULCb3VI1JfbUV7euVDGMaw8U7GY3uznAK4faAwW7jaamxJ7slq7Jsd6QVDGMaw8U7GY3uznAK4LaAwW72S1VU2JPfXXrShXDuPZAwW52S9WU2FNf3bqSbRhLOkvSb09irdoDBbvZzW4O8BZE0unAe4B7J7Zo7YGC3UZTU2JPdkvX5FhvSCY+jCW9EPhTYG1E3CHpYElHSzpgXGvWHijYzW52Kz/Ay3EPvB8BW4FnSjoUuBHYAmyW9OfATRGx4M8aSWuBtQDLly8feMHaAwW72S1VU2JPfXXrysTPjCNiI/AK4I+Au4AbgDOB24A1wNP38Nh1ETETETPT09MDr1l7oGA3u6VqSuypr25dybJnHBF30QzgKyLi2oh4IiI+QjOIBz/lHZDaAwW72c1u5Qd4ObYpAIiIe5kX4ElaA0wD3x/PgonPJ11TYk92S9eU2JPd0jU51huS7NcZq+E8mqsrzo2IB0e9Ru2Bgt3sZjcHeINyP3B2RHxzHE9ee6BgN7ulakrsqa9uXcl+ZhwNfzOuQQwOFOxmt1RNiT311a0r2YfxJKg9ULCb3exWfoBXxTAGHCjYbTQ1JfZkt3RNjvWGpIphXHugYDe72a38AK+KYVx7oGA3u6VqSuypr25dqWIY1x4o2M1uqZoSe+qrW1eqGMa1Bwp2s5vd9uIAT9K1kqYW3cGkqD1QsNtoakrsyW7pmhzrDclizozvBz4j6akAks6U9JXRtDVaag8U7GY3u5Uf4HV+BV5EXCFpI/DfJW0F5oC3LLqjMVB7oGA3u6VqSuypr25dWcw2xb8CLgb+CTgYeHtEfHnRHY2B2gMFu9ktVVNiT31168pitineBrwtIk6leR/iGySdtuiOxkDtgYLd7Ga38gO8xWxTnDbv43vaM+WbgTsW3dU4qD1QsNtoakrsyW7pmhzrDcnAZ8aSPi3pV3b39Yj4AfDykXQ1YmoPFOxmN7uVH+ANs01xBnCrpFPmH5R0oKSLACJi8bvYY6D2QMFudkvVlNhTX926Muye8TuAT0n6pXnHngq8f9GdjJHaAwW72S1VU2JPfXXryjDDOIC/AC4CPi1p5aJXb5GkdFV3ag8U7GY3u+2FAV5EXC9pf+A2SS8HHuyysKQXA8dGxJ9GREhSRIxoK3wBag8U7DaamhJ7slu6Jsd6QzLMmfGTPw4i4jrgXTRXTjxnmAUl7dO+au8a4FJJv9U+Z0gay3tl1B4o2M1udis/wBvmzPgiYPP2TyLiP7dnyJ8aZsGIeALYLOljwDbghZKWRsQftV/bLZLWAmsBli9fPvCatQcKdrNbqqbEnvrq1pWBz0Qj4kMR8dOdjv0h8F7gpws/ao88DhwFfAx4gaT3SbqivVv0gn1FxLqImImImenp6YEXqj1QsJvdUjUl9tRXt6502hZotxpWS/oscDlwQIenuRX4QUR8HpgFfgs4qL1B6R7PkIel9kDBbnazW/kB3lDDWNIxki4Hvgt8EthCc7lbF7YAKyS9mWYQvxdYLumCjs+3Z2oPFOw2mpoSe7JbuibHekOSHMaSpiSdLel24FvAqTRnw8+MiDXA57osHBEP0Az1fwf8bkS8G3gf8Nkuz7cnag8U7GY3u+0dAd53gZ8B1wMXRcT/XvSq/59rgVsjYn37+X8b9RYFOFCwm91SNSX21Fe3rgyyTTEN3Af8HfCdRa84j4j4bkSs3/6ij3EMYnCgYDe7pWpK7Kmvbl0ZZBg/C/hrmq2JByV9RNJLF73yPMb6Yg8cKNjNbnbbCwK8iHgwIq4Afh54DXAI8FeS/l7Su4HjFt3FJKg9ULDbaGpK7Mlu6Zoc6w3JMNcZR0TcFhFnA8uBDwNvoHkP46KpPVCwm93sVn6A1+k644j4QURcDvwz4Ezgvy66kzFSe6BgN7ulakrsqa9uXVnUe0G0Z8ufjYjVi+5kjNQeKNjNbqmaEnvqq1tXxvLGPKVRe6BgN7vZbS8I8PYaag8U7DaamhJ7slu6Jsd6Q1LFMK49ULCb3ey2lwZ4faP2QMFudkvVlNhTX926UsUwrj1QsJvdUjUl9tRXt65UMYxrDxTsZje7OcArh9oDBbuNpqbEnuyWrsmx3pBUMYxrDxTsZje7OcArgtoDBbvZLVVTYk99detKFcO49kDBbnZL1ZTYU1/dulLFMK49ULCb3exWfoA3yJ0+xoKkE4HDgG9ExI/GvmDtgYLdRlNTYk92S9fkWG9IspwZS/pV4BPAW4E/kXTEONerPVCwm93s5gBvFySdAnwA+M323d4eA/75gI9dK2lW0uzc3NzAa9YeKNjNbqmaEnvqq1tXcpwZPwhcEBFfbs+ITwYulHSNpFdvvx/eQkTEuoiYiYiZ6enpgResPVCwm91SNSX21Fe3rkx8GEfE30XEX7efng9c3Z4h/0/gX9PsI4+US1atYOmSqR2OLV0ytcvG/KRqSuzJbnYrrae+unUl69UUEfEH7R1DiIiPAk8Djhr1OqtPWsaalcuYak+6pyTWrFzG6pOWZakpsSe72a20nvrq1pVsw3jn7QhJa4BnAA+Meq1bNmzipvWb2NbehHpbBDet38QtGzZlqSmxJ7vZrbSe+urWlWzDOKKxkbSfpPOBdwNvjIgfjHqtq27fyJat23Y4tmXrtl1S0knVlNiT3exWWk99detKtuuM5/EE8H3g7IhYvNEC1J7u2s1uqZoSe+qrW1eyvwIvIra2NzUdyyAGp7t2s1uqpsSe+urWlezDeBLU/vJMu9nNbuW/HLqKYQz45Zl2G01NiT3ZLV2TY70hqWIY1/7yTLvZzW5+OXQR1B4o2M1uqZoSe+qrW1eqGMa1Bwp2s1uqpsSe+urWlSqGce2Bgt3sZjcHeOVQe6Bgt9HUlNiT3dI1OdYbkiqGce2Bgt3sZjcHeEVQe6BgN7ulakrsqa9uXaliGNceKNjNbqmaEnvqq1tXqhjGtQcKdrOb3RzglUPtgYLdRlNTYk92S9fkWG9IqhjGtQcKdrOb3RzgFUHtgYLd7JaqKbGnvrp1pYphXHugYDe7pWpK7Kmvbl3JedulZ0uakbTfuNeqPVCwm93s5gBvQSSdCdwMXAX8saTjx75o7YGC3UZTU2JPdkvX5FhvSCY+jCW9EPhDmvvd/TLwY+Ad41yz9kDBbnazmwO83fHeiNjQfnwZ8HODbFdIWitpVtLs3NzcwIvVHijYzW6pmhJ76qtbV3IM4/9Fs0WBpClgP+Bo4KD22KG7e2BErIuImYiYmZ6eHnjB2gMFu9ktVVNiT31168rEh3FEbIuIR9pPBTwE/FNEzEl6PXC5pMWbzaP2QMFudrNb+QHevot+hkUQEY8DmyV9V9IVwOnAb0TE4s/5d1ks8fmka0rsyW7pmhJ7slu6Jsd6Q5L1OmM1PAV4CfB64N9ExNdHvU7tgYLd7Ga38gO83GfGATwm6T3AVyLivnGsU3ugYDe7pWpK7Kmvbl0p5RV4H4uIe8b15LUHCnazW6qmxJ766taVIoZxe4Y8NmoPFOxmN7uVH+AVMYwnQu2Bgt1GU1NiT3ZL1+RYb0iqGMa1Bwp2s5vdyg/wqhjGtQcKdrNbqqbEnvrq1pUqhnHtgYLd7JaqKbGnvrp1pYphXHugYDe72c0BXjnUHijYbTQ1JfZkt3RNjvWGpIphXHugYDe72c0BXhHUHijYzW6pmhJ76qtbV6oYxrUHCnazW6qmxJ766taVKoZx7YGC3exmNwd45VB7oGC30dSU2JPd0jU51huSKoZx7YGC3exmNwd4RVB7oGA3u6VqSuypr25dqWIY1x4o2M1uqZoSe+qrW1eqGMa1Bwp2s5vdHODtkfbu0JOh9kDBbqOpKbEnu6Vrcqw3JFmGsaTjASJi2yQGcu2Bgt3sZjcHeLsg6Uzga5JugOEGsqS1kmYlzc7NzQ28Zu2Bgt3slqopsae+unVlosNY0oHAhcDv0NyI9HoYfCBHxLqImImImenp6YHXrT1QsJvdUjUl9tRXt65MdBhHxE+A84AbgIuB/ecP5HGtW3ugYDe72c0B3i5ExAMRsTkifghcACzdPpAlPV/SCeNZOPH5pGtK7Mlu6ZoSe7JbuibHekOS9WqKiPgRzUDeKumbwJ8Bm0e9Tu2Bgt3sZjcHeEnaM+S7gUOAsyPie6Neo/ZAwW52S9WU2FNf3bqSfRhLejpwBnB6RHx9HGvUHijYzW6pmhJ76qtbV7IP44j4MXBWRNw9rjVqDxTsZje7OcAbiIh4dPyLJD6fdE2JPdktXVNiT3ZL1+RYb0iKGMbjpvZAwW52s5sDvCKoPVCwm91SNSX21Fe3rlQxjGsPFOxmt1RNiT311a0rVQzj2gMFu9nNbg7wyqH2QMFuo6kpsSe7pWtyrDckVQzj2gMFu9nNbg7wiqD2QMFudkvVlNhTX926UsUwrj1QsJvdUjUl9tRXt65UMYxrDxTsZje7OcArh9oDBbuNpqbEnuyWrsmx3pBUMYxrDxTsZje7OcArgtoDBbvZLVVTYk99detKFcO49kDBbnZL1ZTYU1/dulLFML5k1QqWLtnxfqdLl0ztsjE/qZoSe7Kb3Urrqa9uXdl30c/QEUkrgJ8DZoEnxnlD0tUnLQOa/Z4HHtrCkYcs5ZJVK548PumaEnuym91K66mvbl1RxIiiwGEWlc4G/j2wqf0zC/xxRDwy6HPMzMzE7OzsmDo0xpjxIGl9RMzsfHzi2xSSlgCvAc6PiJcDtwJHAW+XdFDisWslzUqanZubm0C3xhgzGXLtGR8EHNd+/Cng08BTgNdJ0u4eFBHrImImImamp6cn0KYxxkyGiQ/jiNgKvA84W9JLIuIJ4G+BrwEvnnQ/xhhTArnOjL8A/CXwBkkvjYhtEXEDcCTwLzL1ZIwx2chyNUVEPCrp4zQvJLxU0gnAz4BnAN/P0ZMxxuQky9UUTy4uPQV4EXAB8CjwgYjYMOBj54B/6LDsYcAPOzwuN+57cvSxZ3Dfk6Zr30dHxC6hV9Zh/GQT0hQQ7f7xuNeaXeiyktJx35Ojjz2D+540o+4724s+5jPOF3wYY0wfqOLl0MYYUzo1DuN1uRvoiPueHH3sGdz3pBlp30XsGRtjTO3UeGZsjDHF4WFsjDEFUM0wlnRg7h6GRdIRe3qvDmPM3kMVw1jSrwFXSjo8dy+DImkVzZsoHZW7l2GQ9IuS3tD+9ym5+xkUScdJmpE01V733lv8A3yyjOr7vdcHeJJeBlwDXBQRd+TuZxAknQ78B+AQ4NaI+O28HQ2GpFcClwMbgAOBSyPivrxdpZG0GngX8C3ge8BG4GMR8ZOcfQ2KpJOB/YGfRsRX2mOKwv9xSzpomPcwLwVJzwcOAB6LiC+P6nlrODNeCVwXEXdIOlLSaZJOlnRw7sYWQtKpwNXA62neZvQXJL00b1dpJB0KvAV4XUS8EXgEeJ6kwyXtn7e73dP2fQHw2ohYA9wFvAl4q6SnZW1uACT9KnA9zd+Xd0r6MDQvZy35DLm9wcQX2n+LvZlDks4EPgysBS6WdMGonrs334RF8Pi8j28EzgMuBD4k6el5WtojU8C5EXEPzdnlRuBEKP7Xz8eBpcAJ7U0CTgHOBd4P/NuC9+wfB54KHAEQER+hec+TaeDMjH0labdT3gi8OyLW0ny/V0i6EcodyJKOAX4X+EfgrcDzS+xzZySdRHOHot+IiHOBvwBOGNXz1zCM7wTeLOmTwLUR8VrgMmAz8IKsnS1ARNweEV+UtE9EPAR8BrhM0nNL/rUzIh4GPghcSvP2qB+NiLOA64BnAc/O2N5uafv+OPCmdq/7D2jetOpe4LSszSVo30Zgw7zPH4mIFwPPkHRNe6zEvzNPAO+MiNNovs+/D6yUtMPbMxQ4oJcCV0fEXe3nG4AXSTpqFL3u9cM4Ir4BXAycDBzbHruf5gy02NuFbH/TpIi4jeaVPmeqodj/ZxFxI3AqzftVb2iP3Qk8DTg6Y2spPgHcBvwKcEBEnBMR1wCHp24FlgNJx8/7dBPwe5KWzzv2KuBQSc+ZbGd7ZnvfEfEdmptJEBHvBr5Cc4J0Ulv33PZrRfwgmdf3F4Gb2mNTwAPAg8DD7W8hx+3+WdIU+w97xHyO5n/2OZLOl3Q+zf/4L+Vta2DuAl4B7DOJd7ZbDBHxY5rfRtZIOr0N9Y4F7s7b2e6JiIcj4uM092V8K4Ckc2nuXl7Um1i1e5Zfa3/TIyKup7nq5n9sH8gR8UOa7Zdi9rzn9f0JaL7n26+2iYj3AF+m2ad/L/DxUq58WuD7Pdf+1rqN5jeoqbbuDcB/XMzW515/NcV82hT01cB+NHej/nrmlgZG0p8Db4+Ib+fuJYWkQ2j2L9fQ/IV9+7xf7YpH0nk0v029pqS/I+2++03AzcALgf3abTckvQd4JU34exhwDnBGRPx9pnafZIG+942Ic9qv7RcRP2s//hvgeGBVCd/3RN9TgGh+q3oYeB5N1nNv5/VqGsZ9pA+XKO2O9moE9e3yJUlHA0si4lu5e9kZSUfSXKmyP/BfgK3zBvKraILIlcD72y26Ilig70e3D7b268cDf0YTjhXzg3uAvm+h+QHyqojYuKi1evrv3JjqaS/LW0dzvetrJZ0IbI6ILnfAmRjz+t4SEedIeh7NHePvbbdYimSBvo+juQzy+sWcET/5/B7GxvQXSYcBV9H8Gj0FnBIR38vbVZp5ff8STd8vi4gH8naVZl7fL2oPvSQiHhzFc9cS4BmzV9KeSd4NHEzzq3Lxgxh26PsQ4Ow+DGLYoe+DgDWjGsTgYWxMr2nT+zOA00sIvQbFfS/w3N6mMKbfSNo/Ih7N3cewuO+dntfD2Bhj8uNtCmOMKQAPY2OMKQAPY2OMKQAPY2OMKQAPY2OMKQAPY1M1ki6UFAv8+Wzu3kxd+NI2UzWSnkpzp4/tvBq4Eljdl3smmr0DD2NjWiSdA3yI5uW5n8/dj6kLb1MYA0j6TeA/Aa/wIDY58DA21SPpQpqtiVUR8bfzjv+VpDPajy/dfudlY8bBvukSY/ZeJF0M/B5wakRs2OnLv09zK52lwC/T3PrKmLHgPWNTLZIuBd4BnA3cM+9LmyNic1vzeeBQmvfbfXjyXZpa8DA2VdLeWv0hmvel3ZnfiYgPtHfOuBl4JCL+5ST7M/XhPWNTJdFwcERogT8fkHQEzc0m1wBzks7K3LLZy/GZsTE7IekA4PPAuyLiNkknA1dHxMrMrZm9GA9jY4wpAG9TGGNMAXgYG2NMAXgYG2NMAXgYG2NMAXgYG2NMAXgYG2NMAXgYG2NMAXgYG2NMAXgYG2NMAfw/jR/jAv+9ShMAAAAASUVORK5CYII=\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "ax = anl.Scatter(anl.parameters)" + ] + }, + { + "cell_type": "markdown", + "id": "789ad718", + "metadata": {}, + "source": [ + "## Basic Inspection" + ] + }, + { + "cell_type": "markdown", + "id": "1fe035f0", + "metadata": {}, + "source": [ + "Now, the kind of analysis you can do will be limited by what quantities\n", + "were saved for each model. Recall (from [Example 2-D Grid](example_grid)) that we have \n", + "the following quantities at our disposal:\n", + "\n", + "* 21-cm brightness temperature, ``dTb``.\n", + "* Kinetic temperature of the IGM, ``igm_Tk``.\n", + "* HII region volume filling factor, ``cgm_h_2``.\n", + "* CMB optical depth, ``tau_e``.\n", + "* Position of 21-cm emission maximum, ``z_D`` and ``dTb_D``.\n", + "\n", + "Let's have a look at how the ionization history depends on our two parameters of\n", + "interest in this example, ``tanh_xz0`` and ``tanh_xdz``,\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "35ac05fa", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "# Loaded test_2d_grid.000.blob_1d.cgm_h_2.pkl\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "ax = anl.Scatter(['tanh_xz0', 'tanh_xdz'], c='cgm_h_2', ivar=[None,None,10], fig=2, edgecolors='none')" + ] + }, + { + "cell_type": "markdown", + "id": "e86557f6", + "metadata": {}, + "source": [ + "**NOTE:** All ``ModelSet`` functions accept ``fig`` as an optional keyword \n", + " argument, which you can set to any integer to open plots in a new window. \n", + "\n", + "The keyword argument ``ivar`` is short for \"independent variables\" -- it is ``None`` by default. However, because we have chosen to plot ``cgm_h_2``, which is a 1-D blob, we must specify the redshift of interest. Recall that we have access to integer redshifts in the interval $5 \\leq z \\leq 20$, or check for yourself:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "47a414bf", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(None, [array([ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20])])\n" + ] + } + ], + "source": [ + "print(anl.blob_ivars)" + ] + }, + { + "cell_type": "markdown", + "id": "03296c76", + "metadata": {}, + "source": [ + "So our choice of $z=10$ should be OK. \n", + "\n", + "If you forget what fields are available for analysis, see:" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "e35992b7", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(['z_D', 'dTb_D', 'tau_e'], ['cgm_h_2', 'igm_Tk', 'dTb']) (None, [array([ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20])])\n" + ] + } + ], + "source": [ + "print(anl.blob_names, anl.blob_ivars)" + ] + }, + { + "cell_type": "markdown", + "id": "5b847254", + "metadata": {}, + "source": [ + "**NOTE:** Calling quantities of interest `blobs` was inspired by the arbitrary meta-data blobs in [emcee](http://dan.iel.fm/emcee/current/). \n", + " \n", + "For more 21-cm-focused analyses, you may want to view how the extrema in the\n", + "global 21-cm signal change as a function of the model parameters:" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "31f716a3", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "# Loaded test_2d_grid.000.blob_0d.z_D.pkl\n", + "# Loaded test_2d_grid.000.blob_0d.dTb_D.pkl\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "# Scatterplot showing where emission peak occurs\n", + "ax = anl.Scatter(['z_D', 'dTb_D'], fig=4)" + ] + }, + { + "cell_type": "markdown", + "id": "2401ea2b", + "metadata": {}, + "source": [ + "or, color-code points by CMB optical depth," + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "22b24df3", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "# Loaded test_2d_grid.000.blob_0d.tau_e.pkl\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "ax = anl.Scatter(['z_D', 'dTb_D'], c='tau_e', fig=5, edgecolors='none')" + ] + }, + { + "cell_type": "markdown", + "id": "3e3520d1", + "metadata": {}, + "source": [ + "You can also create your own derived quantities. A very simple example is to convert redshifts to observed frequencies," + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "edc18c3e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "test_2d_grid.blob_0d.nu_D.pkl exists! Set clobber=True or remove by hand.\n" + ] + }, + { + "data": { + "text/plain": [ + "masked_array(data=[136.43962086618077, 136.4395602206665,\n", + " 136.4213637970313, ..., 111.59846749404792,\n", + " 111.8355833582385, 112.06807146360116],\n", + " mask=[False, False, False, ..., False, False, False],\n", + " fill_value=1e+20)" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# 1420.4057 is the rest frequency of the 21-cm line in MHz\n", + "anl.DeriveBlob(expr='1420.4057 / (1. + x)', varmap={'x': 'z_D'}, name='nu_D')" + ] + }, + { + "cell_type": "markdown", + "id": "67f4d943", + "metadata": {}, + "source": [ + "This will create a new blob, called ``nu_D``, that can be used for subsequent analysis. For example," + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "4cf26a9a", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "# Scatterplot showing where emission peak occurs\n", + "ax = anl.Scatter(['nu_D', 'dTb_D'], c='tau_e', fig=6, edgecolors='none')" + ] + }, + { + "cell_type": "markdown", + "id": "353e5aec", + "metadata": {}, + "source": [ + "## Problem Realizations" + ] + }, + { + "cell_type": "markdown", + "id": "2f4a81d2", + "metadata": {}, + "source": [ + "You may have noticed that in this model grid there are three realizations whose emission maxima seem to occur at $\\delta T_b \\approx 0$. In general, this is possible, but given the regularity of the grid points in parameter space it seems unlikely that any individual model would stray substantially from the locus of all other models.\n", + "\n", + "To inspect potentially problematic realizations, it is first useful to isolate them from the rest. You can select them visually by first invoking (**NOTE:** this won't work in a Jupyter notebook):" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "5813370f", + "metadata": {}, + "outputs": [], + "source": [ + "anl.SelectModels()" + ] + }, + { + "cell_type": "markdown", + "id": "3aa26fcd", + "metadata": {}, + "source": [ + "and then clicking and dragging within the plot window to define a rectangle, starting from its upper left corner (click) and ending with its bottom right corner (release). The set of models bounded by this rectangle will be saved as a new ``ModelSet`` object that can be used just like the original one. Each successive \"slice\" will be saved as attributes ``slice_0``, ``slice_1``, etc. that you can assign to a new variable, as, e.g." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "697e73e9", + "metadata": {}, + "outputs": [], + "source": [ + "#slc0 = anl.slice_0\n", + "#slc0.Scatter(['nu_D', 'dTb_D'], c='tau_e', fig=7, edgecolors='none')" + ] + }, + { + "cell_type": "markdown", + "id": "57cb29a6", + "metadata": {}, + "source": [ + "Alternatively, you can specify a rectangle by hand. For example, " + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "1c1702de", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "############################################################################\n", + "## Analysis: Model Set ##\n", + "############################################################################\n", + "## ---------------------------------------------------------------------- ##\n", + "## Basic Information ##\n", + "## ---------------------------------------------------------------------- ##\n", + "## path : ./ ##\n", + "## prefix : test_2d_grid ##\n", + "## N-d : 2 ##\n", + "## ---------------------------------------------------------------------- ##\n", + "## param #00: tanh_xz0 ##\n", + "## param #01: tanh_xdz ##\n", + "############################################################################\n", + "\n", + "Saved result to slice_0 attribute.\n" + ] + } + ], + "source": [ + "slc = anl.Slice([100, 120, 0, 10], pars=['nu_D', 'dTb_D'])" + ] + }, + { + "cell_type": "markdown", + "id": "e35fce0d", + "metadata": {}, + "source": [ + "extracts all models with ``100 <= nu_D <= 120`` and ``0 <= dTb_D <= 10``. Check:" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "6f090839", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "# Loaded test_2d_grid.000.blob_0d.dTb_D.pkl\n", + "# Loaded test_2d_grid.000.blob_0d.tau_e.pkl\n" + ] + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "slc.Scatter(['nu_D', 'dTb_D'], c='tau_e', fig=8, edgecolors='none')" + ] + }, + { + "cell_type": "markdown", + "id": "f97a2264", + "metadata": {}, + "source": [ + "If you wanted to examine models in more detail, you could re-run them. Collecting the parameter dictionaries required to do so is easy" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "01f3436a", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING: Any un-pickleable kwargs will not have been saved in test_2d_grid.binfo.pkl!\n" + ] + } + ], + "source": [ + "kwargs_list = slc.AssembleParametersList(include_bkw=True)" + ] + }, + { + "cell_type": "markdown", + "id": "6c5e2b99", + "metadata": {}, + "source": [ + "This routine returns a list in which each element is a dictionary of parameters for a single model. The keyword argument ``include_bkw`` controls whether the \"base kwargs,\" i.e., those that are shared by all models in the grid, are included in each list element. If they are (as above), then any individual dictionary can be used to initialize a simulation. For example:\n" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "21259010", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "ax = None\n", + "for kwargs in kwargs_list[0:3]:\n", + " sim = ares.simulations.Global21cm(**kwargs)\n", + " sim.run()\n", + " ax, zax = sim.GlobalSignature(color='b', alpha=0.5, ax=ax)" + ] + }, + { + "cell_type": "markdown", + "id": "58bbf8d7", + "metadata": {}, + "source": [ + "If you've got models that seem to have something wrong with them, sending me the dictionary (or a list of them as above) will help a lot. Just do something like:" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "f6d8cf70", + "metadata": {}, + "outputs": [], + "source": [ + "import pickle\n", + "f = open('problematic_models.pkl', 'wb')\n", + "pickle.dump(kwargs_list, f)\n", + "f.close()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4ef4c2ba", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/fields.rst b/docs/fields.rst new file mode 100644 index 000000000..14f3ef52a --- /dev/null +++ b/docs/fields.rst @@ -0,0 +1,50 @@ +Field Listing +============= +The most fundamental quantities associated with any calculation done in ares +are the gas density, species fractions and the gas temperature. + +Species Fractions +----------------- +Our naming convention is to denote ions using their chemical symbol (in lower-case), followed by the ionization state, separated by an underscore. Rather than denoting the ionization state with roman numerals, we simply use integers. For example, neutral hydrogen is `h_1` and ionized hydrogen is `h_2`. + +Here is a complete listing: + +* Neutral hydrogen fraction: ``'h_1'`` +* Ionized hydrogen fraction: ``'h_2'`` +* Neutral helium fraction: ``'he_1'`` +* Singly-ionized helium fraction: ``'he_2'`` +* Doubly-ionized helium fraction: ``'he_3'`` +* Electron fraction: ``'e'`` +* Gas density (in :math:`g \ \text{cm}^{-3}`): ``'rho'`` + +These are the default elements in the ``history`` dictionary, which is an attribute of all ``ares.simulations`` classes. + +We also generally keep track of the ionization and heating rate coefficients: + +* Rate coefficient for photo-ionization, ``k_ion``. +* Rate coefficient for secondary ionization by photo-electrons, ``k_ion2``. +* Rate coefficient for photo-heating, ``k_heat``. + +Each of these quantities are multi-dimensional because we store the rate coefficients for each absorbing species separately. + +Two-Zone IGM Models +------------------- +For calculations of the reionization history or global 21-cm signal, in which we use a two-zone IGM formalism, all quantities described in the previous sections keep their usual names with one important change: they now also have an `igm` or `cgm` prefix to signify which phase of the IGM they belong to. The `igm` phase is of course short for inter-galactic medium, while the `cgm` phase stands for the circum-galactic medium (really just meant to indicate gas near galaxies). + +* Kinetic temperature, ``igm_Tk``. +* HII region volume filling factor, ``cgm_h_2``. +* Neutral fraction in the bulk IGM, ``igm_h_1``. +* Heating rate in the IGM, ``igm_k_heat``. +* Volume-averaged ionization rate, ``cgm_k_ion``. + +There are also new (passive) quantities, like the neutral hydrogen excitation +(or ``spin'' temperature), the 21-cm brightness temperature, and the Lyman-:math:`\alpha` background intensity: + +* 21-cm brightness temperature: ``'igm_dTb'``. +* Spin temperature: ``'igm_Ts'``. +* :math:`J_{\alpha}`: ``'igm_Ja'``. + +Each of these are only associated with the IGM grid patch, since the other phase of the IGM is assumed to be fully ionized and thus dark at 21-cm wavelengths. + + + diff --git a/docs/inits_tables.rst b/docs/inits_tables.rst new file mode 100644 index 000000000..dcd83802b --- /dev/null +++ b/docs/inits_tables.rst @@ -0,0 +1,43 @@ +Initial Conditions & Lookup Tables +================================== + +.. Cosmological Initial Conditions +.. ------------------------------- +.. +.. +.. +.. +.. +.. +.. The Halo Mass Function +.. ---------------------- + + + + + +The Opacity of the Intergalactic Medium +--------------------------------------- +Solutions for the evolution of the cosmic X-ray background are greatly accelerated if one tabulates the IGM opacity, :math:`\tau_{\nu}(z, z^{\prime})`, ahead of time (see in Appendix C of `Haardt & Madau (1996) `_ for some discussion of this technique). *ARES* automatically looks in ``$ARES/input/optical_depth`` for :math:`\tau_{\nu}(z, z^{\prime})` lookup tables. + +The shape of the lookup table is defined by the redshift range being considered (set by the parameters ``first_light_redshift`` and ``final_redshift``), the number of redshift bins used to sample that interval, ``tau_redshift_bins``, the minimum and maximum photon energies (``pop_Emin`` and ``pop_Emax``), and the number of photon energies (determined iteratively from the redshift and energy intervals and the value of ``tau_redshift_bins``). + +By default, ares generates tables assuming the IGM is fully neutral, but that is not required. To make optical depth tables of your own, see ``$ARES/input/optical_depth/generate_optical_depth_tables.py``. See Section 3 of `Mirocha (2014) `_ for more discussion of this technique. + +Tables for ``mirocha2017``-like calculations +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +To generate the table used for the calculations in `Mirocha, Furlanetto, & Sun (2017) `_, modify the following lines of ``$ARES/input/optical_depth/generate_optical_depth_tables.py``: + +:: + + zf, zi = (5, 50) + Emin = 2e2 + Emax = 3e4 + Nz = [1e3] + helium = 1 + +.. note :: You can run the ``generate_optical_depth_tables.py`` script in parallel via, e.g., ``mpirun -np 4 generate_optical_depth_tables.py``, so long as you have MPI and mpi4py installed. + +The set of parameters used for these calculations are described in the "Simulations" section of :doc:`param_bundles`. + + diff --git a/docs/requirements.txt b/docs/requirements.txt index 0686bbde7..5165f2035 100755 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -3,5 +3,5 @@ numpydoc nbsphinx m2r2 docutils<0.17 -lxml -lxml_html_clean +mistune<2.0.0 +lxml_html_clean \ No newline at end of file diff --git a/docs/structure.rst b/docs/structure.rst new file mode 100644 index 000000000..1489f1a8c --- /dev/null +++ b/docs/structure.rst @@ -0,0 +1,8 @@ +Code Structure +============== +*ARES* is organized hierarchically, with particularly heavy use of Python +`generators `_. This makes for a code +whose behavior can be easily adapted during run-time. + +The top level submodule of `ares` is the :py:mod:`ares.simulations` submodule. + diff --git a/input/halos/generate_surf_tables.py b/input/halos/generate_surf_tables.py index e4147eecf..a2f37ca4c 100644 --- a/input/halos/generate_surf_tables.py +++ b/input/halos/generate_surf_tables.py @@ -27,16 +27,16 @@ "halo_dlogM": 0.01, "halo_logMmin": 4, "halo_logMmax": 18, - "halo_zmin": 0, - "halo_zmax": 60, - "halo_dz": 0.05, + #"halo_zmin": 0, + #"halo_zmax": 60, + #"halo_dz": 0.05, #"hps_zmin": 0, #"hps_zmax": 30, #"hps_dz": 0.1, - "halo_dt": 100, - "halo_tmin": 100., + "halo_dt": 10, + "halo_tmin": 30., "halo_tmax": 13.7e3, # Myr @@ -50,4 +50,4 @@ halos = ares.physics.HaloModel(halo_mf_load=True, **pars) -halos.generate_halo_surface_dens(format=fmt, clobber=True, checkpoint=True) +halos.generate_halo_surface_dens(format=fmt, clobber=False, checkpoint=True) diff --git a/pyproject.toml b/pyproject.toml index 47626aeec..20578c8ad 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,68 @@ [build-system] requires = ["setuptools>=40.8.0", "wheel", "setuptools_scm"] build-backend = "setuptools.build_meta" + +[project] +name = "ares" +dependencies = [ + "h5py", + "matplotlib", + "numpy", + "scipy>=1.6", + "setuptools_scm", + "numdifftools<1.0", + "gdown<6", +] +dynamic = ["version"] +requires-python = ">= 3.7" +authors = [ + {name = "Jordan Mirocha", email = "mirochaj@gmail.com"} +] +maintainers = [ + {name = "Jordan Mirocha", email = "mirochaj@gmail.com"} +] +readme = "README.md" +license = {file = "LICENSE"} +keywords = ["astronomy", "cosmology", "reionization"] +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Science/Research", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Langauge :: Python :: 3.10", + "Programming Langauge :: Python :: 3.11", + "Programming Langauge :: Python :: 3.12", + "Topic :: Scientific/Engineering :: Astronomy", +] + +[project.optional-dependencies] +hmf = ["hmf", "camb"] +math = ["mpmath", "mcfit"] +progressbar = ["progressbar"] +doc = ["sphinx", "numpydoc", "nbsphinx"] +sed_modeling = ["dust_extinction", + "dust_attenuation @ git+https://github.com/karllark/dust_attenuation.git@main"] +tests = ["pytest", "coverage", "pytest-cov", "ares[hmf,math,sed_modeling]"] +all = ["ares[progressbar,doc,tests]"] + +[project.scripts] +ares = "ares.util.cli:main" + +[project.urls] +Homepage = "https://github.com/mirochaj/ares/" +Documentation = "https://ares.readthedocs.io/en/latest/" +Repository = "https://github.com/mirochaj/ares/" + +[tool.setuptools.packages.find] +where = ["."] +include = ["ares"] + +[tool.setuptools_scm] + +[tool.pytest.ini_options] +addopts = "--cov-config=.coveragerc --cov=ares --cov-report=html -v" +testpaths = [ + "tests/*.py", +] diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index ae78b1cf5..000000000 --- a/requirements.txt +++ /dev/null @@ -1,15 +0,0 @@ -numpy>=1.22.2 -matplotlib==2.2.4 -scipy==1.2.1 -h5py==2.9.0 -coveralls==1.11.1 -pytest==3.6.4 -pytest-cov==2.8.1 -pyyaml==5.4 -docutils==0.17.1 -cached_property>=1.5.2<2.0 -camb>=1.3<2.0 -hmf>=3.1<4.0 -mcfit -dust_extinction -dust_attenuation diff --git a/run_tests_local.sh b/run_tests_local.sh deleted file mode 100755 index 59327c65e..000000000 --- a/run_tests_local.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash - -# Can never remember all the flags -pytest --cov-config=.coveragerc --cov=ares --cov-report=html -v tests/*.py - -rm -f test_*.pkl test_*.txt test_*.hdf5 hmf*.pkl hmf*.hdf5 diff --git a/setup.py b/setup.py deleted file mode 100644 index bb946cd45..000000000 --- a/setup.py +++ /dev/null @@ -1,73 +0,0 @@ -#!/usr/bin/env python -import io -import os -from setuptools import find_namespace_packages, setup - -# get readme -with io.open("README.md", "r", encoding="utf-8") as readme_file: - readme = readme_file.read() - -hmf_reqs = ["hmf", "camb"] -math_reqs = ["mpmath", "mcfit"] -progressbar_reqs = ["progressbar2"] -doc_reqs = ["sphinx", "numpydoc", "nbsphinx"] -tests_reqs = ["pytest", "coverage", "pytest-cov"] + math_reqs + hmf_reqs -all_optional_reqs = ( - hmf_reqs - + math_reqs - + progressbar_reqs - + doc_reqs - + tests_reqs -) - -setup_args = { - "name": "ares", - "description": "Accelerated Reionization Era Simulations", - "long_description": readme, - "long_description_content_type": "text/markdown", - "author": "Jordan Mirocha", - "author_email": "mirochaj@gmail.com", - "url": "https://github.com/mirochaj/ares", - "package_dir": {"ares": "ares"}, - "packages": find_namespace_packages(), - "use_scm_version": True, - "install_requires": [ - "h5py", - "numpy", - "matplotlib", - "scipy>=1.6", - "setuptools_scm", - ], - "extras_require": { - "hmf": hmf_reqs, - "math": math_reqs, - "progressbar": progressbar_reqs, - "doc": doc_reqs, - "tests": tests_reqs, - "all": all_optional_reqs, - }, - "entry_points": {"console_scripts": ["ares=ares.util.cli:main"]}, - "classifiers": [ - "Development Status :: 5 - Production/Stable", - "Intended Audience :: Science/Research", - "License :: OSI Approved :: MIT License", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Programming Langauge :: Python :: 3.10", - "Topic :: Scientific/Engineering :: Astronomy", - ], - "keywords": "astronomy cosmology reionization", -} - -if __name__ == "__main__": - # Try to set up $HOME/.ares - HOME = os.getenv('HOME') - if not os.path.exists('{!s}/.ares'.format(HOME)): - try: - os.mkdir('{!s}/.ares'.format(HOME)) - except: - pass - - # run package setup - setup(**setup_args) diff --git a/tests/test_physics_halo_mf.py b/tests/test_physics_halo_mf.py index 3938b3434..12d0c66f5 100644 --- a/tests/test_physics_halo_mf.py +++ b/tests/test_physics_halo_mf.py @@ -14,7 +14,7 @@ import numpy as np from scipy.interpolate import RectBivariateSpline -def test(): +def test(tmp_path): pop = ares.populations.HaloPopulation() m = pop.halos.tab_M @@ -76,11 +76,12 @@ def test(): assert abs(fcoll8 - fcoll8_3) < 1e-2, \ "Percent-level differences in tabulated and generated fcoll: {:.12f} {:.12f}".format(fcoll8, fcoll8_3) - pop3.halos.save_hmf(clobber=True, save_MAR=True) - pop3.halos.save_hmf(clobber=True, save_MAR=True, fmt='pkl') + pop3.halos.save_hmf(clobber=True, save_MAR=True, destination=tmp_path) + pop3.halos.save_hmf(clobber=True, save_MAR=True, destination=tmp_path, fmt="pkl") + rerr = np.abs(dndm - dndm3) / dndm3 assert np.allclose(dndm, dndm3, rtol=2e-2), \ - "Percent-level differences in tabulated and generated HMF!" + f"Percent-level differences in tabulated and generated HMF! {rerr}" # Check hmf_func _hmf = RectBivariateSpline(pop3.halos.tab_z, np.log10(pop3.halos.tab_M), @@ -95,4 +96,13 @@ def test(): if __name__ == '__main__': - test() + import os + + if os.environ.get('RUNNER_TEMP') is not None: + tmp_dir = os.environ.get('RUNNER_TEMP') + else: + if not os.path.exists('_tmp_ares_data'): + os.mkdir('_tmp_ares_data') + tmp_dir = '_tmp_ares_data' + + test(tmp_dir) diff --git a/tests/test_physics_nebula.py b/tests/test_physics_nebula.py index 9c4bef0a0..afc85bab0 100644 --- a/tests/test_physics_nebula.py +++ b/tests/test_physics_nebula.py @@ -37,29 +37,9 @@ def test(): pars_ares2['pop_nebular_lookup'] = 'ferland1980' pop_ares2 = ares.populations.GalaxyPopulation(**pars_ares2) - # Setup source with BPASS-generated (CLOUDY) nebular emission - pars_sps = ares.util.ParameterBundle('mirocha2017:base').pars_by_pop(0, 1) - pars_sps.update(ares.util.ParameterBundle('testing:galaxies')) - pars_sps['pop_nebular'] = 1 - pars_sps['pop_fesc'] = 0. - pars_sps['pop_nebular_Tgas'] = 2e4 - pop_sps = ares.populations.GalaxyPopulation(**pars_sps) - for k, t in enumerate([1, 5, 10, 20, 50]): i = np.argmin(np.abs(pop_ares.src.tab_t - t)) - # For some reason, the BPASS+CLOUDY tables only go up to 29999A, - # so the degraded tables will be one element shorter than their - # pop_nebular=False counterparts. So, interpolate for errors. - # (this is really just making shapes the same, since common - # wavelengths will be identical) - y_ares = np.interp(pop_sps.src.tab_waves_c, - pop_ares.src.tab_waves_c, pop_ares.src.tab_sed[:,i]) - y_ares2 = np.interp(pop_sps.src.tab_waves_c, - pop_ares2.src.tab_waves_c, pop_ares2.src.tab_sed[:,i]) - err = np.abs(y_ares - pop_sps.src.tab_sed[:,i]) / pop_sps.src.tab_sed[:,i] - err2 = np.abs(y_ares2 - pop_sps.src.tab_sed[:,i]) / pop_sps.src.tab_sed[:,i] - Lion_H = pop_ares.src._nebula.get_ion_lum(pop_ares.src.tab_sed[:,i], 0) Lion_He = pop_ares.src._nebula.get_ion_lum(pop_ares.src.tab_sed[:,i], 1) Lion_He2 = pop_ares.src._nebula.get_ion_lum(pop_ares.src.tab_sed[:,i], 2) @@ -104,7 +84,7 @@ def test(): err = abs(pop_ares.src.tab_sed[i1000,:] - pop_ares2.src.tab_sed[i1000,:]) \ / pop_ares.src.tab_sed[i1000,:] assert np.all(err <= 1e-2), \ - "Ferland (1980) results should be closer to Dopita \& Sutherland!" + "Ferland (1980) results should be closer to Dopita & Sutherland!" if __name__ == '__main__': diff --git a/tests/test_populations_ensemble.py b/tests/test_populations_ensemble.py index a687a3ee8..f65fe795a 100644 --- a/tests/test_populations_ensemble.py +++ b/tests/test_populations_ensemble.py @@ -14,7 +14,7 @@ import numpy as np from ares.physics.Constants import rhodot_cgs, E_LL, cm_per_mpc, ev_per_hz -def test(): +def test(tmp_dir): pars = ares.util.ParameterBundle('mirocha2020:univ') pars.update(ares.util.ParameterBundle('testing:galaxies')) # Can't actually do this test yet because we don't have access to @@ -23,7 +23,7 @@ def test(): pop = ares.populations.GalaxyPopulation(**pars) # Test I/O. Should add more here eventually. - pop.save('test_ensemble', clobber=True) + pop.save(f'{tmp_dir}/test_ensemble', clobber=True) z = pop.tab_z t = pop.tab_t @@ -202,4 +202,13 @@ def test(): assert 1e47 <= np.mean(n_ion) <= 1e51 if __name__ == '__main__': - test() + import os + + if os.environ.get('RUNNER_TEMP') is not None: + tmp_dir = os.environ.get('RUNNER_TEMP') + else: + if not os.path.exists('_tmp_ares_data'): + os.mkdir('_tmp_ares_data') + tmp_dir = '_tmp_ares_data' + + test(tmp_dir) diff --git a/tests/test_simulations_gs_4par.py b/tests/test_simulations_gs_4par.py index 5e34e4fc8..5f45d24ff 100644 --- a/tests/test_simulations_gs_4par.py +++ b/tests/test_simulations_gs_4par.py @@ -13,7 +13,7 @@ import ares import numpy as np -def test(): +def test(tmp_dir): pars = ares.util.ParameterBundle('global_signal:basic') sim = ares.simulations.Simulation(**pars) @@ -62,11 +62,21 @@ def test(): curv2 = sim_gs.dTb2dnu2 # Save, read back in - sim_gs.save('test', suffix='pkl', clobber=True) - sim_gs.save('test', suffix='hdf5', clobber=True) + output = tmp_dir / "test" + sim_gs.save(output, suffix='pkl', clobber=True) + sim_gs.save(output, suffix='hdf5', clobber=True) - sim_gs2 = ares.analysis.Global21cm('test') + sim_gs2 = ares.analysis.Global21cm(output) assert np.all(sim_gs.history['cgm_h_2'] == sim_gs2.history['cgm_h_2']) if __name__ == '__main__': - test() + import os + + if os.environ.get('RUNNER_TEMP') is not None: + tmp_dir = os.environ.get('RUNNER_TEMP') + else: + if not os.path.exists('_tmp_ares_data'): + os.mkdir('_tmp_ares_data') + tmp_dir = '_tmp_ares_data' + + test(tmp_dir) diff --git a/tests/test_simulations_rt1d_ptsrc.py b/tests/test_simulations_rt1d_ptsrc.py index cd28f6929..b7e72040c 100644 --- a/tests/test_simulations_rt1d_ptsrc.py +++ b/tests/test_simulations_rt1d_ptsrc.py @@ -13,7 +13,7 @@ import ares import numpy as np -def test(): +def test(tmp_dir): updates = {'stop_time': 100, 'grid_cells': 32} @@ -36,7 +36,7 @@ def test(): assert np.mean(sim.history['Tk'][-1]) > sim.history['Tk'][0,0] # This run will have generated a lookup table for Gamma. Write to disk. - sim.save_tables(prefix='test_rt1d') + sim.save_tables(prefix=f'{tmp_dir}/test_rt1d') # Eventually, test read capability. Currently broken. @@ -49,4 +49,13 @@ def test(): assert np.mean(sim.history['Tk'][-1]) > sim.history['Tk'][0,0] if __name__ == "__main__": - test() + import os + + if os.environ.get('RUNNER_TEMP') is not None: + tmp_dir = os.environ.get('RUNNER_TEMP') + else: + if not os.path.exists('_tmp_ares_data'): + os.mkdir('_tmp_ares_data') + tmp_dir = '_tmp_ares_data' + + test(tmp_dir) diff --git a/tests/test_solvers_tau.py b/tests/test_solvers_tau.py index 1b6bef3f5..da66210ff 100644 --- a/tests/test_solvers_tau.py +++ b/tests/test_solvers_tau.py @@ -16,7 +16,7 @@ import numpy as np from ares.physics.Constants import c, ev_per_hz, erg_per_ev, cm_per_mpc -def test(tol=1e-1): +def test(tmp_path, tol=1e-1): alpha = -2. beta = -6. @@ -63,14 +63,15 @@ def test(tol=1e-1): # Tabulate tau tau = igm.TabulateOpticalDepth() - igm.save(prefix='tau_test', suffix='pkl', clobber=True) + prefix = str(tmp_path / "tau_test") + igm.save(prefix=prefix, suffix='pkl', clobber=True) # Run radiation background calculation - pars['tau_table'] = 'tau_test.pkl' + pars['tau_table'] = prefix + ".pkl" sim_1 = ares.simulations.MetaGalacticBackground(**pars) sim_1.run() - os.remove('tau_test.pkl') + os.remove(pars["tau_table"]) # Compare to transparent IGM solution pars['tau_approx'] = True @@ -88,16 +89,17 @@ def test(tol=1e-1): # Tabulate tau tau = igm.TabulateOpticalDepth() - igm.save(prefix='tau_test', suffix='pkl', clobber=True) + prefix = tmp_path / "tau_test" + igm.save(prefix=prefix, suffix='pkl', clobber=True) - pars['tau_table'] = 'tau_test.pkl' + pars['tau_table'] = prefix + ".pkl" pars['tau_approx'] = False sim_3 = ares.simulations.MetaGalacticBackground(**pars) sim_3.run() z3, E3, f3 = sim_3.get_history(0, flatten=True) - os.remove('tau_test.pkl') + os.remove(pars["tau_table"]) # Check at *lowest* redshift assert np.allclose(f3[0], f2[0]), "Problem with tau I/O." diff --git a/tests/test_sources_bh.py b/tests/test_sources_bh.py old mode 100755 new mode 100644 diff --git a/tests/test_sources_galaxy.py b/tests/test_sources_galaxy.py index 9172aa6c8..430e9252f 100644 --- a/tests/test_sources_galaxy.py +++ b/tests/test_sources_galaxy.py @@ -12,7 +12,7 @@ import ares import numpy as np - +from scipy.integrate import trapezoid def test(): testing_pars = ares.util.ParameterBundle('testing:galaxies') @@ -41,7 +41,7 @@ def test(): sfh = galaxy.get_sfr(tarr, tobs, **kw) # Make sure the integral of the SFH = the mass we asked for - m = np.trapz(sfh, x=tarr * 1e6) + m = trapezoid(sfh, x=tarr * 1e6) assert abs(m - mass) / mass < 0.05, \ "Error in SFH! Recovered mass not accurate to 5%."