コード例 #1
0
ファイル: GLATLtCubeMap.cpp プロジェクト: gammalib/gammalib
/***********************************************************************//**
 * @brief Sum effective area multiplied by livetime over zenith and
 *        (optionally) azimuth angles
 *
 * @param[in] dir True sky direction.
 * @param[in] energy True photon energy.
 * @param[in] aeff Effective area.
 *
 * Computes
 * \f[\sum_{\cos \theta, \phi} T_{\rm live}(\cos \theta, \phi) 
 *    A_{\rm eff}(\log E, \cos \theta, \phi)\f]
 * where
 * \f$T_{\rm live}(\cos \theta, \phi)\f$ is the livetime as a function of
 * the cosine of the zenith and the azimuth angle, and
 * \f$A_{\rm eff}(\log E, \cos \theta, \phi)\f$ is the effective area that
 * depends on
 * the log10 of the energy (in MeV),
 * the cosine of the zenith angle, and
 * the azimuth angle.
 * This method assumes that \f$T_{\rm live}(\cos \theta, \phi)\f$ is
 * stored as a set of maps in a 2D array with \f$\cos \theta\f$ being the
 * most rapidely varying parameter and with the first map starting at
 * index m_num_ctheta (the first m_num_ctheta maps are the livetime cube
 * maps without any \f$\phi\f$ dependence).
 ***************************************************************************/
double GLATLtCubeMap::operator()(const GSkyDir& dir, const GEnergy& energy,
                                 const GLATAeff& aeff) const
{
    // Get map index
    int pixel = m_map.dir2pix(dir);

    // Initialise sum
    double sum = 0.0;

    // Circumvent const correctness
    GLATAeff* fct = ((GLATAeff*)&aeff);

    // If livetime cube and response have phi dependence then sum over
    // zenith and azimuth. Note that the map index starts with m_num_ctheta
    // as the first m_num_ctheta maps correspond to an evaluation without
    // any phi-dependence.
    if (has_phi() && aeff.has_phi()) {
        for (int iphi = 0, i = m_num_ctheta; iphi < m_num_phi; ++iphi) {
            double p = phi(iphi);
            for (int itheta = 0; itheta < m_num_ctheta; ++itheta, ++i) {
                sum += m_map(pixel, i) * (*fct)(energy.log10MeV(), costheta(i), p);
            }
        }
    }

    // ... otherwise sum only over zenith angle
    else {
        for (int i = 0; i < m_num_ctheta; ++i) {
            sum += m_map(pixel, i) * (*fct)(energy.log10MeV(), costheta(i));
        }
    }

    // Return sum
    return sum;
}
コード例 #2
0
/***********************************************************************//**
 * @brief Return exponential cut-off energy
 *
 * @return Exponential cut-off energy.
 *
 * Returns the exponential cut-off energy.
 ***************************************************************************/
inline
GEnergy GModelSpectralSuperExpPlaw::cutoff(void) const
{
    GEnergy energy;
    energy.MeV(m_ecut.value());
    return energy;
}
コード例 #3
0
/***********************************************************************//**
 * @brief Return maximum energy
 *
 * @return Maximum energy.
 *
 * Returns the maximum energy.
 ***************************************************************************/
inline
GEnergy GModelSpectralPlaw2::emax(void) const
{
    GEnergy energy;
    energy.MeV(m_emax.value());
    return energy;
}
コード例 #4
0
/***********************************************************************//**
 * @brief Returns model energy flux between [emin, emax] (units: erg/cm2/s)
 *
 * @param[in] emin Minimum photon energy.
 * @param[in] emax Maximum photon energy.
 * @return Energy flux (erg/cm2/s).
 *
 * Computes
 *
 * \f[
 *    \int_{\tt emin}^{\tt emax} S_{\rm E}(E | t) E \, dE
 * \f]
 *
 * where
 * - [@p emin, @p emax] is an energy interval, and
 * - \f$S_{\rm E}(E | t)\f$ is the spectral model (ph/cm2/s/MeV).
 * The integration is done numerically.
 ***************************************************************************/
double GModelSpectralSmoothBrokenPlaw::eflux(const GEnergy& emin,
                                             const GEnergy& emax) const
{
    // Initialise flux
    double eflux = 0.0;
    
    // Compute only if integration range is valid
    if (emin < emax) {
        
        // Initialise function to integrate
        eflux_kern kernel(prefactor(), index1(), pivot(),
                          index2(), breakenergy(), beta());
        
        // Initialise integral class with function
        GIntegral integral(&kernel);
        
        // Set integration precision
        integral.eps(1.0e-8);
        
        // Calculate integral between emin and emax
        eflux = integral.romberg(emin.MeV(), emax.MeV());
        
        // Convert from MeV/cm2/s to erg/cm2/s
        eflux *= gammalib::MeV2erg;
        
    } // endif: integration range was valid
    
    // Return flux
    return eflux;
}
コード例 #5
0
/***********************************************************************//**
 * @brief Returns map cube energies
 *
 * @return Map cube energies.
 *
 * Returns the energies for the map cube in a vector.
 ***************************************************************************/
GEnergies GModelSpatialDiffuseCube::energies(void)
{
    // Initialise energies container
    GEnergies energies;

    // Fetch cube
    fetch_cube();

    // Get number of map energies
    int num = m_logE.size();

    // Continue only if there are maps in the cube
    if (num > 0) {

        // Reserve space for all energies
        energies.reserve(num);

        // Set log10(energy) nodes, where energy is in units of MeV
        for (int i = 0; i < num; ++i) {
            GEnergy energy;
            energy.log10MeV(m_logE[i]);
            energies.append(energy);
        }

    } // endif: there were maps in the cube

    // Return energies
    return energies;
}
コード例 #6
0
/***********************************************************************//**
 * @brief Return pivot energy
 *
 * @return Pivot energy.
 *
 * Returns the pivot energy.
 ***************************************************************************/
inline
GEnergy GModelSpectralPlaw::pivot(void) const
{
    GEnergy energy;
    energy.MeV(m_pivot.value());
    return energy;
}
コード例 #7
0
ファイル: test_CTA.cpp プロジェクト: adonath/gammalib
/***********************************************************************//**
 * @brief Test CTA Npred computation
 *
 * Tests the Npred computation for the diffuse source model. This is done
 * by loading the model from the XML file and by calling the
 * GCTAObservation::npred method which in turn calls the
 * GCTAResponse::npred_diffuse method. The test takes a few seconds.
 ***************************************************************************/
void TestGCTAResponse::test_response_npred_diffuse(void)
{
    // Set reference value
    double ref = 11212.26274;

    // Set parameters
    double src_ra  = 201.3651;
    double src_dec = -43.0191;
    double roi_rad =   4.0;

    // Setup ROI centred on Cen A with a radius of 4 deg
    GCTARoi     roi;
    GCTAInstDir instDir;
    instDir.radec_deg(src_ra, src_dec);
    roi.centre(instDir);
    roi.radius(roi_rad);

    // Setup pointing on Cen A
    GSkyDir skyDir;
    skyDir.radec_deg(src_ra, src_dec);
    GCTAPointing pnt;
    pnt.dir(skyDir);

    // Setup dummy event list
    GGti     gti;
    GEbounds ebounds;
    GTime    tstart(0.0);
    GTime    tstop(1800.0);
    GEnergy  emin;
    GEnergy  emax;
    emin.TeV(0.1);
    emax.TeV(100.0);
    gti.append(tstart, tstop);
    ebounds.append(emin, emax);
    GCTAEventList events;
    events.roi(roi);
    events.gti(gti);
    events.ebounds(ebounds);

    // Setup dummy CTA observation
    GCTAObservation obs;
    obs.ontime(1800.0);
    obs.livetime(1600.0);
    obs.deadc(1600.0/1800.0);
    obs.response(cta_irf, cta_caldb);
    obs.events(&events);
    obs.pointing(pnt);

    // Load models for Npred computation
    GModels models(cta_rsp_xml);

    // Perform Npred computation
    double npred = obs.npred(models, NULL);

    // Test Npred
    test_value(npred, ref, 1.0e-5, "Diffuse Npred computation");

    // Return
    return;
}
コード例 #8
0
/***********************************************************************//**
 * @brief Returns MC energy between [emin, emax]
 *
 * @param[in] emin Minimum photon energy.
 * @param[in] emax Maximum photon energy.
 * @param[in] time True photon arrival time.
 * @param[in,out] ran Random number generator.
 * @return Energy.
 *
 * @exception GException::erange_invalid
 *            Energy range is invalid (emin < emax required).
 *
 * Returns Monte Carlo energy by randomly drawing from a constant between
 * the minimum and maximum photon energy.
 *
 * Method Used: Box-Muller transform, outlined here:
 * http://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform
 *
 * Code from: http://www.design.caltech.edu/erik/Misc/Gaussian.html
 ***************************************************************************/
GEnergy GModelSpectralGauss::mc(const GEnergy& emin,
                                const GEnergy& emax,
                                const GTime&   time,
                                GRan&          ran) const
{
    // Get energy boundaries in MeV
	double xmax = emax.MeV();
	double xmin = emin.MeV();

    // Initialize return energy
	double energy = 0.0;

    // Throw an exception if energy range is invalid
    if (xmin >= xmax) {
        throw GException::erange_invalid(G_MC, xmin, xmax,
              "Minimum energy < maximum energy required.");
    }

    // Sample until we find a value within the requested energy range
    do {

        // Compute random value
    	double val = ran.normal();

    	// Scale to specified width and shift by mean value
    	energy = m_sigma.value() * val + m_mean.value();

    } while (energy < xmin || energy > xmax);


    // Return energy
    return GEnergy(energy, "MeV");
}
コード例 #9
0
/***********************************************************************//**
 * @brief Returns model photon flux between [emin, emax] (ph/cm2/s)
 *
 * @param[in] emin Minimum photon energy.
 * @param[in] emax Maximum photon energy.
 * @return Photon flux (ph/cm2/s).
 *
 * Computes
 *
 * \f[
 *    \int_{\tt emin}^{\tt emax} S_{\rm E}(E | t) dE
 * \f]
 *
 * where
 * - [@p emin, @p emax] is an energy interval, and
 * - \f$S_{\rm E}(E | t)\f$ is the spectral model (ph/cm2/s/MeV).
 * The integration is done analytically.
 ***************************************************************************/
double GModelSpectralGauss::flux(const GEnergy& emin,
                                 const GEnergy& emax) const
{
    // Initialise flux
    double flux = 0.0;
    
    // Compute only if integration range is valid
    if (emin < emax) {

        // Precomputations
        double energy_min = emin.MeV();
        double energy_max = emax.MeV();
        double norm       = m_norm.value();
        double mean       = m_mean.value();
        double sigma      = m_sigma.value();
        double denom      = 1.0 / (gammalib::sqrt_two*sigma);
        double zmin       = (energy_min - mean) * denom;
        double zmax       = (energy_max - mean) * denom;

        // Compute flux for a constant model
        flux = norm*(gammalib::erfcc(zmin) - gammalib::erfcc(zmax))/2.0;
    
    } // endif: integration range was valid

    // Return
    return flux;
}
コード例 #10
0
/***********************************************************************//**
 * @brief Returns model energy flux between [emin, emax] (units: erg/cm2/s)
 *
 * @param[in] emin Minimum photon energy.
 * @param[in] emax Maximum photon energy.
 * @return Energy flux (erg/cm2/s).
 *
 * Computes
 *
 * \f[
 *    \int_{\tt emin}^{\tt emax} S_{\rm E}(E | t) E \, dE
 * \f]
 *
 * where
 * - [@p emin, @p emax] is an energy interval, and
 * - \f$S_{\rm E}(E | t)\f$ is the spectral model (ph/cm2/s/MeV).
 * The integration is done numerically.
 ***************************************************************************/
double GModelSpectralExpPlaw::eflux(const GEnergy& emin,
                                    const GEnergy& emax) const
{
    // Initialise flux
    double eflux = 0.0;
    
    // Compute only if integration range is valid
    if (emin < emax) {

        // Setup integration kernel
        eflux_kernel integrand(m_norm.value(),  m_index.value(),
                               m_pivot.value(), m_ecut.value());
        GIntegral integral(&integrand);

        // Get integration boundaries in MeV
        double e_min = emin.MeV();
        double e_max = emax.MeV();

        // Perform integration
        eflux = integral.romberg(e_min, e_max);

        // Convert from MeV/cm2/s to erg/cm2/s
        eflux *= gammalib::MeV2erg;

    } // endif: integration range was valid

    // Return
    return eflux;
}
コード例 #11
0
/***********************************************************************//**
 * @brief Integration kernel for edisp_kern() method
 *
 * @param[in] x Function value.
 *
 * This method implements the integration kernel needed for the edisp_kern()
 * method.
 ***************************************************************************/
double GResponse::edisp_kern::eval(const double& x)
{
    // Set energy
    GEnergy eng;
    double expx = std::exp(x);
    eng.MeV(expx);

    // Get function value
    double value = m_parent->eval_prob(*m_model, *m_event, eng, m_srcTime, *m_obs, m_grad);

    // Save value if needed
    #if defined(G_NAN_CHECK)
    double value_out = value;
    #endif

    // Correct for variable substitution
    value *= expx;

    // Compile option: Check for NaN
    #if defined(G_NAN_CHECK)
    if (gammalib::is_notanumber(value) || gammalib::is_infinite(value)) {
        std::cout << "*** ERROR: GResponse::edisp_kern::eval";
        std::cout << "(x=" << x << "): ";
        std::cout << " NaN/Inf encountered";
        std::cout << " (value=" << value_out;
        std::cout << " exp(x)=" << expx;
        std::cout << ")" << std::endl;
    }
    #endif

    // Return value
    return value;
}
コード例 #12
0
ファイル: GMWLSpectrum.cpp プロジェクト: gammalib/gammalib
/***********************************************************************//**
 * @brief Convert value into flux
 *
 * @param[in] energy Energy at which flux is given.
 * @param[in] flux Flux value.
 * @param[in] unit Unit of value.
 *
 * @exception GMWLException::invalid_unit
 *            Invalid unit string encountered
 *
 * Converts a flux value into units of ph/cm2/s/MeV based on the specified
 * units. The following units are supported (case insensitive):
 * ph/cm2/s/MeV, ph/s/cm2/MeV, erg/cm2/s and erg/s/cm2.
 ***************************************************************************/
double GMWLSpectrum::conv_flux(const GEnergy& energy, const double& flux,
                               const std::string& unit)
{
    // Initialise energy
    double result;

    // Convert unit string to upper base without any leading/trailing
    // whitespace
    std::string str_unit = gammalib::strip_whitespace(gammalib::toupper(unit));

    // High-energy units
    if (str_unit == "PH/CM2/S/MEV" || str_unit == "PH/S/CM2/MEV") {
        result = flux;
    }
    else if (str_unit == "ERG/CM2/S" || str_unit == "ERG/S/CM2") {
        result = (gammalib::erg2MeV*flux) / (energy.MeV()*energy.MeV());
    }

    // ... otherwise throw exception
    else {
        throw GMWLException::invalid_unit(G_CONV_FLUX, unit);
    }

    // Return energy
    return result;
}
コード例 #13
0
/***********************************************************************//**
 * @brief Initialise Monte Carlo cache
 *
 * @todo Verify assumption made about the solid angles of the response table
 *       elements.
 * @todo Add optional sampling on a finer spatial grid.
 ***************************************************************************/
void GCTABackgroundPerfTable::init_mc_cache(void) const
{
    // Initialise cache
    m_mc_spectrum.clear();

    // Compute solid angle of model
    double solidangle = this->solidangle();

    // Loop over nodes
    for (int i = 0; i < size(); ++i) {

        // Set energy
        GEnergy energy;
        energy.log10TeV(m_logE[i]);

        // Compute total rate
        #if defined(G_LOG_INTERPOLATION)
        double total_rate = std::pow(10.0, m_background[i]) * solidangle;
        #else
        double total_rate = m_background[i] * solidangle;
        #endif

        // Set node
        if (total_rate > 0.0) {
            m_mc_spectrum.append(energy, total_rate);
        }

    }

    // Return
    return;
}
コード例 #14
0
/***********************************************************************//**
 * @brief Return breakenergy energy
 *
 * @return breakenergy energy.
 *
 * Returns the breakenergy energy.
 ***************************************************************************/
inline
GEnergy GModelSpectralBrokenPlaw::breakenergy(void) const
{
    GEnergy energy;
    energy.MeV(m_breakenergy.value());
    return energy;
}
コード例 #15
0
ファイル: test_CTA.cpp プロジェクト: adonath/gammalib
/***********************************************************************//**
 * @brief Test CTA psf computation
 *
 * The Psf computation is tested by integrating numerically the Psf
 * function. Integration is done in a rather simplistic way, by stepping
 * radially away from the centre. The integration is done for a set of
 * energies from 0.1-10 TeV.
 ***************************************************************************/
void TestGCTAResponse::test_response_psf(void)
{
    // Load response
    GCTAResponse rsp;
    rsp.caldb(cta_caldb);
    rsp.load(cta_irf);

    // Integrate Psf
    GEnergy eng;
    for (double e = 0.1; e < 10.0; e *= 2.0) {
        eng.TeV(e);
        double r     = 0.0;
        double dr    = 0.001;
        int    steps = int(1.0/dr);
        double sum   = 0.0;
        for (int i = 0; i < steps; ++i) {
            r   += dr;
            sum += rsp.psf(r*deg2rad, 0.0, 0.0, 0.0, 0.0, eng.log10TeV()) *
                   twopi * std::sin(r*deg2rad) * dr*deg2rad;
        }
        test_value(sum, 1.0, 0.001, "PSF integration for "+eng.print());
    }

    // Return
    return;
}
コード例 #16
0
/***********************************************************************//**
 * @brief Parameter constructor
 *
 * @param[in] prefactor Smoothly broken power law pre factor (ph/cm2/s/MeV).
 * @param[in] index1 Smoothly broken power law index1.
 * @param[in] pivot Smoothly broken power law pivot energy
 * @param[in] index2 Smoothly broken power law index1.
 * @param[in] breakenergy Break energy.
 * @param[in] beta Break smoothness parameter
 *
 * Constructs a smoothly broken power law using the model parameters
 * power law @p prefactor (ph/cm2/s/MeV),
 * spectral @p index1,
 * @p pivot energy,
 * spectral @p index2,
 * @p breakenergy of spectral break, and
 * smoothness parameter @p beta.
 ***************************************************************************/
GModelSpectralSmoothBrokenPlaw::GModelSpectralSmoothBrokenPlaw(
                                        const double&  prefactor,
                                        const double&  index1,
                                        const GEnergy& pivot,
                                        const double&  index2,
                                        const GEnergy& breakenergy,
                                        const double&  beta) :
                                GModelSpectral()
{
    // Initialise members
    init_members();
    
    // Set parameters
    m_norm.value(prefactor);
    m_index1.value(index1);
    m_pivot.value(pivot.MeV());              // Internally stored in MeV
    m_index2.value(index2);
    m_breakenergy.value(breakenergy.MeV());  // Internally stored in MeV
    m_beta.value(beta);
    
    // Perform autoscaling of parameter
    autoscale();
    
    // Return
    return;
}
コード例 #17
0
ファイル: GEbounds.cpp プロジェクト: TarekHC/gammalib
/***********************************************************************//**
 * @brief Insert energy interval
 *
 * @param[in] index Index after with interval is inserted.
 * @param[in] emin Minimum energy of interval.
 * @param[in] emax Maximum energy of interval.
 *
 * @exception GException::invalid_argument
 *            Minimum energy larger than maximum energy
 *
 * Inserts an energy interval after the specified @p index in the energy
 * boundaries. The method does not reorder the intervals by energy, instead
 * the client needs to determine the approriate @p index.
 *
 * Invalid parameters do not produce any exception, but are handled
 * transparently. If the interval is invalid (i.e. @p emin > @p emax) an
 * exception is thrown. If the @p index is out of the valid range, the
 * index will be adjusted to either the first or the last element.
 ***************************************************************************/
void GEbounds::insert_eng(const int&     index,
                          const GEnergy& emin,
                          const GEnergy& emax)
{
    // Throw an exception if energy interval is invalid
    if (emin > emax) {
        std::string msg = "Invalid energy interval specified. Minimum"
                          " energy "+emin.print(NORMAL)+" can not be"
                          " larger than maximum energy "+
                          emax.print(NORMAL)+".";
        throw GException::invalid_argument(G_INSERT_ENG, msg);
    }

    // Set index
    int inx = index;

    // If inx is out of range then adjust it
    if (inx < 0)     inx = 0;
    if (inx > m_num) inx = m_num;

    // Allocate new intervals
    int      num = m_num+1;
    GEnergy* min = new GEnergy[num];
    GEnergy* max = new GEnergy[num];

    // Copy intervals before index to be inserted
    for (int i = 0; i < inx; ++i) {
        min[i] = m_min[i];
        max[i] = m_max[i];
    }

    // Insert interval
    min[inx] = emin;
    max[inx] = emax;

    // Copy intervals after index to be inserted
    for (int i = inx+1; i < num; ++i) {
        min[i] = m_min[i-1];
        max[i] = m_max[i-1];
    }

    // Free memory
    if (m_min != NULL) delete [] m_min;
    if (m_max != NULL) delete [] m_max;

    // Set new memory
    m_min = min;
    m_max = max;

    // Set number of elements
    m_num = num;

    // Set attributes
    set_attributes();

    // Return
    return;
}
コード例 #18
0
/***********************************************************************//**
 * @brief Returns MC energy between [emin, emax]
 *
 * @param[in] emin Minimum photon energy.
 * @param[in] emax Maximum photon energy.
 * @param[in] ran Random number generator.
 * @return Energy.
 *
 * @exception GException::erange_invalid
 *            Energy range is invalid (emin < emax required).
 *
 * Simulates a random energy in the interval [emin, emax] for a spectral
 * function.
 ***************************************************************************/
GEnergy GModelSpectralFunc::mc(const GEnergy& emin, const GEnergy& emax,
                               GRan& ran) const
{
    // Throw an exception if energy range is invalid
    if (emin >= emax) {
        throw GException::erange_invalid(G_MC, emin.MeV(), emax.MeV(),
              "Minimum energy < maximum energy required.");
        
    }

    // Allocate energy
    GEnergy energy;
    
    // Continue only if emax > emin
    if (emax > emin) {
    
        // Update cache
        mc_update(emin, emax);

        // Determine in which bin we reside
        int inx = 0;
        if (m_mc_cum.size() > 1) {
            double u = ran.uniform();
            for (inx = m_mc_cum.size()-1; inx > 0; --inx) {
                if (m_mc_cum[inx-1] <= u) {
                    break;
                }
            }
        }

        // Get random energy for specific bin
        if (m_mc_exp[inx] != 0.0) {
            double e_min = m_mc_min[inx];
            double e_max = m_mc_max[inx];
            double u     = ran.uniform();
            double eng   = (u > 0.0) 
                            ? std::exp(std::log(u * (e_max - e_min) + e_min) / m_mc_exp[inx])
                            : 0.0;
            energy.MeV(eng);
        }
        else {
            double e_min = m_mc_min[inx];
            double e_max = m_mc_max[inx];
            double u     = ran.uniform();
            double eng   = std::exp(u * (e_max - e_min) + e_min);
            energy.MeV(eng);
        }

    } // endif: emax > emin
    
    // Return energy
    return energy;
}
コード例 #19
0
/***********************************************************************//**
 * @brief Update Monte Carlo pre computation cache
 *
 * @param[in] emin Minimum photon energy.
 * @param[in] emax Maximum photon energy.
 *
 * Updates the precomputation cache for Monte Carlo simulations.
 ***************************************************************************/
void GModelSpectralExpPlaw::update_mc_cache(const GEnergy& emin,
                                            const GEnergy& emax) const

{
    // Case A: Index is not -1
    if (index() != -1.0) {

        // Change in energy boundaries?
        if (emin.MeV() != m_mc_emin || emax.MeV() != m_mc_emax) {
            m_mc_emin       = emin.MeV();
            m_mc_emax       = emax.MeV();
            m_mc_exponent   = index() + 1.0;
            m_mc_pow_emin   = std::pow(m_mc_emin, m_mc_exponent);
            m_mc_pow_ewidth = std::pow(m_mc_emax, m_mc_exponent) - m_mc_pow_emin;
        }

    }

    // Case B: Index is -1
    else {

        // Change in energy boundaries?
        if (emin.MeV() != m_mc_emin || emax.MeV() != m_mc_emax) {
            m_mc_emin       = emin.MeV();
            m_mc_emax       = emax.MeV();
            m_mc_exponent   = 0.0;
            m_mc_pow_emin   = std::log(m_mc_emin);
            m_mc_pow_ewidth = std::log(m_mc_emax) - m_mc_pow_emin;
        }

    }

    // Return
    return;
}
コード例 #20
0
/***********************************************************************//**
 * @brief Returns model photon flux between [emin, emax] (units: ph/cm2/s)
 *
 * @param[in] emin Minimum photon energy.
 * @param[in] emax Maximum photon energy.
 * @return Photon flux (ph/cm2/s).
 *
 * @exception GException::erange_invalid
 *            Energy range is invalid (emin < emax required).
 *
 * Computes
 * \f[\int_{E_{\rm min}}^{E_{\rm max}} I(E) dE\f]
 * where
 * \f$E_{\rm min}\f$ and \f$E_{\rm max}\f$ are the minimum and maximum
 * energy, respectively, and
 * \f$I(E)\f$ is the spectral model (units: ph/cm2/s/MeV).
 * The integration is done analytically.
 ***************************************************************************/
double GModelSpectralConst::flux(const GEnergy& emin, const GEnergy& emax) const
{
    // Throw an exception if energy range is invalid
    if (emin >= emax) {
        throw GException::erange_invalid(G_FLUX, emin.MeV(), emax.MeV(),
              "Minimum energy < maximum energy required.");
        
    }

    // Compute flux for a constant model
    double flux = norm() * (emax.MeV() - emin.MeV());

    // Return
    return flux;
}
コード例 #21
0
/***********************************************************************//**
 * @brief Evaluate function and gradients
 *
 * @param[in] srcEng True energy of photon.
 *
 * The spectral model is defined as
 * \f[I(E)=norm f(E)\f]
 * where
 * \f$norm=n_s n_v\f$ is the normalization of the function.
 * Note that the normalization is factorised into a scaling factor and a
 * value and that the method is expected to return the gradient with respect
 * to the parameter value \f$n_v\f$.
 *
 * The partial derivative of the normalization value is given by
 * \f[dI/dn_v=n_s f(E)\f]
 ***************************************************************************/
double GModelSpectralFunc::eval_gradients(const GEnergy& srcEng) const
{
    // Interpolate function. This is done in log10-log10 space, but the
    // linear value is returned.
    double arg  = m_log_nodes.interpolate(srcEng.log10MeV(), m_log_values);
    double func = std::pow(10.0, arg);

    // Compute function value
    double value  = norm() * func;

    // Compute partial derivatives of the parameter values
    double g_norm  = (m_norm.isfree())  ? m_norm.scale() * func : 0.0;

    // Set gradients (circumvent const correctness)
    const_cast<GModelSpectralFunc*>(this)->m_norm.gradient(g_norm);

    // Compile option: Check for NaN/Inf
    #if defined(G_NAN_CHECK)
    if (isnotanumber(value) || isinfinite(value)) {
        std::cout << "*** ERROR: GModelSpectralFunc::eval_gradients";
        std::cout << "(srcEng=" << srcEng << "):";
        std::cout << " NaN/Inf encountered";
        std::cout << " (value=" << value;
        std::cout << ", norm=" << norm();
        std::cout << ", func=" << func;
        std::cout << ", g_norm=" << g_norm;
        std::cout << ")" << std::endl;
    }
    #endif

    // Return
    return value;
}
コード例 #22
0
/***********************************************************************//**
 * @brief Evaluate function
 *
 * @param[in] srcEng True energy of photon.
 *
 * The spectral model is defined as
 * \f[I(E)=norm f(E)\f]
 * where
 * \f$norm\f$ is the normalization of the function.
 * Note that the node energies are stored as log10 of energy in units of
 * MeV.
 ***************************************************************************/
double GModelSpectralFunc::eval(const GEnergy& srcEng) const
{
    // Interpolate function. This is done in log10-log10 space, but the
    // linear value is returned.
    double arg  = m_log_nodes.interpolate(srcEng.log10MeV(), m_log_values);
    double func = std::pow(10.0, arg);

    // Compute function value
    double value  = norm() * func;

    // Compile option: Check for NaN/Inf
    #if defined(G_NAN_CHECK)
    if (isnotanumber(value) || isinfinite(value)) {
        std::cout << "*** ERROR: GModelSpectralFunc::eval";
        std::cout << "(srcEng=" << srcEng << "):";
        std::cout << " NaN/Inf encountered";
        std::cout << " (value=" << value;
        std::cout << ", norm=" << norm();
        std::cout << ", func=" << func;
        std::cout << ")" << std::endl;
    }
    #endif

    // Return
    return value;
}
コード例 #23
0
/***********************************************************************//**
 * @brief Update eval precomputation cache
 *
 * @param[in] energy Energy.
 *
 * Updates the precomputation cache for eval() and eval_gradients() methods.
 ***************************************************************************/
void GModelSpectralExpPlaw::update_eval_cache(const GEnergy& energy) const
{
    // Get parameter values (takes 3 multiplications which are difficult
    // to avoid)
    double index = m_index.value();
    double ecut  = m_ecut.value();
    double pivot = m_pivot.value();
    
    // If the energy or one of the parameters index, cut-off or pivot
    // energy has changed then recompute the cache
    if ((m_last_energy != energy) ||
        (m_last_index  != index)  ||
        (m_last_ecut   != ecut)   ||
        (m_last_pivot  != pivot)) {

        // Store actual energy and parameter values
        m_last_energy = energy;
        m_last_index  = index;
        m_last_ecut   = ecut;
        m_last_pivot  = pivot;

        // Compute and store value
        double eng    = energy.MeV();
        m_last_e_norm = eng / m_last_pivot;
        m_last_e_cut  = eng / m_last_ecut;
        m_last_power  = std::pow(m_last_e_norm, m_last_index) *
                        std::exp(-m_last_e_cut);

    } // endif: recomputation was required

    // Return
    return;
}
コード例 #24
0
/***********************************************************************//**
 * @brief Evaluate model value
 *
 * @param[in] srcEng True photon energy.
 * @param[in] srcTime True photon arrival time.
 * @return Model value (ph/cm2/s/MeV).
 *
 * Evaluates
 *
 * \f[
 * S_{\rm E}(E | t) = \frac{m\_norm}{\sqrt{2\pi}m\_sigma}
 *                    \exp(\frac{-(E-m\_mean)^2}{2 m\_sigma^2})
 * \f]
 *
 * where
 * - \f${\tt m\_norm}\f$ is the normalization,
 * - \f${\tt m\_mean}\f$ is the mean energy, and
 * - \f${\tt m\_sigma}\f$ is the energy width.
 ***************************************************************************/
double GModelSpectralGauss::eval(const GEnergy& srcEng,
                                 const GTime&   srcTime) const
{
    // Get parameter values
    double energy = srcEng.MeV();
    double norm   = m_norm.value();
    double mean   = m_mean.value();
    double sigma  = m_sigma.value();

    // Compute function value
    double delta = energy - mean;
    double term1 = (norm / sigma) * gammalib::inv_sqrt2pi;
    double term2 = delta * delta / (2.0 * sigma * sigma);
    double value = term1 * std::exp(-term2);

    // Compile option: Check for NaN/Inf
    #if defined(G_NAN_CHECK)
    if (gammalib::is_notanumber(value) || gammalib::is_infinite(value)) {
        std::cout << "*** ERROR: GModelSpectralGauss::eval";
        std::cout << "(srcEng=" << srcEng;
        std::cout << ", srcTime=" << srcTime << "):";
        std::cout << " NaN/Inf encountered";
        std::cout << " (value=" << value;
        std::cout << ")" << std::endl;
    }
    #endif

    // Return
    return value;
}
コード例 #25
0
/***********************************************************************//**
 * @brief Evaluate function and gradients
 *
 * @param[in] srcEng True photon energy.
 * @param[in] srcTime True photon arrival time.
 * @return Model value (ph/cm2/s/MeV).
 *
 * Evaluates
 *
 * \f[
 *    S_{\rm E}(E | t) = {\tt m\_norm}
 * \f]
 *
 * where
 * - \f${\tt m\_norm}\f$ is the normalization factor.
 *
 * The method also evaluates the partial derivatives of the model with
 * respect to the normalization parameter using
 *
 * \f[
 *    \frac{\delta S_{\rm E}(E | t)}{\delta {\tt m\_norm}} =
 *      \frac{S_{\rm E}(E | t)}{{\tt m\_norm}}
 * \f]
 ***************************************************************************/
double GModelSpectralFunc::eval_gradients(const GEnergy& srcEng,
                                          const GTime&   srcTime)
{
    // Interpolate function. This is done in log10-log10 space, but the
    // linear value is returned.
    double arg  = m_log_nodes.interpolate(srcEng.log10MeV(), m_log_values);
    double func = std::pow(10.0, arg);

    // Compute function value
    double value  = m_norm.value() * func;

    // Compute partial derivatives of the parameter values
    double g_norm  = (m_norm.is_free())  ? m_norm.scale() * func : 0.0;

    // Set gradients
    m_norm.factor_gradient(g_norm);

    // Compile option: Check for NaN/Inf
    #if defined(G_NAN_CHECK)
    if (gammalib::is_notanumber(value) || gammalib::is_infinite(value)) {
        std::cout << "*** ERROR: GModelSpectralFunc::eval_gradients";
        std::cout << "(srcEng=" << srcEng;
        std::cout << ", srcTime=" << srcTime << "):";
        std::cout << " NaN/Inf encountered";
        std::cout << " (value=" << value;
        std::cout << ", norm=" << norm();
        std::cout << ", func=" << func;
        std::cout << ", g_norm=" << g_norm;
        std::cout << ")" << std::endl;
    }
    #endif

    // Return
    return value;
}
コード例 #26
0
ファイル: GEbounds.cpp プロジェクト: TarekHC/gammalib
/***********************************************************************//**
 * @brief Returns logarithmic mean energy for a given energy interval
 *
 * @param[in] index Energy interval index (0,...,size()-1).
 * @return Logarithmic mean energy of interval.
 *
 * @exception GException::out_of_range
 *            Specified index is out of range.
 *
 * Computes the logarithmic mean energy
 * \f$10^{0.5 * (\log E_{\rm min} + \log E_{\rm max})}\f$
 * for the energy interval @p index.
 ***************************************************************************/
GEnergy GEbounds::elogmean(const int& index) const
{
#if defined(G_RANGE_CHECK)
    // If index is outside boundary then throw an error
    if (index < 0 || index >= m_num) {
        throw GException::out_of_range(G_ELOGMEAN, index, 0, m_num-1);
    }
#endif

    // Compute logarithmic mean energy
    GEnergy elogmean;
    elogmean.MeV(std::sqrt(m_min[index].MeV() * m_max[index].MeV()));

    // Return
    return elogmean;
}
コード例 #27
0
/***********************************************************************//**
 * @brief Returns model energy flux between [emin, emax] (units: ph/cm2/s)
 *
 * @param[in] emin Minimum photon energy.
 * @param[in] emax Minimum photon energy.
 * @return Photon flux (ph/cm2/s).
 *
 * Computes
 *
 * \f[
 *    \int_{\tt emin}^{\tt emax} S_{\rm E}(E | t) E \, dE
 * \f]
 *
 * where
 * - [@p emin, @p emax] is an energy interval, and
 * - \f$S_{\rm E}(E | t)\f$ is the spectral model (ph/cm2/s/MeV).
 ***************************************************************************/
double GModelSpectralPlaw2::eflux(const GEnergy& emin,
                                  const GEnergy& emax) const
{
    // Initialise flux
    double eflux = 0.0;

    // Compute only if integration range is valid
    if (emin < emax) {

        // Compute power law normalization
        double norm;
        if (index() != -1.0) {
            double gamma        = m_index.value() + 1.0;
            double pow_ref_emin = std::pow(this->emin().MeV(), gamma);
            double pow_ref_emax = std::pow(this->emax().MeV(), gamma);
            norm = m_integral.value() * gamma / (pow_ref_emax - pow_ref_emin);
        }
        else {
            double log_ref_emin = std::log(this->emin().MeV());
            double log_ref_emax = std::log(this->emax().MeV());
            norm = m_integral.value() / (log_ref_emax - log_ref_emin);
        }

        // Compute energy flux
        if (index() != -2.0) {
            double gamma    = m_index.value() + 2.0;
            double pow_emin = std::pow(emin.MeV(), gamma);
            double pow_emax = std::pow(emax.MeV(), gamma);
            eflux = norm / gamma * (pow_emax - pow_emin);
        }

        // Case B: Index is -2
        else {
            double log_emin = std::log(emin.MeV());
            double log_emax = std::log(emax.MeV());
            eflux = norm * (log_emax - log_emin);
        }

        // Convert from MeV/cm2/s to erg/cm2/s
        eflux *= gammalib::MeV2erg;

    } // endif: integration range was valid

    // Return flux
    return eflux;
}
コード例 #28
0
/***********************************************************************//**
 * @brief Constructor
 *
 * @param[in] integral Integral flux (ph/cm2/s).
 * @param[in] index Power law index.
 * @param[in] emin Minimum energy.
 * @param[in] emax Maximum energy.
 *
 * Construct a spectral power law from the
 * - integral flux (in ph/cm2/s),
 * - spectral index,
 * - minimum energy and
 * - maximum energy.
 ***************************************************************************/
GModelSpectralPlaw2::GModelSpectralPlaw2(const double&  integral,
                                         const double&  index,
                                         const GEnergy& emin,
                                         const GEnergy& emax) :
                     GModelSpectral()
{
    // Initialise members
    init_members();

    // Set parameters
    m_integral.value(integral);
    m_index.value(index);
    m_emin.value(emin.MeV());
    m_emax.value(emax.MeV());

    // Return
    return;
}
コード例 #29
0
/***********************************************************************//**
 * @brief Constructor
 *
 * @param[in] norm Total flux under Gaussian (in ph/cm2/s).
 * @param[in] mean Mean energy.
 * @param[in] sigma Energy width.
 ***************************************************************************/
GModelSpectralGauss::GModelSpectralGauss(const double&  norm,
                                         const GEnergy& mean,
                                         const GEnergy& sigma) :
                     GModelSpectral()
{
    // Initialise members
    init_members();

    // Set parameters
    m_norm.value(norm);
    m_mean.value(mean.MeV());
    m_sigma.value(sigma.MeV());

    // Autoscale parameters
    autoscale();

    // Return
    return;
}
コード例 #30
0
/***********************************************************************//**
 * @brief Returns Monte Carlo energy between [emin, emax]
 *
 * @param[in] emin Minimum photon energy.
 * @param[in] emax Maximum photon energy.
 * @param[in] time True photon arrival time.
 * @param[in,out] ran Random number generator.
 * @return Energy.
 *
 * @exception GException::erange_invalid
 *            Energy range is invalid (emin < emax required).
 *
 * Returns Monte Carlo energy by randomly drawing from a power law.
 ***************************************************************************/
GEnergy GModelSpectralPlaw::mc(const GEnergy& emin,
                               const GEnergy& emax,
                               const GTime&   time,
                               GRan&          ran) const
{
    // Throw an exception if energy range is invalid
    if (emin >= emax) {
        throw GException::erange_invalid(G_MC, emin.MeV(), emax.MeV(),
              "Minimum energy < maximum energy required.");
    }

    // Update cache
    update_mc_cache(emin, emax);

    // Get uniform random number
    double u = ran.uniform();

    // Initialise energy
    double eng;

    // Case A: Index is not -1
    if (index() != -1.0) {
        if (u > 0.0) {
            eng = std::exp(std::log(u * m_mc_pow_ewidth + m_mc_pow_emin) /
                           m_mc_exponent);
        }
        else {
            eng = 0.0;
        }
    }

    // Case B: Index is -1
    else {
        eng = std::exp(u * m_mc_pow_ewidth + m_mc_pow_emin);
    }

    // Set energy
    GEnergy energy;
    energy.MeV(eng);

    // Return energy
    return energy;
}