Commit 907508c6949c7259b06e917dc5466c3bcbe955c4

Authored by Jürgen Knödlseder
2 parents 40d6cfa9 5c3a8508

Merge branch '1439-adapt-ctools-to-consistently-handle-observation-types' into integration

scripts/cslightcrv.py
... ... @@ -107,7 +107,7 @@ class cslightcrv(ctools.cscript):
107 107 pars.append(gammalib.GApplicationPar("bkgcube","s","a","NONE","","","Background cube file (only needed for stacked analysis)"))
108 108 pars.append(gammalib.GApplicationPar("caldb","s","a","prod2","","","Calibration database"))
109 109 pars.append(gammalib.GApplicationPar("irf","s","a","South_50h","","","Instrument response function"))
110   - pars.append(gammalib.GApplicationPar("tbinalg","s","h","GTI","FILE|LIN|GTI","", "Algorithm for defining time bins"))
  110 + pars.append(gammalib.GApplicationPar("tbinalg","s","a","GTI","FILE|LIN|GTI","", "Algorithm for defining time bins"))
111 111 pars.append(gammalib.GApplicationPar("tmin","r","a","51544.5","","days","Lightcurve start time [MJD]"))
112 112 pars.append(gammalib.GApplicationPar("tmax","r","a","51544.6","","days","Lightcurve stop time [MJD]"))
113 113 pars.append(gammalib.GApplicationPar("tbins","i","a","5","","","Number of time bins"))
... ...
src/ctbin/ctbin.cpp
... ... @@ -244,26 +244,40 @@ void ctbin::run(void)
244 244 // Get CTA observation
245 245 GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]);
246 246  
247   - // Continue only if observation is a CTA observation
248   - if (obs != NULL) {
  247 + // Skip observation if it's not CTA
  248 + if (obs == NULL) {
  249 + if (logTerse()) {
  250 + log << "Warning: Skipping "+m_obs[i]->instrument();
  251 + log << " observation \"";
  252 + log << m_obs[i]->name() << "\"" << std::endl;
  253 + }
  254 + continue;
  255 + }
249 256  
250   - // Write header for observation
  257 + // Skip observation if we have a binned observation
  258 + if (obs->eventtype() == "CountsCube") {
251 259 if (logTerse()) {
252   - if (obs->name().length() > 1) {
253   - log.header3("Observation "+obs->name());
254   - }
255   - else {
256   - log.header3("Observation");
257   - }
  260 + log << "Warning: Skipping binned observation \"";
  261 + log << obs->name()+"\"" << std::endl;
258 262 }
  263 + continue;
  264 + }
259 265  
260   - // Fill the cube
261   - fill_cube(obs);
  266 + // Write header for observation
  267 + if (logTerse()) {
  268 + if (obs->name().length() > 1) {
  269 + log.header3("Observation "+obs->name());
  270 + }
  271 + else {
  272 + log.header3("Observation");
  273 + }
  274 + }
262 275  
263   - // Dispose events to free memory
264   - obs->dispose_events();
  276 + // Fill the cube
  277 + fill_cube(obs);
265 278  
266   - } // endif: CTA observation found
  279 + // Dispose events to free memory
  280 + obs->dispose_events();
267 281  
268 282 } // endfor: looped over observations
269 283  
... ... @@ -561,11 +575,25 @@ void ctbin::obs_cube(void)
561 575 // Attach event cube to CTA observation
562 576 GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[0]);
563 577 if (obs != NULL) {
564   - obs->events(this->cube());
565   - obs->eventfile("");
566   - }
567 578  
568   - }
  579 + // Only change the event type if we had an unbinned observation
  580 + if (obs->eventtype() == "EventList") {
  581 +
  582 + obs->events(this->cube());
  583 + obs->eventfile("");
  584 + } // endif: observation was unbinned
  585 + else { // input observation was binned and skipped
  586 +
  587 + // Create new and empty cube
  588 + GCTAEventCube cube = GCTAEventCube(m_cube, m_ebounds, obs->gti());
  589 +
  590 + // Assign empty cube to have a new binned observation
  591 + obs->events(cube);
  592 + }
  593 +
  594 + } // endif: obervation was valid
  595 +
  596 + } // endif: we only had one observation in the container
569 597  
570 598 // ... otherwise put a single CTA observation in container
571 599 else {
... ...
src/ctbkgcube/ctbkgcube.cpp
... ... @@ -308,7 +308,7 @@ void ctbkgcube::run(void)
308 308 m_obs.models(m_bkgmdl);
309 309  
310 310 // Fill background cube from observations
311   - m_background.fill(m_obs);
  311 + m_background.fill(m_obs, &log);
312 312  
313 313 // Create a background model for the output background cube and append
314 314 // that model to the input model in place of the original
... ...
src/ctexpcube/ctexpcube.cpp
... ... @@ -248,7 +248,7 @@ void ctexpcube::run(void)
248 248 }
249 249  
250 250 // Fill exposure
251   - m_expcube.fill(m_obs);
  251 + m_expcube.fill(m_obs, &log);
252 252  
253 253 // Restore energy dispersion flag for all CTA observations
254 254 for (int i = 0; i < m_obs.size(); ++i) {
... ...
src/ctmodel/ctmodel.cpp
... ... @@ -427,7 +427,7 @@ void ctmodel::get_parameters(void)
427 427 // If there are no observations in container then load them via user
428 428 // parameters
429 429 if (m_obs.size() == 0) {
430   - get_obs();
  430 + m_obs = get_observations();
431 431 }
432 432  
433 433 // Read model definition file if required
... ... @@ -505,126 +505,6 @@ void ctmodel::get_parameters(void)
505 505  
506 506  
507 507 /***********************************************************************//**
508   - * @brief Get observation container
509   - *
510   - * Get an observation container according to the user parameters. The method
511   - * supports loading of a individual FITS file or an observation definition
512   - * file in XML format. If the input filename is empty, parameters are read
513   - * to build a CTA observation from scratch.
514   - ***************************************************************************/
515   -void ctmodel::get_obs(void)
516   -{
517   - // Get the filename from the input parameters
518   - std::string filename = (*this)["inobs"].filename();
519   -
520   - // If no observation definition file has been specified then read all
521   - // parameters that are necessary to create an observation from scratch
522   - if ((filename == "NONE") || (gammalib::strip_whitespace(filename) == "")) {
523   -
524   - // Get response cube filenames
525   - std::string expcube = (*this)["expcube"].filename();
526   - std::string psfcube = (*this)["psfcube"].filename();
527   - std::string bkgcube = (*this)["bkgcube"].filename();
528   -
529   - // If the filenames are valid then build an observation from cube
530   - // response information
531   - if ((expcube != "NONE") && (psfcube != "NONE") && (bkgcube != "NONE") &&
532   - (gammalib::strip_whitespace(expcube) != "") &&
533   - (gammalib::strip_whitespace(psfcube) != "") &&
534   - (gammalib::strip_whitespace(bkgcube) != "")) {
535   -
536   - // Get exposure, PSF and background cubes
537   - GCTACubeExposure exposure(expcube);
538   - GCTACubePsf psf(psfcube);
539   - GCTACubeBackground background(bkgcube);
540   -
541   - // Create energy boundaries
542   - GEbounds ebounds = create_ebounds();
543   -
544   - // Create dummy sky map cube
545   - GSkymap map("CAR","GAL",0.0,0.0,1.0,1.0,1,1,ebounds.size());
546   - m_append_cube = true;
547   -
548   - // Create event cube
549   - GCTAEventCube cube(map, ebounds, exposure.gti());
550   -
551   - // Create CTA observation
552   - GCTAObservation cta;
553   - cta.events(cube);
554   - cta.response(exposure, psf, background);
555   -
556   - // Append observation to container
557   - m_obs.append(cta);
558   -
559   - } // endif: cube response information was available
560   -
561   - // ... otherwise build an observation from IRF response information
562   - else {
563   -
564   - // Create CTA observation
565   - GCTAObservation cta = create_cta_obs();
566   -
567   - // Set response
568   - set_obs_response(&cta);
569   -
570   - // Append observation to container
571   - m_obs.append(cta);
572   -
573   - }
574   -
575   - } // endif: filename was "NONE" or ""
576   -
577   - // ... otherwise we have a file name
578   - else {
579   -
580   - // If file is a FITS file then create an empty CTA observation
581   - // and load file into observation
582   - if (gammalib::is_fits(filename)) {
583   -
584   - // Allocate empty CTA observation
585   - GCTAObservation cta;
586   -
587   - // Load data
588   - cta.load(filename);
589   -
590   - // Set response
591   - set_obs_response(&cta);
592   -
593   - // Append observation to container
594   - m_obs.append(cta);
595   -
596   - // Signal that no XML file should be used for storage
597   - m_use_xml = false;
598   -
599   - }
600   -
601   - // ... otherwise load file into observation container
602   - else {
603   -
604   - // Load observations from XML file
605   - m_obs.load(filename);
606   -
607   - // For all observations that have no response, set the response
608   - // from the task parameters
609   - set_response(m_obs);
610   -
611   - // Set observation boundary parameters (emin, emax, rad)
612   - set_obs_bounds(m_obs);
613   -
614   - // Signal that XML file should be used for storage
615   - m_use_xml = true;
616   -
617   - } // endelse: file was an XML file
618   -
619   - }
620   -
621   - // Return
622   - return;
623   -
624   -}
625   -
626   -
627   -/***********************************************************************//**
628 508 * @brief Fill model into model cube
629 509 *
630 510 * @param[in] obs CTA observation.
... ...
src/ctmodel/ctmodel.hpp
... ... @@ -79,7 +79,6 @@ protected:
79 79 void copy_members(const ctmodel& app);
80 80 void free_members(void);
81 81 void get_parameters(void);
82   - void get_obs(void);
83 82 void fill_cube(const GCTAObservation* obs);
84 83 bool has_cube(void) const;
85 84  
... ...
src/ctobssim/ctobssim.cpp
... ... @@ -327,82 +327,89 @@ void ctobssim::run(void)
327 327 // Get pointer on CTA observation
328 328 GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]);
329 329  
330   - // Continue only if observation is a CTA observation
331   - if (obs != NULL) {
  330 + // Skip observation if it's not CTA
  331 + if (obs == NULL) {
  332 + if (logTerse()) {
  333 + log << "Warning: Skipping "+m_obs[i]->instrument();
  334 + log << " observation \"";
  335 + log << m_obs[i]->name() << "\"" << std::endl;
  336 + }
  337 + continue;
  338 + }
332 339  
333   - // Write header for observation
  340 + // Skip observation if we have a binned observation
  341 + if (obs->eventtype() == "CountsCube") {
334 342 if (logTerse()) {
335   - if (obs->name().length() > 1) {
336   - wrklog.header3("Observation "+obs->name());
337   - }
338   - else {
339   - wrklog.header3("Observation");
340   - }
  343 + log << "Warning: Skipping binned observation \"";
  344 + log << obs->name()+"\"" << std::endl;
341 345 }
  346 + continue;
  347 + }
342 348  
343   - // Work on a clone of the CTA observation. This makes sure that
344   - // any memory allocated for computing (for example a response
345   - // cache) is properly de-allocated on exit of this run
346   - GCTAObservation obs_clone = *obs;
  349 + // Write header for observation
  350 + if (logTerse()) {
  351 + if (obs->name().length() > 1) {
  352 + wrklog.header3("Observation "+obs->name());
  353 + }
  354 + else {
  355 + wrklog.header3("Observation");
  356 + }
  357 + }
347 358  
348   - // Save number of events before entering simulation
349   - int events_before = obs_clone.events()->size();
  359 + // Work on a clone of the CTA observation. This makes sure that
  360 + // any memory allocated for computing (for example a response
  361 + // cache) is properly de-allocated on exit of this run
  362 + GCTAObservation obs_clone = *obs;
350 363  
351   - // Simulate source events
352   - simulate_source(&obs_clone, models, m_rans[i], &wrklog);
  364 + // Save number of events before entering simulation
  365 + int events_before = obs_clone.events()->size();
353 366  
354   - // Simulate source events
355   - simulate_background(&obs_clone, models, m_rans[i], &wrklog);
  367 + // Simulate source events
  368 + simulate_source(&obs_clone, models, m_rans[i], &wrklog);
356 369  
357   - // Dump simulation results
358   - if (logNormal()) {
359   - wrklog << gammalib::parformat("MC events");
360   - wrklog << obs_clone.events()->size() - events_before;
361   - wrklog << " (all models)";
362   - wrklog << std::endl;
363   - }
  370 + // Simulate source events
  371 + simulate_background(&obs_clone, models, m_rans[i], &wrklog);
364 372  
365   - // Append the event list to the original observation
366   - obs->events(*(obs_clone.events()));
  373 + // Dump simulation results
  374 + if (logNormal()) {
  375 + wrklog << gammalib::parformat("MC events");
  376 + wrklog << obs_clone.events()->size() - events_before;
  377 + wrklog << " (all models)";
  378 + wrklog << std::endl;
  379 + }
367 380  
368   - // If requested, event lists are saved immediately
369   - if (m_save_and_dispose) {
  381 + // Append the event list to the original observation
  382 + obs->events(*(obs_clone.events()));
370 383  
371   - // Set event output file name. If multiple observations are
372   - // handled, build the filename from prefix and observation
373   - // index. Otherwise use the outfile parameter.
374   - std::string outfile;
375   - if (m_use_xml) {
376   - m_prefix = (*this)["prefix"].string();
377   - outfile = m_prefix + gammalib::str(i) + ".fits";
378   - }
379   - else {
380   - outfile = (*this)["outevents"].filename();
381   - }
  384 + // If requested, event lists are saved immediately
  385 + if (m_save_and_dispose) {
382 386  
383   - // Store output file name in original observation
384   - obs->eventfile(outfile);
385   -
386   - // Save observation into FITS file. This is a critical zone
387   - // to avoid multiple threads writing simultaneously
388   - #pragma omp critical
389   - {
390   - obs_clone.save(outfile, clobber());
391   - }
  387 + // Set event output file name. If multiple observations are
  388 + // handled, build the filename from prefix and observation
  389 + // index. Otherwise use the outfile parameter.
  390 + std::string outfile;
  391 + if (m_use_xml) {
  392 + m_prefix = (*this)["prefix"].string();
  393 + outfile = m_prefix + gammalib::str(i) + ".fits";
  394 + }
  395 + else {
  396 + outfile = (*this)["outevents"].filename();
  397 + }
392 398  
393   - // Dispose events
394   - obs->dispose_events();
  399 + // Store output file name in original observation
  400 + obs->eventfile(outfile);
395 401  
  402 + // Save observation into FITS file. This is a critical zone
  403 + // to avoid multiple threads writing simultaneously
  404 + #pragma omp critical
  405 + {
  406 + obs_clone.save(outfile, clobber());
396 407 }
397 408  
398   - // ... otherwise append the event list to the original observation
399   - /*
400   - else {
401   - obs->events(*(obs_clone.events()));
402   - }
403   - */
  409 + // Dispose events
  410 + obs->dispose_events();
404 411  
405   - } // endif: CTA observation found
  412 + }
406 413  
407 414 } // endfor: looped over observations
408 415  
... ...
src/ctpsfcube/ctpsfcube.cpp
... ... @@ -247,7 +247,7 @@ void ctpsfcube::run(void)
247 247 }
248 248  
249 249 // Fill PSF
250   - m_psfcube.fill(m_obs);
  250 + m_psfcube.fill(m_obs, &log);
251 251  
252 252 // Restore energy dispersion flag for all CTA observations
253 253 for (int i = 0; i < m_obs.size(); ++i) {
... ...
src/ctselect/ctselect.cpp
... ... @@ -249,74 +249,88 @@ void ctselect::run(void)
249 249 // Get CTA observation
250 250 GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]);
251 251  
252   - // Continue only if observation is a CTA observation
253   - if (obs != NULL) {
  252 + // Skip observation if it's not CTA
  253 + if (obs == NULL) {
  254 + if (logTerse()) {
  255 + log << "Warning: Skipping "+m_obs[i]->instrument();
  256 + log << " observation \"";
  257 + log << m_obs[i]->name() << "\"" << std::endl;
  258 + }
  259 + continue;
  260 + }
254 261  
255   - // Write header for observation
  262 + // Skip observation if we have a binned observation
  263 + if (obs->eventtype() == "CountsCube") {
256 264 if (logTerse()) {
257   - if (obs->name().length() > 1) {
258   - log.header3("Observation "+obs->name());
259   - }
260   - else {
261   - log.header3("Observation");
262   - }
  265 + log << "Warning: Skipping binned observation \"";
  266 + log << obs->name()+"\"" << std::endl;
263 267 }
  268 + continue;
  269 + }
264 270  
265   - // Increment counter
266   - n_observations++;
  271 + // Write header for observation
  272 + if (logTerse()) {
  273 + if (obs->name().length() > 1) {
  274 + log.header3("Observation "+obs->name());
  275 + }
  276 + else {
  277 + log.header3("Observation");
  278 + }
  279 + }
267 280  
268   - // Save event file name (for possible saving)
269   - m_infiles[i] = obs->eventfile();
  281 + // Increment counter
  282 + n_observations++;
270 283  
271   - // Fall through in case that the event file is empty
272   - if (obs->events()->size() == 0) {
273   - if (logTerse()) {
274   - log << " Warning: No events in event file \"";
275   - log << m_infiles[i] << "\". Event selection skipped.";
276   - log << std::endl;
277   - }
278   - continue;
279   - }
  284 + // Save event file name (for possible saving)
  285 + m_infiles[i] = obs->eventfile();
280 286  
281   - // Get temporary file name
282   - #if G_USE_MKSTEMP
283   - char tpl[] = "ctselectXXXXXX";
284   - int fileid = mkstemp(tpl);
285   - std::string filename(tpl);
286   - #else
287   - std::string filename = std::tmpnam(NULL);
288   - #endif
289   -
290   - // Save observation in temporary file
291   - obs->save(filename, true);
292   -
293   - // Log saved FITS file
294   - if (logExplicit()) {
295   - GFits tmpfile(filename);
  287 + // Fall through in case that the event file is empty
  288 + if (obs->events()->size() == 0) {
  289 + if (logTerse()) {
  290 + log << " Warning: No events in event file \"";
  291 + log << m_infiles[i] << "\". Event selection skipped.";
296 292 log << std::endl;
297   - log.header1("FITS file content of temporary file");
298   - log << tmpfile << std::endl;
299   - tmpfile.close();
300 293 }
  294 + continue;
  295 + }
301 296  
302   - // Check temporary file
303   - std::string message = check_infile(filename);
304   - if (message.length() > 0) {
305   - throw GException::app_error(G_RUN, message);
306   - }
  297 + // Get temporary file name
  298 + #if G_USE_MKSTEMP
  299 + char tpl[] = "ctselectXXXXXX";
  300 + int fileid = mkstemp(tpl);
  301 + std::string filename(tpl);
  302 + #else
  303 + std::string filename = std::tmpnam(NULL);
  304 + #endif
  305 +
  306 + // Save observation in temporary file
  307 + obs->save(filename, true);
  308 +
  309 + // Log saved FITS file
  310 + if (logExplicit()) {
  311 + GFits tmpfile(filename);
  312 + log << std::endl;
  313 + log.header1("FITS file content of temporary file");
  314 + log << tmpfile << std::endl;
  315 + tmpfile.close();
  316 + }
  317 +
  318 + // Check temporary file
  319 + std::string message = check_infile(filename);
  320 + if (message.length() > 0) {
  321 + throw GException::app_error(G_RUN, message);
  322 + }
307 323  
308   - // Load observation from temporary file, including event selection
309   - select_events(obs, filename);
  324 + // Load observation from temporary file, including event selection
  325 + select_events(obs, filename);
310 326  
311   - // Close temporary file
312   - #if G_USE_MKSTEMP
313   - close(fileid);
314   - #endif
  327 + // Close temporary file
  328 + #if G_USE_MKSTEMP
  329 + close(fileid);
  330 + #endif
315 331  
316   - // Remove temporary file
317   - std::remove(filename.c_str());
318   -
319   - } // endif: had a CTA observation
  332 + // Remove temporary file
  333 + std::remove(filename.c_str());
320 334  
321 335 } // endfor: looped over all observations
322 336  
... ... @@ -1218,28 +1232,33 @@ void ctselect::save_event_list(const GCTAObservation* obs,
1218 1232 // Save only if observation is valid
1219 1233 if (obs != NULL) {
1220 1234  
1221   - // Save observation into FITS file
1222   - obs->save(outfile, clobber());
1223   -
1224   - // Copy all extensions other than EVENTS and GTI from the input to
1225   - // the output event list. The EVENTS and GTI extensions are written
1226   - // by the save method, all others that may eventually be present
1227   - // have to be copied by hand.
1228   - GFits infits(infile);
1229   - GFits outfits(outfile);
1230   - for (int extno = 1; extno < infits.size(); ++extno) {
1231   - GFitsHDU* hdu = infits.at(extno);
1232   - if (hdu->extname() != "EVENTS" && hdu->extname() != "GTI") {
1233   - outfits.append(*hdu);
  1235 + // Save only if we have an event list
  1236 + if (obs->eventtype() == "EventList") {
  1237 +
  1238 + // Save observation into FITS file
  1239 + obs->save(outfile, clobber());
  1240 +
  1241 + // Copy all extensions other than EVENTS and GTI from the input to
  1242 + // the output event list. The EVENTS and GTI extensions are written
  1243 + // by the save method, all others that may eventually be present
  1244 + // have to be copied by hand.
  1245 + GFits infits(infile);
  1246 + GFits outfits(outfile);
  1247 + for (int extno = 1; extno < infits.size(); ++extno) {
  1248 + GFitsHDU* hdu = infits.at(extno);
  1249 + if (hdu->extname() != "EVENTS" && hdu->extname() != "GTI") {
  1250 + outfits.append(*hdu);
  1251 + }
1234 1252 }
1235   - }
1236 1253  
1237   - // Close input file
1238   - infits.close();
  1254 + // Close input file
  1255 + infits.close();
  1256 +
  1257 + // Save file to disk and close it (we need both operations)
  1258 + outfits.save(true);
  1259 + outfits.close();
1239 1260  
1240   - // Save file to disk and close it (we need both operations)
1241   - outfits.save(true);
1242   - outfits.close();
  1261 + } // endif: observation was unbinned
1243 1262  
1244 1263 } // endif: observation was valid
1245 1264  
... ...
src/ctskymap/ctskymap.cpp
... ... @@ -250,43 +250,43 @@ void ctskymap::run(void)
250 250 // Get CTA observation
251 251 GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]);
252 252  
253   - // Continue only if observation is a CTA observation
254   - if (obs != NULL) {
  253 + // Skip observation if it's not CTA
  254 + if (obs == NULL) {
  255 + if (logTerse()) {
  256 + log << "Warning: Skipping "+m_obs[i]->instrument();
  257 + log << " observation \"";
  258 + log << m_obs[i]->name() << "\"" << std::endl;
  259 + }
  260 + continue;
  261 + }
255 262  
256   - // Write header for current observation
  263 + // Skip observation if we have a binned observation
  264 + if (obs->eventtype() == "CountsCube") {
257 265 if (logTerse()) {
258   - if (obs->name().length() > 1) {
259   - log.header3("Observation "+obs->name());
260   - }
261   - else {
262   - log.header3("Observation");
263   - }
  266 + log << "Warning: Skipping binned observation \"";
  267 + log << obs->name()+"\"" << std::endl;
264 268 }
  269 + continue;
  270 + }
265 271  
266   - // Map events into sky map
267   - map_events(obs);
268   -
269   - // Increment observation counter
270   - num_obs++;
  272 + // Write header for current observation
  273 + if (logTerse()) {
  274 + if (obs->name().length() > 1) {
  275 + log.header3("Observation "+obs->name());
  276 + }
  277 + else {
  278 + log.header3("Observation");
  279 + }
  280 + }
271 281  
272   - } // endif: CTA observation found
  282 + // Map events into sky map
  283 + map_events(obs);
  284 +
  285 + // Increment observation counter
  286 + num_obs++;
273 287  
274 288 } // endfor: looped over observations
275 289  
276   - // Write observation(s) into logger
277   -/*
278   - if (logTerse()) {
279   - log << std::endl;
280   - if (m_obs.size() > 1) {
281   - log.header1("Map observations");
282   - }
283   - else {
284   - log.header1("Map observation");
285   - }
286   - log << m_obs << std::endl;
287   - }
288   -*/
289   -
290 290 // Return
291 291 return;
292 292 }
... ...