diff --git a/Writing_playground.ipynb b/Writing_playground.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..40518e7517abc78680e622771e2cfb368e70cac9 --- /dev/null +++ b/Writing_playground.ipynb @@ -0,0 +1,561 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Error initializing plugin EntryPoint(name='Windows (alt)', value='keyrings.alt.Windows', group='keyring.backends').\n", + "Traceback (most recent call last):\n", + " File \"/home/jutta/.local/lib/python3.6/site-packages/keyring/backend.py\", line 203, in _load_plugins\n", + " init_func = ep.load()\n", + " File \"/home/jutta/.local/lib/python3.6/site-packages/importlib_metadata/__init__.py\", line 105, in load\n", + " module = import_module(match.group('module'))\n", + " File \"/usr/lib/python3.6/importlib/__init__.py\", line 126, in import_module\n", + " return _bootstrap._gcd_import(name[level:], package, level)\n", + " File \"<frozen importlib._bootstrap>\", line 994, in _gcd_import\n", + " File \"<frozen importlib._bootstrap>\", line 971, in _find_and_load\n", + " File \"<frozen importlib._bootstrap>\", line 955, in _find_and_load_unlocked\n", + " File \"<frozen importlib._bootstrap>\", line 665, in _load_unlocked\n", + " File \"<frozen importlib._bootstrap_external>\", line 678, in exec_module\n", + " File \"<frozen importlib._bootstrap>\", line 219, in _call_with_frames_removed\n", + " File \"/usr/lib/python3/dist-packages/keyrings/alt/Windows.py\", line 9, in <module>\n", + " from . import file_base\n", + " File \"/usr/lib/python3/dist-packages/keyrings/alt/file_base.py\", line 13, in <module>\n", + " from keyring.util.escape import escape as escape_for_ini\n", + "ModuleNotFoundError: No module named 'keyring.util.escape'\n", + "Error initializing plugin EntryPoint(name='file', value='keyrings.alt.file', group='keyring.backends').\n", + "Traceback (most recent call last):\n", + " File \"/home/jutta/.local/lib/python3.6/site-packages/keyring/backend.py\", line 203, in _load_plugins\n", + " init_func = ep.load()\n", + " File \"/home/jutta/.local/lib/python3.6/site-packages/importlib_metadata/__init__.py\", line 105, in load\n", + " module = import_module(match.group('module'))\n", + " File \"/usr/lib/python3.6/importlib/__init__.py\", line 126, in import_module\n", + " return _bootstrap._gcd_import(name[level:], package, level)\n", + " File \"<frozen importlib._bootstrap>\", line 994, in _gcd_import\n", + " File \"<frozen importlib._bootstrap>\", line 971, in _find_and_load\n", + " File \"<frozen importlib._bootstrap>\", line 955, in _find_and_load_unlocked\n", + " File \"<frozen importlib._bootstrap>\", line 665, in _load_unlocked\n", + " File \"<frozen importlib._bootstrap_external>\", line 678, in exec_module\n", + " File \"<frozen importlib._bootstrap>\", line 219, in _call_with_frames_removed\n", + " File \"/usr/lib/python3/dist-packages/keyrings/alt/file.py\", line 11, in <module>\n", + " from keyring.util.escape import escape as escape_for_ini\n", + "ModuleNotFoundError: No module named 'keyring.util.escape'\n", + "Error initializing plugin EntryPoint(name='pyfs', value='keyrings.alt.pyfs', group='keyring.backends').\n", + "Traceback (most recent call last):\n", + " File \"/home/jutta/.local/lib/python3.6/site-packages/keyring/backend.py\", line 203, in _load_plugins\n", + " init_func = ep.load()\n", + " File \"/home/jutta/.local/lib/python3.6/site-packages/importlib_metadata/__init__.py\", line 105, in load\n", + " module = import_module(match.group('module'))\n", + " File \"/usr/lib/python3.6/importlib/__init__.py\", line 126, in import_module\n", + " return _bootstrap._gcd_import(name[level:], package, level)\n", + " File \"<frozen importlib._bootstrap>\", line 994, in _gcd_import\n", + " File \"<frozen importlib._bootstrap>\", line 971, in _find_and_load\n", + " File \"<frozen importlib._bootstrap>\", line 955, in _find_and_load_unlocked\n", + " File \"<frozen importlib._bootstrap>\", line 665, in _load_unlocked\n", + " File \"<frozen importlib._bootstrap_external>\", line 678, in exec_module\n", + " File \"<frozen importlib._bootstrap>\", line 219, in _call_with_frames_removed\n", + " File \"/usr/lib/python3/dist-packages/keyrings/alt/pyfs.py\", line 8, in <module>\n", + " from keyring.util.escape import escape as escape_for_ini\n", + "ModuleNotFoundError: No module named 'keyring.util.escape'\n", + "Defaulting to user installation because normal site-packages is not writeable\n", + "Collecting km3astro\n", + " Downloading km3astro-0.13.1-py2.py3-none-any.whl (99 kB)\n", + "\u001b[K |████████████████████████████████| 99 kB 4.2 MB/s eta 0:00:011\n", + "\u001b[?25hRequirement already satisfied: setuptools-scm in /home/jutta/.local/lib/python3.6/site-packages (from km3astro) (4.1.2)\n", + "Requirement already satisfied: tables in /home/jutta/.local/lib/python3.6/site-packages (from km3astro) (3.6.1)\n", + "Requirement already satisfied: matplotlib>=2.2 in /home/jutta/.local/lib/python3.6/site-packages (from km3astro) (3.1.1)\n", + "Requirement already satisfied: astropy>=3.0 in /usr/local/lib/python3.6/dist-packages (from km3astro) (4.0.1.post1)\n", + "Collecting healpy\n", + " Downloading healpy-1.15.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl (18.1 MB)\n", + "\u001b[K |████████████████████████████████| 18.1 MB 11.2 MB/s eta 0:00:01\n", + "\u001b[?25hCollecting utm\n", + " Downloading utm-0.7.0.tar.gz (8.7 kB)\n", + "Requirement already satisfied: numpy in /home/jutta/.local/lib/python3.6/site-packages (from km3astro) (1.19.1)\n", + "Requirement already satisfied: pandas in /home/jutta/.local/lib/python3.6/site-packages (from km3astro) (1.0.3)\n", + "Requirement already satisfied: setuptools>=40.6.2 in /home/jutta/.local/lib/python3.6/site-packages (from km3astro) (49.6.0)\n", + "Requirement already satisfied: kiwisolver>=1.0.1 in /home/jutta/.local/lib/python3.6/site-packages (from matplotlib>=2.2->km3astro) (1.2.0)\n", + "Requirement already satisfied: pyparsing!=2.0.4,!=2.1.2,!=2.1.6,>=2.0.1 in /home/jutta/.local/lib/python3.6/site-packages (from matplotlib>=2.2->km3astro) (2.4.7)\n", + "Requirement already satisfied: cycler>=0.10 in /home/jutta/.local/lib/python3.6/site-packages (from matplotlib>=2.2->km3astro) (0.10.0)\n", + "Requirement already satisfied: python-dateutil>=2.1 in /home/jutta/.local/lib/python3.6/site-packages (from matplotlib>=2.2->km3astro) (2.8.1)\n", + "Requirement already satisfied: six in /home/jutta/.local/lib/python3.6/site-packages (from cycler>=0.10->matplotlib>=2.2->km3astro) (1.15.0)\n", + "Requirement already satisfied: scipy in /home/jutta/.local/lib/python3.6/site-packages (from healpy->km3astro) (1.2.3)\n", + "Requirement already satisfied: pytz>=2017.2 in /home/jutta/.local/lib/python3.6/site-packages (from pandas->km3astro) (2020.1)\n", + "Requirement already satisfied: numexpr>=2.6.2 in /home/jutta/.local/lib/python3.6/site-packages (from tables->km3astro) (2.7.1)\n", + "Building wheels for collected packages: utm\n", + " Building wheel for utm (setup.py) ... \u001b[?25ldone\n", + "\u001b[?25h Created wheel for utm: filename=utm-0.7.0-py3-none-any.whl size=6131 sha256=62f3fb73a12b4256566257597e1244da30d596454550ba5bbbd9914a56af9886\n", + " Stored in directory: /home/jutta/.cache/pip/wheels/ab/8c/43/723355279387088dd6696089e77f9ddd242ba94e71a87c800f\n", + "Successfully built utm\n", + "Installing collected packages: utm, healpy, km3astro\n", + "Successfully installed healpy-1.15.0 km3astro-0.13.1 utm-0.7.0\n", + "\u001b[33mWARNING: You are using pip version 21.1.1; however, version 21.3.1 is available.\n", + "You should consider upgrading via the '/usr/bin/python3 -m pip install --upgrade pip' command.\u001b[0m\n", + "Error initializing plugin EntryPoint(name='Windows (alt)', value='keyrings.alt.Windows', group='keyring.backends').\n", + "Traceback (most recent call last):\n", + " File \"/home/jutta/.local/lib/python3.6/site-packages/keyring/backend.py\", line 203, in _load_plugins\n", + " init_func = ep.load()\n", + " File \"/home/jutta/.local/lib/python3.6/site-packages/importlib_metadata/__init__.py\", line 105, in load\n", + " module = import_module(match.group('module'))\n", + " File \"/usr/lib/python3.6/importlib/__init__.py\", line 126, in import_module\n", + " return _bootstrap._gcd_import(name[level:], package, level)\n", + " File \"<frozen importlib._bootstrap>\", line 994, in _gcd_import\n", + " File \"<frozen importlib._bootstrap>\", line 971, in _find_and_load\n", + " File \"<frozen importlib._bootstrap>\", line 955, in _find_and_load_unlocked\n", + " File \"<frozen importlib._bootstrap>\", line 665, in _load_unlocked\n", + " File \"<frozen importlib._bootstrap_external>\", line 678, in exec_module\n", + " File \"<frozen importlib._bootstrap>\", line 219, in _call_with_frames_removed\n", + " File \"/usr/lib/python3/dist-packages/keyrings/alt/Windows.py\", line 9, in <module>\n", + " from . import file_base\n", + " File \"/usr/lib/python3/dist-packages/keyrings/alt/file_base.py\", line 13, in <module>\n", + " from keyring.util.escape import escape as escape_for_ini\n", + "ModuleNotFoundError: No module named 'keyring.util.escape'\n", + "Error initializing plugin EntryPoint(name='file', value='keyrings.alt.file', group='keyring.backends').\n", + "Traceback (most recent call last):\n", + " File \"/home/jutta/.local/lib/python3.6/site-packages/keyring/backend.py\", line 203, in _load_plugins\n", + " init_func = ep.load()\n", + " File \"/home/jutta/.local/lib/python3.6/site-packages/importlib_metadata/__init__.py\", line 105, in load\n", + " module = import_module(match.group('module'))\n", + " File \"/usr/lib/python3.6/importlib/__init__.py\", line 126, in import_module\n", + " return _bootstrap._gcd_import(name[level:], package, level)\n", + " File \"<frozen importlib._bootstrap>\", line 994, in _gcd_import\n", + " File \"<frozen importlib._bootstrap>\", line 971, in _find_and_load\n", + " File \"<frozen importlib._bootstrap>\", line 955, in _find_and_load_unlocked\n", + " File \"<frozen importlib._bootstrap>\", line 665, in _load_unlocked\n", + " File \"<frozen importlib._bootstrap_external>\", line 678, in exec_module\n", + " File \"<frozen importlib._bootstrap>\", line 219, in _call_with_frames_removed\n", + " File \"/usr/lib/python3/dist-packages/keyrings/alt/file.py\", line 11, in <module>\n", + " from keyring.util.escape import escape as escape_for_ini\n", + "ModuleNotFoundError: No module named 'keyring.util.escape'\n", + "Error initializing plugin EntryPoint(name='pyfs', value='keyrings.alt.pyfs', group='keyring.backends').\n", + "Traceback (most recent call last):\n", + " File \"/home/jutta/.local/lib/python3.6/site-packages/keyring/backend.py\", line 203, in _load_plugins\n", + " init_func = ep.load()\n", + " File \"/home/jutta/.local/lib/python3.6/site-packages/importlib_metadata/__init__.py\", line 105, in load\n", + " module = import_module(match.group('module'))\n", + " File \"/usr/lib/python3.6/importlib/__init__.py\", line 126, in import_module\n", + " return _bootstrap._gcd_import(name[level:], package, level)\n", + " File \"<frozen importlib._bootstrap>\", line 994, in _gcd_import\n", + " File \"<frozen importlib._bootstrap>\", line 971, in _find_and_load\n", + " File \"<frozen importlib._bootstrap>\", line 955, in _find_and_load_unlocked\n", + " File \"<frozen importlib._bootstrap>\", line 665, in _load_unlocked\n", + " File \"<frozen importlib._bootstrap_external>\", line 678, in exec_module\n", + " File \"<frozen importlib._bootstrap>\", line 219, in _call_with_frames_removed\n", + " File \"/usr/lib/python3/dist-packages/keyrings/alt/pyfs.py\", line 8, in <module>\n", + " from keyring.util.escape import escape as escape_for_ini\n", + "ModuleNotFoundError: No module named 'keyring.util.escape'\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Defaulting to user installation because normal site-packages is not writeable\n", + "Requirement already satisfied: km3io in /home/jutta/.local/lib/python3.6/site-packages (0.21.0)\n", + "Requirement already satisfied: awkward>=1.0.0rc2 in /home/jutta/.local/lib/python3.6/site-packages (from km3io) (1.2.2)\n", + "Requirement already satisfied: setuptools-scm in /home/jutta/.local/lib/python3.6/site-packages (from km3io) (4.1.2)\n", + "Requirement already satisfied: uproot>=4.0.0rc5 in /home/jutta/.local/lib/python3.6/site-packages (from km3io) (4.0.7)\n", + "Requirement already satisfied: awkward0 in /home/jutta/.local/lib/python3.6/site-packages (from km3io) (0.15.5)\n", + "Requirement already satisfied: numba>=0.50 in /home/jutta/.local/lib/python3.6/site-packages (from km3io) (0.53.1)\n", + "Requirement already satisfied: uproot3>=3.11.1 in /home/jutta/.local/lib/python3.6/site-packages (from km3io) (3.14.4)\n", + "Requirement already satisfied: docopt in /home/jutta/.local/lib/python3.6/site-packages (from km3io) (0.6.2)\n", + "Requirement already satisfied: numpy>=1.13.1 in /home/jutta/.local/lib/python3.6/site-packages (from awkward>=1.0.0rc2->km3io) (1.19.1)\n", + "Requirement already satisfied: setuptools in /home/jutta/.local/lib/python3.6/site-packages (from awkward>=1.0.0rc2->km3io) (49.6.0)\n", + "Requirement already satisfied: llvmlite<0.37,>=0.36.0rc1 in /home/jutta/.local/lib/python3.6/site-packages (from numba>=0.50->km3io) (0.36.0)\n", + "Requirement already satisfied: uproot3-methods in /home/jutta/.local/lib/python3.6/site-packages (from uproot3>=3.11.1->km3io) (0.10.1)\n", + "Requirement already satisfied: cachetools in /home/jutta/.local/lib/python3.6/site-packages (from uproot3>=3.11.1->km3io) (4.1.0)\n", + "\u001b[33mWARNING: You are using pip version 21.1.1; however, version 21.3.1 is available.\n", + "You should consider upgrading via the '/usr/bin/python3 -m pip install --upgrade pip' command.\u001b[0m\n" + ] + } + ], + "source": [ + "! pip install km3astro\n", + "! pip install km3io" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Writing events in gammapy\n", + "\n", + "Event list: https://docs.gammapy.org/0.20.1/api/gammapy.data.EventList.html\n", + "* based on astropy table\n", + "* following NASA guidelines for event lists: https://heasarc.gsfc.nasa.gov/docs/heasarc/ofwg/docs/events/ogip_94_003/ogip_94_003.html\n", + "* compatible with VO table\n", + "* no direct writing in gammapy, but helper function for table creation: https://docs.gammapy.org/0.20.1/_modules/gammapy/utils/table.html\n", + "\n", + "## Definition of an EventList\n", + "\n", + "> In the context of OGIP FITS files, an Event List is defined to be a FITS extension containing a list of parameters/flags associated with events recorded by an instrument (eg the time-tag, position on the detector, pulse height), and/or parameters/flags derived from these quantities (e.g., barycentric time, linearized detector coordinates, celestial coordinates, photon energy ... etc of the events) -- both the original and derived quantities will be referred to as \"attributes\". The list can contain the results of events arising from the cosmos (including cosmic ray events), and/or \"false\" background events recorded as a result of instrumental/electronic noise. For an OGIP-standard Event List, one row contains attributes of a single event; a related file format which contains multiple events per row may be advantageous for specific missions and will be defined elsewhere.\n", + "\n", + "> An Event List can also be considered a Light Curve, or (binned) time series histogram, with time bins of size equal to the accuracy of the time stamp. However, when viewed as a binned light curve, the Event List has the following properties that binned light curves usually do not have and that, therefore, distinguish the event list as a special kind of binned light curve:\n", + "\n", + "> The event list is a sparse histogram (i.e., only filled bins are present).\n", + " Each bin (by definition) has a population of one event.\n", + " Each bin (as defined by the value of the time stamp) may be present more than once, thus indicating populations greater than one.\n", + "\n", + "> The detailed format of a given Event Lists is considered instrument-specific, and the order in which the events are listed application-specific. " + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "import km3io\n", + "from km3io import OfflineReader\n", + "filename = \"/home/jutta/Desktop/gitstuff/open-event-writer/datav5.40.jorcarec.aanet.00006175.root\"\n", + "myfile = OfflineReader(filename)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Prototype event list\n", + "\n", + "https://gamma-astro-data-formats.readthedocs.io/en/v0.2/events/events.html\n", + "\n", + "## By-event parameters\n", + "\n", + "### Mandatory\n", + "\n", + "#### EVENT_ID type: int64\n", + "Event identification number at the DL3 level. See notes on [EVENT_ID](https://gamma-astro-data-formats.readthedocs.io/en/v0.2/events/events.html#iact-events-event-id)\n", + "* As only a int64 is possible and event identification in KM3NeT contains various subparts, a conversion function between the identifiers and our internal identification is necessary.\n", + "* Identifier parts (19 digits available): \n", + " * instrument (1 digit): i - 1 km3net, 2 antares\n", + " * detector_id (3 digits): ddd\n", + " * run_id (6 digits): rrrrrr\n", + " * frame_index (6 digits): ffffff\n", + " * trigger_counter (3 digits): ttt\n", + " encoded id: idddrrrrrrffffffttt\n", + "\n", + "#### TIME type: float64, unit: s\n", + "Event time (see Time: https://gamma-astro-data-formats.readthedocs.io/en/v0.2/general/time.html#time)\n", + "* KM3NeT: unix time from event time + track time\n", + "\n", + "#### RA type: float, unit: deg\n", + "Reconstructed event Right Ascension (see RA / DEC: https://gamma-astro-data-formats.readthedocs.io/en/v0.2/general/coordinates.html#coords-radec ).\n", + "\n", + "#### DEC type: float, unit: deg\n", + "Reconstructed event Declination (see RA / DEC: [[https://gamma-astro-data-formats.readthedocs.io/en/v0.2/general/coordinates.html#coords-radec]] ).\n", + "\n", + "#### ENERGY type: float, unit: TeV\n", + "Reconstructed event energy\n", + "* In KM3NeT: given in GeV\n", + "\n", + "### Optional\n", + "https://gamma-astro-data-formats.readthedocs.io/en/v0.2/events/events.html#optional-columns\n", + "\n", + "\n", + "## Header parameters\n", + "https://gamma-astro-data-formats.readthedocs.io/en/v0.2/events/events.html#mandatory-header-keywords\n", + "\n", + "### Mandatory\n", + "\n", + "The standard FITS reference time header keywords should be used (see Formats). An observatory Earth location should be given as well (see Earth location).\n", + "\n", + "* HDUCLASS type: string\n", + " * Signal conformance with HEASARC/OGIP conventions (option: ‘OGIP’). See HDU classes.\n", + "* HDUDOC type: string\n", + " * Reference to documentation where data format is documented. See HDU classes.\n", + "* HDUVERS type: string\n", + " * Version of the format (e.g. ‘1.0.0’). See HDU classes.\n", + "* HDUCLAS1 type: string\n", + " * Primary extension class (option: ‘EVENTS’). See HDU classes.\n", + "* OBS_ID type: int\n", + " * Unique observation identifier (Run number)\n", + "* TSTART type: float, unit: s\n", + " * Start time of observation (relative to reference time, see Time)\n", + "* TSTOP type: float, unit: s\n", + " * End time of observation (relative to reference time, see Time)\n", + "* ONTIME type: float, unit: s\n", + " * Total good time (sum of length of all Good Time Intervals). If a Good Time Interval (GTI) table is provided, ONTIME should be calculated as the sum of those intervals. Corrections for instrumental dead time effects are NOT included.\n", + "* LIVETIME type: float, unit: s\n", + " * Total time (in seconds) on source, corrected for the total instrumental dead time effect.\n", + "* DEADC type: float\n", + " * Dead time correction, defined by LIVETIME/ONTIME. Is comprised in [0,1]. Defined to be 0 if ONTIME=0.\n", + "* EQUINOX type: float\n", + " * Equinox in years for the celestial coordinate system in which positions given in either the header or data are expressed (options: 2000.0). See also HFWG Recommendation R3 for the OGIP standard.\n", + "* RADECSYS type: string\n", + " * Stellar reference frame used for the celestial coordinate system in which positions given in either the header or data are expressed. (options: ‘ICRS’, ‘FK5’). See also HFWG Recommendation R3 for the OGIP standard.\n", + "* ORIGIN type: string\n", + " * Organisation that created the FITS file. This can be the same as TELESCOP (e.g. “HESSâ€), but it could also be different if an organisation has multiple telescopes (e.g. “NASA†or “ESOâ€).\n", + "* TELESCOP type: string\n", + " * Telescope (e.g. ‘CTA’, ‘HESS’, ‘VERITAS’, ‘MAGIC’)\n", + "* INSTRUME type: string\n", + " * Instrument used to aquire the data contained in the file. Each organisation and telescop has to define this. E.g. for CTA it could be ‘North’ and ‘South’, or sub-array configurations, this has not been defined yet.\n", + "* CREATOR type: string\n", + " * Software that created the file. When appropriate, the value of the CREATOR keyword should also reference the specific version of the program that created the FITS file. It is intented that this keyword should refer to the program that originally defined the FITS file structure and wrote the contents. If a FITS file is subsequently copied largely intact into a new FITS by another program, then the value of the CREATOR keyword should still refer to the original program. HISTORY keywords should be used instead to document any further processing that is performed on the file after it is created. For more reading on the OGIP standard, see here." + ] + }, + { + "cell_type": "code", + "execution_count": 325, + "metadata": {}, + "outputs": [], + "source": [ + "from astropy.time import Time\n", + "from astropy.table import Table\n", + "from astropy.io import fits\n", + "from km3astro.coord import local_event\n", + "from km3astro.toolbox import get_ra_dec\n", + "\n", + "class OpenEventList:\n", + " def __init__(self):\n", + " self.header = {\"HDUCLASS\": \"VODF\", \"HDUDOC\": \"http://openscience.km3net.de\", \\\n", + " \"HDUVERS\": \"1.0.0\", \"HDUCLAS1\": \"EVENTS\", \\\n", + " \"OBS_ID\": 0, \\\n", + " \"TSTART\": 0.0, \"TSTOP\": 0.0, \"ONTIME\": 0.0, \\\n", + " \"MJDREFI\": 40587, \"MJDREFF\": 0.0, \"TIMESYS\": \"UTC\", \\\n", + " \"LIVETIME\": 0.0, \"DEADC\": 0.0, \"EQUINOX\": 2000.0, \"RADECSYS\": \"ICRS\", \\\n", + " \"ORIGIN\": \"KM3NeT\", \"TELESCOP\": \"KM3NeT\", \"INSTRUME\": \"ARCA\", \"CREATOR\": \"\"}\n", + " self.hdu = None\n", + " \n", + " def set_data(self, evtid, time, energy, ra, dec):\n", + " colid = fits.Column(name='EVENT_ID', format='K', array=np.array(evtid))\n", + " colt = fits.Column(name='TIME', format='D', unit='s', array=np.array(time))\n", + " cole = fits.Column(name='ENERGY', format='E', unit='GeV', array=np.array(energy))\n", + " colra = fits.Column(name='RA', format='E', unit='deg', array=np.array(ra))\n", + " coldec = fits.Column(name='DEC', format='E', unit='deg', array=np.array(dec))\n", + " coldefs = fits.ColDefs([colid, colt, cole, colra, coldec])\n", + " self.hdu = fits.BinTableHDU.from_columns(coldefs)\n", + "\n", + " def set_header(self):\n", + " for entry in self.header:\n", + " self.hdu.header[entry] = self.header[entry]\n", + " \n", + " def write_fits(self, filename):\n", + " self.hdu.writeto(filename)\n", + " \n", + "class OpenEvent:\n", + " def __init__(self):\n", + " self.eventid = None #int64 encoding detector ID, runnumber, frameindex and trigger counter\n", + " self.time = None\n", + " self.direction = None\n", + " self.energy = None\n", + " \n", + " def get_event_from_offlinefile(self, rootfile, entry, detector = \"orca\"):\n", + " self.set_eventID(rootfile.det_id[entry], rootfile.run_id[entry], rootfile.frame_index[entry], rootfile.trigger_counter[entry])\n", + " self.set_time(rootfile.t_sec[entry], rootfile.tracks[entry].t[0], rootfile.t_ns[entry])\n", + " self.set_event(rootfile.tracks[entry].dir_x[0], rootfile.tracks[entry].dir_y[0], \\\n", + " rootfile.tracks[entry].dir_z[0], detector = detector)\n", + " self.set_energy(rootfile.tracks[entry].E[0])\n", + "\n", + " def set_eventID(self, detid, runid, frameindex, triggercounter, detector = \"km3net\"):\n", + " if detector == \"km3net\":\n", + " instid = \"1\"\n", + " elif detector == \"antares\":\n", + " instid = \"2\"\n", + " else:\n", + " instid == \"8\"\n", + " evtstring = instid + str(detid).rjust(3, '0') + str(runid).rjust(6, '0') + \\\n", + " str(frameindex).rjust(6, '0') + str(triggercounter).rjust(3, '0')\n", + " self.eventid = int(evtstring)\n", + "\n", + " def get_eventID_as_string(self):\n", + " evtid = str(eventid)\n", + " if len(evtid) < 19:\n", + " print (\"Wrong event ID, cannot create string!\")\n", + " return None\n", + " if evtid[0] == \"1\":\n", + " return \"km3.\"+evtid[1:4]+\".\"+evtid[4:10]+\".\"+evtid[10:16]+\".\"+evtid[16:20]\n", + " else:\n", + " return evtid[0]+\".\"+evtid[1:4]+\".\"+evtid[4:10]+\".\"+evtid[10:16]+\".\"+evtid[16:20]\n", + "\n", + " def set_time(self, evttime, frametime, frametime_ns):\n", + " self.time = Time((evttime*10E9 + frametime + frametime_ns)/10E9, format = \"unix\")\n", + "\n", + " def get_time_utc(self):\n", + " return self.time.utc.value\n", + "\n", + " def set_event(self, dir_x, dir_y, dir_z, detector = \"orca\"):\n", + " zen = np.arcsin(dir_z) + np.pi / 2 # no idea why, but there are crazy coordinate transformations ...\n", + " az = np.arctan(dir_y/dir_x)\n", + " self.direction = local_event(az, self.time, zen, detector)\n", + "\n", + " def get_ra(self, unit=\"deg\"):\n", + " if unit == \"deg\":\n", + " return self.direction.icrs.ra.deg\n", + " else:\n", + " return self.direction.icrs.ra\n", + "\n", + " def get_dec(self, unit=\"deg\"):\n", + " if unit == \"deg\":\n", + " return oe.direction.icrs.dec.deg\n", + " else:\n", + " return self.direction.icrs.dec\n", + "\n", + " def set_energy(self, energy):\n", + " self.energy = energy\n", + "\n", + " def get_energy(self):\n", + " return self.energy" + ] + }, + { + "cell_type": "code", + "execution_count": 345, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Done 0 events.\n", + "Done 100 events.\n", + "Done 200 events.\n", + "Done 300 events.\n", + "Done 400 events.\n", + "Done 500 events.\n", + "Done 600 events.\n", + "Done 700 events.\n", + "Done 800 events.\n", + "Done 900 events.\n", + "Done 1000 events.\n", + "Done 1100 events.\n", + "Done 1200 events.\n", + "Done 1300 events.\n", + "Done 1400 events.\n", + "Done 1500 events.\n", + "Done 1600 events.\n", + "Done 1700 events.\n", + "Done 1800 events.\n", + "Done 1900 events.\n", + "Done 2000 events.\n", + "Done 2100 events.\n", + "Done 2200 events.\n" + ] + } + ], + "source": [ + "evtlist = {\"id\":[], \"energy\": [], \"ra\": [], \"dec\": [], \"time\": []}\n", + "\n", + "for i in range(len(myfile.det_id)):\n", + " if i%100 == 0:\n", + " print (\"Done \", i, \" events.\")\n", + " oe = OpenEvent()\n", + " oe.get_event_from_offlinefile(myfile, i)\n", + " evtlist[\"energy\"].append(oe.get_energy())\n", + " evtlist[\"id\"].append(oe.eventid)\n", + " evtlist[\"ra\"].append(oe.get_ra())\n", + " evtlist[\"dec\"].append(oe.get_dec())\n", + " evtlist[\"time\"].append(oe.get_time_utc()) " + ] + }, + { + "cell_type": "code", + "execution_count": 346, + "metadata": {}, + "outputs": [], + "source": [ + "oel = OpenEventList()\n", + "oel.set_data(evtlist[\"id\"], evtlist[\"time\"], evtlist[\"energy\"], evtlist[\"ra\"], evtlist[\"dec\"])\n", + "oel.set_header()\n", + "oel.write_fits(\"firstlight.fits\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Reading with gammapy" + ] + }, + { + "cell_type": "code", + "execution_count": 347, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "WARNING: AstropyDeprecationWarning: Specified hdu=EVENTS not found, reading in first available table (hdu=1) instead. This will result in an error in future versions! [astropy.io.fits.connect]\n" + ] + } + ], + "source": [ + "from gammapy.data import EventList\n", + "events = EventList.read(\"firstlight.fits\")" + ] + }, + { + "cell_type": "code", + "execution_count": 363, + "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$[0,~1.0056374,~1.0056374,~\\dots,~7041.355,~10204.438,~12634.629] \\; \\mathrm{GeV}$" + ], + "text/plain": [ + "<Quantity [0.00000000e+00, 1.00563741e+00, 1.00563741e+00, ...,\n", + " 7.04135498e+03, 1.02044375e+04, 1.26346289e+04] GeV>" + ] + }, + "execution_count": 363, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "events.energy" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "* astropy tables have description, units and output formats per column!\n", + "* They have table and column metadata" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Open questions\n", + "\n", + "* Granularity between single files: Can events from several detector configurations occur in the same file? -> influences placement of metadata between event identifier and header" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "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.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}