Ejemplo n.º 1
0
    def get_prediction(self, tel_id, shower_reco, energy_reco):

        horizon_seed = HorizonFrame(az=shower_reco.az, alt=shower_reco.alt)
        nominal_seed = horizon_seed.transform_to(
            NominalFrame(array_direction=horizon_seed))
        source_x = nominal_seed.x.to(u.rad).value
        source_y = nominal_seed.y.to(u.rad).value

        ground = GroundFrame(x=shower_reco.core_x,
                             y=shower_reco.core_y,
                             z=0 * u.m)
        tilted = ground.transform_to(
            TiltedGroundFrame(pointing_direction=self.array_direction))
        tilt_x = tilted.x.to(u.m).value
        tilt_y = tilted.y.to(u.m).value

        zenith = 90 * u.deg - self.array_direction.alt

        x_max = shower_reco.h_max / np.cos(zenith)

        # Calculate expected Xmax given this energy
        x_max_exp = guess_shower_depth(energy_reco.energy)

        # Convert to binning of Xmax, addition of 100 can probably be removed
        x_max_bin = x_max - x_max_exp

        # Check for range
        if x_max_bin > 250 * (u.g * u.cm**-2):
            x_max_bin = 250 * (u.g * u.cm**-2)
        if x_max_bin < -250 * (u.g * u.cm**-2):
            x_max_bin = -250 * (u.g * u.cm**-2)

        x_max_bin = x_max_bin.value

        impact = np.sqrt(
            pow(self.tel_pos_x[tel_id] - tilt_x, 2) +
            pow(self.tel_pos_y[tel_id] - tilt_y, 2))

        phi = np.arctan2((self.tel_pos_y[tel_id] - tilt_y),
                         (self.tel_pos_x[tel_id] - tilt_x))

        pix_x_rot, pix_y_rot = self.rotate_translate(self.pixel_x[tel_id] * -1,
                                                     self.pixel_y[tel_id],
                                                     source_x, source_y, phi)

        prediction = self.image_prediction(self.type[tel_id],
                                           (90 * u.deg) - shower_reco.alt,
                                           shower_reco.az,
                                           energy_reco.energy.value, impact,
                                           x_max_bin,
                                           pix_x_rot * (180 / math.pi),
                                           pix_y_rot * (180 / math.pi))

        prediction *= self.scale[self.type[tel_id]]
        # prediction *= self.pixel_area[tel_id]

        prediction[prediction < 0] = 0
        prediction[np.isnan(prediction)] = 0

        return prediction
Ejemplo n.º 2
0
def sky_to_camera(alt, az, focal, pointing_alt, pointing_az):
    """
    Coordinate transform from aky position (alt, az) (in angles) to camera coordinates (x, y) in distance
    Parameters
    ----------
    alt: astropy Quantity
    az: astropy Quantity
    focal: astropy Quantity
    pointing_alt: pointing altitude in angle unit
    pointing_az: pointing altitude in angle unit

    Returns
    -------

    """
    pointing_direction = HorizonFrame(alt=pointing_alt, az=pointing_az)

    event_direction = HorizonFrame(alt=alt, az=az)
    nom_frame = NominalFrame(array_direction=pointing_direction,
                             pointing_direction=pointing_direction)

    event_dir_nom = event_direction.transform_to(nom_frame)

    camera_pos = NominalFrame(
        pointing_direction=pointing_direction,
        x=event_dir_nom.x.to(u.rad).value * focal,
        y=event_dir_nom.y.to(u.rad).value * focal,
    )

    # return focal * (event_dir_nom.x.to(u.rad).value, event_dir_nom.y.to(u.rad).value)
    return camera_pos
Ejemplo n.º 3
0
    def get_position_in_cam(dir_alt, dir_az, event, tel_id):
        """
        transform position in HorizonFrame to CameraFrame

        Parameters
        ----------
        dir_alt : direction altitude
        dir_az : direction azimuth
        event : event data container
        tel_id : telescope ID

        Returns
        -------
        cam_coord : position in camera of telescope tel_id
        """

        # pointing direction of telescope
        pointing_az = event.mc.tel[tel_id].azimuth_raw * u.rad
        pointing_alt = event.mc.tel[tel_id].altitude_raw * u.rad

        pointing = SkyCoord(alt=pointing_alt, az=pointing_az, frame='altaz')

        focal_length = event.inst.subarray.tel[tel_id].\
            optics.equivalent_focal_length

        cf = CameraFrame(focal_length=focal_length,
                         array_direction=pointing,
                         pointing_direction=pointing)

        # direction of event
        direction = HorizonFrame(alt=dir_alt, az=dir_az)
        cam_coord = direction.transform_to(cf)

        return cam_coord
Ejemplo n.º 4
0
    def get_prediction(self, tel_id, shower_reco, energy_reco):

        horizon_seed = HorizonFrame(az=shower_reco.az, alt=shower_reco.alt)
        nominal_seed = horizon_seed.transform_to(
            NominalFrame(array_direction=horizon_seed))
        source_x = nominal_seed.x.to(u.rad).value
        source_y = nominal_seed.y.to(u.rad).value

        ground = GroundFrame(x=shower_reco.core_x, y=shower_reco.core_y, z=0*u.m)
        tilted = ground.transform_to(
            TiltedGroundFrame(pointing_direction=self.array_direction))
        tilt_x = tilted.x.to(u.m).value
        tilt_y = tilted.y.to(u.m).value

        zenith = 90*u.deg - self.array_direction.alt
        azimuth = self.array_direction.az

        x_max = shower_reco.h_max / np.cos(zenith)

        # Calculate expected Xmax given this energy
        x_max_exp = guess_shower_depth(energy_reco.energy)

        # Convert to binning of Xmax, addition of 100 can probably be removed
        x_max_bin = x_max - x_max_exp

        # Check for range
        if x_max_bin > 250 * (u.g*u.cm**-2):
            x_max_bin = 250 * (u.g*u.cm**-2)
        if x_max_bin < -250 * (u.g*u.cm**-2):
            x_max_bin = -250 * (u.g*u.cm**-2)

        x_max_bin = x_max_bin.value

        impact = np.sqrt(pow(self.tel_pos_x[tel_id] - tilt_x, 2) +
                         pow(self.tel_pos_y[tel_id] - tilt_y, 2))

        phi = np.arctan2( (self.tel_pos_y[tel_id] - tilt_y),
                          (self.tel_pos_x[tel_id] - tilt_x))

        pix_x_rot, pix_y_rot = self.rotate_translate(self.pixel_x[tel_id]
                                                     * -1,
                                                     self.pixel_y[tel_id],
                                                     source_x,
                                                     source_y, phi)

        prediction = self.image_prediction(self.type[tel_id],
                                           (90 * u.deg) - shower_reco.alt,
                                           shower_reco.az,
                                           energy_reco.energy.value,
                                           impact, x_max_bin,
                                           pix_x_rot * (180 / math.pi),
                                           pix_y_rot * (180 / math.pi))

        prediction *= self.scale[self.type[tel_id]]
        #prediction *= self.pixel_area[tel_id]

        prediction[prediction < 0] = 0
        prediction[np.isnan(prediction)] = 0

        return prediction
Ejemplo n.º 5
0
def test_ground_to_tilt():
    from ctapipe.coordinates import GroundFrame, TiltedGroundFrame, HorizonFrame

    # define ground coordinate
    grd_coord = GroundFrame(x=1 * u.m, y=2 * u.m, z=0 * u.m)
    pointing_direction = SkyCoord(alt=90 * u.deg,
                                  az=0 * u.deg,
                                  frame=HorizonFrame())

    # Convert to tilted frame at zenith (should be the same)
    tilt_coord = grd_coord.transform_to(
        TiltedGroundFrame(pointing_direction=pointing_direction))
    assert tilt_coord.separation_3d(grd_coord) == 0 * u.m

    # Check 180 degree rotation reverses y coordinate
    pointing_direction = SkyCoord(alt=90 * u.deg,
                                  az=180 * u.deg,
                                  frame=HorizonFrame())
    tilt_coord = grd_coord.transform_to(
        TiltedGroundFrame(pointing_direction=pointing_direction))
    assert np.abs(tilt_coord.y + 2. * u.m) < 1e-5 * u.m

    # Check that if we look at horizon the x coordinate is 0
    pointing_direction = SkyCoord(alt=0 * u.deg,
                                  az=0 * u.deg,
                                  frame=HorizonFrame())
    tilt_coord = grd_coord.transform_to(
        TiltedGroundFrame(pointing_direction=pointing_direction))
    assert np.abs(tilt_coord.x) < 1e-5 * u.m
Ejemplo n.º 6
0
    def draw_tilted_surface(self, shower_seed, energy_seed,
                            bins=50, core_range=100 * u.m):
        """
        Simple reconstruction for evaluating the likelihood in a grid across the 
        nominal system, fixing all values but the core position of the gamma rays. 
        Useful for checking the reconstruction performance of the algorithm
        
        Parameters
        ----------
        shower_seed: ReconstructedShowerContainer
            Best fit ImPACT shower geometry 
        energy_seed: ReconstructedEnergyContainer
            Best fit ImPACT energy
        bins: int
            Number of bins in surface evaluation
        nominal_range: Quantity
            Range over which to create likelihood surface

        Returns
        -------
        ndarray, ndarray, ndarray: 
        Bin centres in X and Y coordinates and the values of the likelihood at each 
        position
        """
        horizon_seed = HorizonFrame(az=shower_seed.az, alt=shower_seed.alt)
        nominal_seed = horizon_seed.transform_to(
            NominalFrame(array_direction=self.array_direction))

        source_x = nominal_seed.x[0].to(u.rad).value
        source_y = nominal_seed.y[0].to(u.rad).value

        ground = GroundFrame(x=shower_seed.core_x,
                             y=shower_seed.core_y, z=0 * u.m)
        tilted = ground.transform_to(
            TiltedGroundFrame(pointing_direction=self.array_direction)
        )
        tilt_x = tilted.x.to(u.m)
        tilt_y = tilted.y.to(u.m)

        x_ground_list = np.linspace(tilt_x - core_range, tilt_x + core_range, num=bins)
        y_ground_list = np.linspace(tilt_y - core_range, tilt_y + core_range, num=bins)
        w = np.zeros([bins, bins])
        zenith = 90*u.deg - self.array_direction.alt

        for xb in range(bins):
            for yb in range(bins):
                x_max_scale = shower_seed.h_max / \
                              self.get_shower_max(source_x,
                                                  source_y,
                                                  x_ground_list[xb].value,
                                                  y_ground_list[yb].value,
                                                  zenith.to(u.rad).value)

                w[xb][yb] =  self.get_likelihood(source_x,
                                                 source_y,
                                                 x_ground_list[xb].value,
                                                 y_ground_list[yb].value,
                                                 energy_seed.energy.value, x_max_scale)
        return x_ground_list, y_ground_list, w
Ejemplo n.º 7
0
def nominal_to_altaz():

    nom = SkyCoord(x=0 * u.deg,
                   y=0 * u.deg,
                   frame=NominalFrame(
                       origin=HorizonFrame(alt=75 * u.deg, az=180 * u.deg)))
    alt_az = nom.transform_to(HorizonFrame())
    print("HorizonCoordinate", alt_az)
Ejemplo n.º 8
0
    def get_prediction(self, tel_id, shower_reco, energy_reco):

        horizon_seed = HorizonFrame(az=shower_reco.az, alt=shower_reco.alt)
        nominal_seed = horizon_seed.transform_to(
            NominalFrame(array_direction=horizon_seed))
        source_x = nominal_seed.x.to(u.rad).value
        source_y = nominal_seed.y.to(u.rad).value

        print(self.array_direction[0])
        ground = GroundFrame(x=shower_reco.core_x,
                             y=shower_reco.core_y, z=0 * u.m)
        tilted = ground.transform_to(
            TiltedGroundFrame(
                pointing_direction=HorizonFrame(alt=self.array_direction[0],
                                                az=self.array_direction[1])
            )
        )
        tilt_x = tilted.x.to(u.m).value
        tilt_y = tilted.y.to(u.m).value

        zenith = 90 * u.deg - self.array_direction[0]
        azimuth = self.array_direction[1]

        x_max_exp = 300 + 93 * np.log10(energy_reco.energy.value)
        x_max = shower_reco.h_max / np.cos(zenith)

        # Convert to binning of Xmax, addition of 100 can probably be removed
        x_max_bin = x_max.value - x_max_exp
        if x_max_bin > 100:
            x_max_bin = 100
        if x_max_bin < -100:
            x_max_bin = -100

        impact = np.sqrt(pow(self.tel_pos_x[tel_id] - tilt_x, 2) +
                         pow(self.tel_pos_y[tel_id] - tilt_y, 2))

        phi = np.arctan2( (self.tel_pos_y[tel_id] - tilt_y),
                          (self.tel_pos_x[tel_id] - tilt_x))

        pix_x_rot, pix_y_rot = self.rotate_translate(self.pixel_x[tel_id]
                                                     * -1,
                                                     self.pixel_y[tel_id],
                                                     source_x,
                                                     source_y, phi)

        prediction = self.image_prediction(self.type[tel_id],
                                           20 * u.deg,
                                           0 * u.deg,
                                           energy_reco.energy.value,
                                           impact, x_max_bin,
                                           pix_x_rot * (180 / math.pi),
                                           pix_y_rot * (180 / math.pi))

        prediction *= self.scale[self.type[tel_id]]
        prediction[prediction < 0] = 0
        prediction[np.isnan(prediction)] = 0

        return prediction
Ejemplo n.º 9
0
    def get_prediction(self, tel_id, shower_reco, energy_reco):

        horizon_seed = HorizonFrame(az=shower_reco.az, alt=shower_reco.alt)
        nominal_seed = horizon_seed.transform_to(
            NominalFrame(array_direction=horizon_seed))
        source_x = nominal_seed.x.to(u.rad).value
        source_y = nominal_seed.y.to(u.rad).value

        print(self.array_direction[0])
        ground = GroundFrame(x=shower_reco.core_x,
                             y=shower_reco.core_y,
                             z=0 * u.m)
        tilted = ground.transform_to(
            TiltedGroundFrame(pointing_direction=HorizonFrame(
                alt=self.array_direction[0], az=self.array_direction[1])))
        tilt_x = tilted.x.to(u.m).value
        tilt_y = tilted.y.to(u.m).value

        zenith = 90 * u.deg - self.array_direction[0]
        azimuth = self.array_direction[1]

        x_max_exp = 300 + 93 * np.log10(energy_reco.energy.value)
        x_max = shower_reco.h_max / np.cos(zenith)

        # Convert to binning of Xmax, addition of 100 can probably be removed
        x_max_bin = x_max.value - x_max_exp
        if x_max_bin > 100:
            x_max_bin = 100
        if x_max_bin < -100:
            x_max_bin = -100

        impact = np.sqrt(
            pow(self.tel_pos_x[tel_id] - tilt_x, 2) +
            pow(self.tel_pos_y[tel_id] - tilt_y, 2))

        phi = np.arctan2((self.tel_pos_y[tel_id] - tilt_y),
                         (self.tel_pos_x[tel_id] - tilt_x))

        pix_x_rot, pix_y_rot = self.rotate_translate(self.pixel_x[tel_id] * -1,
                                                     self.pixel_y[tel_id],
                                                     source_x, source_y, phi)

        prediction = self.image_prediction(self.type[tel_id], 20 * u.deg,
                                           0 * u.deg, energy_reco.energy.value,
                                           impact, x_max_bin,
                                           pix_x_rot * (180 / math.pi),
                                           pix_y_rot * (180 / math.pi))

        prediction *= self.scale[self.type[tel_id]]
        prediction[prediction < 0] = 0
        prediction[np.isnan(prediction)] = 0

        return prediction
Ejemplo n.º 10
0
def test_estimator_results():
    """
    creating some planes pointing in different directions (two
    north-south, two east-west) and that have a slight position errors (+-
    0.1 m in one of the four cardinal directions """
    horizon_frame = HorizonFrame()

    p1 = SkyCoord(alt=43 * u.deg, az=45 * u.deg, frame=horizon_frame)
    p2 = SkyCoord(alt=47 * u.deg, az=45 * u.deg, frame=horizon_frame)
    circle1 = HillasPlane(p1=p1, p2=p2, telescope_position=[0, 1, 0] * u.m)

    p1 = SkyCoord(alt=44 * u.deg, az=90 * u.deg, frame=horizon_frame)
    p2 = SkyCoord(alt=46 * u.deg, az=90 * u.deg, frame=horizon_frame)
    circle2 = HillasPlane(p1=p1, p2=p2, telescope_position=[1, 0, 0] * u.m)

    p1 = SkyCoord(alt=44.5 * u.deg, az=45 * u.deg, frame=horizon_frame)
    p2 = SkyCoord(alt=46.5 * u.deg, az=45 * u.deg, frame=horizon_frame)
    circle3 = HillasPlane(p1=p1, p2=p2, telescope_position=[0, -1, 0] * u.m)

    p1 = SkyCoord(alt=43.5 * u.deg, az=90 * u.deg, frame=horizon_frame)
    p2 = SkyCoord(alt=45.5 * u.deg, az=90 * u.deg, frame=horizon_frame)
    circle4 = HillasPlane(p1=p1, p2=p2, telescope_position=[-1, 0, 0] * u.m)

    # creating the fit class and setting the the great circle member
    fit = HillasReconstructor()
    fit.hillas_planes = {1: circle1, 2: circle2, 3: circle3, 4: circle4}

    # performing the direction fit with the minimisation algorithm
    # and a seed that is perpendicular to the up direction
    dir_fit_minimise, _ = fit.estimate_direction()
    print("direction fit test minimise:", dir_fit_minimise)
    print()
Ejemplo n.º 11
0
def camera_to_sky(pos_x, pos_y, focal, pointing_alt, pointing_az):
    """

    Parameters
    ----------
    pos_x: X coordinate in camera (distance)
    pos_y: Y coordinate in camera (distance)
    focal: telescope focal (distance)
    pointing_alt: pointing altitude in angle unit
    pointing_az: pointing altitude in angle unit

    Returns
    -------
    (alt, az)

    Example:
    --------
    import astropy.units as u
    import numpy as np
    x = np.array([1,0]) * u.m
    y = np.array([1,1]) * u.m

    """
    pointing_direction = HorizonFrame(alt=pointing_alt, az=pointing_az)

    source_pos_in_camera = NominalFrame(
        array_direction=pointing_direction,
        pointing_direction=pointing_direction,
        x=pos_x / focal * u.rad,
        y=pos_y / focal * u.rad,
    )

    return source_pos_in_camera.transform_to(pointing_direction)
Ejemplo n.º 12
0
def test_h_max_results():
    """
    creating some planes pointing in different directions (two
    north-south, two east-west) and that have a slight position errors (+-
    0.1 m in one of the four cardinal directions """
    horizon_frame = HorizonFrame()

    p1 = SkyCoord(alt=0 * u.deg, az=45 * u.deg, frame=horizon_frame)
    p2 = SkyCoord(alt=0 * u.deg, az=45 * u.deg, frame=horizon_frame)
    circle1 = HillasPlane(p1=p1, p2=p2, telescope_position=[0, 1, 0] * u.m)

    p1 = SkyCoord(alt=0 * u.deg, az=90 * u.deg, frame=horizon_frame)
    p2 = SkyCoord(alt=0 * u.deg, az=90 * u.deg, frame=horizon_frame)
    circle2 = HillasPlane(p1=p1, p2=p2, telescope_position=[1, 0, 0] * u.m)

    p1 = SkyCoord(alt=0 * u.deg, az=45 * u.deg, frame=horizon_frame)
    p2 = SkyCoord(alt=0 * u.deg, az=45 * u.deg, frame=horizon_frame)
    circle3 = HillasPlane(p1=p1, p2=p2, telescope_position=[0, -1, 0] * u.m)

    p1 = SkyCoord(alt=0 * u.deg, az=90 * u.deg, frame=horizon_frame)
    p2 = SkyCoord(alt=0 * u.deg, az=90 * u.deg, frame=horizon_frame)
    circle4 = HillasPlane(p1=p1, p2=p2, telescope_position=[-1, 0, 0] * u.m)

    # creating the fit class and setting the the great circle member
    fit = HillasReconstructor()
    fit.hillas_planes = {1: circle1, 2: circle2, 3: circle3, 4: circle4}

    # performing the direction fit with the minimisation algorithm
    # and a seed that is perpendicular to the up direction
    h_max_reco = fit.estimate_h_max()
    print("h max fit test minimise:", h_max_reco)

    # the results should be close to the direction straight up
    np.testing.assert_allclose(h_max_reco.value, 0, atol=1e-8)
Ejemplo n.º 13
0
def test_cam_to_nominal():
    from ctapipe.coordinates import CameraFrame, HorizonFrame, NominalFrame

    telescope_pointing = SkyCoord(alt=70 * u.deg,
                                  az=0 * u.deg,
                                  frame=HorizonFrame())
    array_pointing = SkyCoord(alt=72 * u.deg,
                              az=0 * u.deg,
                              frame=HorizonFrame())

    cam_frame = CameraFrame(focal_length=28 * u.m,
                            telescope_pointing=telescope_pointing)
    cam = SkyCoord(x=0.5 * u.m, y=0.1 * u.m, frame=cam_frame)

    nom_frame = NominalFrame(origin=array_pointing)
    cam.transform_to(nom_frame)
Ejemplo n.º 14
0
def grd_to_tilt():
    grd_coord = GroundFrame(x=1 * u.m, y=2 * u.m, z=0 * u.m)
    tilt_coord = grd_coord.transform_to(
        TiltedGroundFrame(
            pointing_direction=HorizonFrame(alt=90 * u.deg, az=180 * u.deg)))
    print(project_to_ground(tilt_coord))
    print("Tilted Coordinate", tilt_coord)
Ejemplo n.º 15
0
def test_icrs_to_camera():
    from ctapipe.coordinates import CameraFrame, HorizonFrame

    obstime = Time('2013-11-01T03:00')
    location = EarthLocation.of_site('Roque de los Muchachos')
    horizon_frame = HorizonFrame(location=location, obstime=obstime)

    # simulate crab "on" observations
    crab = SkyCoord(ra='05h34m31.94s', dec='22d00m52.2s')
    telescope_pointing = crab.transform_to(horizon_frame)

    camera_frame = CameraFrame(
        focal_length=28 * u.m,
        telescope_pointing=telescope_pointing,
        location=location,
        obstime=obstime,
    )

    ceta_tauri = SkyCoord(ra='5h37m38.6854231s', dec='21d08m33.158804s')
    ceta_tauri_camera = ceta_tauri.transform_to(camera_frame)

    camera_center = SkyCoord(0 * u.m, 0 * u.m, frame=camera_frame)
    crab_camera = crab.transform_to(camera_frame)

    assert crab_camera.x.to_value(u.m) == approx(0.0, abs=1e-10)
    assert crab_camera.y.to_value(u.m) == approx(0.0, abs=1e-10)

    # assert ceta tauri is in FoV
    assert camera_center.separation_3d(ceta_tauri_camera) < u.Quantity(
        0.6, u.m)
Ejemplo n.º 16
0
    def inititialize_hillas_planes(
        self,
        hillas_dict,
        subarray,
        pointing_alt,
        pointing_az
    ):
        """
        creates a dictionary of :class:`.HillasPlane` from a dictionary of
        hillas
        parameters

        Parameters
        ----------
        hillas_dict : dictionary
            dictionary of hillas moments
        subarray : ctapipe.instrument.SubarrayDescription
            subarray information
        tel_phi, tel_theta : dictionaries
            dictionaries of the orientation angles of the telescopes
            needs to contain at least the same keys as in `hillas_dict`
        """

        self.hillas_planes = {}
        for tel_id, moments in hillas_dict.items():
            p2_x = moments.cen_x + 0.1 * u.m * np.cos(moments.psi)
            p2_y = moments.cen_y + 0.1 * u.m * np.sin(moments.psi)
            focal_length = subarray.tel[tel_id].optics.equivalent_focal_length

            pointing = SkyCoord(
                alt=pointing_alt[tel_id],
                az=pointing_az[tel_id],
                frame='altaz'
            )

            hf = HorizonFrame(
                array_direction=pointing,
                pointing_direction=pointing
            )
            cf = CameraFrame(
                focal_length=focal_length,
                array_direction=pointing,
                pointing_direction=pointing
            )

            cog_coord = SkyCoord(x=moments.cen_x, y=moments.cen_y, frame=cf)
            cog_coord = cog_coord.transform_to(hf)

            p2_coord = SkyCoord(x=p2_x, y=p2_y, frame=cf)
            p2_coord = p2_coord.transform_to(hf)

            circle = HillasPlane(
                p1=cog_coord,
                p2=p2_coord,
                telescope_position=subarray.positions[tel_id],
                weight=moments.size * (moments.length / moments.width),
            )
            self.hillas_planes[tel_id] = circle
Ejemplo n.º 17
0
    def initialize_hillas_planes(
        self,
        hillas_dict,
        subarray,
        pointing_alt,
        pointing_az
    ):
        """
        creates a dictionary of :class:`.HillasPlane` from a dictionary of
        hillas
        parameters

        Parameters
        ----------
        hillas_dict : dictionary
            dictionary of hillas moments
        subarray : ctapipe.instrument.SubarrayDescription
            subarray information
        tel_phi, tel_theta : dictionaries
            dictionaries of the orientation angles of the telescopes
            needs to contain at least the same keys as in `hillas_dict`
        """
        self.hillas_planes = {}
        horizon_frame = HorizonFrame()
        for tel_id, moments in hillas_dict.items():
            # we just need any point on the main shower axis a bit away from the cog
            p2_x = moments.x + 0.1 * u.m * np.cos(moments.psi)
            p2_y = moments.y + 0.1 * u.m * np.sin(moments.psi)
            focal_length = subarray.tel[tel_id].optics.equivalent_focal_length

            pointing = SkyCoord(
                alt=pointing_alt[tel_id],
                az=pointing_az[tel_id],
                frame=horizon_frame,
            )

            camera_frame = CameraFrame(
                focal_length=focal_length,
                telescope_pointing=pointing
            )

            cog_coord = SkyCoord(
                x=moments.x,
                y=moments.y,
                frame=camera_frame,
            )
            cog_coord = cog_coord.transform_to(horizon_frame)

            p2_coord = SkyCoord(x=p2_x, y=p2_y, frame=camera_frame)
            p2_coord = p2_coord.transform_to(horizon_frame)

            circle = HillasPlane(
                p1=cog_coord,
                p2=p2_coord,
                telescope_position=subarray.positions[tel_id],
                weight=moments.intensity * (moments.length / moments.width),
            )
            self.hillas_planes[tel_id] = circle
def nominal_to_altaz():
    t = np.zeros(10)
    t[5] = 1
    nom = NominalFrame(
        x=t * u.deg,
        y=t * u.deg,
        array_direction=HorizonFrame(alt=75 * u.deg, az=180 * u.deg)
    )
    alt_az = nom.transform_to(HorizonFrame)
    print("AltAz Coordinate", alt_az)
def cam_to_nom():
    pix = [np.ones(2048), np.ones(2048), np.zeros(2048)] * u.m
    camera_coord = CameraFrame(pix, focal_length=15 * u.m)
    # In this case we bypass the telescope system
    nom_coord = camera_coord.transform_to(
        NominalFrame(
            pointing_direction=HorizonFrame(alt=70 * u.deg, az=180 * u.deg),
            array_direction=HorizonFrame(alt=75 * u.deg, az=180 * u.deg)
        )
    )
    alt_az = camera_coord.transform_to(
        HorizonFrame(
            pointing_direction=HorizonFrame(alt=70 * u.deg, az=180 * u.deg),
            array_direction=HorizonFrame(alt=75 * u.deg, az=180 * u.deg)
        )
    )

    print("Nominal Coordinate", nom_coord)
    print("AltAz coordinate", alt_az)
Ejemplo n.º 20
0
def transform_azel_to_xy(stars_az, stars_alt, az_obs, el_obs):
    """
    function to transform azimuth and elevation coodinates to XY coordinates in
    the fild of view.
    :param stars_az: 2D array of azimuth coordinates to be transformed.
    1st dimension is for different objects and 2nd dimension is for different
    observation time.
    :param stars_alt: 2D array of elevation coordinates to be transformed.
    1st dimension is for different objects and 2nd dimension is for different
    observation time.
    :param az_obs: 1D array of telescope azimuth pointing direction (1 element
    per observation time).
    :param el_obs: 1D array of telescope elevation pointing direction (1
    element per observation time).
    :return: stars_x, stars_y : 2D array giving for each object (1st dimension)
    and each observation time (2nd dimension) the XY coordinates in the field
    of view.
    """
    n_stars = stars_az.shape[0]
    n_event = az_obs.shape[0]
    assert stars_az.shape == (n_stars, n_event)
    assert stars_alt.shape == (n_stars, n_event)
    assert el_obs.shape[0] == n_event
    stars_x = np.zeros([n_stars, n_event]) * u.mm
    stars_y = np.zeros([n_stars, n_event]) * u.mm
    for event in range(n_event):
        pd = SkyCoord(alt=el_obs[event],
                      az=az_obs[event],
                      frame=HorizonFrame())
        cam_frame = CameraFrame(
            focal_length=5.6 * u.m,
            rotation=90 * u.deg,
            pointing_direction=pd,
            array_direction=pd,
        )
        stars_sky = SkyCoord(alt=stars_alt[:, event],
                             az=stars_az[:, event],
                             frame=HorizonFrame())
        stars_cam = stars_sky.transform_to(cam_frame)
        stars_x[:, event] = -stars_cam.x
        stars_y[:, event] = stars_cam.y
    return stars_x, stars_y
Ejemplo n.º 21
0
def cam_to_nom():
    pix_x = np.ones(2048) * u.m
    pix_y = np.ones(2048) * u.m

    pointing_direction = SkyCoord(alt=70 * u.deg,
                                  az=180 * u.deg,
                                  frame=HorizonFrame())
    camera_frame = CameraFrame(focal_length=15 * u.m,
                               telescope_pointing=pointing_direction)
    camera_coord = SkyCoord(pix_x, pix_y, frame=camera_frame)

    # In this case we bypass the telescope system
    nominal_frame = NominalFrame(
        origin=HorizonFrame(alt=75 * u.deg, az=180 * u.deg))
    nom_coord = camera_coord.transform_to(nominal_frame)

    horizon = camera_coord.transform_to(HorizonFrame())

    print("Nominal Coordinate", nom_coord)
    print("Horizon coordinate", horizon)
Ejemplo n.º 22
0
    def __init__(self, config, tool, event, **kwargs):
        super().__init__(config=config, tool=tool, **kwargs)

        self.camera_geom_dict = {}
        self.nominal_geom_dict = {}

        self.inst = event.inst
        array_pointing = HorizonFrame(
            alt=event.mcheader.run_array_direction[1] * u.rad,
            az=event.mcheader.run_array_direction[0] * u.rad)
        self.nom_system = NominalFrame(array_direction=array_pointing,
                                       pointing_direction=array_pointing)
Ejemplo n.º 23
0
def get_event_pos_in_sky(hillas, disp, tel, pointing_direction):
    side = 1  # TODO: method to guess side

    focal = tel.optics.equivalent_focal_length
    source_pos_in_camera = NominalFrame(array_direction=pointing_direction,
                                        pointing_direction=pointing_direction,
                                        x=(hillas.x + side * disp * np.cos(hillas.phi)) / focal * u.rad,
                                        y=(hillas.y + side * disp * np.sin(hillas.phi)) / focal * u.rad
                                        )

    horizon_frame = HorizonFrame(alt=pointing_direction.alt, az=pointing_direction.az)
    return source_pos_in_camera.transform_to(horizon_frame)
Ejemplo n.º 24
0
def test_roundtrip_camera_horizon():
    from ctapipe.coordinates import CameraFrame, TelescopeFrame, HorizonFrame

    telescope_pointing = SkyCoord(alt=70 * u.deg,
                                  az=0 * u.deg,
                                  frame=HorizonFrame())
    camera_frame = CameraFrame(focal_length=28 * u.m,
                               telescope_pointing=telescope_pointing)

    cam_coord = SkyCoord(x=0.5 * u.m, y=0.1 * u.m, frame=camera_frame)
    telescope_coord = cam_coord.transform_to(TelescopeFrame())
    horizon_coord = telescope_coord.transform_to(HorizonFrame())

    back_telescope_coord = horizon_coord.transform_to(TelescopeFrame())
    back_cam_coord = back_telescope_coord.transform_to(camera_frame)

    delta_az = back_telescope_coord.delta_az.to_value(u.deg)
    delta_alt = back_telescope_coord.delta_alt.to_value(u.deg)
    assert delta_az == approx(telescope_coord.delta_az.to_value(u.deg))
    assert delta_alt == approx(telescope_coord.delta_alt.to_value(u.deg))

    assert back_cam_coord.x.to_value(u.m) == approx(cam_coord.x.to_value(u.m))
    assert back_cam_coord.y.to_value(u.m) == approx(cam_coord.y.to_value(u.m))
Ejemplo n.º 25
0
def ground_grid(event, tel_pos=False):
    """
    Return the telescopes positions in the GroundFrame and plot on ground
    :param event: input event selected from simtel
    :param tel_pos: (bool) if True, plot the telescopes as spheres
    :return:
    """
    alt = event.mcheader.run_array_direction[1]
    az = event.mcheader.run_array_direction[0]
    array_pointing = HorizonFrame(alt=alt, az=az)

    ground_coordinates = GroundFrame(x=event.inst.subarray.tel_coords.x,
                                     y=event.inst.subarray.tel_coords.y,
                                     z=event.inst.subarray.tel_coords.z,
                                     pointing_direction=array_pointing)

    grid_unit = 20000  # in centimeters

    ground_system = union()
    if tel_pos:
        # for i in range(ground_coordinates.x.size):
        for i in range(50):
            coords = [
                100 * ground_coordinates.x[i].value,
                100 * ground_coordinates.y[i].value,
                100 * ground_coordinates.z[i].value
            ]
            position = translate(coords)(color([0, 0, 1])(sphere(r=800)))
            ground_system.add(position)

    grid = grid_plane(
        grid_unit=grid_unit,
        count=2 *
        int(100 * np.max(np.abs(ground_coordinates.x.value)) / grid_unit),
        line_weight=200,
        plane='xy')

    grid = color([0, 0, 1, 0.5])(grid)
    ground_system.add(grid)

    # SYSTEM + ARROW
    ref_arr = ref_arrow_3d(8000,
                           origin=(1000, 1000, 0),
                           label={
                               'x': "x_gnd = NORTH",
                               'y': "y_gnd = WEST",
                               'z': "z_gnd"
                           })
    ground_system = ground_system + ref_arr
    return ground_system
Ejemplo n.º 26
0
def get_event_pos_in_camera(event, tel):
    """
    Return the position of the source in the camera frame
    Parameters
    ----------
    event: `ctapipe.io.containers.DataContainer`
    tel: `ctapipe.instruement.telescope.TelescopeDescription`

    Returns
    -------
    (x, y) (float, float): position in the camera
    """
    array_pointing = HorizonFrame(alt=event.mcheader.run_array_direction[1],
                              az=event.mcheader.run_array_direction[0])
    event_direction = HorizonFrame(alt=event.mc.alt.to(u.rad),
                               az=event.mc.az.to(u.rad))

    nom_frame = NominalFrame(array_direction=array_pointing,
                         pointing_direction=array_pointing)

    event_dir_nom = event_direction.transform_to(nom_frame)
    focal = tel.optics.equivalent_focal_length
    return focal * (event_dir_nom.x.to(u.rad).value, event_dir_nom.y.to(u.rad).value)
Ejemplo n.º 27
0
def test_telescope_separation():
    from ctapipe.coordinates import TelescopeFrame, HorizonFrame

    telescope_pointing = SkyCoord(alt=70 * u.deg,
                                  az=0 * u.deg,
                                  frame=HorizonFrame())

    telescope_frame = TelescopeFrame(telescope_pointing=telescope_pointing)
    tel1 = SkyCoord(delta_az=0 * u.deg,
                    delta_alt=0 * u.deg,
                    frame=telescope_frame)
    tel2 = SkyCoord(delta_az=0 * u.deg,
                    delta_alt=1 * u.deg,
                    frame=telescope_frame)

    assert tel1.separation(tel2) == u.Quantity(1, u.deg)
Ejemplo n.º 28
0
    def estimate_h_max(self, hillas_dict, subarray, pointing_alt, pointing_az):
        weights = []
        tels = []
        dirs = []

        for tel_id, moments in hillas_dict.items():

            focal_length = subarray.tel[tel_id].optics.equivalent_focal_length

            pointing = SkyCoord(
                alt=pointing_alt[tel_id],
                az=pointing_az[tel_id],
                frame='altaz'
            )

            hf = HorizonFrame(
                array_direction=pointing,
                pointing_direction=pointing
            )
            cf = CameraFrame(
                focal_length=focal_length,
                array_direction=pointing,
                pointing_direction=pointing
            )

            cog_coord = SkyCoord(x=moments.cen_x, y=moments.cen_y, frame=cf)
            cog_coord = cog_coord.transform_to(hf)

            cog_direction = spherical_to_cartesian(1, cog_coord.alt, cog_coord.az)
            cog_direction = np.array(cog_direction).ravel()

            weights.append(self.hillas_planes[tel_id].weight)
            tels.append(self.hillas_planes[tel_id].pos)
            dirs.append(cog_direction)

        # minimising the test function
        pos_max = minimize(dist_to_line3d, np.array([0, 0, 10000]),
                           args=(np.array(tels), np.array(dirs), np.array(weights)),
                           method='BFGS',
                           options={'disp': False}
                           ).x
        return pos_max[2] * u.m
Ejemplo n.º 29
0
    def configure(self, config):
        config[self.cout_pix_pos] = self.pix_pos

        config[self.cout_fov] = 0.8  # around a pixel

        # precomputing transformations
        # Will need to do this smarter (in chunks) when the number of frames reaches 10k-100k
        self.obstimes = config["time_steps"]
        self.precomp_hf = HorizonFrame(location=self.location,
                                       obstime=self.obstimes)
        target = SkyCoord(ra=self.par_pointingra.val,
                          dec=self.par_pointingdec.val,
                          unit="deg")
        self.precomp_point = target.transform_to(self.precomp_hf)
        config["start_pointing"] = self.precomp_point[0]
        config[self.cout_altazframes] = self.precomp_hf
        config["cam_frame0"] = CameraFrame(
            telescope_pointing=config["start_pointing"],
            focal_length=u.Quantity(self.focal_length, u.m),  # 28 for LST
            obstime=self.obstimes[0],
            location=self.location,
        )
Ejemplo n.º 30
0
def test_separation_is_the_same():
    from ctapipe.coordinates import TelescopeFrame, HorizonFrame

    obstime = Time('2013-11-01T03:00')
    location = EarthLocation.of_site('Roque de los Muchachos')
    horizon_frame = HorizonFrame(location=location, obstime=obstime)

    crab = SkyCoord(ra='05h34m31.94s', dec='22d00m52.2s')
    ceta_tauri = SkyCoord(ra='5h37m38.6854231s', dec='21d08m33.158804s')

    # simulate crab "on" observations
    telescope_pointing = crab.transform_to(horizon_frame)

    telescope_frame = TelescopeFrame(
        telescope_pointing=telescope_pointing,
        location=location,
        obstime=obstime,
    )

    ceta_tauri_telescope = ceta_tauri.transform_to(telescope_frame)
    crab_telescope = crab.transform_to(telescope_frame)

    sep = ceta_tauri_telescope.separation(crab_telescope).to_value(u.deg)
    assert ceta_tauri.separation(crab).to_value(u.deg) == approx(sep, rel=1e-4)
Ejemplo n.º 31
0
    def predict(self, shower_seed, energy_seed):
        """
        Parameters
        ----------
        shower_seed: ReconstructedShowerContainer
            Seed shower geometry to be used in the fit
        energy_seed: ReconstructedEnergyContainer
            Seed energy to be used in fit

        Returns
        -------
        ReconstructedShowerContainer, ReconstructedEnergyContainer:
        Reconstructed ImPACT shower geometry and energy
        """

        horizon_seed = HorizonFrame(az=shower_seed.az, alt=shower_seed.alt)
        nominal_seed = horizon_seed.transform_to(NominalFrame(
            array_direction=self.array_direction))

        source_x = nominal_seed.x.to(u.rad).value
        source_y = nominal_seed.y.to(u.rad).value
        ground = GroundFrame(x=shower_seed.core_x,
                             y=shower_seed.core_y, z=0 * u.m)
        tilted = ground.transform_to(
            TiltedGroundFrame(pointing_direction=self.array_direction)
        )
        tilt_x = tilted.x.to(u.m).value
        tilt_y = tilted.y.to(u.m).value
        zenith = 90 * u.deg - self.array_direction.alt

        if len(self.hillas_parameters) > 3:
            shift = [1]
        else:
            shift = [1.5, 1, 0.5, 0, -0.5, -1, -1.5]

        seed_list = spread_line_seed(self.hillas_parameters,
                                     self.tel_pos_x, self.tel_pos_y,
                                     source_x[0], source_y[0], tilt_x, tilt_y,
                                     energy_seed.energy.value,
                                     shift_frac = shift)

        chosen_seed = self.choose_seed(seed_list)
        # Perform maximum likelihood fit
        fit_params, errors, like = self.minimise(params=chosen_seed[0],
                                                 step=chosen_seed[1],
                                                 limits=chosen_seed[2],
                                                 minimiser_name=self.minimiser_name)

        # Create a container class for reconstructed shower
        shower_result = ReconstructedShowerContainer()

        # Convert the best fits direction and core to Horizon and ground systems and
        # copy to the shower container
        nominal = NominalFrame(x=fit_params[0] * u.rad,
                               y=fit_params[1] * u.rad,
                               array_direction=self.array_direction)
        horizon = nominal.transform_to(HorizonFrame())

        shower_result.alt, shower_result.az = horizon.alt, horizon.az
        tilted = TiltedGroundFrame(x=fit_params[2] * u.m,
                                   y=fit_params[3] * u.m,
                                   pointing_direction=self.array_direction)
        ground = project_to_ground(tilted)

        shower_result.core_x = ground.x
        shower_result.core_y = ground.y

        shower_result.is_valid = True

        # Currently no errors not availible to copy NaN
        shower_result.alt_uncert = np.nan
        shower_result.az_uncert = np.nan
        shower_result.core_uncert = np.nan

        # Copy reconstructed Xmax
        shower_result.h_max = fit_params[5] * self.get_shower_max(fit_params[0],
                                                                  fit_params[1],
                                                                  fit_params[2],
                                                                  fit_params[3],
                                                                  zenith.to(u.rad).value)

        shower_result.h_max *= np.cos(zenith)
        shower_result.h_max_uncert = errors[5] * shower_result.h_max

        shower_result.goodness_of_fit = like

        # Create a container class for reconstructed energy
        energy_result = ReconstructedEnergyContainer()
        # Fill with results
        energy_result.energy = fit_params[4] * u.TeV
        energy_result.energy_uncert = errors[4] * u.TeV
        energy_result.is_valid = True

        return shower_result, energy_result
Ejemplo n.º 32
0
    def predict(self, shower_seed, energy_seed):
        """

        Parameters
        ----------
        source_x: float
            Initial guess of source position in the nominal frame
        source_y: float
            Initial guess of source position in the nominal frame
        core_x: float
            Initial guess of the core position in the tilted system
        core_y: float
            Initial guess of the core position in the tilted system
        energy: float
            Initial guess of energy

        Returns
        -------
        Shower object with fit results
        """
        horizon_seed = HorizonFrame(az=shower_seed.az, alt=shower_seed.alt)
        nominal_seed = horizon_seed.transform_to(
            NominalFrame(array_direction=self.array_direction)
        )

        source_x = nominal_seed.x.to(u.rad).value
        source_y = nominal_seed.y.to(u.rad).value

        ground = GroundFrame(x=shower_seed.core_x,
                             y=shower_seed.core_y, z=0 * u.m)
        tilted = ground.transform_to(
            TiltedGroundFrame(pointing_direction=self.array_direction)
        )
        tilt_x = tilted.x.to(u.m).value
        tilt_y = tilted.y.to(u.m).value

        lower_en_limit = energy_seed.energy * 0.1
        if lower_en_limit < 0.04 * u.TeV:
            lower_en_limit = 0.04 * u.TeV
        # Create Minuit object with first guesses at parameters, strip away the
        # units as Minuit doesnt like them
        min = Minuit(self.get_likelihood,
                     print_level=1,
                     source_x=source_x,
                     error_source_x=0.01 / 57.3,
                     fix_source_x=False,
                     limit_source_x=(source_x - 0.5 / 57.3,
                                     source_x + 0.5 / 57.3),
                     source_y=source_y,
                     error_source_y=0.01 / 57.3,
                     fix_source_y=False,
                     limit_source_y=(source_y - 0.5 / 57.3,
                                     source_y + 0.5 / 57.3),
                     core_x=tilt_x,
                     error_core_x=10,
                     limit_core_x=(tilt_x - 200, tilt_x + 200),
                     core_y=tilt_y,
                     error_core_y=10,
                     limit_core_y=(tilt_y - 200, tilt_y + 200),
                     energy=energy_seed.energy.value,
                     error_energy=energy_seed.energy.value * 0.05,
                     limit_energy=(lower_en_limit.value,
                                   energy_seed.energy.value * 10.),
                     x_max_scale=1, error_x_max_scale=0.1,
                     limit_x_max_scale=(0.5, 2),
                     fix_x_max_scale=False,
                     errordef=1)

        min.tol *= 1000
        min.strategy = 0

        # Perform minimisation
        migrad = min.migrad()
        fit_params = min.values
        errors = min.errors
    #    print(migrad)
    #    print(min.minos())

        # container class for reconstructed showers '''
        shower_result = ReconstructedShowerContainer()

        nominal = NominalFrame(x=fit_params["source_x"] * u.rad,
                               y=fit_params["source_y"] * u.rad,
                               array_direction=self.array_direction)
        horizon = nominal.transform_to(HorizonFrame())

        shower_result.alt, shower_result.az = horizon.alt, horizon.az
        tilted = TiltedGroundFrame(x=fit_params["core_x"] * u.m,
                                   y=fit_params["core_y"] * u.m,
                                   pointing_direction=self.array_direction)
        ground = project_to_ground(tilted)

        shower_result.core_x = ground.x
        shower_result.core_y = ground.y

        shower_result.is_valid = True

        shower_result.alt_uncert = np.nan
        shower_result.az_uncert = np.nan
        shower_result.core_uncert = np.nan
        zenith = 90 * u.deg - self.array_direction[0]
        shower_result.h_max = fit_params["x_max_scale"] * \
            self.get_shower_max(fit_params["source_x"],
                                fit_params["source_y"],
                                fit_params["core_x"],
                                fit_params["core_y"],
                                zenith.to(u.rad).value)
        shower_result.h_max_uncert = errors["x_max_scale"] * shower_result.h_max
        shower_result.goodness_of_fit = np.nan
        shower_result.tel_ids = list(self.image.keys())

        energy_result = ReconstructedEnergyContainer()
        energy_result.energy = fit_params["energy"] * u.TeV
        energy_result.energy_uncert = errors["energy"] * u.TeV
        energy_result.is_valid = True
        energy_result.tel_ids = list(self.image.keys())
        # Return interesting stuff

        return shower_result, energy_result
Ejemplo n.º 33
0
def plot_muon_event(event, muonparams, args=None):

    if muonparams['MuonRingParams'] is not None:

        # Plot the muon event and overlay muon parameters
        fig = plt.figure(figsize=(16, 7))

        colorbar = None
        colorbar2 = None

        #for tel_id in event.dl0.tels_with_data:
        for tel_id in muonparams['TelIds']:
            idx = muonparams['TelIds'].index(tel_id)

            if not muonparams['MuonRingParams'][idx]:
                continue

            #otherwise...
            npads = 2
            # Only create two pads if there is timing information extracted
            # from the calibration
            ax1 = fig.add_subplot(1, npads, 1)
            plotter = CameraPlotter(event)
            image = event.dl1.tel[tel_id].image[0]
            geom = event.inst.subarray.tel[tel_id].camera

            tailcuts = (5., 7.)
            # Try a higher threshold for
            if geom.cam_id == 'FlashCam':
                tailcuts = (10., 12.)

            clean_mask = tailcuts_clean(geom,
                                        image,
                                        picture_thresh=tailcuts[0],
                                        boundary_thresh=tailcuts[1])

            signals = image * clean_mask

            #print("Ring Centre in Nominal Coords:",muonparams[0].ring_center_x,muonparams[0].ring_center_y)
            muon_incl = np.sqrt(
                muonparams['MuonRingParams'][idx].ring_center_x**2. +
                muonparams['MuonRingParams'][idx].ring_center_y**2.)

            muon_phi = np.arctan(
                muonparams['MuonRingParams'][idx].ring_center_y /
                muonparams['MuonRingParams'][idx].ring_center_x)

            rotr_angle = geom.pix_rotation
            # if event.inst.optical_foclen[tel_id] > 10.*u.m and
            # event.dl0.tel[tel_id].num_pixels != 1764:
            if geom.cam_id == 'LSTCam' or geom.cam_id == 'NectarCam':
                #print("Resetting the rotation angle")
                rotr_angle = 0. * u.deg

            # Convert to camera frame (centre & radius)
            altaz = HorizonFrame(alt=event.mc.alt, az=event.mc.az)

            ring_nominal = NominalFrame(
                x=muonparams['MuonRingParams'][idx].ring_center_x,
                y=muonparams['MuonRingParams'][idx].ring_center_y,
                array_direction=altaz,
                pointing_direction=altaz)

            # embed()
            ring_camcoord = ring_nominal.transform_to(
                CameraFrame(pointing_direction=altaz,
                            focal_length=event.inst.optical_foclen[tel_id],
                            rotation=rotr_angle))

            centroid_rad = np.sqrt(ring_camcoord.y**2 + ring_camcoord.x**2)
            centroid = (ring_camcoord.x.value, ring_camcoord.y.value)

            ringrad_camcoord = muonparams['MuonRingParams'][idx].ring_radius.to(u.rad) \
                               * event.inst.optical_foclen[tel_id] * 2.  # But not FC?

            px, py = event.inst.pixel_pos[tel_id]
            flen = event.inst.optical_foclen[tel_id]
            camera_coord = CameraFrame(x=px,
                                       y=py,
                                       focal_length=flen,
                                       rotation=geom.pix_rotation)

            nom_coord = camera_coord.transform_to(
                NominalFrame(array_direction=altaz, pointing_direction=altaz))

            px = nom_coord.x.to(u.deg)
            py = nom_coord.y.to(u.deg)

            dist = np.sqrt(
                np.power(px -
                         muonparams['MuonRingParams'][idx].ring_center_x, 2) +
                np.power(py -
                         muonparams['MuonRingParams'][idx].ring_center_y, 2))
            ring_dist = np.abs(dist -
                               muonparams['MuonRingParams'][idx].ring_radius)
            pixRmask = ring_dist < muonparams['MuonRingParams'][
                idx].ring_radius * 0.4

            #if muonparams[1] is not None:
            if muonparams['MuonIntensityParams'][idx] is not None:
                signals *= muonparams['MuonIntensityParams'][idx].mask

            camera1 = plotter.draw_camera(tel_id, signals, ax1)

            cmaxmin = (max(signals) - min(signals))
            cmin = min(signals)
            if not cmin:
                cmin = 1.
            if not cmaxmin:
                cmaxmin = 1.

            cmap_charge = colors.LinearSegmentedColormap.from_list(
                'cmap_c', [(0 / cmaxmin, 'darkblue'),
                           (np.abs(cmin) / cmaxmin, 'black'),
                           (2.0 * np.abs(cmin) / cmaxmin, 'blue'),
                           (2.5 * np.abs(cmin) / cmaxmin, 'green'),
                           (1, 'yellow')])
            camera1.pixels.set_cmap(cmap_charge)
            if not colorbar:
                camera1.add_colorbar(ax=ax1, label=" [photo-electrons]")
                colorbar = camera1.colorbar
            else:
                camera1.colorbar = colorbar
            camera1.update(True)

            camera1.add_ellipse(centroid,
                                ringrad_camcoord.value,
                                ringrad_camcoord.value,
                                0.,
                                0.,
                                color="red")

            if muonparams['MuonIntensityParams'][idx] is not None:
                # continue #Comment this...(should ringwidthfrac also be *0.5?)

                ringwidthfrac = muonparams['MuonIntensityParams'][
                    idx].ring_width / muonparams['MuonRingParams'][
                        idx].ring_radius
                ringrad_inner = ringrad_camcoord * (1. - ringwidthfrac)
                ringrad_outer = ringrad_camcoord * (1. + ringwidthfrac)
                camera1.add_ellipse(centroid,
                                    ringrad_inner.value,
                                    ringrad_inner.value,
                                    0.,
                                    0.,
                                    color="magenta")
                camera1.add_ellipse(centroid,
                                    ringrad_outer.value,
                                    ringrad_outer.value,
                                    0.,
                                    0.,
                                    color="magenta")
                npads = 2
                ax2 = fig.add_subplot(1, npads, npads)
                pred = muonparams['MuonIntensityParams'][idx].prediction

                if len(pred) != np.sum(
                        muonparams['MuonIntensityParams'][idx].mask):
                    print("Warning! Lengths do not match...len(pred)=",
                          len(pred), "len(mask)=",
                          np.sum(muonparams['MuonIntensityParams'][idx].mask))

                # Numpy broadcasting - fill in the shape
                plotpred = np.zeros(image.shape)
                plotpred[muonparams['MuonIntensityParams'][idx].mask ==
                         True] = pred

                camera2 = plotter.draw_camera(tel_id, plotpred, ax2)

                if np.isnan(max(plotpred)) or np.isnan(min(plotpred)):
                    print("nan prediction, skipping...")
                    continue

                c2maxmin = (max(plotpred) - min(plotpred))
                if not c2maxmin:
                    c2maxmin = 1.

                c2map_charge = colors.LinearSegmentedColormap.from_list(
                    'c2map_c',
                    [(0 / c2maxmin, 'darkblue'),
                     (np.abs(min(plotpred)) / c2maxmin, 'black'),
                     (2.0 * np.abs(min(plotpred)) / c2maxmin, 'blue'),
                     (2.5 * np.abs(min(plotpred)) / c2maxmin, 'green'),
                     (1, 'yellow')])
                camera2.pixels.set_cmap(c2map_charge)
                if not colorbar2:
                    camera2.add_colorbar(ax=ax2, label=" [photo-electrons]")
                    colorbar2 = camera2.colorbar
                else:
                    camera2.colorbar = colorbar2
                camera2.update(True)
                plt.pause(1.)  # make shorter

            # plt.pause(0.1)
            # if pp is not None:
            #    pp.savefig(fig)
            #fig.savefig(str(args.output_path) + "_" +
            #            str(event.dl0.event_id) + '.png')

            plt.close()
Ejemplo n.º 34
0
    def predict(self, shower_seed, energy_seed):
        """
        
        Parameters
        ----------
        shower_seed: ReconstructedShowerContainer
            Seed shower geometry to be used in the fit
        energy_seed: ReconstructedEnergyContainer
            Seed energy to be used in fit

        Returns
        -------
        ReconstructedShowerContainer, ReconstructedEnergyContainer:
        Reconstructed ImPACT shower geometry and energy
        
        """
        horizon_seed = HorizonFrame(az=shower_seed.az, alt=shower_seed.alt)
        nominal_seed = horizon_seed.transform_to(NominalFrame(array_direction=self.array_direction))
        print(nominal_seed)
        print(horizon_seed)
        print(self.array_direction)

        source_x = nominal_seed.x[0].to(u.rad).value
        source_y = nominal_seed.y[0].to(u.rad).value

        ground = GroundFrame(x=shower_seed.core_x,
                             y=shower_seed.core_y, z=0 * u.m)
        tilted = ground.transform_to(
            TiltedGroundFrame(pointing_direction=self.array_direction)
        )
        tilt_x = tilted.x.to(u.m).value
        tilt_y = tilted.y.to(u.m).value

        lower_en_limit = energy_seed.energy * 0.5
        en_seed =  energy_seed.energy
        if lower_en_limit < 0.04 * u.TeV:
            lower_en_limit = 0.04 * u.TeV
            en_seed = 0.041 * u.TeV

        seed = (source_x, source_y, tilt_x,
                tilt_y, en_seed.value, 0.8)
        step = (0.001, 0.001, 10, 10, en_seed.value*0.1, 0.1)
        limits = ((source_x-0.01, source_x+0.01),
                  (source_y-0.01, source_y+0.01),
                  (tilt_x-100, tilt_x+100),
                  (tilt_y-100, tilt_y+100),
                  (lower_en_limit.value, en_seed.value*2),
                  (0.5,2))

        fit_params, errors = self.minimise(params=seed, step=step, limits=limits,
                                             minimiser_name=self.minimiser_name)

        # container class for reconstructed showers '''
        shower_result = ReconstructedShowerContainer()

        nominal = NominalFrame(x=fit_params[0] * u.rad,
                               y=fit_params[1] * u.rad,
                               array_direction=self.array_direction)
        horizon = nominal.transform_to(HorizonFrame())

        shower_result.alt, shower_result.az = horizon.alt, horizon.az
        tilted = TiltedGroundFrame(x=fit_params[2] * u.m,
                                   y=fit_params[3] * u.m,
                                   pointing_direction=self.array_direction)
        ground = project_to_ground(tilted)

        shower_result.core_x = ground.x
        shower_result.core_y = ground.y

        shower_result.is_valid = True

        shower_result.alt_uncert = np.nan
        shower_result.az_uncert = np.nan
        shower_result.core_uncert = np.nan

        zenith = 90*u.deg - self.array_direction.alt
        shower_result.h_max = fit_params[5] * \
                              self.get_shower_max(fit_params[0],
                                                  fit_params[1],
                                                  fit_params[2],
                                                  fit_params[3],
                                                  zenith.to(u.rad).value)

        shower_result.h_max_uncert = errors[5] * shower_result.h_max

        shower_result.goodness_of_fit = np.nan
        shower_result.tel_ids = list(self.image.keys())

        energy_result = ReconstructedEnergyContainer()
        energy_result.energy = fit_params[4] * u.TeV
        energy_result.energy_uncert = errors[4] * u.TeV
        energy_result.is_valid = True
        energy_result.tel_ids = list(self.image.keys())
        # Return interesting stuff

        return shower_result, energy_result