/***********************************************************************//** * @brief Exposure cube constructor * * @param[in] wcs World Coordinate System. * @param[in] coords Coordinate System (CEL or GAL). * @param[in] x X coordinate of sky map centre (deg). * @param[in] y Y coordinate of sky map centre (deg). * @param[in] dx Pixel size in x direction at centre (deg/pixel). * @param[in] dy Pixel size in y direction at centre (deg/pixel). * @param[in] nx Number of pixels in x direction. * @param[in] ny Number of pixels in y direction. * @param[in] ebounds Energy boundaries. * * Constructs an exposure cube by specifying the sky map grid and the energy * boundaries. ***************************************************************************/ GCTACubeExposure::GCTACubeExposure(const std::string& wcs, const std::string& coords, const double& x, const double& y, const double& dx, const double& dy, const int& nx, const int& ny, const GEbounds& ebounds) { // Initialise class members init_members(); // Store energy boundaries m_ebounds = ebounds; // Set GNodeArray used for interpolation set_eng_axis(); // Create sky map m_cube = GSkymap(wcs, coords, x, y, dx, dy, nx, ny, m_ebounds.size()); // Return return; }
/***********************************************************************//** * @brief Setup observation container * * @exception GException::no_cube * No event cube found in CTA observation. * * This method sets up the observation container for processing. There are * two cases: * * If there are no observations in the actual observation container, the * method will check in "infile" parameter. If this parameter is "NONE" or * empty, the task parameters will be used to construct a model map. * Otherwise, the method first tries to interpret the "infile" parameter as * a counts map, and attemps loading of the file in an event cube. If this * fails, the method tries to interpret the "infile" parameter as an * observation definition XML file. If this also fails, an exception will * be thrown. * * If observations exist already in the observation container, the method * will simply keep them. * * Test if all CTA observations contain counts maps. * * Finally, if no models exist so far in the observation container, the * models will be loaded from the model XML file. ***************************************************************************/ void ctmodel::setup_obs(void) { // If there are no observations in the container then try to build some if (m_obs.size() == 0) { // If no input filename has been specified, then create a model map // from the task parameters if ((m_infile == "NONE") || (gammalib::strip_whitespace(m_infile) == "")) { // Set pointing direction GCTAPointing pnt; GSkyDir skydir; skydir.radec_deg(m_ra, m_dec); pnt.dir(skydir); // Setup energy range covered by model GEnergy emin(m_emin, "TeV"); GEnergy emax(m_emax, "TeV"); GEbounds ebds(m_enumbins, emin, emax); // Setup time interval covered by model GGti gti; GTime tmin(m_tmin); GTime tmax(m_tmax); gti.append(tmin, tmax); // Setup skymap GSkymap map = GSkymap(m_proj, m_coordsys, m_xref, m_yref, -m_binsz, m_binsz, m_nxpix, m_nypix, m_enumbins); // Create model cube from sky map GCTAEventCube cube(map, ebds, gti); // Allocate CTA observation GCTAObservation obs; // Set CTA observation attributes obs.pointing(pnt); obs.ontime(gti.ontime()); obs.livetime(gti.ontime()*m_deadc); obs.deadc(m_deadc); // Set event cube in observation obs.events(cube); // Append CTA observation to container m_obs.append(obs); // Signal that no XML file should be used for storage m_use_xml = false; } // endif: created model map from task parameters // ... otherwise try to load information from the file else { // First try to open the file as a counts map try { // Allocate CTA observation GCTAObservation obs; // Load counts map in CTA observation obs.load_binned(m_infile); // Append CTA observation to container m_obs.append(obs); // Signal that no XML file should be used for storage m_use_xml = false; } // ... otherwise try to open as XML file catch (GException::fits_open_error &e) { // Load observations from XML file. This will throw // an exception if it fails. m_obs.load(m_infile); // Signal that XML file should be used for storage m_use_xml = true; } } // endelse: loaded information from input file } // endif: there was no observation in the container // If there are no models associated with the observations then // load now the model definition from the XML file if (m_obs.models().size() == 0) { m_obs.models(GModels(m_srcmdl)); } // Check if all CTA observations contain an event cube and setup response // for all observations for (int i = 0; i < m_obs.size(); ++i) { // Is this observation a CTA observation? GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]); // Yes ... if (obs != NULL) { // Throw an exception if this observation does not contain // an event cube if (dynamic_cast<const GCTAEventCube*>(obs->events()) == NULL) { throw GException::no_cube(G_SETUP_OBS); } // Set response if it isn't set already if (obs->response().aeff() == NULL) { // Set calibration database. If specified parameter is a // directory then use this as the pathname to the calibration // database. Otherwise interpret this as the instrument name, // the mission being "cta" GCaldb caldb; if (gammalib::dir_exists(m_caldb)) { caldb.rootdir(m_caldb); } else { caldb.open("cta", m_caldb); } // Set reponse obs->response(m_irf, caldb); } // endif: observation already has a response } // endif: observation was a CTA observation } // endfor: looped over all observations // Return return; }
/***********************************************************************//** * @brief Bin events into a counts map * * @param[in] obs CTA observation. * * @exception GException::no_list * No event list found in observation. * @exception GCTAException::no_pointing * No valid CTA pointing found. * * This method bins the events found in a CTA events list into a counts map * and replaces the event list by the counts map in the observation. The * energy boundaries of the counts map are also stored in the observation's * energy boundary member. * * If the reference values for the map centre (m_xref, m_yref) are 9999.0, * the pointing direction of the observation is taken as the map centre. * Otherwise, the specified reference value is used. ***************************************************************************/ void ctbin::bin_events(GCTAObservation* obs) { // Continue only if observation pointer is valid if (obs != NULL) { // Make sure that the observation holds a CTA event list. If this // is not the case then throw an exception. if (dynamic_cast<const GCTAEventList*>(obs->events()) == NULL) { throw GException::no_list(G_BIN_EVENTS); } // Setup energy range covered by data GEnergy emin; GEnergy emax; GEbounds ebds; emin.TeV(m_emin); emax.TeV(m_emax); ebds.setlog(emin, emax, m_enumbins); // Get Good Time intervals GGti gti = obs->events()->gti(); // Get map centre double xref; double yref; if (m_xref != 9999.0 && m_yref != 9999.0) { xref = m_xref; yref = m_yref; } else { // Get pointer on CTA pointing const GCTAPointing *pnt = obs->pointing(); if (pnt == NULL) { throw GCTAException::no_pointing(G_BIN_EVENTS); } // Set reference point to pointing if (toupper(m_coordsys) == "GAL") { xref = pnt->dir().l_deg(); yref = pnt->dir().b_deg(); } else { xref = pnt->dir().ra_deg(); yref = pnt->dir().dec_deg(); } } // endelse: map centre set to pointing // Create skymap GSkymap map = GSkymap(m_proj, m_coordsys, xref, yref, m_binsz, m_binsz, m_nxpix, m_nypix, m_enumbins); // Initialise binning statistics int num_outside_map = 0; int num_outside_ebds = 0; int num_in_map = 0; // Fill sky map GCTAEventList* events = static_cast<GCTAEventList*>(const_cast<GEvents*>(obs->events())); for (GCTAEventList::iterator event = events->begin(); event != events->end(); ++event) { // Determine sky pixel GCTAInstDir* inst = (GCTAInstDir*)&(event->dir()); GSkyDir dir = inst->dir(); GSkyPixel pixel = map.dir2xy(dir); // Skip if pixel is out of range if (pixel.x() < -0.5 || pixel.x() > (m_nxpix-0.5) || pixel.y() < -0.5 || pixel.y() > (m_nypix-0.5)) { num_outside_map++; continue; } // Determine energy bin. Skip if we are outside the energy range int index = ebds.index(event->energy()); if (index == -1) { num_outside_ebds++; continue; } // Fill event in skymap map(pixel, index) += 1.0; num_in_map++; } // endfor: looped over all events // Log binning results if (logTerse()) { log << std::endl; log.header1("Binning"); log << parformat("Events in list"); log << obs->events()->size() << std::endl; log << parformat("Events in map"); log << num_in_map << std::endl; log << parformat("Events outside map area"); log << num_outside_map << std::endl; log << parformat("Events outside energy bins"); log << num_outside_ebds << std::endl; } // Log map if (logTerse()) { log << std::endl; log.header1("Counts map"); log << map << std::endl; } // Create events cube from sky map GCTAEventCube cube(map, ebds, gti); // Replace event list by event cube in observation obs->events(&cube); } // endif: observation was valid // Return return; }