Commit 8af322b8bb79769f87189b2e0bc32f321b4380bb
1 parent
0e005d47
Change ctmodel logic in a way similar to ctbin.
ctmodel now always produces a single model cube on output. There are two important input parameters: "infile" and "obsfile". "infile" specifies a counts or model cube that is used to define the binning of the model cube. The functionnality for this parameter is as before. If "infile=NONE", the cube will be defined according to task parameters that specify the spatial and the energy binning. The "obsfile" parameter is new and allows specifying the observation definition for which the model cube should be computed. If an event list or a counts cube is presented, the pointing and Good Time Intervals will be extracted from the FITS file header. If an observation definition XML file is presented, ctmodel will now loop over all CTA observations in the file and add the model values to the model cube. If no response information is associated to the "obsfile" (which is typically the case for event lists or counts cubes), the "caldb" and "irf" parameters will be used to identify the response.
Showing
8 changed files
with
438 additions
and
452 deletions
ChangeLog
| @@ -6,6 +6,7 @@ | @@ -6,6 +6,7 @@ | ||
| 6 | Clean-up public interface | 6 | Clean-up public interface |
| 7 | Adapt to GammaLib 0.9.0 interface | 7 | Adapt to GammaLib 0.9.0 interface |
| 8 | ctbin now always merges event lists into a single counts cube | 8 | ctbin now always merges event lists into a single counts cube |
| 9 | + ctmodel now always creates a single model cube | ||
| 9 | Add ctexpcube tool (generates exposure cube) | 10 | Add ctexpcube tool (generates exposure cube) |
| 10 | Add ctpsfcube tool (generates PSF cube) | 11 | Add ctpsfcube tool (generates PSF cube) |
| 11 | Add ctbkgcube tool (generates background cube) | 12 | Add ctbkgcube tool (generates background cube) |
NEWS
| @@ -98,8 +98,26 @@ extension in the FITS file. | @@ -98,8 +98,26 @@ extension in the FITS file. | ||
| 98 | None | 98 | None |
| 99 | 99 | ||
| 100 | 100 | ||
| 101 | -10. ctmodel - CTA counts map modelling | ||
| 102 | --------------------------------------- | 101 | +10. ctmodel - CTA counts cube modelling |
| 102 | +--------------------------------------- | ||
| 103 | +WARNING: The philosophy behind the ctmodel tool changed fundamentally! | ||
| 104 | + | ||
| 105 | +ctmodel now always produces a single model cube on output. There are | ||
| 106 | +two important input parameters: "infile" and "obsfile". "infile" | ||
| 107 | +specifies a counts or model cube that is used to define the binning | ||
| 108 | +of the model cube. The functionnality for this parameter is as before. | ||
| 109 | +If "infile=NONE", the cube will be defined according to task parameters | ||
| 110 | +that specify the spatial and the energy binning. The "obsfile" | ||
| 111 | +parameter is new and allows specifying the observation definition | ||
| 112 | +for which the model cube should be computed. If an event list or a | ||
| 113 | +counts cube is presented, the pointing and Good Time Intervals will | ||
| 114 | +be extracted from the FITS file header. If an observation definition | ||
| 115 | +XML file is presented, ctmodel will now loop over all CTA observations | ||
| 116 | +in the file and add the model values to the model cube. If no | ||
| 117 | +response information is associated to the "obsfile" (which is typically | ||
| 118 | +the case for event lists or counts cubes), the "caldb" and "irf" | ||
| 119 | +parameters will be used to identify the response. | ||
| 120 | + | ||
| 103 | ctmodel now has full access to the calibration database, allowing | 121 | ctmodel now has full access to the calibration database, allowing |
| 104 | the use for 2D response functions in FITS files. | 122 | the use for 2D response functions in FITS files. |
| 105 | 123 |
pyext/ctmodel.i
| 1 | /*************************************************************************** | 1 | /*************************************************************************** |
| 2 | - * ctmodel - CTA counts model tool * | 2 | + * ctmodel - CTA model cube generation tool * |
| 3 | * ----------------------------------------------------------------------- * | 3 | * ----------------------------------------------------------------------- * |
| 4 | * copyright (C) 2012-2014 by Juergen Knoedlseder * | 4 | * copyright (C) 2012-2014 by Juergen Knoedlseder * |
| 5 | * ----------------------------------------------------------------------- * | 5 | * ----------------------------------------------------------------------- * |
| @@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
| 20 | ***************************************************************************/ | 20 | ***************************************************************************/ |
| 21 | /** | 21 | /** |
| 22 | * @file ctmodel.i | 22 | * @file ctmodel.i |
| 23 | - * @brief CTA counts model tool definition | 23 | + * @brief CTA model cube tool definition |
| 24 | * @author Juergen Knoedlseder | 24 | * @author Juergen Knoedlseder |
| 25 | */ | 25 | */ |
| 26 | %{ | 26 | %{ |
| @@ -51,6 +51,7 @@ public: | @@ -51,6 +51,7 @@ public: | ||
| 51 | void run(void); | 51 | void run(void); |
| 52 | void save(void); | 52 | void save(void); |
| 53 | const GObservations& obs(void) const; | 53 | const GObservations& obs(void) const; |
| 54 | + const GCTAEventCube& cube(void) const; | ||
| 54 | }; | 55 | }; |
| 55 | 56 | ||
| 56 | 57 |
src/ctmodel/ctmodel.cpp
| 1 | /*************************************************************************** | 1 | /*************************************************************************** |
| 2 | - * ctmodel - CTA counts model tool * | 2 | + * ctmodel - CTA model cube generation tool * |
| 3 | * ----------------------------------------------------------------------- * | 3 | * ----------------------------------------------------------------------- * |
| 4 | * copyright (C) 2012-2014 by Juergen Knoedlseder * | 4 | * copyright (C) 2012-2014 by Juergen Knoedlseder * |
| 5 | * ----------------------------------------------------------------------- * | 5 | * ----------------------------------------------------------------------- * |
| @@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
| 20 | ***************************************************************************/ | 20 | ***************************************************************************/ |
| 21 | /** | 21 | /** |
| 22 | * @file ctmodel.cpp | 22 | * @file ctmodel.cpp |
| 23 | - * @brief CTA counts model tool implementation | 23 | + * @brief CTA model cube tool implementation |
| 24 | * @author Juergen Knoedlseder | 24 | * @author Juergen Knoedlseder |
| 25 | */ | 25 | */ |
| 26 | 26 | ||
| @@ -33,8 +33,7 @@ | @@ -33,8 +33,7 @@ | ||
| 33 | #include "GTools.hpp" | 33 | #include "GTools.hpp" |
| 34 | 34 | ||
| 35 | /* __ Method name definitions ____________________________________________ */ | 35 | /* __ Method name definitions ____________________________________________ */ |
| 36 | -#define G_SETUP_OBS "ctmodel::setup_obs()" | ||
| 37 | -#define G_MODEL_MAP "ctmodel::model_map(GCTAObservation*)" | 36 | +#define G_GET_EBOUNDS "ctmodel::get_ebounds()" |
| 38 | 37 | ||
| 39 | /* __ Debug definitions __________________________________________________ */ | 38 | /* __ Debug definitions __________________________________________________ */ |
| 40 | 39 | ||
| @@ -212,10 +211,10 @@ void ctmodel::execute(void) | @@ -212,10 +211,10 @@ void ctmodel::execute(void) | ||
| 212 | // Signal that some parameters should be read ahead | 211 | // Signal that some parameters should be read ahead |
| 213 | m_read_ahead = true; | 212 | m_read_ahead = true; |
| 214 | 213 | ||
| 215 | - // Create the model map(s) | 214 | + // Create model cube |
| 216 | run(); | 215 | run(); |
| 217 | 216 | ||
| 218 | - // Save the model map(s) into FITS file | 217 | + // Save model cube into FITS file |
| 219 | save(); | 218 | save(); |
| 220 | 219 | ||
| 221 | // Return | 220 | // Return |
| @@ -276,23 +275,15 @@ void ctmodel::run(void) | @@ -276,23 +275,15 @@ void ctmodel::run(void) | ||
| 276 | // Write header | 275 | // Write header |
| 277 | if (logTerse()) { | 276 | if (logTerse()) { |
| 278 | log << std::endl; | 277 | log << std::endl; |
| 279 | - if (m_obs.size() > 1) { | ||
| 280 | - log.header1("Generate model maps"); | ||
| 281 | - } | ||
| 282 | - else { | ||
| 283 | - log.header1("Generate model map"); | ||
| 284 | - } | 278 | + log.header1("Generate model cube"); |
| 285 | } | 279 | } |
| 286 | 280 | ||
| 287 | - // Initialise observation counter | ||
| 288 | - int n_observations = 0; | 281 | + // Initialise counts cube |
| 282 | + init_cube(); | ||
| 289 | 283 | ||
| 290 | // Loop over all observations in the container | 284 | // Loop over all observations in the container |
| 291 | for (int i = 0; i < m_obs.size(); ++i) { | 285 | for (int i = 0; i < m_obs.size(); ++i) { |
| 292 | 286 | ||
| 293 | - // Initialise event input and output filenames | ||
| 294 | - m_infiles.push_back(""); | ||
| 295 | - | ||
| 296 | // Get CTA observation | 287 | // Get CTA observation |
| 297 | GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]); | 288 | GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]); |
| 298 | 289 | ||
| @@ -309,35 +300,18 @@ void ctmodel::run(void) | @@ -309,35 +300,18 @@ void ctmodel::run(void) | ||
| 309 | } | 300 | } |
| 310 | } | 301 | } |
| 311 | 302 | ||
| 312 | - // Increment number of observations | ||
| 313 | - n_observations++; | ||
| 314 | - | ||
| 315 | - // Save event file name (for possible saving) | ||
| 316 | - m_infiles[i] = obs->eventfile(); | ||
| 317 | - | ||
| 318 | - // Generate model map | ||
| 319 | - model_map(obs, m_obs.models()); | 303 | + // Fill the cube |
| 304 | + fill_cube(obs); | ||
| 320 | 305 | ||
| 321 | } // endif: CTA observation found | 306 | } // endif: CTA observation found |
| 322 | 307 | ||
| 323 | } // endfor: looped over observations | 308 | } // endfor: looped over observations |
| 324 | 309 | ||
| 325 | - // If more than a single observation has been handled then make sure | ||
| 326 | - // that an XML file will be used for storage | ||
| 327 | - if (n_observations > 1) { | ||
| 328 | - m_use_xml = true; | ||
| 329 | - } | ||
| 330 | - | ||
| 331 | - // Write observation(s) into logger | 310 | + // Log cube |
| 332 | if (logTerse()) { | 311 | if (logTerse()) { |
| 333 | log << std::endl; | 312 | log << std::endl; |
| 334 | - if (m_obs.size() > 1) { | ||
| 335 | - log.header1("Observations after model map generation"); | ||
| 336 | - } | ||
| 337 | - else { | ||
| 338 | - log.header1("Observation after model map generation"); | ||
| 339 | - } | ||
| 340 | - log << m_obs << std::endl; | 313 | + log.header1("Model cube"); |
| 314 | + log << m_cube << std::endl; | ||
| 341 | } | 315 | } |
| 342 | 316 | ||
| 343 | // Restore energy dispersion flag for all CTA observations | 317 | // Restore energy dispersion flag for all CTA observations |
| @@ -354,43 +328,135 @@ void ctmodel::run(void) | @@ -354,43 +328,135 @@ void ctmodel::run(void) | ||
| 354 | 328 | ||
| 355 | 329 | ||
| 356 | /***********************************************************************//** | 330 | /***********************************************************************//** |
| 357 | - * @brief Save model map(s) | ||
| 358 | - * | ||
| 359 | - * This method saves the model map(s) into FITS file(s). There are two | ||
| 360 | - * modes, depending on the m_use_xml flag. | 331 | + * @brief Save model cube |
| 361 | * | 332 | * |
| 362 | - * If m_use_xml is true, all model map(s) will be saved into FITS files, | ||
| 363 | - * where the output filenames are constructued from the input filenames by | ||
| 364 | - * prepending the m_prefix string to name. Any path information will be | ||
| 365 | - * stripped form the input name, hence event files will be written into the | ||
| 366 | - * local working directory (unless some path information is present | ||
| 367 | - * in the prefix). In addition, an XML file will be created that gathers | ||
| 368 | - * the filename information for the model map(s). If an XML file was present | ||
| 369 | - * on input, all metadata information will be copied from this input file. | ||
| 370 | - * | ||
| 371 | - * If m_use_xml is false, the model map will be saved into a FITS file. | 333 | + * Saves the model cube into a FITS file specified using the "outfile" |
| 334 | + * task parameter. | ||
| 372 | ***************************************************************************/ | 335 | ***************************************************************************/ |
| 373 | void ctmodel::save(void) | 336 | void ctmodel::save(void) |
| 374 | { | 337 | { |
| 375 | // Write header | 338 | // Write header |
| 376 | if (logTerse()) { | 339 | if (logTerse()) { |
| 377 | log << std::endl; | 340 | log << std::endl; |
| 378 | - if (m_obs.size() > 1) { | ||
| 379 | - log.header1("Save observations"); | ||
| 380 | - } | ||
| 381 | - else { | ||
| 382 | - log.header1("Save observation"); | ||
| 383 | - } | 341 | + log.header1("Save cube"); |
| 384 | } | 342 | } |
| 385 | 343 | ||
| 386 | - // Case A: Save model map(s) and XML metadata information | ||
| 387 | - if (m_use_xml) { | ||
| 388 | - save_xml(); | ||
| 389 | - } | 344 | + // Make sure we have the FITS filename |
| 345 | + m_outfile = (*this)["outfile"].filename(); | ||
| 390 | 346 | ||
| 391 | - // Case B: Save model map as FITS file | ||
| 392 | - else { | ||
| 393 | - save_fits(); | 347 | + // Save model cube into FITS file |
| 348 | + m_cube.save(m_outfile, clobber()); | ||
| 349 | + | ||
| 350 | + // Return | ||
| 351 | + return; | ||
| 352 | +} | ||
| 353 | + | ||
| 354 | + | ||
| 355 | +/*========================================================================== | ||
| 356 | + = = | ||
| 357 | + = Private methods = | ||
| 358 | + = = | ||
| 359 | + ==========================================================================*/ | ||
| 360 | + | ||
| 361 | +/***********************************************************************//** | ||
| 362 | + * @brief Initialise class members | ||
| 363 | + ***************************************************************************/ | ||
| 364 | +void ctmodel::init_members(void) | ||
| 365 | +{ | ||
| 366 | + // Initialise members | ||
| 367 | + m_infile.clear(); | ||
| 368 | + m_obsfile.clear(); | ||
| 369 | + m_outfile.clear(); | ||
| 370 | + m_caldb.clear(); | ||
| 371 | + m_irf.clear(); | ||
| 372 | + m_srcmdl.clear(); | ||
| 373 | + m_proj.clear(); | ||
| 374 | + m_coordsys.clear(); | ||
| 375 | + m_ebinalg.clear(); | ||
| 376 | + m_ebinfile.clear(); | ||
| 377 | + m_ra = 0.0; | ||
| 378 | + m_dec = 0.0; | ||
| 379 | + m_deadc = 1.0; | ||
| 380 | + m_tmin = 0.0; | ||
| 381 | + m_tmax = 0.0; | ||
| 382 | + m_emin = 0.0; | ||
| 383 | + m_emax = 0.0; | ||
| 384 | + m_enumbins = 0; | ||
| 385 | + m_xref = 0.0; | ||
| 386 | + m_yref = 0.0; | ||
| 387 | + m_binsz = 0.0; | ||
| 388 | + m_nxpix = 0; | ||
| 389 | + m_nypix = 0; | ||
| 390 | + m_apply_edisp = false; | ||
| 391 | + | ||
| 392 | + // Initialise protected members | ||
| 393 | + m_obs.clear(); | ||
| 394 | + m_cube.clear(); | ||
| 395 | + m_ebounds.clear(); | ||
| 396 | + m_gti.clear(); | ||
| 397 | + m_read_ahead = false; | ||
| 398 | + | ||
| 399 | + // Set logger properties | ||
| 400 | + log.date(true); | ||
| 401 | + | ||
| 402 | + // Return | ||
| 403 | + return; | ||
| 404 | +} | ||
| 405 | + | ||
| 406 | + | ||
| 407 | +/***********************************************************************//** | ||
| 408 | + * @brief Copy class members | ||
| 409 | + * | ||
| 410 | + * @param[in] app Application. | ||
| 411 | + ***************************************************************************/ | ||
| 412 | +void ctmodel::copy_members(const ctmodel& app) | ||
| 413 | +{ | ||
| 414 | + // Copy attributes | ||
| 415 | + m_infile = app.m_infile; | ||
| 416 | + m_obsfile = app.m_obsfile; | ||
| 417 | + m_outfile = app.m_outfile; | ||
| 418 | + m_caldb = app.m_caldb; | ||
| 419 | + m_irf = app.m_irf; | ||
| 420 | + m_srcmdl = app.m_srcmdl; | ||
| 421 | + m_proj = app.m_proj; | ||
| 422 | + m_coordsys = app.m_coordsys; | ||
| 423 | + m_ebinalg = app.m_ebinalg; | ||
| 424 | + m_ebinfile = app.m_ebinfile; | ||
| 425 | + m_ra = app.m_ra; | ||
| 426 | + m_dec = app.m_dec; | ||
| 427 | + m_deadc = app.m_deadc; | ||
| 428 | + m_tmin = app.m_tmin; | ||
| 429 | + m_tmax = app.m_tmax; | ||
| 430 | + m_emin = app.m_emin; | ||
| 431 | + m_emax = app.m_emax; | ||
| 432 | + m_enumbins = app.m_enumbins; | ||
| 433 | + m_xref = app.m_xref; | ||
| 434 | + m_yref = app.m_yref; | ||
| 435 | + m_binsz = app.m_binsz; | ||
| 436 | + m_nxpix = app.m_nxpix; | ||
| 437 | + m_nypix = app.m_nypix; | ||
| 438 | + m_apply_edisp = app.m_apply_edisp; | ||
| 439 | + | ||
| 440 | + // Copy protected members | ||
| 441 | + m_obs = app.m_obs; | ||
| 442 | + m_cube = app.m_cube; | ||
| 443 | + m_ebounds = app.m_ebounds; | ||
| 444 | + m_gti = app.m_gti; | ||
| 445 | + m_read_ahead = app.m_read_ahead; | ||
| 446 | + | ||
| 447 | + // Return | ||
| 448 | + return; | ||
| 449 | +} | ||
| 450 | + | ||
| 451 | + | ||
| 452 | +/***********************************************************************//** | ||
| 453 | + * @brief Delete class members | ||
| 454 | + ***************************************************************************/ | ||
| 455 | +void ctmodel::free_members(void) | ||
| 456 | +{ | ||
| 457 | + // Write separator into logger | ||
| 458 | + if (logTerse()) { | ||
| 459 | + log << std::endl; | ||
| 394 | } | 460 | } |
| 395 | 461 | ||
| 396 | // Return | 462 | // Return |
| @@ -406,62 +472,78 @@ void ctmodel::save(void) | @@ -406,62 +472,78 @@ void ctmodel::save(void) | ||
| 406 | ***************************************************************************/ | 472 | ***************************************************************************/ |
| 407 | void ctmodel::get_parameters(void) | 473 | void ctmodel::get_parameters(void) |
| 408 | { | 474 | { |
| 409 | - // If we do not have any observations in the container then get all | ||
| 410 | - // information to build (at least) one | ||
| 411 | - if (m_obs.size() == 0) { | 475 | + // Read input and optionally output cube filenames |
| 476 | + m_infile = (*this)["infile"].filename(); | ||
| 477 | + if (m_read_ahead) { | ||
| 478 | + m_outfile = (*this)["outfile"].filename(); | ||
| 479 | + } | ||
| 412 | 480 | ||
| 413 | - // Read general parameters. Only read the output parameters if | ||
| 414 | - // required, and also only read the model XML filename if no | ||
| 415 | - // model is yet in the container. | ||
| 416 | - m_infile = (*this)["infile"].filename(); | ||
| 417 | - if (m_read_ahead) { | ||
| 418 | - m_outfile = (*this)["outfile"].filename(); | ||
| 419 | - m_prefix = (*this)["prefix"].string(); | ||
| 420 | - } | ||
| 421 | - m_caldb = (*this)["caldb"].string(); | ||
| 422 | - m_irf = (*this)["irf"].string(); | ||
| 423 | - if (m_obs.models().size() == 0) { | ||
| 424 | - m_srcmdl = (*this)["srcmdl"].filename(); | 481 | + // Read model definiton file if required |
| 482 | + if (m_obs.models().size() == 0) { | ||
| 483 | + m_srcmdl = (*this)["srcmdl"].filename(); | ||
| 484 | + } | ||
| 485 | + | ||
| 486 | + // Get energy dispersion flag parameters | ||
| 487 | + m_apply_edisp = (*this)["edisp"].boolean(); | ||
| 488 | + | ||
| 489 | + // If the observation container is empty then read the parameters that | ||
| 490 | + // are necessary to fill it | ||
| 491 | + if (m_obs.size() == 0) { | ||
| 492 | + | ||
| 493 | + // Read observation definition filename and response parameters | ||
| 494 | + m_obsfile = (*this)["obsfile"].filename(); | ||
| 495 | + m_caldb = (*this)["caldb"].string(); | ||
| 496 | + m_irf = (*this)["irf"].string(); | ||
| 497 | + | ||
| 498 | + // If no observation definition file has been specified then read all | ||
| 499 | + // parameters that are necessary to create an observation from scratch | ||
| 500 | + // (see method setup_obs) | ||
| 501 | + if ((m_obsfile == "NONE") || (gammalib::strip_whitespace(m_obsfile) == "")) { | ||
| 502 | + m_ra = (*this)["ra"].real(); | ||
| 503 | + m_dec = (*this)["dec"].real(); | ||
| 504 | + m_deadc = (*this)["deadc"].real(); | ||
| 505 | + m_tmin = (*this)["tmin"].real(); | ||
| 506 | + m_tmax = (*this)["tmax"].real(); | ||
| 507 | + if (m_obs.models().size() == 0) { | ||
| 508 | + m_srcmdl = (*this)["srcmdl"].filename(); | ||
| 509 | + } | ||
| 425 | } | 510 | } |
| 426 | 511 | ||
| 427 | - // If there is no input filename then read all parameters that | ||
| 428 | - // are required to build a model map from scratch | ||
| 429 | - if ((m_infile == "NONE") || (gammalib::strip_whitespace(m_infile) == "")) { | ||
| 430 | - m_ra = (*this)["ra"].real(); | ||
| 431 | - m_dec = (*this)["dec"].real(); | ||
| 432 | - m_deadc = (*this)["deadc"].real(); | ||
| 433 | - m_tmin = (*this)["tmin"].real(); | ||
| 434 | - m_tmax = (*this)["tmax"].real(); | ||
| 435 | - m_emin = (*this)["emin"].real(); | ||
| 436 | - m_emax = (*this)["emax"].real(); | ||
| 437 | - m_enumbins = (*this)["enumbins"].integer(); | ||
| 438 | - m_proj = (*this)["proj"].string(); | ||
| 439 | - m_coordsys = (*this)["coordsys"].string(); | ||
| 440 | - m_xref = (*this)["xref"].real(); | ||
| 441 | - m_yref = (*this)["yref"].real(); | ||
| 442 | - m_binsz = (*this)["binsz"].real(); | ||
| 443 | - m_nxpix = (*this)["nxpix"].integer(); | ||
| 444 | - m_nypix = (*this)["nypix"].integer(); | 512 | + } |
| 513 | + | ||
| 514 | + // Check if we need response information | ||
| 515 | + for (int i = 0; i < m_obs.size(); ++i) { | ||
| 516 | + GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]); | ||
| 517 | + if (obs != NULL) { | ||
| 518 | + if (!obs->has_response()) { | ||
| 519 | + m_caldb = (*this)["caldb"].string(); | ||
| 520 | + m_irf = (*this)["irf"].string(); | ||
| 521 | + break; | ||
| 522 | + } | ||
| 445 | } | 523 | } |
| 446 | } | 524 | } |
| 447 | 525 | ||
| 448 | - // ... otherwise, read only the parameters that are required for the | ||
| 449 | - // model generation. | ||
| 450 | - else { | ||
| 451 | - if (m_read_ahead) { | ||
| 452 | - m_outfile = (*this)["outfile"].filename(); | ||
| 453 | - m_prefix = (*this)["prefix"].string(); | 526 | + // If no cube file has been specified then read all parameters that |
| 527 | + // are necessary to create the cube from scratch (see method init_cube) | ||
| 528 | + if ((m_infile == "NONE") || (gammalib::strip_whitespace(m_infile) == "")) { | ||
| 529 | + m_ebinalg = (*this)["ebinalg"].string(); | ||
| 530 | + if (m_ebinalg == "FILE") { | ||
| 531 | + m_ebinfile = (*this)["ebinfile"].filename(); | ||
| 454 | } | 532 | } |
| 455 | - m_caldb = (*this)["caldb"].string(); | ||
| 456 | - m_irf = (*this)["irf"].string(); | ||
| 457 | - if (m_obs.models().size() == 0) { | ||
| 458 | - m_srcmdl = (*this)["srcmdl"].filename(); | 533 | + else { |
| 534 | + m_emin = (*this)["emin"].real(); | ||
| 535 | + m_emax = (*this)["emax"].real(); | ||
| 536 | + m_enumbins = (*this)["enumbins"].integer(); | ||
| 459 | } | 537 | } |
| 538 | + m_proj = (*this)["proj"].string(); | ||
| 539 | + m_coordsys = (*this)["coordsys"].string(); | ||
| 540 | + m_xref = (*this)["xref"].real(); | ||
| 541 | + m_yref = (*this)["yref"].real(); | ||
| 542 | + m_binsz = (*this)["binsz"].real(); | ||
| 543 | + m_nxpix = (*this)["nxpix"].integer(); | ||
| 544 | + m_nypix = (*this)["nypix"].integer(); | ||
| 460 | } | 545 | } |
| 461 | 546 | ||
| 462 | - // Get other parameters | ||
| 463 | - m_apply_edisp = (*this)["edisp"].boolean(); | ||
| 464 | - | ||
| 465 | // Return | 547 | // Return |
| 466 | return; | 548 | return; |
| 467 | } | 549 | } |
| @@ -470,37 +552,33 @@ void ctmodel::get_parameters(void) | @@ -470,37 +552,33 @@ void ctmodel::get_parameters(void) | ||
| 470 | /***********************************************************************//** | 552 | /***********************************************************************//** |
| 471 | * @brief Setup observation container | 553 | * @brief Setup observation container |
| 472 | * | 554 | * |
| 473 | - * @exception GException::no_cube | ||
| 474 | - * No event cube found in CTA observation. | ||
| 475 | - * | ||
| 476 | - * This method sets up the observation container for processing. There are | ||
| 477 | - * two cases: | ||
| 478 | - * | ||
| 479 | - * If there are no observations in the actual observation container, the | ||
| 480 | - * method will check in "infile" parameter. If this parameter is "NONE" or | ||
| 481 | - * empty, the task parameters will be used to construct a model map. | ||
| 482 | - * Otherwise, the method first tries to interpret the "infile" parameter as | ||
| 483 | - * a counts map, and attemps loading of the file in an event cube. If this | ||
| 484 | - * fails, the method tries to interpret the "infile" parameter as an | ||
| 485 | - * observation definition XML file. If this also fails, an exception will | ||
| 486 | - * be thrown. | 555 | + * This method makes sure that we have an observation container with an |
| 556 | + * associated model and that all CTA observations have a valid response | ||
| 557 | + * functions. | ||
| 487 | * | 558 | * |
| 488 | - * If observations exist already in the observation container, the method | ||
| 489 | - * will simply keep them. | 559 | + * If on input the observation container is empty, the method sets up an |
| 560 | + * observation container by either loading the information from an | ||
| 561 | + * observation definition XML file, by loading an event list or a counts | ||
| 562 | + * cube as a single observation, or by constructing an observation from | ||
| 563 | + * the scratch from the task parameters. | ||
| 490 | * | 564 | * |
| 491 | - * Test if all CTA observations contain counts maps. | 565 | + * If no model exists yet in the observation container, the method will load |
| 566 | + * the model from the file given by the task parameter "srcmdl". | ||
| 492 | * | 567 | * |
| 493 | - * Finally, if no models exist so far in the observation container, the | ||
| 494 | - * models will be loaded from the model XML file. | 568 | + * The method then loops over all observations in the container and makes |
| 569 | + * sure that all CTA observations have a valid response function. If no | ||
| 570 | + * response function exists so far, the response function will be set | ||
| 571 | + * using the "caldb" and "irf" task parameters. | ||
| 495 | ***************************************************************************/ | 572 | ***************************************************************************/ |
| 496 | void ctmodel::setup_obs(void) | 573 | void ctmodel::setup_obs(void) |
| 497 | { | 574 | { |
| 498 | - // If there are no observations in the container then try to build some | 575 | + // If there are no observations in the container then get them either |
| 576 | + // from the observation definition file or from the task parameters | ||
| 499 | if (m_obs.size() == 0) { | 577 | if (m_obs.size() == 0) { |
| 500 | 578 | ||
| 501 | - // If no input filename has been specified, then create a model map | ||
| 502 | - // from the task parameters | ||
| 503 | - if ((m_infile == "NONE") || (gammalib::strip_whitespace(m_infile) == "")) { | 579 | + // If no observation definition file has been specified, then create |
| 580 | + // an observation container from the task parameters | ||
| 581 | + if ((m_obsfile == "NONE") || (gammalib::strip_whitespace(m_obsfile) == "")) { | ||
| 504 | 582 | ||
| 505 | // Set pointing direction | 583 | // Set pointing direction |
| 506 | GCTAPointing pnt; | 584 | GCTAPointing pnt; |
| @@ -508,27 +586,20 @@ void ctmodel::setup_obs(void) | @@ -508,27 +586,20 @@ void ctmodel::setup_obs(void) | ||
| 508 | skydir.radec_deg(m_ra, m_dec); | 586 | skydir.radec_deg(m_ra, m_dec); |
| 509 | pnt.dir(skydir); | 587 | pnt.dir(skydir); |
| 510 | 588 | ||
| 511 | - // Setup energy range covered by model | ||
| 512 | - GEnergy emin(m_emin, "TeV"); | ||
| 513 | - GEnergy emax(m_emax, "TeV"); | ||
| 514 | - GEbounds ebds(m_enumbins, emin, emax); | ||
| 515 | - | ||
| 516 | // Setup time interval covered by model | 589 | // Setup time interval covered by model |
| 517 | GGti gti; | 590 | GGti gti; |
| 518 | GTime tmin(m_tmin); | 591 | GTime tmin(m_tmin); |
| 519 | GTime tmax(m_tmax); | 592 | GTime tmax(m_tmax); |
| 520 | gti.append(tmin, tmax); | 593 | gti.append(tmin, tmax); |
| 521 | 594 | ||
| 522 | - // Setup skymap | ||
| 523 | - GSkymap map = GSkymap(m_proj, m_coordsys, | ||
| 524 | - m_xref, m_yref, -m_binsz, m_binsz, | ||
| 525 | - m_nxpix, m_nypix, m_enumbins); | ||
| 526 | - | ||
| 527 | - // Create model cube from sky map | ||
| 528 | - GCTAEventCube cube(map, ebds, gti); | ||
| 529 | - | ||
| 530 | - // Allocate CTA observation | 595 | + // Allocate CTA observation and empty event list |
| 531 | GCTAObservation obs; | 596 | GCTAObservation obs; |
| 597 | + GCTAEventList list; | ||
| 598 | + | ||
| 599 | + // Set event list GTI and append event list to observation | ||
| 600 | + // (we need in fact only the GTI for the computations) | ||
| 601 | + list.gti(gti); | ||
| 602 | + obs.events(list); | ||
| 532 | 603 | ||
| 533 | // Set CTA observation attributes | 604 | // Set CTA observation attributes |
| 534 | obs.pointing(pnt); | 605 | obs.pointing(pnt); |
| @@ -536,34 +607,25 @@ void ctmodel::setup_obs(void) | @@ -536,34 +607,25 @@ void ctmodel::setup_obs(void) | ||
| 536 | obs.livetime(gti.ontime()*m_deadc); | 607 | obs.livetime(gti.ontime()*m_deadc); |
| 537 | obs.deadc(m_deadc); | 608 | obs.deadc(m_deadc); |
| 538 | 609 | ||
| 539 | - // Set event cube in observation | ||
| 540 | - obs.events(cube); | ||
| 541 | - | ||
| 542 | // Append CTA observation to container | 610 | // Append CTA observation to container |
| 543 | m_obs.append(obs); | 611 | m_obs.append(obs); |
| 544 | 612 | ||
| 545 | - // Signal that no XML file should be used for storage | ||
| 546 | - m_use_xml = false; | ||
| 547 | - | ||
| 548 | - } // endif: created model map from task parameters | 613 | + } // endif: created single CTA observation from task parameters |
| 549 | 614 | ||
| 550 | // ... otherwise try to load information from the file | 615 | // ... otherwise try to load information from the file |
| 551 | else { | 616 | else { |
| 552 | 617 | ||
| 553 | - // First try to open the file as a counts map | 618 | + // First try to open the file as an event list or counts map |
| 554 | try { | 619 | try { |
| 555 | 620 | ||
| 556 | // Allocate CTA observation | 621 | // Allocate CTA observation |
| 557 | GCTAObservation obs; | 622 | GCTAObservation obs; |
| 558 | 623 | ||
| 559 | - // Load counts map in CTA observation | ||
| 560 | - obs.load(m_infile); | 624 | + // Load CTA observation from FITS file |
| 625 | + obs.load(m_obsfile); | ||
| 561 | 626 | ||
| 562 | // Append CTA observation to container | 627 | // Append CTA observation to container |
| 563 | m_obs.append(obs); | 628 | m_obs.append(obs); |
| 564 | - | ||
| 565 | - // Signal that no XML file should be used for storage | ||
| 566 | - m_use_xml = false; | ||
| 567 | 629 | ||
| 568 | } | 630 | } |
| 569 | 631 | ||
| @@ -572,10 +634,7 @@ void ctmodel::setup_obs(void) | @@ -572,10 +634,7 @@ void ctmodel::setup_obs(void) | ||
| 572 | 634 | ||
| 573 | // Load observations from XML file. This will throw | 635 | // Load observations from XML file. This will throw |
| 574 | // an exception if it fails. | 636 | // an exception if it fails. |
| 575 | - m_obs.load(m_infile); | ||
| 576 | - | ||
| 577 | - // Signal that XML file should be used for storage | ||
| 578 | - m_use_xml = true; | 637 | + m_obs.load(m_obsfile); |
| 579 | 638 | ||
| 580 | } | 639 | } |
| 581 | 640 | ||
| @@ -589,8 +648,7 @@ void ctmodel::setup_obs(void) | @@ -589,8 +648,7 @@ void ctmodel::setup_obs(void) | ||
| 589 | m_obs.models(GModels(m_srcmdl)); | 648 | m_obs.models(GModels(m_srcmdl)); |
| 590 | } | 649 | } |
| 591 | 650 | ||
| 592 | - // Check if all CTA observations contain an event cube and setup response | ||
| 593 | - // for all observations | 651 | + // Setup response for all observations |
| 594 | for (int i = 0; i < m_obs.size(); ++i) { | 652 | for (int i = 0; i < m_obs.size(); ++i) { |
| 595 | 653 | ||
| 596 | // Is this observation a CTA observation? | 654 | // Is this observation a CTA observation? |
| @@ -599,12 +657,6 @@ void ctmodel::setup_obs(void) | @@ -599,12 +657,6 @@ void ctmodel::setup_obs(void) | ||
| 599 | // Yes ... | 657 | // Yes ... |
| 600 | if (obs != NULL) { | 658 | if (obs != NULL) { |
| 601 | 659 | ||
| 602 | - // Throw an exception if this observation does not contain | ||
| 603 | - // an event cube | ||
| 604 | - if (dynamic_cast<const GCTAEventCube*>(obs->events()) == NULL) { | ||
| 605 | - throw GException::no_cube(G_SETUP_OBS); | ||
| 606 | - } | ||
| 607 | - | ||
| 608 | // Set response if we don't have one | 660 | // Set response if we don't have one |
| 609 | if (!obs->has_response()) { | 661 | if (!obs->has_response()) { |
| 610 | 662 | ||
| @@ -635,106 +687,53 @@ void ctmodel::setup_obs(void) | @@ -635,106 +687,53 @@ void ctmodel::setup_obs(void) | ||
| 635 | 687 | ||
| 636 | 688 | ||
| 637 | /***********************************************************************//** | 689 | /***********************************************************************//** |
| 638 | - * @brief Generate model map | 690 | + * @brief Initialise model cube |
| 639 | * | 691 | * |
| 640 | - * @param[in] obs CTA observation pointer. | ||
| 641 | - * @param[in] models Model container. | ||
| 642 | - * | ||
| 643 | - * @exception GException::no_cube | ||
| 644 | - * No event cube found in CTA observation. | 692 | + * Initialises model cube by either reading the cube definition from an |
| 693 | + * existing cube file specified by the "infile" parameter, or by constructing | ||
| 694 | + * a cube from the energy and spatial binning information provided by the | ||
| 695 | + * task parameters. The GTIs of the model cube will be undefined on | ||
| 696 | + * exit. | ||
| 645 | ***************************************************************************/ | 697 | ***************************************************************************/ |
| 646 | -void ctmodel::model_map(GCTAObservation* obs, const GModels& models) | 698 | +void ctmodel::init_cube(void) |
| 647 | { | 699 | { |
| 648 | - // Continue only if observation pointer is valid | ||
| 649 | - if (obs != NULL) { | 700 | + // Clear model cube and GTIs |
| 701 | + m_cube.clear(); | ||
| 702 | + m_gti.clear(); | ||
| 650 | 703 | ||
| 651 | - // Get event cube pointer | ||
| 652 | - GCTAEventCube* cube = | ||
| 653 | - const_cast<GCTAEventCube*>(dynamic_cast<const GCTAEventCube*>(obs->events())); | 704 | + // If no cube file has been specified then create a cube from the task |
| 705 | + // parameters | ||
| 706 | + if ((m_infile == "NONE") || (gammalib::strip_whitespace(m_infile) == "")) { | ||
| 654 | 707 | ||
| 655 | - // Throw an exception if the observation does not hold and event | ||
| 656 | - // cube | ||
| 657 | - if (cube == NULL) { | ||
| 658 | - throw GException::no_cube(G_MODEL_MAP); | ||
| 659 | - } | 708 | + // Set dummy GTI that is needed for event cube creation |
| 709 | + GGti gti; | ||
| 710 | + gti.append(GTime(0.0), GTime(0.1234)); | ||
| 711 | + | ||
| 712 | + // Set energy boundaries | ||
| 713 | + get_ebounds(); | ||
| 660 | 714 | ||
| 661 | - // Initialise statistics | ||
| 662 | - double sum = 0.0; | 715 | + // Setup skymap |
| 716 | + GSkymap map = GSkymap(m_proj, m_coordsys, | ||
| 717 | + m_xref, m_yref, -m_binsz, m_binsz, | ||
| 718 | + m_nxpix, m_nypix, m_enumbins); | ||
| 663 | 719 | ||
| 664 | - // Loop over all events in counts map | ||
| 665 | - for (int i = 0; i < cube->size(); ++i) { | 720 | + // Create model cube |
| 721 | + m_cube = GCTAEventCube(map, m_ebounds, gti); | ||
| 666 | 722 | ||
| 667 | - // Get event bin | ||
| 668 | - GCTAEventBin* bin = (*cube)[i]; | ||
| 669 | - | ||
| 670 | - // Compute model value for event bin | ||
| 671 | - double model = | ||
| 672 | - models.eval(*(const_cast<const GCTAEventBin*>(bin)), *obs) * | ||
| 673 | - bin->size(); | 723 | + } |
| 674 | 724 | ||
| 675 | - // Store value | ||
| 676 | - bin->counts(model); | 725 | + // ... otherwise load cube from file |
| 726 | + else { | ||
| 677 | 727 | ||
| 678 | - // Sum all events | ||
| 679 | - sum += model; | ||
| 680 | - } | 728 | + // Load cube |
| 729 | + m_cube.load(m_infile); | ||
| 681 | 730 | ||
| 682 | - // Log results | ||
| 683 | - if (logTerse()) { | ||
| 684 | - log << gammalib::parformat("Model events in cube"); | ||
| 685 | - log << sum << std::endl; | 731 | + // Set all cube bins to zero |
| 732 | + for (int i = 0; i < m_cube.size(); ++i) { | ||
| 733 | + m_cube[i]->counts(0.0); | ||
| 686 | } | 734 | } |
| 687 | 735 | ||
| 688 | - } // endif: observation pointer was not valid | ||
| 689 | - | ||
| 690 | - // Return | ||
| 691 | - return; | ||
| 692 | -} | ||
| 693 | - | ||
| 694 | - | ||
| 695 | -/*========================================================================== | ||
| 696 | - = = | ||
| 697 | - = Private methods = | ||
| 698 | - = = | ||
| 699 | - ==========================================================================*/ | ||
| 700 | - | ||
| 701 | -/***********************************************************************//** | ||
| 702 | - * @brief Initialise class members | ||
| 703 | - ***************************************************************************/ | ||
| 704 | -void ctmodel::init_members(void) | ||
| 705 | -{ | ||
| 706 | - // Initialise members | ||
| 707 | - m_infile.clear(); | ||
| 708 | - m_outfile.clear(); | ||
| 709 | - m_prefix.clear(); | ||
| 710 | - m_caldb.clear(); | ||
| 711 | - m_irf.clear(); | ||
| 712 | - m_srcmdl.clear(); | ||
| 713 | - m_proj.clear(); | ||
| 714 | - m_coordsys.clear(); | ||
| 715 | - m_ra = 0.0; | ||
| 716 | - m_dec = 0.0; | ||
| 717 | - m_deadc = 1.0; | ||
| 718 | - m_tmin = 0.0; | ||
| 719 | - m_tmax = 0.0; | ||
| 720 | - m_emin = 0.0; | ||
| 721 | - m_emax = 0.0; | ||
| 722 | - m_enumbins = 0; | ||
| 723 | - m_xref = 0.0; | ||
| 724 | - m_yref = 0.0; | ||
| 725 | - m_binsz = 0.0; | ||
| 726 | - m_nxpix = 0; | ||
| 727 | - m_nypix = 0; | ||
| 728 | - m_apply_edisp = false; | ||
| 729 | - | ||
| 730 | - // Initialise protected members | ||
| 731 | - m_obs.clear(); | ||
| 732 | - m_infiles.clear(); | ||
| 733 | - m_use_xml = false; | ||
| 734 | - m_read_ahead = false; | ||
| 735 | - | ||
| 736 | - // Set logger properties | ||
| 737 | - log.date(true); | 736 | + } |
| 738 | 737 | ||
| 739 | // Return | 738 | // Return |
| 740 | return; | 739 | return; |
| @@ -742,104 +741,64 @@ void ctmodel::init_members(void) | @@ -742,104 +741,64 @@ void ctmodel::init_members(void) | ||
| 742 | 741 | ||
| 743 | 742 | ||
| 744 | /***********************************************************************//** | 743 | /***********************************************************************//** |
| 745 | - * @brief Copy class members | 744 | + * @brief Fill model into model cube |
| 746 | * | 745 | * |
| 747 | - * @param[in] app Application. | 746 | + * @param[in] obs CTA observation. |
| 747 | + * | ||
| 748 | + * Adds the expected number of events for a given observation to the events | ||
| 749 | + * that are already found in the model cube. The method also updates the | ||
| 750 | + * GTI of the model cube so that cube GTI is a list of the GTIs of all | ||
| 751 | + * observations that were used to generate the model cube. | ||
| 748 | ***************************************************************************/ | 752 | ***************************************************************************/ |
| 749 | -void ctmodel::copy_members(const ctmodel& app) | 753 | +void ctmodel::fill_cube(const GCTAObservation* obs) |
| 750 | { | 754 | { |
| 751 | - // Copy attributes | ||
| 752 | - m_infile = app.m_infile; | ||
| 753 | - m_outfile = app.m_outfile; | ||
| 754 | - m_prefix = app.m_prefix; | ||
| 755 | - m_caldb = app.m_caldb; | ||
| 756 | - m_irf = app.m_irf; | ||
| 757 | - m_srcmdl = app.m_srcmdl; | ||
| 758 | - m_proj = app.m_proj; | ||
| 759 | - m_coordsys = app.m_coordsys; | ||
| 760 | - m_ra = app.m_ra; | ||
| 761 | - m_dec = app.m_dec; | ||
| 762 | - m_deadc = app.m_deadc; | ||
| 763 | - m_tmin = app.m_tmin; | ||
| 764 | - m_tmax = app.m_tmax; | ||
| 765 | - m_emin = app.m_emin; | ||
| 766 | - m_emax = app.m_emax; | ||
| 767 | - m_enumbins = app.m_enumbins; | ||
| 768 | - m_xref = app.m_xref; | ||
| 769 | - m_yref = app.m_yref; | ||
| 770 | - m_binsz = app.m_binsz; | ||
| 771 | - m_nxpix = app.m_nxpix; | ||
| 772 | - m_nypix = app.m_nypix; | ||
| 773 | - m_apply_edisp = app.m_apply_edisp; | 755 | + // Continue only if observation pointer is valid |
| 756 | + if (obs != NULL) { | ||
| 774 | 757 | ||
| 775 | - // Copy protected members | ||
| 776 | - m_obs = app.m_obs; | ||
| 777 | - m_infiles = app.m_infiles; | ||
| 778 | - m_use_xml = app.m_use_xml; | ||
| 779 | - m_read_ahead = app.m_read_ahead; | 758 | + // Initialise statistics |
| 759 | + double sum = 0.0; | ||
| 780 | 760 | ||
| 781 | - // Return | ||
| 782 | - return; | ||
| 783 | -} | 761 | + // Setup cube GTIs for this observation |
| 762 | + m_cube.gti(obs->events()->gti()); | ||
| 784 | 763 | ||
| 764 | + // Loop over all cube bins | ||
| 765 | + for (int i = 0; i < m_cube.size(); ++i) { | ||
| 785 | 766 | ||
| 786 | -/***********************************************************************//** | ||
| 787 | - * @brief Delete class members | ||
| 788 | - ***************************************************************************/ | ||
| 789 | -void ctmodel::free_members(void) | ||
| 790 | -{ | ||
| 791 | - // Write separator into logger | ||
| 792 | - if (logTerse()) { | ||
| 793 | - log << std::endl; | ||
| 794 | - } | ||
| 795 | - | ||
| 796 | - // Return | ||
| 797 | - return; | ||
| 798 | -} | 767 | + // Get cube bin and actual value |
| 768 | + GCTAEventBin* bin = m_cube[i]; | ||
| 769 | + double value = bin->counts(); | ||
| 770 | + | ||
| 771 | + // Compute model value for cube bin | ||
| 772 | + double model = m_obs.models().eval(*bin, *obs) * bin->size(); | ||
| 799 | 773 | ||
| 774 | + // Add model to actual value | ||
| 775 | + value += model; | ||
| 776 | + sum += model; | ||
| 800 | 777 | ||
| 801 | -/***********************************************************************//** | ||
| 802 | - * @brief Set output file name. | ||
| 803 | - * | ||
| 804 | - * @param[in] filename Input file name. | ||
| 805 | - * | ||
| 806 | - * Converts an input filename into an output filename by prepending the | ||
| 807 | - * prefix stored in the member m_prefix to the input filename. Any path will | ||
| 808 | - * be stripped from the input filename. Also a trailing ".gz" will be | ||
| 809 | - * stripped. | ||
| 810 | - ***************************************************************************/ | ||
| 811 | -std::string ctmodel::set_outfile_name(const std::string& filename) const | ||
| 812 | -{ | ||
| 813 | - // Split input filename into path elements | ||
| 814 | - std::vector<std::string> elements = gammalib::split(filename, "/"); | 778 | + // Store value |
| 779 | + bin->counts(value); | ||
| 815 | 780 | ||
| 816 | - // The last path element is the filename | ||
| 817 | - std::string outname = m_prefix + elements[elements.size()-1]; | 781 | + } // endfor: looped over all cube bins |
| 818 | 782 | ||
| 819 | - // Strip any ".gz" | ||
| 820 | - outname = gammalib::strip_chars(outname, ".gz"); | ||
| 821 | - | ||
| 822 | - // Return output filename | ||
| 823 | - return outname; | ||
| 824 | -} | 783 | + // Append GTIs of observation to list of GTIs |
| 784 | + m_gti.extend(obs->events()->gti()); | ||
| 825 | 785 | ||
| 786 | + // Update GTIs | ||
| 787 | + m_cube.gti(m_gti); | ||
| 826 | 788 | ||
| 827 | -/***********************************************************************//** | ||
| 828 | - * @brief Save model map in FITS format. | ||
| 829 | - * | ||
| 830 | - * Save the model map as a FITS file. The filename of the FITS file is | ||
| 831 | - * specified by the m_outfile member. | ||
| 832 | - ***************************************************************************/ | ||
| 833 | -void ctmodel::save_fits(void) | ||
| 834 | -{ | ||
| 835 | - // Get output filename | ||
| 836 | - m_outfile = (*this)["outfile"].filename(); | 789 | + // Log results |
| 790 | + if (logTerse()) { | ||
| 791 | + log << gammalib::parformat("Model events in cube"); | ||
| 792 | + log << sum << std::endl; | ||
| 793 | + } | ||
| 837 | 794 | ||
| 838 | - // Get CTA observation from observation container | ||
| 839 | - GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[0]); | 795 | + // Log cube |
| 796 | + if (logExplicit()) { | ||
| 797 | + log.header2("Model cube"); | ||
| 798 | + log << m_cube << std::endl; | ||
| 799 | + } | ||
| 840 | 800 | ||
| 841 | - // Save model map | ||
| 842 | - save_model_map(obs, m_outfile); | 801 | + } // endif: observation was valid |
| 843 | 802 | ||
| 844 | // Return | 803 | // Return |
| 845 | return; | 804 | return; |
| @@ -847,83 +806,76 @@ void ctmodel::save_fits(void) | @@ -847,83 +806,76 @@ void ctmodel::save_fits(void) | ||
| 847 | 806 | ||
| 848 | 807 | ||
| 849 | /***********************************************************************//** | 808 | /***********************************************************************//** |
| 850 | - * @brief Save model map(s) in XML format. | 809 | + * @brief Get the energy boundaries |
| 810 | + * | ||
| 811 | + * @exception GException::invalid_value | ||
| 812 | + * No valid energy boundary extension found. | ||
| 851 | * | 813 | * |
| 852 | - * Save the model map(s) into FITS files and write the file path information | ||
| 853 | - * into a XML file. The filename of the XML file is specified by the | ||
| 854 | - * m_outfile member, the filename(s) of the model map(s) are built by | ||
| 855 | - * prepending the prefix given by the m_prefix member to the input model | ||
| 856 | - * map(s) filenames. Any path present in the input filename will be stripped, | ||
| 857 | - * i.e. the model map(s) will be written in the local working directory | ||
| 858 | - * (unless a path is specified in the m_prefix member). | 814 | + * Get the energy boundaries according to the user parameters. The method |
| 815 | + * supports loading of energy boundary information from the EBOUNDS or | ||
| 816 | + * ENERGYBINS extension, or setting energy boundaries using a linear | ||
| 817 | + * or logarithmical spacing. | ||
| 818 | + * | ||
| 819 | + * @todo Ultimately this method should go in a support library as it is | ||
| 820 | + * used by several ctools. | ||
| 859 | ***************************************************************************/ | 821 | ***************************************************************************/ |
| 860 | -void ctmodel::save_xml(void) | 822 | +void ctmodel::get_ebounds(void) |
| 861 | { | 823 | { |
| 862 | - // Get output filename and prefix | ||
| 863 | - m_outfile = (*this)["outfile"].filename(); | ||
| 864 | - m_prefix = (*this)["prefix"].string(); | ||
| 865 | - | ||
| 866 | - // Issue warning if output filename has no .xml suffix | ||
| 867 | - std::string suffix = gammalib::tolower(m_outfile.substr(m_outfile.length()-4,4)); | ||
| 868 | - if (suffix != ".xml") { | ||
| 869 | - log << "*** WARNING: Name of observation definition output file \""+ | ||
| 870 | - m_outfile+"\"" << std::endl; | ||
| 871 | - log << "*** WARNING: does not terminate with \".xml\"." << std::endl; | ||
| 872 | - log << "*** WARNING: This is not an error, but might be misleading." | ||
| 873 | - " It is recommended" << std::endl; | ||
| 874 | - log << "*** WARNING: to use the suffix \".xml\" for observation" | ||
| 875 | - " definition files." << std::endl; | ||
| 876 | - } | ||
| 877 | - | ||
| 878 | - // Loop over all observation in the container | ||
| 879 | - for (int i = 0; i < m_obs.size(); ++i) { | ||
| 880 | - | ||
| 881 | - // Get CTA observation | ||
| 882 | - GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]); | ||
| 883 | - | ||
| 884 | - // Handle only CTA observations | ||
| 885 | - if (obs != NULL) { | ||
| 886 | - | ||
| 887 | - // Set event output file name | ||
| 888 | - std::string outfile = set_outfile_name(m_infiles[i]); | ||
| 889 | - | ||
| 890 | - // Store output file name in observation | ||
| 891 | - obs->eventfile(outfile); | ||
| 892 | - | ||
| 893 | - // Save event list | ||
| 894 | - save_model_map(obs, outfile); | ||
| 895 | - | ||
| 896 | - } // endif: observation was a CTA observations | 824 | + // Initialse energy boundary information |
| 825 | + m_ebounds.clear(); | ||
| 826 | + | ||
| 827 | + // Check whether energy binning information should be read from a FITS | ||
| 828 | + // file ... | ||
| 829 | + if (m_ebinalg == "FILE") { | ||
| 830 | + | ||
| 831 | + // Open energy boundary file using the EBOUNDS or ENERGYBINS | ||
| 832 | + // extension. Throw an exception if opening fails. | ||
| 833 | + GFits file(m_ebinfile); | ||
| 834 | + if (file.contains("EBOUNDS")) { | ||
| 835 | + file.close(); | ||
| 836 | + m_ebounds.load(m_ebinfile,"EBOUNDS"); | ||
| 837 | + } | ||
| 838 | + else if (file.contains("ENERGYBINS")) { | ||
| 839 | + file.close(); | ||
| 840 | + m_ebounds.load(m_ebinfile,"ENERGYBINS"); | ||
| 841 | + } | ||
| 842 | + else { | ||
| 843 | + file.close(); | ||
| 844 | + std::string msg = "No extension with name \"EBOUNDS\" or" | ||
| 845 | + " \"ENERGYBINS\" found in FITS file" | ||
| 846 | + " \""+m_ebinfile+"\".\n" | ||
| 847 | + "An \"EBOUNDS\" or \"ENERGYBINS\" extension" | ||
| 848 | + " is required if the parameter \"ebinalg\"" | ||
| 849 | + " is set to \"FILE\"."; | ||
| 850 | + throw GException::invalid_value(G_GET_EBOUNDS, msg); | ||
| 851 | + } | ||
| 852 | + | ||
| 853 | + // Set enumbins parameter to number of ebounds | ||
| 854 | + m_enumbins = m_ebounds.size(); | ||
| 897 | 855 | ||
| 898 | - } // endfor: looped over observations | 856 | + } // endif: ebinalg was "FILE" |
| 899 | 857 | ||
| 900 | - // Save observations in XML file | ||
| 901 | - m_obs.save(m_outfile); | 858 | + // ... otherwise use a linear or a logarithmically-spaced energy binning |
| 859 | + else { | ||
| 902 | 860 | ||
| 903 | - // Return | ||
| 904 | - return; | ||
| 905 | -} | 861 | + // Initialise log mode for ebinning |
| 862 | + bool log = true; | ||
| 906 | 863 | ||
| 864 | + // check if algorithm is linear | ||
| 865 | + if (m_ebinalg == "LIN") { | ||
| 866 | + log = false; | ||
| 867 | + } | ||
| 907 | 868 | ||
| 908 | -/***********************************************************************//** | ||
| 909 | - * @brief Save a single model map into a FITS file | ||
| 910 | - * | ||
| 911 | - * @param[in] obs Pointer to CTA observation. | ||
| 912 | - * @param[in] outfile Output file name. | ||
| 913 | - * | ||
| 914 | - * This method saves a single model map into a FITS file. The method does | ||
| 915 | - * nothing if the observation pointer is not valid. | ||
| 916 | - ***************************************************************************/ | ||
| 917 | -void ctmodel::save_model_map(const GCTAObservation* obs, | ||
| 918 | - const std::string& outfile) const | ||
| 919 | -{ | ||
| 920 | - // Save only if observation is valid | ||
| 921 | - if (obs != NULL) { | 869 | + // todo: should we also check if m_ebinalg is "LOG" |
| 870 | + // and throw an exception if neither LIN/LOG/FILE | ||
| 871 | + // is given? | ||
| 922 | 872 | ||
| 923 | - // Save observation into FITS file | ||
| 924 | - obs->save(outfile, clobber()); | 873 | + // Setup energy range covered by data |
| 874 | + GEnergy emin(m_emin, "TeV"); | ||
| 875 | + GEnergy emax(m_emax, "TeV"); | ||
| 876 | + m_ebounds = GEbounds(m_enumbins, emin, emax, log); | ||
| 925 | 877 | ||
| 926 | - } // endif: observation was valid | 878 | + } //endif: ebinalg was not "FILE" |
| 927 | 879 | ||
| 928 | // Return | 880 | // Return |
| 929 | return; | 881 | return; |
src/ctmodel/ctmodel.hpp
| 1 | /*************************************************************************** | 1 | /*************************************************************************** |
| 2 | - * ctmodel - CTA counts model tool * | 2 | + * ctmodel - CTA model cube generation tool * |
| 3 | * ----------------------------------------------------------------------- * | 3 | * ----------------------------------------------------------------------- * |
| 4 | * copyright (C) 2012-2014 by Juergen Knoedlseder * | 4 | * copyright (C) 2012-2014 by Juergen Knoedlseder * |
| 5 | * ----------------------------------------------------------------------- * | 5 | * ----------------------------------------------------------------------- * |
| @@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
| 20 | ***************************************************************************/ | 20 | ***************************************************************************/ |
| 21 | /** | 21 | /** |
| 22 | * @file ctmodel.hpp | 22 | * @file ctmodel.hpp |
| 23 | - * @brief CTA counts model tool definition | 23 | + * @brief CTA model cube tool definition |
| 24 | * @author Juergen Knoedlseder | 24 | * @author Juergen Knoedlseder |
| 25 | */ | 25 | */ |
| 26 | 26 | ||
| @@ -69,25 +69,23 @@ public: | @@ -69,25 +69,23 @@ public: | ||
| 69 | void run(void); | 69 | void run(void); |
| 70 | void save(void); | 70 | void save(void); |
| 71 | const GObservations& obs(void) const; | 71 | const GObservations& obs(void) const; |
| 72 | + const GCTAEventCube& cube(void) const; | ||
| 72 | 73 | ||
| 73 | protected: | 74 | protected: |
| 74 | // Protected methods | 75 | // Protected methods |
| 75 | - void init_members(void); | ||
| 76 | - void copy_members(const ctmodel& app); | ||
| 77 | - void free_members(void); | ||
| 78 | - void get_parameters(void); | ||
| 79 | - void setup_obs(void); | ||
| 80 | - void model_map(GCTAObservation* obs, const GModels& models); | ||
| 81 | - std::string set_outfile_name(const std::string& filename) const; | ||
| 82 | - void save_fits(void); | ||
| 83 | - void save_xml(void); | ||
| 84 | - void save_model_map(const GCTAObservation* obs, | ||
| 85 | - const std::string& outfile) const; | ||
| 86 | - | 76 | + void init_members(void); |
| 77 | + void copy_members(const ctmodel& app); | ||
| 78 | + void free_members(void); | ||
| 79 | + void get_parameters(void); | ||
| 80 | + void setup_obs(void); | ||
| 81 | + void init_cube(void); | ||
| 82 | + void fill_cube(const GCTAObservation* obs); | ||
| 83 | + void get_ebounds(void); | ||
| 84 | + | ||
| 87 | // User parameters | 85 | // User parameters |
| 88 | - std::string m_infile; //!< Input counts map or XML file | ||
| 89 | - std::string m_outfile; //!< Output model map or XML file | ||
| 90 | - std::string m_prefix; //!< Prefix for multiple model maps | 86 | + std::string m_infile; //!< Input counts cube |
| 87 | + std::string m_obsfile; //!< Event list, counts map or observation definition XML file | ||
| 88 | + std::string m_outfile; //!< Output model cube | ||
| 91 | std::string m_caldb; //!< Calibration database | 89 | std::string m_caldb; //!< Calibration database |
| 92 | std::string m_irf; //!< Instrument response functions | 90 | std::string m_irf; //!< Instrument response functions |
| 93 | std::string m_srcmdl; //!< Source model | 91 | std::string m_srcmdl; //!< Source model |
| @@ -96,6 +94,8 @@ protected: | @@ -96,6 +94,8 @@ protected: | ||
| 96 | double m_deadc; //!< Deadtime correction factor | 94 | double m_deadc; //!< Deadtime correction factor |
| 97 | double m_tmin; //!< Start time | 95 | double m_tmin; //!< Start time |
| 98 | double m_tmax; //!< Stop time | 96 | double m_tmax; //!< Stop time |
| 97 | + std::string m_ebinalg; //!< Algorithm for energy binning | ||
| 98 | + std::string m_ebinfile; //!< FITS-file containing energy binning | ||
| 99 | double m_emin; //!< Lower energy | 99 | double m_emin; //!< Lower energy |
| 100 | double m_emax; //!< Upper energy | 100 | double m_emax; //!< Upper energy |
| 101 | int m_enumbins; //!< Number of energy bins | 101 | int m_enumbins; //!< Number of energy bins |
| @@ -109,10 +109,11 @@ protected: | @@ -109,10 +109,11 @@ protected: | ||
| 109 | bool m_apply_edisp; //!< Apply energy dispersion? | 109 | bool m_apply_edisp; //!< Apply energy dispersion? |
| 110 | 110 | ||
| 111 | // Protected members | 111 | // Protected members |
| 112 | - GObservations m_obs; //!< Observation container | ||
| 113 | - std::vector<std::string> m_infiles; //!< Input event filenames | ||
| 114 | - bool m_use_xml; //!< Use XML file instead of FITS file | ||
| 115 | - bool m_read_ahead; //!< Read ahead parameters | 112 | + GObservations m_obs; //!< Observation container |
| 113 | + GCTAEventCube m_cube; //!< Model cube | ||
| 114 | + GEbounds m_ebounds; //!< Energy boundaries | ||
| 115 | + GGti m_gti; //!< Model cube GTIs | ||
| 116 | + bool m_read_ahead; //!< Read ahead parameters | ||
| 116 | }; | 117 | }; |
| 117 | 118 | ||
| 118 | 119 | ||
| @@ -127,4 +128,16 @@ const GObservations& ctmodel::obs(void) const | @@ -127,4 +128,16 @@ const GObservations& ctmodel::obs(void) const | ||
| 127 | return m_obs; | 128 | return m_obs; |
| 128 | } | 129 | } |
| 129 | 130 | ||
| 131 | + | ||
| 132 | +/***********************************************************************//** | ||
| 133 | + * @brief Return model cube | ||
| 134 | + * | ||
| 135 | + * @return Reference to model cube | ||
| 136 | + ***************************************************************************/ | ||
| 137 | +inline | ||
| 138 | +const GCTAEventCube& ctmodel::cube(void) const | ||
| 139 | +{ | ||
| 140 | + return m_cube; | ||
| 141 | +} | ||
| 142 | + | ||
| 130 | #endif /* CTMODEL_HPP */ | 143 | #endif /* CTMODEL_HPP */ |
src/ctmodel/ctmodel.par
| @@ -5,7 +5,7 @@ | @@ -5,7 +5,7 @@ | ||
| 5 | # ------------------------------------------------------------------------- # | 5 | # ------------------------------------------------------------------------- # |
| 6 | # # | 6 | # # |
| 7 | # File: ctmodel.par # | 7 | # File: ctmodel.par # |
| 8 | -# Version: 00-02-00 # | 8 | +# Version: 00-03-00 # |
| 9 | # # | 9 | # # |
| 10 | # Author: Juergen Knoedlseder # | 10 | # Author: Juergen Knoedlseder # |
| 11 | # Jurgen.Knodlseder@irap.omp.eu # | 11 | # Jurgen.Knodlseder@irap.omp.eu # |
| @@ -19,22 +19,19 @@ | @@ -19,22 +19,19 @@ | ||
| 19 | #=================== | 19 | #=================== |
| 20 | infile, f, a, "NONE",,, "Input counts map or observation definition file" | 20 | infile, f, a, "NONE",,, "Input counts map or observation definition file" |
| 21 | outfile, f, a, "modmap.fits",,, "Output counts map or observation definition file" | 21 | outfile, f, a, "modmap.fits",,, "Output counts map or observation definition file" |
| 22 | -prefix, s, h, "modmap_",,, "Prefix for counts maps in observation definition file" | ||
| 23 | -caldb, s, a, "$CTOOLS/share/caldb/data/cta/dummy",,, "Calibration database" | ||
| 24 | -irf, s, a, "cta_dummy_irf",,, "Instrument response function" | ||
| 25 | -edisp, b, h, no,,, "Apply energy dispersion?" | ||
| 26 | srcmdl, f, a, "$CTOOLS/share/models/crab.xml",,, "Source model" | 22 | srcmdl, f, a, "$CTOOLS/share/models/crab.xml",,, "Source model" |
| 23 | +edisp, b, h, no,,, "Apply energy dispersion?" | ||
| 27 | # | 24 | # |
| 28 | -# Instrument parameters | ||
| 29 | -#====================== | ||
| 30 | -ra, r, a, 83.63, 0,360, "RA of pointing (degrees)" | ||
| 31 | -dec, r, a, 22.01, -90, 90, "Dec of pointing (degrees)" | ||
| 32 | -deadc, r, h, 0.95, 0, 1, "Average deadtime correction factor" | ||
| 33 | -# | ||
| 34 | -# Time range parameters | ||
| 35 | -#====================== | ||
| 36 | -tmin, r, a, 0.0, 0, , "Start time (MET in s)" | ||
| 37 | -tmax, r, a, 1800.0, 0, , "End time (MET in s)" | 25 | +# Observation parameters |
| 26 | +#======================= | ||
| 27 | +obsfile, f, a, "NONE",,, "Observation definition file" | ||
| 28 | +caldb, s, a, "$CTOOLS/share/caldb/data/cta/dummy",,, "Calibration database" | ||
| 29 | +irf, s, a, "cta_dummy_irf",,, "Instrument response function" | ||
| 30 | +ra, r, a, 83.63,0,360, "RA of pointing (degrees)" | ||
| 31 | +dec, r, a, 22.01,-90,90, "Dec of pointing (degrees)" | ||
| 32 | +tmin, r, a, 0.0,0,, "Start time (MET in s)" | ||
| 33 | +tmax, r, a, 1800.0,0,, "End time (MET in s)" | ||
| 34 | +deadc, r, h, 0.95,0,1, "Average deadtime correction factor" | ||
| 38 | # | 35 | # |
| 39 | # Energy binning parameters | 36 | # Energy binning parameters |
| 40 | #========================== | 37 | #========================== |
test/test_ctmodel.py
| @@ -68,9 +68,10 @@ class Test(gammalib.GPythonTestSuite): | @@ -68,9 +68,10 @@ class Test(gammalib.GPythonTestSuite): | ||
| 68 | model = ctools.ctmodel() | 68 | model = ctools.ctmodel() |
| 69 | model["infile"].filename("NONE") | 69 | model["infile"].filename("NONE") |
| 70 | model["outfile"].filename("modmap.fits") | 70 | model["outfile"].filename("modmap.fits") |
| 71 | + model["srcmdl"].filename(self.model_name) | ||
| 72 | + model["obsfile"].filename("NONE") | ||
| 71 | model["caldb"].string(self.caldb) | 73 | model["caldb"].string(self.caldb) |
| 72 | model["irf"].string(self.irf) | 74 | model["irf"].string(self.irf) |
| 73 | - model["srcmdl"].filename(self.model_name) | ||
| 74 | model["ra"].real(83.63) | 75 | model["ra"].real(83.63) |
| 75 | model["dec"].real(22.01) | 76 | model["dec"].real(22.01) |
| 76 | model["tmin"].real(0.0) | 77 | model["tmin"].real(0.0) |
test/test_ctools.sh
| @@ -197,6 +197,7 @@ $ECHO -n "Test ctmodel: " | @@ -197,6 +197,7 @@ $ECHO -n "Test ctmodel: " | ||
| 197 | # | 197 | # |
| 198 | # Run 1 | 198 | # Run 1 |
| 199 | $ctmodel infile="cntmap.fits" \ | 199 | $ctmodel infile="cntmap.fits" \ |
| 200 | + obsfile="cntmap.fits" \ | ||
| 200 | outfile="modmap1.fits" \ | 201 | outfile="modmap1.fits" \ |
| 201 | caldb="irf" \ | 202 | caldb="irf" \ |
| 202 | irf="cta_dummy_irf" \ | 203 | irf="cta_dummy_irf" \ |
| @@ -212,6 +213,7 @@ fi | @@ -212,6 +213,7 @@ fi | ||
| 212 | # | 213 | # |
| 213 | # Run 3 | 214 | # Run 3 |
| 214 | $ctmodel infile="NONE" \ | 215 | $ctmodel infile="NONE" \ |
| 216 | + obsfile="NONE" \ | ||
| 215 | outfile="modmap3.fits" \ | 217 | outfile="modmap3.fits" \ |
| 216 | caldb="irf" \ | 218 | caldb="irf" \ |
| 217 | irf="cta_dummy_irf" \ | 219 | irf="cta_dummy_irf" \ |
| @@ -241,6 +243,7 @@ fi | @@ -241,6 +243,7 @@ fi | ||
| 241 | # | 243 | # |
| 242 | # Run 2 | 244 | # Run 2 |
| 243 | $ctmodel infile="cntmap2.fits" \ | 245 | $ctmodel infile="cntmap2.fits" \ |
| 246 | + obsfile="cntmap2.fits" \ | ||
| 244 | outfile="modmap2.fits" \ | 247 | outfile="modmap2.fits" \ |
| 245 | caldb="irf" \ | 248 | caldb="irf" \ |
| 246 | irf="cta_dummy_irf" \ | 249 | irf="cta_dummy_irf" \ |