/***********************************************************************//** * @brief Set pointers * * Set pointers to all model parameters. The pointers are stored in a vector * that is member of the GModelData base class. ***************************************************************************/ void GCTAModelBackground::set_pointers(void) { // Clear parameters m_pars.clear(); // Determine the number of parameters int n_radial = (spatial() != NULL) ? spatial()->size() : 0; int n_spectral = (spectral() != NULL) ? spectral()->size() : 0; int n_temporal = (temporal() != NULL) ? temporal()->size() : 0; int n_pars = n_radial + n_spectral + n_temporal; // Continue only if there are parameters if (n_pars > 0) { // Gather radial parameter pointers for (int i = 0; i < n_radial; ++i) { m_pars.push_back(&((*spatial())[i])); } // Gather spectral parameters for (int i = 0; i < n_spectral; ++i) { m_pars.push_back(&((*spectral())[i])); } // Gather temporal parameters for (int i = 0; i < n_temporal; ++i) { m_pars.push_back(&((*temporal())[i])); } } // Return return; }
/***********************************************************************//** * @brief Write model into XML element * * @param[in] xml XML element. * * @todo Document method. ***************************************************************************/ void GCTAModelBackground::write(GXmlElement& xml) const { // Initialise pointer on source GXmlElement* src = NULL; // Search corresponding source int n = xml.elements("source"); for (int k = 0; k < n; ++k) { GXmlElement* element = xml.element("source", k); if (element->attribute("name") == name()) { src = element; break; } } // If no source with corresponding name was found then append one if (src == NULL) { src = xml.append("source"); if (spectral() != NULL) src->append(GXmlElement("spectrum")); if (spatial() != NULL) src->append(GXmlElement("spatialModel")); //if (temporal() != NULL) src->append(GXmlElement("temporalModel")); } // Set model type, name and optionally instruments src->attribute("name", name()); src->attribute("type", type()); if (instruments().length() > 0) { src->attribute("instrument", instruments()); } std::string identifiers = ids(); if (identifiers.length() > 0) { src->attribute("id", identifiers); } // Write spectral model if (spectral() != NULL) { GXmlElement* spec = src->element("spectrum", 0); spectral()->write(*spec); } // Write spatial model if (spatial() != NULL) { GXmlElement* spat = src->element("spatialModel", 0); spatial()->write(*spat); } // Write temporal model /* if (temporal() != NULL) { if (dynamic_cast<GModelTemporalConst*>(temporal()) == NULL) { GXmlElement* temp = src->element("temporalModel", 0); temporal()->write(*temp); } } */ // Return return; }
/***********************************************************************//** * @brief Print model information ***************************************************************************/ std::string GModelSky::print_model(void) const { // Initialise result string std::string result; // Determine number of parameters per type int n_spatial = (m_spatial != NULL) ? m_spatial->size() : 0; int n_spectral = (m_spectral != NULL) ? m_spectral->size() : 0; int n_temporal = (m_temporal != NULL) ? m_temporal->size() : 0; // Append attributes result.append(print_attributes()); // Append model type result.append("\n"+parformat("Model type")); if (n_spatial > 0) { result.append("\""+spatial()->type()+"\""); if (n_spectral > 0 || n_temporal > 0) { result.append(" * "); } } if (n_spectral > 0) { result.append("\""+spectral()->type()+"\""); if (n_temporal > 0) { result.append(" * "); } } if (n_temporal > 0) { result.append("\""+temporal()->type()+"\""); } // Append parameters result.append("\n"+parformat("Number of parameters")+str(size())); result.append("\n"+parformat("Number of spatial par's")+str(n_spatial)); for (int i = 0; i < n_spatial; ++i) { result.append("\n"+(*spatial())[i].print()); } result.append("\n"+parformat("Number of spectral par's")+str(n_spectral)); for (int i = 0; i < n_spectral; ++i) { result.append("\n"+(*spectral())[i].print()); } result.append("\n"+parformat("Number of temporal par's")+str(n_temporal)); for (int i = 0; i < n_temporal; ++i) { result.append("\n"+(*temporal())[i].print()); } // Return result return result; }
/***********************************************************************//** * @brief Write model into XML element * * @param[in] xml Source library. ***************************************************************************/ void GModelSky::write(GXmlElement& xml) const { // Initialise pointer on source GXmlElement* src = NULL; // Search corresponding source int n = xml.elements("source"); for (int k = 0; k < n; ++k) { GXmlElement* element = static_cast<GXmlElement*>(xml.element("source", k)); if (element->attribute("name") == name()) { src = element; break; } } // If no source with corresponding name was found then append one if (src == NULL) { src = new GXmlElement("source"); src->attribute("name") = name(); if (spectral() != NULL) src->append(new GXmlElement("spectrum")); if (spatial() != NULL) src->append(new GXmlElement("spatialModel")); xml.append(src); } // Set model attributes src->attribute("name", name()); src->attribute("type", type()); std::string instruments = this->instruments(); if (instruments.length() > 0) { src->attribute("instrument", instruments); } // Write spectral model if (spectral() != NULL) { GXmlElement* spec = static_cast<GXmlElement*>(src->element("spectrum", 0)); spectral()->write(*spec); } // Write spatial model if (spatial() != NULL) { GXmlElement* spat = static_cast<GXmlElement*>(src->element("spatialModel", 0)); spatial()->write(*spat); } // Return return; }
/***********************************************************************//** * @brief Verifies if model has all components * * Returns 'true' if models has a spatial, a spectral and a temporal * component. Otherwise returns 'false'. ***************************************************************************/ bool GCTAModelBackground::valid_model(void) const { // Set result bool result = ((spatial() != NULL) && (spectral() != NULL) && (temporal() != NULL)); // Return result return result; }
/***********************************************************************//** * @brief Evaluate function * * @param[in] event Observed event. * @param[in] obs Observation. * @return Function value. * * @exception GException::invalid_argument * No CTA instrument direction found in event. * * Evaluates tha CTA background model which is a factorization of a * spatial, spectral and temporal model component. This method also applies * a deadtime correction factor, so that the normalization of the model is * a real rate (counts/exposure time). * * @todo Add bookkeeping of last value and evaluate only if argument * changed ***************************************************************************/ double GCTAModelBackground::eval(const GEvent& event, const GObservation& obs) const { // Get pointer on CTA observation const GCTAObservation* ctaobs = dynamic_cast<const GCTAObservation*>(&obs); if (ctaobs == NULL) { std::string msg = "Specified observation is not a CTA observation.\n" + obs.print(); throw GException::invalid_argument(G_EVAL, msg); } // Extract CTA instrument direction const GCTAInstDir* dir = dynamic_cast<const GCTAInstDir*>(&(event.dir())); if (dir == NULL) { std::string msg = "No CTA instrument direction found in event."; throw GException::invalid_argument(G_EVAL, msg); } // Create a Photon from the event. // We need the GPhoton to evaluate the spatial model. // For the background, GEvent and GPhoton are identical // since the IRFs are not folded in GPhoton photon(dir->dir(), event.energy(), event.time()); // Evaluate function and gradients double spat = (spatial() != NULL) ? spatial()->eval(photon) : 1.0; double spec = (spectral() != NULL) ? spectral()->eval(event.energy(), event.time()) : 1.0; double temp = (temporal() != NULL) ? temporal()->eval(event.time()) : 1.0; // Compute value double value = spat * spec * temp; // Apply deadtime correction value *= obs.deadc(event.time()); // Return return value; }
void VisibleEntityManager::setupComponent(Component* visible) { String asset = visible->attr(VISIBLE_KEY_ASSET).string(); int z = visible->attr(VISIBLE_KEY_Z).intValue(); bool isVisible = true; if (!visible->attr(VISIBLE_KEY_VISIBLE).isNull()) { isVisible = visible->attr(VISIBLE_KEY_VISIBLE).boolValue(); } Component* spatialComponent = level_->component(SPATIAL_TYPE, visible->label()); SpatialDecorator spatial(level_->component("spatial", visible->label())); view_->addSprite(asset, spatial.x(), spatial.y(), z, spatial.rotation(), visible->label(), spatialComponent, isVisible); }
/***********************************************************************//** * @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; }
//-***************************************************************************** int main(int argc, char* argv[]) { int powerOfTwo = 12; ewav::RSpatialField2Df spatial(powerOfTwo); int N = spatial.width(); std::cout << "Made " << N << " x " << N << " spatial field." << std::endl; ewav::CSpectralField2Df spectral(powerOfTwo); std::cout << "Made " << N << " x " << N << " spectral field." << std::endl; ewav::SpectralToSpatial2Df convert(spectral, spatial); std::cout << "Made " << N << " x " << N << " converter." << std::endl; // Fill spectral { RandFillFunctor F; F.Spectral = spectral.data(); F.StrideJ = spectral.stride(); F.N = N; F.Domain = 1000.0f; F.Seed = 54321; // Rows, then columns. tbb::blocked_range2d<int> range{0, spectral.height(), 1, 0, spectral.width(), 512}; tbb::parallel_for(range, F); } std::cout << "Filled spectral array with gaussian random numbers" << std::endl; // Convert. convert.execute(spectral, spatial); std::cout << "Converted to spatial." << std::endl << "Spatial midpoint: " << spatial[N / 2][N / 2] << std::endl; return 0; }
/***********************************************************************//** * @brief Print model information * * @param[in] chatter Chattiness (defaults to NORMAL). * @return String containing model information. ***************************************************************************/ std::string GCTAModelBackground::print(const GChatter& chatter) const { // Initialise result string std::string result; // Continue only if chatter is not silent if (chatter != SILENT) { // Append header result.append("=== GCTAModelBackground ==="); // Determine number of parameters per type int n_radial = (spatial() != NULL) ? spatial()->size() : 0; int n_spectral = (spectral() != NULL) ? spectral()->size() : 0; int n_temporal = (temporal() != NULL) ? temporal()->size() : 0; // Append attributes result.append("\n"+print_attributes()); // Append model type result.append("\n"+gammalib::parformat("Model type")); if (n_radial > 0) { result.append("\""+spatial()->type()+"\""); if (n_spectral > 0 || n_temporal > 0) { result.append(" * "); } } if (n_spectral > 0) { result.append("\""+spectral()->type()+"\""); if (n_temporal > 0) { result.append(" * "); } } if (n_temporal > 0) { result.append("\""+temporal()->type()+"\""); } // Append parameters result.append("\n"+gammalib::parformat("Number of parameters") + gammalib::str(size())); result.append("\n"+gammalib::parformat("Number of spatial par's") + gammalib::str(n_radial)); for (int i = 0; i < n_radial; ++i) { result.append("\n"+(*spatial())[i].print()); } result.append("\n"+gammalib::parformat("Number of spectral par's") + gammalib::str(n_spectral)); for (int i = 0; i < n_spectral; ++i) { result.append("\n"+(*spectral())[i].print()); } result.append("\n"+gammalib::parformat("Number of temporal par's") + gammalib::str(n_temporal)); for (int i = 0; i < n_temporal; ++i) { result.append("\n"+(*temporal())[i].print()); } } // endif: chatter was not silent // Return result return result; }
/***********************************************************************//** * @brief Return simulated list of events * * @param[in] obs Observation. * @param[in] ran Random number generator. * @return Pointer to list of simulated events (needs to be de-allocated by * client) * * @exception GException::invalid_argument * No CTA event list found in observation. * * Draws a sample of events from the background model using a Monte * Carlo simulation. The pointing information, the energy boundaries and the * good time interval for the sampling will be extracted from the observation * argument that is passed to the method. The method also requires a random * number generator of type GRan which is passed by reference, hence the * state of the random number generator will be changed by the method. * * The method also applies a deadtime correction using a Monte Carlo process, * taking into account temporal deadtime variations. For this purpose, the * method makes use of the time dependent GObservation::deadc method. ***************************************************************************/ GCTAEventList* GCTAModelBackground::mc(const GObservation& obs, GRan& ran) const { // Initialise new event list GCTAEventList* list = new GCTAEventList; // Continue only if model is valid) if (valid_model()) { // Extract event list to access the ROI, energy boundaries and GTIs const GCTAEventList* events = dynamic_cast<const GCTAEventList*>(obs.events()); if (events == NULL) { std::string msg = "No CTA event list found in observation.\n" + obs.print(); throw GException::invalid_argument(G_MC, msg); } // Get simulation region const GCTARoi& roi = events->roi(); const GEbounds& ebounds = events->ebounds(); const GGti& gti = events->gti(); // Set simulation region for result event list list->roi(roi); list->ebounds(ebounds); list->gti(gti); // Loop over all energy boundaries for (int ieng = 0; ieng < ebounds.size(); ++ieng) { // Initialise de-allocation flag bool free_spectral = false; // Set pointer to spectral model GModelSpectral* spectral = m_spectral; // If the spectral model is a diffuse cube then create a node // function spectral model that is the product of the diffuse // cube node function and the spectral model evaluated at the // energies of the node function GModelSpatialDiffuseCube* cube = dynamic_cast<GModelSpatialDiffuseCube*>(m_spatial); if (cube != NULL) { // Set MC simulation cone based on ROI cube->set_mc_cone(roi.centre().dir(), roi.radius()); // Allocate node function to replace the spectral component GModelSpectralNodes* nodes = new GModelSpectralNodes(cube->spectrum()); for (int i = 0; i < nodes->nodes(); ++i) { GEnergy energy = nodes->energy(i); double intensity = nodes->intensity(i); double norm = m_spectral->eval(energy, events->tstart()); nodes->intensity(i, norm*intensity); } // Signal that node function needs to be de-allocated later free_spectral = true; // Set the spectral model pointer to the node function spectral = nodes; } // endif: spatial model was a diffuse cube // Compute the background rate in model within the energy boundaries // from spectral component (units: cts/s). // Note that the time here is ontime. Deadtime correction will be done // later. double rate = spectral->flux(ebounds.emin(ieng), ebounds.emax(ieng)); // Debug option: dump rate #if defined(G_DUMP_MC) std::cout << "GCTAModelBackground::mc(\"" << name() << "\": "; std::cout << "rate=" << rate << " cts/s)" << std::endl; #endif // Loop over all good time intervals for (int itime = 0; itime < gti.size(); ++itime) { // Get Monte Carlo event arrival times from temporal model GTimes times = m_temporal->mc(rate, gti.tstart(itime), gti.tstop(itime), ran); // Get number of events int n_events = times.size(); // Reserve space for events if (n_events > 0) { list->reserve(n_events); } // Loop over events for (int i = 0; i < n_events; ++i) { // Apply deadtime correction double deadc = obs.deadc(times[i]); if (deadc < 1.0) { if (ran.uniform() > deadc) { continue; } } // Get Monte Carlo event energy from spectral model GEnergy energy = spectral->mc(ebounds.emin(ieng), ebounds.emax(ieng), times[i], ran); // Get Monte Carlo event direction from spatial model GSkyDir dir = spatial()->mc(energy, times[i], ran); // Allocate event GCTAEventAtom event; // Set event attributes event.dir(GCTAInstDir(dir)); event.energy(energy); event.time(times[i]); // Append event to list if it falls in ROI if (events->roi().contains(event)) { list->append(event); } } // endfor: looped over all events } // endfor: looped over all GTIs // Free spectral model if required if (free_spectral) delete spectral; } // endfor: looped over all energy boundaries } // endif: model was valid // Return return list; }
/***********************************************************************//** * @brief Return spatially integrated data model * * @param[in] obsEng Measured event energy. * @param[in] obsTime Measured event time. * @param[in] obs Observation. * @return Spatially integrated model. * * @exception GException::invalid_argument * No CTA event list found in observation. * No CTA pointing found in observation. * * Spatially integrates the data model for a given measured event energy and * event time. This method also applies a deadtime correction factor, so that * the normalization of the model is a real rate (counts/exposure time). ***************************************************************************/ double GCTAModelBackground::npred(const GEnergy& obsEng, const GTime& obsTime, const GObservation& obs) const { // Initialise result double npred = 0.0; bool has_npred = false; // Build unique identifier std::string id = obs.instrument() + "::" + obs.id(); // Check if Npred value is already in cache #if defined(G_USE_NPRED_CACHE) if (!m_npred_names.empty()) { // Search for unique identifier, and if found, recover Npred value // and break for (int i = 0; i < m_npred_names.size(); ++i) { if (m_npred_names[i] == id && m_npred_energies[i] == obsEng) { npred = m_npred_values[i]; has_npred = true; #if defined(G_DEBUG_NPRED) std::cout << "GCTAModelBackground::npred:"; std::cout << " cache=" << i; std::cout << " npred=" << npred << std::endl; #endif break; } } } // endif: there were values in the Npred cache #endif // Continue only if no Npred cache value was found if (!has_npred) { // Evaluate only if model is valid if (valid_model()) { // Get CTA event list const GCTAEventList* events = dynamic_cast<const GCTAEventList*>(obs.events()); if (events == NULL) { std::string msg = "No CTA event list found in observation.\n" + obs.print(); throw GException::invalid_argument(G_NPRED, msg); } #if !defined(G_NPRED_AROUND_ROI) // Get CTA pointing direction GCTAPointing* pnt = dynamic_cast<GCTAPointing*>(obs.pointing()); if (pnt == NULL) { std::string msg = "No CTA pointing found in observation.\n" + obs.print(); throw GException::invalid_argument(G_NPRED, msg); } #endif // Get reference to ROI centre const GSkyDir& roi_centre = events->roi().centre().dir(); // Get ROI radius in radians double roi_radius = events->roi().radius() * gammalib::deg2rad; // Get distance from ROI centre in radians #if defined(G_NPRED_AROUND_ROI) double roi_distance = 0.0; #else double roi_distance = roi_centre.dist(pnt->dir()); #endif // Initialise rotation matrix to transform from ROI system to // celestial coordinate system GMatrix ry; GMatrix rz; ry.eulery(roi_centre.dec_deg() - 90.0); rz.eulerz(-roi_centre.ra_deg()); GMatrix rot = (ry * rz).transpose(); // Compute position angle of ROI centre with respect to model // centre (radians) #if defined(G_NPRED_AROUND_ROI) double omega0 = 0.0; #else double omega0 = pnt->dir().posang(events->roi().centre().dir()); #endif // Setup integration function GCTAModelBackground::npred_roi_kern_theta integrand(spatial(), obsEng, obsTime, rot, roi_radius, roi_distance, omega0); // Setup integrator GIntegral integral(&integrand); integral.eps(1e-3); // Setup integration boundaries #if defined(G_NPRED_AROUND_ROI) double rmin = 0.0; double rmax = roi_radius; #else double rmin = (roi_distance > roi_radius) ? roi_distance-roi_radius : 0.0; double rmax = roi_radius + roi_distance; #endif // Spatially integrate radial component npred = integral.romb(rmin, rmax); // Store result in Npred cache #if defined(G_USE_NPRED_CACHE) m_npred_names.push_back(id); m_npred_energies.push_back(obsEng); m_npred_times.push_back(obsTime); m_npred_values.push_back(npred); #endif // Debug: Check for NaN #if defined(G_NAN_CHECK) if (gammalib::is_notanumber(npred) || gammalib::is_infinite(npred)) { std::cout << "*** ERROR: GCTAModelBackground::npred:"; std::cout << " NaN/Inf encountered"; std::cout << " (npred=" << npred; std::cout << ", roi_radius=" << roi_radius; std::cout << ")" << std::endl; } #endif } // endif: model was valid } // endif: Npred computation required // Multiply in spectral and temporal components npred *= spectral()->eval(obsEng, obsTime); npred *= temporal()->eval(obsTime); // Apply deadtime correction npred *= obs.deadc(obsTime); // Return Npred return npred; }
/***********************************************************************//** * @brief Evaluate function and gradients * * @param[in] event Observed event. * @param[in] obs Observation. * @return Function value. * * @exception GException::invalid_argument * No CTA instrument direction found in event. * * Evaluates tha CTA background model and parameter gradients. The CTA * background model is a factorization of a spatial, spectral and * temporal model component. This method also applies a deadtime correction * factor, so that the normalization of the model is a real rate * (counts/exposure time). * * @todo Add bookkeeping of last value and evaluate only if argument * changed ***************************************************************************/ double GCTAModelBackground::eval_gradients(const GEvent& event, const GObservation& obs) const { // Get pointer on CTA observation const GCTAObservation* ctaobs = dynamic_cast<const GCTAObservation*>(&obs); if (ctaobs == NULL) { std::string msg = "Specified observation is not a CTA observation.\n" + obs.print(); throw GException::invalid_argument(G_EVAL_GRADIENTS, msg); } // Extract CTA instrument direction const GCTAInstDir* dir = dynamic_cast<const GCTAInstDir*>(&(event.dir())); if (dir == NULL) { std::string msg = "No CTA instrument direction found in event."; throw GException::invalid_argument(G_EVAL_GRADIENTS, msg); } // Create a Photon from the event // We need the photon to evaluate the spatial model // For the background, GEvent and GPhoton are identical // since the IRFs are not folded in GPhoton photon = GPhoton(dir->dir(), event.energy(),event.time()); // Evaluate function and gradients double spat = (spatial() != NULL) ? spatial()->eval_gradients(photon) : 1.0; double spec = (spectral() != NULL) ? spectral()->eval_gradients(event.energy(), event.time()) : 1.0; double temp = (temporal() != NULL) ? temporal()->eval_gradients(event.time()) : 1.0; // Compute value double value = spat * spec * temp; // Apply deadtime correction double deadc = obs.deadc(event.time()); value *= deadc; // Multiply factors to spatial gradients if (spatial() != NULL) { double fact = spec * temp * deadc; if (fact != 1.0) { for (int i = 0; i < spatial()->size(); ++i) (*spatial())[i].factor_gradient( (*spatial())[i].factor_gradient() * fact ); } } // Multiply factors to spectral gradients if (spectral() != NULL) { double fact = spat * temp * deadc; if (fact != 1.0) { for (int i = 0; i < spectral()->size(); ++i) (*spectral())[i].factor_gradient( (*spectral())[i].factor_gradient() * fact ); } } // Multiply factors to temporal gradients if (temporal() != NULL) { double fact = spat * spec * deadc; if (fact != 1.0) { for (int i = 0; i < temporal()->size(); ++i) (*temporal())[i].factor_gradient( (*temporal())[i].factor_gradient() * fact ); } } // Return value return value; }
void AnimatableManager::setupComponents(const AnimatableDecorator &animatable) { animatable.cacheAnimations(); SpatialDecorator spatial(level_->component("spatial", animatable.label())); view_->addSprite(animatable.defaultFrame(), spatial.x(), spatial.y(), animatable.z(), spatial.rotation(), animatable.label(), level_->component("spatial", animatable.label()), true); view_->playAnimation(animatable.defaultAnimation(), animatable.label(), true, true, DefaultAnimationCompleteHandler::handler()); }