def make_camera_binary_image(image, sigma, clean_bound, death_pixel_ids_list):
    fig, ax = plt.subplots(1, 2, figsize=(14, 7))

    geom = CameraGeometry.from_name('LSTCam-003')
    disp0 = CameraDisplay(geom, ax=ax[0])
    disp0.image = image
    disp0.cmap = plt.cm.gnuplot2
    disp0.add_colorbar(ax=ax[0])
    ax[0].set_title(
        "Cleaning threshold from interleaved pedestal. \n sigma = {}".format(
            sigma),
        fontsize=15)

    disp1 = CameraDisplay(geom, ax=ax[1])
    disp1.image = image
    cmap = matplotlib.colors.ListedColormap(['black', 'red'])
    bounds = [0, clean_bound, 2 * clean_bound]
    norm = matplotlib.colors.BoundaryNorm(bounds, cmap.N)
    disp1.cmap = cmap
    disp1.add_colorbar(norm=norm,
                       boundaries=bounds,
                       ticks=[0, clean_bound, 2 * clean_bound])
    disp1.set_limits_minmax(0, 2 * clean_bound)
    disp1.highlight_pixels(death_pixel_ids_list, linewidth=3)
    ax[1].set_title("Red pixels - above cleaning tailcut threshold",
                    fontsize=15)
    plt.tight_layout()
    plt.show()
Example #2
0
    def create(self, df, geom):
        super().save()

        camera = CameraDisplay(geom, ax=self.ax,
                               image=np.ma.zeros(2048),
                               cmap='viridis')
        camera.add_colorbar(pad=-0.2)
        camera.colorbar.set_label("Peak Time (ns)", fontsize=20)

        with PdfPages(self.output_path) as pdf:
            n_rows = len(df.index)
            desc = "Saving image pages"
            for index, row in tqdm(df.iterrows(), total=n_rows, desc=desc):
                event_id = row['id']
                tel = row['tel']
                image = row['peak_time']
                tc = row['tc']
                hillas = row['hillas']

                cleaned_image = np.ma.masked_array(image, mask=~tc)
                cleaned_image.fill_value = 0
                max_ = np.percentile(cleaned_image.compressed(), 99)
                min_ = np.percentile(cleaned_image.compressed(), 1)

                camera.image = cleaned_image
                camera.set_limits_minmax(min_, max_)
                camera.highlight_pixels(np.arange(2048), 'black', 1, 0.2)
                # camera.overlay_moments_update(hillas, color='red')
                self.ax.set_title("Event: {}, Tel: {}".format(event_id, tel))
                self.ax.axis('off')
                camera.colorbar.ax.tick_params(labelsize=30)

                pdf.savefig(self.fig)
Example #3
0
def test_camera_display_single():
    """ test CameraDisplay functionality """
    from ..mpl_camera import CameraDisplay

    geom = CameraGeometry.from_name("LSTCam")
    disp = CameraDisplay(geom)
    image = np.random.normal(size=len(geom.pix_x))
    disp.image = image
    disp.add_colorbar()
    disp.cmap = "nipy_spectral"
    disp.set_limits_minmax(0, 10)
    disp.set_limits_percent(95)
    disp.enable_pixel_picker()
    disp.highlight_pixels([1, 2, 3, 4, 5])
    disp.norm = "log"
    disp.norm = "symlog"
    disp.cmap = "rainbow"

    with pytest.raises(ValueError):
        disp.image = np.ones(10)

    with pytest.raises(ValueError):
        disp.add_colorbar()

    disp.add_ellipse(centroid=(0, 0), width=0.1, length=0.1, angle=0.1)
    disp.clear_overlays()
Example #4
0
def Simple_CamPlot(image, geom, pix_ids, title=""):
    disp1 = CameraDisplay(geom, title=title)
    disp1.add_colorbar()
    disp1.set_limits_minmax(zmin=image.min() * 0.98, zmax=image.max() * 1.02)
    blankam1 = np.zeros(1855)
    blankam1[pix_ids] = image
    disp1.image = blankam1
    plt.show()
Example #5
0
def Simple_AxCamPlot(image, geom, pix_ids, title=""):
    f, ax = plt.subplots()
    disp1 = CameraDisplay(geom, title=title, ax=ax)
    disp1.add_colorbar(ax=ax)
    # ~ disp1.set_limits_minmax(zmin=image.min()*0.98,zmax=image.max()*1.02)
    disp1.set_limits_minmax(zmin=image.min(), zmax=image.max())
    blankam1 = np.zeros(1855)
    blankam1[pix_ids] = image
    disp1.image = blankam1

    ax.set_ylim(-0.65, 0.65)
    ax.set_xlim(-0.6, 0.6)
    return ax
def plot_all(data_file, legend='camera average'):
    mean_charge_all, std_charge_all, mean_t_all, std_t_all, true_pe = \
        load_data(data_file)
    mean_t_100pe = np.array(
        [np.interp(100, true_pe[:, i], mean_t_all[:, i]) for i in range(1296)])
    std_t_100pe = np.array(
        [np.interp(100, true_pe[:, i], std_t_all[:, i]) for i in range(1296)])
    fig, axes = plt.subplots(2, 3, figsize=(24, 18))
    plot_zone(true_pe,
              mean_charge_all,
              [np.logspace(.5, 2.75, 101),
               np.logspace(-.3, 2.8, 101)],
              axes[0, 0],
              legend,
              yscale='log')
    axes[0, 0].loglog([0.1, 1000], [0.1, 1000], 'k--')
    axes[0, 0].set_ylabel('mean charge reco. [p.e]')
    plot_zone(true_pe,
              std_charge_all,
              [np.logspace(.5, 2.75, 101),
               np.logspace(-0.5, 1.5, 101)],
              axes[0, 1],
              legend,
              yscale='log')
    axes[0, 1].loglog([0.1, 1000], np.sqrt([0.1, 1000]), 'k--')
    axes[0, 1].set_ylabel('std charge reco. [p.e]')
    plot_resol(data_file, legend=legend, ax=axes[0, 2])
    plot_offset(data_file, legend=legend, ax=axes[1, 0])
    display = CameraDisplay(DigiCam.geometry,
                            ax=axes[1, 1],
                            title='timing offset (at 100 p.e) [ns]')
    display.image = mean_t_100pe - np.nanmean(mean_t_100pe)
    display.set_limits_minmax(-2, 2)
    display.add_colorbar(ax=axes[1, 1])
    display = CameraDisplay(DigiCam.geometry,
                            ax=axes[1, 2],
                            title='timing resolution (at 100 p.e.) [ns]')
    display.image = std_t_100pe
    display.set_limits_minmax(0.1, 0.3)
    display.add_colorbar(ax=axes[1, 2])
    plt.tight_layout()
Example #7
0
def plot_allparam_map(df):
    nc = 4
    nr = 2
    f,axs = plt.subplots(ncols=nc,nrows=nr,figsize=(12,6))
    # ~ table = Table.read('./NewNectarCam.camgeom.fits.gz')
    # ~ geom = CameraGeometry.from_table(table)
    # ~ geom.rotate(10.3*u.deg)

    geom = CameraGeometry.from_name("NectarCam-002")
        
    for ii,key in enumerate(df):
    # ~ for ii,key in enumerate(['Light I', 'ped mean', 'ped width', 'res', 'Mu2', 'gain']):
        ax = axs[ii%nr,ii//nr%nc]
        blankam = np.zeros(1855)
        blankam[pix_ids]=df[key]
        
        disp = CameraDisplay(geom,title=key,ax=ax)
        disp.add_colorbar(ax=ax)
        disp.set_limits_minmax(zmin=np.min(df[key])*.99,zmax=np.max(df[key])*1.01)
        disp.image = blankam
        ax.set_ylim(-0.8,0.8)
        ax.set_xlim(-0.5,0.4)
    plt.show()
    return
Example #8
0
def plot_pedestals(data_file,
                   pedestal_file,
                   run=0,
                   plot_file="none",
                   tel_id=1,
                   offset_value=400):
    """
     plot pedestal quantities quantities

     Parameters
     ----------
     data_file:   pedestal run

     pedestal_file:   file with drs4 corrections

     run: run number of data to be corrected

     plot_file:  name of output pdf file

     tel_id: id of the telescope

     offset_value: baseline off_set
     """

    # plot open pdf
    if plot_file != "none":
        pp = PdfPages(plot_file)

    plt.rc('font', size=15)

    # r0 calibrator
    r0_calib = LSTR0Corrections(pedestal_path=pedestal_file,
                                offset=offset_value,
                                tel_id=tel_id)

    # event_reader
    reader = event_source(data_file, max_events=1000)
    t = np.linspace(2, 37, 36)

    # configuration for the charge integrator
    charge_config = Config(
        {"FixedWindowSum": {
            "window_start": 12,
            "window_width": 12,
        }})
    # declare the pedestal component
    pedestal = PedestalIntegrator(tel_id=tel_id,
                                  sample_size=1000,
                                  sample_duration=1000000,
                                  charge_median_cut_outliers=[-10, 10],
                                  charge_std_cut_outliers=[-10, 10],
                                  charge_product="FixedWindowSum",
                                  config=charge_config,
                                  subarray=reader.subarray)

    for i, event in enumerate(reader):
        if tel_id != event.r0.tels_with_data[0]:
            raise Exception(
                f"Given wrong telescope id {tel_id}, files has id {event.r0.tels_with_data[0]}"
            )

        # move from R0 to R1
        r0_calib.calibrate(event)

        ok = pedestal.calculate_pedestals(event)
        if ok:
            ped_data = event.mon.tel[tel_id].pedestal
            break

    camera_geometry = reader.subarray.tels[tel_id].camera.geometry
    camera_geometry = camera_geometry.transform_to(EngineeringCameraFrame())
    # plot open pdf
    if plot_file != "none":
        pp = PdfPages(plot_file)

    plt.rc('font', size=15)

    ### first figure
    fig = plt.figure(1, figsize=(12, 24))
    plt.tight_layout()
    n_samples = charge_config["FixedWindowSum"]['window_width']
    fig.suptitle(f"Run {run}, integration on {n_samples} samples", fontsize=25)
    pad = 420

    image = ped_data.charge_median
    mask = ped_data.charge_median_outliers
    for chan in (np.arange(2)):
        pad += 1
        plt.subplot(pad)
        plt.tight_layout()
        disp = CameraDisplay(camera_geometry)
        mymin = np.median(image[chan]) - 2 * np.std(image[chan])
        mymax = np.median(image[chan]) + 2 * np.std(image[chan])
        disp.set_limits_minmax(mymin, mymax)
        disp.highlight_pixels(mask[chan], linewidth=2)
        disp.image = image[chan]
        disp.cmap = plt.cm.coolwarm
        # disp.axes.text(lposx, 0, f'{channel[chan]} pedestal [ADC]', rotation=90)
        plt.title(f'{channel[chan]} pedestal [ADC]')
        disp.add_colorbar()

    image = ped_data.charge_std
    mask = ped_data.charge_std_outliers
    for chan in (np.arange(2)):
        pad += 1
        plt.subplot(pad)
        plt.tight_layout()
        disp = CameraDisplay(camera_geometry)
        mymin = np.median(image[chan]) - 2 * np.std(image[chan])
        mymax = np.median(image[chan]) + 2 * np.std(image[chan])
        disp.set_limits_minmax(mymin, mymax)
        disp.highlight_pixels(mask[chan], linewidth=2)
        disp.image = image[chan]
        disp.cmap = plt.cm.coolwarm
        # disp.axes.text(lposx, 0, f'{channel[chan]} pedestal std [ADC]', rotation=90)
        plt.title(f'{channel[chan]} pedestal std [ADC]')
        disp.add_colorbar()

    ###  histograms
    for chan in np.arange(2):
        mean_ped = ped_data.charge_mean[chan]
        ped_std = ped_data.charge_std[chan]

        # select good pixels
        select = np.logical_not(mask[chan])

        #fig.suptitle(f"Run {run} channel: {channel[chan]}", fontsize=25)
        pad += 1
        # pedestal charge
        plt.subplot(pad)
        plt.tight_layout()
        plt.ylabel('pixels')
        plt.xlabel(f'{channel[chan]} pedestal')
        median = np.median(mean_ped[select])
        rms = np.std(mean_ped[select])
        label = f"{channel[chan]} Median {median:3.2f}, std {rms:3.2f}"
        plt.hist(mean_ped[select], bins=50, label=label)
        plt.legend()
        pad += 1
        # pedestal std
        plt.subplot(pad)
        plt.ylabel('pixels')
        plt.xlabel(f'{channel[chan]} pedestal std')
        median = np.median(ped_std[select])
        rms = np.std(ped_std[select])
        label = f" Median {median:3.2f}, std {rms:3.2f}"
        plt.hist(ped_std[select], bins=50, label=label)
        plt.legend()

    plt.subplots_adjust(top=0.94)
    if plot_file != "none":

        pp.savefig()

    pix = 0
    pad = 420
    # plot corrected waveforms of first 8 events
    for i, ev in enumerate(reader):
        for chan in np.arange(2):

            if pad == 420:
                # new figure

                fig = plt.figure(ev.index.event_id, figsize=(12, 24))
                fig.suptitle(f"Run {run}, pixel {pix}", fontsize=25)
                plt.tight_layout()
            pad += 1
            plt.subplot(pad)

            plt.subplots_adjust(top=0.92)
            label = f"event {ev.index.event_id}, {channel[chan]}: R0"
            plt.step(t,
                     ev.r0.tel[tel_id].waveform[chan, pix, 2:38],
                     color="blue",
                     label=label)

            r0_calib.subtract_pedestal(ev, tel_id)
            label = "+ pedestal substraction"
            plt.step(t,
                     ev.r1.tel[tel_id].waveform[chan, pix, 2:38],
                     color="red",
                     alpha=0.5,
                     label=label)

            r0_calib.time_lapse_corr(ev, tel_id)
            r0_calib.interpolate_spikes(ev, tel_id)
            label = "+ dt corr + interp. spikes"
            plt.step(t,
                     ev.r1.tel[tel_id].waveform[chan, pix, 2:38],
                     alpha=0.5,
                     color="green",
                     label=label)
            plt.plot([0, 40], [offset_value, offset_value],
                     'k--',
                     label="offset")
            plt.xlabel("time sample [ns]")
            plt.ylabel("counts [ADC]")
            plt.legend()
            plt.ylim([-50, 500])

        if plot_file != "none" and pad == 428:
            pad = 420
            plt.subplots_adjust(top=0.92)
            pp.savefig()

        if i == 8:
            break

    if plot_file != "none":
        pp.close()
Example #9
0
class ImagePlotter(Component):
    """ Plotter for camera images """

    display = Bool(
        True,
        help="Display the photoelectron images on-screen as they are produced."
    ).tag(config=True)
    output_path = traits.Path(
        directory_ok=False,
        help=("Output path for the pdf containing all the images."
              " Set to None for no saved output."),
    ).tag(config=True)

    def __init__(self, subarray, config=None, parent=None, **kwargs):
        """
        Plotter for camera images.

        Parameters
        ----------
        config : traitlets.loader.Config
            Configuration specified by config file or cmdline arguments.
            Used to set traitlet values.
            Set to None if no configuration to pass.
        tool : ctapipe.core.Tool
            Tool executable that is calling this component.
            Passes the correct logger to the component.
            Set to None if no Tool to pass.
        kwargs
        """
        super().__init__(config=config, parent=parent, **kwargs)
        self._current_tel = None
        self.c_intensity = None
        self.c_peak_time = None
        self.cb_intensity = None
        self.cb_peak_time = None
        self.pdf = None
        self.subarray = subarray

        self._init_figure()

    def _init_figure(self):
        self.fig = plt.figure(figsize=(16, 7))
        self.ax_intensity = self.fig.add_subplot(1, 2, 1)
        self.ax_peak_time = self.fig.add_subplot(1, 2, 2)
        if self.output_path:
            self.log.info(f"Creating PDF: {self.output_path}")
            self.pdf = PdfPages(self.output_path)

    def plot(self, event, telid):
        image = event.dl1.tel[telid].image
        peak_time = event.dl1.tel[telid].peak_time

        if self._current_tel != telid:
            self._current_tel = telid

            self.ax_intensity.cla()
            self.ax_peak_time.cla()

            # Redraw camera
            geom = self.subarray.tel[telid].camera.geometry
            self.c_intensity = CameraDisplay(geom, ax=self.ax_intensity)

            time_cmap = copy(plt.get_cmap("RdBu_r"))
            time_cmap.set_under("gray")
            time_cmap.set_over("gray")
            self.c_peak_time = CameraDisplay(geom,
                                             ax=self.ax_peak_time,
                                             cmap=time_cmap)

            if not self.cb_intensity:
                self.c_intensity.add_colorbar(ax=self.ax_intensity,
                                              label="Intensity (p.e.)")
                self.cb_intensity = self.c_intensity.colorbar
            else:
                self.c_intensity.colorbar = self.cb_intensity
                self.c_intensity.update(True)
            if not self.cb_peak_time:
                self.c_peak_time.add_colorbar(ax=self.ax_peak_time,
                                              label="Pulse Time (ns)")
                self.cb_peak_time = self.c_peak_time.colorbar
            else:
                self.c_peak_time.colorbar = self.cb_peak_time
                self.c_peak_time.update(True)

        self.c_intensity.image = image
        self.c_peak_time.image = peak_time

        # center around brightes pixel, show 10ns total
        t_chargemax = peak_time[image.argmax()]
        self.c_peak_time.set_limits_minmax(t_chargemax - 5, t_chargemax + 5)

        self.fig.suptitle("Event_index={}  Event_id={}  Telescope={}".format(
            event.count, event.index.event_id, telid))

        if self.display:
            plt.pause(0.001)

        if self.pdf is not None:
            self.pdf.savefig(self.fig)

    def finish(self):
        if self.pdf is not None:
            self.log.info("Closing PDF")
            self.pdf.close()
Example #10
0
def draw_neighbors(geom, pixel_index, color='r', **kwargs):
    """Draw lines between a pixel and its neighbors"""

    neigh = geom.neighbors[pixel_index]  # neighbor indices (not pixel ids)
    x, y = geom.pix_x[pixel_index].value, geom.pix_y[pixel_index].value
    for nn in neigh:
        nx, ny = geom.pix_x[nn].value, geom.pix_y[nn].value
        plt.plot([x, nx], [y, ny], color=color, **kwargs)


if __name__ == '__main__':

    # Load the camera
    geom = CameraGeometry.from_name("LSTCam")
    disp = CameraDisplay(geom)
    disp.set_limits_minmax(0, 300)
    disp.add_colorbar()

    # Create a fake camera image to display:
    model = toymodel.generate_2d_shower_model(centroid=(0.2, 0.0),
                                              width=0.01,
                                              length=0.1,
                                              psi='35d')

    image, sig, bg = toymodel.make_toymodel_shower_image(geom, model.pdf,
                                                         intensity=50,
                                                         nsb_level_pe=1000)

    # Apply image cleaning
    cleanmask = tailcuts_clean(geom, image, picture_thresh=200,
                               boundary_thresh=100)
Example #11
0
def nsb_rate(
        baseline_histo_file, dark_histo_file, param_file, template_filename,
        plot="show", plot_nsb_range=None, norm="log",
        bias_resistance=1e4 * u.Ohm, cell_capacitance=5e-14 * u.Farad
):
    baseline_histo = Histogram1D.load(baseline_histo_file)
    dark_histo = Histogram1D.load(dark_histo_file)
    baseline_shift = baseline_histo.mean()-dark_histo.mean()
    n_pixel = len(DigiCam.geometry.neighbors)
    pixels = np.arange(n_pixel, dtype=int)
    with open(param_file) as file:
        pulse_template = NormalizedPulseTemplate.load(template_filename)
        pulse_area = pulse_template.integral() * u.ns
        charge_to_amplitude = pulse_template.compute_charge_amplitude_ratio(7, 4)
        calibration_parameters = yaml.load(file)
        gain_integral = np.array(calibration_parameters['gain'])
        gain_amplitude = gain_integral * charge_to_amplitude
        crosstalk = np.array(calibration_parameters['mu_xt'])
    rate = _compute_nsb_rate(
        baseline_shift=baseline_shift, gain=gain_amplitude,
        pulse_area=pulse_area, crosstalk=crosstalk,
        bias_resistance=bias_resistance, cell_capacitance=cell_capacitance
    )
    bad_pixels = get_bad_pixels(
        calib_file=param_file, nsigma_gain=5, nsigma_elecnoise=5,
        dark_histo=dark_histo_file, nsigma_dark=8, plot=None, output=None
    )
    bad_pixels = np.unique(np.hstack(
        (
            bad_pixels,
            pixels[rate < 0],
            pixels[rate > 5 * u.GHz]
        )
    ))
    avg_matrix = _get_average_matrix_bad_pixels(DigiCam.geometry, bad_pixels)
    good_pixels_mask = np.ones(n_pixel, dtype=bool)
    good_pixels_mask[bad_pixels] = False
    good_pixels = pixels[good_pixels_mask]

    rate[bad_pixels] = avg_matrix[bad_pixels, :].dot(rate[good_pixels])
    if plot is None:
        return rate
    fig1, ax = plt.subplots(1, 1)
    display = CameraDisplay(DigiCam.geometry, ax=ax, norm=norm,
                            title='NSB rate [GHz]')
    rate_ghz = rate.to(u.GHz).value
    display.image = rate_ghz
    if plot_nsb_range is None:
        plot_nsb_range = (np.min(rate_ghz), np.max(rate_ghz))
    display.set_limits_minmax(*plot_nsb_range)
    display.add_colorbar(ax=ax)
    display.highlight_pixels(bad_pixels, color='r', linewidth=2)
    plt.tight_layout()
    output_path = os.path.dirname(plot)
    if plot == "show" or \
            (output_path != "" and not os.path.isdir(output_path)):
        if not plot == "show":
            print('WARNING: Path ' + output_path + ' for output trigger ' +
                  'uniformity does not exist, displaying the plot instead.\n')
        plt.show()
    else:
        plt.savefig(plot)
        print(plot, 'created')
    plt.close(fig1)
    return rate
Example #12
0
rdbu = plt.get_cmap('RdBu_r')
rdbu.set_bad('gray')

for i in range(2):
    fig, axs = plt.subplots(1, 2, figsize=(5, 2), constrained_layout=True)

    if i == 1:
        clean = tailcuts_clean(cam, img, 9, 3)
        img[~clean] = np.nan
        time[~clean] = np.nan

    disp = CameraDisplay(cam, ax=axs[0])
    disp.image = img
    disp.cmap = inferno
    disp.add_colorbar(ax=axs[0])
    disp.set_limits_minmax(0, 45)
    disp.pixels.set_rasterized(True)

    disp2 = CameraDisplay(cam, ax=axs[1])
    disp2.image = time
    disp2.cmap = rdbu
    disp2.set_limits_minmax(10, 40)
    disp2.add_colorbar(ax=axs[1])
    disp2.pixels.set_rasterized(True)

    axs[0].set_title('\# Photons')
    axs[1].set_title('Time / ns')

    for ax in axs:
        ax.set_axis_off()
        ax.set_aspect(1, 'box')
    def finish(self):
        """
        write fit results in h5 file and the check-plots in pdf file
        """

        gain = np.ma.array(self.fit_parameters.T[0], mask=self.fit_error.T)
        quadratic_term = np.ma.array(self.fit_parameters.T[1], mask=self.fit_error.T)

        # give to the badly fitted pixel a median value for the B term
        median_quadratic_term = np.ma.median(quadratic_term, axis=0)

        fill_array = np.ones((constants.N_PIXELS, constants.N_GAINS)) * median_quadratic_term

        quadratic_term_corrected = np.ma.filled(quadratic_term, fill_array)

        with h5py.File(self.output_path, 'w') as hf:
            hf.create_dataset('gain', data=gain.T)
            hf.create_dataset('B_term', data=quadratic_term_corrected.T)
            hf.create_dataset('covariance_matrix', data=self.fit_cov_matrix)
            hf.create_dataset('bad_fit_mask', data=self.fit_error)

            # remember the camera median and the variance per run
            channel = ["HG", "LG"]
            for chan in [0, 1]:
                if self.signal[chan] is not None:
                    hf.create_dataset(f'median_signal_{channel[chan]}', data=np.median(self.signal[chan], axis=0))
                    hf.create_dataset(f'median_variance_{channel[chan]}', data=np.median(self.variance[chan], axis=0))
                    hf.create_dataset(f'runs_{channel[chan]}', data=self.selected_runs[chan])

            hf.create_dataset('runs', data=self.run_list)
            hf.create_dataset('sub_run', data=self.sub_run)

            # plot open pdf
            with PdfPages(self.plot_path) as pdf:
                plt.rc("font", size=15)

                for chan in self.gain_channels:
                    # plot the used runs and their median camera charge
                    fig = plt.figure((chan + 1), figsize=(8, 20))
                    fig.suptitle(f"{channel[chan]} channel", fontsize=25)
                    ax = plt.subplot(2, 1, 1)
                    ax.grid(True)
                    ax.yaxis.set_major_locator(MaxNLocator(integer=True))
                    ax.xaxis.set_major_locator(MaxNLocator(integer=True))
                    ax.yaxis.set_major_locator(plt.MultipleLocator(1))

                    plt.plot(np.median(self.signal[chan], axis=0), self.selected_runs[chan], "o")
                    plt.xlabel(r'$\mathrm{\overline{Q}-\overline{ped}}$ [ADC]')
                    plt.ylabel(r'Runs used in the fit')

                    plt.subplot(2, 1, 2)
                    camera = load_camera_geometry()
                    camera = camera.transform_to(EngineeringCameraFrame())
                    disp = CameraDisplay(camera)
                    image = self.fit_parameters.T[1].T * 100
                    mymin = np.median(image[chan]) - 3 * np.std(image[chan])
                    mymax = np.median(image[chan]) + 3 * np.std(image[chan])
                    disp.set_limits_minmax(mymin, mymax)
                    mask = np.where(self.fit_error[chan] == 1)[0]
                    disp.highlight_pixels(mask, linewidth=2.5, color="green")
                    disp.image = image[chan]
                    disp.cmap = plt.cm.coolwarm
                    plt.title(f"{channel[chan]} Fitted B values [%]")
                    disp.add_colorbar()
                    plt.tight_layout()
                    pdf.savefig()

                    # plot the fit results and residuals for four arbitrary  pixels
                    fig = plt.figure((chan + 1) * 10, figsize=(11, 22))
                    fig.suptitle(f"{channel[chan]} channel", fontsize=25)

                    pad = 0
                    for pix in [0, 600, 1200, 1800]:
                        pad += 1
                        plt.subplot(4, 2, pad)
                        plt.grid(which='minor')

                        mask = self.unusable_pixels[chan][pix]
                        sig = np.ma.array(self.signal[chan][pix], mask=mask).compressed()
                        var = np.ma.array(self.variance[chan][pix], mask=mask).compressed()
                        popt = self.fit_parameters[chan, pix]

                        # plot points
                        plt.plot(sig, var, 'o', color="C0")

                        # plot fit
                        min_x = min(1000, np.min(sig) * 0.9)
                        max_x = max(10000, np.max(sig) * 1.1)
                        x = np.arange(np.min(sig), np.max(sig))

                        plt.plot(x, quadratic_fit(x, *popt), '--', color="C1",
                                 label=f'Pixel {pix}:\ng={popt[0]:5.2f} [ADC/pe] , B={popt[1]:5.3f}')
                        plt.xlim(min_x, max_x)
                        plt.xlabel('Q-ped [ADC]')
                        plt.ylabel(r'$\mathrm{\sigma_Q^2-\sigma_{ped}^2}$ [$ADC^2$]')
                        plt.xscale('log')
                        plt.yscale('log')
                        plt.legend()

                        # plot residuals
                        pad += 1
                        plt.subplot(4, 2, pad)
                        plt.grid(which='both', axis='both')

                        popt = self.fit_parameters[chan, pix]
                        plt.plot(sig, (quadratic_fit(sig, *popt) - var) / var * 100, 'o', color="C0")
                        plt.xlim(min_x, max_x)
                        plt.xscale('log')
                        plt.ylabel('fit residuals %')
                        plt.xlabel('Q-ped [ADC]')
                        plt.hlines(0, 0, np.max(sig), linestyle='dashed', color="black")

                    plt.tight_layout()
                    pdf.savefig()
Example #14
0
def plot_pedestals(data_file, pedestal_file, run=0, plot_file=None, tel_id=1, offset_value=400, sample_size=1000):
    """
    plot pedestal quantities quantities

    Parameters
    ----------
    data_file:   pedestal run

    pedestal_file:   file with drs4 corrections

    run: run number of data to be corrected

    plot_file:  name of output pdf file

    tel_id: id of the telescope

    offset_value: baseline off_set
    """

    config = {
        "LSTEventSource": {
            "allowed_tels": [1],
            "LSTR0Corrections": {
                "drs4_pedestal_path": pedestal_file,
            },
        }
    }
    # event_reader
    reader = EventSource(data_file, config=Config(config), max_events=None)
    t = np.linspace(2, 37, 36)

    # configuration for the charge integrator
    charge_config = Config(
        {
            "FixedWindowSum": {
                "window_shift": 6,
                "window_width": 12,
                "peak_index": 18,
            }
        }
    )
    # declare the pedestal component
    pedestal = PedestalIntegrator(
        tel_id=tel_id,
        time_sampling_correction_path=None,
        sample_size=sample_size,
        sample_duration=1000000,
        charge_median_cut_outliers=[-10, 10],
        charge_std_cut_outliers=[-10, 10],
        charge_product="FixedWindowSum",
        config=charge_config,
        subarray=reader.subarray,
    )

    for i, event in enumerate(reader):
        if tel_id != event.trigger.tels_with_trigger[0]:
            raise Exception(
                f"Given wrong telescope id {tel_id}, files has id {event.trigger.tels_with_trigger[0]}"
            )

        are_pedestals_calculated = pedestal.calculate_pedestals(event)
        if are_pedestals_calculated:
            ped_data = event.mon.tel[tel_id].pedestal
            break

    camera_geometry = reader.subarray.tels[tel_id].camera.geometry
    camera_geometry = camera_geometry.transform_to(EngineeringCameraFrame())

    if are_pedestals_calculated and plot_file is not None:
        with PdfPages(plot_file) as pdf:

            plt.rc("font", size=15)

            # first figure
            fig = plt.figure(1, figsize=(12, 24))
            plt.tight_layout()
            n_samples = charge_config["FixedWindowSum"]["window_width"]
            fig.suptitle(f"Run {run}, integration on {n_samples} samples", fontsize=25)
            pad = 420

            image = ped_data.charge_median
            mask = ped_data.charge_median_outliers
            for chan in np.arange(2):
                pad += 1
                plt.subplot(pad)
                plt.tight_layout()
                disp = CameraDisplay(camera_geometry)
                mymin = np.median(image[chan]) - 2 * np.std(image[chan])
                mymax = np.median(image[chan]) + 2 * np.std(image[chan])
                disp.set_limits_minmax(mymin, mymax)
                disp.highlight_pixels(mask[chan], linewidth=2)
                disp.image = image[chan]
                disp.cmap = plt.cm.coolwarm
                # disp.axes.text(lposx, 0, f'{channel[chan]} pedestal [ADC]', rotation=90)
                plt.title(f"{channel[chan]} pedestal [ADC]")
                disp.add_colorbar()

            image = ped_data.charge_std
            mask = ped_data.charge_std_outliers
            for chan in np.arange(2):
                pad += 1
                plt.subplot(pad)
                plt.tight_layout()
                disp = CameraDisplay(camera_geometry)
                mymin = np.median(image[chan]) - 2 * np.std(image[chan])
                mymax = np.median(image[chan]) + 2 * np.std(image[chan])
                disp.set_limits_minmax(mymin, mymax)
                disp.highlight_pixels(mask[chan], linewidth=2)
                disp.image = image[chan]
                disp.cmap = plt.cm.coolwarm
                # disp.axes.text(lposx, 0, f'{channel[chan]} pedestal std [ADC]', rotation=90)
                plt.title(f"{channel[chan]} pedestal std [ADC]")
                disp.add_colorbar()

            #  histograms
            for chan in np.arange(2):
                mean_ped = ped_data.charge_mean[chan]
                ped_std = ped_data.charge_std[chan]

                # select good pixels
                select = np.logical_not(mask[chan])

                # fig.suptitle(f"Run {run} channel: {channel[chan]}", fontsize=25)
                pad += 1
                # pedestal charge
                plt.subplot(pad)
                plt.tight_layout()
                plt.ylabel("pixels")
                plt.xlabel(f"{channel[chan]} pedestal")
                median = np.median(mean_ped[select])
                rms = np.std(mean_ped[select])
                label = f"{channel[chan]} Median {median:3.2f}, std {rms:3.2f}"
                plt.hist(mean_ped[select], bins=50, label=label)
                plt.legend()
                pad += 1
                # pedestal std
                plt.subplot(pad)
                plt.ylabel("pixels")
                plt.xlabel(f"{channel[chan]} pedestal std")
                median = np.median(ped_std[select])
                rms = np.std(ped_std[select])
                label = f" Median {median:3.2f}, std {rms:3.2f}"
                plt.hist(ped_std[select], bins=50, label=label)
                plt.legend()

            plt.subplots_adjust(top=0.94, bottom=0.04, right=0.96)

            pdf.savefig()
            plt.close()

            # event_reader
            # reader = EventSource(data_file, config=Config(config), max_events=1000)

            pix = 0
            pad = 420
            offset_value = reader.r0_r1_calibrator.offset.tel[tel_id]

            # plot corrected waveforms of first 8 events
            for i, ev in enumerate(reader):
                for chan in np.arange(2):

                    if pad == 420:
                        # new figure

                        fig = plt.figure(ev.index.event_id * 1000, figsize=(12, 24))
                        fig.suptitle(f"Run {run}, pixel {pix}", fontsize=25)
                        plt.tight_layout()
                    pad += 1
                    plt.subplot(pad)

                    # remove samples at beginning / end of waveform
                    start = reader.r0_r1_calibrator.r1_sample_start.tel[tel_id]
                    end = reader.r0_r1_calibrator.r1_sample_end.tel[tel_id]

                    plt.subplots_adjust(top=0.92)
                    label = f"event {ev.index.event_id}, {channel[chan]}: R0"
                    plt.step(
                        t,
                        ev.r0.tel[tel_id].waveform[chan, pix, start:end],
                        color="blue",
                        label=label,
                    )

                    label = "baseline correction \n + dt corr + interp. spikes"

                    plt.step(
                        t,
                        ev.r1.tel[tel_id].waveform[chan, pix] + offset_value,
                        alpha=0.5,
                        color="green",
                        label=label,
                    )
                    plt.plot([0, 40], [offset_value, offset_value], "k--", label="offset")
                    plt.xlabel("time sample [ns]")
                    plt.ylabel("counts [ADC]")
                    plt.legend()
                    plt.ylim(200, 600)

                if pad == 428:
                    pad = 420
                    plt.subplots_adjust(top=0.92)
                    pdf.savefig()
                    plt.close()

                if i == 8:
                    break

    elif not are_pedestals_calculated:
        log.error("Not able to calculate pedestals or output pdf file not especified.")

    elif plot_file is None:
        log.warning("Not PDF outputfile specified.")
Example #15
0
def nsb_rate(
        files, aux_basepath, dark_histo_file, param_file, template_filename,
        output=None, plot="show", plot_nsb_range=None, norm="log",
        plot_baselines=False, disable_bar=False, max_events=None, n_skip=10,
        stars=True,
        bias_resistance=1e4 * u.Ohm, cell_capacitance=5e-14 * u.Farad
):
    files = np.atleast_1d(files)

    if len(files) == 1 and not files[0].endswith('.fz'):
        table = Table.read(files[0])[:max_events]
        data = dict(table)
        data['nsb_rate'] = np.array(data['nsb_rate']) * u.GHz
    else:
        dark_histo = Histogram1D.load(dark_histo_file)
        n_pixel = len(DigiCam.geometry.neighbors)
        pixels = np.arange(n_pixel, dtype=int)
        with open(param_file) as file:
            pulse_template = NormalizedPulseTemplate.load(template_filename)
            pulse_area = pulse_template.integral() * u.ns
            charge_to_amplitude = pulse_template.compute_charge_amplitude_ratio(7, 4)
            calibration_parameters = yaml.load(file)
            gain_integral = np.array(calibration_parameters['gain'])
            gain_amplitude = gain_integral * charge_to_amplitude
            crosstalk = np.array(calibration_parameters['mu_xt'])
        events = calibration_event_stream(files, max_events=max_events,
                                          disable_bar=disable_bar)
        events = add_slow_data_calibration(
            events, basepath=aux_basepath,
            aux_services=('DriveSystem', )
        )
        data = {
            "baseline": [],
            "nsb_rate": [],
            "good_pixels_mask": [],
            "timestamp": [],
            "event_id": [],
            "az": [],
            "el": [],
        }
        bad_pixels = get_bad_pixels(
            calib_file=param_file, nsigma_gain=5, nsigma_elecnoise=5,
            dark_histo=dark_histo_file, nsigma_dark=8, plot=None, output=None
        )
        events_skipped = 0
        for event in events:
            if event.event_type.INTERNAL not in event.event_type:
                continue
            events_skipped += 1
            if events_skipped < n_skip:
                continue
            events_skipped = 0
            data['baseline'].append(event.data.digicam_baseline)
            baseline_shift = event.data.digicam_baseline - dark_histo.mean()
            rate = _compute_nsb_rate(
                baseline_shift=baseline_shift, gain=gain_amplitude,
                pulse_area=pulse_area, crosstalk=crosstalk,
                bias_resistance=bias_resistance, cell_capacitance=cell_capacitance
            )
            bad_pixels_event = np.unique(np.hstack(
                (
                    bad_pixels,
                    pixels[rate < 0],
                    pixels[rate > 5 * u.GHz]
                )
            ))
            avg_matrix = _get_average_matrix_bad_pixels(
                DigiCam.geometry, bad_pixels_event
            )
            good_pixels_mask = np.ones(n_pixel, dtype=bool)
            good_pixels_mask[bad_pixels_event] = False
            good_pixels = pixels[good_pixels_mask]
            rate[bad_pixels_event] = avg_matrix[bad_pixels_event, :].dot(
                rate[good_pixels]
            )
            data['good_pixels_mask'].append(good_pixels_mask)
            data['timestamp'].append(event.data.local_time)
            data['event_id'].append(event.event_id)
            data['nsb_rate'].append(rate)
            data['az'].append(event.slow_data.DriveSystem.current_position_az)
            data['el'].append(event.slow_data.DriveSystem.current_position_el)
        data['nsb_rate'] = np.array(data['nsb_rate']) * u.GHz
        if output is not None:
            table = Table(data)
            if os.path.isfile(output):
                os.remove(output)
            table.write(output, format='fits')

    time_obs = Time(
        np.array(data['timestamp'], dtype=np.float64) * 1e-9,
        format='unix'
    )
    if plot_baselines:
        fig2, (ax1, ax2) = plt.subplots(2, 1, figsize=(16, 8), dpi=50)
        baseline_std = np.std(data['baseline'], axis=0)
        ax1.hist(baseline_std, 100)
        ax1.set_xlabel('std(baseline) [LSB]')
        # pixels_shown = np.arange(len(baseline_std))[baseline_std > 10]
        pixels_shown = [834,]
        ax2.plot_date(
            time_obs.to_datetime(),
            data['baseline'][:, pixels_shown],
            '-'
        )
        ax2.set_xlabel('time')
        ax2.set_ylabel('baseline [LSB]')
        plt.tight_layout()
        plt.show()
        plt.close(fig2)

    az_obs = np.array(data['az']) * u.deg
    el_obs = np.array(data['el']) * u.deg
    n_event = len(data['timestamp'])
    fig1, ax = plt.subplots(1, 1, figsize=(16, 12), dpi=50)
    date = datetime.fromtimestamp(data['timestamp'][0]*1e-9)
    date_str = date.strftime("%H:%M:%S")
    display = CameraDisplay(
        DigiCam.geometry, ax=ax, norm=norm,
        title='NSB rate [GHz], t=' + date_str
    )
    rate_ghz = np.array(data['nsb_rate'][0].to(u.GHz).value)
    display.image = rate_ghz
    if plot_nsb_range is None:
        min_range_rate = np.max([np.min(rate_ghz), 50e-3])
        plot_nsb_range = (min_range_rate, np.max(rate_ghz))
    display.set_limits_minmax(*plot_nsb_range)
    display.add_colorbar(ax=ax)
    bad_pixels = np.arange(
        len(data['good_pixels_mask'][0])
    )[~data['good_pixels_mask'][0]]
    display.highlight_pixels(bad_pixels, color='r', linewidth=2)
    display.axes.set_xlim([-500., 500.])
    display.axes.set_ylim([-500., 500.])
    plt.tight_layout()
    if stars is True:
        stars_az, stars_alt, stars_pmag = get_stars_in_fov(
            az_obs[0], el_obs[0], time_obs
        )
        stars_x, stars_y = transform_azel_to_xy(
            stars_az, stars_alt, az_obs, el_obs
        )
        point_stars = []
        for index_star in range(len(stars_pmag)):
            point_star, = ax.plot(
                stars_x[index_star, 0],
                stars_y[index_star, 0],
                'ok',
                ms=20-2*stars_pmag[index_star],
                mew=3,
                mfc='None'
            )
            point_stars.append(point_star)

    def update(i, display):
        print('frame', i, '/', len(data['timestamp']))
        display.image = data['nsb_rate'][i].to(u.GHz).value
        date = datetime.fromtimestamp(data['timestamp'][i] * 1e-9)
        date_str = date.strftime("%H:%M:%S")
        display.axes.set_title('NSB rate [GHz], t=' + date_str)
        bad_pixels = np.arange(
            len(data['good_pixels_mask'][i])
        )[~data['good_pixels_mask'][i]]
        display.highlight_pixels(
            bad_pixels, color='r', linewidth=2
        )
        if stars is True:
            for index_star in range(len(stars_pmag)):
                point_stars[index_star].set_xdata(
                    stars_x[index_star, i]
                )
                point_stars[index_star].set_ydata(
                    stars_y[index_star, i]
                )

    anim = FuncAnimation(
        fig1,
        update,
        frames=len(data['timestamp']),
        interval=20,
        fargs=(display, )
    )
    Writer = animation.writers['ffmpeg']
    writer = Writer(fps=50, metadata=dict(artist='Y. Renier'),
                    bitrate=4000, codec='h263p')

    output_path = os.path.dirname(plot)
    if plot == "show" or \
            (output_path != "" and not os.path.isdir(output_path)):
        if not plot == "show":
            print('WARNING: Path ' + output_path + ' for output trigger ' +
                  'uniformity does not exist, displaying the plot instead.\n')
        display.enable_pixel_picker()
        plt.show()
    else:
        anim.save(plot, writer=writer)
        print(plot, 'created')
    plt.close(fig1)
Example #16
0
def animate_baseline(events, video, event_id_min=None, event_id_max=None):
    event_ids = []
    ts = []
    baselines = []
    for event in events:
        if event_id_min and event.event_id <= event_id_min:
            continue
        if event_id_max and event.event_id >= event_id_max:
            break
        event_ids.append(event.event_id)
        ts.append(event.data.local_time)
        baselines.append(event.data.digicam_baseline)

    fig = plt.figure()
    ax = plt.gca()
    display = CameraDisplay(DigiCam.geometry, ax=ax)
    display.set_limits_minmax(300, 400)
    display.add_colorbar()
    title = plt.title("")

    if len(ts) == 0:
        print('WARNING: no event found for burst !')
        return
    t0 = ts[0]
    title_text = 'Baseline evolution\n' + 'event: %i, t=%.3f s' % \
                 (event_ids[0], 0.000)
    title.set_text(title_text)
    display.image = baselines[0]

    def update(i):
        event_id = event_ids[i]
        t = ts[i]
        title_text = 'Baseline evolution\n' + 'event: %i, t=%.3f s' \
                     % (event_id, np.round((t - t0) * 1e-9, 3))
        title.set_text(title_text)
        display.image = baselines[i]
        return display, title

    nframe = len(ts)
    print('creating animation with', nframe, 'frames')
    anim = animation.FuncAnimation(fig,
                                   update,
                                   frames=np.arange(1, nframe),
                                   interval=200)
    print('saving...')
    # plt.rcParams['animation.ffmpeg_path'] = \
    #     u'/home/yves/anaconda3/envs/digicampipe/bin/ffmpeg'
    if video != "show":
        # import logging
        # logger = logging.getLogger('matplotlib.animation')
        # logger.setLevel(logging.DEBUG)
        anim.save(video,
                  writer='ffmpeg',
                  metadata=dict(artist='*****@*****.**',
                                comment='baseline during burst'),
                  codec='mpeg4',
                  bitrate=20000)
        print('video saved as', video)
    else:
        plt.show()
    plt.close(fig)
Example #17
0
def plot_all(ped_data, ff_data, calib_data, run=0, plot_file=None):
    """
    plot camera calibration quantities

    Parameters
    ----------
    ped_data:   pedestal container PedestalContainer()

    ff_data:    flat-field container FlatFieldContainer()

    calib_data: calibration container WaveformCalibrationContainer()

    run: run number

    plot_file: name of the output PDF file. No file is produced if name is not provided

    """
    # read geometry
    camera = load_camera_geometry()
    camera = camera.transform_to(EngineeringCameraFrame())

    # plot open pdf
    if plot_file is not None:
        with PdfPages(plot_file) as pdf:

            plt.rc("font", size=15)

            # first figure
            fig = plt.figure(1, figsize=(12, 24))
            plt.tight_layout()
            fig.suptitle(f"Run {run}", fontsize=25)
            pad = 420
            image = ff_data.charge_median
            mask = ff_data.charge_median_outliers
            for chan in np.arange(2):
                pad += 1
                plt.subplot(pad)
                plt.tight_layout()
                disp = CameraDisplay(camera)
                mymin = np.median(image[chan]) - 2 * np.std(image[chan])
                mymax = np.median(image[chan]) + 2 * np.std(image[chan])
                disp.set_limits_minmax(mymin, mymax)
                disp.highlight_pixels(mask[chan], linewidth=2)
                disp.image = image[chan]
                disp.cmap = plt.cm.coolwarm
                # disp.axes.text(lposx, 0, f'{channel[chan]} signal charge (ADC)', rotation=90)
                plt.title(f"{channel[chan]} signal charge [ADC]")
                disp.add_colorbar()

            image = ff_data.charge_std
            mask = ff_data.charge_std_outliers
            for chan in np.arange(2):
                pad += 1
                plt.subplot(pad)
                plt.tight_layout()
                disp = CameraDisplay(camera)
                mymin = np.median(image[chan]) - 2 * np.std(image[chan])
                mymax = np.median(image[chan]) + 2 * np.std(image[chan])
                disp.set_limits_minmax(mymin, mymax)
                disp.highlight_pixels(mask[chan], linewidth=2)
                disp.image = image[chan]
                disp.cmap = plt.cm.coolwarm
                # disp.axes.text(lposx, 0, f'{channel[chan]} signal std [ADC]', rotation=90)
                plt.title(f"{channel[chan]} signal std [ADC]")
                disp.add_colorbar()

            image = ped_data.charge_median
            mask = ped_data.charge_median_outliers
            for chan in np.arange(2):
                pad += 1
                plt.subplot(pad)
                plt.tight_layout()
                disp = CameraDisplay(camera)
                mymin = np.median(image[chan]) - 2 * np.std(image[chan])
                mymax = np.median(image[chan]) + 2 * np.std(image[chan])
                disp.set_limits_minmax(mymin, mymax)
                disp.highlight_pixels(mask[chan], linewidth=2)
                disp.image = image[chan]
                disp.cmap = plt.cm.coolwarm
                # disp.axes.text(lposx, 0, f'{channel[chan]} pedestal [ADC]', rotation=90)
                plt.title(f"{channel[chan]} pedestal [ADC]")
                disp.add_colorbar()

            image = ped_data.charge_std
            mask = ped_data.charge_std_outliers
            for chan in np.arange(2):
                pad += 1
                plt.subplot(pad)
                plt.tight_layout()
                disp = CameraDisplay(camera)
                mymin = np.median(image[chan]) - 2 * np.std(image[chan])
                mymax = np.median(image[chan]) + 2 * np.std(image[chan])
                disp.set_limits_minmax(mymin, mymax)
                disp.highlight_pixels(mask[chan], linewidth=2)
                disp.image = image[chan]
                disp.cmap = plt.cm.coolwarm
                # disp.axes.text(lposx, 0, f'{channel[chan]} pedestal std [ADC]', rotation=90)
                plt.title(f"{channel[chan]} pedestal std [ADC]")
                disp.add_colorbar()

            plt.subplots_adjust(top=0.92)

            pdf.savefig()
            plt.close()

            # second figure
            fig = plt.figure(2, figsize=(12, 24))
            plt.tight_layout()
            fig.suptitle(f"Run {run}", fontsize=25)
            pad = 420

            # time
            image = ff_data.time_median
            mask = ff_data.time_median_outliers
            for chan in np.arange(2):
                pad += 1
                plt.subplot(pad)
                plt.tight_layout()
                disp = CameraDisplay(camera)
                disp.highlight_pixels(mask[chan], linewidth=2)
                disp.image = image[chan]
                disp.cmap = plt.cm.coolwarm
                # disp.axes.text(lposx, 0, f'{channel[chan]} time', rotation=90)
                plt.title(f"{channel[chan]} time")
                disp.add_colorbar()

            image = ff_data.relative_gain_median
            mask = calib_data.unusable_pixels
            for chan in np.arange(2):
                pad += 1
                plt.subplot(pad)
                plt.tight_layout()
                disp = CameraDisplay(camera)
                disp.highlight_pixels(mask[chan], linewidth=2)
                mymin = np.median(image[chan]) - 2 * np.std(image[chan])
                mymax = np.median(image[chan]) + 2 * np.std(image[chan])
                disp.set_limits_minmax(mymin, mymax)
                disp.image = image[chan]
                disp.cmap = plt.cm.coolwarm
                disp.set_limits_minmax(0.7, 1.3)
                plt.title(f"{channel[chan]} relative signal")
                # disp.axes.text(lposx, 0, f'{channel[chan]} relative gain', rotation=90)
                disp.add_colorbar()

            # pe
            image = calib_data.n_pe
            mask = calib_data.unusable_pixels
            image = np.where(np.isnan(image), 0, image)
            for chan in np.arange(2):
                pad += 1
                plt.subplot(pad)
                plt.tight_layout()
                disp = CameraDisplay(camera)
                disp.highlight_pixels(mask[chan], linewidth=2)
                disp.image = image[chan]
                mymin = np.median(image[chan]) - 2 * np.std(image[chan])
                mymax = np.median(image[chan]) + 2 * np.std(image[chan])
                disp.set_limits_minmax(mymin, mymax)
                disp.cmap = plt.cm.coolwarm
                plt.title(f"{channel[chan]} photon-electrons")
                # disp.axes.text(lposx, 0, f'{channel[chan]} photon-electrons', rotation=90)
                disp.add_colorbar()

            # pe histogram
            pad += 1
            plt.subplot(pad)
            plt.tight_layout()
            for chan in np.arange(2):
                n_pe = calib_data.n_pe[chan]
                # select good pixels
                select = np.logical_not(mask[chan])
                median = int(np.median(n_pe[select]))
                rms = np.std(n_pe[select])
                mymin = median - 4 * rms
                mymax = median + 4 * rms
                label = f"{channel[chan]} Median {median:3.2f}, std {rms:5.2f}"
                plt.hist(
                    n_pe[select],
                    label=label,
                    histtype="step",
                    range=(mymin, mymax),
                    bins=50,
                    stacked=True,
                    alpha=0.5,
                    fill=True,
                )
                plt.legend()
            plt.xlabel("pe", fontsize=20)
            plt.ylabel("pixels", fontsize=20)

            # pe scatter plot
            pad += 1
            plt.subplot(pad)
            plt.tight_layout()
            HG = calib_data.n_pe[0]
            LG = calib_data.n_pe[1]
            HG = np.where(np.isnan(HG), 0, HG)
            LG = np.where(np.isnan(LG), 0, LG)
            mymin = np.median(LG) - 2 * np.std(LG)
            mymax = np.median(LG) + 2 * np.std(LG)
            plt.hist2d(LG, HG, bins=[100, 100])
            plt.xlabel("LG", fontsize=20)
            plt.ylabel("HG", fontsize=20)

            x = np.arange(mymin, mymax)
            plt.plot(x, x)
            plt.ylim(mymin, mymax)
            plt.xlim(mymin, mymax)
            plt.subplots_adjust(top=0.92)

            pdf.savefig()
            plt.close()

            # figures 3 and 4: histograms
            for chan in np.arange(2):
                n_pe = calib_data.n_pe[chan]

                gain_median = ff_data.relative_gain_median[chan]
                charge_median = ff_data.charge_median[chan]
                #charge_mean = ff_data.charge_mean[chan]
                charge_std = ff_data.charge_std[chan]
                n_ff = ff_data.n_events
                median_ped = ped_data.charge_median[chan]
                #mean_ped = ped_data.charge_mean[chan]
                ped_std = ped_data.charge_std[chan]
                n_ped = ped_data.n_events

                dc_to_pe = calib_data.dc_to_pe[chan]
                time_correction = calib_data.time_correction[chan]

                # select good pixels
                select = np.logical_not(mask[chan])
                fig = plt.figure(chan + 10, figsize=(12, 24))
                fig.tight_layout(rect=[0, 0.0, 1, 0.95])

                fig.suptitle(f"Run {run} channel: {channel[chan]}", fontsize=25)

                # charge
                plt.subplot(421)
                plt.title(f"FF sample of {n_ff} events")
                plt.tight_layout()
                median = int(np.median(charge_median[select]))
                rms = np.std(charge_median[select])
                label = f"Median {median:3.2f}, std {rms:5.0f}"
                plt.xlabel("charge (ADC)", fontsize=20)
                plt.ylabel("pixels", fontsize=20)
                plt.hist(charge_median[select], bins=50, label=label)
                plt.legend()

                plt.subplot(422)
                plt.tight_layout()
                plt.ylabel("pixels", fontsize=20)
                plt.xlabel("charge std", fontsize=20)
                median = np.median(charge_std[select])
                rms = np.std(charge_std[select])
                label = f"Median {median:3.2f}, std {rms:3.2f}"
                plt.hist(charge_std[select], bins=50, label=label)
                plt.legend()

                # pedestal charge
                plt.subplot(423)
                plt.tight_layout()
                plt.title(f"pedestal sample of {n_ped} events")
                plt.ylabel("pixels", fontsize=20)
                plt.xlabel("pedestal", fontsize=20)
                median = np.median(median_ped[select])
                rms = np.std(median_ped[select])
                label = f"Median {median:3.2f}, std {rms:3.2f}"
                plt.hist(median_ped[select], bins=50, label=label)
                plt.legend()

                # pedestal std
                plt.subplot(424)
                plt.ylabel("pixels", fontsize=20)
                plt.xlabel("pedestal std", fontsize=20)
                median = np.median(ped_std[select])
                rms = np.std(ped_std[select])
                label = f"Median {median:3.2f}, std {rms:3.2f}"
                plt.hist(ped_std[select], bins=50, label=label)
                plt.legend()

                # relative gain
                plt.subplot(425)
                plt.tight_layout()
                plt.ylabel("pixels", fontsize=20)
                plt.xlabel("relative signal", fontsize=20)
                median = np.median(gain_median[select])
                rms = np.std(gain_median[select])
                label = f"Relative gain {median:3.2f}, std {rms:5.2f}"
                plt.hist(gain_median[select], bins=50, label=label)
                plt.legend()

                # photon electrons
                plt.subplot(426)
                plt.tight_layout()
                plt.ylabel("pixels", fontsize=20)
                plt.xlabel("time corrections [ns]", fontsize=20)
                median = np.median(time_correction[select])
                rms = np.std(time_correction[select])
                label = f"Median {median:3.2f}, std {rms:3.2f}"
                plt.hist(time_correction[select].value, bins=50, label=label)
                plt.legend()

                plt.subplots_adjust(top=0.92)
                # photon electrons
                plt.subplot(427)
                plt.tight_layout()
                plt.ylabel("pixels", fontsize=20)
                plt.xlabel("pe", fontsize=20)
                median = np.median(n_pe[select])
                rms = np.std(n_pe[select])
                label = f"Median {median:3.2f}, std {rms:3.2f}"
                plt.hist(n_pe[select], bins=50, label=label)
                plt.legend()
                plt.subplots_adjust(top=0.92)

                # gain
                plt.subplot(428)
                plt.tight_layout()
                plt.ylabel("pixels", fontsize=20)
                plt.xlabel("flat-fielded gain [ADC/pe]", fontsize=20)
                denominator = dc_to_pe[select]
                numerator = 1.

                gain = np.divide(numerator, denominator, out=np.zeros_like(denominator), where=denominator != 0)
                median = np.median(gain)
                rms = np.std(gain)
                label = f"Median {median:3.2f}, std {rms:3.2f}"
                plt.hist(gain, bins=50, label=label)
                plt.legend()
                plt.subplots_adjust(top=0.92)

                pdf.savefig(plt.gcf())
                plt.close()
Example #18
0
    #### CAM PLOT ####b
    ################## 
    f,axs = plt.subplots(ncols=2,figsize=(12,6))
    blankam1 = np.zeros(1855)
    blankam2 = np.zeros(1855)
    
    blankam2[pix_ids]=gains_2g
    
    # ~ blankam1[pix_ids]=res_2g.T[0]
    # ~ blankam2[pix_ids]=res_2g.T[1]


    disp2 = CameraDisplay(geom,title="gains (2 gauss mes)",ax=axs[1])

    disp2.add_colorbar(ax=axs[1])
    disp2.set_limits_minmax(zmin=gains_2g.min()-5,zmax=gains_2g.max()+5)
    disp2.image = blankam2
    
    

    # ~ pix_HVs     = get_pixs_HV( get_config_xml2(file_path) )
    d= {param_names[0] : res_2g.T[0], \
        param_names[1] : res_2g.T[1], \
        param_names[2] : res_2g.T[2], \
        param_names[3] : res_2g.T[3], \
        param_names[4] : res_2g.T[4], \
        'gain'         : gains_2g   , \
        'pix_num'      : modpix     }
    df = pd.DataFrame(d)
    sns.set()
    disp_p = 0
Example #19
0
    def start(self):

        # Get first event information
        first_event = self.reader.get_event(0)
        n_pixels = first_event.inst.num_pixels[0]
        n_samples = first_event.r0.tel[0].num_samples
        pos = first_event.inst.pixel_pos[0]
        foclen = first_event.inst.optical_foclen[0]
        geom = CameraGeometry.guess(*pos, foclen)

        # Setup Output
        output_dir = self.reader.output_directory
        title = self.reader.filename
        title = title[:title.find("_")]
        # Prepare Output
        if not exists(output_dir):
            self.log.info("Creating directory: {}".format(output_dir))
            makedirs(output_dir)
        output_path = join(output_dir, title + "_events.pdf")

        # Setup plot
        fig = plt.figure(figsize=(10, 10))
        ax_camera = fig.add_subplot(1, 1, 1)
        fig.patch.set_visible(False)
        ax_camera.axis('off')
        camera = CameraDisplay(geom,
                               ax=ax_camera,
                               image=np.zeros(2048),
                               cmap='viridis')
        camera.add_colorbar()
        cb = camera.colorbar
        camera.colorbar.set_label("Amplitude (p.e.)")
        fig.suptitle(title)

        source = self.reader.read()
        desc = "Looping through file"
        with PdfPages(output_path) as pdf:
            for event in tqdm(source, desc=desc):
                ev = event.count
                event_id = event.r0.event_id
                self.r1.calibrate(event)
                self.dl0.reduce(event)
                self.dl1.calibrate(event)
                for t in event.r0.tels_with_data:
                    dl1 = event.dl1.tel[t].image[0]

                    # Cleaning
                    tc = tailcuts_clean(geom, dl1, 20, 10)
                    if not tc.any():
                        continue
                    cleaned_dl1 = np.ma.masked_array(dl1, mask=~tc)

                    try:
                        # hillas = hillas_parameters(*pos, cleaned_tc)
                        hillas = hillas_parameters_4(*pos, cleaned_dl1)
                    except HillasParameterizationError:
                        continue

                    ax_camera.cla()
                    camera = CameraDisplay(geom,
                                           ax=ax_camera,
                                           image=np.zeros(2048),
                                           cmap='viridis')
                    camera.colorbar = cb
                    camera.image = dl1
                    max_ = cleaned_dl1.max()  # np.percentile(dl1, 99.9)
                    min_ = np.percentile(dl1, 0.1)
                    camera.set_limits_minmax(min_, max_)
                    camera.highlight_pixels(tc, 'white')
                    camera.overlay_moments(hillas, color='red')
                    camera.update(True)
                    ax_camera.set_title("Event: {}".format(event_id))
                    ax_camera.axis('off')

                    pdf.savefig(fig)

        self.log.info("Created images: {}".format(output_path))
Example #20
0
def plot_all(ped_data, ff_data, calib_data, run=0, plot_file="none"):
    """
     plot camera calibration quantities

     Parameters
     ----------
     ped_data:   pedestal container PedestalContainer()

     ff_data:    flat-field container FlatFieldContainer()

     calib_data: calibration container WaveformCalibrationContainer()

     """
    camera = CameraGeometry.from_name("LSTCam", 2)

    # plot open pdf
    if plot_file != "none":
        pp = PdfPages(plot_file)

    plt.rc('font', size=15)

    ### first figure
    fig = plt.figure(1, figsize=(12, 24))
    plt.tight_layout()
    fig.suptitle(f"Run {run}", fontsize=25)
    pad = 420
    image = ff_data.charge_median
    mask = ff_data.charge_median_outliers
    for chan in (np.arange(2)):
        pad += 1
        plt.subplot(pad)
        plt.tight_layout()
        disp = CameraDisplay(camera)
        mymin = np.median(image[chan]) - 2 * np.std(image[chan])
        mymax = np.median(image[chan]) + 2 * np.std(image[chan])
        disp.set_limits_minmax(mymin, mymax)
        disp.highlight_pixels(mask[chan], linewidth=2)
        disp.image = image[chan]
        disp.cmap = plt.cm.coolwarm
        #disp.axes.text(lposx, 0, f'{channel[chan]} signal charge (ADC)', rotation=90)
        plt.title(f'{channel[chan]} signal charge [ADC]')
        disp.add_colorbar()

    image = ff_data.charge_std
    mask = ff_data.charge_std_outliers
    for chan in (np.arange(2)):
        pad += 1
        plt.subplot(pad)
        plt.tight_layout()
        disp = CameraDisplay(camera)
        mymin = np.median(image[chan]) - 2 * np.std(image[chan])
        mymax = np.median(image[chan]) + 2 * np.std(image[chan])
        disp.set_limits_minmax(mymin, mymax)
        disp.highlight_pixels(mask[chan], linewidth=2)
        disp.image = image[chan]
        disp.cmap = plt.cm.coolwarm
        #disp.axes.text(lposx, 0, f'{channel[chan]} signal std [ADC]', rotation=90)
        plt.title(f'{channel[chan]} signal std [ADC]')
        disp.add_colorbar()

    image = ped_data.charge_median
    mask = ped_data.charge_median_outliers
    for chan in (np.arange(2)):
        pad += 1
        plt.subplot(pad)
        plt.tight_layout()
        disp = CameraDisplay(camera)
        mymin = np.median(image[chan]) - 2 * np.std(image[chan])
        mymax = np.median(image[chan]) + 2 * np.std(image[chan])
        disp.set_limits_minmax(mymin, mymax)
        disp.highlight_pixels(mask[chan], linewidth=2)
        disp.image = image[chan]
        disp.cmap = plt.cm.coolwarm
        #disp.axes.text(lposx, 0, f'{channel[chan]} pedestal [ADC]', rotation=90)
        plt.title(f'{channel[chan]} pedestal [ADC]')
        disp.add_colorbar()

    image = ped_data.charge_std
    mask = ped_data.charge_std_outliers
    for chan in (np.arange(2)):
        pad += 1
        plt.subplot(pad)
        plt.tight_layout()
        disp = CameraDisplay(camera)
        mymin = np.median(image[chan]) - 2 * np.std(image[chan])
        mymax = np.median(image[chan]) + 2 * np.std(image[chan])
        disp.set_limits_minmax(mymin, mymax)
        disp.highlight_pixels(mask[chan], linewidth=2)
        disp.image = image[chan]
        disp.cmap = plt.cm.coolwarm
        #disp.axes.text(lposx, 0, f'{channel[chan]} pedestal std [ADC]', rotation=90)
        plt.title(f'{channel[chan]} pedestal std [ADC]')
        disp.add_colorbar()

    plt.subplots_adjust(top=0.92)

    if plot_file != "none":
        pp.savefig()

    ### second figure
    fig = plt.figure(2, figsize=(12, 24))
    plt.tight_layout()
    fig.suptitle(f"Run {run}", fontsize=25)
    pad = 420

    # time
    image = ff_data.time_median
    mask = ff_data.time_median_outliers
    for chan in (np.arange(2)):
        pad += 1
        plt.subplot(pad)
        plt.tight_layout()
        disp = CameraDisplay(camera)
        disp.highlight_pixels(mask[chan], linewidth=2)
        disp.image = image[chan]
        disp.cmap = plt.cm.coolwarm
        #disp.axes.text(lposx, 0, f'{channel[chan]} time', rotation=90)
        plt.title(f'{channel[chan]} time')
        disp.add_colorbar()

    image = ff_data.relative_gain_median
    mask = calib_data.unusable_pixels
    for chan in (np.arange(2)):
        pad += 1
        plt.subplot(pad)
        plt.tight_layout()
        disp = CameraDisplay(camera)
        disp.highlight_pixels(mask[chan], linewidth=2)
        mymin = np.median(image[chan]) - 2 * np.std(image[chan])
        mymax = np.median(image[chan]) + 2 * np.std(image[chan])
        disp.set_limits_minmax(mymin, mymax)
        disp.image = image[chan]
        disp.cmap = plt.cm.coolwarm
        disp.set_limits_minmax(0.7, 1.3)
        plt.title(f'{channel[chan]} relative gain')
        #disp.axes.text(lposx, 0, f'{channel[chan]} relative gain', rotation=90)
        disp.add_colorbar()

    # pe
    image = calib_data.n_pe
    mask = calib_data.unusable_pixels
    image = np.where(np.isnan(image), 0, image)
    for chan in (np.arange(2)):
        pad += 1
        plt.subplot(pad)
        plt.tight_layout()
        disp = CameraDisplay(camera)
        disp.highlight_pixels(mask[chan], linewidth=2)
        disp.image = image[chan]
        mymin = np.median(image[chan]) - 2 * np.std(image[chan])
        mymax = np.median(image[chan]) + 2 * np.std(image[chan])
        disp.set_limits_minmax(mymin, mymax)
        disp.cmap = plt.cm.coolwarm
        plt.title(f'{channel[chan]} photon-electrons')
        #disp.axes.text(lposx, 0, f'{channel[chan]} photon-electrons', rotation=90)
        disp.add_colorbar()

    # pe histogram
    pad += 1
    plt.subplot(pad)
    plt.tight_layout()
    for chan in np.arange(2):
        n_pe = calib_data.n_pe[chan]
        # select good pixels
        select = np.logical_not(mask[chan])
        median = int(np.median(n_pe[select]))
        rms = np.std(n_pe[select])
        mymin = median - 4 * rms
        mymax = median + 4 * rms
        label = f"{channel[chan]} Median {median:3.2f}, std {rms:5.2f}"
        plt.hist(n_pe[select],
                 label=label,
                 histtype='step',
                 range=(mymin, mymax),
                 bins=50,
                 stacked=True,
                 alpha=0.5,
                 fill=True)
        plt.legend()
    plt.xlabel(f'pe', fontsize=20)
    plt.ylabel('pixels', fontsize=20)

    # pe scatter plot
    pad += 1
    plt.subplot(pad)
    plt.tight_layout()
    HG = calib_data.n_pe[0]
    LG = calib_data.n_pe[1]
    HG = np.where(np.isnan(HG), 0, HG)
    LG = np.where(np.isnan(LG), 0, LG)
    mymin = np.median(LG) - 2 * np.std(LG)
    mymax = np.median(LG) + 2 * np.std(LG)
    plt.hist2d(LG, HG, bins=[100, 100])
    plt.xlabel("LG", fontsize=20)
    plt.ylabel("HG", fontsize=20)

    x = np.arange(mymin, mymax)
    plt.plot(x, x)
    plt.ylim(mymin, mymax)
    plt.xlim(mymin, mymax)
    plt.subplots_adjust(top=0.92)
    if plot_file != "none":
        pp.savefig()

    ### figures 3 and 4 : histograms
    for chan in np.arange(2):
        n_pe = calib_data.n_pe[chan]

        gain_median = ff_data.relative_gain_median[chan]
        #charge_median = ff_data.charge_median[chan]
        charge_mean = ff_data.charge_mean[chan]
        charge_std = ff_data.charge_std[chan]
        #median_ped = ped_data.charge_median[chan]
        mean_ped = ped_data.charge_mean[chan]
        ped_std = ped_data.charge_std[chan]

        # select good pixels
        select = np.logical_not(mask[chan])
        fig = plt.figure(chan + 10, figsize=(12, 18))
        fig.tight_layout(rect=[0, 0.03, 1, 0.95])

        fig.suptitle(f"Run {run} channel: {channel[chan]}", fontsize=25)

        # charge
        plt.subplot(321)
        plt.tight_layout()
        median = int(np.median(charge_mean[select]))
        rms = np.std(charge_mean[select])
        label = f"Median {median:3.2f}, std {rms:5.0f}"
        plt.xlabel('charge (ADC)', fontsize=20)
        plt.ylabel('pixels', fontsize=20)
        plt.hist(charge_mean[select], bins=50, label=label)
        plt.legend()

        plt.subplot(322)
        plt.tight_layout()
        plt.ylabel('pixels', fontsize=20)
        plt.xlabel('charge std', fontsize=20)
        median = np.median(charge_std[select])
        rms = np.std(charge_std[select])
        label = f"Median {median:3.2f}, std {rms:3.2f}"
        plt.hist(charge_std[select], bins=50, label=label)
        plt.legend()

        # pedestal charge
        plt.subplot(323)
        plt.tight_layout()
        plt.ylabel('pixels', fontsize=20)
        plt.xlabel('pedestal', fontsize=20)
        median = np.median(mean_ped[select])
        rms = np.std(mean_ped[select])
        label = f"Median {median:3.2f}, std {rms:3.2f}"
        plt.hist(mean_ped[select], bins=50, label=label)
        plt.legend()

        # pedestal std
        plt.subplot(324)
        plt.ylabel('pixels', fontsize=20)
        plt.xlabel('pedestal std', fontsize=20)
        median = np.median(ped_std[select])
        rms = np.std(ped_std[select])
        label = f"Median {median:3.2f}, std {rms:3.2f}"
        plt.hist(ped_std[select], bins=50, label=label)
        plt.legend()

        # relative gain
        plt.subplot(325)
        plt.tight_layout()
        plt.ylabel('pixels', fontsize=20)
        plt.xlabel('relative gain', fontsize=20)
        median = np.median(gain_median[select])
        rms = np.std(gain_median[select])
        label = f"Relative gain {median:3.2f}, std {rms:5.2f}"
        plt.hist(gain_median[select], bins=50, label=label)
        plt.legend()

        # photon electrons
        plt.subplot(326)
        plt.tight_layout()
        plt.ylabel('pixels', fontsize=20)
        plt.xlabel('pe', fontsize=20)
        median = np.median(n_pe[select])
        rms = np.std(n_pe[select])
        label = f"Median {median:3.2f}, std {rms:3.2f}"
        plt.hist(n_pe[select], bins=50, label=label)
        plt.legend()
        plt.subplots_adjust(top=0.92)
        if plot_file != "none":
            pp.savefig(plt.gcf())

    if plot_file != "none":
        pp.close()
Example #21
0
    def plot(self, waveforms, geom, event_id, output_dir):
        camera = CameraDisplay(geom,
                               ax=self.camera,
                               image=np.zeros(2048),
                               cmap='viridis')
        camera.add_colorbar()
        max_ = np.percentile(waveforms[:, self.start:self.end].max(), 60)
        camera.set_limits_minmax(0, max_)

        self.ax1.plot(waveforms[self.p1, :])
        self.ax2.plot(waveforms[self.p2, :])

        self.fig.suptitle("Event {}".format(event_id))
        self.ax1.set_title("Pixel: {}".format(self.p1))
        self.ax1.set_xlabel("Time (ns)")
        self.ax1.set_ylabel("Amplitude (p.e.)")
        self.ax2.set_title("Pixel: {}".format(self.p2))
        self.ax2.set_xlabel("Time (ns)")
        self.ax2.set_ylabel("Amplitude (p.e.)")
        camera.colorbar.set_label("Amplitude (p.e.)")

        line1, = self.ax1.plot([0, 0], self.ax1.get_ylim(), color='r', alpha=1)
        line2, = self.ax2.plot([0, 0], self.ax2.get_ylim(), color='r', alpha=1)

        self.camera.annotate("Pixel: {}".format(self.p1),
                             xy=(geom.pix_x.value[self.p1],
                                 geom.pix_y.value[self.p1]),
                             xycoords='data',
                             xytext=(0.05, 0.98),
                             textcoords='axes fraction',
                             arrowprops=dict(facecolor='red',
                                             width=2,
                                             alpha=0.4),
                             horizontalalignment='left',
                             verticalalignment='top')
        self.camera.annotate("Pixel: {}".format(self.p2),
                             xy=(geom.pix_x.value[self.p2],
                                 geom.pix_y.value[self.p2]),
                             xycoords='data',
                             xytext=(0.05, 0.94),
                             textcoords='axes fraction',
                             arrowprops=dict(facecolor='orange',
                                             width=2,
                                             alpha=0.4),
                             horizontalalignment='left',
                             verticalalignment='top')

        # Create animation
        div = 5
        increment = 1 / div
        n_frames = int((self.end - self.start) / increment)
        interval = int(500 * increment)

        # Prepare Output
        output_path = join(output_dir, "animation_e{}.gif".format(event_id))
        if not exists(output_dir):
            self.log.info("Creating directory: {}".format(output_dir))
            makedirs(output_dir)
        self.log.info("Output: {}".format(output_path))

        with tqdm(total=n_frames, desc="Creating animation") as pbar:

            def animate(i):
                pbar.update(1)
                t = self.start + (i / div)
                camera.image = waveforms[:, int(t)]
                line1.set_xdata(t)
                line2.set_xdata(t)

            anim = animation.FuncAnimation(self.fig,
                                           animate,
                                           frames=n_frames,
                                           interval=interval)
            anim.save(output_path, writer='imagemagick')

        self.log.info("Created animation: {}".format(output_path))