class EventSelector(Component): """ Filter values used for event filters and list of finite parameters are taken as inputs and filter_events() is used on a table of events called in with the Component. For event_type, we choose the sub-array trigger, EventType.SUBARRAY.value, 32, which is for shower event candidate, as per the latest CTA R1 Event Data Model. """ filters = Dict( help="Dict of event filter parameters", default_value={ "r": [0, 1], "wl": [0.01, 1], "leakage_intensity_width_2": [0, 1], "event_type": [EventType.SUBARRAY.value, EventType.SUBARRAY.value], }, ).tag(config=True) finite_params = List( help="List of parameters to ensure finite values", default_value=["intensity", "length", "width"], ).tag(config=True) def filter_cut(self, events): """ Apply the event filters """ return filter_events(events, self.filters, self.finite_params)
class ImageSumDisplayerTool(Tool): description = Unicode(__doc__) name = "ctapipe-image-sum-display" infile = Unicode( help='input simtelarray file', default="/Users/kosack/Data/CTA/Prod3/gamma.simtel.gz").tag( config=True) telgroup = Integer(help='telescope group number', default=1).tag(config=True) aliases = Dict({ 'infile': 'ImageSumDisplayerTool.infile', 'telgroup': 'ImageSumDisplayerTool.telgroup' }) def setup(self): # load up the telescope types table (need to first open a file, a bit of # a hack until a proper insturment module exists) and select only the # telescopes with the same camera type data = next(hessio_event_source(self.infile, max_events=1)) camtypes = get_camera_types(data.inst) group = camtypes.groups[self.telgroup] self._selected_tels = group['tel_id'].data self._base_tel = self._selected_tels[0] self.log.info("Telescope group %d: %s with %s camera", self.telgroup, group[0]['tel_type'], group[0]['cam_type']) self.log.info("SELECTED TELESCOPES:{}".format(self._selected_tels)) def start(self): geom = None imsum = None disp = None for data in hessio_event_source(self.infile, allowed_tels=self._selected_tels, max_events=None): if geom is None: x, y = data.inst.pixel_pos[self._base_tel] flen = data.inst.optical_foclen[self._base_tel] geom = CameraGeometry.guess(x, y, flen) imsum = np.zeros(shape=x.shape, dtype=np.float) disp = CameraDisplay(geom, title=geom.cam_id) disp.add_colorbar() disp.cmap = 'viridis' if len(data.r0.tels_with_data) <= 2: continue imsum[:] = 0 for telid in data.r0.tels_with_data: imsum += data.r0.tel[telid].adc_sums[0] self.log.info("event={} ntels={} energy={}" \ .format(data.r0.event_id, len(data.r0.tels_with_data), data.mc.energy)) disp.image = imsum plt.pause(0.1)
class DumpInstrumentTool(Tool): description = Unicode(__doc__) name = 'ctapipe-dump-instrument' infile = Unicode(help='input simtelarray file').tag(config=True) format = Enum(['fits', 'ecsv', 'hdf5'], default_value='fits', help='Format ' 'of ' 'output ' 'file', config=True) aliases = Dict( dict(infile='DumpInstrumentTool.infile', format='DumpInstrumentTool.format')) def setup(self): source = hessio_event_source(self.infile) data = next(source) # get one event, so the instrument table is # filled in self.inst = data.inst # keep a pointer to the instrument stuff pass def start(self): self.write_camera_geometries() def finish(self): pass def _get_file_format_info(self, format_name, table_type, cam_name): """ returns file extension + dict of required parameters for Table.write""" if format_name == 'fits': return 'fits.gz', dict() elif format_name == 'ecsv': return 'ecsv.txt', dict(format='ascii.ecsv') elif format_name == 'hdf5': return 'h5', dict(path="/" + table_type + "/" + cam_name) else: raise NameError("format not supported") def write_camera_geometries(self): cam_types = get_camera_types(self.inst) print_camera_types(self.inst, printer=self.log.info) for cam_name in cam_types: ext, args = self._get_file_format_info(self.format, 'CAMGEOM', cam_name) self.log.debug("writing {}".format(cam_name)) tel_id = cam_types[cam_name].pop() pix = self.inst.pixel_pos[tel_id] flen = self.inst.optical_foclen[tel_id] geom = CameraGeometry.guess(*pix, flen) table = geom.to_table() table.meta['SOURCE'] = self.infile table.write("{}.camgeom.{}".format(cam_name, ext), **args)
class EventSelector(Component): """ Filter values used for event filters and list of finite parameters are taken as inputs and filter_events() is used on a table of events called in with the Component. """ filters = Dict( help="Dict of event filter parameters", default_value={ "r": [0, 1], "wl": [0.01, 1], "leakage_intensity_width_2": [0, 1], }, ).tag(config=True) finite_params = List( help="List of parameters to ensure finite values", default_value=["intensity", "length", "width"], ).tag(config=True) def filter_cut(self, events): return filter_events(events, self.filters, self.finite_params)
class MakeHistFirstCap(Tool): name = "make-hist-first-cap" infile = Unicode(help='input LST file', default="").tag(config=True) max_events = Integer(help='stop after this many events if non-zero', default_value=0, min=0).tag(config=True) output_suffix = Unicode(help='suffix (file extension) of output ' 'filenames to write images ' 'to (no writing is done if blank). ' 'Images will be named [EVENTID][suffix]', default_value="").tag(config=True) aliases = Dict({ 'infile': 'MakeHistFirstCap.infile', 'max-events': 'MakeHistFirstCap.max_events', 'output-suffix': 'MakeHistFirstCap.output_suffix' }) def setup(self): # load LST data self.log.info("Read file:{}".format(self.infile)) self.reader = LSTEventSource(input_url=self.infile, max_events=self.max_events) def start(self): fc = [] for event in self.reader: fc.extend(get_first_capacitor_array(event)) plt.figure() plt.hist(fc, bins=4096) plt.ylabel("Number") plt.xlabel("Stop Cell") plt.show()
class ImageSumDisplayerTool(Tool): description = Unicode(__doc__) name = "ctapipe-display-imagesum" infile = Path( help="input simtelarray file", default_value=get_dataset_path("gamma_test_large.simtel.gz"), exists=True, directory_ok=False, ).tag(config=True) telgroup = Integer(help="telescope group number", default_value=1).tag(config=True) max_events = Integer( help="stop after this many events if non-zero", default_value=0, min=0 ).tag(config=True) output_suffix = Unicode( help="suffix (file extension) of output " "filenames to write images " "to (no writing is done if blank). " "Images will be named [EVENTID][suffix]", default_value="", ).tag(config=True) aliases = Dict( { "infile": "ImageSumDisplayerTool.infile", "telgroup": "ImageSumDisplayerTool.telgroup", "max-events": "ImageSumDisplayerTool.max_events", "output-suffix": "ImageSumDisplayerTool.output_suffix", } ) classes = [CameraCalibrator, SimTelEventSource] def setup(self): # load up the telescope types table (need to first open a file, a bit of # a hack until a proper instrument module exists) and select only the # telescopes with the same camera type # make sure gzip files are seekable self.reader = SimTelEventSource( input_url=self.infile, max_events=self.max_events, back_seekable=True ) camtypes = self.reader.subarray.to_table().group_by("camera_type") self.reader.subarray.info(printer=self.log.info) group = camtypes.groups[self.telgroup] self._selected_tels = list(group["tel_id"].data) self._base_tel = self._selected_tels[0] self.log.info( "Telescope group %d: %s", self.telgroup, str(self.reader.subarray.tel[self._selected_tels[0]]), ) self.log.info(f"SELECTED TELESCOPES:{self._selected_tels}") self.calibrator = CameraCalibrator(parent=self, subarray=self.reader.subarray) self.reader = SimTelEventSource( input_url=self.infile, max_events=self.max_events, back_seekable=True, allowed_tels=set(self._selected_tels), ) def start(self): geom = None imsum = None disp = None for event in self.reader: self.calibrator(event) if geom is None: geom = self.reader.subarray.tel[self._base_tel].camera.geometry imsum = np.zeros(shape=geom.pix_x.shape, dtype=np.float64) disp = CameraDisplay(geom, title=geom.camera_name) disp.add_colorbar() disp.cmap = "viridis" if len(event.dl0.tel.keys()) <= 2: continue imsum[:] = 0 for telid in event.dl0.tel.keys(): imsum += event.dl1.tel[telid].image self.log.info( "event={} ntels={} energy={}".format( event.index.event_id, len(event.dl0.tel.keys()), event.simulation.shower.energy, ) ) disp.image = imsum plt.pause(0.1) if self.output_suffix != "": filename = "{:020d}{}".format(event.index.event_id, self.output_suffix) self.log.info(f"saving: '{filename}'") plt.savefig(filename)
class SingleTelEventDisplay(Tool): name = "ctapipe-display-televents" description = Unicode(__doc__) infile = Path(help="input file to read", exists=True, directory_ok=False).tag(config=True) tel = Int(help="Telescope ID to display", default_value=0).tag(config=True) write = Bool(help="Write out images to PNG files", default_value=False).tag(config=True) clean = Bool(help="Apply image cleaning", default_value=False).tag(config=True) hillas = Bool(help="Apply and display Hillas parametrization", default_value=False).tag(config=True) samples = Bool(help="Show each sample", default_value=False).tag(config=True) display = Bool(help="Display results in interactive window", default_value=True).tag(config=True) delay = Float(help="delay between events in s", default_value=0.01, min=0.001).tag(config=True) progress = Bool(help="display progress bar", default_value=True).tag(config=True) aliases = Dict({ "infile": "SingleTelEventDisplay.infile", "tel": "SingleTelEventDisplay.tel", "max-events": "EventSource.max_events", "write": "SingleTelEventDisplay.write", "clean": "SingleTelEventDisplay.clean", "hillas": "SingleTelEventDisplay.hillas", "samples": "SingleTelEventDisplay.samples", "display": "SingleTelEventDisplay.display", "delay": "SingleTelEventDisplay.delay", "progress": "SingleTelEventDisplay.progress", }) classes = List([EventSource, CameraCalibrator]) def __init__(self, **kwargs): super().__init__(**kwargs) def setup(self): print("TOLLES INFILE", self.infile) self.event_source = EventSource.from_url(self.infile, parent=self) self.event_source.allowed_tels = {self.tel} self.calibrator = CameraCalibrator(parent=self, subarray=self.event_source.subarray) self.log.info(f"SELECTING EVENTS FROM TELESCOPE {self.tel}") def start(self): disp = None for event in tqdm( self.event_source, desc=f"Tel{self.tel}", total=self.event_source.max_events, disable=~self.progress, ): self.log.debug(event.trigger) self.log.debug(f"Energy: {event.simulation.shower.energy}") self.calibrator(event) if disp is None: geom = self.event_source.subarray.tel[self.tel].camera.geometry self.log.info(geom) disp = CameraDisplay(geom) # disp.enable_pixel_picker() disp.add_colorbar() if self.display: plt.show(block=False) # display the event disp.axes.set_title("CT{:03d} ({}), event {:06d}".format( self.tel, geom.camera_name, event.index.event_id)) if self.samples: # display time-varying event data = event.dl0.tel[self.tel].waveform for ii in range(data.shape[1]): disp.image = data[:, ii] disp.set_limits_percent(70) plt.suptitle(f"Sample {ii:03d}") if self.display: plt.pause(self.delay) if self.write: plt.savefig( f"CT{self.tel:03d}_EV{event.index.event_id:10d}" f"_S{ii:02d}.png") else: # display integrated event: im = event.dl1.tel[self.tel].image if self.clean: mask = tailcuts_clean(geom, im, picture_thresh=10, boundary_thresh=7) im[~mask] = 0.0 disp.image = im if self.hillas: try: ellipses = disp.axes.findobj(Ellipse) if len(ellipses) > 0: ellipses[0].remove() params = hillas_parameters(geom, image=im) disp.overlay_moments(params, color="pink", lw=3, with_label=False) except HillasParameterizationError: pass if self.display: plt.pause(self.delay) if self.write: plt.savefig( f"CT{self.tel:03d}_EV{event.index.event_id:010d}.png") self.log.info("FINISHED READING DATA FILE") if disp is None: self.log.warning( "No events for tel {} were found in {}. Try a " "different EventIO file or another telescope".format( self.tel, self.infile))
class SimpleEventWriter(Tool): name = 'ctapipe-simple-event-writer' description = Unicode(__doc__) infile = Unicode(help='input file to read', default='').tag(config=True) outfile = Unicode(help='output file name', default_value='output.h5').tag(config=True) progress = Bool(help='display progress bar', default_value=True).tag(config=True) aliases = Dict({ 'infile': 'EventSource.input_url', 'outfile': 'SimpleEventWriter.outfile', 'max-events': 'EventSource.max_events', 'progress': 'SimpleEventWriter.progress' }) classes = List([EventSource, CameraCalibrator, CutFlow]) def setup(self): self.log.info('Configure EventSource...') self.event_source = self.add_component( EventSource.from_config(config=self.config, parent=self)) self.calibrator = self.add_component(CameraCalibrator(parent=self)) self.writer = self.add_component( HDF5TableWriter(filename=self.outfile, group_name='image_infos', overwrite=True)) # Define Pre-selection for images preselcuts = self.config['Preselect'] self.image_cutflow = CutFlow('Image preselection') self.image_cutflow.set_cuts( dict(no_sel=None, n_pixel=lambda s: np.count_nonzero(s) < preselcuts['n_pixel'][ 'min'], image_amplitude=lambda q: q < preselcuts['image_amplitude'][ 'min'])) # Define Pre-selection for events self.event_cutflow = CutFlow('Event preselection') self.event_cutflow.set_cuts(dict(no_sel=None)) def start(self): self.log.info('Loop on events...') for event in tqdm(self.event_source, desc='EventWriter', total=self.event_source.max_events, disable=~self.progress): self.event_cutflow.count('no_sel') self.calibrator(event) for tel_id in event.dl0.tels_with_data: self.image_cutflow.count('no_sel') camera = event.inst.subarray.tel[tel_id].camera dl1_tel = event.dl1.tel[tel_id] # Image cleaning image = dl1_tel.image # Waiting for automatic gain selection mask = tailcuts_clean(camera, image, picture_thresh=10, boundary_thresh=5) cleaned = image.copy() cleaned[~mask] = 0 # Preselection cuts if self.image_cutflow.cut('n_pixel', cleaned): continue if self.image_cutflow.cut('image_amplitude', np.sum(cleaned)): continue # Image parametrisation params = hillas_parameters(camera, cleaned) # Save Ids, MC infos and Hillas informations self.writer.write(camera.cam_id, [event.r0, event.mc, params]) def finish(self): self.log.info('End of job.') self.image_cutflow() self.event_cutflow() self.writer.close()
class DumpInstrumentTool(Tool): description = Unicode(__doc__) name = "ctapipe-dump-instrument" infile = Path(exists=True, help="input simtelarray file").tag(config=True) format = Enum( ["fits", "ecsv", "hdf5"], default_value="fits", help="Format of output file", config=True, ) aliases = Dict( dict(infile="DumpInstrumentTool.infile", format="DumpInstrumentTool.format")) def setup(self): with event_source(self.infile) as source: self.subarray = source.subarray def start(self): if self.format == "hdf5": self.subarray.to_hdf("subarray.h5") else: self.write_camera_geometries() self.write_optics_descriptions() self.write_subarray_description() def finish(self): pass @staticmethod def _get_file_format_info(format_name, table_type, table_name): """ returns file extension + dict of required parameters for Table.write""" if format_name == "fits": return "fits.gz", dict() elif format_name == "ecsv": return "ecsv.txt", dict(format="ascii.ecsv") else: raise NameError(f"format {format_name} not supported") def write_camera_geometries(self): cam_types = get_camera_types(self.subarray) self.subarray.info(printer=self.log.info) for cam_name in cam_types: ext, args = self._get_file_format_info(self.format, "CAMGEOM", cam_name) self.log.debug(f"writing {cam_name}") tel_id = cam_types[cam_name].pop() geom = self.subarray.tel[tel_id].camera.geometry table = geom.to_table() table.meta["SOURCE"] = str(self.infile) filename = f"{cam_name}.camgeom.{ext}" try: table.write(filename, **args) Provenance().add_output_file(filename, "dl0.tel.svc.camera") except IOError as err: self.log.warning( "couldn't write camera definition '%s' because: %s", filename, err) def write_optics_descriptions(self): sub = self.subarray ext, args = self._get_file_format_info(self.format, sub.name, "optics") tab = sub.to_table(kind="optics") tab.meta["SOURCE"] = str(self.infile) filename = f"{sub.name}.optics.{ext}" try: tab.write(filename, **args) Provenance().add_output_file(filename, "dl0.sub.svc.optics") except IOError as err: self.log.warning( "couldn't write optics description '%s' because: %s", filename, err) def write_subarray_description(self): sub = self.subarray ext, args = self._get_file_format_info(self.format, sub.name, "subarray") tab = sub.to_table(kind="subarray") tab.meta["SOURCE"] = str(self.infile) filename = f"{sub.name}.subarray.{ext}" try: tab.write(filename, **args) Provenance().add_output_file(filename, "dl0.sub.svc.subarray") except IOError as err: self.log.warning( "couldn't write subarray description '%s' because: %s", filename, err)
class DumpInstrumentTool(Tool): description = Unicode(__doc__) name = 'ctapipe-dump-instrument' infile = Unicode(help='input simtelarray file').tag(config=True) format = Enum(['fits', 'ecsv', 'hdf5'], default_value='fits', help='Format of output file', config=True) aliases = Dict(dict(infile='DumpInstrumentTool.infile', format='DumpInstrumentTool.format')) def setup(self): with event_source(self.infile) as source: data = next(iter(source)) # get one event, so the instrument table is there self.inst = data.inst # keep a reference to the instrument stuff def start(self): self.write_camera_geometries() self.write_optics_descriptions() self.write_subarray_description() def finish(self): pass @staticmethod def _get_file_format_info(format_name, table_type, table_name): """ returns file extension + dict of required parameters for Table.write""" if format_name == 'fits': return 'fits.gz', dict() elif format_name == 'ecsv': return 'ecsv.txt', dict(format='ascii.ecsv') elif format_name == 'hdf5': return 'h5', dict(path="/" + table_type + "/" + table_name) else: raise NameError("format not supported") def write_camera_geometries(self): cam_types = get_camera_types(self.inst.subarray) self.inst.subarray.info(printer=self.log.info) for cam_name in cam_types: ext, args = self._get_file_format_info(self.format, 'CAMGEOM', cam_name) self.log.debug("writing {}".format(cam_name)) tel_id = cam_types[cam_name].pop() geom = self.inst.subarray.tel[tel_id].camera table = geom.to_table() table.meta['SOURCE'] = self.infile filename = "{}.camgeom.{}".format(cam_name, ext) try: table.write(filename, **args) Provenance().add_output_file(filename, 'dl0.tel.svc.camera') except IOError as err: self.log.warn("couldn't write camera definition '%s' because: " "%s", filename, err) def write_optics_descriptions(self): sub = self.inst.subarray ext, args = self._get_file_format_info(self.format, sub.name, 'optics') tab = sub.to_table(kind='optics') tab.meta['SOURCE'] = self.infile filename = '{}.optics.{}'.format(sub.name, ext) try: tab.write(filename, **args) Provenance().add_output_file(filename, 'dl0.sub.svc.optics') except IOError as err: self.log.warn("couldn't write optics description '%s' because: " "%s", filename, err) def write_subarray_description(self): sub = self.inst.subarray ext, args = self._get_file_format_info(self.format, sub.name, 'subarray') tab = sub.to_table(kind='subarray') tab.meta['SOURCE'] = self.infile filename = '{}.subarray.{}'.format(sub.name, ext) try: tab.write(filename, **args) Provenance().add_output_file(filename, 'dl0.sub.svc.subarray') except IOError as err: self.log.warn("couldn't write subarray description '%s' because: " "%s", filename, err)
class SingleTelEventDisplay(Tool): name = "ctapipe-display-televents" description = Unicode(__doc__) infile = Unicode(help="input file to read", default='').tag(config=True) tel = Int(help='Telescope ID to display', default=0).tag(config=True) channel = Integer(help="channel number to display", min=0, max=1).tag(config=True) write = Bool(help="Write out images to PNG files", default=False).tag(config=True) clean = Bool(help="Apply image cleaning", default=False).tag(config=True) hillas = Bool(help="Apply and display Hillas parametrization", default=False).tag(config=True) samples = Bool(help="Show each sample", default=False).tag(config=True) display = Bool(help="Display results in interactive window", default_value=True).tag(config=True) delay = Float(help='delay between events in s', default_value=0.01, min=0.001).tag(config=True) progress = Bool(help='display progress bar', default_value=True).tag(config=True) aliases = Dict({ 'infile': 'SingleTelEventDisplay.infile', 'tel': 'SingleTelEventDisplay.tel', 'max-events': 'EventSource.max_events', 'channel': 'SingleTelEventDisplay.channel', 'write': 'SingleTelEventDisplay.write', 'clean': 'SingleTelEventDisplay.clean', 'hillas': 'SingleTelEventDisplay.hillas', 'samples': 'SingleTelEventDisplay.samples', 'display': 'SingleTelEventDisplay.display', 'delay': 'SingleTelEventDisplay.delay', 'progress': 'SingleTelEventDisplay.progress' }) classes = List([EventSource, CameraCalibrator]) def __init__(self, **kwargs): super().__init__(**kwargs) def setup(self): print('TOLLES INFILE', self.infile) self.event_source = EventSource.from_url(self.infile, parent=self) self.event_source.allowed_tels = { self.tel, } self.calibrator = CameraCalibrator(parent=self) self.log.info(f'SELECTING EVENTS FROM TELESCOPE {self.tel}') def start(self): disp = None for event in tqdm(self.event_source, desc=f'Tel{self.tel}', total=self.event_source.max_events, disable=~self.progress): self.log.debug(event.trig) self.log.debug(f"Energy: {event.mc.energy}") self.calibrator(event) if disp is None: geom = event.inst.subarray.tel[self.tel].camera self.log.info(geom) disp = CameraDisplay(geom) # disp.enable_pixel_picker() disp.add_colorbar() if self.display: plt.show(block=False) # display the event disp.axes.set_title('CT{:03d} ({}), event {:06d}'.format( self.tel, geom.cam_id, event.r0.event_id)) if self.samples: # display time-varying event data = event.dl0.tel[self.tel].waveform[self.channel] for ii in range(data.shape[1]): disp.image = data[:, ii] disp.set_limits_percent(70) plt.suptitle(f"Sample {ii:03d}") if self.display: plt.pause(self.delay) if self.write: plt.savefig( f'CT{self.tel:03d}_EV{event.r0.event_id:10d}' f'_S{ii:02d}.png') else: # display integrated event: im = event.dl1.tel[self.tel].image[self.channel] if self.clean: mask = tailcuts_clean(geom, im, picture_thresh=10, boundary_thresh=7) im[~mask] = 0.0 disp.image = im if self.hillas: try: ellipses = disp.axes.findobj(Ellipse) if len(ellipses) > 0: ellipses[0].remove() params = hillas_parameters(geom, image=im) disp.overlay_moments(params, color='pink', lw=3, with_label=False) except HillasParameterizationError: pass if self.display: plt.pause(self.delay) if self.write: plt.savefig( f'CT{self.tel:03d}_EV{event.r0.event_id:010d}.png') self.log.info("FINISHED READING DATA FILE") if disp is None: self.log.warning( 'No events for tel {} were found in {}. Try a ' 'different EventIO file or another telescope'.format( self.tel, self.infile), )
class ImageSumDisplayerTool(Tool): description = Unicode(__doc__) name = "ctapipe-display-imagesum" infile = Unicode( help='input simtelarray file', default="/Users/kosack/Data/CTA/Prod3/gamma.simtel.gz").tag( config=True) telgroup = Integer(help='telescope group number', default=1).tag(config=True) max_events = Integer(help='stop after this many events if non-zero', default_value=0, min=0).tag(config=True) output_suffix = Unicode(help='suffix (file extension) of output ' 'filenames to write images ' 'to (no writing is done if blank). ' 'Images will be named [EVENTID][suffix]', default_value="").tag(config=True) aliases = Dict({ 'infile': 'ImageSumDisplayerTool.infile', 'telgroup': 'ImageSumDisplayerTool.telgroup', 'max-events': 'ImageSumDisplayerTool.max_events', 'output-suffix': 'ImageSumDisplayerTool.output_suffix' }) classes = List([CameraCalibrator, SimTelEventSource]) def setup(self): # load up the telescope types table (need to first open a file, a bit of # a hack until a proper insturment module exists) and select only the # telescopes with the same camera type # make sure gzip files are seekable self.reader = SimTelEventSource(input_url=self.infile, max_events=self.max_events, back_seekable=True) for event in self.reader: camtypes = event.inst.subarray.to_table().group_by('camera_type') event.inst.subarray.info(printer=self.log.info) break group = camtypes.groups[self.telgroup] self._selected_tels = list(group['tel_id'].data) self._base_tel = self._selected_tels[0] self.log.info("Telescope group %d: %s", self.telgroup, str(event.inst.subarray.tel[self._selected_tels[0]])) self.log.info(f"SELECTED TELESCOPES:{self._selected_tels}") self.calibrator = CameraCalibrator(parent=self) self.reader.allowed_tels = self._selected_tels def start(self): geom = None imsum = None disp = None for event in self.reader: self.calibrator(event) if geom is None: geom = event.inst.subarray.tel[self._base_tel].camera imsum = np.zeros(shape=geom.pix_x.shape, dtype=np.float) disp = CameraDisplay(geom, title=geom.cam_id) disp.add_colorbar() disp.cmap = 'viridis' if len(event.dl0.tels_with_data) <= 2: continue imsum[:] = 0 for telid in event.dl0.tels_with_data: imsum += event.dl1.tel[telid].image self.log.info("event={} ntels={} energy={}".format( event.r0.event_id, len(event.dl0.tels_with_data), event.mc.energy)) disp.image = imsum plt.pause(0.1) if self.output_suffix is not "": filename = "{:020d}{}".format(event.r0.event_id, self.output_suffix) self.log.info(f"saving: '{filename}'") plt.savefig(filename)
class DumpTriggersTool(Tool): description = Unicode(__doc__) name = 'ctapipe-dump-triggers' # ============================================= # configuration parameters: # ============================================= infile = Path(exists=True, directory_ok=False, help='input simtelarray file').tag(config=True) outfile = Path( default_value='triggers.fits', directory_ok=False, help='output filename (*.fits, *.h5)', ).tag(config=True) overwrite = Bool(False, help="overwrite existing output file").tag(config=True) # ============================================= # map low-level options to high-level command-line options # ============================================= aliases = Dict({ 'infile': 'DumpTriggersTool.infile', 'outfile': 'DumpTriggersTool.outfile' }) flags = Dict({ 'overwrite': ({ 'DumpTriggersTool': { 'overwrite': True } }, 'Enable overwriting of output file') }) examples = ('ctapipe-dump-triggers --infile gamma.simtel.gz ' '--outfile trig.fits --overwrite' '\n\n' 'If you want to see more output, use --log_level=DEBUG') # ============================================= # The methods of the Tool (initialize, start, finish): # ============================================= def add_event_to_table(self, event): """ add the current hessio event to a row in the `self.events` table """ time = event.trigger.time if self._prev_time is None: self._prev_time = time if self._current_starttime is None: self._current_starttime = time relative_time = time - self._current_starttime delta_t = time - self._prev_time self._prev_time = time # build the trigger pattern as a fixed-length array # (better for storage in FITS format) # trigtels = event.get_telescope_with_data_list() trigtels = event.dl0.tels_with_data self._current_trigpattern[:] = 0 # zero the trigger pattern self._current_trigpattern[list(trigtels)] = 1 # set the triggered tels # to 1 # insert the row into the table self.events.add_row( (event.index.event_id, relative_time.sec, delta_t.sec, len(trigtels), self._current_trigpattern)) def setup(self): """ setup function, called before `start()` """ if self.infile == '': raise ToolConfigurationError( "No 'infile' parameter was specified. ") self.events = Table( names=['EVENT_ID', 'T_REL', 'DELTA_T', 'N_TRIG', 'TRIGGERED_TELS'], dtype=[np.int64, np.float64, np.float64, np.int32, np.uint8]) self.events['TRIGGERED_TELS'].shape = (0, MAX_TELS) self.events['T_REL'].unit = u.s self.events['T_REL'].description = 'Time relative to first event' self.events['DELTA_T'].unit = u.s self.events.meta['INPUT'] = self.infile self._current_trigpattern = np.zeros(MAX_TELS) self._current_starttime = None self._prev_time = None def start(self): """ main event loop """ with event_source(self.infile) as source: for event in source: self.add_event_to_table(event) def finish(self): """ finish up and write out results (called automatically after `start()`) """ # write out the final table try: if '.fits' in self.outfile.suffixes: self.events.write(self.outfile, overwrite=self.overwrite) elif self.outfile.suffix in ('.hdf5', '.h5', '.hdf'): self.events.write(self.outfile, path='/events', overwrite=self.overwrite) else: self.events.write(self.outfile) Provenance().add_output_file(self.outfile) except IOError as err: self.log.warning("Couldn't write output (%s)", err) self.log.info('\n %s', self.events)
class SimpleEventWriter(Tool): name = "ctapipe-simple-event-writer" description = Unicode(__doc__) infile = Path( default_value=get_dataset_path( "lst_prod3_calibration_and_mcphotons.simtel.zst"), help="input file to read", directory_ok=False, exists=True, ).tag(config=True) outfile = Path(help="output file name", directory_ok=False, default_value="output.h5").tag(config=True) progress = Bool(help="display progress bar", default_value=True).tag(config=True) aliases = Dict({ "infile": "EventSource.input_url", "outfile": "SimpleEventWriter.outfile", "max-events": "EventSource.max_events", "progress": "SimpleEventWriter.progress", }) classes = List([EventSource, CameraCalibrator]) def setup(self): self.log.info("Configure EventSource...") self.event_source = EventSource.from_url(self.infile, parent=self) self.calibrator = CameraCalibrator(subarray=self.event_source.subarray, parent=self) self.writer = HDF5TableWriter(filename=self.outfile, group_name="image_infos", overwrite=True, parent=self) def start(self): self.log.info("Loop on events...") for event in tqdm( self.event_source, desc="EventWriter", total=self.event_source.max_events, disable=~self.progress, ): self.calibrator(event) for tel_id in event.dl0.tel.keys(): geom = self.event_source.subarray.tel[tel_id].camera.geometry dl1_tel = event.dl1.tel[tel_id] # Image cleaning image = dl1_tel.image # Waiting for automatic gain selection mask = tailcuts_clean(geom, image, picture_thresh=10, boundary_thresh=5) cleaned = image.copy() cleaned[~mask] = 0 # Image parametrisation params = hillas_parameters(geom, cleaned) # Save Ids, MC infos and Hillas informations self.writer.write(geom.camera_name, [event.r0, event.simulation.shower, params]) def finish(self): self.log.info("End of job.") self.writer.close()
class DumpTriggersTool(Tool): description = Unicode(__doc__) # ============================================= # configuration parameters: # ============================================= infile = Unicode(help='input simtelarray file').tag(config=True, allow_none=False) outfile = Unicode('triggers.fits', help='output filename (*.fits, *.h5)').tag(config=True) overwrite = Bool(False, help="overwrite existing output file").tag(config=True) # ============================================= # map low-level options to high-level command-line options # ============================================= aliases = Dict({ 'infile': 'DumpTriggersTool.infile', 'outfile': 'DumpTriggersTool.outfile' }) flags = Dict({ 'overwrite': ({ 'DumpTriggersTool': { 'overwrite': True } }, 'Enable overwriting of output file') }) examples = ('ctapipe-dump-triggers --infile gamma.simtel.gz ' '--outfile trig.fits --overwrite' '\n\n' 'If you want to see more output, use --log_level=DEBUG') # ============================================= # The methods of the Tool (initialize, start, finish): # ============================================= def add_event_to_table(self, event_id): """ add the current pyhessio event to a row in the `self.events` table """ ts, tns = pyhessio.get_central_event_gps_time() gpstime = Time(ts * u.s, tns * u.ns, format='gps', scale='utc') if self._prev_gpstime is None: self._prev_gpstime = gpstime if self._current_starttime is None: self._current_starttime = gpstime relative_time = gpstime - self._current_starttime delta_t = gpstime - self._prev_gpstime self._prev_gpstime = gpstime # build the trigger pattern as a fixed-length array # (better for storage in FITS format) trigtels = pyhessio.get_telescope_with_data_list() self._current_trigpattern[:] = 0 # zero the trigger pattern self._current_trigpattern[trigtels] = 1 # set the triggered tels to 1 # insert the row into the table self.events.add_row((event_id, relative_time.sec, delta_t.sec, len(trigtels), self._current_trigpattern)) def setup(self): """ setup function, called before `start()` """ if self.infile == '': raise ValueError("No 'infile' parameter was specified. " "Use --help for info") self.events = Table( names=['EVENT_ID', 'T_REL', 'DELTA_T', 'N_TRIG', 'TRIGGERED_TELS'], dtype=[np.int64, np.float64, np.float64, np.int32, np.uint8]) self.events['TRIGGERED_TELS'].shape = (0, MAX_TELS) self.events['T_REL'].unit = u.s self.events['T_REL'].description = 'Time relative to first event' self.events['DELTA_T'].unit = u.s self.events.meta['INPUT'] = self.infile self._current_trigpattern = np.zeros(MAX_TELS) self._current_starttime = None self._prev_gpstime = None pyhessio.file_open(self.infile) def start(self): """ main event loop """ for run_id, event_id in pyhessio.move_to_next_event(): self.add_event_to_table(event_id) def finish(self): """ finish up and write out results (called automatically after `start()`) """ pyhessio.close_file() # write out the final table if self.outfile.endswith('fits') or self.outfile.endswith('fits.gz'): self.events.write(self.outfile, overwrite=self.overwrite) elif self.outfile.endswith('h5'): self.events.write(self.outfile, path='/events', overwrite=self.overwrite) else: self.events.write(self.outfile) self.log.info("Table written to '{}'".format(self.outfile)) self.log.info('\n %s', self.events)