{ "cells": [ { "cell_type": "markdown", "id": "1b66947f", "metadata": {}, "source": [ "# 2. Choose a backend\n", "\n", "Both backends predict Jeans velocity moments from a tracer, halo and\n", "anisotropy. Their parameter interfaces and numerical implementations differ.\n", "The Quickstart uses **JAX/NumPyro** so the likelihood can supply gradients to\n", "NUTS. Choose NumPy/SciPy when you need its profile implementations or a\n", "stateful interface.\n", "\n", "\n", "This notebook is self-contained. Install JeansPy with the `numpyro_cpu` and\n", "`plotting` extras as described in the installation guide, then select that\n", "environment as your Jupyter kernel and run cells from top to bottom.\n", "Saved outputs are an example run; timings and short-chain results can vary.\n", "\n", "## Decide which interface you need\n", "\n", "| Choice | NumPy/SciPy | JAX |\n", "| --- | --- | --- |\n", "| Spherical import | `jeanspy.model` | `jeanspy.model_jax` |\n", "| Physical parameters | Stored in components; change with `update(...)` | Passed explicitly in `params` or named method arguments |\n", "| Computation | CPU NumPy/SciPy | JAX device arrays, optional JIT compilation |\n", "| Physical-parameter gradients | No JAX automatic differentiation | Available on supported differentiable paths |\n", "| Sampling used here | emcee ensemble sampler | NumPyro NUTS |\n", "| Repeated calls | No JIT compilation cost | Can reuse compiled calculations with compatible shapes and static options |\n", "\n", "Backend choice does not change the intended physical units. It does change\n", "available models, argument names, returned shapes and numerical defaults.\n", "For example, the NumPy/SciPy spherical solver has `sigmalos` and `sigmalos2`;\n", "the JAX model exposes `sigmalos2`, whose square root gives the dispersion.\n", "The profile catalogues are not identical. See the two sections of the\n", "[spherical API](../api/spherical.rst) before switching a component.\n", "\n", "## Build the same model twice\n", "\n", "This executable example uses the same physical values and radius grid for\n", "both backends. The NumPy/SciPy components receive constructor parameters;\n", "the JAX components receive a dictionary at evaluation time." ] }, { "cell_type": "code", "execution_count": 1, "id": "61d63a9c", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'jax_platform_requested': 'cpu', 'jax_platform_effective_env': 'cpu', 'jax_backend_active': 'cpu', 'jax_enable_x64': True, 'kernel_backend_default': 'jax', 'constant_kernel_n_quad_default': 32, 'sigmalos2_solver_default': 'auto', 'sigmalos2_jit_default': True, 'sigmalos2_kernel_outer_transform_default': 'sqrtlog', 'baes_kernel_n_quad_default': 32, 'baes_eta_recommended_max': 10.0, 'sigmalos2_n_u_default': 128, 'sigmalos2_n_r_default': 768, 'sigmalos2_u_max_default': 10000.0}\n", "[CpuDevice(id=0)]\n" ] } ], "source": [ "import os\n", "os.environ.setdefault(\"JEANSPY_JAX_PLATFORM\", \"cpu\")\n", "os.environ.setdefault(\"JEANSPY_JAX_ENABLE_X64\", \"true\")\n", "\n", "from jeanspy import model as numpy_backend\n", "from jeanspy import model_jax as jax_backend\n", "import jax\n", "import jax.numpy as jnp\n", "import numpy as np\n", "from time import perf_counter\n", "\n", "params = dict(re_pc=200., rs_pc=500., rhos_Msunpc3=.1,\n", " r_t_pc=5000., beta_ani=0.)\n", "R_pc = np.geomspace(20., 1000., 32)\n", "numpy_model = numpy_backend.DSphModel(vmem_kms=0., submodels={\n", " \"StellarModel\": numpy_backend.PlummerModel(re_pc=params[\"re_pc\"]),\n", " \"DMModel\": numpy_backend.NFWModel(**{k: params[k] for k in\n", " (\"rs_pc\", \"rhos_Msunpc3\", \"r_t_pc\")}),\n", " \"AnisotropyModel\": numpy_backend.ConstantAnisotropyModel(beta_ani=0.),\n", "})\n", "jax_model = jax_backend.DSphModel(submodels={\n", " \"StellarModel\": jax_backend.PlummerModel(),\n", " \"DMModel\": jax_backend.NFWModel(),\n", " \"AnisotropyModel\": jax_backend.ConstantAnisotropyModel(),\n", "})\n", "print(jax_backend.get_runtime_config())\n", "print(jax.devices())\n", "#" ] }, { "cell_type": "markdown", "id": "b0af7801", "metadata": {}, "source": [ "Set the platform and precision before importing JAX, including in notebooks.\n", "If JAX is already initialized, restart the kernel before applying the setup.\n", "`get_runtime_config()` and `jax.devices()` report the effective settings;\n", "installing GPU dependencies alone does not establish which device is active.\n", "\n", "## Measure first-call and repeated-call time separately" ] }, { "cell_type": "code", "execution_count": 2, "id": "890671fe", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'numpy_call_s': 0.0023460329975932837, 'jax_first_call_s': 0.41772538679651916, 'jax_repeated_median_s': 0.001643685856834054, 'max_relative_variance_difference': 3.200623051036189e-07}\n" ] } ], "source": [ "start = perf_counter()\n", "numpy_variance = numpy_model.sigmalos2(R_pc, n=512, n_kernel=128)\n", "numpy_seconds = perf_counter() - start\n", "R_jax = jnp.asarray(R_pc)\n", "jax_params = {name: jnp.asarray(value) for name, value in params.items()}\n", "jax.block_until_ready((R_jax, jax_params)) # Complete transfers before timing.\n", "\n", "def predict(p):\n", " return jax_model.sigmalos2(R_jax, params=p, solver=\"kernel\",\n", " kernel_backend=\"jax\", n_u=512, n_kernel=128)\n", "\n", "start = perf_counter()\n", "jax_variance = jax.block_until_ready(predict(jax_params))\n", "first_seconds = perf_counter() - start\n", "times = []\n", "for _ in range(5):\n", " start = perf_counter()\n", " jax.block_until_ready(predict(jax_params))\n", " times.append(perf_counter() - start)\n", "relative_difference = np.max(np.abs(np.asarray(jax_variance) / numpy_variance - 1.))\n", "print({\"numpy_call_s\": numpy_seconds, \"jax_first_call_s\": first_seconds,\n", " \"jax_repeated_median_s\": float(np.median(times)),\n", " \"max_relative_variance_difference\": float(relative_difference)})\n", "#" ] }, { "cell_type": "code", "execution_count": 3, "id": "ef951769", "metadata": { "mystnb": { "image": { "alt": "NumPy and JAX dispersion predictions on the same radius grid, and their relative variance difference." } } }, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import matplotlib.pyplot as plt\n", "fig, axes = plt.subplots(2, 1, figsize=(6, 5), sharex=True, layout=\"constrained\")\n", "axes[0].semilogx(R_pc, np.sqrt(numpy_variance), label=\"NumPy/SciPy\")\n", "axes[0].semilogx(R_pc, np.sqrt(np.asarray(jax_variance)), ls=\"--\", label=\"JAX\")\n", "axes[0].set_ylabel(r\"$\\sigma_{los}$ [km/s]\")\n", "axes[0].legend()\n", "axes[1].semilogx(R_pc, np.asarray(jax_variance)/numpy_variance - 1.)\n", "axes[1].axhline(0., color=\"gray\", lw=.7)\n", "axes[1].set(xlabel=\"Projected radius [pc]\", ylabel=\"Relative variance difference\")\n", "plt.show()" ] }, { "cell_type": "markdown", "id": "e1f5f341", "metadata": {}, "source": [ "JAX dispatch is asynchronous, so wait for completion with\n", "`jax.block_until_ready`. The first call includes tracing, compilation and\n", "execution; the median of later calls measures reuse of that compiled shape.\n", "The code completes input transfers before either JAX timing. New array\n", "shapes, node counts or static backend choices can require another compilation.\n", "\n", "The printed difference compares the two **variances**, not their square roots.\n", "Equal node counts do not imply equal quadrature rules or accuracy. Refine\n", "each solver and compare predictions at an accuracy appropriate to the analysis\n", "before comparing speed. A small one-off calculation can favor NumPy; repeated\n", "large calculations may benefit from JIT or a GPU. There is no universal speed\n", "ordering, and this example supplies no frozen performance claim. Include\n", "likelihood, gradient, transfer and compilation costs for the workload you\n", "actually intend to run.\n", "\n", "## Differentiate a physical parameter" ] }, { "cell_type": "code", "execution_count": 4, "id": "c0645469", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "d(sum sigma_los^2) / d(ln rho_s): 2239.4195206705785\n" ] } ], "source": [ "def summed_variance(log_density):\n", " return jnp.sum(predict({**jax_params, \"rhos_Msunpc3\": jnp.exp(log_density)}))\n", "\n", "log_density = jnp.log(jax_params[\"rhos_Msunpc3\"])\n", "derivative = jax.block_until_ready(jax.grad(summed_variance)(log_density))\n", "# With a massless tracer and fixed shape, sigma^2 scales linearly with rho_s.\n", "np.testing.assert_allclose(derivative, jnp.sum(jax_variance), rtol=1e-8)\n", "assert np.all(np.isfinite(numpy_variance)) and np.all(np.asarray(jax_variance) > 0)\n", "print(\"d(sum sigma_los^2) / d(ln rho_s):\", float(derivative))\n", "#" ] }, { "cell_type": "markdown", "id": "6c4f345a", "metadata": {}, "source": [ "This checks a derivative with a known scaling: at fixed halo shape and\n", "massless tracer, $\\sigma_{los}^2$ is proportional to the halo density scale.\n", "For other parameters, check gradients against finite differences and refined\n", "quadrature on the intended domain. Use JAX operations in transforms and\n", "custom components; converting a traced value with `float` or `np.asarray`\n", "breaks that calculation.\n", "\n", "The `solver=\"kernel\"` option above selects a numerical route **within JAX**;\n", "it is separate from selecting NumPy versus JAX by import. For the constant\n", "anisotropy kernel, `kernel_backend=\"jax\"` keeps the path in JAX.\n", "The SciPy callback alternative is not an all-JAX differentiable kernel.\n", "Cutoffs, validity masks and discrete choices also need care at boundaries.\n", "Current J/D-factor postprocessing uses NumPy and is not a differentiable\n", "continuation of NUTS.\n", "\n", "Rerun this notebook to inspect timings on your machine. The displayed timings\n", "are a single illustrative run, not a portable performance benchmark.\n", "Next: [define and extend models](models.ipynb)." ] } ], "metadata": { "jeanspy": { "execution": { "code_sha256": "edf741f3aa1e1a0c798abf5e1929b1b31aab1a07f6efca94407d557825da859e", "jax_enable_x64": true, "lock_sha256": "a30f366620e23a49d6d7466055223a761824454169d8fc0364c24ac25b626dc7", "packages": { "arviz": "1.0.0", "corner": "2.2.3", "jax": "0.9.1", "jeanspy": "0.1.0", "matplotlib": "3.10.8", "numpy": "2.4.3", "numpyro": "0.20.0", "scipy": "1.17.1" }, "platform": "cpu", "source_sha256": { "src/jeanspy/__init__.py": "61671d182af04c0056cfb8d273db499d8774694711506698dbe7dc4a63d3b403", "src/jeanspy/_axisymmetric_components.py": "4b203c616c87e55182d105b37f9fa49e44fe1df6bc430ccccb09edc5cca42530", "src/jeanspy/_axisymmetric_params.py": "85da8de45bf5ba8cd9a40a137f7ccf971f7ce9534f312ef49fcd33539a230802", "src/jeanspy/_jax_env.py": "2ef46eaf5cbd8e72a0c17351490207c29586979082cabc87128c9bd16fc689a4", "src/jeanspy/_numpy/__init__.py": "de2d19d61e00702f13996582369f6acbe92b74628e6f569f91c3215a53580117", "src/jeanspy/_numpy/core.py": "d073c6409d5f8cf527947c1ddf3916cb39cef3f6d4e43173cad59d148e463296", "src/jeanspy/_numpy/inference.py": "ab58728400b6e56189ffba9ee805d9edbf59ca13dfebe05498801592314552db", "src/jeanspy/_numpy/jfactor.py": "823f58a66a615ba59e057022ce51e2adfab577c25a4ced2f2033304c2cbd6cfe", "src/jeanspy/_numpy/profiles.py": "e77fda6fb068392a63f0479e4c33bf80a22de3d2ab2cd101ea0c1f33e579491d", "src/jeanspy/_numpy/solver.py": "b419796e2a912a46f65404cb5026ccb73799e1dbb8f80052f404148dd1f5ef3c", "src/jeanspy/_sampling_identity.py": "b0e70b77e38f25e2148ab1f108a714512a8b6054405c846c3a41730b07081cec", "src/jeanspy/_sersic_deprojection.py": "004c5566448698ecfe536096c3fc8d5c348a8d4e1610042763c77568c0f3d821", "src/jeanspy/_zhao.py": "df83c7427dc583123c7464a03d2d45272e90f5a6724c9729eee64fad92e0c41a", "src/jeanspy/axisymmetric.py": "683d67b91f8eb67e8d898eb23e6c8ca0e5c78020a65a7d05e183c19b076bd506", "src/jeanspy/axisymmetric_factors.py": "754b256f7d3d43cc72571cde2b22bc9419917cf13b17342cd5f52406c4111336", "src/jeanspy/axisymmetric_inference.py": "57078226b3643f8babda4d942b96ae546622da28802119d3d99ff6a0c5b45695", "src/jeanspy/axisymmetric_jax.py": "de5f78937104ce7008242d55c321c8a3c6d9491f6aa25d4be3bdab8de076ed54", "src/jeanspy/baes_eta2.py": "c274a16ca8c4b4d8d76ec30a2e705b5a5f6ce7659b31e31b5c685f92ab7a7ece", "src/jeanspy/dequad.py": "6260e7ee2d8da12265573e86ff81ba0a3e8912df5fec8588a84bfda9d3b1133d", "src/jeanspy/hyp2f1_jax.py": "03d8df3b48fcd9d418e289ea2ffaf174ffbdf14dffe483a150403c092bbaeea8", "src/jeanspy/model.py": "72af25df8f34816f27d373fdecf41408c79eb505cb4cb52c830822d5d8f12f2b", "src/jeanspy/model_jax.py": "355ba42ad16b2cadd00906679dd06ee12fd85fe4f1fc48630c779e68e4fabd64", "src/jeanspy/parameters.py": "7760f4c85063105eb1328910867f3c57516f885dc577533bf9b91ac08a648cb2", "src/jeanspy/sampler.py": "42ca0bbcef84b7c1620fd977d71810284a5d6abd70ff6047ae3175822d63f10e", "src/jeanspy/sampler_numpyro.py": "ccd367d576bc55173d85939ad4bf7eeb8a44130d693f40ee56f4eade278c2195", "src/jeanspy/sersic.py": "487f473351f9a309ad7d8dad1b1405e496196413e7606d0b0a18c5f71bfcf4a3" }, "utc": "2026-09-18T00:32:32.851568+00:00" }, "mcmc": false }, "kernelspec": { "display_name": "Python 3 (JeansPy)", "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.12.13" } }, "nbformat": 4, "nbformat_minor": 5 }