예제 #1
0
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)
예제 #2
0
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)
예제 #3
0
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)
예제 #4
0
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()
예제 #6
0
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))
예제 #8
0
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()
예제 #9
0
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)
예제 #10
0
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)
예제 #11
0
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), )
예제 #12
0
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)
예제 #13
0
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)
예제 #14
0
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()
예제 #15
0
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)