示例#1
0
def create_sample_image(
        psi='-30d',
        x=0.2 * u.m,
        y=0.3 * u.m,
        width=0.05 * u.m,
        length=0.15 * u.m,
        intensity=1500
):
    seed(10)

    geom = CameraGeometry.from_name('LSTCam')

    # make a toymodel shower model
    model = toymodel.Gaussian(x=x, y=y, width=width, length=length, psi=psi)

    # generate toymodel image in camera for this shower model.
    image, _, _ = model.generate_image(
        geom,
        intensity=1500,
        nsb_level_pe=3,
    )

    # calculate pixels likely containing signal
    clean_mask = tailcuts_clean(geom, image, 10, 5)

    return geom, image, clean_mask
示例#2
0
def create_sample_image(
    psi="-30d",
    x=0.2 * u.m,
    y=0.3 * u.m,
    width=0.05 * u.m,
    length=0.15 * u.m,
    intensity=1500,
):

    geom = CameraGeometry.from_name("LSTCam")

    # make a toymodel shower model
    model = toymodel.Gaussian(x=x, y=y, width=width, length=length, psi=psi)

    # generate toymodel image in camera for this shower model.
    rng = np.random.default_rng(0)
    image, _, _ = model.generate_image(geom,
                                       intensity=1500,
                                       nsb_level_pe=3,
                                       rng=rng)

    # calculate pixels likely containing signal
    clean_mask = tailcuts_clean(geom, image, 10, 5)

    return geom, image, clean_mask
示例#3
0
def test_intensity(seed, monkeypatch):
    """
    Test generation of the toymodel roughly follows the given intensity.

    Tests once with passing a custom rng instance, once with relying on the
    modules rng.
    """
    from ctapipe.image import toymodel

    geom = CameraGeometry.from_name("LSTCam")

    x, y = u.Quantity([0.2, 0.3], u.m)
    width = 0.05 * u.m
    length = 0.15 * u.m
    intensity = 200
    psi = "30d"

    # make sure we set a fixed seed for this test even when testing the
    # API without giving the rng
    monkeypatch.setattr(toymodel, "TOYMODEL_RNG", np.random.default_rng(0))

    # make a toymodel shower model
    model = toymodel.Gaussian(x=x, y=y, width=width, length=length, psi=psi)

    if seed is None:
        _, signal, _ = model.generate_image(geom,
                                            intensity=intensity,
                                            nsb_level_pe=5)
    else:
        rng = np.random.default_rng(seed)
        _, signal, _ = model.generate_image(geom,
                                            intensity=intensity,
                                            nsb_level_pe=5,
                                            rng=rng)

    # test if signal reproduces given cog values
    assert np.average(geom.pix_x.to_value(u.m),
                      weights=signal) == approx(0.2, rel=0.15)
    assert np.average(geom.pix_y.to_value(u.m),
                      weights=signal) == approx(0.3, rel=0.15)

    # test if signal reproduces given width/length values
    cov = np.cov(geom.pix_x.value, geom.pix_y.value, aweights=signal)
    eigvals, _ = np.linalg.eigh(cov)

    assert np.sqrt(eigvals[0]) == approx(width.to_value(u.m), rel=0.15)
    assert np.sqrt(eigvals[1]) == approx(length.to_value(u.m), rel=0.15)

    # test if total intensity is inside in 99 percent confidence interval
    assert poisson(intensity).ppf(0.05) <= signal.sum() <= poisson(
        intensity).ppf(0.95)
示例#4
0
def test_with_toy():
    np.random.seed(42)

    geom = CameraGeometry.from_name("LSTCam")

    width = 0.03 * u.m
    length = 0.15 * u.m
    width_uncertainty = 0.00094 * u.m
    length_uncertainty = 0.00465 * u.m
    intensity = 500

    xs = u.Quantity([0.5, 0.5, -0.5, -0.5], u.m)
    ys = u.Quantity([0.5, -0.5, 0.5, -0.5], u.m)
    psis = Angle([-90, -45, 0, 45, 90], unit="deg")

    for x, y in zip(xs, ys):
        for psi in psis:

            # make a toymodel shower model
            model = toymodel.Gaussian(
                x=x,
                y=y,
                width=width,
                length=length,
                psi=psi,
            )

            image, signal, noise = model.generate_image(
                geom,
                intensity=intensity,
                nsb_level_pe=5,
            )

            result = hillas_parameters(geom, signal)

            assert u.isclose(result.x, x, rtol=0.1)
            assert u.isclose(result.y, y, rtol=0.1)

            assert u.isclose(result.width, width, rtol=0.1)
            assert u.isclose(result.width_uncertainty,
                             width_uncertainty,
                             rtol=0.4)
            assert u.isclose(result.length, length, rtol=0.1)
            assert u.isclose(result.length_uncertainty,
                             length_uncertainty,
                             rtol=0.4)
            assert (result.psi.to_value(u.deg) == approx(
                psi.deg, abs=2)) or abs(result.psi.to_value(u.deg) -
                                        psi.deg) == approx(180.0, abs=2)

            assert signal.sum() == result.intensity
示例#5
0
def draw_several_cams(geom, ncams=4):

    cmaps = ["jet", "afmhot", "terrain", "autumn"]
    fig, axs = plt.subplots(
        1,
        ncams,
        figsize=(15, 4),
    )

    for ii in range(ncams):
        disp = CameraDisplay(
            geom,
            ax=axs[ii],
            title="CT{}".format(ii + 1),
        )
        disp.cmap = cmaps[ii]

        model = toymodel.Gaussian(
            x=(0.2 - ii * 0.1) * u.m,
            y=(-ii * 0.05) * u.m,
            width=(0.05 + 0.001 * ii) * u.m,
            length=(0.15 + 0.05 * ii) * u.m,
            psi=ii * 20 * u.deg,
        )

        image, _, _ = model.generate_image(
            geom,
            intensity=1500,
            nsb_level_pe=5,
        )

        mask = tailcuts_clean(
            geom,
            image,
            picture_thresh=6 * image.mean(),
            boundary_thresh=4 * image.mean(),
        )
        cleaned = image.copy()
        cleaned[~mask] = 0

        hillas = hillas_parameters(geom, cleaned)

        disp.image = image
        disp.add_colorbar(ax=axs[ii])

        disp.set_limits_percent(95)
        disp.overlay_moments(hillas, linewidth=3, color="blue")
示例#6
0
    def update(frame):
        x, y = np.random.uniform(-fov, fov, size=2)
        width = np.random.uniform(0.01, maxwid)
        length = np.random.uniform(width, maxlen)
        angle = np.random.uniform(0, 180)
        intens = width * length * (5e4 + 1e5 * np.random.exponential(2))

        model = toymodel.Gaussian(
            x=x * u.m,
            y=y * u.m,
            width=width * u.m,
            length=length * u.m,
            psi=angle * u.deg,
        )
        image, _, _ = model.generate_image(
            geom,
            intensity=intens,
            nsb_level_pe=5,
        )
        disp.image = image
示例#7
0
from ctapipe.image import toymodel, hillas_parameters, tailcuts_clean
from ctapipe.instrument import CameraGeometry
from ctapipe.visualization import CameraDisplay


if __name__ == "__main__":

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

    # Create a fake camera image to display:
    model = toymodel.Gaussian(
        x=0.2 * u.m, y=0.0 * u.m, width=0.05 * u.m, length=0.15 * u.m, psi="35d"
    )

    image, sig, bg = model.generate_image(geom, intensity=1500, nsb_level_pe=2)

    # Apply image cleaning
    cleanmask = tailcuts_clean(geom, image, picture_thresh=10, boundary_thresh=5)
    clean = image.copy()
    clean[~cleanmask] = 0.0

    # Calculate image parameters
    hillas = hillas_parameters(geom, clean)
    print(hillas)

    # Show the camera image and overlay Hillas ellipse and clean pixels
    disp.image = image
示例#8
0
        def update(frame):
            x, y = np.random.uniform(-fov, fov, size=2) * scale
            width = np.random.uniform(0, maxwid - minwid) * scale + minwid
            length = np.random.uniform(0, maxlen) * scale + width
            angle = np.random.uniform(0, 360)
            intens = np.random.exponential(2) * 500
            model = toymodel.Gaussian(
                x=x * u.m,
                y=y * u.m,
                width=width * u.m,
                length=length * u.m,
                psi=angle * u.deg,
            )
            self.log.debug(
                "Frame=%d width=%03f length=%03f intens=%03d",
                frame, width, length, intens
            )

            image, _, _ = model.generate_image(
                geom,
                intensity=intens,
                nsb_level_pe=3,
            )

            # alternate between cleaned and raw images
            if self._counter == self.cleanframes:
                plt.suptitle("Image Cleaning ON")
                self.imclean = True
            if self._counter == self.cleanframes * 2:
                plt.suptitle("Image Cleaning OFF")
                self.imclean = False
                self._counter = 0
                disp.clear_overlays()

            if self.imclean:
                cleanmask = tailcuts_clean(geom, image,
                                           picture_thresh=10.0,
                                           boundary_thresh=5.0)
                for ii in range(2):
                    dilate(geom, cleanmask)
                image[cleanmask == 0] = 0  # zero noise pixels
                try:
                    hillas = hillas_parameters(geom, image)
                    disp.overlay_moments(hillas, with_label=False,
                                         color='red', alpha=0.7,
                                         linewidth=2, linestyle='dashed')
                except HillasParameterizationError:
                    disp.clear_overlays()
                    pass

            self.log.debug("Frame=%d  image_sum=%.3f max=%.3f",
                           self._counter, image.sum(), image.max())
            disp.image = image

            if self.autoscale:
                disp.set_limits_percent(95)
            else:
                disp.set_limits_minmax(-5, 200)

            disp.axes.figure.canvas.draw()
            self._counter += 1
            return [ax, ]
camgeoms = ('HESS-I', 'HESS-II', 'VERITAS', 'Whipple109', 'Whipple151')

camgeoms_len = len(camgeoms)

for camgeom_index, camgeom in enumerate(camgeoms):
    print(
        f'> ({camgeom_index + 1:{len(str(camgeoms_len))}}/{camgeoms_len}) camgeom={camgeom}'
    )

    geom = CameraGeometry.from_name(camgeom)

    image = np.zeros(geom.n_pixels)

    for i in range(5):
        model = toymodel.Gaussian(x=np.random.uniform(-0.8, 0.8) * u.m,
                                  y=np.random.uniform(-0.8, 0.8) * u.m,
                                  width=np.random.uniform(0.05, 0.075) * u.m,
                                  length=np.random.uniform(0.1, 0.15) * u.m,
                                  psi=np.random.uniform(0, 2 * np.pi) * u.rad)

        new_image, sig, bg = model.generate_image(geom,
                                                  intensity=np.random.uniform(
                                                      1000, 3000),
                                                  nsb_level_pe=5)

        image += new_image

    disp = CameraDisplay(geom, image=image)
    plt.show(disp)
示例#10
0
def test_reconstruction_in_telescope_frame():
    """
    Compare the reconstruction in the telescope
    and camera frame.
    """
    np.random.seed(42)

    telescope_frame = TelescopeFrame()
    camera_frame = CameraFrame(focal_length=28 * u.m)

    geom = CameraGeometry.from_name("LSTCam")
    geom.frame = camera_frame
    geom_nom = geom.transform_to(telescope_frame)

    width = 0.03 * u.m
    length = 0.15 * u.m
    intensity = 500

    xs = u.Quantity([0.5, 0.5, -0.5, -0.5], u.m)
    ys = u.Quantity([0.5, -0.5, 0.5, -0.5], u.m)
    psis = Angle([-90, -45, 0, 45, 90], unit="deg")

    def distance(coord):
        return np.sqrt(np.diff(coord.x)**2 + np.diff(coord.y)**2) / 2

    def get_transformed_length(telescope_hillas, telescope_frame,
                               camera_frame):
        main_edges = u.Quantity(
            [-telescope_hillas.length, telescope_hillas.length])
        main_lon = main_edges * np.cos(
            telescope_hillas.psi) + telescope_hillas.fov_lon
        main_lat = main_edges * np.sin(
            telescope_hillas.psi) + telescope_hillas.fov_lat
        cam_main_axis = SkyCoord(
            fov_lon=main_lon, fov_lat=main_lat,
            frame=telescope_frame).transform_to(camera_frame)
        transformed_length = distance(cam_main_axis)
        return transformed_length

    def get_transformed_width(telescope_hillas, telescope_frame, camera_frame):
        secondary_edges = u.Quantity(
            [-telescope_hillas.width, telescope_hillas.width])
        secondary_lon = (secondary_edges * np.cos(telescope_hillas.psi) +
                         telescope_result.fov_lon)
        secondary_lat = (secondary_edges * np.sin(telescope_hillas.psi) +
                         telescope_result.fov_lat)
        cam_secondary_edges = SkyCoord(
            fov_lon=secondary_lon,
            fov_lat=secondary_lat,
            frame=telescope_frame).transform_to(camera_frame)
        transformed_width = distance(cam_secondary_edges)
        return transformed_width

    for x, y in zip(xs, ys):
        for psi in psis:
            # generate a toy image
            model = toymodel.Gaussian(x=x,
                                      y=y,
                                      width=width,
                                      length=length,
                                      psi=psi)
            image, signal, noise = model.generate_image(geom,
                                                        intensity=intensity,
                                                        nsb_level_pe=5)

            telescope_result = hillas_parameters(geom_nom, signal)
            camera_result = hillas_parameters(geom, signal)
            assert camera_result.intensity == telescope_result.intensity

            # Compare results in both frames
            transformed_cog = SkyCoord(
                fov_lon=telescope_result.fov_lon,
                fov_lat=telescope_result.fov_lat,
                frame=telescope_frame,
            ).transform_to(camera_frame)
            assert u.isclose(transformed_cog.x, camera_result.x, rtol=0.01)
            assert u.isclose(transformed_cog.y, camera_result.y, rtol=0.01)

            transformed_length = get_transformed_length(
                telescope_result, telescope_frame, camera_frame)
            assert u.isclose(transformed_length,
                             camera_result.length,
                             rtol=0.01)

            transformed_width = get_transformed_width(telescope_result,
                                                      telescope_frame,
                                                      camera_frame)
            assert u.isclose(transformed_width, camera_result.width, rtol=0.01)
示例#11
0
from ctapipe.image import toymodel
from ctapipe.instrument import CameraGeometry
from ctapipe.visualization import CameraDisplay

if __name__ == '__main__':

    plt.style.use('ggplot')

    fig = plt.figure(figsize=(12, 8))
    ax = fig.add_subplot(1, 1, 1)

    geom = CameraGeometry.from_name('NectarCam')
    disp = CameraDisplay(geom, ax=ax)
    disp.add_colorbar()

    model = toymodel.Gaussian(x=0.05 * u.m,
                              y=0 * u.m,
                              width=0.05 * u.m,
                              length=0.15 * u.m,
                              psi='35d')

    image, sig, bg = model.generate_image(geom, intensity=1500, nsb_level_pe=5)

    disp.image = image

    mask = disp.image > 10
    disp.highlight_pixels(mask, linewidth=2, color='crimson')

    plt.show()
示例#12
0
def toymodel_event_source(geoms,
                          max_events=100,
                          single_tel=False,
                          n_channels=1,
                          n_samples=25,
                          p_trigger=0.3):
    """
    An event source that produces array
    Parameters
    ----------
    geoms : list of CameraGeometry instances
        Geometries for the telescopes to simulate
    max_events : int, default: 100
        maximum number of events to create
    n_channels : int
        how many channels per telescope
    n_samples : int
        how many adc samples per pixel
    p_trigger : float
        mean trigger probability for the telescopes
    """
    n_telescopes = len(geoms)
    container = DataContainer()
    container.meta['toymodel__max_events'] = max_events
    container.meta['source'] = "toymodel"
    tel_ids = np.arange(n_telescopes)

    for event_id in range(max_events):

        n_triggered = np.random.poisson(n_telescopes * 0.3)
        if n_triggered > n_telescopes:
            n_triggered = n_telescopes

        triggered_tels = np.random.choice(tel_ids, n_triggered, replace=False)

        container.r0.event_id = event_id
        container.r0.tels_with_data = triggered_tels
        container.count = event_id

        # handle single-telescope case (ignore others:
        if single_tel:
            if single_tel not in container.r0.tels_with_data:
                continue
            container.r0.tels_with_data = [
                single_tel,
            ]

        container.r0.tel.reset()  # clear the previous telescopes
        t = np.arange(n_samples)

        for tel_id in container.r0.tels_with_data:
            geom = geoms[tel_id]

            # fill pixel position dictionary, if not already done:
            if tel_id not in container.inst.pixel_pos:
                container.inst.pixel_pos[tel_id] = (
                    geom.pix_x.value,
                    geom.pix_y.value,
                )

            x, y = np.random.uniform(geom.pix_x.min(), geom.pix_y.max(), 2)
            length = np.random.uniform(0.02, 0.2)
            width = np.random.uniform(0.01, length)
            psi = np.random.randint(0, 360)
            intensity = np.random.poisson(int(10000 * width * length))
            model = toymodel.Gaussian(
                x=x * u.m,
                y=y * u.m,
                length=length * u.m,
                width=width * u.m,
                psi=f'{psi}d',
            )
            image, _, _ = model.generate_image(
                geom,
                intensity,
            )

            # container.r0.tel[tel_id] = R0CameraContainer()
            container.inst.num_channels[tel_id] = n_channels
            n_pix = len(geom.pix_id)
            means = np.random.normal(15, 1, (n_pix, 1))
            stds = np.random.uniform(3, 6, (n_pix, 1))
            samples = image[:, np.newaxis] * norm.pdf(t, means, stds)

            for chan in range(n_channels):
                container.r0.tel[tel_id].waveform[chan] = samples
                container.r0.tel[tel_id].image[chan] = image

        yield container