/***********************************************************************//** * @brief Return spatially integrated sky model * * @param[in] obsEng Measured photon energy. * @param[in] obsTime Measured photon arrival time. * @param[in] obs Observation. * * @exception GException::no_response * No valid instrument response function defined. * * Computes * \f[N"_{\rm pred} = \int_{\rm ROI} * S(\vec{p}, E, t) PSF(\vec{p'}, E', t' | \vec{d}, \vec{p}, E, t) \, * {\rm d}\vec{p'}\f] * where * \f$S(\vec{p}, E, t)\f$ is the source model, * \f$PSF(\vec{p'}, E', t' | \vec{d}, \vec{p}, E, t)\f$ is the point * spread function, * \f$\vec{p'}\f$ is the measured photon direction, * \f$E'\f$ is the measured photon energy, * \f$t'\f$ is the measured photon arrival time, * \f$\vec{p}\f$ is the true photon arrival direction, * \f$E\f$ is the true photon energy, * \f$t\f$ is the true photon arrival time, and * \f$d\f$ is the instrument pointing. * * \f${\rm ROI}\f$ is the region of interest that is stored in the * GObservation::m_roi member. The integration over the ROI is performed * by the GResponse::npred() method. * * @todo The actual method is only correct if no energy and time dispersion * exists. For the moment we set srcEng=obsEng and srcTime=obsTime. * Formally, Equation (2) of the instrument document has to be * computed, which is an integration over source energy, time * and arrival direction. For the moment, only the integration over * arrival direction is performed by GResponse::npred(). ***************************************************************************/ double GModelSky::npred(const GEnergy& obsEng, const GTime& obsTime, const GObservation& obs) const { // Initialise result double npred = 0.0; // Continue only if model is valid) if (valid_model()) { // Get response function GResponse* rsp = obs.response(); if (rsp == NULL) { throw GException::no_response(G_NPRED); } // Here we make the simplifying approximations // srcEng=obsEng and srcTime=obsTime. To be fully correct we should // integrate over true energy and true time here ... at least true // time if we want to consider energy dispersion ... GEnergy srcEng = obsEng; GTime srcTime = obsTime; // Set source GSource source(this->name(), *m_spatial, srcEng, srcTime); // Compute response components double npred_spatial = rsp->npred(source, obs); double npred_spectral = spectral()->eval(srcEng); double npred_temporal = temporal()->eval(srcTime); // Compute response npred = npred_spatial * npred_spectral * npred_temporal; // Compile option: Check for NaN/Inf #if defined(G_NAN_CHECK) if (isnotanumber(npred) || isinfinite(npred)) { std::cout << "*** ERROR: GModelSky::npred:"; std::cout << " NaN/Inf encountered"; std::cout << " (npred=" << npred; std::cout << ", npred_spatial=" << npred_spatial; std::cout << ", npred_spectral=" << npred_spectral; std::cout << ", npred_temporal=" << npred_temporal; std::cout << ", srcEng=" << srcEng; std::cout << ", srcTime=" << srcTime; std::cout << ")" << std::endl; } #endif } // endif: model was valid // Return npred return npred; }
/***********************************************************************//** * @brief Perform integration over spectral component * * @param[in] event Observed event. * @param[in] srcTime True photon arrival time. * @param[in] obs Observation. * @param[in] grad Evaluate gradients. * * @exception GException::no_response * Observation has no valid instrument response * @exception GException::feature_not_implemented * Energy integration not yet implemented * * This method integrates the source model over the spectral component. If * the response function has no energy dispersion then no spectral * integration is needed and the observed photon energy is identical to the * true photon energy. * * @todo Needs implementation of spectral integration to handle energy * dispersion. ***************************************************************************/ double GModelSky::spectral(const GEvent& event, const GTime& srcTime, const GObservation& obs, bool grad) const { // Initialise result double value = 0.0; // Get response function GResponse* rsp = obs.response(); if (rsp == NULL) { throw GException::no_response(G_SPECTRAL); } // Determine if energy integration is needed bool integrate = rsp->hasedisp(); // Case A: Integraion if (integrate) { throw GException::feature_not_implemented(G_SPECTRAL); } // Case B: No integration (assume no energy dispersion) else { value = spatial(event, event.energy(), srcTime, obs, grad); } // Compile option: Check for NaN/Inf #if defined(G_NAN_CHECK) if (isnotanumber(value) || isinfinite(value)) { std::cout << "*** ERROR: GModelSky::spectral:"; std::cout << " NaN/Inf encountered"; std::cout << " (value=" << value; std::cout << ", event=" << event; std::cout << ", srcTime=" << srcTime; std::cout << ")" << std::endl; } #endif // Return value return value; }
/***********************************************************************//** * @brief Returns spatial model component * * @param[in] event Observed event. * @param[in] srcEng True photon energy. * @param[in] srcTime True photon arrival time. * @param[in] obs Observation. * @param[in] grad Evaluate gradients. * * @exception GException::no_response * Observation has no valid instrument response * * This method computes the spatial model component for a given true photon * energy and arrival time. ***************************************************************************/ double GModelSky::spatial(const GEvent& event, const GEnergy& srcEng, const GTime& srcTime, const GObservation& obs, bool grad) const { // Initialise result double value = 0.0; // Continue only if the model has a spatial component if (m_spatial != NULL) { // Get response function GResponse* rsp = obs.response(); if (rsp == NULL) { throw GException::no_response(G_SPATIAL); } // Set source GSource source(this->name(), *m_spatial, srcEng, srcTime); // Get IRF value. This method returns the spatial component of the // source model. double irf = rsp->irf(event, source, obs); // Case A: evaluate gradients if (grad) { // Evaluate source model double spec = (spectral() != NULL) ? spectral()->eval_gradients(srcEng) : 1.0; double temp = (temporal() != NULL) ? temporal()->eval_gradients(srcTime) : 1.0; // Set value value = spec * temp * irf; // Compile option: Check for NaN/Inf #if defined(G_NAN_CHECK) if (isnotanumber(value) || isinfinite(value)) { std::cout << "*** ERROR: GModelSky::spatial:"; std::cout << " NaN/Inf encountered"; std::cout << " (value=" << value; std::cout << ", spec=" << spec; std::cout << ", temp=" << temp; std::cout << ", irf=" << irf; std::cout << ")" << std::endl; } #endif // Multiply factors to spectral gradients if (spectral() != NULL) { double fact = temp * irf; if (fact != 1.0) { for (int i = 0; i < spectral()->size(); ++i) { (*spectral())[i].gradient((*spectral())[i].gradient() * fact); } } } // Multiply factors to temporal gradients if (temporal() != NULL) { double fact = spec * irf; if (fact != 1.0) { for (int i = 0; i < temporal()->size(); ++i) { (*temporal())[i].gradient((*temporal())[i].gradient() * fact); } } } } // endif: gradient evaluation has been requested // Case B: evaluate no gradients else { // Evaluate source model double spec = (m_spectral != NULL) ? m_spectral->eval(srcEng) : 1.0; double temp = (m_temporal != NULL) ? m_temporal->eval(srcTime) : 1.0; // Set value value = spec * temp * irf; // Compile option: Check for NaN/Inf #if defined(G_NAN_CHECK) if (isnotanumber(value) || isinfinite(value)) { std::cout << "*** ERROR: GModelSky::spatial:"; std::cout << " NaN/Inf encountered"; std::cout << " (value=" << value; std::cout << ", spec=" << spec; std::cout << ", temp=" << temp; std::cout << ", irf=" << irf; std::cout << ")" << std::endl; } #endif } } // endif: Gamma-ray source model had a spatial component // Return value return value; }