{ "cells": [ { "cell_type": "markdown", "id": "48171309-57ba-411b-bcd3-fafaf43b029b", "metadata": {}, "source": [ "# Interface with gammapy\n", "\n", "This notebook demonstrates how you can easily set up a model for `gammapy` that interfaces with the `OptDepth` class from `ebltable`.\n", "For this notebook to run, you need to have `gammapy` installed. I tested the notebook with `gammapy` version 1.0." ] }, { "cell_type": "markdown", "id": "c502df4c-bb0f-426f-85bd-c1d5a2b4e232", "metadata": {}, "source": [ "We start with the necessary `gammapy` imports." ] }, { "cell_type": "code", "execution_count": 1, "id": "d6502940-a447-495e-afd6-3aec7414f010", "metadata": {}, "outputs": [], "source": [ "from gammapy.modeling.models import TemplateSpectralModel, SpectralModel\n", "from gammapy.modeling import Parameter" ] }, { "cell_type": "markdown", "id": "b9809923-4395-42d6-aa99-69fc7e8b33d0", "metadata": {}, "source": [ "And continue with addtional imports. " ] }, { "cell_type": "code", "execution_count": 2, "id": "907a72c1-21a2-4bc9-a9af-7737b39340e2", "metadata": {}, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "import numpy as np\n", "from astropy import units as u\n", "from ebltable.tau_from_model import OptDepth" ] }, { "cell_type": "markdown", "id": "801940be-426b-4fef-9a48-d81c7a5906b8", "metadata": {}, "source": [ "Then we pick an EBL model in initialize the `OptDepth` class. For illustration we also set up a `gammapy` template spectrum. For this, it's however not possible to change the EBL normalization parameter." ] }, { "cell_type": "code", "execution_count": 3, "id": "bcc4a3e0-10b7-4e9f-acfb-6f36a82508fe", "metadata": {}, "outputs": [], "source": [ "ebl_model = 'finke2022'" ] }, { "cell_type": "code", "execution_count": 4, "id": "1ae78746-3b3f-4509-975f-fde8eddf127b", "metadata": {}, "outputs": [], "source": [ "tau = OptDepth.readmodel(model=ebl_model)" ] }, { "cell_type": "code", "execution_count": 5, "id": "3c23d882-3997-4573-8728-643c0ef35e86", "metadata": {}, "outputs": [], "source": [ "z = 0.2\n", "ETeV = np.logspace(-1,1.5,50)" ] }, { "cell_type": "code", "execution_count": 6, "id": "d035f19f-8397-4dd9-be2d-b69282707b6a", "metadata": {}, "outputs": [], "source": [ "atten = np.exp(-1. * tau.opt_depth(z,ETeV))" ] }, { "cell_type": "code", "execution_count": 7, "id": "5e74b5a1-91f0-460c-bb24-188a64f25de1", "metadata": {}, "outputs": [], "source": [ "template = TemplateSpectralModel(energy=ETeV * u.TeV, values=atten)" ] }, { "cell_type": "markdown", "id": "edb43045-9d54-412a-af3e-a12b6295c25b", "metadata": {}, "source": [ "Now we build our own spectral model class. The class has the possibility to be initiated from a built-in model." ] }, { "cell_type": "code", "execution_count": 8, "id": "939d0c6a-55d7-4b20-9da9-22ffb9cb1ddb", "metadata": {}, "outputs": [], "source": [ "class OptDepthSpectralModel(SpectralModel):\n", " \n", " r\"\"\"Gamma-ray absorption models build from the `~ebltable` package. \n", " \n", " Parameters\n", " ----------\n", " optdepth : `~ebltable.tau_from_model.OptDepth`\n", " optical depth class\n", " redshift : float\n", " Redshift of the absorption model\n", " alpha_norm: float\n", " Norm of the EBL model\n", " \"\"\"\n", "\n", " tag = [\"OptDepthSpectralModel\", \"tau-norm\"]\n", " alpha_norm = Parameter(\"alpha_norm\", 1.0, frozen=True)\n", " redshift = Parameter(\"redshift\", 0.1, frozen=True)\n", "\n", " def __init__(self, optdepth, redshift, alpha_norm):\n", " self.optdepth = optdepth\n", " self._cashed_redshift = None\n", " self._cashed_tau = None\n", " \n", " super().__init__(redshift=redshift, alpha_norm=alpha_norm)\n", "\n", " @classmethod\n", " def read_model(cls, model, redshift, alpha_norm=1.):\n", " \"\"\"\n", " Initiate the class from a built-in model \n", " \n", " Parameters\n", " ----------\n", " model: str\n", " model name implemented in `ebltable.tau_from_model.OptDepth`\n", " \n", " redshift: float\n", " source redshift\n", " \"\"\"\n", " optdepth = OptDepth.readmodel(model=model)\n", " \n", " return cls(\n", " optdepth=optdepth,\n", " redshift=redshift,\n", " alpha_norm=alpha_norm,\n", " )\n", "\n", " def evaluate(self, energy, redshift, alpha_norm):\n", " \"\"\"Evaluate model for energy and parameter value.\"\"\"\n", " if self._cashed_redshift is None \\\n", " or not self._cashed_redshift == redshift:\n", " \n", " try: \n", " self._cashed_tau = self.optdepth.opt_depth(redshift.value, energy.to(u.TeV).value)\n", " except AttributeError:\n", " self._cashed_tau = self.optdepth.opt_depth(redshift, energy.to(u.TeV).value)\n", " \n", " absorption = np.exp(-self._cashed_tau * alpha_norm)\n", " return absorption" ] }, { "cell_type": "markdown", "id": "dec1f077-8773-48cd-a359-7920b556574c", "metadata": {}, "source": [ "Initialize the class from a built-in model is done in the following way:" ] }, { "cell_type": "code", "execution_count": 9, "id": "a1097c21-ed55-4228-8d9b-4b107f0b531d", "metadata": {}, "outputs": [], "source": [ "optdepth = OptDepthSpectralModel.read_model(ebl_model, z)" ] }, { "cell_type": "markdown", "id": "2849fe99-9b79-42a8-b3fe-c86073a99f9e", "metadata": {}, "source": [ "Here are the parameters of the model:" ] }, { "cell_type": "code", "execution_count": 10, "id": "454f811a-d19f-42c6-90f6-31a05ba4b407", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
| type | name | value | unit | error | min | max | frozen | is_norm | link |
|---|---|---|---|---|---|---|---|---|---|
| str8 | str10 | float64 | str1 | int64 | float64 | float64 | bool | bool | str1 |
| spectral | alpha_norm | 1.0000e+00 | 0.000e+00 | nan | nan | True | False | ||
| spectral | redshift | 2.0000e-01 | 0.000e+00 | nan | nan | True | False |