{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Example 6: Electron Cooling"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In this example, we will show how to use the electron cooling module, found in [*darkhistory.elec.elec_cooling*](https://darkhistory.readthedocs.io/en/master/_autosummary/darkhistory/electrons/darkhistory.electrons.elec_cooling.html). This module takes an injected electron with some initial energy, and cools it completely through inverse Compton scattering (ICS) as well as ionization, excitation (both on HI, HeI and HeII) as well as Coulomb heating of free electrons. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Initialization"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's load the stuff that we need. The function of interest is [*get_elec_cooling_tf()*](https://darkhistory.readthedocs.io/en/master/_autosummary/darkhistory/electrons/elec_cooling/darkhistory.electrons.elec_cooling.get_elec_cooling_tf.html).\n",
    "\n",
    "We have also imported the default binning for photons and electrons used throughout DarkHistory using [*config.load_data()*](https://darkhistory.readthedocs.io/en/master/_autosummary/config/config.load_data.html).\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%load_ext autoreload\n",
    "import sys\n",
    "sys.path.append(\"..\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%autoreload\n",
    "\n",
    "import matplotlib\n",
    "matplotlib.rc_file('matplotlibrc')\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "import numpy as np\n",
    "\n",
    "from darkhistory.config import load_data\n",
    "import darkhistory.physics as phys\n",
    "from darkhistory.electrons.elec_cooling import get_elec_cooling_tf\n",
    "\n",
    "photeng = load_data('binning')['phot']\n",
    "eleceng = load_data('binning')['elec']"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Electron Cooling Function: [*get_elec_cooling_tf()*](https://darkhistory.readthedocs.io/en/master/_autosummary/darkhistory/electrons/elec_cooling/darkhistory.electrons.elec_cooling.get_elec_cooling_tf.html)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The user should refer to the online documentation for details on how to use [*get_elec_cooling_tf()*](https://darkhistory.readthedocs.io/en/master/_autosummary/darkhistory/electrons/elec_cooling/darkhistory.electrons.elec_cooling.get_elec_cooling_tf.html). In the simplest default case, we just need to give the function the electron and photon abscissae of interest, the redshift, and the ionization levels of hydrogen and helium.\n",
    "\n",
    "If we do not specify any ICS transfer functions to the function, DarkHistory automatically loads the required transfer functions from the downloaded data. If this is the first time the transfer functions are loaded, the successful completion of the import would look like this:\n",
    "\n",
    "```\n",
    "****** Loading transfer functions... ******\n",
    "    for inverse Compton (Thomson)...  Done!\n",
    "    for inverse Compton (relativistic)...  Done!\n",
    "    for inverse Compton (energy loss)...  Done!\n",
    "****** Loading complete! ******\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "rs = 600\n",
    "# This function returns the baseline value of xHII. \n",
    "xHII  = phys.xHII_std(rs)\n",
    "\n",
    "elec_cooling_info = get_elec_cooling_tf(\n",
    "    eleceng, photeng, rs, xHII, check_conservation_eng=True, verbose=True\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The output, stored in *elec_cooling_info*, is a tuple containing the following, as well as what each variable is indexed by: \n",
    "\n",
    "0. The secondary propagating photon transfer function $\\overline{T}_\\text{ICS}$ (*eleceng*, *photeng*). This spectrum has the original upscattered CMB photons **already subtracted**, and generically contains negative values at low energies. This spectrum should be viewed as a **distortion** to the CMB spectrum; \n",
    "1. The low-energy electron transfer function $\\overline{T}_e$ (*eleceng*, *eleceng*); \n",
    "2. The energy deposited into ionization $\\overline{R}_\\text{ion}$ (*eleceng*); \n",
    "3. The energy deposited into excitation $\\overline{R}_\\text{exc}$ (*eleceng*);\n",
    "4. The energy deposited into heating $\\overline{R}_\\text{heat}$ (*eleceng*); \n",
    "5. The total pre-scattering energy of upscattered CMB photons $\\overline{R}_\\text{CMB}$ (*eleceng*), and\n",
    "6. Numerical error away from energy conservation (*eleceng*).\n",
    "\n",
    "These transfer functions are functions of the injected electron energy, and tell us how energy is deposited by a *single* electron with that energy.  For more details, see Section III.D of paper I.\n",
    "\n",
    "Let's make some plots to understand this. First, let's extract the high-energy deposition into ionization, excitation and heating. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## High-Energy Deposition Fractions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "elec_dep_ion  = elec_cooling_info[2]\n",
    "elec_dep_exc  = elec_cooling_info[3]\n",
    "elec_dep_heat = elec_cooling_info[4]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We'll make a plot of the fraction of energy deposited into each of these channels, as a function of the energy injected. These high-energy deposition fractions (for electrons above 3 keV) do *not* include the energy in low-energy electrons, which are processed separately in DarkHistory by [*physics.low_energy*](https://darkhistory.readthedocs.io/en/latest/_autosummary/darkhistory/darkhistory.low_energy.html). "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.figure()\n",
    "\n",
    "plt.loglog()\n",
    "\n",
    "ion_plot,  = plt.plot(eleceng, elec_dep_ion/eleceng,  label='Ionization')\n",
    "exc_plot,  = plt.plot(eleceng, elec_dep_exc/eleceng,  label='Excitation')\n",
    "heat_plot, = plt.plot(eleceng, elec_dep_heat/eleceng, label='Heating')\n",
    "\n",
    "plt.xlabel('Electron Energy [eV]')\n",
    "plt.ylabel('Fraction')\n",
    "plt.title('High-Energy Deposition Fraction')\n",
    "\n",
    "plt.legend(handles=[ion_plot, exc_plot, heat_plot])\n",
    "\n",
    "plt.axis([3.2e3, 5e12, 1e-10, 1])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This plot reflects the fact that for higher energy electrons, atomic processes become less important as channels of energy deposition: instead, most of the energy is instead transferred to CMB photons that undergo inverse Compton scattering (ICS). "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Comparing Inverse Compton Scattering and Atomic Processes"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's explicitly compare the energy deposited into inverse Compton scattering against the energy deposited via atomic processes plus the low-energy electrons. We will ultimately reproduce the plot shown as Fig. 2 of [[1]](#cite_2015). \n",
    "\n",
    "Let's add up all the energy in atomic processes plus low-energy electrons. First, we get the low-energy electrons, which is saved as a [*TransFuncAtRedshift*](https://darkhistory.readthedocs.io/en/master/_autosummary/darkhistory/spec/transferfunction/darkhistory.spec.transferfunction.TransFuncAtRedshift.html). We can obtain the total energy for each injected electron using `TransFuncAtRedshift.toteng()`. The function `toteng()` sums over the the last axis, i.e. it sums the energy of all photons in each spectrum corresponding to an injected electron. This can then be added to the other components to get the total energy deposited as atomic processes. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "lowengelec_tf = elec_cooling_info[1]\n",
    "\n",
    "eng_dep_lowengelec = lowengelec_tf.toteng()\n",
    "\n",
    "eng_dep_atomic = eng_dep_lowengelec + elec_dep_ion + elec_dep_exc + elec_dep_heat"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now let's look at the energy deposited into ICS. This is equal to the energy stored in the secondary propagating photon spectrum, minus the initial energy of these upscattered photons. Again, we can use `TransFuncAtRedshift.toteng()` to get the total energy in the photon spectrum."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "ICS_phot_tf = elec_cooling_info[0]\n",
    "\n",
    "eng_dep_ICS_phot = ICS_phot_tf.toteng()\n",
    "\n",
    "eng_dep_ICS = eng_dep_ICS_phot"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "All right, let's make the plot!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.figure()\n",
    "\n",
    "ax = plt.gca()\n",
    "ax.set_xscale('log')\n",
    "\n",
    "atomic_plot, = plt.plot(eleceng, eng_dep_atomic/eleceng,  label='Atomic Processes')\n",
    "ICS_plot,    = plt.plot(eleceng, eng_dep_ICS/eleceng,  label='Inverse Compton')\n",
    "\n",
    "plt.xlabel('Electron Energy [eV]')\n",
    "plt.ylabel('Fraction')\n",
    "plt.title(r'Deposition Fractions, $z=600$')\n",
    "\n",
    "plt.legend(handles=[atomic_plot, ICS_plot])\n",
    "\n",
    "plt.axis([1, 5e12, 0, 1.1])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Getting Spectra"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The transfer function stored in `ICS_phot_tf` is essentially a list of photon spectra produced by a single electron at some injected energy. Acting this function by matrix multiplication on any arbitrary injection electron spectrum therefore gives the secondary photon spectrum produced after complete cooling of that spectrum. Again, we emphasize that `ICS_phot_tf` has the pre-scattering spectrum of upscattered CMB photons **subtracted** from the spectrum. \n",
    "\n",
    "Let's take some electron spectrum, produced by annihilation of dark matter into a $\\tau^+ \\tau^-$ pair. This can be obtained from [*darkhistory.spec.pppc*](https://darkhistory.readthedocs.io/en/master/_autosummary/darkhistory/spec/darkhistory.spec.pppc.html), which returns the same flux produced by PPPC4DMID [[2]](#cite_PPPC). We'll pick $m_\\text{DM}$ = 50 GeV, and obtain the spectrum per annihilation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from darkhistory.spec.pppc import get_pppc_spec\n",
    "\n",
    "mDM = 50e9\n",
    "\n",
    "elec_spec = get_pppc_spec(mDM, eleceng, 'tau', 'elec')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`elec_spec` here is a [*Spectrum*](https://darkhistory.readthedocs.io/en/master/_autosummary/darkhistory/spec/spectrum/darkhistory.spec.spectrum.Spectrum.html) object, and contains the abscissa (`eleceng`) and the spectrum, stored as dN/dE or N. To contract this spectrum with `ICS_phot_tf`, we use the `TransferFuncAtRedshift.sum_specs`, which acts with the matrix stored in `ICS_phot_tf` on the spectrum. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "phot_spec = ICS_phot_tf.sum_specs(elec_spec.N)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This produces a photon [*Spectrum*](https://darkhistory.readthedocs.io/en/master/_autosummary/darkhistory/spec/spectrum/darkhistory.spec.spectrum.Spectrum.html) object, with the abscissa given by `photeng`. \n",
    "\n",
    "We can also produce the initial spectrum of photons that got scattered. This is a blackbody spectrum, since we are only tracking photons that get upscattered in the nonrelativistic, Thomson regime (see section III.D of paper I for more details). The CMB spectrum at any temperature can be obtained using [*physics.CMB_spec()*](https://darkhistory.readthedocs.io/en/master/_autosummary/darkhistory/physics/darkhistory.physics.CMB_spec.html). This returns a spectrum containing $dN/(dE\\, dV)$ of the CMB. \n",
    "\n",
    "We simply have to rescale this spectrum to the total energy of CMB photons upscattered, which is stored in the output above.   "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "eng_initial_cmb = elec_cooling_info[5]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "First, let's put the spectrum in a [*Spectrum*](https://darkhistory.readthedocs.io/en/master/_autosummary/darkhistory/spec/spectrum/darkhistory.spec.spectrum.Spectrum.html) object."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from darkhistory.spec.spectrum import Spectrum\n",
    "\n",
    "# Use physics.TCMB() to get the temperature at the right redshift.\n",
    "CMB_spec = Spectrum(photeng, phys.CMB_spec(photeng, phys.TCMB(rs)), spec_type='dNdE')\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now, we want to rescale this spectrum so that it has the initial energy of the photons that got upscattered. This energy is given by `np.dot(eng_initial_cmb, elec_spec.N)`, since `eng_initial_cmb` has each bin normalized to one injected electron at some energy. \n",
    "\n",
    "We can do the rescaling simply by multiplying the [*Spectrum*](https://darkhistory.readthedocs.io/en/master/_autosummary/darkhistory/spec/spectrum/darkhistory.spec.spectrum.Spectrum.html) object itself. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "CMB_spec *= np.dot(eng_initial_cmb, elec_spec.N)/CMB_spec.toteng()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here are the produced spectra. To recap, `elec_spec` contains the injected electron spectrum. `phot_spec` contains the secondary photon spectrum produced with the initial upscattered CMB spectrum subtracted. `CMB_spec` is that initial upscattered CMB spectrum, and `phot_spec + CMB_spec` gives the final spectrum of all photons upscattered by ICS. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.figure()\n",
    "\n",
    "plt.loglog()\n",
    "\n",
    "elec_spec_plot, = plt.plot(eleceng, elec_spec.dNdE*eleceng**2, label=r'Injected $e^+e^-$ Spectrum')\n",
    "phot_spec_plot, = plt.plot(photeng, phot_spec.dNdE*photeng**2, label='ICS Secondary Photon Spectrum')\n",
    "CMB_plot,       = plt.plot(photeng, CMB_spec.dNdE*photeng**2,  'k--', label='Upscattered CMB')\n",
    "combined_plot,  = plt.plot(photeng, (phot_spec.dNdE + CMB_spec.dNdE)*photeng**2, label='ICS Scattered Photon Spectrum')\n",
    "\n",
    "plt.xlabel('Energy [eV]')\n",
    "plt.ylabel(r'$E^2\\, dN/dE$ [eV]')\n",
    "plt.title('ICS Spectra')\n",
    "\n",
    "plt.text(0.1, 0.92, r'$\\chi \\chi \\to \\tau^+\\tau^-$, $m_\\chi$ = 50 GeV', fontsize=20, transform=ax.transAxes) \n",
    "\n",
    "plt.legend(handles=[elec_spec_plot, phot_spec_plot, CMB_plot, combined_plot], loc=(0.1, 0.58))\n",
    "\n",
    "plt.axis([1e-4, 1e12, 1e-10, 1e25])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The black dashed line shows the spectrum of photons that got upscattered as the electron spectrum (blue) cools completely, producing the final photon spectrum shown in orange. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Bibliography"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "[1]<a id='cite_2015'></a> T. Slatyer, \"Indirect Dark Matter Signatures in the Cosmic Dark Ages II. Ionization, Heating and Photon Production from Arbitrary Energy Injections,\" arXiv:1506.03812, Phys. Rev. D93, 023521 (2016).\n",
    "\n",
    "[2]<a id='cite_PPPC'></a> M.Cirelli, G.Corcella, A.Hektor, G.Hütsi, M.Kadastik, P.Panci, M.Raidal, F.Sala, A.Strumia, \"PPPC 4 DM ID: A Poor Particle Physicist Cookbook for Dark Matter Indirect Detection,\" arXiv 1012.4515, JCAP 1103 (2011) 051. Erratum: JCAP 1210 (2012) E01."
   ]
  }
 ],
 "metadata": {
  "cite2c": {
   "citations": {
    "6232408/W944VR5Z": {
     "DOI": "10.1088/1475-7516/2011/03/051",
     "URL": "https://doi.org/10.1088%2F1475-7516%2F2011%2F03%2F051",
     "abstract": "We provide ingredients and recipes for computing signals of TeV-scale Dark Matter annihilations and decays in the Galaxy and beyond. For each DM channel, we present the energy spectra of at production, computed by high-statistics simulations. We estimate the Monte Carlo uncertainty by comparing the results yielded by the Pythia and Herwig event generators. We then provide the propagation functions for charged particles in the Galaxy, for several DM distribution profiles and sets of propagation parameters. Propagation of e± is performed with an improved semi-analytic method that takes into account position-dependent energy losses in the Milky Way. Using such propagation functions, we compute the energy spectra of e±,p̄ and d̄ at the location of the Earth. We then present the gamma ray fluxes, both from prompt emission and from Inverse Compton scattering in the galactic halo. Finally, we provide the spectra of extragalactic gamma rays. All results are available in numerical form and ready to be consumed.",
     "accessed": {
      "day": 15,
      "month": 3,
      "year": 2019
     },
     "author": [
      {
       "family": "Cirelli",
       "given": "Marco"
      },
      {
       "family": "Corcella",
       "given": "Gennaro"
      },
      {
       "family": "Hektor",
       "given": "Andi"
      },
      {
       "family": "Hütsi",
       "given": "Gert"
      },
      {
       "family": "Kadastik",
       "given": "Mario"
      },
      {
       "family": "Panci",
       "given": "Paolo"
      },
      {
       "family": "Raidal",
       "given": "Martti"
      },
      {
       "family": "Sala",
       "given": "Filippo"
      },
      {
       "family": "Strumia",
       "given": "Alessandro"
      }
     ],
     "container-title": "Journal of Cosmology and Astroparticle Physics",
     "container-title-short": "J. Cosmol. Astropart. Phys.",
     "id": "6232408/W944VR5Z",
     "issue": "03",
     "issued": {
      "month": 3,
      "year": 2011
     },
     "journalAbbreviation": "J. Cosmol. Astropart. Phys.",
     "language": "en",
     "page": "051–051",
     "page-first": "051",
     "shortTitle": "PPPC 4 DM ID",
     "title": "PPPC 4 DM ID: a poor particle physicist cookbook for dark matter indirect detection",
     "title-short": "PPPC 4 DM ID",
     "type": "article-journal",
     "volume": "2011"
    }
   }
  },
  "kernelspec": {
   "display_name": "Python 3",
   "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.6.7"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
