Note
Go to the end to download the full example code.
Working with Instrumental Descriptions#
the instrumental description is loaded by the event source, and consists
of a hierarchy of classes in the ctapipe.instrument module, the base of
which is the SubarrayDescription
11 from astropy.coordinates import SkyCoord
12
13 from ctapipe.io import EventSource
14 from ctapipe.utils.datasets import get_dataset_path
15 from ctapipe.visualization import CameraDisplay
16
17 filename = get_dataset_path("gamma_prod5.simtel.zst")
18
19 with EventSource(filename, max_events=1) as source:
20 subarray = source.subarray
the SubarrayDescription:#
28 subarray.info()
Subarray : MonteCarloArray
Num Tels : 180
Footprint: 4.92 km2
Height : 2147.00 m
Lon/Lat : 0.0 deg, 0.0 deg
Type Count Tel IDs
----------------- ----- ---------------
SST_ASTRI_CHEC 120 30-99,131-180
LST_LST_LSTCam 4 1-4
MST_MST_NectarCam 28 100-124,128-130
MST_MST_FlashCam 28 5-29,125-127
31 subarray.to_table()
You can also get a table of just the OpticsDescriptions
(CameraGeometry
is more complex and can’t be stored on a single
table row, so each one can be converted to a table separately)
40 subarray.to_table(kind="optics")
Make a sub-array with only SC-type telescopes:
47 sc_tels = [tel_id for tel_id, tel in subarray.tel.items() if tel.optics.n_mirrors == 2]
48 newsub = subarray.select_subarray(sc_tels, name="SCTels")
49 newsub.info()
Subarray : SCTels
Num Tels : 120
Footprint: 4.92 km2
Height : 2147.00 m
Lon/Lat : 0.0 deg, 0.0 deg
Type Count Tel IDs
-------------- ----- -------------
SST_ASTRI_CHEC 120 30-99,131-180
can also do this by using Table.group_by
Explore some of the details of the telescopes#
62 tel = subarray.tel[1]
63 tel
TelescopeDescription(type='LST', optics_name='LST', camera_name='LSTCam')
<Quantity 386.73324585 m2>
198
<Quantity 28. m>
75 tel.camera
CameraDescription(name=LSTCam, geometry=LSTCam, readout=LSTCam)
<Quantity [ 0. , -0.0377967 , -0.04724547, ..., 0.67088033,
-0.45356484, -0.50081024] m>
%matplotlib inline
83 CameraDisplay(tel.camera.geometry)
<ctapipe.visualization.mpl_camera.CameraDisplay object at 0x7f7469722e30>
86 CameraDisplay(subarray.tel[98].camera.geometry)
<ctapipe.visualization.mpl_camera.CameraDisplay object at 0x7f746bde3ee0>
Plot the subarray#
We’ll make a subarray by telescope type and plot each separately, so they appear in different colors. We also calculate the radius using the mirror area (and exaggerate it a bit).
This is just for debugging and info, for any “real” use, a
visualization.ArrayDisplay
should be used
101 subarray.peek()
<ctapipe.visualization.mpl_array.ArrayDisplay object at 0x7f74693e0790>
104 subarray.footprint
<Quantity 4.92346317 km2>
Get info about the subarray in general#
112 subarray.telescope_types
(TelescopeDescription(type='SST', optics_name='ASTRI', camera_name='CHEC'), TelescopeDescription(type='LST', optics_name='LST', camera_name='LSTCam'), TelescopeDescription(type='MST', optics_name='MST', camera_name='NectarCam'), TelescopeDescription(type='MST', optics_name='MST', camera_name='FlashCam'))
115 subarray.camera_types
(CameraDescription(name=CHEC, geometry=CHEC, readout=CHEC), CameraDescription(name=FlashCam, geometry=FlashCam, readout=FlashCam), CameraDescription(name=LSTCam, geometry=LSTCam, readout=LSTCam), CameraDescription(name=NectarCam, geometry=NectarCam, readout=NectarCam))
118 subarray.optics_types
(OpticsDescription(name=ASTRI, size_type=SST, reflector_shape=SCHWARZSCHILD_COUDER, equivalent_focal_length=2.15 m, effective_focal_length=2.15 m, n_mirrors=2, mirror_area=14.13 m2), OpticsDescription(name=LST, size_type=LST, reflector_shape=PARABOLIC, equivalent_focal_length=28.00 m, effective_focal_length=29.31 m, n_mirrors=1, mirror_area=386.73 m2), OpticsDescription(name=MST, size_type=MST, reflector_shape=HYBRID, equivalent_focal_length=16.00 m, effective_focal_length=16.45 m, n_mirrors=1, mirror_area=106.24 m2))
/home/docs/checkouts/readthedocs.org/user_builds/ctapipe/envs/stable/lib/python3.10/site-packages/astropy/coordinates/baseframe.py:1781: NonRotationTransformationWarning: transforming other coordinates from <GroundFrame Frame (reference_location=None)> to <GroundFrame Frame (reference_location=(6380284., 0., 0.) m)>. Angular separation can depend on the direction of the transformation.
warnings.warn(NonRotationTransformationWarning(self, other_frame))
<Angle [115.63014925, 23.28019825, 94.78251809, 160.63833105,
90.03968582, 101.62099853, 101.77713186, 78.30773406,
78.17454627, 45.45999318, 16.99024097, 39.97681403,
69.10011445, 110.92884517, 139.89780763, 161.89929049,
134.2346161 , 45.32551882, 15.68600633, 12.39167346,
39.26720394, 69.03997654, 111.01749555, 140.58856049,
166.95920229, 163.5926509 , 134.48337671, 11.93286185,
167.6312177 , 26.03184384, 49.71482147, 130.25249696,
153.46499701, 56.96848545, 80.68305003, 99.34352352,
122.90613377, 78.14518161, 101.82393586, 34.03013531,
57.77812763, 122.25987001, 145.65400609, 1.24847673,
24.4351971 , 155.4045918 , 176.51634911, 78.14317624,
101.82029017, 15.42110816, 39.11960335, 140.84366604,
164.08053533, 45.2944 , 69.0116324 , 111.02764679,
134.53170892, 11.86334528, 167.95021132, 62.66858341,
86.38258597, 93.62776638, 117.24715339, 78.14629175,
101.82276291, 28.82116959, 52.5822834 , 127.47080551,
150.89538014, 2.62368916, 26.31949805, 153.64598659,
176.29185523, 15.43039946, 39.15671481, 140.86271881,
164.24754675, 52.32928199, 76.01509842, 104.01119977,
127.58846981, 38.4733912 , 62.15691802, 117.87742569,
141.38857316, 11.86126608, 168.05379849, 66.00708336,
89.69705753, 90.24601689, 113.94624583, 25.88207469,
49.60709205, 130.42448957, 153.87133383, 5.30778392,
29.01857802, 150.98856247, 174.28987968, 90.03968582,
101.62099853, 101.77713186, 78.30773406, 78.17454627,
45.45999318, 16.99024097, 39.97681403, 69.10011445,
110.92884517, 139.89780763, 161.89929049, 134.2346161 ,
45.32551882, 15.68600633, 12.39167346, 39.26720394,
69.03997654, 111.01749555, 140.58856049, 166.95920229,
163.5926509 , 134.48337671, 11.93286185, 167.6312177 ,
136.96276599, 135.11900705, 144.05204051, 136.96276599,
135.11900705, 144.05204051, 12.35295465, 11.82539648,
14.44126841, 117.54207441, 16.07076033, 62.95215834,
78.71063774, 101.23945651, 118.80259983, 141.14099915,
38.61593395, 61.23460289, 104.65230495, 127.14142134,
52.74730257, 75.37507965, 154.28453858, 175.8585009 ,
3.12783539, 25.67964614, 155.51826904, 177.13010287,
1.85937865, 24.46808065, 168.55396095, 11.31373768,
89.81390819, 112.72712481, 67.19911849, 90.1865994 ,
125.7628168 , 148.11935228, 31.63533913, 54.27252709,
143.61092845, 165.80550518, 13.7638788 , 36.38310163,
94.46928992, 117.00095127, 62.94172212, 85.53949763,
110.21645931, 132.67644008, 47.21979395, 69.8132856 ,
129.72645037, 152.11809823, 27.67066973, 50.30722103] deg>
Telescope IDs vs Indices#
Note that subarray.tel
is a dict mapped by tel_id
(the
identifying number of a telescope). It is possible to have telescope
IDs that do not start at 0, are not contiguouous (e.g. if a subarray is
selected). Some functions and properties like tel_coords
are numpy
arrays (not dicts) so they are not mapped to the telescope ID, but
rather the index within this SubarrayDescription. To convert between
the two concepts you can do:
140 subarray.tel_ids_to_indices([1, 5, 23])
array([ 0, 4, 22])
or you can get the indexing array directly in numpy or dict form:
147 subarray.tel_index_array
array([-9223372036854775808, 0, 1,
2, 3, 4,
5, 6, 7,
8, 9, 10,
11, 12, 13,
14, 15, 16,
17, 18, 19,
20, 21, 22,
23, 24, 25,
26, 27, 28,
29, 30, 31,
32, 33, 34,
35, 36, 37,
38, 39, 40,
41, 42, 43,
44, 45, 46,
47, 48, 49,
50, 51, 52,
53, 54, 55,
56, 57, 58,
59, 60, 61,
62, 63, 64,
65, 66, 67,
68, 69, 70,
71, 72, 73,
74, 75, 76,
77, 78, 79,
80, 81, 82,
83, 84, 85,
86, 87, 88,
89, 90, 91,
92, 93, 94,
95, 96, 97,
98, 99, 100,
101, 102, 103,
104, 105, 106,
107, 108, 109,
110, 111, 112,
113, 114, 115,
116, 117, 118,
119, 120, 121,
122, 123, 124,
125, 126, 127,
128, 129, 130,
131, 132, 133,
134, 135, 136,
137, 138, 139,
140, 141, 142,
143, 144, 145,
146, 147, 148,
149, 150, 151,
152, 153, 154,
155, 156, 157,
158, 159, 160,
161, 162, 163,
164, 165, 166,
167, 168, 169,
170, 171, 172,
173, 174, 175,
176, 177, 178,
179])
150 subarray.tel_index_array[[1, 5, 23]]
array([ 0, 4, 22])
(30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180)
array([ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
94, 95, 96, 97, 98, 130, 131, 132, 133, 134, 135, 136, 137,
138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150,
151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163,
164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176,
177, 178, 179])
165 subarray.tel_coords[idx]
<SkyCoord (GroundFrame: reference_location=(6380284., 0., 0.) m): (x, y, z) in m
[( 207.036 , 156.949 , 14.25),
( 203.986 , -160.894 , 19.75),
( -204.02 , 160.893 , 22.25),
( -207.07 , -156.95 , 28.25),
( 168.88199, 423.275 , 18.25),
( 160.729 , -426.44 , 33.25),
( -160.76201, 426.43802 , 10.25),
( -168.916 , -423.27698 , 42.25),
( 4.972 , 519.86896 , 11.75),
( -5.006 , -519.87103 , 41.25),
( 395.51 , 399.996 , 11.25),
( 387.762 , -407.513 , 28.25),
( -387.795 , 407.512 , 13.25),
( -395.545 , -399.99698 , 50.25),
( 495.605 , 105.269005 , 9.25),
( 493.494 , -114.760994 , 11.75),
( -493.528 , 114.76 , 28.25),
( -495.64 , -105.269005 , 30.25),
( 6.927 , 723.596 , 11.75),
( -6.961 , -723.599 , 59.75),
( 621.223 , 312.711 , 7.25),
( 615.114 , -324.075 , 19.25),
( -615.14197, 324.575 , 19.75),
( -621.259 , -312.711 , 49.25),
( 441.802 , 669.11206 , 30.25),
( 428.882 , -677.47 , 47.25),
( -428.91397, 677.46704 , 7.25),
( -441.838 , -669.114 , 70.25),
( 820.094 , -7.8690004, 4.25),
( -820.128 , 7.87 , 30.75),
( 228.46 , 794.887 , 25.25),
( 213.165 , -799.128 , 56.25),
( -213.19801, 799.125 , 10.25),
( -228.495 , -794.89 , 68.25),
( 9.046 , 944.425 , 27.25),
( -9.08 , -944.43 , 75.25),
( 668.034 , 562.918 , 13.25),
( 657.111 , -575.635 , 43.25),
( -657.142 , 575.635 , 8.25),
( -668.07 , -562.919 , 66.25),
( 885.687 , 219.253 , 6.25),
( 881.318 , -236.20801 , 9.25),
( -881.35 , 236.21 , 24.25),
( -885.72205, -219.252 , 42.25),
( 920.53705, 463.474 , 12.75),
( 911.476 , -481.054 , 26.25),
( -911.507 , 481.054 , 11.25),
( -920.574 , -463.47302 , 59.25),
( 480.36603, 966.80896 , 56.25),
( 461.727 , -975.85297 , 65.75),
( -461.758 , 975.849 , 16.75),
( -480.403 , -966.813 , 87.25),
( 714.73206, 843.133 , 49.25),
( 698.425 , -856.69604 , 53.75),
( -698.455 , 856.694 , 14.75),
( -714.77 , -843.135 , 84.75),
( 1100.131 , -10.556 , 3.75),
(-1100.165 , 10.558001 , 27.75),
( 249.865 , 1107.552 , 55.25),
( 228.566 , -1112.148 , 77.75),
( -227.39801, 1112.131 , 25.25),
( -249.9 , -1107.557 , 89.25),
( 964.01 , 730.71704 , 27.25),
( 949.81396, -749.08295 , 46.25),
( -949.844 , 749.08203 , 17.25),
( -964.048 , -730.71704 , 83.25),
( 1199.684 , 357.573 , 10.25),
( 1192.605 , -380.52698 , 19.25),
(-1192.635 , 380.53 , 12.75),
(-1199.7211 , -357.57 , 47.25),
( 1100.131 , -20. , 3.75),
( 880.094 , -7.8690004, 4.25),
( 785. , -42.9 , 4.25),
( -228.495 , -779.49896 , 68.25),
( 910. , 471. , 12.75),
( 228.46 , 810. , 25.25),
( -0. , 350. , 21. ),
( 0. , -350. , 39. ),
( -270. , 320. , 22. ),
( -270. , -320. , 40. ),
( 270. , 320. , 20. ),
( 270. , -320. , 30. ),
( -280. , 575. , 10. ),
( -280. , -575.00104 , 50. ),
( 280. , 575. , 20. ),
( 280. , -575. , 40. ),
( -685. , 175. , 25. ),
( -685. , -175. , 35. ),
( 685. , 175. , 10. ),
( 685. , -175. , 18. ),
(-1070. , 250. , 20. ),
(-1070. , -250. , 42.25),
( 1070. , 250. , 5. ),
( 1070. , -250. , 11.75),
( -970. , -0. , 30. ),
( 970. , -0. , 5. ),
( 120. , -590.00104 , 45. ),
( -120. , -590. , 49. ),
( 120. , 590. , 13. ),
( -120. , 590. , 11. ),
( -500. , 465. , 10. ),
( -500. , -465. , 52. ),
( 500. , 465. , 15. ),
( 500. , -465. , 30. ),
( -770. , 360. , 20. ),
( -770. , -360. , 53. ),
( 770. , 360. , 10. ),
( 770. , -360. , 17. ),
( -260. , 920. , 25. ),
( -260. , -920. , 75. ),
( 260. , 920. , 45. ),
( 260. , -920. , 65. ),
( -500. , 815. , 15. ),
( -500. , -815. , 75. ),
( 500. , 815. , 45. ),
( 500. , -815. , 53. ),
( -810. , 655. , 12. ),
( -810. , -655. , 68. ),
( 810. , 655. , 20. ),
( 810. , -655. , 41. )]>
so, with that method you can quickly get many telescope positions at
once (the alternative is to use the dict positions
which maps
tel_id
to a position on the ground
174 subarray.positions[1]
<Quantity [-20.643, -64.817, 34.3 ] m>
Total running time of the script: (0 minutes 2.927 seconds)