Commit f8091f657a4fd25d62be9f2232ec409ff08d9151

Authored by Jürgen Knödlseder
2 parents ac71a9ff 0658d867

Merge branch '1439-change-usage-of-binned-observations-in-GCTACube-classes' into integration

inst/cta/include/GCTACubeBackground.hpp
... ... @@ -65,7 +65,7 @@ public:
65 65 void clear(void);
66 66 GCTACubeBackground* clone(void) const;
67 67 std::string classname(void) const;
68   - void fill(const GObservations& obs);
  68 + void fill(const GObservations& obs, GLog* log = NULL);
69 69 double integral(const double& logE) const;
70 70 void read(const GFits& fits);
71 71 void write(GFits& file) const;
... ...
inst/cta/include/GCTACubeExposure.hpp
... ... @@ -74,7 +74,7 @@ public:
74 74 GCTACubeExposure* clone(void) const;
75 75 std::string classname(void) const;
76 76 void set(const GCTAObservation& obs);
77   - void fill(const GObservations& obs);
  77 + void fill(const GObservations& obs, GLog* log = NULL);
78 78 const GSkymap& cube(void) const;
79 79 const GEbounds& ebounds(void) const;
80 80 const GGti& gti(void) const;
... ...
inst/cta/include/GCTACubePsf.hpp
... ... @@ -82,7 +82,7 @@ public:
82 82 GCTACubePsf* clone(void) const;
83 83 std::string classname(void) const;
84 84 void set(const GCTAObservation& obs);
85   - void fill(const GObservations& obs);
  85 + void fill(const GObservations& obs, GLog* log = NULL);
86 86 const GSkymap& map(void) const;
87 87 const GEbounds& ebounds(void) const;
88 88 const GNodeArray& deltas(void) const;
... ...
inst/cta/include/GCTAObservation.hpp
... ... @@ -124,6 +124,7 @@ public:
124 124 void deadc(const double& deadc);
125 125 void eventfile(const std::string& filename);
126 126 const std::string& eventfile(void) const;
  127 + const std::string& eventtype(void) const;
127 128 void dispose_events(void);
128 129 const double& lo_user_thres(void) const;
129 130 const double& hi_user_thres(void) const;
... ... @@ -413,6 +414,18 @@ const std::string& GCTAObservation::eventfile(void) const
413 414  
414 415  
415 416 /***********************************************************************//**
  417 + * @brief Return type of events
  418 + *
  419 + * @return Type of events.
  420 + ***************************************************************************/
  421 +inline
  422 +const std::string& GCTAObservation::eventtype(void) const
  423 +{
  424 + return m_eventtype;
  425 +}
  426 +
  427 +
  428 +/***********************************************************************//**
416 429 * @brief Return user low energy threshold
417 430 *
418 431 * @return User low energy threshold.
... ...
inst/cta/pyext/GCTACubeBackground.i
... ... @@ -52,7 +52,7 @@ public:
52 52 void clear(void);
53 53 GCTACubeBackground* clone(void) const;
54 54 std::string classname(void) const;
55   - void fill(const GObservations& obs);
  55 + void fill(const GObservations& obs, GLog* log = NULL);
56 56 double integral(const double& logE) const;
57 57 void read(const GFits& fits);
58 58 void write(GFits& file) const;
... ...
inst/cta/pyext/GCTACubeExposure.i
... ... @@ -65,7 +65,7 @@ public:
65 65 GCTACubeExposure* clone(void) const;
66 66 std::string classname(void) const;
67 67 void set(const GCTAObservation& obs);
68   - void fill(const GObservations& obs);
  68 + void fill(const GObservations& obs, GLog* log = NULL);
69 69 const GSkymap& cube(void) const;
70 70 const GEbounds& ebounds(void) const;
71 71 const GGti& gti(void) const;
... ...
inst/cta/pyext/GCTACubePsf.i
... ... @@ -74,7 +74,7 @@ public:
74 74 GCTACubePsf* clone(void) const;
75 75 std::string classname(void) const;
76 76 void set(const GCTAObservation& obs);
77   - void fill(const GObservations& obs);
  77 + void fill(const GObservations& obs, GLog* log = NULL);
78 78 const GSkymap& map(void) const;
79 79 const GEbounds& ebounds(void) const;
80 80 const GNodeArray& deltas(void) const;
... ...
inst/cta/pyext/GCTAObservation.i
... ... @@ -96,6 +96,7 @@ public:
96 96 void deadc(const double& deadc);
97 97 void eventfile(const std::string& filename);
98 98 const std::string& eventfile(void) const;
  99 + const std::string& eventtype(void) const;
99 100 void dispose_events(void);
100 101 const double& lo_user_thres(void) const;
101 102 const double& hi_user_thres(void) const;
... ...
inst/cta/src/GCTACubeBackground.cpp
... ... @@ -40,6 +40,7 @@
40 40 #include "GCTARoi.hpp"
41 41 #include "GCTAInstDir.hpp"
42 42 #include "GCTACubeBackground.hpp"
  43 +#include "GLog.hpp"
43 44  
44 45 /* __ Method name definitions ____________________________________________ */
45 46 #define G_READ "GCTACubeBackground::read(GFits&)"
... ... @@ -263,6 +264,7 @@ GCTACubeBackground* GCTACubeBackground::clone(void) const
263 264 * @brief Fill background cube from observation container
264 265 *
265 266 * @param[in] obs Observation container.
  267 + * @param[in] log Pointer to logger (optional).
266 268 *
267 269 * @exception GException::invalid_value
268 270 * No event list found in CTA observations.
... ... @@ -271,7 +273,7 @@ GCTACubeBackground* GCTACubeBackground::clone(void) const
271 273 * for all CTA observations in an observation container. The cube pixel
272 274 * values are computed as the sum over the background rates.
273 275 ***************************************************************************/
274   -void GCTACubeBackground::fill(const GObservations& obs)
  276 +void GCTACubeBackground::fill(const GObservations& obs, GLog* log)
275 277 {
276 278 // Clear background cube
277 279 m_cube = 0.0;
... ... @@ -288,49 +290,63 @@ void GCTACubeBackground::fill(const GObservations& obs)
288 290 // Get observation and continue only if it is a CTA observation
289 291 const GCTAObservation* cta = dynamic_cast<const GCTAObservation*>(obs[i]);
290 292  
291   - if (cta != NULL) {
  293 + // Skip observation if it's not CTA
  294 + if (cta == NULL) {
  295 + if (log != NULL) {
  296 + *log << "Warning: Skipping "+obs[i]->instrument()+" observation ";
  297 + *log << "\"" << obs[i]->name() << "\"" <<std::endl;
  298 + }
  299 + continue;
  300 + }
292 301  
293   - // Extract region of interest from CTA observation
294   - GCTARoi roi = cta->roi();
  302 + // Skip observation if we don't have an unbinned observation
  303 + if (cta->eventtype() != "EventList") {
  304 + if (log != NULL) {
  305 + *log << "Warning: Skipping binned observation ";
  306 + *log << "\"" << cta->name() << "\"" <<std::endl;
  307 + }
  308 + continue;
  309 + }
295 310  
296   - // Set GTI of actual observations as the GTI of the event cube
297   - eventcube.gti(cta->gti());
  311 + // Extract region of interest from CTA observation
  312 + GCTARoi roi = cta->roi();
298 313  
299   - // Get observation livetime
300   - double livetime = cta->livetime();
  314 + // Set GTI of actual observations as the GTI of the event cube
  315 + eventcube.gti(cta->gti());
301 316  
302   - // Loop over all bins in background cube
303   - for (int i = 0; i < eventcube.size(); ++i) {
  317 + // Get observation livetime
  318 + double livetime = cta->livetime();
304 319  
305   - // Get event bin
306   - GCTAEventBin* bin = eventcube[i];
  320 + // Loop over all bins in background cube
  321 + for (int i = 0; i < eventcube.size(); ++i) {
307 322  
308   - // Continue only if binned in contained in ROI
309   - if (roi.contains(*bin)) {
  323 + // Get event bin
  324 + GCTAEventBin* bin = eventcube[i];
310 325  
311   - // Compute model value for event bin. The model value is
312   - // given in counts/MeV/s/sr.
313   - double model = obs.models().eval(*bin, *cta);
  326 + // Continue only if binned in contained in ROI
  327 + if (roi.contains(*bin)) {
314 328  
315   - // Multiply by livetime to get the correct weighting for
316   - // each observation. We divide by the total livetime later
317   - // to get the background model in units of counts/MeV/s/sr.
318   - model *= livetime;
  329 + // Compute model value for event bin. The model value is
  330 + // given in counts/MeV/s/sr.
  331 + double model = obs.models().eval(*bin, *cta);
319 332  
320   - // Add existing number of counts
321   - model += bin->counts();
  333 + // Multiply by livetime to get the correct weighting for
  334 + // each observation. We divide by the total livetime later
  335 + // to get the background model in units of counts/MeV/s/sr.
  336 + model *= livetime;
322 337  
323   - // Store cumulated value (units: counts/MeV/sr)
324   - bin->counts(model);
  338 + // Add existing number of counts
  339 + model += bin->counts();
325 340  
326   - } // endif: bin was contained in RoI
  341 + // Store cumulated value (units: counts/MeV/sr)
  342 + bin->counts(model);
327 343  
328   - } // endfor: looped over all bins
  344 + } // endif: bin was contained in RoI
329 345  
330   - // Accumulate livetime
331   - total_livetime += livetime;
  346 + } // endfor: looped over all bins
332 347  
333   - } // endif: cta observation was vaild
  348 + // Accumulate livetime
  349 + total_livetime += livetime;
334 350  
335 351 } // endfor: looped over all observations
336 352  
... ...
inst/cta/src/GCTACubeExposure.cpp
... ... @@ -34,6 +34,7 @@
34 34 #include "GCTAEventList.hpp"
35 35 #include "GMath.hpp"
36 36 #include "GTools.hpp"
  37 +#include "GLog.hpp"
37 38  
38 39 /* __ Method name definitions ____________________________________________ */
39 40  
... ... @@ -298,55 +299,61 @@ GCTACubeExposure* GCTACubeExposure::clone(void) const
298 299 ***************************************************************************/
299 300 void GCTACubeExposure::set(const GCTAObservation& obs)
300 301 {
301   - // Clear GTIs, reset livetime and exposure cube pixels
302   - m_gti.clear();
303   - m_livetime = 0.0;
304   - m_cube = 0.0;
305 302  
306   - // Extract region of interest from CTA observation
307   - GCTARoi roi = obs.roi();
  303 + // Only continue if we have an unbinned observation
  304 + if (obs.eventtype() == "EventList") {
308 305  
309   - // Get references on CTA response and pointing direction
310   - const GCTAResponseIrf* rsp = dynamic_cast<const GCTAResponseIrf*>(obs.response());
311   - const GSkyDir& pnt = obs.pointing().dir();
  306 + // Clear GTIs, reset livetime and exposure cube pixels
  307 + m_gti.clear();
  308 + m_livetime = 0.0;
  309 + m_cube = 0.0;
312 310  
313   - // Continue only if response is valid
314   - if (rsp != NULL) {
  311 + // Extract region of interest from CTA observation
  312 + GCTARoi roi = obs.roi();
315 313  
316   - // Loop over all pixels in sky map
317   - for (int pixel = 0; pixel < m_cube.npix(); ++pixel) {
  314 + // Get references on CTA response and pointing direction
  315 + const GCTAResponseIrf* rsp = dynamic_cast<const GCTAResponseIrf*>(obs.response());
  316 + const GSkyDir& pnt = obs.pointing().dir();
318 317  
319   - // Get pixel sky direction
320   - GSkyDir dir = m_cube.inx2dir(pixel);
321   -
322   - // Continue only if pixel is within RoI
323   - if (roi.centre().dir().dist_deg(dir) <= roi.radius()) {
  318 + // Continue only if response is valid
  319 + if (rsp != NULL) {
324 320  
325   - // Compute theta angle with respect to pointing direction
326   - // in radians
327   - double theta = pnt.dist(dir);
328   -
329   - // Loop over all exposure cube energy bins
330   - for (int iebin = 0; iebin < m_ebounds.size(); ++iebin){
  321 + // Loop over all pixels in sky map
  322 + for (int pixel = 0; pixel < m_cube.npix(); ++pixel) {
331 323  
332   - // Get logE/TeV
333   - double logE = m_ebounds.elogmean(iebin).log10TeV();
  324 + // Get pixel sky direction
  325 + GSkyDir dir = m_cube.inx2dir(pixel);
334 326  
335   - // Set exposure cube (effective area * lifetime)
336   - m_cube(pixel, iebin) = rsp->aeff(theta, 0.0, 0.0, 0.0, logE) *
337   - obs.livetime();
  327 + // Continue only if pixel is within RoI
  328 + if (roi.centre().dir().dist_deg(dir) <= roi.radius()) {
338 329  
339   - } // endfor: looped over energy bins
  330 + // Compute theta angle with respect to pointing direction
  331 + // in radians
  332 + double theta = pnt.dist(dir);
340 333  
341   - } // endif: pixel was within RoI
  334 + // Loop over all exposure cube energy bins
  335 + for (int iebin = 0; iebin < m_ebounds.size(); ++iebin){
342 336  
343   - } // endfor: looped over all pixels
  337 + // Get logE/TeV
  338 + double logE = m_ebounds.elogmean(iebin).log10TeV();
344 339  
345   - // Append GTIs and increment livetime
346   - m_gti.extend(obs.gti());
347   - m_livetime += obs.livetime();
  340 + // Set exposure cube (effective area * lifetime)
  341 + m_cube(pixel, iebin) = rsp->aeff(theta, 0.0, 0.0, 0.0, logE) *
  342 + obs.livetime();
  343 +
  344 + } // endfor: looped over energy bins
  345 +
  346 + } // endif: pixel was within RoI
  347 +
  348 + } // endfor: looped over all pixels
348 349  
349   - } // endif: response was valid
  350 + // Append GTIs and increment livetime
  351 + m_gti.extend(obs.gti());
  352 + m_livetime += obs.livetime();
  353 +
  354 + } // endif: response was valid
  355 +
  356 + } // endif: observation was unbinned
350 357  
351 358 // Return
352 359 return;
... ... @@ -357,6 +364,7 @@ void GCTACubeExposure::set(const GCTAObservation&amp; obs)
357 364 * @brief Fill exposure cube from observation container
358 365 *
359 366 * @param[in] obs Observation container.
  367 + * @param[in] log Pointer to logger (optional).
360 368 *
361 369 * @exception GException::invalid_value
362 370 * No event list found in CTA observations.
... ... @@ -365,7 +373,7 @@ void GCTACubeExposure::set(const GCTAObservation&amp; obs)
365 373 * an observation container. The cube pixel values are computed as the sum
366 374 * over the products of the effective area and the livetime.
367 375 ***************************************************************************/
368   -void GCTACubeExposure::fill(const GObservations& obs)
  376 +void GCTACubeExposure::fill(const GObservations& obs, GLog* log)
369 377 {
370 378 // Clear GTIs, reset livetime and exposure cube pixels
371 379 m_gti.clear();
... ... @@ -377,55 +385,74 @@ void GCTACubeExposure::fill(const GObservations&amp; obs)
377 385  
378 386 // Get observation and continue only if it is a CTA observation
379 387 const GCTAObservation* cta = dynamic_cast<const GCTAObservation*>(obs[i]);
380   - if (cta != NULL) {
381 388  
382   - // Extract region of interest from CTA observation
383   - GCTARoi roi = cta->roi();
  389 + // Skip observation if it's not CTA
  390 + if (cta == NULL) {
  391 + if (log != NULL) {
  392 + *log << "Warning: Skipping "+obs[i]->instrument()+" observation ";
  393 + *log << "\"" << obs[i]->name() << "\"" <<std::endl;
  394 + }
  395 + continue;
  396 + }
  397 +
  398 + // Skip observation if we don't have an unbinned observation
  399 + if (cta->eventtype() != "EventList") {
  400 + if (log != NULL) {
  401 + *log << "Warning: Skipping binned observation ";
  402 + *log << "\"" << cta->name() << "\"" <<std::endl;
  403 + }
  404 + continue;
  405 + }
  406 +
  407 + // Extract region of interest from CTA observation
  408 + GCTARoi roi = cta->roi();
384 409  
385   - // Get references on CTA response and pointing direction
386   - const GCTAResponseIrf* rsp = dynamic_cast<const GCTAResponseIrf*>(cta->response());
387   - const GSkyDir& pnt = cta->pointing().dir();
  410 + // Get references on CTA response and pointing direction
  411 + const GCTAResponseIrf* rsp = dynamic_cast<const GCTAResponseIrf*>(cta->response());
  412 + const GSkyDir& pnt = cta->pointing().dir();
388 413  
389   - // Continue only if response is valid
390   - if (rsp != NULL) {
  414 + // Skip observation if we don't have an unbinned observation
  415 + if (rsp == NULL) {
  416 + if (log != NULL) {
  417 + *log << "Warning: Observation \"" << cta->name();
  418 + *log << "\" contains no IRF response." <<std::endl;
  419 + }
  420 + continue;
  421 + }
391 422  
392   - // Loop over all pixels in sky map
393   - for (int pixel = 0; pixel < m_cube.npix(); ++pixel) {
  423 + // Loop over all pixels in sky map
  424 + for (int pixel = 0; pixel < m_cube.npix(); ++pixel) {
394 425  
395   - // Get pixel sky direction
396   - GSkyDir dir = m_cube.inx2dir(pixel);
  426 + // Get pixel sky direction
  427 + GSkyDir dir = m_cube.inx2dir(pixel);
397 428  
398   - // Continue only if pixel is within RoI
399   - if (roi.centre().dir().dist_deg(dir) <= roi.radius()) {
  429 + // Continue only if pixel is within RoI
  430 + if (roi.centre().dir().dist_deg(dir) <= roi.radius()) {
400 431  
401   - // Compute theta angle with respect to pointing
402   - // direction in radians
403   - double theta = pnt.dist(dir);
404   -
405   - // Loop over all exposure cube energy bins
406   - for (int iebin = 0; iebin < m_ebounds.size(); ++iebin){
  432 + // Compute theta angle with respect to pointing
  433 + // direction in radians
  434 + double theta = pnt.dist(dir);
  435 +
  436 + // Loop over all exposure cube energy bins
  437 + for (int iebin = 0; iebin < m_ebounds.size(); ++iebin){
407 438  
408   - // Get logE/TeV
409   - double logE = m_ebounds.elogmean(iebin).log10TeV();
  439 + // Get logE/TeV
  440 + double logE = m_ebounds.elogmean(iebin).log10TeV();
410 441  
411   - // Add to exposure cube (effective area * livetime)
412   - m_cube(pixel, iebin) += rsp->aeff(theta, 0.0, 0.0, 0.0, logE) *
413   - cta->livetime();
  442 + // Add to exposure cube (effective area * livetime)
  443 + m_cube(pixel, iebin) += rsp->aeff(theta, 0.0, 0.0, 0.0, logE) *
  444 + cta->livetime();
414 445  
415   - } // endfor: looped over energy bins
  446 + } // endfor: looped over energy bins
416 447  
417   - } // endif: pixel within RoI
  448 + } // endif: pixel within RoI
418 449  
419   - } // endfor: looped over all pixels
  450 + } // endfor: looped over all pixels
420 451  
421   - // Append GTIs and increment livetime
422   - m_gti.extend(cta->gti());
423   - m_livetime += cta->livetime();
  452 + // Append GTIs and increment livetime
  453 + m_gti.extend(cta->gti());
  454 + m_livetime += cta->livetime();
424 455  
425   - } // endif: response was valid
426   -
427   - } // endif: observation was a CTA observation
428   -
429 456 } // endfor: looped over observations
430 457  
431 458 // Return
... ...
inst/cta/src/GCTACubePsf.cpp
... ... @@ -34,6 +34,7 @@
34 34 #include "GCTAEventList.hpp"
35 35 #include "GMath.hpp"
36 36 #include "GTools.hpp"
  37 +#include "GLog.hpp"
37 38  
38 39 /* __ Method name definitions ____________________________________________ */
39 40 #define G_SET "GCTACubePsf::set(GCTAObservation&)"
... ... @@ -357,64 +358,69 @@ void GCTACubePsf::set(const GCTAObservation&amp; obs)
357 358 // Clear PSF cube
358 359 clear_cube();
359 360  
360   - // Extract region of interest from CTA observation
361   - const GCTAEventList* list = dynamic_cast<const GCTAEventList*>(obs.events());
362   - if (list == NULL) {
363   - std::string msg = "CTA Observation does not contain an event "
364   - "list. Event list information is needed to "
365   - "retrieve the Region of Interest for each "
366   - "CTA observation.";
367   - throw GException::invalid_value(G_SET, msg);
368   - }
369   - const GCTARoi& roi = list->roi();
  361 + // Only continue if we have an unbinned observation
  362 + if (obs.eventtype() == "EventList") {
  363 +
  364 + // Extract region of interest from CTA observation
  365 + const GCTAEventList* list = dynamic_cast<const GCTAEventList*>(obs.events());
  366 + if (list == NULL) {
  367 + std::string msg = "CTA Observation does not contain an event "
  368 + "list. Event list information is needed to "
  369 + "retrieve the Region of Interest for each "
  370 + "CTA observation.";
  371 + throw GException::invalid_value(G_SET, msg);
  372 + }
  373 + const GCTARoi& roi = list->roi();
370 374  
371   - // Get references on CTA response and pointing direction
372   - const GCTAResponseIrf* rsp = dynamic_cast<const GCTAResponseIrf*>(obs.response());
373   - const GSkyDir& pnt = obs.pointing().dir();
  375 + // Get references on CTA response and pointing direction
  376 + const GCTAResponseIrf* rsp = dynamic_cast<const GCTAResponseIrf*>(obs.response());
  377 + const GSkyDir& pnt = obs.pointing().dir();
374 378  
375   - // Continue only if response is valid
376   - if (rsp != NULL) {
  379 + // Continue only if response is valid
  380 + if (rsp != NULL) {
377 381  
378   - // Loop over all pixels in sky map
379   - for (int pixel = 0; pixel < m_cube.npix(); ++pixel) {
  382 + // Loop over all pixels in sky map
  383 + for (int pixel = 0; pixel < m_cube.npix(); ++pixel) {
  384 +
  385 + // Get pixel sky direction
  386 + GSkyDir dir = m_cube.inx2dir(pixel);
  387 +
  388 + // Continue only if pixel is within RoI
  389 + if (roi.centre().dir().dist_deg(dir) <= roi.radius()) {
380 390  
381   - // Get pixel sky direction
382   - GSkyDir dir = m_cube.inx2dir(pixel);
383   -
384   - // Continue only if pixel is within RoI
385   - if (roi.centre().dir().dist_deg(dir) <= roi.radius()) {
  391 + // Compute theta angle with respect to pointing direction
  392 + // in radians
  393 + double theta = pnt.dist(dir);
386 394  
387   - // Compute theta angle with respect to pointing direction
388   - // in radians
389   - double theta = pnt.dist(dir);
390   -
391   - // Loop over all exposure cube energy bins
392   - for (int iebin = 0; iebin < m_ebounds.size(); ++iebin){
  395 + // Loop over all exposure cube energy bins
  396 + for (int iebin = 0; iebin < m_ebounds.size(); ++iebin){
393 397  
394   - // Get logE/TeV
395   - double logE = m_ebounds.elogmean(iebin).log10TeV();
  398 + // Get logE/TeV
  399 + double logE = m_ebounds.elogmean(iebin).log10TeV();
396 400  
397   - // Loop over delta values
398   - for (int idelta = 0; idelta < m_deltas.size(); ++idelta) {
  401 + // Loop over delta values
  402 + for (int idelta = 0; idelta < m_deltas.size(); ++idelta) {
399 403  
400   - // Compute delta in radians
401   - double delta = m_deltas[idelta] * gammalib::deg2rad;
  404 + // Compute delta in radians
  405 + double delta = m_deltas[idelta] * gammalib::deg2rad;
402 406  
403   - // Set map index
404   - int imap = offset(idelta, iebin);
405   -
406   - // Set PSF cube
407   - m_cube(pixel, imap) = rsp->psf(delta, theta, 0.0, 0.0, 0.0, logE);
  407 + // Set map index
  408 + int imap = offset(idelta, iebin);
408 409  
409   - } // endfor: looped over delta bins
  410 + // Set PSF cube
  411 + m_cube(pixel, imap) = rsp->psf(delta, theta, 0.0, 0.0, 0.0, logE);
410 412  
411   - } // endfor: looped over energy bins
  413 + } // endfor: looped over delta bins
412 414  
413   - } // endif: pixel was within RoI
  415 + } // endfor: looped over energy bins
414 416  
415   - } // endfor: looped over all pixels
  417 + } // endif: pixel was within RoI
416 418  
417   - } // endif: response was valid
  419 + } // endfor: looped over all pixels
  420 +
  421 + } // endif: response was valid
  422 +
  423 + } // endif: observation was unbinned
418 424  
419 425 // Compile option: guarantee smooth Psf
420 426 #if defined(G_SMOOTH_PSF)
... ... @@ -431,7 +437,7 @@ void GCTACubePsf::set(const GCTAObservation&amp; obs)
431 437 *
432 438 * @param[in] obs Observation container.
433 439 ***************************************************************************/
434   -void GCTACubePsf::fill(const GObservations& obs)
  440 +void GCTACubePsf::fill(const GObservations& obs, GLog* log)
435 441 {
436 442 // Clear PSF cube
437 443 clear_cube();
... ... @@ -444,68 +450,87 @@ void GCTACubePsf::fill(const GObservations&amp; obs)
444 450  
445 451 // Get observation and continue only if it is a CTA observation
446 452 const GCTAObservation* cta = dynamic_cast<const GCTAObservation*>(obs[i]);
447   - if (cta != NULL) {
448 453  
449   - // Extract region of interest from CTA observation
450   - GCTARoi roi = cta->roi();
  454 + // Skip observation if it's not CTA
  455 + if (cta == NULL) {
  456 + if (log != NULL) {
  457 + *log << "Warning: Skipping "+obs[i]->instrument()+" observation ";
  458 + *log << "\"" << obs[i]->name() << "\"" <<std::endl;
  459 + }
  460 + continue;
  461 + }
451 462  
452   - // Get references on CTA response and pointing direction
453   - const GCTAResponseIrf* rsp = dynamic_cast<const GCTAResponseIrf*>(cta->response());
454   - const GSkyDir& pnt = cta->pointing().dir();
  463 + // Skip observation if we don't have an unbinned observation
  464 + if (cta->eventtype() != "EventList") {
  465 + if (log != NULL) {
  466 + *log << "Warning: Skipping binned observation ";
  467 + *log << "\"" << cta->name() << "\"" <<std::endl;
  468 + }
  469 + continue;
  470 + }
455 471  
456   - // Continue only if response is valid
457   - if (rsp != NULL) {
  472 + // Extract region of interest from CTA observation
  473 + GCTARoi roi = cta->roi();
458 474  
459   - // Loop over all pixels in sky map
460   - for (int pixel = 0; pixel < m_cube.npix(); ++pixel) {
  475 + // Get references on CTA response and pointing direction
  476 + const GCTAResponseIrf* rsp = dynamic_cast<const GCTAResponseIrf*>(cta->response());
  477 + const GSkyDir& pnt = cta->pointing().dir();
461 478  
462   - // Get pixel sky direction
463   - GSkyDir dir = m_cube.inx2dir(pixel);
464   -
465   - // Continue only if pixel is within RoI
466   - if (roi.centre().dir().dist_deg(dir) <= roi.radius()) {
  479 + // Skip observation if we don't have an unbinned observation
  480 + if (rsp == NULL) {
  481 + if (log != NULL) {
  482 + *log << "Warning: Observation \"" << cta->name();
  483 + *log << "\" contains no IRF response." <<std::endl;
  484 + }
  485 + continue;
  486 + }
467 487  
468   - // Compute theta angle with respect to pointing
469   - // direction in radians
470   - double theta = pnt.dist(dir);
471   -
472   - // Loop over all energy bins
473   - for (int iebin = 0; iebin < m_ebounds.size(); ++iebin) {
  488 + // Loop over all pixels in sky map
  489 + for (int pixel = 0; pixel < m_cube.npix(); ++pixel) {
474 490  
475   - // Get logE/TeV
476   - double logE = m_ebounds.elogmean(iebin).log10TeV();
  491 + // Get pixel sky direction
  492 + GSkyDir dir = m_cube.inx2dir(pixel);
  493 +
  494 + // Continue only if pixel is within RoI
  495 + if (roi.centre().dir().dist_deg(dir) <= roi.radius()) {
477 496  
478   - // Compute exposure weight
479   - double weight = rsp->aeff(theta, 0.0, 0.0, 0.0, logE) *
480   - cta->livetime();
  497 + // Compute theta angle with respect to pointing
  498 + // direction in radians
  499 + double theta = pnt.dist(dir);
481 500  
482   - // Accumulate weights
483   - exposure(pixel, iebin) += weight;
  501 + // Loop over all energy bins
  502 + for (int iebin = 0; iebin < m_ebounds.size(); ++iebin) {
484 503  
485   - // Loop over delta values
486   - for (int idelta = 0; idelta < m_deltas.size(); ++idelta) {
  504 + // Get logE/TeV
  505 + double logE = m_ebounds.elogmean(iebin).log10TeV();
487 506  
488   - // Compute delta in radians
489   - double delta = m_deltas[idelta] * gammalib::deg2rad;
  507 + // Compute exposure weight
  508 + double weight = rsp->aeff(theta, 0.0, 0.0, 0.0, logE) *
  509 + cta->livetime();
490 510  
491   - // Set map index
492   - int imap = offset(idelta, iebin);
  511 + // Accumulate weights
  512 + exposure(pixel, iebin) += weight;
493 513  
494   - // Add on PSF cube
495   - m_cube(pixel, imap) +=
496   - rsp->psf(delta, theta, 0.0, 0.0, 0.0, logE) * weight;
  514 + // Loop over delta values
  515 + for (int idelta = 0; idelta < m_deltas.size(); ++idelta) {
497 516  
498   - } // endfor: looped over delta bins
  517 + // Compute delta in radians
  518 + double delta = m_deltas[idelta] * gammalib::deg2rad;
499 519  
500   - } // endfor: looped over energy bins
  520 + // Set map index
  521 + int imap = offset(idelta, iebin);
  522 +
  523 + // Add on PSF cube
  524 + m_cube(pixel, imap) +=
  525 + rsp->psf(delta, theta, 0.0, 0.0, 0.0, logE) * weight;
501 526  
502   - } // endif: pixel was within RoI
  527 + } // endfor: looped over delta bins
503 528  
504   - } // endfor: looped over all pixels
  529 + } // endfor: looped over energy bins
505 530  
506   - } // endif: response was valid
  531 + } // endif: pixel was within RoI
507 532  
508   - } // endif: observation was a CTA observation
  533 + } // endfor: looped over all pixels
509 534  
510 535 } // endfor: looped over observations
511 536  
... ...