Quickstart ========== Installation ------------ Make sure you have ``git-lfs`` installed on your system. Otherwise, ``21cmEMU`` will not be installed properly. For users ^^^^^^^^^ To use ``21cmEMU``, install it with pip: .. code-block:: console $ pip install py21cmemu For developers ^^^^^^^^^^^^^^ Clone the repository and install the development dependencies using `uv `_: .. code-block:: console $ git clone https://github.com/21cmfast/21cmEMU $ cd 21cmEMU $ uv sync --group dev Or with pip: .. code-block:: console $ git clone https://github.com/21cmfast/21cmEMU $ cd 21cmEMU $ pip install -e . .. note:: If you need GPU (CUDA) support, install the appropriate version of PyTorch before installing ``21cmEMU`` by following the `official PyTorch installation guide `_. Conda/mamba can be convenient for installing CUDA libraries, but only the minimal CUDA toolkit is needed — all Python dependencies can then be managed with ``uv`` or ``pip``. To test the installation, run: .. code-block:: python from py21cmemu import Emulator emu_instance = Emulator() Emulating 21cmFAST Summaries ---------------------------- ``py21cmemu`` currently supports three emulators: - ``default`` (v1, PyTorch runtime; converted from the original TensorFlow model) - ``radio_background`` (v2, PyTorch) - ``mh`` (v3, PyTorch minihalo emulator) The emulator ``predict`` method accepts two kinds of input parameters: - Fully normalized parameters i.e. nine numbers :math:`\\in [0,1]`. These can either be in a ``numpy`` array in the following order: ``['F_STAR10', 'ALPHA_STAR', 'F_ESC10', 'ALPHA_ESC', 'M_TURN', 't_STAR', 'L_X', 'NU_X_THRESH', 'X_RAY_SPEC_INDEX']`` or in a dictionary with these labels as keys. - Parameters with the following units (same as ``21cmFAST``): If you have ``21cmFAST`` installed, you can supply the parameters directly with the ``defining_dict`` attribute of ``p21.AstroParams`` objects. You can batch evaluate by putting a set of parameters into a ``list`` or an ``np.ndarray``. Let's look at a basic example. After importing the emulator in the previous code snippet: .. code-block:: python import numpy as np theta = np.random.rand(9*5).reshape((5,9)) theta, output, output_errors = emu_instance.predict(theta) The output here will contain all the summaries i.e. power spectrum, global 21-cm brightness temperature, IGM spin temperature, neutral fraction, as well as emulated $\tau_e$ and UV LFs. Using the v3 (Minihalo) Emulator -------------------------------- The v3 minihalo emulator uses an LSTM architecture for global summaries and supports 2D power spectrum emulation via a score-based diffusion model. It uses 11 astrophysical parameters instead of 9. .. code-block:: python from py21cmemu import Emulator # Create v3 emulator (without 2D PS for faster predictions) emu = Emulator(emulator="mcg", emulate_2d_ps=False) # Use 11 parameters for the minihalo model import numpy as np theta = np.random.rand(11*3).reshape((3, 11)) theta, output, errors = emu.predict(theta) # Access outputs with units (astropy Quantities) print(output.Tb.shape) # Brightness temperature [mK] print(output.xHI.shape) # Neutral fraction [dimensionless] print(output.Ts.shape) # Spin temperature [K] print(output.UVLFs.shape) # UV luminosity functions [dex(Mpc^-3 mag^-1)] print(output.tau) # Optical depth [dimensionless] print(output.PS.shape) # 1D Power spectrum [dex(mK^2)] The v3 parameter keys are: .. code-block:: python ['F_STAR10', 'ALPHA_STAR', 't_STAR', 'F_ESC10', 'ALPHA_ESC', 'F_STAR7_MINI', 'F_ESC7_MINI', 'L_X', 'L_X_MINI', 'A_LW', 'NU_X_THRESH'] Output Units ------------ All output quantities are returned as astropy ``Quantity`` objects with units attached: **Linear quantities** (physical units): - ``Tb``: Brightness temperature [mK] - ``xHI``: Neutral hydrogen fraction [dimensionless, 0-1] - ``Ts``: Spin temperature [K] - ``tau``: Optical depth [dimensionless] **Logarithmic quantities** (dex units, i.e., log10 of physical values): - ``PS``: 1D power spectrum [dex(mK²)] = log10(Δ²) - ``PS_2D``: 2D power spectrum [dex(mK²)] = log10(Δ²) - ``UVLFs``: UV luminosity functions [dex(Mpc⁻³ mag⁻¹)] = log10(φ) To convert log quantities to linear, use ``.physical``: .. code-block:: python # Get power spectrum in linear mK^2 ps_linear = output.PS.physical Error Statistics ---------------- Error statistics are accessible via properties like ``output.PS_err``. All errors are **Fractional Errors (FE%)** computed as: .. math:: \\text{FE\\%} = \\frac{|\\text{true} - \\text{predicted}|}{|\\text{true}|} \\times 100 **IMPORTANT**: Power spectrum errors are computed on **log10(PS)**, not linear PS. A 5% FE on log10(PS) corresponds to approximately 12% error on linear PS, because a 5% uncertainty in the exponent multiplies the result by 10^0.05 ≈ 1.12. Available error statistics: - ``PS_err``: Median FE% on 1D PS log10 values, shape (32 z, 32 k) - ``PS_2D_err``: Median FE% on 2D PS log10 values, shape (32 kperp, 64 kpar) - ``PS_2D_var``: Variance of FE% across test set - ``PS_2D_cov``: Full covariance matrix of errors between pixels To compute absolute error in log10 units at each pixel: .. code-block:: python abs_err_dex = output.PS_err / 100.0 * output.PS.value See ``MHEmulatorProperties`` for comprehensive documentation of all error statistics, aggregation methods (median vs mean), and interpretation guidance. Continue on to the tutorials to see how to make plots of the output (first tutorial) and how to use ``21cmFAST`` in conjunction with ``21cmEMU`` for analytic calculations of :math:`\\tau_e` and UV luminosity functions.