Commit 8af322b8bb79769f87189b2e0bc32f321b4380bb

Authored by Jürgen Knödlseder
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.
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)
@@ -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&amp; ctmodel::obs(void) const @@ -127,4 +128,16 @@ const GObservations&amp; 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 &quot;Test ctmodel: &quot; @@ -197,6 +197,7 @@ $ECHO -n &quot;Test ctmodel: &quot;
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" \