{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Binning Schemes with `GammaBinning`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`GammaBayes` works primarily with binned event data. In essence, we have a continuous set of energy, longitude, and latitude values that we group into discrete values either due to limitations in the instrument that detected them or for computational efficiency, the latter being the main reason `GammaBayes` bins the data.\n", "\n", "`GammaBayes` is primarily developed for use of Imaging Atmospheric Cherenkov Telescope arrays (mostly CTAO) which gives reconstructed event data of energy, longitude and latitude values. `GammaBinning` takes in the axes for these values and provides many handy related utilities which we will look at in this tutorial." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Base use case" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The default presumed use case of `GammaBinning` is that you, the user, have some idea for what the bin centres for your energy, longitude and latitude values like below." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "from astropy import units as u\n", "\n", "energy_axis = np.logspace(-1,2, 16)*u.TeV\n", "longitude_axis = np.linspace(-3, 3, 31)*u.deg\n", "latitude_axis = np.linspace(-2, 2, 11)*u.deg" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We have set our energy axis to be from 0.1 TeV to 100 TeV with 10 bins per decade, our longitude axis to go from -3 to 3 degree in galactic longitude and our latitude axis to go from -2 to 2 degree in galactic latitude.\n", "\n", "We then put these into `GammaBinning` like so." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/Users/lpin0002/anaconda3/envs/testofwest/lib/python3.12/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", " from .autonotebook import tqdm as notebook_tqdm\n" ] } ], "source": [ "from gammabayes import GammaBinning\n", "\n", "binning_geometry = GammaBinning(energy_axis=energy_axis, lon_axis=longitude_axis, lat_axis=latitude_axis)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "No we will go into the various functions and attributes for this class instance." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## `GammaBinning` attributes" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `axes`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This attribute allow you to extract a list of the axes contained in a `GammaBinning` instance." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[,\n", " ,\n", " ]" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "binning_geometry.axes" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `lon_res` and `lat_res`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Presuming that the angular axes have linearly separated values `lat_res` and `lon_res` allow you to extract the spacing between the bins. Here you can see that we set the spacing between the longitude axis bins to be smaller than the latitude axis bin separation." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(, )" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "binning_geometry.lon_res, binning_geometry.lat_res" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `axes_mesh`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Gives a mesh grid of all the axis values. If you have axes of size x, y, and z for example then you will get a list of three arrays of size (x, y, z) for the energy, longitude and latitude values respectively." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(16, 31, 11)" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "binning_geometry.axes_mesh[0].shape # energy values" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `axes_dim`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Returns the dimensions of the energy, longitude and latitude axes in a tuple" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(16, 31, 11)" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "binning_geometry.axes_dim" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `spatial_axes`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "An attribute that contains a list of the two angular/spatial axes, i.e. [longitude axis, latitude axis]" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[,\n", " ]" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "binning_geometry.spatial_axes" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `spatial_centre`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This attribute is the mean of the longitude and latitude axes as a coordinate for use as a 'centre'. It is not necessarily also a bin coordinate and quite often there are some floating point errors leading to slightly off results like the one below which should just be [0,0]." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$[1.4325458 \\times 10^{-16},~1.2111524 \\times 10^{-16}] \\; \\mathrm{{}^{\\circ}}$" ], "text/plain": [ "" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "binning_geometry.spatial_centre" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## `GammaBinning` methods" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `to_dict`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This method will take the axes and put them in a dictionary like the one below " ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'energy_axis': ,\n", " 'lon_axis': ,\n", " 'lat_axis': }" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "binning_geometry.to_dict()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `from_params`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This method allow you to construct a `GammaBinning` object by giving the axis information like minima, maxima and bin size. It is useful for high level setups where you can have a dictionary of the float values within a yaml file for example and pass them into this method." ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "([,\n", " ,\n", " ],\n", " (27, 21, 6))" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "axis_info = {\n", " 'lon_min': -2,\n", " 'lon_max': 2,\n", " 'lon_bin_size': 0.2,\n", " 'lat_min': -1, \n", " 'lat_max': 1,\n", " 'lat_bin_size': 0.4,\n", " 'energy_min': 0.2,\n", " 'energy_max': 80,\n", " 'energy_bins_per_decade': 10,\n", " 'energy_unit': \"TeV\",\n", " 'angle_unit': \"deg\",\n", "}\n", "\n", "\n", "\n", "\n", "new_binning_geometry = GammaBinning.from_params(**axis_info)\n", "\n", "new_binning_geometry.axes, new_binning_geometry.axes_dim" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## `GammaBinning` behaviours" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Equality" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can also check to see if two `GammaBinning` instances are equal, or not equal. " ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(False, True)" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "new_binning_geometry==binning_geometry, new_binning_geometry!=binning_geometry" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Containment" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can also check if one instance of a binning geometry is entirely contained within another. \n", "\n", "This will return True the bounds for one are equal to or more constrained than the other, and False if any axis sits out the other. \n", "\n", "If we use the two bin geometries defined above, the `new_binning_geometry` has energy and angular axes contained within the bounds of `binning_geometry`, so we get the following." ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(True, True, False, False)" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "new_binning_geometrybinning_geometry, new_binning_geometry>=binning_geometry" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now let's say we make a third binning_geometry that has the same bounds as `binning_geometry` but different resolutions. Then the comparison statements would say that they are equal." ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [], "source": [ "energy_axis = np.logspace(-1,2, 31)*u.TeV\n", "longitude_axis = np.linspace(-3, 3, 61)*u.deg\n", "latitude_axis = np.linspace(-2, 2, 21)*u.deg\n", "\n", "\n", "new_new_binning_geometry = GammaBinning(energy_axis=energy_axis, lon_axis=longitude_axis, lat_axis=latitude_axis)" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(False, True, False, True)" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "new_new_binning_geometrybinning_geometry, new_new_binning_geometry>=binning_geometry" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "But they are not the same so an equality comparison will return `False`." ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "new_new_binning_geometry==binning_geometry" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Next tutorial" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The next recommend tutorial is dealing with exposures within `GammaBayes`." ] } ], "metadata": { "kernelspec": { "display_name": "testofwest", "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.0" } }, "nbformat": 4, "nbformat_minor": 2 }