Exemple #1
0
/***********************************************************************//**
 * @brief Return point spread function (in units of sr^-1)
 *
 * @param[in] delta Angular separation between true and measured photon
 *            directions (rad).
 * @param[in] logE Log10 of the true photon energy (TeV).
 * @param[in] theta Offset angle in camera system (rad).
 * @param[in] phi Azimuth angle in camera system (rad). Not used.
 * @param[in] zenith Zenith angle in Earth system (rad). Not used.
 * @param[in] azimuth Azimuth angle in Earth system (rad). Not used.
 * @param[in] etrue Use true energy (true/false). Not used.
 *
 * Returns the point spread function for a given angular separation in units
 * of sr^-1 for a given energy and offset angle. The PSF value will be
 * determined by trilinear interpolation (and extrapolation) in the PSF
 * histograms. If the interpolation or extrapolation would lead to negative
 * PSF values, the value of zero is returned. A zero value is also returned
 * if the @p delta angle is larger than the largest angle in the response
 * table.
 ***************************************************************************/
double GCTAPsfTable::operator()(const double& delta,
                                const double& logE,
                                const double& theta,
                                const double& phi,
                                const double& zenith,
                                const double& azimuth,
                                const bool&   etrue) const
{
    // Initialise PSF value
    double psf = 0.0;

    // Continue only if delta is not larger than delta_max
    if (delta <= m_delta_max) {

        // Setup argument vector
        double arg[3];
        arg[m_inx_energy] = logE;
        arg[m_inx_theta]  = theta;
        arg[m_inx_delta]  = delta;

        // Compute point spread function by trilinear interpolation
        psf = m_psf(m_inx_rpsf, arg[0], arg[1], arg[2]);

        // Constrain PSF value to non-negative values
        if (psf < 0.0) {
            psf = 0.0;
        }

    } // endif: delta was within validity range

    // Return PSF
    return psf;
}
Exemple #2
0
/***********************************************************************//**
 * @brief Update PSF parameter cache
 *
 * @param[in] logE Log10 of the true photon energy (TeV).
 * @param[in] theta Offset angle in camera system (rad).
 *
 * This method updates the PSF parameter cache.
 ***************************************************************************/
void GCTAPsf2D::update(const double& logE, const double& theta) const
{
    // Only compute PSF parameters if arguments have changed
    if (logE != m_par_logE || theta != m_par_theta) {

        // Save parameters
        m_par_logE  = logE;
        m_par_theta = theta;

        // Interpolate response parameters
        std::vector<double> pars = m_psf(logE, theta);

        // Set Gaussian sigmas
        m_sigma1 = pars[1];
        m_sigma2 = pars[3];
        m_sigma3 = pars[5];

        // Set width parameters
        double sigma1 = m_sigma1 * m_sigma1;
        double sigma2 = m_sigma2 * m_sigma2;
        double sigma3 = m_sigma3 * m_sigma3;

        // Compute Gaussian 1
        if (sigma1 > 0.0) {
            m_width1 = -0.5 / sigma1;
        }
        else {
            m_width1 = 0.0;
        }

        // Compute Gaussian 2
        if (sigma2 > 0.0) {
            m_width2 = -0.5 / sigma2;
            m_norm2  = pars[2];
        }
        else {
            m_width2 = 0.0;
            m_norm2  = 0.0;
        }

        // Compute Gaussian 3
        if (sigma3 > 0.0) {
            m_width3 = -0.5 / sigma3;
            m_norm3  = pars[4];
        }
        else {
            m_width3 = 0.0;
            m_norm3  = 0.0;
        }

        // Compute global normalization parameter
        double integral = gammalib::twopi * (sigma1 + sigma2*m_norm2 + sigma3*m_norm3);
        m_norm = (integral > 0.0) ? 1.0 / integral : 0.0;

    }

    // Return
    return;
}
Exemple #3
0
/***********************************************************************//**
 * @brief Performs precomputations for point spread function
 *
 * Replaces any invalid PSF histogram by zeroes, normalises the PSF
 * histograms to unity, and computes maximum PSF value and maximum delta
 * value.
 ***************************************************************************/
void GCTAPsfTable::precompute(void)
{
    // Determine PSF dimensions
    int neng   = m_psf.axis_bins(m_inx_energy);
    int ntheta = m_psf.axis_bins(m_inx_theta);
    int ndelta = m_psf.axis_bins(m_inx_delta);

    // Determine delta element increment
    int inx_inc = element(0,0,1) - element(0,0,0);

    // Replace any negative or invalid histogram values by zero values
    for (int i = 0; i < m_psf.elements(); ++i) {
        double element = m_psf(m_inx_rpsf, i);
        if (element < 0.0 ||
            gammalib::is_notanumber(element) ||
            gammalib::is_infinite(element)) {
            m_psf(m_inx_rpsf, i) = 0.0;
        }
    }

    // Normalise PSF to unity
    for (int ieng = 0; ieng < neng; ++ieng) {
        for (int itheta = 0; itheta < ntheta; ++itheta) {

            // Initialise PSF integral
            double sum = 0.0;

            // Set start element
            int inx = element(ieng, itheta, 0);

            // Integrate delta array by computing the sum over the pixels
            // times the pixel size time the delta angle
            for (int idelta = 0; idelta < ndelta; ++idelta, inx += inx_inc) {

                // Compute delta value (radians)
                double delta = m_psf.axis_nodes(m_inx_delta)[idelta];

                // Compute delta bin width (radians)
                double width = (m_psf.axis_hi(m_inx_delta, idelta) -
                                m_psf.axis_lo(m_inx_delta, idelta)) *
                                gammalib::deg2rad;

                // Integrate PSF
                sum += m_psf(m_inx_rpsf, inx) * std::sin(delta) * width *
                       gammalib::twopi;

            }

            // If integral is positive then divide PSF by integral so that it
            // normalises to unity
            if (sum > 0.0) {

                // Set start element
                int inx = element(ieng, itheta, 0);

                // Normalise PSF
                for (int idelta = 0; idelta < ndelta; ++idelta, inx += inx_inc) {
                    m_psf(m_inx_rpsf, inx) /= sum;
                }

            } // endif: PSF integral was positive

        } // endfor: looped over all theta angles
    } // endfor: looped over all PSF values

    // Compute maximum PSF value
    m_psf_max = 0.0;
    for (int i = 0; i < m_psf.elements(); ++i) {
        if (m_psf(m_inx_rpsf, i) > m_psf_max) {
            m_psf_max = m_psf(m_inx_rpsf, i);
        }
    }

    // Set maximum PSF radius (radians)
    m_delta_max = m_psf.axis_hi(m_inx_delta, m_psf.axis_bins(m_inx_delta)-1) *
                  gammalib::deg2rad;

    // Return
    return;
}