Пример #1
0
/***********************************************************************//**
 * @brief Return normalization of radial source for Monte Carlo simulations
 *
 * @param[in] dir Centre of simulation cone.
 * @param[in] radius Radius of simulation cone (degrees).
 * @return Normalization.
 *
 * Returns the normalization for a radial source within a circular region.
 * The normalization is 1 if the radial source falls within the circle
 * defined by @p dir and @p radius, 0 otherwise.
 ***************************************************************************/
inline
double GModelSpatialRadial::mc_norm(const GSkyDir& dir,
                                    const double&  radius) const
{
    double norm = (dir.dist_deg(this->dir()) <= radius+theta_max()) ? 1.0 : 0.0;
    return (norm);
}
Пример #2
0
/***********************************************************************//**
 * @brief Checks where model contains specified sky direction
 *
 * @param[in] dir Sky direction.
 * @param[in] margin Margin to be added to sky direction (degrees)
 * @return True if the model contains the sky direction.
 *
 * Signals whether a sky direction is contained in the radial gauss model.
 ***************************************************************************/
bool GModelSpatialRadialGauss::contains(const GSkyDir& dir,
                                        const double&  margin) const
{
    // Compute distance to centre (radians)
    double distance = dir.dist(this->dir());

    // Return flag
    return (distance <= theta_max() + margin*gammalib::deg2rad);
}
/***********************************************************************//**
 * @brief Evaluate function (in units of sr^-1)
 *
 * @param[in] theta Angular distance from disk centre (radians).
 * @param[in] posangle Position angle (counterclockwise from North) (radians).
 * @param[in] energy Photon energy.
 * @param[in] time Photon arrival time.
 * @return Model value.
 *
 * Evaluates the spatial component for an elliptical disk source model. The
 * disk source model is an elliptical function
 * \f$S_{\rm p}(\theta, \phi | E, t)\f$, where
 * \f$\theta\f$ is the angular separation between elliptical disk centre and
 * the actual location and \f$\phi\f$ the position angle with respect to the
 * ellipse centre, counted counterclockwise from North.
 *
 * The function \f$f(\theta, \phi)\f$ is given by
 *
 * \f[
 * S_{\rm p}(\theta, \phi | E, t) = \left \{
 *  \begin{array}{l l}
 *     {\tt m\_norm}
 *     & \mbox{if} \, \, \theta \le \theta_0 \\
 *     \\
 *     0 & \mbox{else}
 *  \end{array}
 *  \right .
 * \f]
 *
 * where \f$\theta_0\f$ is the effective radius of the ellipse on the sphere
 * given by
 *
 * \f[\theta_0\ =
 *    \frac{ab}{\sqrt{b^2 \cos^2(\phi-\phi_0) + a^2 \sin^2(\phi-\phi_0)}}\f]
 *
 * and
 * \f$a\f$ is the semi-major axis of the ellipse,
 * \f$b\f$ is the semi-minor axis, and
 * \f$\phi_0\f$ is the position angle of the ellipse, counted
 * counterclockwise from North.
 *
 * The normalisation constant \f${\tt m\_norm}\f$ which is the inverse of the
 * solid angle subtended by an ellipse is given by
 *
 * @todo Quote formula for ellipse solid angle
 *
 * (see the update() method).
 ***************************************************************************/
double GModelSpatialEllipticalDisk::eval(const double&  theta,
                                         const double&  posangle,
                                         const GEnergy& energy,
                                         const GTime&   time) const
{
    // Initialise value
    double value = 0.0;

    // Continue only if we're inside circle enclosing the ellipse
    if (theta <= theta_max()) {

        // Update precomputation cache
        update();

        // Perform computations
        double diff_angle = posangle - m_posangle.value() * gammalib::deg2rad;
        double cosinus    = std::cos(diff_angle);
        double sinus      = std::sin(diff_angle);
        double arg1       = m_semiminor_rad * cosinus;
        double arg2       = m_semimajor_rad * sinus;
        double r_ell      = m_semiminor_rad * m_semimajor_rad /
                            std::sqrt(arg1*arg1 + arg2*arg2);

        // Set value
        value = (theta <= r_ell) ? m_norm : 0.0;

        // Compile option: Check for NaN/Inf
        #if defined(G_NAN_CHECK)
        if (gammalib::is_notanumber(value) || gammalib::is_infinite(value)) {
            std::cout << "*** ERROR: GModelSpatialEllipticalDisk::eval";
            std::cout << "(theta=" << theta << "): NaN/Inf encountered";
            std::cout << "(posangle=" << posangle << "): NaN/Inf encountered";
            std::cout << " (value=" << value;
            std::cout << ", R_ellipse=" << r_ell;
            std::cout << ", diff_angle=" << diff_angle;
            std::cout << ", m_norm=" << m_norm;
            std::cout << ")" << std::endl;
        }
        #endif

    } // endif: position was inside enclosing circle

    // Return value
    return value;
}
Пример #4
0
/***********************************************************************//**
 * @brief Evaluate function (in units of sr^-1)
 *
 * @param[in] theta Angular distance from disk centre (radians).
 * @param[in] posangle Position angle (counterclockwise from North) (radians).
 * @param[in] energy Photon energy.
 * @param[in] time Photon arrival time.
 * @return Model value.
 *
 * Evaluates the spatial component for an elliptical Gaussian source model.
 *
 * The elliptical Gaussian function is defined by
 * \f$S_{\rm p}(\theta, \phi | E, t)\f$, where
 * \f$\theta\f$ is the angular separation between elliptical Gaussian centre
 * and the actual location and \f$\phi\f$ the position angle with respect to
 * the model centre, counted counterclockwise from North.
 *
 * The function \f$S_{\rm p}(\theta, \phi | E, t)\f$ is given by
 *
 * \f[
 * S_{\rm p}(\theta, \phi | E, t) = {\tt m\_norm} \times
 * \exp \left( -\frac{\theta^2}{2 r_{\rm eff}^2} \right)
 * \f]
 *
 * where the effective ellipse radius \f$r_{\rm eff}\f$ towards a given
 * position angle is given by
 *
 * \f[
 * r_{\rm eff} = \frac{ab}
 *                   {\sqrt{\left( a \sin (\phi - \phi_0) \right)^2} +
 *                    \sqrt{\left( b \cos (\phi - \phi_0) \right)^2}}
 * \f]
 * and  
 * \f$a\f$ is the semi-major axis of the ellipse,
 * \f$b\f$ is the semi-minor axis, and
 * \f$\phi_0\f$ is the position angle of the ellipse, counted
 * counterclockwise from North.
 * \f${\tt m\_norm}\f$ is a normalization constant given by
 *
 * \f[
 *    {\tt m\_norm} = \frac{1}{2 \pi \times a \times b}
 * \f]
 *
 * @warning
 * The above formula for an elliptical Gaussian are accurate for small
 * angles, with semimajor and semiminor axes below a few degrees. This
 * should be fine for most use cases, but you should be aware that the
 * ellipse will get distorted for larger angles.
 *
 * @warning
 * For numerical reasons the elliptical Gaussian will be truncated for
 * \f$\theta\f$ angles that correspond to 3.0 times the effective ellipse
 * radius.
 ***************************************************************************/
double GModelSpatialEllipticalGauss::eval(const double&  theta,
                                          const double&  posangle,
                                          const GEnergy& energy,
                                          const GTime&   time) const
{
    // Initialise value
    double value = 0.0;

    // Continue only if we're inside circle enclosing the ellipse
    if (theta <= theta_max()) {

        // Update precomputation cache
        update();

        // Perform computations to compute exponent
        #if defined(G_SMALL_ANGLE_APPROXIMATION)
        double rel_posangle  = posangle - this->posangle() * gammalib::deg2rad;
        double cosinus       = std::cos(rel_posangle);
        double sinus         = std::sin(rel_posangle);
        double arg1          = m_minor_rad * cosinus;
        double arg2          = m_major_rad * sinus;
        double r_ellipse     = m_minor_rad * m_major_rad /
                               std::sqrt(arg1*arg1 + arg2*arg2); //!< small angle
        double r_relative    = theta/r_ellipse;
        double exponent      = 0.5*r_relative*r_relative;
        #else
        // Perform computations
        double sinphi = std::sin(posangle);
        double cosphi = std::cos(posangle);

        // Compute help term
        double term1 = m_term1 * cosphi * cosphi;
        double term2 = m_term2 * sinphi * sinphi;
        double term3 = m_term3 * sinphi * cosphi;

        // Compute exponent
        double exponent = theta * theta * (term1 + term2 + term3);        
        #endif

        // Set value if the exponent is within the truncation region
        if (exponent <= c_max_exponent) {
            value = m_norm * std::exp(-exponent);
        }

        // Compile option: Check for NaN/Inf
        #if defined(G_NAN_CHECK)
        if (gammalib::is_notanumber(value) || gammalib::is_infinite(value)) {
            std::cout << "*** ERROR: GModelSpatialEllipticalGauss::eval";
            std::cout << "(theta=" << theta << "): NaN/Inf encountered";
            std::cout << "(posangle=" << posangle << "): NaN/Inf encountered";
            std::cout << " (value=" << value;
            std::cout << ", MinorAxis^2=" << m_minor2;
            std::cout << ", MaxjorAxis^2=" << m_major2;
            std::cout << ", m_norm=" << m_norm;
            std::cout << ")" << std::endl;
        }
        #endif

    } // endif: position was inside enclosing circle

    // Return value
    return value;
}