From 6aea9b4e3f1a5c9a166c2f6ee7cd212f04f66cc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Fr=C3=B6se?= Date: Thu, 6 Jul 2023 11:56:27 +0200 Subject: [PATCH] remove more build studd --- .../calibrated_data_exploration.ipynb | 187 ---- docs/tutorials/calibrated_data_exploration.py | 206 ----- .../tutorials/calibrated_data_exploration.rst | 314 ------- ...calibrated_data_exploration_codeobj.pickle | Bin 1557 -> 0 bytes docs/tutorials/coordinates_example.ipynb | 261 ------ docs/tutorials/coordinates_example.py | 414 --------- docs/tutorials/coordinates_example.rst | 531 ------------ .../coordinates_example_codeobj.pickle | Bin 2465 -> 0 bytes docs/tutorials/ctapipe_handson.ipynb | 215 ----- docs/tutorials/ctapipe_handson.py | 254 ------ docs/tutorials/ctapipe_handson.rst | 370 -------- docs/tutorials/ctapipe_handson_codeobj.pickle | Bin 219 -> 0 bytes docs/tutorials/ctapipe_overview.ipynb | 329 ------- docs/tutorials/ctapipe_overview.py | 675 --------------- docs/tutorials/ctapipe_overview.rst | 811 ------------------ .../tutorials/ctapipe_overview_codeobj.pickle | Bin 3630 -> 0 bytes ..._glr_calibrated_data_exploration_thumb.png | Bin 26794 -> 0 bytes .../sphx_glr_coordinates_example_thumb.png | Bin 26794 -> 0 bytes .../thumb/sphx_glr_ctapipe_handson_thumb.png | Bin 26794 -> 0 bytes .../thumb/sphx_glr_ctapipe_overview_thumb.png | Bin 26794 -> 0 bytes .../thumb/sphx_glr_ipynb_to_gallery_thumb.png | Bin 26794 -> 0 bytes .../sphx_glr_raw_data_exploration_thumb.png | Bin 26794 -> 0 bytes .../thumb/sphx_glr_theta_square_thumb.png | Bin 26794 -> 0 bytes docs/tutorials/index.rst | 152 ---- docs/tutorials/raw_data_exploration.ipynb | 381 -------- docs/tutorials/raw_data_exploration.py | 303 ------- docs/tutorials/raw_data_exploration.rst | 483 ----------- .../raw_data_exploration_codeobj.pickle | Bin 1597 -> 0 bytes docs/tutorials/theta_square.ipynb | 97 --- docs/tutorials/theta_square.py | 77 -- docs/tutorials/theta_square.rst | 150 ---- docs/tutorials/theta_square_codeobj.pickle | Bin 1131 -> 0 bytes docs/tutorials/tutorials_jupyter.zip | Bin 73891 -> 0 bytes docs/tutorials/tutorials_python.zip | Bin 54816 -> 0 bytes 34 files changed, 6210 deletions(-) delete mode 100644 docs/tutorials/calibrated_data_exploration.ipynb delete mode 100644 docs/tutorials/calibrated_data_exploration.py delete mode 100644 docs/tutorials/calibrated_data_exploration.rst delete mode 100644 docs/tutorials/calibrated_data_exploration_codeobj.pickle delete mode 100644 docs/tutorials/coordinates_example.ipynb delete mode 100644 docs/tutorials/coordinates_example.py delete mode 100644 docs/tutorials/coordinates_example.rst delete mode 100644 docs/tutorials/coordinates_example_codeobj.pickle delete mode 100644 docs/tutorials/ctapipe_handson.ipynb delete mode 100644 docs/tutorials/ctapipe_handson.py delete mode 100644 docs/tutorials/ctapipe_handson.rst delete mode 100644 docs/tutorials/ctapipe_handson_codeobj.pickle delete mode 100644 docs/tutorials/ctapipe_overview.ipynb delete mode 100644 docs/tutorials/ctapipe_overview.py delete mode 100644 docs/tutorials/ctapipe_overview.rst delete mode 100644 docs/tutorials/ctapipe_overview_codeobj.pickle delete mode 100644 docs/tutorials/images/thumb/sphx_glr_calibrated_data_exploration_thumb.png delete mode 100644 docs/tutorials/images/thumb/sphx_glr_coordinates_example_thumb.png delete mode 100644 docs/tutorials/images/thumb/sphx_glr_ctapipe_handson_thumb.png delete mode 100644 docs/tutorials/images/thumb/sphx_glr_ctapipe_overview_thumb.png delete mode 100644 docs/tutorials/images/thumb/sphx_glr_ipynb_to_gallery_thumb.png delete mode 100644 docs/tutorials/images/thumb/sphx_glr_raw_data_exploration_thumb.png delete mode 100644 docs/tutorials/images/thumb/sphx_glr_theta_square_thumb.png delete mode 100644 docs/tutorials/index.rst delete mode 100644 docs/tutorials/raw_data_exploration.ipynb delete mode 100644 docs/tutorials/raw_data_exploration.py delete mode 100644 docs/tutorials/raw_data_exploration.rst delete mode 100644 docs/tutorials/raw_data_exploration_codeobj.pickle delete mode 100644 docs/tutorials/theta_square.ipynb delete mode 100644 docs/tutorials/theta_square.py delete mode 100644 docs/tutorials/theta_square.rst delete mode 100644 docs/tutorials/theta_square_codeobj.pickle delete mode 100644 docs/tutorials/tutorials_jupyter.zip delete mode 100644 docs/tutorials/tutorials_python.zip diff --git a/docs/tutorials/calibrated_data_exploration.ipynb b/docs/tutorials/calibrated_data_exploration.ipynb deleted file mode 100644 index 1c912983c35..00000000000 --- a/docs/tutorials/calibrated_data_exploration.ipynb +++ /dev/null @@ -1,187 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n# Explore Calibrated Data\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "import numpy as np\nfrom astropy import units as u\nfrom matplotlib import pyplot as plt\n\nimport ctapipe\nfrom ctapipe.instrument import CameraGeometry\nfrom ctapipe.io import EventSeeker, EventSource\nfrom ctapipe.utils.datasets import get_dataset_path\nfrom ctapipe.visualization import CameraDisplay\n\n# %matplotlib inline\nplt.style.use(\"ggplot\")\n\nprint(ctapipe.__version__)\nprint(ctapipe.__file__)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let\u2019s first open a raw event file and get an event out of it:\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "filename = get_dataset_path(\"gamma_prod5.simtel.zst\")\nsource = EventSource(filename, max_events=2)\n\nfor event in source:\n print(event.index.event_id)\n\nfilename\n\nsource\n\nevent\n\nprint(event.r1)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Perform basic calibration:\n\nHere we will use a ``CameraCalibrator`` which is just a simple wrapper\nthat runs the three calibraraton and trace-integration phases of the\npipeline, taking the data from levels:\n\n**R0** \u2192 **R1** \u2192 **DL0** \u2192 **DL1**\n\nYou could of course do these each separately, by using the classes\n``R1Calibrator``, ``DL0Reducer``, and ``DL1Calibrator``. Note that we\nhave not specified any configuration to the ``CameraCalibrator``, so it\nwill be using the default algorithms and thresholds, other than\nspecifying that the product is a \u201cHESSIOR1Calibrator\u201d (hopefully in the\nnear future that will be automatic).\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "from ctapipe.calib import CameraCalibrator\n\ncalib = CameraCalibrator(subarray=source.subarray)\ncalib(event)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now the *r1*, *dl0* and *dl1* containers are filled in the event\n\n- **r1.tel[x]**: contains the \u201cr1-calibrated\u201d waveforms, after\n gain-selection, pedestal subtraciton, and gain-correction\n- **dl0.tel[x]**: is the same but with optional data volume reduction\n (some pixels not filled), in this case this is not performed by\n default, so it is the same as r1\n- **dl1.tel[x]**: contains the (possibly re-calibrated) waveforms as\n dl0, but also the time-integrated *image* that has been calculated\n using a ``ImageExtractor`` (a ``NeighborPeakWindowSum`` by default)\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "for tel_id in event.dl1.tel:\n print(\"TEL{:03}: {}\".format(tel_id, source.subarray.tel[tel_id]))\n print(\" - r0 wave shape : {}\".format(event.r0.tel[tel_id].waveform.shape))\n print(\" - r1 wave shape : {}\".format(event.r1.tel[tel_id].waveform.shape))\n print(\" - dl1 image shape : {}\".format(event.dl1.tel[tel_id].image.shape))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Some image processing:\n\nLet\u2019s look at the image\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "from ctapipe.visualization import CameraDisplay\n\ntel_id = sorted(event.r1.tel.keys())[1]\nsub = source.subarray\ngeometry = sub.tel[tel_id].camera.geometry\nimage = event.dl1.tel[tel_id].image\n\ndisp = CameraDisplay(geometry, image=image)\n\nfrom ctapipe.image import hillas_parameters, tailcuts_clean\n\nmask = tailcuts_clean(\n geometry,\n image,\n picture_thresh=10,\n boundary_thresh=5,\n min_number_picture_neighbors=2,\n)\ncleaned = image.copy()\ncleaned[~mask] = 0\ndisp = CameraDisplay(geometry, image=cleaned)\n\nparams = hillas_parameters(geometry, cleaned)\nprint(params)\nparams\n\nparams = hillas_parameters(geometry, cleaned)\n\nplt.figure(figsize=(10, 10))\ndisp = CameraDisplay(geometry, image=image)\ndisp.add_colorbar()\ndisp.overlay_moments(params, color=\"red\", lw=3)\ndisp.highlight_pixels(mask, color=\"white\", alpha=0.3, linewidth=2)\n\nplt.xlim(params.x.to_value(u.m) - 0.5, params.x.to_value(u.m) + 0.5)\nplt.ylim(params.y.to_value(u.m) - 0.5, params.y.to_value(u.m) + 0.5)\n\nsource.metadata" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## More complex image processing:\n\nLet\u2019s now explore how stereo reconstruction works.\n\n### first, look at a summed image from multiple telescopes\n\nFor this, we want to use a ``CameraDisplay`` again, but since we can\u2019t\nsum and display images with different cameras, we\u2019ll just sub-select\nimages from a particular camera type\n\nThese are the telescopes that are in this event:\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "tels_in_event = set(\n event.dl1.tel.keys()\n) # use a set here, so we can intersect it later\ntels_in_event\n\ncam_ids = set(sub.get_tel_ids_for_type(\"MST_MST_NectarCam\"))\ncam_ids\n\ncams_in_event = tels_in_event.intersection(cam_ids)\nfirst_tel_id = list(cams_in_event)[0]\ntel = sub.tel[first_tel_id]\nprint(\"{}s in event: {}\".format(tel, cams_in_event))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, let\u2019s sum those images:\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "image_sum = np.zeros_like(\n tel.camera.geometry.pix_x.value\n) # just make an array of 0's in the same shape as the camera\n\nfor tel_id in cams_in_event:\n image_sum += event.dl1.tel[tel_id].image" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "And finally display the sum of those images\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "plt.figure(figsize=(8, 8))\n\ndisp = CameraDisplay(tel.camera.geometry, image=image_sum)\ndisp.overlay_moments(params, with_label=False)\nplt.title(\"Sum of {}x {}\".format(len(cams_in_event), tel))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "let\u2019s also show which telescopes those were. Note that currently\nArrayDisplay\u2019s value field is a vector by ``tel_index``, not ``tel_id``,\nso we have to convert to a tel_index. (this may change in a future\nversion to be more user-friendly)\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "from ctapipe.visualization import ArrayDisplay\n\nnectarcam_subarray = sub.select_subarray(cam_ids, name=\"NectarCam\")\n\nhit_pattern = np.zeros(shape=nectarcam_subarray.n_tels)\nhit_pattern[[nectarcam_subarray.tel_indices[x] for x in cams_in_event]] = 100\n\nplt.set_cmap(plt.cm.Accent)\nplt.figure(figsize=(8, 8))\n\nad = ArrayDisplay(nectarcam_subarray)\nad.values = hit_pattern\nad.add_labels()" - ] - } - ], - "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.9.16" - } - }, - "nbformat": 4, - "nbformat_minor": 0 -} \ No newline at end of file diff --git a/docs/tutorials/calibrated_data_exploration.py b/docs/tutorials/calibrated_data_exploration.py deleted file mode 100644 index da235ebe648..00000000000 --- a/docs/tutorials/calibrated_data_exploration.py +++ /dev/null @@ -1,206 +0,0 @@ -""" -Explore Calibrated Data -======================= - -""" - -import numpy as np -from astropy import units as u -from matplotlib import pyplot as plt - -import ctapipe -from ctapipe.instrument import CameraGeometry -from ctapipe.io import EventSeeker, EventSource -from ctapipe.utils.datasets import get_dataset_path -from ctapipe.visualization import CameraDisplay - -# %matplotlib inline -plt.style.use("ggplot") - -print(ctapipe.__version__) -print(ctapipe.__file__) - - -###################################################################### -# Let’s first open a raw event file and get an event out of it: -# - -filename = get_dataset_path("gamma_prod5.simtel.zst") -source = EventSource(filename, max_events=2) - -for event in source: - print(event.index.event_id) - -filename - -source - -event - -print(event.r1) - - -###################################################################### -# Perform basic calibration: -# -------------------------- -# -# Here we will use a ``CameraCalibrator`` which is just a simple wrapper -# that runs the three calibraraton and trace-integration phases of the -# pipeline, taking the data from levels: -# -# **R0** → **R1** → **DL0** → **DL1** -# -# You could of course do these each separately, by using the classes -# ``R1Calibrator``, ``DL0Reducer``, and ``DL1Calibrator``. Note that we -# have not specified any configuration to the ``CameraCalibrator``, so it -# will be using the default algorithms and thresholds, other than -# specifying that the product is a “HESSIOR1Calibrator” (hopefully in the -# near future that will be automatic). -# - -from ctapipe.calib import CameraCalibrator - -calib = CameraCalibrator(subarray=source.subarray) -calib(event) - - -###################################################################### -# Now the *r1*, *dl0* and *dl1* containers are filled in the event -# -# - **r1.tel[x]**: contains the “r1-calibrated” waveforms, after -# gain-selection, pedestal subtraciton, and gain-correction -# - **dl0.tel[x]**: is the same but with optional data volume reduction -# (some pixels not filled), in this case this is not performed by -# default, so it is the same as r1 -# - **dl1.tel[x]**: contains the (possibly re-calibrated) waveforms as -# dl0, but also the time-integrated *image* that has been calculated -# using a ``ImageExtractor`` (a ``NeighborPeakWindowSum`` by default) -# - -for tel_id in event.dl1.tel: - print("TEL{:03}: {}".format(tel_id, source.subarray.tel[tel_id])) - print(" - r0 wave shape : {}".format(event.r0.tel[tel_id].waveform.shape)) - print(" - r1 wave shape : {}".format(event.r1.tel[tel_id].waveform.shape)) - print(" - dl1 image shape : {}".format(event.dl1.tel[tel_id].image.shape)) - - -###################################################################### -# Some image processing: -# ---------------------- -# -# Let’s look at the image -# - -from ctapipe.visualization import CameraDisplay - -tel_id = sorted(event.r1.tel.keys())[1] -sub = source.subarray -geometry = sub.tel[tel_id].camera.geometry -image = event.dl1.tel[tel_id].image - -disp = CameraDisplay(geometry, image=image) - -from ctapipe.image import hillas_parameters, tailcuts_clean - -mask = tailcuts_clean( - geometry, - image, - picture_thresh=10, - boundary_thresh=5, - min_number_picture_neighbors=2, -) -cleaned = image.copy() -cleaned[~mask] = 0 -disp = CameraDisplay(geometry, image=cleaned) - -params = hillas_parameters(geometry, cleaned) -print(params) -params - -params = hillas_parameters(geometry, cleaned) - -plt.figure(figsize=(10, 10)) -disp = CameraDisplay(geometry, image=image) -disp.add_colorbar() -disp.overlay_moments(params, color="red", lw=3) -disp.highlight_pixels(mask, color="white", alpha=0.3, linewidth=2) - -plt.xlim(params.x.to_value(u.m) - 0.5, params.x.to_value(u.m) + 0.5) -plt.ylim(params.y.to_value(u.m) - 0.5, params.y.to_value(u.m) + 0.5) - -source.metadata - - -###################################################################### -# More complex image processing: -# ------------------------------ -# -# Let’s now explore how stereo reconstruction works. -# -# first, look at a summed image from multiple telescopes -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# -# For this, we want to use a ``CameraDisplay`` again, but since we can’t -# sum and display images with different cameras, we’ll just sub-select -# images from a particular camera type -# -# These are the telescopes that are in this event: -# - -tels_in_event = set( - event.dl1.tel.keys() -) # use a set here, so we can intersect it later -tels_in_event - -cam_ids = set(sub.get_tel_ids_for_type("MST_MST_NectarCam")) -cam_ids - -cams_in_event = tels_in_event.intersection(cam_ids) -first_tel_id = list(cams_in_event)[0] -tel = sub.tel[first_tel_id] -print("{}s in event: {}".format(tel, cams_in_event)) - - -###################################################################### -# Now, let’s sum those images: -# - -image_sum = np.zeros_like( - tel.camera.geometry.pix_x.value -) # just make an array of 0's in the same shape as the camera - -for tel_id in cams_in_event: - image_sum += event.dl1.tel[tel_id].image - - -###################################################################### -# And finally display the sum of those images -# - -plt.figure(figsize=(8, 8)) - -disp = CameraDisplay(tel.camera.geometry, image=image_sum) -disp.overlay_moments(params, with_label=False) -plt.title("Sum of {}x {}".format(len(cams_in_event), tel)) - - -###################################################################### -# let’s also show which telescopes those were. Note that currently -# ArrayDisplay’s value field is a vector by ``tel_index``, not ``tel_id``, -# so we have to convert to a tel_index. (this may change in a future -# version to be more user-friendly) -# - -from ctapipe.visualization import ArrayDisplay - -nectarcam_subarray = sub.select_subarray(cam_ids, name="NectarCam") - -hit_pattern = np.zeros(shape=nectarcam_subarray.n_tels) -hit_pattern[[nectarcam_subarray.tel_indices[x] for x in cams_in_event]] = 100 - -plt.set_cmap(plt.cm.Accent) -plt.figure(figsize=(8, 8)) - -ad = ArrayDisplay(nectarcam_subarray) -ad.values = hit_pattern -ad.add_labels() diff --git a/docs/tutorials/calibrated_data_exploration.rst b/docs/tutorials/calibrated_data_exploration.rst deleted file mode 100644 index 14a11c240ff..00000000000 --- a/docs/tutorials/calibrated_data_exploration.rst +++ /dev/null @@ -1,314 +0,0 @@ - -.. DO NOT EDIT. -.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. -.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: -.. "tutorials/calibrated_data_exploration.py" -.. LINE NUMBERS ARE GIVEN BELOW. - -.. only:: html - - .. note:: - :class: sphx-glr-download-link-note - - :ref:`Go to the end ` - to download the full example code - -.. rst-class:: sphx-glr-example-title - -.. _sphx_glr_tutorials_calibrated_data_exploration.py: - - -Explore Calibrated Data -======================= - -.. GENERATED FROM PYTHON SOURCE LINES 6-24 - -.. code-block:: default - - - import numpy as np - from astropy import units as u - from matplotlib import pyplot as plt - - import ctapipe - from ctapipe.instrument import CameraGeometry - from ctapipe.io import EventSeeker, EventSource - from ctapipe.utils.datasets import get_dataset_path - from ctapipe.visualization import CameraDisplay - - # %matplotlib inline - plt.style.use("ggplot") - - print(ctapipe.__version__) - print(ctapipe.__file__) - - - -.. GENERATED FROM PYTHON SOURCE LINES 25-27 - -Let’s first open a raw event file and get an event out of it: - - -.. GENERATED FROM PYTHON SOURCE LINES 27-43 - -.. code-block:: default - - - filename = get_dataset_path("gamma_prod5.simtel.zst") - source = EventSource(filename, max_events=2) - - for event in source: - print(event.index.event_id) - - filename - - source - - event - - print(event.r1) - - - -.. GENERATED FROM PYTHON SOURCE LINES 44-60 - -Perform basic calibration: --------------------------- - -Here we will use a ``CameraCalibrator`` which is just a simple wrapper -that runs the three calibraraton and trace-integration phases of the -pipeline, taking the data from levels: - -**R0** → **R1** → **DL0** → **DL1** - -You could of course do these each separately, by using the classes -``R1Calibrator``, ``DL0Reducer``, and ``DL1Calibrator``. Note that we -have not specified any configuration to the ``CameraCalibrator``, so it -will be using the default algorithms and thresholds, other than -specifying that the product is a “HESSIOR1Calibrator” (hopefully in the -near future that will be automatic). - - -.. GENERATED FROM PYTHON SOURCE LINES 60-67 - -.. code-block:: default - - - from ctapipe.calib import CameraCalibrator - - calib = CameraCalibrator(subarray=source.subarray) - calib(event) - - - -.. GENERATED FROM PYTHON SOURCE LINES 68-79 - -Now the *r1*, *dl0* and *dl1* containers are filled in the event - -- **r1.tel[x]**: contains the “r1-calibrated” waveforms, after - gain-selection, pedestal subtraciton, and gain-correction -- **dl0.tel[x]**: is the same but with optional data volume reduction - (some pixels not filled), in this case this is not performed by - default, so it is the same as r1 -- **dl1.tel[x]**: contains the (possibly re-calibrated) waveforms as - dl0, but also the time-integrated *image* that has been calculated - using a ``ImageExtractor`` (a ``NeighborPeakWindowSum`` by default) - - -.. GENERATED FROM PYTHON SOURCE LINES 79-87 - -.. code-block:: default - - - for tel_id in event.dl1.tel: - print("TEL{:03}: {}".format(tel_id, source.subarray.tel[tel_id])) - print(" - r0 wave shape : {}".format(event.r0.tel[tel_id].waveform.shape)) - print(" - r1 wave shape : {}".format(event.r1.tel[tel_id].waveform.shape)) - print(" - dl1 image shape : {}".format(event.dl1.tel[tel_id].image.shape)) - - - -.. GENERATED FROM PYTHON SOURCE LINES 88-93 - -Some image processing: ----------------------- - -Let’s look at the image - - -.. GENERATED FROM PYTHON SOURCE LINES 93-134 - -.. code-block:: default - - - from ctapipe.visualization import CameraDisplay - - tel_id = sorted(event.r1.tel.keys())[1] - sub = source.subarray - geometry = sub.tel[tel_id].camera.geometry - image = event.dl1.tel[tel_id].image - - disp = CameraDisplay(geometry, image=image) - - from ctapipe.image import hillas_parameters, tailcuts_clean - - mask = tailcuts_clean( - geometry, - image, - picture_thresh=10, - boundary_thresh=5, - min_number_picture_neighbors=2, - ) - cleaned = image.copy() - cleaned[~mask] = 0 - disp = CameraDisplay(geometry, image=cleaned) - - params = hillas_parameters(geometry, cleaned) - print(params) - params - - params = hillas_parameters(geometry, cleaned) - - plt.figure(figsize=(10, 10)) - disp = CameraDisplay(geometry, image=image) - disp.add_colorbar() - disp.overlay_moments(params, color="red", lw=3) - disp.highlight_pixels(mask, color="white", alpha=0.3, linewidth=2) - - plt.xlim(params.x.to_value(u.m) - 0.5, params.x.to_value(u.m) + 0.5) - plt.ylim(params.y.to_value(u.m) - 0.5, params.y.to_value(u.m) + 0.5) - - source.metadata - - - -.. GENERATED FROM PYTHON SOURCE LINES 135-149 - -More complex image processing: ------------------------------- - -Let’s now explore how stereo reconstruction works. - -first, look at a summed image from multiple telescopes -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -For this, we want to use a ``CameraDisplay`` again, but since we can’t -sum and display images with different cameras, we’ll just sub-select -images from a particular camera type - -These are the telescopes that are in this event: - - -.. GENERATED FROM PYTHON SOURCE LINES 149-164 - -.. code-block:: default - - - tels_in_event = set( - event.dl1.tel.keys() - ) # use a set here, so we can intersect it later - tels_in_event - - cam_ids = set(sub.get_tel_ids_for_type("MST_MST_NectarCam")) - cam_ids - - cams_in_event = tels_in_event.intersection(cam_ids) - first_tel_id = list(cams_in_event)[0] - tel = sub.tel[first_tel_id] - print("{}s in event: {}".format(tel, cams_in_event)) - - - -.. GENERATED FROM PYTHON SOURCE LINES 165-167 - -Now, let’s sum those images: - - -.. GENERATED FROM PYTHON SOURCE LINES 167-176 - -.. code-block:: default - - - image_sum = np.zeros_like( - tel.camera.geometry.pix_x.value - ) # just make an array of 0's in the same shape as the camera - - for tel_id in cams_in_event: - image_sum += event.dl1.tel[tel_id].image - - - -.. GENERATED FROM PYTHON SOURCE LINES 177-179 - -And finally display the sum of those images - - -.. GENERATED FROM PYTHON SOURCE LINES 179-187 - -.. code-block:: default - - - plt.figure(figsize=(8, 8)) - - disp = CameraDisplay(tel.camera.geometry, image=image_sum) - disp.overlay_moments(params, with_label=False) - plt.title("Sum of {}x {}".format(len(cams_in_event), tel)) - - - -.. GENERATED FROM PYTHON SOURCE LINES 188-193 - -let’s also show which telescopes those were. Note that currently -ArrayDisplay’s value field is a vector by ``tel_index``, not ``tel_id``, -so we have to convert to a tel_index. (this may change in a future -version to be more user-friendly) - - -.. GENERATED FROM PYTHON SOURCE LINES 193-207 - -.. code-block:: default - - - from ctapipe.visualization import ArrayDisplay - - nectarcam_subarray = sub.select_subarray(cam_ids, name="NectarCam") - - hit_pattern = np.zeros(shape=nectarcam_subarray.n_tels) - hit_pattern[[nectarcam_subarray.tel_indices[x] for x in cams_in_event]] = 100 - - plt.set_cmap(plt.cm.Accent) - plt.figure(figsize=(8, 8)) - - ad = ArrayDisplay(nectarcam_subarray) - ad.values = hit_pattern - ad.add_labels() - - -.. rst-class:: sphx-glr-timing - - **Total running time of the script:** ( 0 minutes 0.000 seconds) - - -.. _sphx_glr_download_tutorials_calibrated_data_exploration.py: - -.. only:: html - - .. container:: sphx-glr-footer sphx-glr-footer-example - - - - - .. container:: sphx-glr-download sphx-glr-download-python - - :download:`Download Python source code: calibrated_data_exploration.py ` - - .. container:: sphx-glr-download sphx-glr-download-jupyter - - :download:`Download Jupyter notebook: calibrated_data_exploration.ipynb ` - - -.. only:: html - - .. rst-class:: sphx-glr-signature - - `Gallery generated by Sphinx-Gallery `_ diff --git a/docs/tutorials/calibrated_data_exploration_codeobj.pickle b/docs/tutorials/calibrated_data_exploration_codeobj.pickle deleted file mode 100644 index 831c6447cea48d44b7ccd3631558398d12867798..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1557 zcmbVMO>5gg5N%29D3%o*(vM$IXfL9d{(zA5Rwy**A~x%dHFPB{yR#+=6nZu2*6si8 ztSzl2+i6LBv1Uf|=FQu;`ZfA98NXQnnwVEo3XV{f#x?O*Jr`QcuYsfc?LK^S@0%l= z7Vf+INsq@RD}-xa7Ooi=)!a%75@t|Ws!nYQND$LaAv1ZUalaga$+%?3xK$I=v$$6h zIG|fu*31?HvpGX%=wC6+H*@oo1C{)=dBc$@P$IPm(xh#pae3S%gObaWRet6tOq9g* z4i;96fIV(wLOd@RDp{d~+f>#5$%7rrc7VwhNut>`7$sR9Fn7`f{kmhc1Y?=G6_Gn%T0PY>K&D~P_^&;6gtmy zkYptCiKZh!njc0VC_QPfQ?EDzlE2r+Cj*W)A;BDS!@oT;+j!)PPW@IhtaL!#uk?9x z-!Ra>&2;)lop=FowARhrVk_B~AldX%YgX@ib(p2r#|-&@tHz&~qQslZYQB|jkR`__. -# -# Pointing direction of telescopes or the origin of a simulated shower are -# described in the ``AltAz`` frame. This is a local, angular coordinate -# frame, with angles ``altitude`` and ``azimuth``. Altitude is the -# measured from the Horizon (0°) to the Zenith (90°). For the azimuth, -# there are different conventions. In Astropy und thus ctapipe, Azimuth is -# oriented East of North (i.e., N=0°, E=90°). -# - -from astropy.coordinates import EarthLocation -from astropy.time import Time - -obstime = Time("2013-11-01T03:00") -location = EarthLocation.of_site("Roque de los Muchachos") - -altaz = AltAz(location=location, obstime=obstime) - -array_pointing = SkyCoord( - alt=event.pointing.array_azimuth, - az=event.pointing.array_altitude, - frame=altaz, -) - -print(array_pointing) - - -###################################################################### -# CameraFrame -# ----------- -# -# Camera coordinate frame. -# -# The camera frame is a 2d cartesian frame, describing position of objects -# in the focal plane of the telescope. -# -# The frame is defined as in H.E.S.S., starting at the horizon, the -# telescope is pointed to magnetic north in azimuth and then up to zenith. -# -# Now, x points north and y points west, so in this orientation, the -# camera coordinates line up with the CORSIKA ground coordinate system. -# -# MAGIC and FACT use a different camera coordinate system: Standing at the -# dish, looking at the camera, x points right, y points up. To transform -# MAGIC/FACT to ctapipe, do x’ = -y, y’ = -x. -# -# **Typical usage**: Position of pixels in the focal plane. -# - -geometry = source.subarray.tel[tel_id].camera.geometry -pix_x = geometry.pix_x -pix_y = geometry.pix_y -focal_length = source.subarray.tel[tel_id].optics.equivalent_focal_length - -telescope_pointing = SkyCoord( - alt=event.pointing.tel[tel_id].altitude, - az=event.pointing.tel[tel_id].azimuth, - frame=altaz, -) - -camera_frame = CameraFrame( - focal_length=focal_length, - rotation=0 * u.deg, - telescope_pointing=telescope_pointing, -) - -cam_coords = SkyCoord(x=pix_x, y=pix_y, frame=camera_frame) - -print(cam_coords) - -plt.scatter(cam_coords.x, cam_coords.y) -plt.title(f"Camera type: {geometry.name}") -plt.xlabel(f"x / {cam_coords.x.unit}") -plt.ylabel(f"y / {cam_coords.y.unit}") -plt.axis("square") - - -###################################################################### -# The implementation of the coordinate system with astropy makes it easier -# to use time of the observation and location of the observing site, to -# understand, for example which stars are visible during a certain night -# and how they might be visible in the camera. -# - -from ctapipe.instrument import SubarrayDescription -from ctapipe.visualization import CameraDisplay - -location = EarthLocation.of_site("Roque de los Muchachos") -obstime = Time("2018-11-01T04:00") - -crab = SkyCoord.from_name("crab nebula") - -altaz = AltAz(location=location, obstime=obstime) - -pointing = crab.transform_to(altaz) - -camera_frame = CameraFrame( - telescope_pointing=pointing, - focal_length=focal_length, - obstime=obstime, - location=location, -) - - -subarray = SubarrayDescription.read("dataset://gamma_prod5.simtel.zst") -cam = subarray.tel[1].camera.geometry -fig, ax = plt.subplots() -display = CameraDisplay(cam, ax=ax) - -ax.set_title( - f"La Palma, {obstime}, az={pointing.az.deg:.1f}°, zenith={pointing.zen.deg:.1f}°, camera={geometry.name}" -) - -for i, name in enumerate(["crab nebula", "o tau", "zet tau"]): - star = SkyCoord.from_name(name) - star_cam = star.transform_to(camera_frame) - - x = star_cam.x.to_value(u.m) - y = star_cam.y.to_value(u.m) - - ax.plot(x, y, marker="*", color=f"C{i}") - ax.annotate( - name, - xy=(x, y), - xytext=(5, 5), - textcoords="offset points", - color=f"C{i}", - ) - -plt.show() - - -###################################################################### -# TelescopeFrame -# -------------- -# -# Telescope coordinate frame. A ``Frame`` using a -# ``UnitSphericalRepresentation``. -# -# This is basically the same as a ``HorizonCoordinate``, but the origin is -# at the telescope’s pointing direction. This is what astropy calls a -# ``SkyOffsetFrame``. -# -# The axis of the telescope frame, ``fov_lon`` and ``fov_lat``, are -# aligned with the horizontal system’s azimuth and altitude respectively. -# -# Pointing corrections should applied to the transformation between this -# frame and the camera frame. -# - -telescope_frame = TelescopeFrame( - telescope_pointing=pointing, - obstime=pointing.obstime, - location=pointing.location, -) -telescope_coords = cam_coords.transform_to(telescope_frame) - -wrap_angle = telescope_pointing.az + 180 * u.deg - -plt.axis("equal") -plt.scatter( - telescope_coords.fov_lon.deg, telescope_coords.fov_lat.deg, alpha=0.2, color="gray" -) - - -for i, name in enumerate(["crab nebula", "o tau", "zet tau"]): - star = SkyCoord.from_name(name) - star_tel = star.transform_to(telescope_frame) - - plt.plot(star_tel.fov_lon.deg, star_tel.fov_lat.deg, "*", ms=10) - plt.annotate( - name, - xy=(star_tel.fov_lon.deg, star_tel.fov_lat.deg), - xytext=(5, 5), - textcoords="offset points", - color=f"C{i}", - ) - -plt.xlabel("fov_lon / {}".format(telescope_coords.altaz.az.unit)) -plt.ylabel("fov_lat / {}".format(telescope_coords.altaz.alt.unit)) - - -###################################################################### -# NominalFrame -# ------------ -# -# Nominal coordinate frame. A Frame using a -# ``UnitSphericalRepresentation``. This is basically the same as a -# ``HorizonCoordinate``, but the origin is at an arbitray position in the -# sky. This is what astropy calls a ``SkyOffsetFrame`` If the telescopes -# are in divergent pointing, this ``Frame`` can be used to transform to a -# common system. - 2D reconstruction (``HillasIntersector``) is performed -# in this frame - 3D reconstruction (``HillasReconstructor``) doesn’t need -# this frame -# - - -###################################################################### -# Let’s play a bit with 3 LSTs with divergent pointing -# - -location = EarthLocation.of_site("Roque de los Muchachos") -obstime = Time("2018-11-01T02:00") -altaz = AltAz(location=location, obstime=obstime) - -crab = SkyCoord.from_name("crab nebula") - -# let's observe crab -array_pointing = crab.transform_to(altaz) - - -# let the telescopes point to different positions -alt_offsets = u.Quantity([1, -1, -1], u.deg) -az_offsets = u.Quantity([0, -2, +2], u.deg) - - -tel_pointings = SkyCoord( - alt=array_pointing.alt + alt_offsets, - az=array_pointing.az + az_offsets, - frame=altaz, -) - -camera_frames = CameraFrame( - telescope_pointing=tel_pointings, # multiple pointings, so we get multiple frames - focal_length=focal_length, - obstime=obstime, - location=location, -) - -nom_frame = NominalFrame(origin=array_pointing, obstime=obstime, location=location) - -fig, ax = plt.subplots(figsize=(15, 10)) -ax.set_aspect(1) - -for i in range(3): - cam_coord = SkyCoord(x=pix_x, y=pix_y, frame=camera_frames[i]) - nom_coord = cam_coord.transform_to(nom_frame) - - ax.scatter( - x=nom_coord.fov_lon.deg, - y=nom_coord.fov_lat.deg, - label=f"Telescope {i + 1}", - s=30, - alpha=0.15, - ) - - -for i, name in enumerate(["Crab", "o tau", "zet tau"]): - s = SkyCoord.from_name(name) - s_nom = s.transform_to(nom_frame) - ax.plot( - s_nom.fov_lon.deg, - s_nom.fov_lat.deg, - "*", - ms=10, - ) - ax.annotate( - name, - xy=(s_nom.fov_lon.deg, s_nom.fov_lat.deg), - xytext=(5, 5), - textcoords="offset points", - color=f"C{i}", - ) - - -ax.set_xlabel(f"fov_lon / deg") -ax.set_ylabel(f"fov_lat / deg") - -ax.legend() -plt.show() - - -###################################################################### -# GroundFrame -# ----------- -# -# Ground coordinate frame. The ground coordinate frame is a simple -# cartesian frame describing the 3 dimensional position of objects -# compared to the array ground level in relation to the nomial centre of -# the array. Typically this frame will be used for describing the position -# on telescopes and equipment -# -# **Typical usage**: positions of telescopes on the ground (x, y, z) -# - -source.subarray.peek() - - -###################################################################### -# In case a layout is selected, the following line will produce a -# different output from the picture above. -# - -source.subarray.select_subarray(layout, name="Prod3b layout").peek() - - -###################################################################### -# .. figure:: ground_frame.png -# :alt: Ground Frame -# -# Ground Frame -# - - -###################################################################### -# In this image all the telescope from the ``gamma_test.simtel.gz`` file -# are plotted as spheres in the GroundFrame. -# - - -###################################################################### -# TiltedGroundFrame -# ----------------- -# - - -###################################################################### -# Tilted ground coordinate frame. -# -# The tilted ground coordinate frame is a cartesian system describing the -# 2 dimensional projected positions of objects in a tilted plane described -# by pointing_direction. The plane is rotated along the z_axis by the -# azimuth of the ``pointing_direction`` and then it is inclined with an -# angle equal to the zenith angle of the ``pointing_direction``. -# -# This frame is used for the reconstruction of the shower core position. -# - - -###################################################################### -# .. figure:: tilted_ground_frame.png -# :alt: Tilted Ground Frame -# -# Tilted Ground Frame -# - - -###################################################################### -# This image picture both the telescopes in the GroundFrame (red) and in -# the TiltedGroundFrame (green) are displayed: in this case since the -# azimuth of the ``pointing_direction`` is 0 degrees, then the plane is -# just tilted according to the zenith angle. -# -# For playing with these and with more 3D models of the telescopes -# themselves, have a look at the -# `CREED_VTK `__ library. -# diff --git a/docs/tutorials/coordinates_example.rst b/docs/tutorials/coordinates_example.rst deleted file mode 100644 index 03dc4707d46..00000000000 --- a/docs/tutorials/coordinates_example.rst +++ /dev/null @@ -1,531 +0,0 @@ - -.. DO NOT EDIT. -.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. -.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: -.. "tutorials/coordinates_example.py" -.. LINE NUMBERS ARE GIVEN BELOW. - -.. only:: html - - .. note:: - :class: sphx-glr-download-link-note - - :ref:`Go to the end ` - to download the full example code - -.. rst-class:: sphx-glr-example-title - -.. _sphx_glr_tutorials_coordinates_example.py: - - -Coordinates usage in ctapipe -============================ - -.. GENERATED FROM PYTHON SOURCE LINES 6-34 - -.. code-block:: default - - - import copy - - import astropy.units as u - import matplotlib.pyplot as plt - import numpy as np - from astropy.coordinates import AltAz, SkyCoord - - from ctapipe.calib import CameraCalibrator - from ctapipe.coordinates import ( - CameraFrame, - GroundFrame, - NominalFrame, - TelescopeFrame, - TiltedGroundFrame, - ) - from ctapipe.io import EventSource - from ctapipe.utils import get_dataset_path - from ctapipe.visualization import ArrayDisplay - - # %matplotlib inline - - - # make plots and fonts larger - plt.rcParams["figure.figsize"] = (12, 8) - plt.rcParams["font.size"] = 16 - - - -.. GENERATED FROM PYTHON SOURCE LINES 35-38 - -Open test dataset ------------------ - - -.. GENERATED FROM PYTHON SOURCE LINES 38-48 - -.. code-block:: default - - - filename = get_dataset_path("gamma_prod5.simtel.zst") - source = EventSource(filename) - - events = [copy.deepcopy(event) for event in source] - event = events[4] - - layout = set(source.subarray.tel_ids) - - - -.. GENERATED FROM PYTHON SOURCE LINES 49-52 - -Choose event with LST -~~~~~~~~~~~~~~~~~~~~~ - - -.. GENERATED FROM PYTHON SOURCE LINES 55-58 - -This ensures that the telescope is not “parked” (as it would be in an -event where it is not triggered) but is actually pointing to a source. - - -.. GENERATED FROM PYTHON SOURCE LINES 58-63 - -.. code-block:: default - - - print(f"Telescope with data: {event.r1.tel.keys()}") - tel_id = 3 - - - -.. GENERATED FROM PYTHON SOURCE LINES 64-77 - -AltAz ------ - -See `Astropy Docs on -AltAz `__. - -Pointing direction of telescopes or the origin of a simulated shower are -described in the ``AltAz`` frame. This is a local, angular coordinate -frame, with angles ``altitude`` and ``azimuth``. Altitude is the -measured from the Horizon (0°) to the Zenith (90°). For the azimuth, -there are different conventions. In Astropy und thus ctapipe, Azimuth is -oriented East of North (i.e., N=0°, E=90°). - - -.. GENERATED FROM PYTHON SOURCE LINES 77-95 - -.. code-block:: default - - - from astropy.coordinates import EarthLocation - from astropy.time import Time - - obstime = Time("2013-11-01T03:00") - location = EarthLocation.of_site("Roque de los Muchachos") - - altaz = AltAz(location=location, obstime=obstime) - - array_pointing = SkyCoord( - alt=event.pointing.array_azimuth, - az=event.pointing.array_altitude, - frame=altaz, - ) - - print(array_pointing) - - - -.. GENERATED FROM PYTHON SOURCE LINES 96-116 - -CameraFrame ------------ - -Camera coordinate frame. - -The camera frame is a 2d cartesian frame, describing position of objects -in the focal plane of the telescope. - -The frame is defined as in H.E.S.S., starting at the horizon, the -telescope is pointed to magnetic north in azimuth and then up to zenith. - -Now, x points north and y points west, so in this orientation, the -camera coordinates line up with the CORSIKA ground coordinate system. - -MAGIC and FACT use a different camera coordinate system: Standing at the -dish, looking at the camera, x points right, y points up. To transform -MAGIC/FACT to ctapipe, do x’ = -y, y’ = -x. - -**Typical usage**: Position of pixels in the focal plane. - - -.. GENERATED FROM PYTHON SOURCE LINES 116-145 - -.. code-block:: default - - - geometry = source.subarray.tel[tel_id].camera.geometry - pix_x = geometry.pix_x - pix_y = geometry.pix_y - focal_length = source.subarray.tel[tel_id].optics.equivalent_focal_length - - telescope_pointing = SkyCoord( - alt=event.pointing.tel[tel_id].altitude, - az=event.pointing.tel[tel_id].azimuth, - frame=altaz, - ) - - camera_frame = CameraFrame( - focal_length=focal_length, - rotation=0 * u.deg, - telescope_pointing=telescope_pointing, - ) - - cam_coords = SkyCoord(x=pix_x, y=pix_y, frame=camera_frame) - - print(cam_coords) - - plt.scatter(cam_coords.x, cam_coords.y) - plt.title(f"Camera type: {geometry.name}") - plt.xlabel(f"x / {cam_coords.x.unit}") - plt.ylabel(f"y / {cam_coords.y.unit}") - plt.axis("square") - - - -.. GENERATED FROM PYTHON SOURCE LINES 146-151 - -The implementation of the coordinate system with astropy makes it easier -to use time of the observation and location of the observing site, to -understand, for example which stars are visible during a certain night -and how they might be visible in the camera. - - -.. GENERATED FROM PYTHON SOURCE LINES 151-200 - -.. code-block:: default - - - from ctapipe.instrument import SubarrayDescription - from ctapipe.visualization import CameraDisplay - - location = EarthLocation.of_site("Roque de los Muchachos") - obstime = Time("2018-11-01T04:00") - - crab = SkyCoord.from_name("crab nebula") - - altaz = AltAz(location=location, obstime=obstime) - - pointing = crab.transform_to(altaz) - - camera_frame = CameraFrame( - telescope_pointing=pointing, - focal_length=focal_length, - obstime=obstime, - location=location, - ) - - - subarray = SubarrayDescription.read("dataset://gamma_prod5.simtel.zst") - cam = subarray.tel[1].camera.geometry - fig, ax = plt.subplots() - display = CameraDisplay(cam, ax=ax) - - ax.set_title( - f"La Palma, {obstime}, az={pointing.az.deg:.1f}°, zenith={pointing.zen.deg:.1f}°, camera={geometry.name}" - ) - - for i, name in enumerate(["crab nebula", "o tau", "zet tau"]): - star = SkyCoord.from_name(name) - star_cam = star.transform_to(camera_frame) - - x = star_cam.x.to_value(u.m) - y = star_cam.y.to_value(u.m) - - ax.plot(x, y, marker="*", color=f"C{i}") - ax.annotate( - name, - xy=(x, y), - xytext=(5, 5), - textcoords="offset points", - color=f"C{i}", - ) - - plt.show() - - - -.. GENERATED FROM PYTHON SOURCE LINES 201-217 - -TelescopeFrame --------------- - -Telescope coordinate frame. A ``Frame`` using a -``UnitSphericalRepresentation``. - -This is basically the same as a ``HorizonCoordinate``, but the origin is -at the telescope’s pointing direction. This is what astropy calls a -``SkyOffsetFrame``. - -The axis of the telescope frame, ``fov_lon`` and ``fov_lat``, are -aligned with the horizontal system’s azimuth and altitude respectively. - -Pointing corrections should applied to the transformation between this -frame and the camera frame. - - -.. GENERATED FROM PYTHON SOURCE LINES 217-250 - -.. code-block:: default - - - telescope_frame = TelescopeFrame( - telescope_pointing=pointing, - obstime=pointing.obstime, - location=pointing.location, - ) - telescope_coords = cam_coords.transform_to(telescope_frame) - - wrap_angle = telescope_pointing.az + 180 * u.deg - - plt.axis("equal") - plt.scatter( - telescope_coords.fov_lon.deg, telescope_coords.fov_lat.deg, alpha=0.2, color="gray" - ) - - - for i, name in enumerate(["crab nebula", "o tau", "zet tau"]): - star = SkyCoord.from_name(name) - star_tel = star.transform_to(telescope_frame) - - plt.plot(star_tel.fov_lon.deg, star_tel.fov_lat.deg, "*", ms=10) - plt.annotate( - name, - xy=(star_tel.fov_lon.deg, star_tel.fov_lat.deg), - xytext=(5, 5), - textcoords="offset points", - color=f"C{i}", - ) - - plt.xlabel("fov_lon / {}".format(telescope_coords.altaz.az.unit)) - plt.ylabel("fov_lat / {}".format(telescope_coords.altaz.alt.unit)) - - - -.. GENERATED FROM PYTHON SOURCE LINES 251-263 - -NominalFrame ------------- - -Nominal coordinate frame. A Frame using a -``UnitSphericalRepresentation``. This is basically the same as a -``HorizonCoordinate``, but the origin is at an arbitray position in the -sky. This is what astropy calls a ``SkyOffsetFrame`` If the telescopes -are in divergent pointing, this ``Frame`` can be used to transform to a -common system. - 2D reconstruction (``HillasIntersector``) is performed -in this frame - 3D reconstruction (``HillasReconstructor``) doesn’t need -this frame - - -.. GENERATED FROM PYTHON SOURCE LINES 266-268 - -Let’s play a bit with 3 LSTs with divergent pointing - - -.. GENERATED FROM PYTHON SOURCE LINES 268-340 - -.. code-block:: default - - - location = EarthLocation.of_site("Roque de los Muchachos") - obstime = Time("2018-11-01T02:00") - altaz = AltAz(location=location, obstime=obstime) - - crab = SkyCoord.from_name("crab nebula") - - # let's observe crab - array_pointing = crab.transform_to(altaz) - - - # let the telescopes point to different positions - alt_offsets = u.Quantity([1, -1, -1], u.deg) - az_offsets = u.Quantity([0, -2, +2], u.deg) - - - tel_pointings = SkyCoord( - alt=array_pointing.alt + alt_offsets, - az=array_pointing.az + az_offsets, - frame=altaz, - ) - - camera_frames = CameraFrame( - telescope_pointing=tel_pointings, # multiple pointings, so we get multiple frames - focal_length=focal_length, - obstime=obstime, - location=location, - ) - - nom_frame = NominalFrame(origin=array_pointing, obstime=obstime, location=location) - - fig, ax = plt.subplots(figsize=(15, 10)) - ax.set_aspect(1) - - for i in range(3): - cam_coord = SkyCoord(x=pix_x, y=pix_y, frame=camera_frames[i]) - nom_coord = cam_coord.transform_to(nom_frame) - - ax.scatter( - x=nom_coord.fov_lon.deg, - y=nom_coord.fov_lat.deg, - label=f"Telescope {i + 1}", - s=30, - alpha=0.15, - ) - - - for i, name in enumerate(["Crab", "o tau", "zet tau"]): - s = SkyCoord.from_name(name) - s_nom = s.transform_to(nom_frame) - ax.plot( - s_nom.fov_lon.deg, - s_nom.fov_lat.deg, - "*", - ms=10, - ) - ax.annotate( - name, - xy=(s_nom.fov_lon.deg, s_nom.fov_lat.deg), - xytext=(5, 5), - textcoords="offset points", - color=f"C{i}", - ) - - - ax.set_xlabel(f"fov_lon / deg") - ax.set_ylabel(f"fov_lat / deg") - - ax.legend() - plt.show() - - - -.. GENERATED FROM PYTHON SOURCE LINES 341-352 - -GroundFrame ------------ - -Ground coordinate frame. The ground coordinate frame is a simple -cartesian frame describing the 3 dimensional position of objects -compared to the array ground level in relation to the nomial centre of -the array. Typically this frame will be used for describing the position -on telescopes and equipment - -**Typical usage**: positions of telescopes on the ground (x, y, z) - - -.. GENERATED FROM PYTHON SOURCE LINES 352-356 - -.. code-block:: default - - - source.subarray.peek() - - - -.. GENERATED FROM PYTHON SOURCE LINES 357-360 - -In case a layout is selected, the following line will produce a -different output from the picture above. - - -.. GENERATED FROM PYTHON SOURCE LINES 360-364 - -.. code-block:: default - - - source.subarray.select_subarray(layout, name="Prod3b layout").peek() - - - -.. GENERATED FROM PYTHON SOURCE LINES 365-370 - -.. figure:: ground_frame.png - :alt: Ground Frame - - Ground Frame - - -.. GENERATED FROM PYTHON SOURCE LINES 373-376 - -In this image all the telescope from the ``gamma_test.simtel.gz`` file -are plotted as spheres in the GroundFrame. - - -.. GENERATED FROM PYTHON SOURCE LINES 379-382 - -TiltedGroundFrame ------------------ - - -.. GENERATED FROM PYTHON SOURCE LINES 385-395 - -Tilted ground coordinate frame. - -The tilted ground coordinate frame is a cartesian system describing the -2 dimensional projected positions of objects in a tilted plane described -by pointing_direction. The plane is rotated along the z_axis by the -azimuth of the ``pointing_direction`` and then it is inclined with an -angle equal to the zenith angle of the ``pointing_direction``. - -This frame is used for the reconstruction of the shower core position. - - -.. GENERATED FROM PYTHON SOURCE LINES 398-403 - -.. figure:: tilted_ground_frame.png - :alt: Tilted Ground Frame - - Tilted Ground Frame - - -.. GENERATED FROM PYTHON SOURCE LINES 406-415 - -This image picture both the telescopes in the GroundFrame (red) and in -the TiltedGroundFrame (green) are displayed: in this case since the -azimuth of the ``pointing_direction`` is 0 degrees, then the plane is -just tilted according to the zenith angle. - -For playing with these and with more 3D models of the telescopes -themselves, have a look at the -`CREED_VTK `__ library. - - - -.. rst-class:: sphx-glr-timing - - **Total running time of the script:** ( 0 minutes 0.000 seconds) - - -.. _sphx_glr_download_tutorials_coordinates_example.py: - -.. only:: html - - .. container:: sphx-glr-footer sphx-glr-footer-example - - - - - .. container:: sphx-glr-download sphx-glr-download-python - - :download:`Download Python source code: coordinates_example.py ` - - .. container:: sphx-glr-download sphx-glr-download-jupyter - - :download:`Download Jupyter notebook: coordinates_example.ipynb ` - - -.. only:: html - - .. rst-class:: sphx-glr-signature - - `Gallery generated by Sphinx-Gallery `_ diff --git a/docs/tutorials/coordinates_example_codeobj.pickle b/docs/tutorials/coordinates_example_codeobj.pickle deleted file mode 100644 index 077b7bfb737bc97f5a8001ae9809e4da23e290bd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2465 zcmbuB&u`N(6vsiNTidh~Fimja!exSsbLYgg772m)u~pnq<)&U^;lz=DjAarMM<(?~ z;LL>!e$z85-Z9xSQ4V&&e}^Q&PS!KYqUZTeB0%5luFl;zbtglBS*Ga6G>UTHiJhvy_yr(BD8kxR0>DkhzI*DX$YnS`rh z|0>xtpsq%5HO>@OMfFa=X?q1AeJqvWd4Y6Bl{B1n#i81#ABto1nl;EP0NQt;<*fi* zv+kgsoGAp^!DiYmhxA%i2*^7rRypH}(Fw{6^JMaCQXQ^ma5&4jf=YN|+bdf^+Xf1? z{OEy!jkbcdG@6o`C*3jufYvvCa~W=Fl=|s6(|?v zxMK8P@e~exwra^$6&7gr-rqcFcUZ)4FkD9UhP1u1aZ|eWky-kBS>If&`DPJsBsICo zy?ba+L}(aAgs=auTnJksgAsMtE_8Mk0jTF1MVVnJ%bMUavhJ}rgu6z9>b}^fE$+H| z4V?*|j_pT)!**&3(tF_2TRK^gn{Cd5AHE2~M5$apiJ~cwC35q)m_;Ouq{0(MBKVew z+{iM~9wR7GY2EjMjUa`m|I0OL{)N^iscN;==fwf9E{(M WUihlt+w=oSZEuxj7W(BD(&#s6b-0QE diff --git a/docs/tutorials/ctapipe_handson.ipynb b/docs/tutorials/ctapipe_handson.ipynb deleted file mode 100644 index 86a17e91bbf..00000000000 --- a/docs/tutorials/ctapipe_handson.ipynb +++ /dev/null @@ -1,215 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n# SyntaxError\n\nExample script with invalid Python syntax\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "\"\"\"\nGetting Started with ctapipe\n============================\n\nThis hands-on was presented at the Paris CTA Consoritum meeting (K.\nKosack)\n\n\"\"\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Part 1: load and loop over data\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "import numpy as np\nfrom matplotlib import pyplot as plt\n\nfrom ctapipe import utils\nfrom ctapipe.io import EventSource\n\n# %matplotlib inline\n\npath = utils.get_dataset_path(\"gamma_prod5.simtel.zst\")\n\nsource = EventSource(path, max_events=5)\n\nfor event in source:\n print(event.count, event.index.event_id, event.simulation.shower.energy)\n\nevent\n\nevent.r1\n\nfor event in EventSource(path, max_events=5):\n print(event.count, event.r1.tel.keys())\n\nevent.r0.tel[3]\n\nr0tel = event.r0.tel[3]\n\nr0tel.waveform\n\nr0tel.waveform.shape" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "note that this is ($N_{channels}$, $N_{pixels}$,\n$N_{samples}$)\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "plt.pcolormesh(r0tel.waveform[0])\n\nbrightest_pixel = np.argmax(r0tel.waveform[0].sum(axis=1))\nprint(f\"pixel {brightest_pixel} has sum {r0tel.waveform[0,1535].sum()}\")\n\nplt.plot(r0tel.waveform[0,brightest_pixel], label=\"channel 0 (high-gain)\")\nplt.plot(r0tel.waveform[1,brightest_pixel], label=\"channel 1 (low-gain)\")\nplt.legend()\n\nfrom ipywidgets import interact\n\n\n@interact\ndef view_waveform(chan=0, pix_id=brightest_pixel):\n plt.plot(r0tel.waveform[chan, pix_id])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "try making this compare 2 waveforms\n\n\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Part 2: Explore the instrument description\n\nThis is all well and good, but we don\u2019t really know what camera or\ntelescope this is\u2026 how do we get instrumental description info?\n\nCurrently this is returned *inside* the event (it will soon change to be\nseparate in next version or so)\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "subarray = source.subarray \n\nsubarray\n\nsubarray.peek()\n\nsubarray.to_table()\n\nsubarray.tel[2]\n\nsubarray.tel[2].camera\n\nsubarray.tel[2].optics\n\ntel = subarray.tel[2]\n\ntel.camera\n\ntel.optics\n\ntel.camera.geometry.pix_x\n\ntel.camera.geometry.to_table()\n\ntel.optics.mirror_area\n\nfrom ctapipe.visualization import CameraDisplay\n\ndisp = CameraDisplay(tel.camera.geometry)\n\ndisp = CameraDisplay(tel.camera.geometry)\ndisp.image = r0tel.waveform[0,:,10] # display channel 0, sample 0 (try others like 10)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\\*\\* aside: \\*\\* show demo using a CameraDisplay in interactive mode in\nipython rather than notebook\n\n\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Part 3: Apply some calibration and trace integration\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "from ctapipe.calib import CameraCalibrator\n\ncalib = CameraCalibrator(subarray=subarray)\n\nfor event in EventSource(path, max_events=5):\n calib(event) # fills in r1, dl0, and dl1\n print(event.dl1.tel.keys())\n\nevent.dl1.tel[3]\n\ndl1tel = event.dl1.tel[3]\n\ndl1tel.image.shape # note this will be gain-selected in next version, so will be just 1D array of 1855\n\ndl1tel.peak_time\n\nCameraDisplay(tel.camera.geometry, image=dl1tel.image)\n\nCameraDisplay(tel.camera.geometry, image=dl1tel.peak_time)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now for Hillas Parameters\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "from ctapipe.image import hillas_parameters, tailcuts_clean\n\nimage = dl1tel.image\nmask = tailcuts_clean(tel.camera.geometry, image, picture_thresh=10, boundary_thresh=5)\nmask\n\nCameraDisplay(tel.camera.geometry, image=mask)\n\ncleaned = image.copy()\ncleaned[~mask] = 0 \n\ndisp = CameraDisplay(tel.camera.geometry, image=cleaned)\ndisp.cmap = plt.cm.coolwarm\ndisp.add_colorbar()\nplt.xlim(0.5, 1.0)\nplt.ylim(-1.0, 0.0)\n\nparams = hillas_parameters(tel.camera.geometry, cleaned)\nprint(params)\n\ndisp = CameraDisplay(tel.camera.geometry, image=cleaned)\ndisp.cmap = plt.cm.coolwarm\ndisp.add_colorbar()\nplt.xlim(0.5, 1.0)\nplt.ylim(-1.0, 0.0)\ndisp.overlay_moments(params, color='white', lw=2)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Part 4: Let\u2019s put it all together:\n\n- loop over events, selecting only telescopes of the same type\n (e.g.\u00a0LST:LSTCam)\n- for each event, apply calibration/trace integration\n- calculate Hillas parameters\n- write out all hillas paremeters to a file that can be loaded with\n Pandas\n\n\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "first let\u2019s select only those telescopes with LST:LSTCam\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "subarray.telescope_types\n\nsubarray.get_tel_ids_for_type(\"LST_LST_LSTCam\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now let\u2019s write out program\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "data = utils.get_dataset_path(\"gamma_prod5.simtel.zst\") \nsource = EventSource(data) # remove the max_events limit to get more stats\n\nfor event in source:\n calib(event)\n \n for tel_id, tel_data in event.dl1.tel.items():\n tel = source.subarray.tel[tel_id]\n mask = tailcuts_clean(tel.camera.geometry, tel_data.image)\n if np.count_nonzero(mask) > 0:\n params = hillas_parameters(tel.camera.geometry[mask], tel_data.image[mask])\n\nfrom ctapipe.io import HDF5TableWriter\n\nwith HDF5TableWriter(filename='hillas.h5', group_name='dl1', overwrite=True) as writer:\n \n source = EventSource(data, allowed_tels=[1,2,3,4], max_events=10)\n for event in source:\n calib(event)\n \n for tel_id, tel_data in event.dl1.tel.items():\n tel = source.subarray.tel[tel_id]\n mask = tailcuts_clean(tel.camera.geometry, tel_data.image)\n params = hillas_parameters(tel.camera.geometry[mask], tel_data.image[mask])\n writer.write(\"hillas\", params)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### We can now load in the file we created and plot it\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "!ls *.h5\n\nimport pandas as pd\n\nhillas = pd.read_hdf(\"hillas.h5\", key='/dl1/hillas')\nhillas\n\n_ = hillas.hist(figsize=(8,8))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "If you do this yourself, chose a larger file to loop over more events to\nget better statistics\n\n" - ] - } - ], - "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.9.16" - } - }, - "nbformat": 4, - "nbformat_minor": 0 -} \ No newline at end of file diff --git a/docs/tutorials/ctapipe_handson.py b/docs/tutorials/ctapipe_handson.py deleted file mode 100644 index a09e5d55051..00000000000 --- a/docs/tutorials/ctapipe_handson.py +++ /dev/null @@ -1,254 +0,0 @@ -""" -Getting Started with ctapipe -============================ - -This hands-on was presented at the Paris CTA Consoritum meeting (K. -Kosack) - -""" - - -###################################################################### -# Part 1: load and loop over data -# ------------------------------- -# - -import numpy as np -from matplotlib import pyplot as plt - -from ctapipe import utils -from ctapipe.io import EventSource - -# %matplotlib inline - -path = utils.get_dataset_path("gamma_prod5.simtel.zst") - -source = EventSource(path, max_events=5) - -for event in source: - print(event.count, event.index.event_id, event.simulation.shower.energy) - -event - -event.r1 - -for event in EventSource(path, max_events=5): - print(event.count, event.r1.tel.keys()) - -event.r0.tel[3] - -r0tel = event.r0.tel[3] - -r0tel.waveform - -r0tel.waveform.shape - - -###################################################################### -# note that this is (:math:`N_{channels}`, :math:`N_{pixels}`, -# :math:`N_{samples}`) -# - -plt.pcolormesh(r0tel.waveform[0]) - -brightest_pixel = np.argmax(r0tel.waveform[0].sum(axis=1)) -print(f"pixel {brightest_pixel} has sum {r0tel.waveform[0,1535].sum()}") - -plt.plot(r0tel.waveform[0,brightest_pixel], label="channel 0 (high-gain)") -plt.plot(r0tel.waveform[1,brightest_pixel], label="channel 1 (low-gain)") -plt.legend() - -from ipywidgets import interact - - -@interact -def view_waveform(chan=0, pix_id=brightest_pixel): - plt.plot(r0tel.waveform[chan, pix_id]) - - -###################################################################### -# try making this compare 2 waveforms -# - - -###################################################################### -# Part 2: Explore the instrument description -# ------------------------------------------ -# -# This is all well and good, but we don’t really know what camera or -# telescope this is… how do we get instrumental description info? -# -# Currently this is returned *inside* the event (it will soon change to be -# separate in next version or so) -# - -subarray = source.subarray - -subarray - -subarray.peek() - -subarray.to_table() - -subarray.tel[2] - -subarray.tel[2].camera - -subarray.tel[2].optics - -tel = subarray.tel[2] - -tel.camera - -tel.optics - -tel.camera.geometry.pix_x - -tel.camera.geometry.to_table() - -tel.optics.mirror_area - -from ctapipe.visualization import CameraDisplay - -disp = CameraDisplay(tel.camera.geometry) - -disp = CameraDisplay(tel.camera.geometry) -disp.image = r0tel.waveform[0,:,10] # display channel 0, sample 0 (try others like 10) - - -###################################################################### -# \*\* aside: \*\* show demo using a CameraDisplay in interactive mode in -# ipython rather than notebook -# - - -###################################################################### -# Part 3: Apply some calibration and trace integration -# ---------------------------------------------------- -# - -from ctapipe.calib import CameraCalibrator - -calib = CameraCalibrator(subarray=subarray) - -for event in EventSource(path, max_events=5): - calib(event) # fills in r1, dl0, and dl1 - print(event.dl1.tel.keys()) - -event.dl1.tel[3] - -dl1tel = event.dl1.tel[3] - -dl1tel.image.shape # note this will be gain-selected in next version, so will be just 1D array of 1855 - -dl1tel.peak_time - -CameraDisplay(tel.camera.geometry, image=dl1tel.image) - -CameraDisplay(tel.camera.geometry, image=dl1tel.peak_time) - - -###################################################################### -# Now for Hillas Parameters -# - -from ctapipe.image import hillas_parameters, tailcuts_clean - -image = dl1tel.image -mask = tailcuts_clean(tel.camera.geometry, image, picture_thresh=10, boundary_thresh=5) -mask - -CameraDisplay(tel.camera.geometry, image=mask) - -cleaned = image.copy() -cleaned[~mask] = 0 - -disp = CameraDisplay(tel.camera.geometry, image=cleaned) -disp.cmap = plt.cm.coolwarm -disp.add_colorbar() -plt.xlim(0.5, 1.0) -plt.ylim(-1.0, 0.0) - -params = hillas_parameters(tel.camera.geometry, cleaned) -print(params) - -disp = CameraDisplay(tel.camera.geometry, image=cleaned) -disp.cmap = plt.cm.coolwarm -disp.add_colorbar() -plt.xlim(0.5, 1.0) -plt.ylim(-1.0, 0.0) -disp.overlay_moments(params, color='white', lw=2) - - -###################################################################### -# Part 4: Let’s put it all together: -# ---------------------------------- -# -# - loop over events, selecting only telescopes of the same type -# (e.g. LST:LSTCam) -# - for each event, apply calibration/trace integration -# - calculate Hillas parameters -# - write out all hillas paremeters to a file that can be loaded with -# Pandas -# - - -###################################################################### -# first let’s select only those telescopes with LST:LSTCam -# - -subarray.telescope_types - -subarray.get_tel_ids_for_type("LST_LST_LSTCam") - - -###################################################################### -# Now let’s write out program -# - -data = utils.get_dataset_path("gamma_prod5.simtel.zst") -source = EventSource(data) # remove the max_events limit to get more stats - -for event in source: - calib(event) - - for tel_id, tel_data in event.dl1.tel.items(): - tel = source.subarray.tel[tel_id] - mask = tailcuts_clean(tel.camera.geometry, tel_data.image) - if np.count_nonzero(mask) > 0: - params = hillas_parameters(tel.camera.geometry[mask], tel_data.image[mask]) - -from ctapipe.io import HDF5TableWriter - -with HDF5TableWriter(filename='hillas.h5', group_name='dl1', overwrite=True) as writer: - - source = EventSource(data, allowed_tels=[1,2,3,4], max_events=10) - for event in source: - calib(event) - - for tel_id, tel_data in event.dl1.tel.items(): - tel = source.subarray.tel[tel_id] - mask = tailcuts_clean(tel.camera.geometry, tel_data.image) - params = hillas_parameters(tel.camera.geometry[mask], tel_data.image[mask]) - writer.write("hillas", params) - - -###################################################################### -# We can now load in the file we created and plot it -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# - -!ls *.h5 - -import pandas as pd - -hillas = pd.read_hdf("hillas.h5", key='/dl1/hillas') -hillas - -_ = hillas.hist(figsize=(8,8)) - - -###################################################################### -# If you do this yourself, chose a larger file to loop over more events to -# get better statistics -# \ No newline at end of file diff --git a/docs/tutorials/ctapipe_handson.rst b/docs/tutorials/ctapipe_handson.rst deleted file mode 100644 index 57b71bb5498..00000000000 --- a/docs/tutorials/ctapipe_handson.rst +++ /dev/null @@ -1,370 +0,0 @@ - -.. DO NOT EDIT. -.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. -.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: -.. "tutorials/ctapipe_handson.py" -.. LINE NUMBERS ARE GIVEN BELOW. - -.. only:: html - - .. note:: - :class: sphx-glr-download-link-note - - :ref:`Go to the end ` - to download the full example code - -.. rst-class:: sphx-glr-example-title - -.. _sphx_glr_tutorials_ctapipe_handson.py: - - -SyntaxError -=========== - -Example script with invalid Python syntax - -.. GENERATED FROM PYTHON SOURCE LINES 1-11 - -.. code-block:: default - - """ - Getting Started with ctapipe - ============================ - - This hands-on was presented at the Paris CTA Consoritum meeting (K. - Kosack) - - """ - - - -.. GENERATED FROM PYTHON SOURCE LINES 12-15 - -Part 1: load and loop over data -------------------------------- - - -.. GENERATED FROM PYTHON SOURCE LINES 15-47 - -.. code-block:: default - - - import numpy as np - from matplotlib import pyplot as plt - - from ctapipe import utils - from ctapipe.io import EventSource - - # %matplotlib inline - - path = utils.get_dataset_path("gamma_prod5.simtel.zst") - - source = EventSource(path, max_events=5) - - for event in source: - print(event.count, event.index.event_id, event.simulation.shower.energy) - - event - - event.r1 - - for event in EventSource(path, max_events=5): - print(event.count, event.r1.tel.keys()) - - event.r0.tel[3] - - r0tel = event.r0.tel[3] - - r0tel.waveform - - r0tel.waveform.shape - - - -.. GENERATED FROM PYTHON SOURCE LINES 48-51 - -note that this is (:math:`N_{channels}`, :math:`N_{pixels}`, -:math:`N_{samples}`) - - -.. GENERATED FROM PYTHON SOURCE LINES 51-69 - -.. code-block:: default - - - plt.pcolormesh(r0tel.waveform[0]) - - brightest_pixel = np.argmax(r0tel.waveform[0].sum(axis=1)) - print(f"pixel {brightest_pixel} has sum {r0tel.waveform[0,1535].sum()}") - - plt.plot(r0tel.waveform[0,brightest_pixel], label="channel 0 (high-gain)") - plt.plot(r0tel.waveform[1,brightest_pixel], label="channel 1 (low-gain)") - plt.legend() - - from ipywidgets import interact - - - @interact - def view_waveform(chan=0, pix_id=brightest_pixel): - plt.plot(r0tel.waveform[chan, pix_id]) - - - -.. GENERATED FROM PYTHON SOURCE LINES 70-72 - -try making this compare 2 waveforms - - -.. GENERATED FROM PYTHON SOURCE LINES 75-84 - -Part 2: Explore the instrument description ------------------------------------------- - -This is all well and good, but we don’t really know what camera or -telescope this is… how do we get instrumental description info? - -Currently this is returned *inside* the event (it will soon change to be -separate in next version or so) - - -.. GENERATED FROM PYTHON SOURCE LINES 84-119 - -.. code-block:: default - - - subarray = source.subarray - - subarray - - subarray.peek() - - subarray.to_table() - - subarray.tel[2] - - subarray.tel[2].camera - - subarray.tel[2].optics - - tel = subarray.tel[2] - - tel.camera - - tel.optics - - tel.camera.geometry.pix_x - - tel.camera.geometry.to_table() - - tel.optics.mirror_area - - from ctapipe.visualization import CameraDisplay - - disp = CameraDisplay(tel.camera.geometry) - - disp = CameraDisplay(tel.camera.geometry) - disp.image = r0tel.waveform[0,:,10] # display channel 0, sample 0 (try others like 10) - - - -.. GENERATED FROM PYTHON SOURCE LINES 120-123 - -\*\* aside: \*\* show demo using a CameraDisplay in interactive mode in -ipython rather than notebook - - -.. GENERATED FROM PYTHON SOURCE LINES 126-129 - -Part 3: Apply some calibration and trace integration ----------------------------------------------------- - - -.. GENERATED FROM PYTHON SOURCE LINES 129-151 - -.. code-block:: default - - - from ctapipe.calib import CameraCalibrator - - calib = CameraCalibrator(subarray=subarray) - - for event in EventSource(path, max_events=5): - calib(event) # fills in r1, dl0, and dl1 - print(event.dl1.tel.keys()) - - event.dl1.tel[3] - - dl1tel = event.dl1.tel[3] - - dl1tel.image.shape # note this will be gain-selected in next version, so will be just 1D array of 1855 - - dl1tel.peak_time - - CameraDisplay(tel.camera.geometry, image=dl1tel.image) - - CameraDisplay(tel.camera.geometry, image=dl1tel.peak_time) - - - -.. GENERATED FROM PYTHON SOURCE LINES 152-154 - -Now for Hillas Parameters - - -.. GENERATED FROM PYTHON SOURCE LINES 154-183 - -.. code-block:: default - - - from ctapipe.image import hillas_parameters, tailcuts_clean - - image = dl1tel.image - mask = tailcuts_clean(tel.camera.geometry, image, picture_thresh=10, boundary_thresh=5) - mask - - CameraDisplay(tel.camera.geometry, image=mask) - - cleaned = image.copy() - cleaned[~mask] = 0 - - disp = CameraDisplay(tel.camera.geometry, image=cleaned) - disp.cmap = plt.cm.coolwarm - disp.add_colorbar() - plt.xlim(0.5, 1.0) - plt.ylim(-1.0, 0.0) - - params = hillas_parameters(tel.camera.geometry, cleaned) - print(params) - - disp = CameraDisplay(tel.camera.geometry, image=cleaned) - disp.cmap = plt.cm.coolwarm - disp.add_colorbar() - plt.xlim(0.5, 1.0) - plt.ylim(-1.0, 0.0) - disp.overlay_moments(params, color='white', lw=2) - - - -.. GENERATED FROM PYTHON SOURCE LINES 184-194 - -Part 4: Let’s put it all together: ----------------------------------- - -- loop over events, selecting only telescopes of the same type - (e.g. LST:LSTCam) -- for each event, apply calibration/trace integration -- calculate Hillas parameters -- write out all hillas paremeters to a file that can be loaded with - Pandas - - -.. GENERATED FROM PYTHON SOURCE LINES 197-199 - -first let’s select only those telescopes with LST:LSTCam - - -.. GENERATED FROM PYTHON SOURCE LINES 199-205 - -.. code-block:: default - - - subarray.telescope_types - - subarray.get_tel_ids_for_type("LST_LST_LSTCam") - - - -.. GENERATED FROM PYTHON SOURCE LINES 206-208 - -Now let’s write out program - - -.. GENERATED FROM PYTHON SOURCE LINES 208-236 - -.. code-block:: default - - - data = utils.get_dataset_path("gamma_prod5.simtel.zst") - source = EventSource(data) # remove the max_events limit to get more stats - - for event in source: - calib(event) - - for tel_id, tel_data in event.dl1.tel.items(): - tel = source.subarray.tel[tel_id] - mask = tailcuts_clean(tel.camera.geometry, tel_data.image) - if np.count_nonzero(mask) > 0: - params = hillas_parameters(tel.camera.geometry[mask], tel_data.image[mask]) - - from ctapipe.io import HDF5TableWriter - - with HDF5TableWriter(filename='hillas.h5', group_name='dl1', overwrite=True) as writer: - - source = EventSource(data, allowed_tels=[1,2,3,4], max_events=10) - for event in source: - calib(event) - - for tel_id, tel_data in event.dl1.tel.items(): - tel = source.subarray.tel[tel_id] - mask = tailcuts_clean(tel.camera.geometry, tel_data.image) - params = hillas_parameters(tel.camera.geometry[mask], tel_data.image[mask]) - writer.write("hillas", params) - - - -.. GENERATED FROM PYTHON SOURCE LINES 237-240 - -We can now load in the file we created and plot it -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - -.. GENERATED FROM PYTHON SOURCE LINES 240-251 - -.. code-block:: default - - - !ls *.h5 - - import pandas as pd - - hillas = pd.read_hdf("hillas.h5", key='/dl1/hillas') - hillas - - _ = hillas.hist(figsize=(8,8)) - - - -.. GENERATED FROM PYTHON SOURCE LINES 252-254 - -If you do this yourself, chose a larger file to loop over more events to -get better statistics - - -.. rst-class:: sphx-glr-timing - - **Total running time of the script:** ( 0 minutes 0.000 seconds) - - -.. _sphx_glr_download_tutorials_ctapipe_handson.py: - -.. only:: html - - .. container:: sphx-glr-footer sphx-glr-footer-example - - - - - .. container:: sphx-glr-download sphx-glr-download-python - - :download:`Download Python source code: ctapipe_handson.py ` - - .. container:: sphx-glr-download sphx-glr-download-jupyter - - :download:`Download Jupyter notebook: ctapipe_handson.ipynb ` - - -.. only:: html - - .. rst-class:: sphx-glr-signature - - `Gallery generated by Sphinx-Gallery `_ diff --git a/docs/tutorials/ctapipe_handson_codeobj.pickle b/docs/tutorials/ctapipe_handson_codeobj.pickle deleted file mode 100644 index 63ee824921053b7769021f0a7b9acb090d2935b4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 219 zcmZ9GK?=e!5Jg>7txW}wp&L)(TEV@Pm=ZAz0sK?*J{%+B#%9?6s#jkgjORy?ltq1Gx}O}Du!a;?kj01r@{tme QaamgCIA2c diff --git a/docs/tutorials/ctapipe_overview.ipynb b/docs/tutorials/ctapipe_overview.ipynb deleted file mode 100644 index 55b1fc7850d..00000000000 --- a/docs/tutorials/ctapipe_overview.ipynb +++ /dev/null @@ -1,329 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n# Analyzing Events Using ctapipe\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - ".. container::\n\n .. raw:: html\n\n

\n\n Initially presented @ LST Analysis Bootcamp\n\n .. raw:: html\n\n

\n\n .. raw:: html\n\n

\n\n Padova, 26.11.2018\n\n .. raw:: html\n\n

\n\n .. raw:: html\n\n

\n\n Maximilian N\u00f6the (@maxnoe) & Kai A. Br\u00fcgge (@mackaiver)\n\n .. raw:: html\n\n

\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "import matplotlib.pyplot as plt\nimport numpy as np\n\n# %matplotlib inline\n\nplt.rcParams[\"figure.figsize\"] = (12, 8)\nplt.rcParams[\"font.size\"] = 14\nplt.rcParams[\"figure.figsize\"]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - ".. raw:: html\n\n

\n\nTable of Contents\n\n.. raw:: html\n\n

\n\n.. container::\n :name: toc\n\n\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## General Information\n\n\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Design\n\n- DL0 \u2192 DL3 analysis\n\n- Currently some R0 \u2192 DL2 code to be able to analyze simtel files\n\n- ctapipe is built upon the Scientific Python Stack, core dependencies\n are\n\n - numpy\n - scipy\n - astropy\n - numba\n\n\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Developement\n\n- ctapipe is developed as Open Source Software (BSD 3-Clause License)\n at https://github.com/cta-observatory/ctapipe\n\n- We use the \u201cGithub-Workflow\u201d:\n\n - Few people (e.g. @kosack, @maxnoe) have write access to the main\n repository\n - Contributors fork the main repository and work on branches\n - Pull Requests are merged after Code Review and automatic execution\n of the test suite\n\n- Early developement stage \u21d2 backwards-incompatible API changes might\n and will happen\n\n\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### What\u2019s there?\n\n- Reading simtel simulation files\n- Simple calibration, cleaning and feature extraction functions\n- Camera and Array plotting\n- Coordinate frames and transformations\n- Stereo-reconstruction using line intersections\n\n\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### What\u2019s still missing?\n\n- Good integration with machine learning techniques\n- IRF calculation\n- Documentation, e.g.\u00a0formal definitions of coordinate frames\n\n\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### What can you do?\n\n- Report issues\n\n - Hard to get started? Tell us where you are stuck\n - Tell user stories\n - Missing features\n\n- Start contributing\n\n - ctapipe needs more workpower\n - Implement new reconstruction features\n\n\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## A simple hillas analysis\n\n\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Reading in simtel files\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "from ctapipe.io import EventSource\nfrom ctapipe.utils.datasets import get_dataset_path\n\ninput_url = get_dataset_path(\"gamma_prod5.simtel.zst\")\n\n# EventSource() automatically detects what kind of file we are giving it,\n# if already supported by ctapipe\nsource = EventSource(input_url, max_events=5)\n\nprint(type(source))\n\nfor event in source:\n print(\n \"Id: {}, E = {:1.3f}, Telescopes: {}\".format(\n event.count, event.simulation.shower.energy, len(event.r0.tel)\n )\n )" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Each event is a ``DataContainer`` holding several ``Field``\\ s of data,\nwhich can be containers or just numbers. Let\u2019s look a one event:\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "event\n\nsource.subarray.camera_types\n\nlen(event.r0.tel), len(event.r1.tel)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Data calibration\n\nThe ``CameraCalibrator`` calibrates the event (obtaining the ``dl1``\nimages).\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "from ctapipe.calib import CameraCalibrator\n\ncalibrator = CameraCalibrator(subarray=source.subarray)\n\ncalibrator(event)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Event displays\n\nLet\u2019s use ctapipe\u2019s plotting facilities to plot the telescope images\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "event.dl1.tel.keys()\n\ntel_id = 130\n\ngeometry = source.subarray.tel[tel_id].camera.geometry\ndl1 = event.dl1.tel[tel_id]\n\ngeometry, dl1\n\ndl1.image\n\nfrom ctapipe.visualization import CameraDisplay\n\ndisplay = CameraDisplay(geometry)\n\n# right now, there might be one image per gain channel.\n# This will change as soon as\ndisplay.image = dl1.image\ndisplay.add_colorbar()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Image Cleaning\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "from ctapipe.image.cleaning import tailcuts_clean\n\n# unoptimized cleaning levels\ncleaning_level = {\n \"CHEC\": (2, 4, 2),\n \"LSTCam\": (3.5, 7, 2),\n \"FlashCam\": (3.5, 7, 2),\n \"NectarCam\": (4, 8, 2),\n}\n\nboundary, picture, min_neighbors = cleaning_level[geometry.name]\n\nclean = tailcuts_clean(\n geometry,\n dl1.image,\n boundary_thresh=boundary,\n picture_thresh=picture,\n min_number_picture_neighbors=min_neighbors,\n)\n\nfig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 5))\n\nd1 = CameraDisplay(geometry, ax=ax1)\nd2 = CameraDisplay(geometry, ax=ax2)\n\nax1.set_title(\"Image\")\nd1.image = dl1.image\nd1.add_colorbar(ax=ax1)\n\nax2.set_title(\"Pulse Time\")\nd2.image = dl1.peak_time - np.average(dl1.peak_time, weights=dl1.image)\nd2.cmap = \"RdBu_r\"\nd2.add_colorbar(ax=ax2)\nd2.set_limits_minmax(-20, 20)\n\nd1.highlight_pixels(clean, color=\"red\", linewidth=1)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Image Parameters\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "from ctapipe.image import (\n camera_to_shower_coordinates,\n concentration_parameters,\n hillas_parameters,\n leakage_parameters,\n number_of_islands,\n timing_parameters,\n)\n\nhillas = hillas_parameters(geometry[clean], dl1.image[clean])\n\nprint(hillas)\n\ndisplay = CameraDisplay(geometry)\n\n# set \"unclean\" pixels to 0\ncleaned = dl1.image.copy()\ncleaned[~clean] = 0.0\n\ndisplay.image = cleaned\ndisplay.add_colorbar()\n\ndisplay.overlay_moments(hillas, color=\"xkcd:red\")\n\ntiming = timing_parameters(geometry, dl1.image, dl1.peak_time, hillas, clean)\n\nprint(timing)\n\nlong, trans = camera_to_shower_coordinates(\n geometry.pix_x, geometry.pix_y, hillas.x, hillas.y, hillas.psi\n)\n\nplt.plot(long[clean], dl1.peak_time[clean], \"o\")\nplt.plot(long[clean], timing.slope * long[clean] + timing.intercept)\n\nl = leakage_parameters(geometry, dl1.image, clean)\nprint(l)\n\ndisp = CameraDisplay(geometry)\ndisp.image = dl1.image\ndisp.highlight_pixels(geometry.get_border_pixel_mask(1), linewidth=2, color=\"xkcd:red\")\n\nn_islands, island_id = number_of_islands(geometry, clean)\n\nprint(n_islands)\n\nconc = concentration_parameters(geometry, dl1.image, hillas)\nprint(conc)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Putting it all together / Stereo reconstruction\n\nAll these steps are now unified in several components configurable\nthrough the config system, mainly:\n\n- CameraCalibrator for DL0 \u2192 DL1 (Images)\n- ImageProcessor for DL1 (Images) \u2192 DL1 (Parameters)\n- ShowerProcessor for stereo reconstruction of the shower geometry\n- DataWriter for writing data into HDF5\n\nA command line tool doing these steps and writing out data in HDF5\nformat is available as ``ctapipe-process``\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "import tempfile\nfrom copy import deepcopy\n\nimport astropy.units as u\nfrom astropy.coordinates import AltAz, SkyCoord\nfrom traitlets.config import Config\n\nfrom ctapipe.calib import CameraCalibrator\nfrom ctapipe.containers import ImageParametersContainer\nfrom ctapipe.image import ImageProcessor\nfrom ctapipe.io import DataWriter, EventSource\nfrom ctapipe.reco import ShowerProcessor\nfrom ctapipe.utils.datasets import get_dataset_path\n\nimage_processor_config = Config(\n {\n \"ImageProcessor\": {\n \"image_cleaner_type\": \"TailcutsImageCleaner\",\n \"TailcutsImageCleaner\": {\n \"picture_threshold_pe\": [\n (\"type\", \"LST_LST_LSTCam\", 7.5),\n (\"type\", \"MST_MST_FlashCam\", 8),\n (\"type\", \"MST_MST_NectarCam\", 8),\n (\"type\", \"SST_ASTRI_CHEC\", 7),\n ],\n \"boundary_threshold_pe\": [\n (\"type\", \"LST_LST_LSTCam\", 5),\n (\"type\", \"MST_MST_FlashCam\", 4),\n (\"type\", \"MST_MST_NectarCam\", 4),\n (\"type\", \"SST_ASTRI_CHEC\", 4),\n ],\n },\n }\n }\n)\n\ninput_url = get_dataset_path(\"gamma_prod5.simtel.zst\")\nsource = EventSource(input_url)\n\ncalibrator = CameraCalibrator(subarray=source.subarray)\nimage_processor = ImageProcessor(\n subarray=source.subarray, config=image_processor_config\n)\nshower_processor = ShowerProcessor(subarray=source.subarray)\nhorizon_frame = AltAz()\n\nf = tempfile.NamedTemporaryFile(suffix=\".hdf5\")\n\nwith DataWriter(\n source, output_path=f.name, overwrite=True, write_showers=True\n) as writer:\n\n for event in source:\n energy = event.simulation.shower.energy\n n_telescopes_r1 = len(event.r1.tel)\n event_id = event.index.event_id\n print(f\"Id: {event_id}, E = {energy:1.3f}, Telescopes (R1): {n_telescopes_r1}\")\n\n calibrator(event)\n image_processor(event)\n shower_processor(event)\n\n stereo = event.dl2.stereo.geometry[\"HillasReconstructor\"]\n if stereo.is_valid:\n print(\" Alt: {:.2f}\u00b0\".format(stereo.alt.deg))\n print(\" Az: {:.2f}\u00b0\".format(stereo.az.deg))\n print(\" Hmax: {:.0f}\".format(stereo.h_max))\n print(\" CoreX: {:.1f}\".format(stereo.core_x))\n print(\" CoreY: {:.1f}\".format(stereo.core_y))\n print(\" Multiplicity: {:d}\".format(len(stereo.telescopes)))\n\n # save a nice event for plotting later\n if event.count == 3:\n plotting_event = deepcopy(event)\n\n writer(event)\n\nimport pandas as pd\nfrom astropy.coordinates.angle_utilities import angular_separation\n\nfrom ctapipe.io import TableLoader\n\nloader = TableLoader(f.name, load_dl2=True, load_simulated=True)\n\nevents = loader.read_subarray_events()\n\ntheta = angular_separation(\n events[\"HillasReconstructor_az\"].quantity,\n events[\"HillasReconstructor_alt\"].quantity,\n events[\"true_az\"].quantity,\n events[\"true_alt\"].quantity,\n)\n\nplt.hist(theta.to_value(u.deg) ** 2, bins=25, range=[0, 0.3])\nplt.xlabel(r\"$\\theta\u00b2 / deg\u00b2$\")\nNone" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## ArrayDisplay\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "from ctapipe.visualization import ArrayDisplay\n\nangle_offset = plotting_event.pointing.array_azimuth\n\nplotting_hillas = {\n tel_id: dl1.parameters.hillas for tel_id, dl1 in plotting_event.dl1.tel.items()\n}\n\nplotting_core = {\n tel_id: dl1.parameters.core.psi for tel_id, dl1 in plotting_event.dl1.tel.items()\n}\n\n\ndisp = ArrayDisplay(source.subarray)\n\ndisp.set_line_hillas(plotting_hillas, plotting_core, 500)\n\nplt.scatter(\n plotting_event.simulation.shower.core_x,\n plotting_event.simulation.shower.core_y,\n s=200,\n c=\"k\",\n marker=\"x\",\n label=\"True Impact\",\n)\nplt.scatter(\n plotting_event.dl2.stereo.geometry[\"HillasReconstructor\"].core_x,\n plotting_event.dl2.stereo.geometry[\"HillasReconstructor\"].core_y,\n s=200,\n c=\"r\",\n marker=\"x\",\n label=\"Estimated Impact\",\n)\n\nplt.legend()\n# plt.xlim(-400, 400)\n# plt.ylim(-400, 400)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Reading the LST dl1 data\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "loader = TableLoader(f.name, load_simulated=True, load_dl1_parameters=True)\n\ndl1_table = loader.read_telescope_events([\"LST_LST_LSTCam\"])\n\nplt.scatter(\n np.log10(dl1_table[\"true_energy\"].quantity / u.TeV),\n np.log10(dl1_table[\"hillas_intensity\"]),\n)\nplt.xlabel(\"log10(E / TeV)\")\nplt.ylabel(\"log10(intensity)\")\nNone" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Isn\u2019t python slow?\n\n- Many of you might have heard: \u201cPython is slow\u201d.\n- That\u2019s trueish.\n- All python objects are classes living on the heap, even integers.\n- Looping over lots of \u201cprimitives\u201d is quite slow compared to other\n languages.\n\n| \u21d2 Vectorize as much as possible using numpy\n| \u21d2 Use existing interfaces to fast C / C++ / Fortran code\n| \u21d2 Optimize using numba\n\n**But: \u201cPremature Optimization is the root of all evil\u201d \u2014 Donald Knuth**\n\nSo profile to find exactly what is slow.\n\n### Why use python then?\n\n- Python works very well as *glue* for libraries of all kinds of\n languages\n- Python has a rich ecosystem for data science, physics, algorithms,\n astronomy\n\n### Example: Number of Islands\n\nFind all groups of pixels, that survived the cleaning\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "from ctapipe.image import toymodel\nfrom ctapipe.instrument import SubarrayDescription\n\ngeometry = loader.subarray.tel[1].camera.geometry" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let\u2019s create a toy images with several islands;\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "np.random.seed(42)\n\nimage = np.zeros(geometry.n_pixels)\n\n\nfor i in range(9):\n\n model = toymodel.Gaussian(\n x=np.random.uniform(-0.8, 0.8) * u.m,\n y=np.random.uniform(-0.8, 0.8) * u.m,\n width=np.random.uniform(0.05, 0.075) * u.m,\n length=np.random.uniform(0.1, 0.15) * u.m,\n psi=np.random.uniform(0, 2 * np.pi) * u.rad,\n )\n\n new_image, sig, bg = model.generate_image(\n geometry, intensity=np.random.uniform(1000, 3000), nsb_level_pe=5\n )\n image += new_image\n\nclean = tailcuts_clean(\n geometry,\n image,\n picture_thresh=10,\n boundary_thresh=5,\n min_number_picture_neighbors=2,\n)\n\ndisp = CameraDisplay(geometry)\ndisp.image = image\ndisp.highlight_pixels(clean, color=\"xkcd:red\", linewidth=1.5)\ndisp.add_colorbar()\n\n\ndef num_islands_python(camera, clean):\n \"\"\"A breadth first search to find connected islands of neighboring pixels in the cleaning set\"\"\"\n\n # the camera geometry has a [n_pixel, n_pixel] boolean array\n # that is True where two pixels are neighbors\n neighbors = camera.neighbor_matrix\n\n island_ids = np.zeros(camera.n_pixels)\n current_island = 0\n\n # a set to remember which pixels we already visited\n visited = set()\n\n # go only through the pixels, that survived cleaning\n for pix_id in np.where(clean)[0]:\n if pix_id not in visited:\n # remember that we already checked this pixel\n visited.add(pix_id)\n\n # if we land in the outer loop again, we found a new island\n current_island += 1\n island_ids[pix_id] = current_island\n\n # now check all neighbors of the current pixel recursively\n to_check = set(np.where(neighbors[pix_id] & clean)[0])\n while to_check:\n pix_id = to_check.pop()\n\n if pix_id not in visited:\n visited.add(pix_id)\n island_ids[pix_id] = current_island\n\n to_check.update(np.where(neighbors[pix_id] & clean)[0])\n\n n_islands = current_island\n return n_islands, island_ids\n\n\nn_islands, island_ids = num_islands_python(geometry, clean)\n\nfrom matplotlib.colors import ListedColormap\n\ncmap = plt.get_cmap(\"Paired\")\ncmap = ListedColormap(cmap.colors[:n_islands])\ncmap.set_under(\"k\")\n\ndisp = CameraDisplay(geometry)\ndisp.image = island_ids\ndisp.cmap = cmap\ndisp.set_limits_minmax(0.5, n_islands + 0.5)\ndisp.add_colorbar()\n\n# %timeit num_islands_python(geometry, clean)\n\nfrom scipy.sparse.csgraph import connected_components\n\n\ndef num_islands_scipy(geometry, clean):\n neighbors = geometry.neighbor_matrix_sparse\n\n clean_neighbors = neighbors[clean][:, clean]\n num_islands, labels = connected_components(clean_neighbors, directed=False)\n\n island_ids = np.zeros(geometry.n_pixels)\n island_ids[clean] = labels + 1\n\n return num_islands, island_ids\n\n\nn_islands_s, island_ids_s = num_islands_scipy(geometry, clean)\n\ndisp = CameraDisplay(geometry)\ndisp.image = island_ids_s\ndisp.cmap = cmap\ndisp.set_limits_minmax(0.5, n_islands_s + 0.5)\ndisp.add_colorbar()\n\n# %timeit num_islands_scipy(geometry, clean)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**A lot less code, and a factor 3 speed improvement**\n\n\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Finally, current ctapipe implementation is using numba:\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "# %timeit number_of_islands(geometry, clean)" - ] - } - ], - "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.9.16" - } - }, - "nbformat": 4, - "nbformat_minor": 0 -} \ No newline at end of file diff --git a/docs/tutorials/ctapipe_overview.py b/docs/tutorials/ctapipe_overview.py deleted file mode 100644 index 7266aac8f0a..00000000000 --- a/docs/tutorials/ctapipe_overview.py +++ /dev/null @@ -1,675 +0,0 @@ -""" -Analyzing Events Using ctapipe -============================== - -""" - - -###################################################################### -# .. container:: -# -# .. raw:: html -# -#

-# -# Initially presented @ LST Analysis Bootcamp -# -# .. raw:: html -# -#

-# -# .. raw:: html -# -#

-# -# Padova, 26.11.2018 -# -# .. raw:: html -# -#

-# -# .. raw:: html -# -#

-# -# Maximilian Nöthe (@maxnoe) & Kai A. Brügge (@mackaiver) -# -# .. raw:: html -# -#

-# - -import matplotlib.pyplot as plt -import numpy as np - -# %matplotlib inline - -plt.rcParams["figure.figsize"] = (12, 8) -plt.rcParams["font.size"] = 14 -plt.rcParams["figure.figsize"] - - -###################################################################### -# .. raw:: html -# -#

-# -# Table of Contents -# -# .. raw:: html -# -#

-# -# .. container:: -# :name: toc -# - - -###################################################################### -# General Information -# ------------------- -# - - -###################################################################### -# Design -# ~~~~~~ -# -# - DL0 → DL3 analysis -# -# - Currently some R0 → DL2 code to be able to analyze simtel files -# -# - ctapipe is built upon the Scientific Python Stack, core dependencies -# are -# -# - numpy -# - scipy -# - astropy -# - numba -# - - -###################################################################### -# Developement -# ~~~~~~~~~~~~ -# -# - ctapipe is developed as Open Source Software (BSD 3-Clause License) -# at https://github.com/cta-observatory/ctapipe -# -# - We use the “Github-Workflow”: -# -# - Few people (e.g. @kosack, @maxnoe) have write access to the main -# repository -# - Contributors fork the main repository and work on branches -# - Pull Requests are merged after Code Review and automatic execution -# of the test suite -# -# - Early developement stage ⇒ backwards-incompatible API changes might -# and will happen -# - - -###################################################################### -# What’s there? -# ~~~~~~~~~~~~~ -# -# - Reading simtel simulation files -# - Simple calibration, cleaning and feature extraction functions -# - Camera and Array plotting -# - Coordinate frames and transformations -# - Stereo-reconstruction using line intersections -# - - -###################################################################### -# What’s still missing? -# ~~~~~~~~~~~~~~~~~~~~~ -# -# - Good integration with machine learning techniques -# - IRF calculation -# - Documentation, e.g. formal definitions of coordinate frames -# - - -###################################################################### -# What can you do? -# ~~~~~~~~~~~~~~~~ -# -# - Report issues -# -# - Hard to get started? Tell us where you are stuck -# - Tell user stories -# - Missing features -# -# - Start contributing -# -# - ctapipe needs more workpower -# - Implement new reconstruction features -# - - -###################################################################### -# A simple hillas analysis -# ------------------------ -# - - -###################################################################### -# Reading in simtel files -# ~~~~~~~~~~~~~~~~~~~~~~~ -# - -from ctapipe.io import EventSource -from ctapipe.utils.datasets import get_dataset_path - -input_url = get_dataset_path("gamma_prod5.simtel.zst") - -# EventSource() automatically detects what kind of file we are giving it, -# if already supported by ctapipe -source = EventSource(input_url, max_events=5) - -print(type(source)) - -for event in source: - print( - "Id: {}, E = {:1.3f}, Telescopes: {}".format( - event.count, event.simulation.shower.energy, len(event.r0.tel) - ) - ) - - -###################################################################### -# Each event is a ``DataContainer`` holding several ``Field``\ s of data, -# which can be containers or just numbers. Let’s look a one event: -# - -event - -source.subarray.camera_types - -len(event.r0.tel), len(event.r1.tel) - - -###################################################################### -# Data calibration -# ~~~~~~~~~~~~~~~~ -# -# The ``CameraCalibrator`` calibrates the event (obtaining the ``dl1`` -# images). -# - -from ctapipe.calib import CameraCalibrator - -calibrator = CameraCalibrator(subarray=source.subarray) - -calibrator(event) - - -###################################################################### -# Event displays -# ~~~~~~~~~~~~~~ -# -# Let’s use ctapipe’s plotting facilities to plot the telescope images -# - -event.dl1.tel.keys() - -tel_id = 130 - -geometry = source.subarray.tel[tel_id].camera.geometry -dl1 = event.dl1.tel[tel_id] - -geometry, dl1 - -dl1.image - -from ctapipe.visualization import CameraDisplay - -display = CameraDisplay(geometry) - -# right now, there might be one image per gain channel. -# This will change as soon as -display.image = dl1.image -display.add_colorbar() - - -###################################################################### -# Image Cleaning -# ~~~~~~~~~~~~~~ -# - -from ctapipe.image.cleaning import tailcuts_clean - -# unoptimized cleaning levels -cleaning_level = { - "CHEC": (2, 4, 2), - "LSTCam": (3.5, 7, 2), - "FlashCam": (3.5, 7, 2), - "NectarCam": (4, 8, 2), -} - -boundary, picture, min_neighbors = cleaning_level[geometry.name] - -clean = tailcuts_clean( - geometry, - dl1.image, - boundary_thresh=boundary, - picture_thresh=picture, - min_number_picture_neighbors=min_neighbors, -) - -fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 5)) - -d1 = CameraDisplay(geometry, ax=ax1) -d2 = CameraDisplay(geometry, ax=ax2) - -ax1.set_title("Image") -d1.image = dl1.image -d1.add_colorbar(ax=ax1) - -ax2.set_title("Pulse Time") -d2.image = dl1.peak_time - np.average(dl1.peak_time, weights=dl1.image) -d2.cmap = "RdBu_r" -d2.add_colorbar(ax=ax2) -d2.set_limits_minmax(-20, 20) - -d1.highlight_pixels(clean, color="red", linewidth=1) - - -###################################################################### -# Image Parameters -# ~~~~~~~~~~~~~~~~ -# - -from ctapipe.image import ( - camera_to_shower_coordinates, - concentration_parameters, - hillas_parameters, - leakage_parameters, - number_of_islands, - timing_parameters, -) - -hillas = hillas_parameters(geometry[clean], dl1.image[clean]) - -print(hillas) - -display = CameraDisplay(geometry) - -# set "unclean" pixels to 0 -cleaned = dl1.image.copy() -cleaned[~clean] = 0.0 - -display.image = cleaned -display.add_colorbar() - -display.overlay_moments(hillas, color="xkcd:red") - -timing = timing_parameters(geometry, dl1.image, dl1.peak_time, hillas, clean) - -print(timing) - -long, trans = camera_to_shower_coordinates( - geometry.pix_x, geometry.pix_y, hillas.x, hillas.y, hillas.psi -) - -plt.plot(long[clean], dl1.peak_time[clean], "o") -plt.plot(long[clean], timing.slope * long[clean] + timing.intercept) - -l = leakage_parameters(geometry, dl1.image, clean) -print(l) - -disp = CameraDisplay(geometry) -disp.image = dl1.image -disp.highlight_pixels(geometry.get_border_pixel_mask(1), linewidth=2, color="xkcd:red") - -n_islands, island_id = number_of_islands(geometry, clean) - -print(n_islands) - -conc = concentration_parameters(geometry, dl1.image, hillas) -print(conc) - - -###################################################################### -# Putting it all together / Stereo reconstruction -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# -# All these steps are now unified in several components configurable -# through the config system, mainly: -# -# - CameraCalibrator for DL0 → DL1 (Images) -# - ImageProcessor for DL1 (Images) → DL1 (Parameters) -# - ShowerProcessor for stereo reconstruction of the shower geometry -# - DataWriter for writing data into HDF5 -# -# A command line tool doing these steps and writing out data in HDF5 -# format is available as ``ctapipe-process`` -# - -import tempfile -from copy import deepcopy - -import astropy.units as u -from astropy.coordinates import AltAz, SkyCoord -from traitlets.config import Config - -from ctapipe.calib import CameraCalibrator -from ctapipe.containers import ImageParametersContainer -from ctapipe.image import ImageProcessor -from ctapipe.io import DataWriter, EventSource -from ctapipe.reco import ShowerProcessor -from ctapipe.utils.datasets import get_dataset_path - -image_processor_config = Config( - { - "ImageProcessor": { - "image_cleaner_type": "TailcutsImageCleaner", - "TailcutsImageCleaner": { - "picture_threshold_pe": [ - ("type", "LST_LST_LSTCam", 7.5), - ("type", "MST_MST_FlashCam", 8), - ("type", "MST_MST_NectarCam", 8), - ("type", "SST_ASTRI_CHEC", 7), - ], - "boundary_threshold_pe": [ - ("type", "LST_LST_LSTCam", 5), - ("type", "MST_MST_FlashCam", 4), - ("type", "MST_MST_NectarCam", 4), - ("type", "SST_ASTRI_CHEC", 4), - ], - }, - } - } -) - -input_url = get_dataset_path("gamma_prod5.simtel.zst") -source = EventSource(input_url) - -calibrator = CameraCalibrator(subarray=source.subarray) -image_processor = ImageProcessor( - subarray=source.subarray, config=image_processor_config -) -shower_processor = ShowerProcessor(subarray=source.subarray) -horizon_frame = AltAz() - -f = tempfile.NamedTemporaryFile(suffix=".hdf5") - -with DataWriter( - source, output_path=f.name, overwrite=True, write_showers=True -) as writer: - - for event in source: - energy = event.simulation.shower.energy - n_telescopes_r1 = len(event.r1.tel) - event_id = event.index.event_id - print(f"Id: {event_id}, E = {energy:1.3f}, Telescopes (R1): {n_telescopes_r1}") - - calibrator(event) - image_processor(event) - shower_processor(event) - - stereo = event.dl2.stereo.geometry["HillasReconstructor"] - if stereo.is_valid: - print(" Alt: {:.2f}°".format(stereo.alt.deg)) - print(" Az: {:.2f}°".format(stereo.az.deg)) - print(" Hmax: {:.0f}".format(stereo.h_max)) - print(" CoreX: {:.1f}".format(stereo.core_x)) - print(" CoreY: {:.1f}".format(stereo.core_y)) - print(" Multiplicity: {:d}".format(len(stereo.telescopes))) - - # save a nice event for plotting later - if event.count == 3: - plotting_event = deepcopy(event) - - writer(event) - -import pandas as pd -from astropy.coordinates.angle_utilities import angular_separation - -from ctapipe.io import TableLoader - -loader = TableLoader(f.name, load_dl2=True, load_simulated=True) - -events = loader.read_subarray_events() - -theta = angular_separation( - events["HillasReconstructor_az"].quantity, - events["HillasReconstructor_alt"].quantity, - events["true_az"].quantity, - events["true_alt"].quantity, -) - -plt.hist(theta.to_value(u.deg) ** 2, bins=25, range=[0, 0.3]) -plt.xlabel(r"$\theta² / deg²$") -None - - -###################################################################### -# ArrayDisplay -# ------------ -# - -from ctapipe.visualization import ArrayDisplay - -angle_offset = plotting_event.pointing.array_azimuth - -plotting_hillas = { - tel_id: dl1.parameters.hillas for tel_id, dl1 in plotting_event.dl1.tel.items() -} - -plotting_core = { - tel_id: dl1.parameters.core.psi for tel_id, dl1 in plotting_event.dl1.tel.items() -} - - -disp = ArrayDisplay(source.subarray) - -disp.set_line_hillas(plotting_hillas, plotting_core, 500) - -plt.scatter( - plotting_event.simulation.shower.core_x, - plotting_event.simulation.shower.core_y, - s=200, - c="k", - marker="x", - label="True Impact", -) -plt.scatter( - plotting_event.dl2.stereo.geometry["HillasReconstructor"].core_x, - plotting_event.dl2.stereo.geometry["HillasReconstructor"].core_y, - s=200, - c="r", - marker="x", - label="Estimated Impact", -) - -plt.legend() -# plt.xlim(-400, 400) -# plt.ylim(-400, 400) - - -###################################################################### -# Reading the LST dl1 data -# ~~~~~~~~~~~~~~~~~~~~~~~~ -# - -loader = TableLoader(f.name, load_simulated=True, load_dl1_parameters=True) - -dl1_table = loader.read_telescope_events(["LST_LST_LSTCam"]) - -plt.scatter( - np.log10(dl1_table["true_energy"].quantity / u.TeV), - np.log10(dl1_table["hillas_intensity"]), -) -plt.xlabel("log10(E / TeV)") -plt.ylabel("log10(intensity)") -None - - -###################################################################### -# Isn’t python slow? -# ------------------ -# -# - Many of you might have heard: “Python is slow”. -# - That’s trueish. -# - All python objects are classes living on the heap, even integers. -# - Looping over lots of “primitives” is quite slow compared to other -# languages. -# -# | ⇒ Vectorize as much as possible using numpy -# | ⇒ Use existing interfaces to fast C / C++ / Fortran code -# | ⇒ Optimize using numba -# -# **But: “Premature Optimization is the root of all evil” — Donald Knuth** -# -# So profile to find exactly what is slow. -# -# Why use python then? -# ~~~~~~~~~~~~~~~~~~~~ -# -# - Python works very well as *glue* for libraries of all kinds of -# languages -# - Python has a rich ecosystem for data science, physics, algorithms, -# astronomy -# -# Example: Number of Islands -# ~~~~~~~~~~~~~~~~~~~~~~~~~~ -# -# Find all groups of pixels, that survived the cleaning -# - -from ctapipe.image import toymodel -from ctapipe.instrument import SubarrayDescription - -geometry = loader.subarray.tel[1].camera.geometry - - -###################################################################### -# Let’s create a toy images with several islands; -# - -np.random.seed(42) - -image = np.zeros(geometry.n_pixels) - - -for i in range(9): - - model = toymodel.Gaussian( - x=np.random.uniform(-0.8, 0.8) * u.m, - y=np.random.uniform(-0.8, 0.8) * u.m, - width=np.random.uniform(0.05, 0.075) * u.m, - length=np.random.uniform(0.1, 0.15) * u.m, - psi=np.random.uniform(0, 2 * np.pi) * u.rad, - ) - - new_image, sig, bg = model.generate_image( - geometry, intensity=np.random.uniform(1000, 3000), nsb_level_pe=5 - ) - image += new_image - -clean = tailcuts_clean( - geometry, - image, - picture_thresh=10, - boundary_thresh=5, - min_number_picture_neighbors=2, -) - -disp = CameraDisplay(geometry) -disp.image = image -disp.highlight_pixels(clean, color="xkcd:red", linewidth=1.5) -disp.add_colorbar() - - -def num_islands_python(camera, clean): - """A breadth first search to find connected islands of neighboring pixels in the cleaning set""" - - # the camera geometry has a [n_pixel, n_pixel] boolean array - # that is True where two pixels are neighbors - neighbors = camera.neighbor_matrix - - island_ids = np.zeros(camera.n_pixels) - current_island = 0 - - # a set to remember which pixels we already visited - visited = set() - - # go only through the pixels, that survived cleaning - for pix_id in np.where(clean)[0]: - if pix_id not in visited: - # remember that we already checked this pixel - visited.add(pix_id) - - # if we land in the outer loop again, we found a new island - current_island += 1 - island_ids[pix_id] = current_island - - # now check all neighbors of the current pixel recursively - to_check = set(np.where(neighbors[pix_id] & clean)[0]) - while to_check: - pix_id = to_check.pop() - - if pix_id not in visited: - visited.add(pix_id) - island_ids[pix_id] = current_island - - to_check.update(np.where(neighbors[pix_id] & clean)[0]) - - n_islands = current_island - return n_islands, island_ids - - -n_islands, island_ids = num_islands_python(geometry, clean) - -from matplotlib.colors import ListedColormap - -cmap = plt.get_cmap("Paired") -cmap = ListedColormap(cmap.colors[:n_islands]) -cmap.set_under("k") - -disp = CameraDisplay(geometry) -disp.image = island_ids -disp.cmap = cmap -disp.set_limits_minmax(0.5, n_islands + 0.5) -disp.add_colorbar() - -# %timeit num_islands_python(geometry, clean) - -from scipy.sparse.csgraph import connected_components - - -def num_islands_scipy(geometry, clean): - neighbors = geometry.neighbor_matrix_sparse - - clean_neighbors = neighbors[clean][:, clean] - num_islands, labels = connected_components(clean_neighbors, directed=False) - - island_ids = np.zeros(geometry.n_pixels) - island_ids[clean] = labels + 1 - - return num_islands, island_ids - - -n_islands_s, island_ids_s = num_islands_scipy(geometry, clean) - -disp = CameraDisplay(geometry) -disp.image = island_ids_s -disp.cmap = cmap -disp.set_limits_minmax(0.5, n_islands_s + 0.5) -disp.add_colorbar() - -# %timeit num_islands_scipy(geometry, clean) - - -###################################################################### -# **A lot less code, and a factor 3 speed improvement** -# - - -###################################################################### -# Finally, current ctapipe implementation is using numba: -# - -# %timeit number_of_islands(geometry, clean) diff --git a/docs/tutorials/ctapipe_overview.rst b/docs/tutorials/ctapipe_overview.rst deleted file mode 100644 index 22c4e71a828..00000000000 --- a/docs/tutorials/ctapipe_overview.rst +++ /dev/null @@ -1,811 +0,0 @@ - -.. DO NOT EDIT. -.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. -.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: -.. "tutorials/ctapipe_overview.py" -.. LINE NUMBERS ARE GIVEN BELOW. - -.. only:: html - - .. note:: - :class: sphx-glr-download-link-note - - :ref:`Go to the end ` - to download the full example code - -.. rst-class:: sphx-glr-example-title - -.. _sphx_glr_tutorials_ctapipe_overview.py: - - -Analyzing Events Using ctapipe -============================== - -.. GENERATED FROM PYTHON SOURCE LINES 9-41 - -.. container:: - - .. raw:: html - -

- - Initially presented @ LST Analysis Bootcamp - - .. raw:: html - -

- - .. raw:: html - -

- - Padova, 26.11.2018 - - .. raw:: html - -

- - .. raw:: html - -

- - Maximilian Nöthe (@maxnoe) & Kai A. Brügge (@mackaiver) - - .. raw:: html - -

- - -.. GENERATED FROM PYTHON SOURCE LINES 41-52 - -.. code-block:: default - - - import matplotlib.pyplot as plt - import numpy as np - - # %matplotlib inline - - plt.rcParams["figure.figsize"] = (12, 8) - plt.rcParams["font.size"] = 14 - plt.rcParams["figure.figsize"] - - - -.. GENERATED FROM PYTHON SOURCE LINES 53-66 - -.. raw:: html - -

- -Table of Contents - -.. raw:: html - -

- -.. container:: - :name: toc - - -.. GENERATED FROM PYTHON SOURCE LINES 69-72 - -General Information -------------------- - - -.. GENERATED FROM PYTHON SOURCE LINES 75-90 - -Design -~~~~~~ - -- DL0 → DL3 analysis - -- Currently some R0 → DL2 code to be able to analyze simtel files - -- ctapipe is built upon the Scientific Python Stack, core dependencies - are - - - numpy - - scipy - - astropy - - numba - - -.. GENERATED FROM PYTHON SOURCE LINES 93-110 - -Developement -~~~~~~~~~~~~ - -- ctapipe is developed as Open Source Software (BSD 3-Clause License) - at https://github.com/cta-observatory/ctapipe - -- We use the “Github-Workflow”: - - - Few people (e.g. @kosack, @maxnoe) have write access to the main - repository - - Contributors fork the main repository and work on branches - - Pull Requests are merged after Code Review and automatic execution - of the test suite - -- Early developement stage ⇒ backwards-incompatible API changes might - and will happen - - -.. GENERATED FROM PYTHON SOURCE LINES 113-122 - -What’s there? -~~~~~~~~~~~~~ - -- Reading simtel simulation files -- Simple calibration, cleaning and feature extraction functions -- Camera and Array plotting -- Coordinate frames and transformations -- Stereo-reconstruction using line intersections - - -.. GENERATED FROM PYTHON SOURCE LINES 125-132 - -What’s still missing? -~~~~~~~~~~~~~~~~~~~~~ - -- Good integration with machine learning techniques -- IRF calculation -- Documentation, e.g. formal definitions of coordinate frames - - -.. GENERATED FROM PYTHON SOURCE LINES 135-149 - -What can you do? -~~~~~~~~~~~~~~~~ - -- Report issues - - - Hard to get started? Tell us where you are stuck - - Tell user stories - - Missing features - -- Start contributing - - - ctapipe needs more workpower - - Implement new reconstruction features - - -.. GENERATED FROM PYTHON SOURCE LINES 152-155 - -A simple hillas analysis ------------------------- - - -.. GENERATED FROM PYTHON SOURCE LINES 158-161 - -Reading in simtel files -~~~~~~~~~~~~~~~~~~~~~~~ - - -.. GENERATED FROM PYTHON SOURCE LINES 161-181 - -.. code-block:: default - - - from ctapipe.io import EventSource - from ctapipe.utils.datasets import get_dataset_path - - input_url = get_dataset_path("gamma_prod5.simtel.zst") - - # EventSource() automatically detects what kind of file we are giving it, - # if already supported by ctapipe - source = EventSource(input_url, max_events=5) - - print(type(source)) - - for event in source: - print( - "Id: {}, E = {:1.3f}, Telescopes: {}".format( - event.count, event.simulation.shower.energy, len(event.r0.tel) - ) - ) - - - -.. GENERATED FROM PYTHON SOURCE LINES 182-185 - -Each event is a ``DataContainer`` holding several ``Field``\ s of data, -which can be containers or just numbers. Let’s look a one event: - - -.. GENERATED FROM PYTHON SOURCE LINES 185-193 - -.. code-block:: default - - - event - - source.subarray.camera_types - - len(event.r0.tel), len(event.r1.tel) - - - -.. GENERATED FROM PYTHON SOURCE LINES 194-200 - -Data calibration -~~~~~~~~~~~~~~~~ - -The ``CameraCalibrator`` calibrates the event (obtaining the ``dl1`` -images). - - -.. GENERATED FROM PYTHON SOURCE LINES 200-208 - -.. code-block:: default - - - from ctapipe.calib import CameraCalibrator - - calibrator = CameraCalibrator(subarray=source.subarray) - - calibrator(event) - - - -.. GENERATED FROM PYTHON SOURCE LINES 209-214 - -Event displays -~~~~~~~~~~~~~~ - -Let’s use ctapipe’s plotting facilities to plot the telescope images - - -.. GENERATED FROM PYTHON SOURCE LINES 214-236 - -.. code-block:: default - - - event.dl1.tel.keys() - - tel_id = 130 - - geometry = source.subarray.tel[tel_id].camera.geometry - dl1 = event.dl1.tel[tel_id] - - geometry, dl1 - - dl1.image - - from ctapipe.visualization import CameraDisplay - - display = CameraDisplay(geometry) - - # right now, there might be one image per gain channel. - # This will change as soon as - display.image = dl1.image - display.add_colorbar() - - - -.. GENERATED FROM PYTHON SOURCE LINES 237-240 - -Image Cleaning -~~~~~~~~~~~~~~ - - -.. GENERATED FROM PYTHON SOURCE LINES 240-279 - -.. code-block:: default - - - from ctapipe.image.cleaning import tailcuts_clean - - # unoptimized cleaning levels - cleaning_level = { - "CHEC": (2, 4, 2), - "LSTCam": (3.5, 7, 2), - "FlashCam": (3.5, 7, 2), - "NectarCam": (4, 8, 2), - } - - boundary, picture, min_neighbors = cleaning_level[geometry.name] - - clean = tailcuts_clean( - geometry, - dl1.image, - boundary_thresh=boundary, - picture_thresh=picture, - min_number_picture_neighbors=min_neighbors, - ) - - fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 5)) - - d1 = CameraDisplay(geometry, ax=ax1) - d2 = CameraDisplay(geometry, ax=ax2) - - ax1.set_title("Image") - d1.image = dl1.image - d1.add_colorbar(ax=ax1) - - ax2.set_title("Pulse Time") - d2.image = dl1.peak_time - np.average(dl1.peak_time, weights=dl1.image) - d2.cmap = "RdBu_r" - d2.add_colorbar(ax=ax2) - d2.set_limits_minmax(-20, 20) - - d1.highlight_pixels(clean, color="red", linewidth=1) - - - -.. GENERATED FROM PYTHON SOURCE LINES 280-283 - -Image Parameters -~~~~~~~~~~~~~~~~ - - -.. GENERATED FROM PYTHON SOURCE LINES 283-334 - -.. code-block:: default - - - from ctapipe.image import ( - camera_to_shower_coordinates, - concentration_parameters, - hillas_parameters, - leakage_parameters, - number_of_islands, - timing_parameters, - ) - - hillas = hillas_parameters(geometry[clean], dl1.image[clean]) - - print(hillas) - - display = CameraDisplay(geometry) - - # set "unclean" pixels to 0 - cleaned = dl1.image.copy() - cleaned[~clean] = 0.0 - - display.image = cleaned - display.add_colorbar() - - display.overlay_moments(hillas, color="xkcd:red") - - timing = timing_parameters(geometry, dl1.image, dl1.peak_time, hillas, clean) - - print(timing) - - long, trans = camera_to_shower_coordinates( - geometry.pix_x, geometry.pix_y, hillas.x, hillas.y, hillas.psi - ) - - plt.plot(long[clean], dl1.peak_time[clean], "o") - plt.plot(long[clean], timing.slope * long[clean] + timing.intercept) - - l = leakage_parameters(geometry, dl1.image, clean) - print(l) - - disp = CameraDisplay(geometry) - disp.image = dl1.image - disp.highlight_pixels(geometry.get_border_pixel_mask(1), linewidth=2, color="xkcd:red") - - n_islands, island_id = number_of_islands(geometry, clean) - - print(n_islands) - - conc = concentration_parameters(geometry, dl1.image, hillas) - print(conc) - - - -.. GENERATED FROM PYTHON SOURCE LINES 335-349 - -Putting it all together / Stereo reconstruction -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -All these steps are now unified in several components configurable -through the config system, mainly: - -- CameraCalibrator for DL0 → DL1 (Images) -- ImageProcessor for DL1 (Images) → DL1 (Parameters) -- ShowerProcessor for stereo reconstruction of the shower geometry -- DataWriter for writing data into HDF5 - -A command line tool doing these steps and writing out data in HDF5 -format is available as ``ctapipe-process`` - - -.. GENERATED FROM PYTHON SOURCE LINES 349-448 - -.. code-block:: default - - - import tempfile - from copy import deepcopy - - import astropy.units as u - from astropy.coordinates import AltAz, SkyCoord - from traitlets.config import Config - - from ctapipe.calib import CameraCalibrator - from ctapipe.containers import ImageParametersContainer - from ctapipe.image import ImageProcessor - from ctapipe.io import DataWriter, EventSource - from ctapipe.reco import ShowerProcessor - from ctapipe.utils.datasets import get_dataset_path - - image_processor_config = Config( - { - "ImageProcessor": { - "image_cleaner_type": "TailcutsImageCleaner", - "TailcutsImageCleaner": { - "picture_threshold_pe": [ - ("type", "LST_LST_LSTCam", 7.5), - ("type", "MST_MST_FlashCam", 8), - ("type", "MST_MST_NectarCam", 8), - ("type", "SST_ASTRI_CHEC", 7), - ], - "boundary_threshold_pe": [ - ("type", "LST_LST_LSTCam", 5), - ("type", "MST_MST_FlashCam", 4), - ("type", "MST_MST_NectarCam", 4), - ("type", "SST_ASTRI_CHEC", 4), - ], - }, - } - } - ) - - input_url = get_dataset_path("gamma_prod5.simtel.zst") - source = EventSource(input_url) - - calibrator = CameraCalibrator(subarray=source.subarray) - image_processor = ImageProcessor( - subarray=source.subarray, config=image_processor_config - ) - shower_processor = ShowerProcessor(subarray=source.subarray) - horizon_frame = AltAz() - - f = tempfile.NamedTemporaryFile(suffix=".hdf5") - - with DataWriter( - source, output_path=f.name, overwrite=True, write_showers=True - ) as writer: - - for event in source: - energy = event.simulation.shower.energy - n_telescopes_r1 = len(event.r1.tel) - event_id = event.index.event_id - print(f"Id: {event_id}, E = {energy:1.3f}, Telescopes (R1): {n_telescopes_r1}") - - calibrator(event) - image_processor(event) - shower_processor(event) - - stereo = event.dl2.stereo.geometry["HillasReconstructor"] - if stereo.is_valid: - print(" Alt: {:.2f}°".format(stereo.alt.deg)) - print(" Az: {:.2f}°".format(stereo.az.deg)) - print(" Hmax: {:.0f}".format(stereo.h_max)) - print(" CoreX: {:.1f}".format(stereo.core_x)) - print(" CoreY: {:.1f}".format(stereo.core_y)) - print(" Multiplicity: {:d}".format(len(stereo.telescopes))) - - # save a nice event for plotting later - if event.count == 3: - plotting_event = deepcopy(event) - - writer(event) - - import pandas as pd - from astropy.coordinates.angle_utilities import angular_separation - - from ctapipe.io import TableLoader - - loader = TableLoader(f.name, load_dl2=True, load_simulated=True) - - events = loader.read_subarray_events() - - theta = angular_separation( - events["HillasReconstructor_az"].quantity, - events["HillasReconstructor_alt"].quantity, - events["true_az"].quantity, - events["true_alt"].quantity, - ) - - plt.hist(theta.to_value(u.deg) ** 2, bins=25, range=[0, 0.3]) - plt.xlabel(r"$\theta² / deg²$") - None - - - -.. GENERATED FROM PYTHON SOURCE LINES 449-452 - -ArrayDisplay ------------- - - -.. GENERATED FROM PYTHON SOURCE LINES 452-492 - -.. code-block:: default - - - from ctapipe.visualization import ArrayDisplay - - angle_offset = plotting_event.pointing.array_azimuth - - plotting_hillas = { - tel_id: dl1.parameters.hillas for tel_id, dl1 in plotting_event.dl1.tel.items() - } - - plotting_core = { - tel_id: dl1.parameters.core.psi for tel_id, dl1 in plotting_event.dl1.tel.items() - } - - - disp = ArrayDisplay(source.subarray) - - disp.set_line_hillas(plotting_hillas, plotting_core, 500) - - plt.scatter( - plotting_event.simulation.shower.core_x, - plotting_event.simulation.shower.core_y, - s=200, - c="k", - marker="x", - label="True Impact", - ) - plt.scatter( - plotting_event.dl2.stereo.geometry["HillasReconstructor"].core_x, - plotting_event.dl2.stereo.geometry["HillasReconstructor"].core_y, - s=200, - c="r", - marker="x", - label="Estimated Impact", - ) - - plt.legend() - # plt.xlim(-400, 400) - # plt.ylim(-400, 400) - - - -.. GENERATED FROM PYTHON SOURCE LINES 493-496 - -Reading the LST dl1 data -~~~~~~~~~~~~~~~~~~~~~~~~ - - -.. GENERATED FROM PYTHON SOURCE LINES 496-510 - -.. code-block:: default - - - loader = TableLoader(f.name, load_simulated=True, load_dl1_parameters=True) - - dl1_table = loader.read_telescope_events(["LST_LST_LSTCam"]) - - plt.scatter( - np.log10(dl1_table["true_energy"].quantity / u.TeV), - np.log10(dl1_table["hillas_intensity"]), - ) - plt.xlabel("log10(E / TeV)") - plt.ylabel("log10(intensity)") - None - - - -.. GENERATED FROM PYTHON SOURCE LINES 511-541 - -Isn’t python slow? ------------------- - -- Many of you might have heard: “Python is slow”. -- That’s trueish. -- All python objects are classes living on the heap, even integers. -- Looping over lots of “primitives” is quite slow compared to other - languages. - -| ⇒ Vectorize as much as possible using numpy -| ⇒ Use existing interfaces to fast C / C++ / Fortran code -| ⇒ Optimize using numba - -**But: “Premature Optimization is the root of all evil” — Donald Knuth** - -So profile to find exactly what is slow. - -Why use python then? -~~~~~~~~~~~~~~~~~~~~ - -- Python works very well as *glue* for libraries of all kinds of - languages -- Python has a rich ecosystem for data science, physics, algorithms, - astronomy - -Example: Number of Islands -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Find all groups of pixels, that survived the cleaning - - -.. GENERATED FROM PYTHON SOURCE LINES 541-548 - -.. code-block:: default - - - from ctapipe.image import toymodel - from ctapipe.instrument import SubarrayDescription - - geometry = loader.subarray.tel[1].camera.geometry - - - -.. GENERATED FROM PYTHON SOURCE LINES 549-551 - -Let’s create a toy images with several islands; - - -.. GENERATED FROM PYTHON SOURCE LINES 551-666 - -.. code-block:: default - - - np.random.seed(42) - - image = np.zeros(geometry.n_pixels) - - - for i in range(9): - - model = toymodel.Gaussian( - x=np.random.uniform(-0.8, 0.8) * u.m, - y=np.random.uniform(-0.8, 0.8) * u.m, - width=np.random.uniform(0.05, 0.075) * u.m, - length=np.random.uniform(0.1, 0.15) * u.m, - psi=np.random.uniform(0, 2 * np.pi) * u.rad, - ) - - new_image, sig, bg = model.generate_image( - geometry, intensity=np.random.uniform(1000, 3000), nsb_level_pe=5 - ) - image += new_image - - clean = tailcuts_clean( - geometry, - image, - picture_thresh=10, - boundary_thresh=5, - min_number_picture_neighbors=2, - ) - - disp = CameraDisplay(geometry) - disp.image = image - disp.highlight_pixels(clean, color="xkcd:red", linewidth=1.5) - disp.add_colorbar() - - - def num_islands_python(camera, clean): - """A breadth first search to find connected islands of neighboring pixels in the cleaning set""" - - # the camera geometry has a [n_pixel, n_pixel] boolean array - # that is True where two pixels are neighbors - neighbors = camera.neighbor_matrix - - island_ids = np.zeros(camera.n_pixels) - current_island = 0 - - # a set to remember which pixels we already visited - visited = set() - - # go only through the pixels, that survived cleaning - for pix_id in np.where(clean)[0]: - if pix_id not in visited: - # remember that we already checked this pixel - visited.add(pix_id) - - # if we land in the outer loop again, we found a new island - current_island += 1 - island_ids[pix_id] = current_island - - # now check all neighbors of the current pixel recursively - to_check = set(np.where(neighbors[pix_id] & clean)[0]) - while to_check: - pix_id = to_check.pop() - - if pix_id not in visited: - visited.add(pix_id) - island_ids[pix_id] = current_island - - to_check.update(np.where(neighbors[pix_id] & clean)[0]) - - n_islands = current_island - return n_islands, island_ids - - - n_islands, island_ids = num_islands_python(geometry, clean) - - from matplotlib.colors import ListedColormap - - cmap = plt.get_cmap("Paired") - cmap = ListedColormap(cmap.colors[:n_islands]) - cmap.set_under("k") - - disp = CameraDisplay(geometry) - disp.image = island_ids - disp.cmap = cmap - disp.set_limits_minmax(0.5, n_islands + 0.5) - disp.add_colorbar() - - # %timeit num_islands_python(geometry, clean) - - from scipy.sparse.csgraph import connected_components - - - def num_islands_scipy(geometry, clean): - neighbors = geometry.neighbor_matrix_sparse - - clean_neighbors = neighbors[clean][:, clean] - num_islands, labels = connected_components(clean_neighbors, directed=False) - - island_ids = np.zeros(geometry.n_pixels) - island_ids[clean] = labels + 1 - - return num_islands, island_ids - - - n_islands_s, island_ids_s = num_islands_scipy(geometry, clean) - - disp = CameraDisplay(geometry) - disp.image = island_ids_s - disp.cmap = cmap - disp.set_limits_minmax(0.5, n_islands_s + 0.5) - disp.add_colorbar() - - # %timeit num_islands_scipy(geometry, clean) - - - -.. GENERATED FROM PYTHON SOURCE LINES 667-669 - -**A lot less code, and a factor 3 speed improvement** - - -.. GENERATED FROM PYTHON SOURCE LINES 672-674 - -Finally, current ctapipe implementation is using numba: - - -.. GENERATED FROM PYTHON SOURCE LINES 674-676 - -.. code-block:: default - - - # %timeit number_of_islands(geometry, clean) - - -.. rst-class:: sphx-glr-timing - - **Total running time of the script:** ( 0 minutes 0.000 seconds) - - -.. _sphx_glr_download_tutorials_ctapipe_overview.py: - -.. only:: html - - .. container:: sphx-glr-footer sphx-glr-footer-example - - - - - .. container:: sphx-glr-download sphx-glr-download-python - - :download:`Download Python source code: ctapipe_overview.py ` - - .. container:: sphx-glr-download sphx-glr-download-jupyter - - :download:`Download Jupyter notebook: ctapipe_overview.ipynb ` - - -.. only:: html - - .. rst-class:: sphx-glr-signature - - `Gallery generated by Sphinx-Gallery `_ diff --git a/docs/tutorials/ctapipe_overview_codeobj.pickle b/docs/tutorials/ctapipe_overview_codeobj.pickle deleted file mode 100644 index c221a4892622b03dd12333e46d0a99abc883bd24..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3630 zcmbtXO>g5i5Y5(h;@XZIr`r#pz3rvF2<=Y@lC~(YXcyg}dnyc?Vl1|lD3DZk9iTu@ z1p??+_5b!!5-C}hH*uOvJTsif;e0$&e~tcqF+VE*@+p-y)q*?n|sea7&)V@m2OLU@cSacli&e*N^jTb7vDGE=nKWJ?Lh2{k0;DGRv7Zrh^U zc$5X#>{q|*zzT3ZCE6&NZh|b~MqBT$#sQ2|VSwj61UP2_%zJ1UXdh}aiAFsz1Ogm;4~|9U9YjbcNA{p=`~pi_EHkG zlSkQ70_-vQTtr-;F_tM&=rO}oQ_&t1Ku>*6TMs2izbk9y)1fbCRg zZ@ET*OSy;m0Kehg4AvXpArsr4f~{H7bjNWm!=Y0FGS%~%mbtd4M zrn~yB2=lq79CV@4_nHM%uN6rn+s%6nO=D#73au<}mRt*raT&IFGv)WMu`V-f6w_Il! z{=2H?IQc${JNVoXE@)=#Yml`v+tu&pw_FcO*y5Rb*gg77JgZoEDFyD!R$k^EeJ4A3 zAxk_v5Po}Foz{VW4xXpr_Nu}A25J8aZ1{K@o?R$KHr*<0YyVdfCReyj-zbj9mT#T5 z4&aY@xs^Sr=qvkhYfYcmbh6w$XeZ4xx4DDoKicbQm-V{(gHl?1^)pM{&*<> diff --git a/docs/tutorials/images/thumb/sphx_glr_calibrated_data_exploration_thumb.png b/docs/tutorials/images/thumb/sphx_glr_calibrated_data_exploration_thumb.png deleted file mode 100644 index 8a5fed589d17fe6ee62d6a9788519dba471fbd65..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26794 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 diff --git a/docs/tutorials/images/thumb/sphx_glr_coordinates_example_thumb.png b/docs/tutorials/images/thumb/sphx_glr_coordinates_example_thumb.png deleted file mode 100644 index 8a5fed589d17fe6ee62d6a9788519dba471fbd65..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26794 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 diff --git a/docs/tutorials/images/thumb/sphx_glr_ctapipe_handson_thumb.png b/docs/tutorials/images/thumb/sphx_glr_ctapipe_handson_thumb.png deleted file mode 100644 index 8a5fed589d17fe6ee62d6a9788519dba471fbd65..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26794 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 diff --git a/docs/tutorials/images/thumb/sphx_glr_ctapipe_overview_thumb.png b/docs/tutorials/images/thumb/sphx_glr_ctapipe_overview_thumb.png deleted file mode 100644 index 8a5fed589d17fe6ee62d6a9788519dba471fbd65..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26794 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 diff --git a/docs/tutorials/images/thumb/sphx_glr_ipynb_to_gallery_thumb.png b/docs/tutorials/images/thumb/sphx_glr_ipynb_to_gallery_thumb.png deleted file mode 100644 index 8a5fed589d17fe6ee62d6a9788519dba471fbd65..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26794 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 diff --git a/docs/tutorials/images/thumb/sphx_glr_raw_data_exploration_thumb.png b/docs/tutorials/images/thumb/sphx_glr_raw_data_exploration_thumb.png deleted file mode 100644 index 8a5fed589d17fe6ee62d6a9788519dba471fbd65..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26794 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 diff --git a/docs/tutorials/images/thumb/sphx_glr_theta_square_thumb.png b/docs/tutorials/images/thumb/sphx_glr_theta_square_thumb.png deleted file mode 100644 index 8a5fed589d17fe6ee62d6a9788519dba471fbd65..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26794 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 diff --git a/docs/tutorials/index.rst b/docs/tutorials/index.rst deleted file mode 100644 index 77b9f957cea..00000000000 --- a/docs/tutorials/index.rst +++ /dev/null @@ -1,152 +0,0 @@ -:orphan: - -.. _tutorials_gallery: - -Tutorials gallery -================= - -This gallery contains different tutorials of different use cases for ctapipe. - - - -.. raw:: html - -
- - -.. raw:: html - -
- -.. only:: html - - .. image:: /tutorials/images/thumb/sphx_glr_theta_square_thumb.png - :alt: - - :ref:`sphx_glr_tutorials_theta_square.py` - -.. raw:: html - -
Make a theta-square plot
-
- - -.. raw:: html - -
- -.. only:: html - - .. image:: /tutorials/images/thumb/sphx_glr_calibrated_data_exploration_thumb.png - :alt: - - :ref:`sphx_glr_tutorials_calibrated_data_exploration.py` - -.. raw:: html - -
Explore Calibrated Data
-
- - -.. raw:: html - -
- -.. only:: html - - .. image:: /tutorials/images/thumb/sphx_glr_raw_data_exploration_thumb.png - :alt: - - :ref:`sphx_glr_tutorials_raw_data_exploration.py` - -.. raw:: html - -
Exploring Raw Data
-
- - -.. raw:: html - -
- -.. only:: html - - .. image:: /tutorials/images/thumb/sphx_glr_ctapipe_handson_thumb.png - :alt: - - :ref:`sphx_glr_tutorials_ctapipe_handson.py` - -.. raw:: html - -
SyntaxError
-
- - -.. raw:: html - -
- -.. only:: html - - .. image:: /tutorials/images/thumb/sphx_glr_coordinates_example_thumb.png - :alt: - - :ref:`sphx_glr_tutorials_coordinates_example.py` - -.. raw:: html - -
Coordinates usage in ctapipe
-
- - -.. raw:: html - -
- -.. only:: html - - .. image:: /tutorials/images/thumb/sphx_glr_ctapipe_overview_thumb.png - :alt: - - :ref:`sphx_glr_tutorials_ctapipe_overview.py` - -.. raw:: html - -
Analyzing Events Using ctapipe
-
- - -.. raw:: html - -
- - -.. toctree:: - :hidden: - - /tutorials/theta_square - /tutorials/calibrated_data_exploration - /tutorials/raw_data_exploration - /tutorials/ctapipe_handson - /tutorials/coordinates_example - /tutorials/ctapipe_overview - - -.. only:: html - - .. container:: sphx-glr-footer sphx-glr-footer-gallery - - .. container:: sphx-glr-download sphx-glr-download-python - - :download:`Download all examples in Python source code: tutorials_python.zip ` - - .. container:: sphx-glr-download sphx-glr-download-jupyter - - :download:`Download all examples in Jupyter notebooks: tutorials_jupyter.zip ` - - -.. only:: html - - .. rst-class:: sphx-glr-signature - - `Gallery generated by Sphinx-Gallery `_ diff --git a/docs/tutorials/raw_data_exploration.ipynb b/docs/tutorials/raw_data_exploration.ipynb deleted file mode 100644 index 111668f5a6a..00000000000 --- a/docs/tutorials/raw_data_exploration.ipynb +++ /dev/null @@ -1,381 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n# Exploring Raw Data\n\nHere are just some very simple examples of going through and inspecting\nthe raw data, and making some plots using ``ctapipe``. The data explored\nhere are *raw Monte Carlo* data, which is Data Level \u201cR0\u201d in CTA\nterminology (e.g.\u00a0it is before any processing that would happen inside a\nCamera or off-line)\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Setup:\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "from astropy import units as u\nfrom matplotlib import pyplot as plt\n\nfrom ctapipe.instrument import CameraGeometry\nfrom ctapipe.io import EventSource\nfrom ctapipe.utils import get_dataset_path\nfrom ctapipe.visualization import CameraDisplay\n\n# %matplotlib inline" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To read SimTelArray format data, ctapipe uses the ``pyeventio`` library\n(which is installed automatically along with ctapipe). The following\nlines however will load any data known to ctapipe (multiple\n``EventSources`` are implemented, and chosen automatically based on the\ntype of the input file.\n\nAll data access first starts with an ``EventSource``, and here we use a\nhelper function ``event_source`` that constructs one. The resulting\n``source`` object can be iterated over like a list of events. We also\nhere use an ``EventSeeker`` which provides random-access to the source\n(by seeking to the given event ID or number)\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "source = EventSource(get_dataset_path(\"gamma_prod5.simtel.zst\"), max_events=5)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Explore the contents of an event\n\nnote that the R0 level is the raw data that comes out of a camera, and\nalso the lowest level of monte-carlo data.\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "# so we can advance through events one-by-one\nevent_iterator = iter(source)\n\nevent = next(event_iterator)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "the event is just a class with a bunch of data items in it. You can see\na more compact represntation via:\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "event.r0" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "printing the event structure, will currently print the value all items\nunder it (so you get a lot of output if you print a high-level\ncontainer):\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "print(event.simulation.shower)\n\nprint(event.r0.tel.keys())" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "note that the event has 3 telescopes in it: Let\u2019s try the next one:\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "event = next(event_iterator)\nprint(event.r0.tel.keys())" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "now, we have a larger event with many telescopes\u2026 Let\u2019s look at one of\nthem:\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "teldata = event.r0.tel[26]\nprint(teldata)\nteldata" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note that some values are unit quantities (``astropy.units.Quantity``)\nor angular quantities (``astropy.coordinates.Angle``), and you can\neasily maniuplate them:\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "event.simulation.shower.energy\n\nevent.simulation.shower.energy.to(\"GeV\")\n\nevent.simulation.shower.energy.to(\"J\")\n\nevent.simulation.shower.alt\n\nprint(\"Altitude in degrees:\", event.simulation.shower.alt.deg)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Look for signal pixels in a camera\n\nagain, ``event.r0.tel[x]`` contains a data structure for the telescope\ndata, with some fields like ``waveform``.\n\nLet\u2019s make a 2D plot of the sample data (sample vs pixel), so we can see\nif we see which pixels contain Cherenkov light signals:\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "plt.pcolormesh(teldata.waveform[0]) # note the [0] is for channel 0\nplt.colorbar()\nplt.xlabel(\"sample number\")\nplt.ylabel(\"Pixel_id\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let\u2019s zoom in to see if we can identify the pixels that have the\nCherenkov signal in them\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "plt.pcolormesh(teldata.waveform[0])\nplt.colorbar()\nplt.ylim(700, 750)\nplt.xlabel(\"sample number\")\nplt.ylabel(\"pixel_id\")\nprint(\"waveform[0] is an array of shape (N_pix,N_slice) =\", teldata.waveform[0].shape)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can really see that some pixels have a signal in them!\n\nLets look at a 1D plot of pixel 270 in channel 0 and see the signal:\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "trace = teldata.waveform[0][719]\nplt.plot(trace, drawstyle=\"steps\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Great! It looks like a *standard Cherenkov signal*!\n\nLet\u2019s take a look at several traces to see if the peaks area aligned:\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "for pix_id in range(718, 723):\n plt.plot(\n teldata.waveform[0][pix_id], label=\"pix {}\".format(pix_id), drawstyle=\"steps\"\n )\nplt.legend()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Look at the time trace from a Camera Pixel\n\n``ctapipe.calib.camera`` includes classes for doing automatic trace\nintegration with many methods, but before using that, let\u2019s just try to\ndo something simple!\n\nLet\u2019s define the integration windows first: By eye, they seem to be\nreaonsable from sample 8 to 13 for signal, and 20 to 29 for pedestal\n(which we define as the sum of all noise: NSB + electronic)\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "for pix_id in range(718, 723):\n plt.plot(teldata.waveform[0][pix_id], \"+-\")\nplt.fill_betweenx([0, 1600], 19, 24, color=\"red\", alpha=0.3, label=\"Ped window\")\nplt.fill_betweenx([0, 1600], 5, 9, color=\"green\", alpha=0.3, label=\"Signal window\")\nplt.legend()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Do a very simplisitic trace analysis\n\nNow, let\u2019s for example calculate a signal and background in a the fixed\nwindows we defined for this single event. Note we are ignoring the fact\nthat cameras have 2 gains, and just using a single gain (channel 0,\nwhich is the high-gain channel):\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "data = teldata.waveform[0]\npeds = data[:, 19:24].mean(axis=1) # mean of samples 20 to 29 for all pixels\nsums = data[:, 5:9].sum(axis=1) / (13 - 8) # simple sum integration\n\nphist = plt.hist(peds, bins=50, range=[0, 150])\nplt.title(\"Pedestal Distribution of all pixels for a single event\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "let\u2019s now take a look at the pedestal-subtracted sums and a\npedestal-subtracted signal:\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "plt.plot(sums - peds)\nplt.xlabel(\"pixel id\")\nplt.ylabel(\"Pedestal-subtracted Signal\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, we can clearly see that the signal is centered at 0 where there is\nno Cherenkov light, and we can also clearly see the shower around pixel\n250.\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "# we can also subtract the pedestals from the traces themselves, which would be needed to compare peaks properly\nfor ii in range(270, 280):\n plt.plot(data[ii] - peds[ii], drawstyle=\"steps\", label=\"pix{}\".format(ii))\nplt.legend()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Camera Displays\n\nIt\u2019s of course much easier to see the signal if we plot it in 2D with\ncorrect pixel positions!\n\n note: the instrument data model is not fully implemented, so there is\n not a good way to load all the camera information (right now it is\n hacked into the ``inst`` sub-container that is read from the\n Monte-Carlo file)\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "camgeom = source.subarray.tel[24].camera.geometry\n\ntitle = \"CT24, run {} event {} ped-sub\".format(event.index.obs_id, event.index.event_id)\ndisp = CameraDisplay(camgeom, title=title)\ndisp.image = sums - peds\ndisp.cmap = plt.cm.RdBu_r\ndisp.add_colorbar()\ndisp.set_limits_percent(95) # autoscale" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "It looks like a nice signal! We have plotted our pedestal-subtracted\ntrace integral, and see the shower clearly!\n\nLet\u2019s look at all telescopes:\n\n note we plot here the raw signal, since we have not calculated the\n pedestals for each)\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "for tel in event.r0.tel.keys():\n plt.figure()\n camgeom = source.subarray.tel[tel].camera.geometry\n title = \"CT{}, run {} event {}\".format(\n tel, event.index.obs_id, event.index.event_id\n )\n disp = CameraDisplay(camgeom, title=title)\n disp.image = event.r0.tel[tel].waveform[0].sum(axis=1)\n disp.cmap = plt.cm.RdBu_r\n disp.add_colorbar()\n disp.set_limits_percent(95)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## some signal processing\u2026\n\nLet\u2019s try to detect the peak using the scipy.signal package:\nhttps://docs.scipy.org/doc/scipy/reference/signal.html\n\n\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "import numpy as np\nfrom scipy import signal\n\npix_ids = np.arange(len(data))\nhas_signal = sums > 300\n\nwidths = np.array(\n [\n 8,\n ]\n) # peak widths to search for (let's fix it at 8 samples, about the width of the peak)\npeaks = [signal.find_peaks_cwt(trace, widths) for trace in data[has_signal]]\n\nfor p, s in zip(pix_ids[has_signal], peaks):\n print(\"pix{} has peaks at sample {}\".format(p, s))\n plt.plot(data[p], drawstyle=\"steps-mid\")\n plt.scatter(np.array(s), data[p, s])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "clearly the signal needs to be filtered first, or an appropriate wavelet\nused, but the idea is nice\n\n\n" - ] - } - ], - "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.9.16" - } - }, - "nbformat": 4, - "nbformat_minor": 0 -} \ No newline at end of file diff --git a/docs/tutorials/raw_data_exploration.py b/docs/tutorials/raw_data_exploration.py deleted file mode 100644 index b12c35ff70c..00000000000 --- a/docs/tutorials/raw_data_exploration.py +++ /dev/null @@ -1,303 +0,0 @@ -""" -Exploring Raw Data -================== - -Here are just some very simple examples of going through and inspecting -the raw data, and making some plots using ``ctapipe``. The data explored -here are *raw Monte Carlo* data, which is Data Level “R0” in CTA -terminology (e.g. it is before any processing that would happen inside a -Camera or off-line) - -""" - - -###################################################################### -# Setup: -# - -from astropy import units as u -from matplotlib import pyplot as plt - -from ctapipe.instrument import CameraGeometry -from ctapipe.io import EventSource -from ctapipe.utils import get_dataset_path -from ctapipe.visualization import CameraDisplay - -# %matplotlib inline - - -###################################################################### -# To read SimTelArray format data, ctapipe uses the ``pyeventio`` library -# (which is installed automatically along with ctapipe). The following -# lines however will load any data known to ctapipe (multiple -# ``EventSources`` are implemented, and chosen automatically based on the -# type of the input file. -# -# All data access first starts with an ``EventSource``, and here we use a -# helper function ``event_source`` that constructs one. The resulting -# ``source`` object can be iterated over like a list of events. We also -# here use an ``EventSeeker`` which provides random-access to the source -# (by seeking to the given event ID or number) -# - -source = EventSource(get_dataset_path("gamma_prod5.simtel.zst"), max_events=5) - - -###################################################################### -# Explore the contents of an event -# -------------------------------- -# -# note that the R0 level is the raw data that comes out of a camera, and -# also the lowest level of monte-carlo data. -# - -# so we can advance through events one-by-one -event_iterator = iter(source) - -event = next(event_iterator) - - -###################################################################### -# the event is just a class with a bunch of data items in it. You can see -# a more compact represntation via: -# - -event.r0 - - -###################################################################### -# printing the event structure, will currently print the value all items -# under it (so you get a lot of output if you print a high-level -# container): -# - -print(event.simulation.shower) - -print(event.r0.tel.keys()) - - -###################################################################### -# note that the event has 3 telescopes in it: Let’s try the next one: -# - -event = next(event_iterator) -print(event.r0.tel.keys()) - - -###################################################################### -# now, we have a larger event with many telescopes… Let’s look at one of -# them: -# - -teldata = event.r0.tel[26] -print(teldata) -teldata - - -###################################################################### -# Note that some values are unit quantities (``astropy.units.Quantity``) -# or angular quantities (``astropy.coordinates.Angle``), and you can -# easily maniuplate them: -# - -event.simulation.shower.energy - -event.simulation.shower.energy.to("GeV") - -event.simulation.shower.energy.to("J") - -event.simulation.shower.alt - -print("Altitude in degrees:", event.simulation.shower.alt.deg) - - -###################################################################### -# Look for signal pixels in a camera -# ---------------------------------- -# -# again, ``event.r0.tel[x]`` contains a data structure for the telescope -# data, with some fields like ``waveform``. -# -# Let’s make a 2D plot of the sample data (sample vs pixel), so we can see -# if we see which pixels contain Cherenkov light signals: -# - -plt.pcolormesh(teldata.waveform[0]) # note the [0] is for channel 0 -plt.colorbar() -plt.xlabel("sample number") -plt.ylabel("Pixel_id") - - -###################################################################### -# Let’s zoom in to see if we can identify the pixels that have the -# Cherenkov signal in them -# - -plt.pcolormesh(teldata.waveform[0]) -plt.colorbar() -plt.ylim(700, 750) -plt.xlabel("sample number") -plt.ylabel("pixel_id") -print("waveform[0] is an array of shape (N_pix,N_slice) =", teldata.waveform[0].shape) - - -###################################################################### -# Now we can really see that some pixels have a signal in them! -# -# Lets look at a 1D plot of pixel 270 in channel 0 and see the signal: -# - -trace = teldata.waveform[0][719] -plt.plot(trace, drawstyle="steps") - - -###################################################################### -# Great! It looks like a *standard Cherenkov signal*! -# -# Let’s take a look at several traces to see if the peaks area aligned: -# - -for pix_id in range(718, 723): - plt.plot( - teldata.waveform[0][pix_id], label="pix {}".format(pix_id), drawstyle="steps" - ) -plt.legend() - - -###################################################################### -# Look at the time trace from a Camera Pixel -# ------------------------------------------ -# -# ``ctapipe.calib.camera`` includes classes for doing automatic trace -# integration with many methods, but before using that, let’s just try to -# do something simple! -# -# Let’s define the integration windows first: By eye, they seem to be -# reaonsable from sample 8 to 13 for signal, and 20 to 29 for pedestal -# (which we define as the sum of all noise: NSB + electronic) -# - -for pix_id in range(718, 723): - plt.plot(teldata.waveform[0][pix_id], "+-") -plt.fill_betweenx([0, 1600], 19, 24, color="red", alpha=0.3, label="Ped window") -plt.fill_betweenx([0, 1600], 5, 9, color="green", alpha=0.3, label="Signal window") -plt.legend() - - -###################################################################### -# Do a very simplisitic trace analysis -# ------------------------------------ -# -# Now, let’s for example calculate a signal and background in a the fixed -# windows we defined for this single event. Note we are ignoring the fact -# that cameras have 2 gains, and just using a single gain (channel 0, -# which is the high-gain channel): -# - -data = teldata.waveform[0] -peds = data[:, 19:24].mean(axis=1) # mean of samples 20 to 29 for all pixels -sums = data[:, 5:9].sum(axis=1) / (13 - 8) # simple sum integration - -phist = plt.hist(peds, bins=50, range=[0, 150]) -plt.title("Pedestal Distribution of all pixels for a single event") - - -###################################################################### -# let’s now take a look at the pedestal-subtracted sums and a -# pedestal-subtracted signal: -# - -plt.plot(sums - peds) -plt.xlabel("pixel id") -plt.ylabel("Pedestal-subtracted Signal") - - -###################################################################### -# Now, we can clearly see that the signal is centered at 0 where there is -# no Cherenkov light, and we can also clearly see the shower around pixel -# 250. -# - -# we can also subtract the pedestals from the traces themselves, which would be needed to compare peaks properly -for ii in range(270, 280): - plt.plot(data[ii] - peds[ii], drawstyle="steps", label="pix{}".format(ii)) -plt.legend() - - -###################################################################### -# Camera Displays -# --------------- -# -# It’s of course much easier to see the signal if we plot it in 2D with -# correct pixel positions! -# -# note: the instrument data model is not fully implemented, so there is -# not a good way to load all the camera information (right now it is -# hacked into the ``inst`` sub-container that is read from the -# Monte-Carlo file) -# - -camgeom = source.subarray.tel[24].camera.geometry - -title = "CT24, run {} event {} ped-sub".format(event.index.obs_id, event.index.event_id) -disp = CameraDisplay(camgeom, title=title) -disp.image = sums - peds -disp.cmap = plt.cm.RdBu_r -disp.add_colorbar() -disp.set_limits_percent(95) # autoscale - - -###################################################################### -# It looks like a nice signal! We have plotted our pedestal-subtracted -# trace integral, and see the shower clearly! -# -# Let’s look at all telescopes: -# -# note we plot here the raw signal, since we have not calculated the -# pedestals for each) -# - -for tel in event.r0.tel.keys(): - plt.figure() - camgeom = source.subarray.tel[tel].camera.geometry - title = "CT{}, run {} event {}".format( - tel, event.index.obs_id, event.index.event_id - ) - disp = CameraDisplay(camgeom, title=title) - disp.image = event.r0.tel[tel].waveform[0].sum(axis=1) - disp.cmap = plt.cm.RdBu_r - disp.add_colorbar() - disp.set_limits_percent(95) - - -###################################################################### -# some signal processing… -# ----------------------- -# -# Let’s try to detect the peak using the scipy.signal package: -# https://docs.scipy.org/doc/scipy/reference/signal.html -# - -import numpy as np -from scipy import signal - -pix_ids = np.arange(len(data)) -has_signal = sums > 300 - -widths = np.array( - [ - 8, - ] -) # peak widths to search for (let's fix it at 8 samples, about the width of the peak) -peaks = [signal.find_peaks_cwt(trace, widths) for trace in data[has_signal]] - -for p, s in zip(pix_ids[has_signal], peaks): - print("pix{} has peaks at sample {}".format(p, s)) - plt.plot(data[p], drawstyle="steps-mid") - plt.scatter(np.array(s), data[p, s]) - - -###################################################################### -# clearly the signal needs to be filtered first, or an appropriate wavelet -# used, but the idea is nice -# diff --git a/docs/tutorials/raw_data_exploration.rst b/docs/tutorials/raw_data_exploration.rst deleted file mode 100644 index 8d02f639198..00000000000 --- a/docs/tutorials/raw_data_exploration.rst +++ /dev/null @@ -1,483 +0,0 @@ - -.. DO NOT EDIT. -.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. -.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: -.. "tutorials/raw_data_exploration.py" -.. LINE NUMBERS ARE GIVEN BELOW. - -.. only:: html - - .. note:: - :class: sphx-glr-download-link-note - - :ref:`Go to the end ` - to download the full example code - -.. rst-class:: sphx-glr-example-title - -.. _sphx_glr_tutorials_raw_data_exploration.py: - - -Exploring Raw Data -================== - -Here are just some very simple examples of going through and inspecting -the raw data, and making some plots using ``ctapipe``. The data explored -here are *raw Monte Carlo* data, which is Data Level “R0” in CTA -terminology (e.g. it is before any processing that would happen inside a -Camera or off-line) - -.. GENERATED FROM PYTHON SOURCE LINES 15-17 - -Setup: - - -.. GENERATED FROM PYTHON SOURCE LINES 17-29 - -.. code-block:: default - - - from astropy import units as u - from matplotlib import pyplot as plt - - from ctapipe.instrument import CameraGeometry - from ctapipe.io import EventSource - from ctapipe.utils import get_dataset_path - from ctapipe.visualization import CameraDisplay - - # %matplotlib inline - - - -.. GENERATED FROM PYTHON SOURCE LINES 30-42 - -To read SimTelArray format data, ctapipe uses the ``pyeventio`` library -(which is installed automatically along with ctapipe). The following -lines however will load any data known to ctapipe (multiple -``EventSources`` are implemented, and chosen automatically based on the -type of the input file. - -All data access first starts with an ``EventSource``, and here we use a -helper function ``event_source`` that constructs one. The resulting -``source`` object can be iterated over like a list of events. We also -here use an ``EventSeeker`` which provides random-access to the source -(by seeking to the given event ID or number) - - -.. GENERATED FROM PYTHON SOURCE LINES 42-46 - -.. code-block:: default - - - source = EventSource(get_dataset_path("gamma_prod5.simtel.zst"), max_events=5) - - - -.. GENERATED FROM PYTHON SOURCE LINES 47-53 - -Explore the contents of an event --------------------------------- - -note that the R0 level is the raw data that comes out of a camera, and -also the lowest level of monte-carlo data. - - -.. GENERATED FROM PYTHON SOURCE LINES 53-60 - -.. code-block:: default - - - # so we can advance through events one-by-one - event_iterator = iter(source) - - event = next(event_iterator) - - - -.. GENERATED FROM PYTHON SOURCE LINES 61-64 - -the event is just a class with a bunch of data items in it. You can see -a more compact represntation via: - - -.. GENERATED FROM PYTHON SOURCE LINES 64-68 - -.. code-block:: default - - - event.r0 - - - -.. GENERATED FROM PYTHON SOURCE LINES 69-73 - -printing the event structure, will currently print the value all items -under it (so you get a lot of output if you print a high-level -container): - - -.. GENERATED FROM PYTHON SOURCE LINES 73-79 - -.. code-block:: default - - - print(event.simulation.shower) - - print(event.r0.tel.keys()) - - - -.. GENERATED FROM PYTHON SOURCE LINES 80-82 - -note that the event has 3 telescopes in it: Let’s try the next one: - - -.. GENERATED FROM PYTHON SOURCE LINES 82-87 - -.. code-block:: default - - - event = next(event_iterator) - print(event.r0.tel.keys()) - - - -.. GENERATED FROM PYTHON SOURCE LINES 88-91 - -now, we have a larger event with many telescopes… Let’s look at one of -them: - - -.. GENERATED FROM PYTHON SOURCE LINES 91-97 - -.. code-block:: default - - - teldata = event.r0.tel[26] - print(teldata) - teldata - - - -.. GENERATED FROM PYTHON SOURCE LINES 98-102 - -Note that some values are unit quantities (``astropy.units.Quantity``) -or angular quantities (``astropy.coordinates.Angle``), and you can -easily maniuplate them: - - -.. GENERATED FROM PYTHON SOURCE LINES 102-114 - -.. code-block:: default - - - event.simulation.shower.energy - - event.simulation.shower.energy.to("GeV") - - event.simulation.shower.energy.to("J") - - event.simulation.shower.alt - - print("Altitude in degrees:", event.simulation.shower.alt.deg) - - - -.. GENERATED FROM PYTHON SOURCE LINES 115-124 - -Look for signal pixels in a camera ----------------------------------- - -again, ``event.r0.tel[x]`` contains a data structure for the telescope -data, with some fields like ``waveform``. - -Let’s make a 2D plot of the sample data (sample vs pixel), so we can see -if we see which pixels contain Cherenkov light signals: - - -.. GENERATED FROM PYTHON SOURCE LINES 124-131 - -.. code-block:: default - - - plt.pcolormesh(teldata.waveform[0]) # note the [0] is for channel 0 - plt.colorbar() - plt.xlabel("sample number") - plt.ylabel("Pixel_id") - - - -.. GENERATED FROM PYTHON SOURCE LINES 132-135 - -Let’s zoom in to see if we can identify the pixels that have the -Cherenkov signal in them - - -.. GENERATED FROM PYTHON SOURCE LINES 135-144 - -.. code-block:: default - - - plt.pcolormesh(teldata.waveform[0]) - plt.colorbar() - plt.ylim(700, 750) - plt.xlabel("sample number") - plt.ylabel("pixel_id") - print("waveform[0] is an array of shape (N_pix,N_slice) =", teldata.waveform[0].shape) - - - -.. GENERATED FROM PYTHON SOURCE LINES 145-149 - -Now we can really see that some pixels have a signal in them! - -Lets look at a 1D plot of pixel 270 in channel 0 and see the signal: - - -.. GENERATED FROM PYTHON SOURCE LINES 149-154 - -.. code-block:: default - - - trace = teldata.waveform[0][719] - plt.plot(trace, drawstyle="steps") - - - -.. GENERATED FROM PYTHON SOURCE LINES 155-159 - -Great! It looks like a *standard Cherenkov signal*! - -Let’s take a look at several traces to see if the peaks area aligned: - - -.. GENERATED FROM PYTHON SOURCE LINES 159-167 - -.. code-block:: default - - - for pix_id in range(718, 723): - plt.plot( - teldata.waveform[0][pix_id], label="pix {}".format(pix_id), drawstyle="steps" - ) - plt.legend() - - - -.. GENERATED FROM PYTHON SOURCE LINES 168-179 - -Look at the time trace from a Camera Pixel ------------------------------------------- - -``ctapipe.calib.camera`` includes classes for doing automatic trace -integration with many methods, but before using that, let’s just try to -do something simple! - -Let’s define the integration windows first: By eye, they seem to be -reaonsable from sample 8 to 13 for signal, and 20 to 29 for pedestal -(which we define as the sum of all noise: NSB + electronic) - - -.. GENERATED FROM PYTHON SOURCE LINES 179-187 - -.. code-block:: default - - - for pix_id in range(718, 723): - plt.plot(teldata.waveform[0][pix_id], "+-") - plt.fill_betweenx([0, 1600], 19, 24, color="red", alpha=0.3, label="Ped window") - plt.fill_betweenx([0, 1600], 5, 9, color="green", alpha=0.3, label="Signal window") - plt.legend() - - - -.. GENERATED FROM PYTHON SOURCE LINES 188-196 - -Do a very simplisitic trace analysis ------------------------------------- - -Now, let’s for example calculate a signal and background in a the fixed -windows we defined for this single event. Note we are ignoring the fact -that cameras have 2 gains, and just using a single gain (channel 0, -which is the high-gain channel): - - -.. GENERATED FROM PYTHON SOURCE LINES 196-205 - -.. code-block:: default - - - data = teldata.waveform[0] - peds = data[:, 19:24].mean(axis=1) # mean of samples 20 to 29 for all pixels - sums = data[:, 5:9].sum(axis=1) / (13 - 8) # simple sum integration - - phist = plt.hist(peds, bins=50, range=[0, 150]) - plt.title("Pedestal Distribution of all pixels for a single event") - - - -.. GENERATED FROM PYTHON SOURCE LINES 206-209 - -let’s now take a look at the pedestal-subtracted sums and a -pedestal-subtracted signal: - - -.. GENERATED FROM PYTHON SOURCE LINES 209-215 - -.. code-block:: default - - - plt.plot(sums - peds) - plt.xlabel("pixel id") - plt.ylabel("Pedestal-subtracted Signal") - - - -.. GENERATED FROM PYTHON SOURCE LINES 216-220 - -Now, we can clearly see that the signal is centered at 0 where there is -no Cherenkov light, and we can also clearly see the shower around pixel -250. - - -.. GENERATED FROM PYTHON SOURCE LINES 220-227 - -.. code-block:: default - - - # we can also subtract the pedestals from the traces themselves, which would be needed to compare peaks properly - for ii in range(270, 280): - plt.plot(data[ii] - peds[ii], drawstyle="steps", label="pix{}".format(ii)) - plt.legend() - - - -.. GENERATED FROM PYTHON SOURCE LINES 228-239 - -Camera Displays ---------------- - -It’s of course much easier to see the signal if we plot it in 2D with -correct pixel positions! - - note: the instrument data model is not fully implemented, so there is - not a good way to load all the camera information (right now it is - hacked into the ``inst`` sub-container that is read from the - Monte-Carlo file) - - -.. GENERATED FROM PYTHON SOURCE LINES 239-250 - -.. code-block:: default - - - camgeom = source.subarray.tel[24].camera.geometry - - title = "CT24, run {} event {} ped-sub".format(event.index.obs_id, event.index.event_id) - disp = CameraDisplay(camgeom, title=title) - disp.image = sums - peds - disp.cmap = plt.cm.RdBu_r - disp.add_colorbar() - disp.set_limits_percent(95) # autoscale - - - -.. GENERATED FROM PYTHON SOURCE LINES 251-259 - -It looks like a nice signal! We have plotted our pedestal-subtracted -trace integral, and see the shower clearly! - -Let’s look at all telescopes: - - note we plot here the raw signal, since we have not calculated the - pedestals for each) - - -.. GENERATED FROM PYTHON SOURCE LINES 259-273 - -.. code-block:: default - - - for tel in event.r0.tel.keys(): - plt.figure() - camgeom = source.subarray.tel[tel].camera.geometry - title = "CT{}, run {} event {}".format( - tel, event.index.obs_id, event.index.event_id - ) - disp = CameraDisplay(camgeom, title=title) - disp.image = event.r0.tel[tel].waveform[0].sum(axis=1) - disp.cmap = plt.cm.RdBu_r - disp.add_colorbar() - disp.set_limits_percent(95) - - - -.. GENERATED FROM PYTHON SOURCE LINES 274-280 - -some signal processing… ------------------------ - -Let’s try to detect the peak using the scipy.signal package: -https://docs.scipy.org/doc/scipy/reference/signal.html - - -.. GENERATED FROM PYTHON SOURCE LINES 280-300 - -.. code-block:: default - - - import numpy as np - from scipy import signal - - pix_ids = np.arange(len(data)) - has_signal = sums > 300 - - widths = np.array( - [ - 8, - ] - ) # peak widths to search for (let's fix it at 8 samples, about the width of the peak) - peaks = [signal.find_peaks_cwt(trace, widths) for trace in data[has_signal]] - - for p, s in zip(pix_ids[has_signal], peaks): - print("pix{} has peaks at sample {}".format(p, s)) - plt.plot(data[p], drawstyle="steps-mid") - plt.scatter(np.array(s), data[p, s]) - - - -.. GENERATED FROM PYTHON SOURCE LINES 301-304 - -clearly the signal needs to be filtered first, or an appropriate wavelet -used, but the idea is nice - - - -.. rst-class:: sphx-glr-timing - - **Total running time of the script:** ( 0 minutes 0.000 seconds) - - -.. _sphx_glr_download_tutorials_raw_data_exploration.py: - -.. only:: html - - .. container:: sphx-glr-footer sphx-glr-footer-example - - - - - .. container:: sphx-glr-download sphx-glr-download-python - - :download:`Download Python source code: raw_data_exploration.py ` - - .. container:: sphx-glr-download sphx-glr-download-jupyter - - :download:`Download Jupyter notebook: raw_data_exploration.ipynb ` - - -.. only:: html - - .. rst-class:: sphx-glr-signature - - `Gallery generated by Sphinx-Gallery `_ diff --git a/docs/tutorials/raw_data_exploration_codeobj.pickle b/docs/tutorials/raw_data_exploration_codeobj.pickle deleted file mode 100644 index be2794c7a1b39ff968553bcf0b5d4da46add4688..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1597 zcmbVMJ#X7E5ba%qmfzp?J1C{vX=UJc!eq>43sj*F1FwF zAQ%$V=GZ{D5lp9dSTvHJ43rmL)Z=p9T~?q4t2M)YDq8nt%J@Y#IhH#on0&GRCETDA z4BAoijJDEOLl*a_8esSvT(zA1YmwoIt@CUPT+2Pk@r2dL1o>V&QH|Ob*f+w~VR?c< za*6j?rMLO#CYww~J+_+fo|QHwl}*3AE{8fGkAp0%yaoAWzLp>z zoEi8wH_)CL=y8yND}@CIW^WG9GeO~(y` - to download the full example code - -.. rst-class:: sphx-glr-example-title - -.. _sphx_glr_tutorials_theta_square.py: - - -Make a theta-square plot -======================== - -This is a basic example to analyze some events and make a -:math:`\Theta^2` plot - -.. GENERATED FROM PYTHON SOURCE LINES 9-24 - -.. code-block:: default - - - # %matplotlib inline - - import matplotlib.pyplot as plt - import numpy as np - from astropy import units as u - from astropy.coordinates import AltAz, SkyCoord - from astropy.coordinates.angle_utilities import angular_separation - from tqdm.auto import tqdm - - from ctapipe.calib import CameraCalibrator - from ctapipe.image import ImageProcessor - from ctapipe.io import EventSource - from ctapipe.reco import ShowerProcessor - - -.. GENERATED FROM PYTHON SOURCE LINES 25-27 - -Get source events in MC dataset. - - -.. GENERATED FROM PYTHON SOURCE LINES 27-61 - -.. code-block:: default - - - source = EventSource( - "dataset://gamma_prod5.simtel.zst", - # allowed_tels={1, 2, 3, 4}, - ) - - subarray = source.subarray - - calib = CameraCalibrator(subarray=subarray) - image_processor = ImageProcessor(subarray=subarray) - shower_processor = ShowerProcessor(subarray=subarray) - - off_angles = [] - - for event in tqdm(source): - - # calibrating the event - calib(event) - image_processor(event) - shower_processor(event) - - reco_result = event.dl2.stereo.geometry["HillasReconstructor"] - - # get angular offset between reconstructed shower direction and MC - # generated shower direction - true_shower = event.simulation.shower - off_angle = angular_separation( - true_shower.az, true_shower.alt, reco_result.az, reco_result.alt - ) - - # Appending all estimated off angles - off_angles.append(off_angle.to(u.deg).value) - - - -.. GENERATED FROM PYTHON SOURCE LINES 62-64 - -calculate theta square for angles which are not nan - - -.. GENERATED FROM PYTHON SOURCE LINES 64-69 - -.. code-block:: default - - - off_angles = np.array(off_angles) - thetasquare = off_angles[np.isfinite(off_angles)] ** 2 - - - -.. GENERATED FROM PYTHON SOURCE LINES 70-73 - -Plot the results ----------------- - - -.. GENERATED FROM PYTHON SOURCE LINES 73-78 - -.. code-block:: default - - - plt.hist(thetasquare, bins=10, range=[0, 0.4]) - plt.xlabel(r"$\theta^2$ (deg)") - plt.ylabel("# of events") - plt.show() - - -.. rst-class:: sphx-glr-timing - - **Total running time of the script:** ( 0 minutes 0.000 seconds) - - -.. _sphx_glr_download_tutorials_theta_square.py: - -.. only:: html - - .. container:: sphx-glr-footer sphx-glr-footer-example - - - - - .. container:: sphx-glr-download sphx-glr-download-python - - :download:`Download Python source code: theta_square.py ` - - .. container:: sphx-glr-download sphx-glr-download-jupyter - - :download:`Download Jupyter notebook: theta_square.ipynb ` - - -.. only:: html - - .. rst-class:: sphx-glr-signature - - `Gallery generated by Sphinx-Gallery `_ diff --git a/docs/tutorials/theta_square_codeobj.pickle b/docs/tutorials/theta_square_codeobj.pickle deleted file mode 100644 index d6d799fa6ef65c8c5520b0337d367dfb0a4a4298..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1131 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 H`tAP#;e@>v