{ "cells": [ { "cell_type": "markdown", "id": "43b2f4ef-c9c3-46ce-b4b2-a822c3600e11", "metadata": {}, "source": [ "# Notebook 1: Loading snapshots with units and derived variables\n", "\n", "This script shows how to\n", "\n", "- load data: present in arepo snapshots and derived by Paicos\n", "- how to convert the Arepo data from comoving code units to physical values in various unit systems\n" ] }, { "cell_type": "markdown", "id": "b5ffecf2-3b1f-4616-b394-2b181c0dd874", "metadata": {}, "source": [ "## Compilation\n", "The first step is to compile the code, this only needs to be done the first time you use Paicos and if you have not already followed the installation instructions (replace the path to your own cloned version, you will also need to add this path to your PYTHONPATH)." ] }, { "cell_type": "code", "execution_count": 1, "id": "8dd135d5-5106-419c-9a56-7211e0790c5a", "metadata": {}, "outputs": [], "source": [ "#%%bash\n", "#cd ~/projects/paicos\n", "#make clean\n", "#make" ] }, { "cell_type": "markdown", "id": "76db5702-5cb4-433e-af1a-8eef178e9116", "metadata": {}, "source": [ "## Loading arepo snapshots\n", "\n", "We load a zoom-in simulation of a galaxy cluster simulation below (the data is not included in the repo, so you will need to download this. See documentation)" ] }, { "cell_type": "code", "execution_count": 2, "id": "96daabc9-0510-4667-ac79-f9c3def959a7", "metadata": {}, "outputs": [], "source": [ "import paicos as pa\n", "import numpy as np\n", "\n", "# A snapshot object\n", "snap = pa.Snapshot(pa.data_dir, 247)\n", "\n", "# The center of the most massive Friends-of-friends group in the simulation\n", "center = snap.Cat.Group['GroupPos'][0]" ] }, { "cell_type": "markdown", "id": "0f4c6c0f-1115-404f-bd5b-b834b3dbee34", "metadata": {}, "source": [ "## Useful metadata\n", "We can look at some of snap attributes:" ] }, { "cell_type": "code", "execution_count": 3, "id": "3ed9bfa3-58e8-4dce-88ef-ae6741ce9861", "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$13.802235 \\;\\mathrm{Gyr}$" ], "text/plain": [ "" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Age of the Universe for the snapshot\n", "snap.age" ] }, { "cell_type": "code", "execution_count": 4, "id": "38046640-529d-4ba5-8319-1b662c9c8936", "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$3.5527137 \\times 10^{-15} \\;\\mathrm{Gyr}$" ], "text/plain": [ "" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# The lookback time\n", "snap.lookback_time" ] }, { "cell_type": "code", "execution_count": 5, "id": "9f46dcfc-c85f-45d3-8e47-ef08c7362f87", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "LambdaCDM(H0=67.32117 km / (Mpc s), Om0=0.31582309, Ode0=0.68417691, Tcmb0=0.0 K, Neff=3.04, m_nu=None, Ob0=0.04938682)" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# An astropy cosmology object (used internally to calculate the age and lookback, \n", "# cosmological parameters automatically loaded from the the snapshot)\n", "snap.cosmo" ] }, { "cell_type": "code", "execution_count": 6, "id": "e4a3a772-6853-4c89-8f5b-1aa2943eebcf", "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$[1485.417,~1485.417,~1485.417] \\;\\mathrm{Mpc}$" ], "text/plain": [ "" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# The size of the computational box\n", "snap.box_size.to('Mpc').to_physical" ] }, { "cell_type": "code", "execution_count": 7, "id": "964e9fd6-4f9e-404d-8cc7-8e554d6d5757", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "2.220446049250313e-16" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# The redshift\n", "snap.z" ] }, { "cell_type": "code", "execution_count": 8, "id": "9946206e-e204-48a8-82d4-d22c35a5c122", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1.6666666666666667" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Adiabatic index used in the simulation\n", "snap.gamma" ] }, { "cell_type": "code", "execution_count": 9, "id": "837caf67-6b26-4f53-bb07-a43ee3996088", "metadata": {}, "outputs": [], "source": [ "# Contents of the three hdf5 groups containing information about the snapshot (uncomment to see output)\n", "#snap.Header\n", "#snap.Parameters\n", "#snap.Config" ] }, { "cell_type": "markdown", "id": "549c98a1-2eca-440c-9185-ccfcff2e60b3", "metadata": {}, "source": [ "## Loading of data blocks\n", "Loading of data can be done using function calls or by trying to access them explicitly.\n", "Here we load the Arepo data as a PaicosQuantity (basically a subclass of an astropy quantity), which gives the numeric data units and some useful methods. The numeric values are the same as stored in the hdf5 files but we can now see the units used in the simulation. Here small_h and small_a are the reduced Hubble parameter and the scale factor, respectively. " ] }, { "cell_type": "code", "execution_count": 10, "id": "f926a39f-0967-49ca-837c-18bf0e57e3ab", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Attempting to get derived variable: 0_Volume...\t[DONE]\n", "\n" ] }, { "data": { "text/latex": [ "$[1135.483,~1257.4441,~1500.9361,~\\dots,~88719546,~6.2120684 \\times 10^{8},~71113576] \\;\\mathrm{\\frac{arepo\\_mass}{arepo\\_density}}\\times\\mathrm{\\frac{a^{3}}{h^{3}}}$" ], "text/plain": [ "" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Load some variables from the PartType 0 (gas variables) \n", "\n", "# You can explicitly load using function call:\n", "snap.load_data(0, 'Coordinates')\n", "snap['0_Coordinates']\n", "\n", "# But is much easier to just do it like this:\n", "snap['0_Density']\n", "snap['0_MagneticField']\n", "\n", "# snap\n", "snap['0_Volume']" ] }, { "cell_type": "code", "execution_count": 11, "id": "f52ce07c-2299-47cc-8590-9652b1e2a3a2", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Keys for PartType0 in the hdf5 file:\n", "0_AllowRefinement\n", "0_CenterOfMass\n", "0_Coordinates\n", "0_Density\n", "0_ElectronAbundance\n", "0_EnergyDissipation\n", "0_GFM_AGNRadiation\n", "0_GFM_CoolingRate\n", "0_GFM_Metallicity\n", "0_GFM_Metals\n", "0_GFM_WindDMVelDisp\n", "0_GFM_WindHostHaloMass\n", "0_HighResGasMass\n", "0_InternalEnergy\n", "0_Machnumber\n", "0_MagneticField\n", "0_MagneticFieldDivergence\n", "0_MagneticFieldDivergenceAlternative\n", "0_Masses\n", "0_NeutralHydrogenAbundance\n", "0_ParticleIDs\n", "0_Potential\n", "0_StarFormationRate\n", "0_SubfindDMDensity\n", "0_SubfindDensity\n", "0_SubfindHsml\n", "0_SubfindVelDisp\n", "0_Velocities\n", "0_VelocityGradient\n", "\n", "Possible derived variables are:\n", "0_Diameters\n", "0_Enstrophy\n", "0_EnstrophyTimesMasses\n", "0_GFM_MetallicityTimesMasses\n", "0_MachnumberTimesEnergyDissipation\n", "0_MagneticFieldSquared\n", "0_MagneticFieldSquaredTimesVolume\n", "0_MagneticFieldStrength\n", "0_MeanMolecularWeight\n", "0_NumberDensity\n", "0_Pressure\n", "0_PressureTimesVolume\n", "0_Temperatures\n", "0_TemperaturesTimesMasses\n", "0_VelocityCurvature\n", "0_VelocityMagnitude\n", "0_Volume\n" ] } ], "source": [ "# The available fields for a PartType can be found as shown below for parttype 0 (the gas)\n", "keys = snap.info(0)\n", "\n", "# alternatively, by starting to type and using tab-completion, i.e., snap['0_ and then hit tab" ] }, { "cell_type": "markdown", "id": "456c560a-7fc5-4ca5-9f35-20058473a01b", "metadata": {}, "source": [ "## Unit conversion \n", "Here we show how to use convert the density field to various useful physical units and\n", "how to get rid of the a and h factors used in cosmological simulations with Arepo." ] }, { "cell_type": "code", "execution_count": 12, "id": "3aba6d3e-69dd-4091-b575-a5633a593b9e", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "rho[0] in CGS:\t 6.586066423538464e-25 g small_h2 / (cm3 small_a3)\n", "rho[0] in SI:\t 6.586066423538463e-22 kg small_h2 / (m3 small_a3)\n", "rho[0] in 'astro' units:\t 9731321.74428584 small_h2 solMass / (kpc3 small_a3)\n", "rho[0] in Msun/au^3:\t 1.1089103378991942e-18 small_h2 solMass / (AU3 small_a3) \n", "\n", "\n", "rho[0] without h:\t 0.00044090644374425626 arepo_density / small_a3\n", "rho[0] without a and h:\t 0.00044090644374425653 arepo_density \n", "\n", "\n", "$\\rho\\;a^{-3}h^{2}\\; \\left[\\mathrm{arepo\\_density}\\right]$\n", "$\\rho\\;a^{-3}h^{2}\\; \\left[\\mathrm{M_{\\odot}}\\;\\mathrm{kpc}^{-3}\\right]$\n" ] } ], "source": [ "# Unit conversion\n", "rho = snap['0_Density']\n", "print('rho[0] in CGS:\\t', rho[0].cgs)\n", "print('rho[0] in SI:\\t', rho[0].si)\n", "print(\"rho[0] in 'astro' units:\\t\", rho[0].astro)\n", "print(\"rho[0] in Msun/au^3:\\t\", rho[0].to('Msun/au3'), '\\n\\n')\n", "\n", "# Get rid of h factors\n", "print('rho[0] without h:\\t', rho[0].no_small_h)\n", "\n", "# Get rid of both a and h factors\n", "print('rho[0] without a and h:\\t', rho[0].to_physical, '\\n\\n')\n", "\n", "# Get a label for use in plots\n", "print(rho.label(r'\\rho'))\n", "print(rho.astro.label(r'\\rho'))" ] }, { "cell_type": "markdown", "id": "5c087972-3d83-408a-9913-f2c360dfb752", "metadata": {}, "source": [ "### Changing the units in a PaicosQuantity\n", "Please note that the methods above return a new object without modifying the original data. Modification can be done by overwriting, e.g., like this:" ] }, { "cell_type": "code", "execution_count": 13, "id": "68e6810d-4344-4243-861d-112fe9ac10ae", "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$[0.00044090644,~0.00041112652,~0.00038160096,~\\dots,~9.603584 \\times 10^{-9},~3.6788828 \\times 10^{-10},~1.1816428 \\times 10^{-8}] \\;\\mathrm{arepo\\_density}$" ], "text/plain": [ "" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "rho = rho.to_physical\n", "rho" ] }, { "cell_type": "markdown", "id": "e1dccf2b-417e-45e6-8ab4-5cb520e5143a", "metadata": {}, "source": [ "### Getting rid of units\n", "\n", "The PaicosQuantity uses the astropy quantity internally, which again uses numpy arrays.\n", "In case you are not familiar with astropy: Here is how you can access the unit and numeric values independently like this: " ] }, { "cell_type": "code", "execution_count": 14, "id": "153ebf1e-f8b9-4ae9-8c4f-a1ba3bf2af7d", "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$\\mathrm{arepo\\_density}$" ], "text/plain": [ "Unit(\"arepo_density\")" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# The unit\n", "rho.unit" ] }, { "cell_type": "code", "execution_count": 15, "id": "fc11b0ad-4f57-4aef-aaf7-963fbb88e007", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([4.40906444e-04, 4.11126523e-04, 3.81600963e-04, ...,\n", " 9.60358397e-09, 3.67888283e-10, 1.18164277e-08])" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# The numeric values (a numpy array)\n", "rho.value" ] }, { "cell_type": "markdown", "id": "642852e7-05c0-4114-9191-7dc44de91f0c", "metadata": {}, "source": [ "## Loading automatically computed derived variables\n", "Here we show how Paicos can automatically compute derived variables.\n", "Paicos gives information about what is happening under the hood.\n", "\n", "This feature can be turned off by setting\n", "\n", "```\n", "pa.settings.use_only_user_functions = True\n", "```\n", "but we note that changes to `pa.settings.use_only_user_functions` only take effect for freshly loaded snapshots." ] }, { "cell_type": "code", "execution_count": 16, "id": "7d937ab7-38a4-450d-9d1f-c3e61b6c17b8", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Attempting to get derived variable: 0_TemperaturesTimesMasses...\n", "\tSo we need the variable: 0_Temperatures...\n", "\tSo we need the variable: 0_MeanMolecularWeight...\t[DONE]\n", "\n", "Attempting to get derived variable: 0_Enstrophy...\t[DONE]\n", "\n" ] }, { "data": { "text/latex": [ "$[2054.8327,~3710.7326,~4088.9848,~\\dots,~0.44583916,~0.00017996505,~0.073376168] \\;\\mathrm{\\frac{arepo\\_velocity^{2}}{arepo\\_length^{2}}}\\times\\mathrm{\\frac{h^{2}}{a}}$" ], "text/plain": [ "" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# The gas cell volumes (per default Arepo only outputs the gas mass and density)\n", "snap['0_Volume']\n", "\n", "# The gas temperature times the cell gas mass\n", "snap['0_TemperaturesTimesMasses']\n", "\n", "# The gas enstrophy\n", "snap['0_Enstrophy']" ] }, { "cell_type": "markdown", "id": "56fe2809-9b55-4227-a626-9ba4aef1147c", "metadata": {}, "source": [ "The console output can be turned off by setting\n", "```\n", "pa.settings.print_info_when_deriving_variables = False\n", "```\n", "This is illustrated below where no information is printed:" ] }, { "cell_type": "code", "execution_count": 17, "id": "5f146ddf-fad5-4037-9969-a0912edf0345", "metadata": {}, "outputs": [], "source": [ "# Turn off info\n", "pa.settings.print_info_when_deriving_variables = False\n", "\n", "# The metallicity multiplied by the mass\n", "snap['0_GFM_MetallicityTimesMasses']\n", "\n", "# Turn info back on\n", "pa.settings.print_info_when_deriving_variables = True" ] } ], "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.10.12" } }, "nbformat": 4, "nbformat_minor": 5 }