Example #1
0
    def show_projection(self, track, axes=True, max_theta=30., X_mark=None):
        """
        Obtain the polar coordinates of a shower track relative to a telescope
        position in both horizontal and FoV coordinates systems and determine
        the fraction of the track within the telescope field of view.
        In addition, show the projection of the shower track as viewed by the
        telescope.

        Parameters
        ----------
        track : Track object or Shower object.
        axes : bool, default True
            Show the axes of both coordinate systems of reference.
        max_theta : float, default 30 degrees
            Maximum offset angle in degrees relative to the telescope
            pointing direction.
        X_mark : float
            Reference slant depth in g/cm^2 of the shower track to be
            marked in the figure. If None, no mark is included.

        Returns
        -------
        Projection object.
        (ax1, ax2) : PolarAxesSubplot objects.

        See also
        --------
        Projection.show
        """
        projection = sm.Projection(self, track)
        from ._tools import show_projection
        return projection, (show_projection(projection, None, False, axes,
                                            max_theta, X_mark))
Example #2
0
    def Projection(self, track):
        """
        Obtain the coordinates of a shower track relative to the telescope
        position in both zenith and camera projection and determine the
        fraction of the track within the telescope field of view.

        Parameters
        ----------
        track : Track object or Shower object.

        Returns
        -------
        Projection object.

        See also
        --------
        Projection.show
        """
        return sm.Projection(self, track)
Example #3
0
    def Projection(self, telescope):
        """
        Obtain the coordinates of a shower track relative to a telescope
        position in both zenith and camera projection and determine the
        fraction of the track within the telescope field of view.

        Parameters
        ----------
        telescope : Telescope object.

        Returns
        -------
        Projection object.
        (ax1, ax2) : AxesSubplot objects.

        See also
        --------
        Projection.show
        """
        return sm.Projection(telescope, self.track)
Example #4
0
    def show_projection(self,
                        telescope,
                        shower_size=True,
                        axes=True,
                        max_theta=30.,
                        X_mark='X_max'):
        """
        Make a Projection object and show it.

        Parameters
        ----------
        telescope : Telescope object.
        shower_size : book, default True
            Make the radii of the shower track points proportional to the
            shower size.
        axes : book, default True
            Show the axes of both frames of reference.
        max_theta : float, default 30 degrees
            Maximum offset angle in degrees relative to the telescope
            pointing direction.
        X_mark : float
            Reference slant depth in g/cm^2 of the shower track to be ma
            ked in the figure, default X_max. If X_mark=None, no mark is
            included.

        Returns
        -------
        Projection object.
        (ax1, ax2) : PolarAxesSubpot objects.

        See also
        --------
        Projection.show
        """
        if X_mark == 'X_max':
            X_mark = self.X_max
        projection = sm.Projection(telescope, self.track)
        profile = self.profile
        from ._tools import show_projection
        return projection, (show_projection(projection, profile, shower_size,
                                            axes, max_theta, X_mark))
Example #5
0
def Signal(telescope,
           shower,
           projection=None,
           atm_trans=True,
           tel_eff=True,
           **kwargs):
    """
    Calculate the signal produced by a shower detected by a telescope.

    Parameters
    ----------
    telescope : Telescope object.
    shower : Shower object.
    projection : Projection object
        If None, it will generated from telescope and shower.
    atm_trans : bool, default True
        Include the atmospheric transmision to transport photons.
    tel_eff : bool, default True
        Include the telescope efficiency to calculate the signal. If False,
        100% efficiency is assumed for a given wavelenght interval.
    **kwargs {wvl_ini, wvl_fin, wvl_step}
        These parameters will modify the wavelenght interval when
        tel_eff==False. If None, the wavelength interval defined in the
        telescope is used.

    Returns
    -------
    signal : Signal object.
    """
    from .telescope import _Telescope
    from .shower import _Shower
    if not isinstance(telescope, _Telescope):
        if not isinstance(telescope, _Shower):
            raise ValueError('The input telescope is not valid')
        else:
            telescope, shower = (shower, telescope)
    if not isinstance(shower, _Shower):
        raise ValueError('The input shower is not valid')

    # This function is normally called from Event. If not, projection must be
    # generated.
    from .projection import _Projection
    if not isinstance(projection, _Projection):
        projection = sm.Projection(telescope, shower.track)
    atmosphere = shower.atmosphere
    track = shower.track
    fluorescence = shower.fluorescence
    cherenkov = shower.cherenkov

    signal = _Signal()
    signal.shower = shower
    signal.telescope = telescope
    signal.projection = projection
    signal.atmosphere = atmosphere
    signal.track = track
    signal.profile = shower.profile
    signal.fluorescence = fluorescence
    signal.cherenkov = cherenkov

    signal.atm_trans = atm_trans
    signal.tel_eff = tel_eff

    if tel_eff:
        # Wavelenght range to calculate the signal
        wvl_ini = telescope.wvl_ini
        wvl_fin = telescope.wvl_fin
        wvl_step = telescope.wvl_step
        wvl_cher = telescope.wvl_cher
        eff_fluo = telescope.eff_fluo
        eff_cher = telescope.eff_cher
    else:
        # User-defined wavalength range
        wvl_ini = kwargs.get('wvl_ini', telescope.wvl_ini)
        wvl_fin = kwargs.get('wvl_fin', telescope.wvl_fin)
        wvl_step = kwargs.get('wvl_step', telescope.wvl_step)
        wvl_cher = np.arange(wvl_ini, wvl_fin, wvl_step)
    signal.wvl_ini = wvl_ini
    signal.wvl_fin = wvl_fin
    signal.wvl_step = wvl_step

    # Only discretization points within the telescope field of view contributes
    # to the signal. In addition, the very begninning of the shower profile is
    # ignored to speed up calculations
    points = projection[projection.FoV & (signal.profile.s > 0.01)].index
    distance = np.array(projection.distance.loc[points])
    theta = np.radians(projection.theta.loc[points])
    alt = np.radians(projection.alt.loc[points])

    # Solid angle fraction covered by the telescope area. Only discretization
    # points within the telescope field of view contributes to the signal
    collection = (telescope.area * np.cos(theta) / 4000000. / np.pi /
                  distance**2)

    # Collection efficiency for the angular distribution of Cherenkov light
    # See F. Nerling et al., Astropart. Phys. 24(2006)241.
    beta = np.radians(projection.beta.loc[points])
    theta_c = np.radians(cherenkov.theta_c.loc[points])
    theta_cc = np.radians(cherenkov.theta_cc.loc[points])
    a = np.array(cherenkov.a.loc[points])
    b = np.array(cherenkov.b.loc[points])
    collection_cher = collection * 2. / np.sin(beta) * (
        a / theta_c * np.exp(-beta / theta_c) +
        b / theta_cc * np.exp(-beta / theta_cc))

    # Relative fluorescence contribution from each shower point at each band
    # (between wvl_ini and wvl_fin). The atmospheric transmission is included
    # later
    rel_fluo = fluorescence.loc[points]
    if tel_eff:
        rel_fluo *= eff_fluo  # 34 bands
    # Selection of bands within the wavelenght range
    rel_fluo = rel_fluo.loc[:, wvl_ini:wvl_fin]

    if atm_trans:
        # Atmospheric transmission at 350 nm. Only Rayleigh scattering is
        # considered
        X_vert = np.array(atmosphere.X_vert.loc[points])
        rho = np.array(atmosphere.rho.loc[points])
        thickness = np.array(
            atmosphere.h_to_Xv(atmosphere.h0 + telescope.z) - X_vert)
        thickness[thickness != 0] = (thickness[thickness != 0] /
                                     np.sin(alt[thickness != 0]))
        thickness[thickness == 0] = (100000. * distance[thickness == 0] *
                                     rho[thickness == 0])
        # Only points within the telescope FoV, otherwise trans=0
        trans = np.exp(-thickness / 1645.)

        # Relative fluorescence contribution including atmospheric transmission
        for wvl in rel_fluo:
            rel_fluo[wvl] *= trans**((350. / wvl)**4)

        # Wavelenght factor for Cherenkov contribution to signal from each
        # shower point
        wvl_factor = pd.DataFrame(index=points)
        for wvl in wvl_cher:
            wvl_factor[wvl] = trans**((350. / wvl)**4) / wvl**2
            # wvl**2 -> (wvl**2 - wvl_step**2 / 4.)
        if tel_eff:
            wvl_factor *= eff_cher
        wvl_factor = wvl_factor.sum(axis=1) * wvl_step / (1. / 290. -
                                                          1. / 430.)

    elif tel_eff:  # If atmospheric transmission is not included
        # The wavelength factor of Cherenkov signal is the same for all
        # shower points
        wvl_factor = eff_cher / wvl_cher**2
        # wvl_cher**2 -> (wvl_cher**2 - wvl_step**2 / 4.)
        wvl_factor = wvl_factor.sum() * wvl_step / (1. / 290. - 1. / 430.)

    # If neither the atmospheric transmission nor the telescope efficiency are
    # included
    else:
        # The wavelength factor of Cherenkov signal only depends on the
        # integration wavelength interval
        wvl_factor = (1. / wvl_ini - 1. / wvl_fin) / (1. / 290. - 1. / 430.)

    # Number of photoelectrons due to fluorescence light emitted from each
    # shower point
    signal['Npe_fluo'] = rel_fluo.sum(axis=1) * collection
    # Number of photoelectrons due to fluorescence light within the FoV
    signal.Npe_fluo_sum = signal.Npe_fluo.sum()
    # Number of photoelectrons due to Cherenkov light emitted from each shower
    # point
    signal['Npe_cher'] = (cherenkov.N_ph.loc[points] * collection_cher *
                          wvl_factor)
    # Number of photoelectrons due to Cherenkov light within the FoV
    signal.Npe_cher_sum = signal.Npe_cher.sum()
    # Total number of photoelectrons from both light components emitted at each
    # shower point
    signal['Npe_total'] = signal.sum(axis=1)
    # Total number of photoelectrons
    signal.Npe_total_sum = signal.Npe_cher_sum + signal.Npe_fluo_sum

    return signal
Example #6
0
def Event(observatory, shower, atm_trans=True, tel_eff=True, **kwargs):
    """
    Construct an Event object from a shower and an observatory.
    
    The Event objet contains the signal produced by the shower in each
    telescope of the observatory.

    Parameters
    ----------
    observatory : Observatory object (may be a Grid object).
    shower : Shower object.
    atm_trans : bool, default True
        Include the atmospheric transmision to transport photons.
    tel_eff : bool, default True
        Include the telescope efficiency to calculate the signals.
        If False, 100% efficiency is assumed for a given wavelength interval.
    **kwargs {wvl_ini, wvl_fin, wvl_step}
        These parameters will be passed to the Signal constructor to modify
        the wavelength interval when tel_eff==False. If None, the wavelength
        interval defined in each telescope is used.

    Returns
    -------
    event : Event object.
    """
    from .observatory import _Observatory, _Grid
    from .telescope import _Telescope
    from .shower import _Shower
    if not isinstance(shower, _Shower):
        observatory, shower = (shower, observatory)
        if not isinstance(shower, _Shower):
            raise ValueError('The input shower is not valid')

    if isinstance(observatory, (_Telescope, _Observatory)):
        if isinstance(observatory, _Grid):
            event = _GridEvent()
            event.grid = observatory
        else:
            event = _Event()
            if isinstance(observatory, _Telescope):
                telescope = observatory
                event.observatory = _Observatory()
                event.observatory.append(telescope)
            else:
                event.observatory = observatory
    else:
        raise ValueError('The input observatory is not valid')

    event.shower = shower
    event.atmosphere = shower.atmosphere
    event.track = shower.track
    event.profile = shower.profile
    event.cherenkov = shower.cherenkov
    event.fluorescence = shower.fluorescence

    event.atm_trans = atm_trans
    event.tel_eff = tel_eff

    event.projections = []
    event.signals = []
    for telescope in observatory:
        projection = sm.Projection(telescope, event.track)
        event.projections.append(projection)
        signal = sm.Signal(telescope, shower, projection, atm_trans, tel_eff,
                           **kwargs)
        event.signals.append(signal)

    event.images = None

    return event