{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Using ctools from Python" ] }, { "cell_type": "raw", "metadata": { "jupyter.source_hidden": true }, "source": [ "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this notebook you will learn how to use the ctools and cscripts from Python instead of typing the commands in the console.\n", "\n", "ctools provides two Python modules that allow using all tools and scripts as Python classes. To use ctools from Python you have to import the `ctools` and `cscripts` modules into Python. You should also import the `gammalib` module, as ctools without GammaLib is generally not very useful.\n", "\n", "__Warning:__ Always import `gammalib` before you import `ctools` and `cscripts`." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import gammalib\n", "import ctools\n", "import cscripts" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Simulating events\n", "\n", "As an example we will simulate an observation of an hour of the Crab nebula." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "sim = ctools.ctobssim()\n", "sim['inmodel'] = '${CTOOLS}/share/models/crab.xml'\n", "sim['outevents'] = 'events.fits'\n", "sim['caldb'] = 'prod2'\n", "sim['irf'] = 'South_0.5h'\n", "sim['ra'] = 83.5\n", "sim['dec'] = 22.8\n", "sim['rad'] = 5.0\n", "sim['tmin'] = '2020-01-01T00:00:00'\n", "sim['tmax'] = '2020-01-01T01:00:00'\n", "sim['emin'] = 0.03\n", "sim['emax'] = 150.0\n", "sim.execute()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The first line generates an instance of the ctobssim tool as a Python class. User parameters are then set using the `[ ]` operator. After setting all parameters the `execute()` method is called to execute the `ctobssim` tool. On output the `events.fits` FITS file is created. Until now everything is analogous to running the tool from the command line, but in Python you can easily combine the different blocks into more complex workflows.\n", "\n", "Remember that you can consult the manual of each tool to find out how it works and to discover all the input parameters that you can set." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\r\n", "ctobssim\r\n", "========\r\n", "\r\n", "Simulate event list(s).\r\n", "\r\n", "\r\n", "Synopsis\r\n", "--------\r\n", "\r\n", "This tool simulates event list(s) using the instrument characteristics \r\n", "specified by the instrument response function(s) and an input model. The \r\n", "simulation includes photon events from astrophysical sources and background\r\n", "events from an instrumental background model.\r\n", "\r\n", "By default, ctobssim creates a single event list. ctobssim queries a pointing\r\n", "direction, the radius of the simulation region, a time interval, an energy\r\n", "interval, an instrumental response function, and an input model. ctobssim uses\r\n", "a numerical random number generator for the simulations with a seed value\r\n", "provided by the hidden seed parameter. Changing this parameter for\r\n", "subsequent runs will lead to different event samples.\r\n", "\r\n", "ctobssim performs a safety check on the maximum photon rate for all model\r\n", "components to avoid that the tool locks up and requests huge memory \r\n", "resources, which may happen if a mistake was made in setting up the input \r\n", "model (for example if an error in the flux units is made). The maximum allowed\r\n", "photon rate is controlled by the hidden maxrate parameter, which by default \r\n", "is set to 1e6.\r\n", "\r\n", "ctobssim can also generate multiple event lists if an observation definition \r\n", "file is specified on input using the hidden inobs parameter. In that \r\n", "case, simulation information will be gathered from the file, and for each \r\n", "observation an event list will be created.\r\n", "\r\n", "For each event file, the simulation parameters will be written as data\r\n", "selection keywords to the FITS header. These keywords are mandatory for any\r\n", "unbinned maximum likelihood analysis of the event data.\r\n", "\r\n", "\r\n", "General parameters\r\n", "------------------\r\n", "\r\n", "inobs [file]\r\n", " Input event list or observation definition XML file. If provided (i.e. the\r\n", " parameter is not blank or NONE), the pointing definition and eventually the\r\n", " response information will be extracted from the input file for event\r\n", " simulation.\r\n", "\r\n", "inmodel [file]\r\n", " Input model XML file.\r\n", "\r\n", "caldb [string]\r\n", " Calibration database.\r\n", "\r\n", "irf [string]\r\n", " Instrumental response function.\r\n", "\r\n", "(edisp = no) [boolean]\r\n", " Apply energy dispersion?\r\n", "\r\n", "outevents [file]\r\n", " Output event list or observation definition XML file.\r\n", "\r\n", "(prefix = sim_events_) [string]\r\n", " Prefix for event list in observation definition XML file.\r\n", "\r\n", "(startindex = 1) [integer]\r\n", " Start index of event list in observation definition XML file.\r\n", "\r\n", "(seed = 1) [integer]\r\n", " Integer seed value to be used for Monte Carlo simulations. Keep this \r\n", " parameter at the same value for repeatable simulations, or increment \r\n", " this value for subsequent runs if non-repeatable simulations are\r\n", " required.\r\n", "\r\n", "ra [real]\r\n", " Right Ascension of CTA pointing (J2000, in degrees).\r\n", "\r\n", "dec [real]\r\n", " Declination of CTA pointing (J2000, in degrees).\r\n", "\r\n", "rad [real]\r\n", " Radius of CTA field of view (simulation cone radius) (in degrees).\r\n", "\r\n", "tmin [time]\r\n", " Start time (UTC string, JD, MJD or MET in seconds).\r\n", "\r\n", "tmax [time]\r\n", " Stop time (UTC string, JD, MJD or MET in seconds).\r\n", "\r\n", "(mjdref = 51544.5) [real]\r\n", " Reference Modified Julian Day (MJD) for simulated events. The times in\r\n", " seconds for each event are counted from this reference time on.\r\n", "\r\n", "emin [real]\r\n", " Lower energy limit of simulated events (in TeV).\r\n", "\r\n", "emax [real]\r\n", " Upper energy limit of simulated events (in TeV).\r\n", "\r\n", "(deadc = 0.95) [real]\r\n", " Average deadtime correction factor.\r\n", "\r\n", "(maxrate = 1.0e6) [real]\r\n", " Maximum photon rate for source models. Source models that exceed this\r\n", " maximum photon rate will lead to an exception as very likely the\r\n", " specified model normalisation is too large (probably due to the\r\n", " a misinterpretation of units). Note that ctools specifies intensity\r\n", " units per MeV.\r\n", "\r\n", "\r\n", "Standard parameters\r\n", "-------------------\r\n", "\r\n", "(nthreads = 0) [integer]\r\n", " Number of parallel processes (0=use all available CPUs).\r\n", "\r\n", "(publish = no) [boolean]\r\n", " Specifies whether the event list(s) should be published on VO Hub.\r\n", "\r\n", "(chatter = 2) [integer]\r\n", " Verbosity of the executable:\r\n", " chatter = 0: no information will be logged\r\n", "\r\n", " chatter = 1: only errors will be logged\r\n", "\r\n", " chatter = 2: errors and actions will be logged\r\n", "\r\n", " chatter = 3: report about the task execution\r\n", "\r\n", " chatter = 4: detailed report about the task execution\r\n", "\r\n", "(clobber = yes) [boolean]\r\n", " Specifies whether existing files should be overwritten.\r\n", "\r\n", "(debug = no) [boolean]\r\n", " Enables debug mode. In debug mode the executable will dump any log file output to the console.\r\n", "\r\n", "(mode = ql) [string]\r\n", " Mode of automatic parameters (default is ql, i.e. \"query and learn\").\r\n", "\r\n", "(logfile = ctobssim.log) [string]\r\n", " Name of log file.\r\n", "\r\n", "\r\n", "Related tools or scripts\r\n", "------------------------\r\n", "\r\n", "csobsdef\r\n" ] } ], "source": [ "!ctobssim --help" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In a Jupyter notebook a code line starting with `!` is executed in the shell, so you can do the operation above just from the command line.\n", "\n", "One of the advantages of using ctools from Python is that you can run a tool using" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "sim.run()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The main difference to the `execute()` method is that the `run()` method will not write the output (i.e., the simulated event list) to disk. Why is this useful? Well, after having typed `sim.run()` the `ctobssim` class still exists as an object in memory, including all the simulated events. You can always save to disk later using the `save()` method.\n", "\n", "The `ctobssim` class has an `obs()` method that returns an observation container that holds the simulated CTA observation with its associated events. To visualise this container, type:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "=== GObservations ===\n", " Number of observations ....: 1\n", " Number of models ..........: 2\n", " Number of observed events .: 204568\n", " Number of predicted events : 0\n" ] } ], "source": [ "print(sim.obs())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There is one CTA observation in the container and to visualise that observation type:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "=== GCTAObservation ===\n", " Name ......................: \n", " Identifier ................: 000001\n", " Instrument ................: CTA\n", " Event file ................: events.fits\n", " Event type ................: EventList\n", " Statistic .................: cstat\n", " Ontime ....................: 3599.99999976158 s\n", " Livetime ..................: 3527.99999976635 s\n", " Deadtime correction .......: 0.98\n", " User energy range .........: undefined\n", "=== GCTAPointing ===\n", " Pointing direction ........: (RA,Dec)=(83.5,22.8)\n", "=== GCTAResponseIrf ===\n", " Caldb mission .............: cta\n", " Caldb instrument ..........: prod2\n", " Response name .............: South_0.5h\n", " Energy dispersion .........: Not used\n", " Safe energy range .........: undefined\n", "=== GCTAEventList ===\n", " Number of events ..........: 204568 (disposed in \"events.fits\")\n", " Time interval .............: 58849.0008007407 - 58849.0424674074 days\n", " Energy interval ...........: 0.03 - 150 TeV\n", " Region of interest ........: RA=83.5, DEC=22.8 [0,0] Radius=5 deg\n", "=== GSkyRegions ===\n", " Number of regions .........: 0\n" ] } ], "source": [ "print(sim.obs()[0])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The observation contains a CTA event list that is implement by the GammaLib class `GCTAEventList`. You can access the event list using the `events()` method. To visualise the individual events you can iterate over the events using a for loop. This will show the simulated celestial coordinates `(RA, DEC)`, the coordinate in the camera system `[DETX, DETY]`, the energies and the terrestrial times (TT) of all events. Let's peek at the first events of the list:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Dir=RA=83.7821807861328, DEC=22.0288944244385 [-0.0134540141482956,0.00456559645656115] Energy=36.9588024914265 GeV Time=315532804.286922 s (TT)\n" ] } ], "source": [ "events = sim.obs()[0].events()\n", "for event in events[:1]:\n", " print(event)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can use this feature to inspect some of the event properties, for example look at their energy spectrum. For this we will use the Python packages matplotlib. If you do not have matplotlib you can use another plotting package of your choice or skip this step." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "