Commit 7c3dedd78e8fef1c6840dd7f8c86e85cdd70a662

Authored by Jürgen Knödlseder
1 parent 71ceba5f

Optionally replace point sources by small Gaussians and add reference documentation.

Also some code speed up by considering only relevant pixels for radial and elliptical models.
doc/source/reference_manual/ctmapcube.rst 0 → 100644
  1 +.. _ctmapcube:
  2 +
  3 +ctmapcube
  4 +=========
  5 +
  6 +Generate a map cube from an input model.
  7 +
  8 +
  9 +Synopsis
  10 +--------
  11 +
  12 +This tool generates a map cube from all sky model components contained in
  13 +an input model. A map cube is a series of sky maps, each spanned by Right
  14 +Ascension or Galactic longitude and Declination or Galactic latitude. Each
  15 +map corresponds to a specific photon energy. The energy binning of the map
  16 +cube may be either linear, logarithmic, or custom defined using an input
  17 +file.
  18 +
  19 +ctmapcube generates a map cube FITS file comprising two extensions. The
  20 +primary extension contains a 3-dimensional image containing the map cube
  21 +values. A second extension named ``ENERGIES`` contains a binary table that
  22 +defines the energy values of each map in the cube.
  23 +
  24 +
  25 +General parameters
  26 +------------------
  27 +
  28 +``inmodel [file]``
  29 + Input model XML file.
  30 +
  31 +``outcube [file]``
  32 + Output map cube file.
  33 +
  34 +``(ptsrcsig = 1.0) [real]``
  35 + Sigma of Gaussian to be used for point sources (in arcmin).
  36 +
  37 +``ebinalg <FILE|LIN|LOG> [string]``
  38 + Algorithm for defining energy bins.
  39 +
  40 +``emin [real]``
  41 + Lower energy value for first energy bin (in TeV).
  42 +
  43 +``emax [real]``
  44 + Upper energy value for last energy bin (in TeV).
  45 +
  46 +``enumbins [integer]``
  47 + Number of energy bins.
  48 +
  49 +``ebinfile [file]``
  50 + Name of the file containing the energy bin definition.
  51 +
  52 +``nxpix [integer]``
  53 + Number of cube bins in Right Ascension or Galactic longitude.
  54 +
  55 +``nypix [integer]``
  56 + Number of cube bins in Declination or Galactic latitude.
  57 +
  58 +``binsz [real]``
  59 + Image scale (in degrees/pixel).
  60 +
  61 +``coordsys <CEL|GAL> [string]``
  62 + Coordinate system (CEL - celestial, GAL - galactic).
  63 +
  64 +``xref [real]``
  65 + Right Ascension / Galactic longitude of cube centre (J2000, in degrees).
  66 +
  67 +``yref [real]``
  68 + Declination / Galactic latitude of cube centre (J2000, in degrees).
  69 +
  70 +``proj <AIT|AZP|CAR|MER|MOL|STG|TAN> [string]``
  71 + Projection method.
  72 +
  73 +
  74 +Standard parameters
  75 +-------------------
  76 +
  77 +``(publish = no) [boolean]``
  78 + Specifies whether the map cube should be published on VO Hub.
  79 +
  80 +``(chatter = 2) [integer]``
  81 + Verbosity of the executable:
  82 + chatter = 0: no information will be logged
  83 +
  84 + chatter = 1: only errors will be logged
  85 +
  86 + chatter = 2: errors and actions will be logged
  87 +
  88 + chatter = 3: report about the task execution
  89 +
  90 + chatter = 4: detailed report about the task execution
  91 +
  92 +``(clobber = yes) [boolean]``
  93 + Specifies whether an existing output counts cube file should be overwritten.
  94 +
  95 +``(debug = no) [boolean]``
  96 + Enables debug mode. In debug mode the executable will dump any log file output to the console.
  97 +
  98 +``(mode = ql) [string]``
  99 + Mode of automatic parameters (default is "ql", i.e. "query and learn").
  100 +
  101 +``(logfile = ctmapcube.log) [string]``
  102 + Name of log file.
  103 +
  104 +
  105 +Related tools or scripts
  106 +------------------------
  107 +
  108 +None
doc/source/reference_manual/index.rst
@@ -20,16 +20,17 @@ ctools @@ -20,16 +20,17 @@ ctools
20 ctbutterfly --- Compute butterfly <ctbutterfly> 20 ctbutterfly --- Compute butterfly <ctbutterfly>
21 ctcubemask --- Filter counts cube <ctcubemask> 21 ctcubemask --- Filter counts cube <ctcubemask>
22 ctedispcube --- Generates energy dispersion cube <ctedispcube> 22 ctedispcube --- Generates energy dispersion cube <ctedispcube>
  23 + cterror --- Calculates likelihood profile errors <cterror>
23 ctexpcube --- Generates exposure cube <ctexpcube> 24 ctexpcube --- Generates exposure cube <ctexpcube>
24 ctlike --- Performs maximum likelihood fitting <ctlike> 25 ctlike --- Performs maximum likelihood fitting <ctlike>
  26 + ctmapcube --- Generates a map cube <ctmapcube>
25 ctmodel --- Computes model counts cube <ctmodel> 27 ctmodel --- Computes model counts cube <ctmodel>
26 - ctobssim --- Simulate CTA observations <ctobssim> 28 + ctobssim --- Simulate observations <ctobssim>
27 ctpsfcube --- Generates point spread function cube <ctpsfcube> 29 ctpsfcube --- Generates point spread function cube <ctpsfcube>
28 ctselect --- Selects event data <ctselect> 30 ctselect --- Selects event data <ctselect>
29 ctskymap --- Generates sky map <ctskymap> 31 ctskymap --- Generates sky map <ctskymap>
30 - cttsmap --- Generates Test Statistics map <cttsmap> 32 + cttsmap --- Generates Test Statistic map <cttsmap>
31 ctulimit --- Calculates upper limit <ctulimit> 33 ctulimit --- Calculates upper limit <ctulimit>
32 - cterror --- Calculates likelihood profile errors <cterror>  
33 34
34 35
35 General cscripts 36 General cscripts
src/ctmapcube/ctmapcube.cpp
@@ -151,7 +151,7 @@ ctmapcube&amp; ctmapcube::operator=(const ctmapcube&amp; app) @@ -151,7 +151,7 @@ ctmapcube&amp; ctmapcube::operator=(const ctmapcube&amp; app)
151 ==========================================================================*/ 151 ==========================================================================*/
152 152
153 /***********************************************************************//** 153 /***********************************************************************//**
154 - * @brief Clear instance 154 + * @brief Clear tool
155 ***************************************************************************/ 155 ***************************************************************************/
156 void ctmapcube::clear(void) 156 void ctmapcube::clear(void)
157 { 157 {
@@ -245,6 +245,8 @@ void ctmapcube::save(void) @@ -245,6 +245,8 @@ void ctmapcube::save(void)
245 * @brief Publish map cube 245 * @brief Publish map cube
246 * 246 *
247 * @param[in] name Map cube name. 247 * @param[in] name Map cube name.
  248 + *
  249 + * Publishes the map cube on a VO Hub.
248 ***************************************************************************/ 250 ***************************************************************************/
249 void ctmapcube::publish(const std::string& name) 251 void ctmapcube::publish(const std::string& name)
250 { 252 {
@@ -287,7 +289,8 @@ void ctmapcube::init_members(void) @@ -287,7 +289,8 @@ void ctmapcube::init_members(void)
287 { 289 {
288 // Initialise members 290 // Initialise members
289 m_outcube.clear(); 291 m_outcube.clear();
290 - m_publish = false; 292 + m_ptsrcsig = 1.0;
  293 + m_publish = false;
291 294
292 // Initialise protected members 295 // Initialise protected members
293 m_models.clear(); 296 m_models.clear();
@@ -306,8 +309,9 @@ void ctmapcube::init_members(void) @@ -306,8 +309,9 @@ void ctmapcube::init_members(void)
306 void ctmapcube::copy_members(const ctmapcube& app) 309 void ctmapcube::copy_members(const ctmapcube& app)
307 { 310 {
308 // Copy attributes 311 // Copy attributes
309 - m_outcube = app.m_outcube;  
310 - m_publish = app.m_publish; 312 + m_outcube = app.m_outcube;
  313 + m_ptsrcsig = app.m_ptsrcsig;
  314 + m_publish = app.m_publish;
311 315
312 // Copy protected members 316 // Copy protected members
313 m_models = app.m_models; 317 m_models = app.m_models;
@@ -332,10 +336,21 @@ void ctmapcube::free_members(void) @@ -332,10 +336,21 @@ void ctmapcube::free_members(void)
332 * @brief Get application parameters 336 * @brief Get application parameters
333 * 337 *
334 * Get all task parameters from parameter file or (if required) by querying 338 * Get all task parameters from parameter file or (if required) by querying
335 - * the user. The parameters are read in the correct order. 339 + * the user.
336 ***************************************************************************/ 340 ***************************************************************************/
337 void ctmapcube::get_parameters(void) 341 void ctmapcube::get_parameters(void)
338 { 342 {
  343 + // Read model definition file if required
  344 + if (m_models.size() == 0) {
  345 +
  346 + // Get model filename
  347 + GFilename inmodel = (*this)["inmodel"].filename();
  348 +
  349 + // Load models from file
  350 + m_models.load(inmodel);
  351 +
  352 + } // endif: there were no models
  353 +
339 // Get energy binning parameters 354 // Get energy binning parameters
340 GEnergies energies = create_energies(); 355 GEnergies energies = create_energies();
341 356
@@ -348,19 +363,9 @@ void ctmapcube::get_parameters(void) @@ -348,19 +363,9 @@ void ctmapcube::get_parameters(void)
348 int nxpix = (*this)["nxpix"].integer(); 363 int nxpix = (*this)["nxpix"].integer();
349 int nypix = (*this)["nypix"].integer(); 364 int nypix = (*this)["nypix"].integer();
350 365
351 - // Read model definition file if required  
352 - if (m_models.size() == 0) {  
353 -  
354 - // Get model filename  
355 - GFilename inmodel = (*this)["inmodel"].filename();  
356 -  
357 - // Load models from file  
358 - m_models.load(inmodel);  
359 -  
360 - } // endif: there were no models  
361 -  
362 - // Get remaining parameters  
363 - m_publish = (*this)["publish"].boolean(); 366 + // Get remaining hidden parameters
  367 + m_ptsrcsig = (*this)["ptsrcsig"].real();
  368 + m_publish = (*this)["publish"].boolean();
364 369
365 // Read optionally output cube filenames 370 // Read optionally output cube filenames
366 if (read_ahead()) { 371 if (read_ahead()) {
@@ -386,18 +391,19 @@ void ctmapcube::get_parameters(void) @@ -386,18 +391,19 @@ void ctmapcube::get_parameters(void)
386 391
387 392
388 /***********************************************************************//** 393 /***********************************************************************//**
389 - * @brief Create energy vector from user parameters 394 + * @brief Create map cube energies from user parameters
390 * 395 *
391 - * Get the energy vector according to the user parameters. The method  
392 - * supports loading of energy information from the ENERGIES extension (or  
393 - * any other extension specified by the "ebinfile" parameters), or setting  
394 - * energies using a linear or logarithmical spacing. 396 + * Creates the map cube energies according to the user parameters. If the
  397 + * @p ebinfile parameter is "FILE" the method loads the energy information
  398 + * from a FITS file. The name of the FITS file is given by the @p ebinfile
  399 + * parameter. If no extension name is specified the method will use assume
  400 + * the name to be "ENERGIES".
395 * 401 *
396 - * The following parameters are read:  
397 - * ebinalg - Energy binning algorithm  
398 - * emin - Minimum energy (if ebinalg != FILE)  
399 - * emax - Maximum energy (if ebinalg != FILE)  
400 - * enumbins - Number of energies (if ebinalg != FILE) 402 + * If the @p ebinfile parameter is "LIN" the method will create a linearly
  403 + * spaced series of @p enumbins energies in the interval @p emin to @p emax.
  404 + * Otherwise, the @p ebinfile parameter is assumed to be "LOG" and the method
  405 + * will create a logarithmically spaced series of @p enumbins energies in the
  406 + * interval @p emin to @p emax.
401 ***************************************************************************/ 407 ***************************************************************************/
402 GEnergies ctmapcube::create_energies(void) 408 GEnergies ctmapcube::create_energies(void)
403 { 409 {
@@ -510,6 +516,8 @@ void ctmapcube::create_cube(void) @@ -510,6 +516,8 @@ void ctmapcube::create_cube(void)
510 /***********************************************************************//** 516 /***********************************************************************//**
511 * @brief Add one model to map cube 517 * @brief Add one model to map cube
512 * 518 *
  519 + * @param[in] model Pointer to point source sky model.
  520 + *
513 * Adds one model to map cube. 521 * Adds one model to map cube.
514 ***************************************************************************/ 522 ***************************************************************************/
515 void ctmapcube::add_model(GModelSky* model) 523 void ctmapcube::add_model(GModelSky* model)
@@ -520,21 +528,37 @@ void ctmapcube::add_model(GModelSky* model) @@ -520,21 +528,37 @@ void ctmapcube::add_model(GModelSky* model)
520 // Get pointer to sky map 528 // Get pointer to sky map
521 GSkyMap* map = const_cast<GSkyMap*>(&m_cube.cube()); 529 GSkyMap* map = const_cast<GSkyMap*>(&m_cube.cube());
522 530
523 - // Loop over all energy bins  
524 - for (int iebin = 0; iebin < energies.size(); ++iebin) { 531 + // Get the model's bounding circle
  532 + GSkyDir centre;
  533 + double radius;
  534 + get_bounding_circle(model, &centre, &radius);
525 535
526 - // Loop over all spatial pixels  
527 - for (int ipixel = 0; ipixel < map->npix(); ++ipixel) { 536 + // Add some margin to circle radius
  537 + radius += 0.1;
  538 +
  539 + // Loop over all map cube pixels
  540 + for (int ipixel = 0; ipixel < map->npix(); ++ipixel) {
  541 +
  542 + // Get pixel sky direction
  543 + GSkyDir dir = map->inx2dir(ipixel);
  544 +
  545 + // Skip pixel if it's outside the bounding circle
  546 + if (centre.dist_deg(dir) > radius) {
  547 + continue;
  548 + }
  549 +
  550 + // Loop over all energy bins
  551 + for (int iebin = 0; iebin < energies.size(); ++iebin) {
528 552
529 // Set photon 553 // Set photon
530 - GPhoton photon(map->inx2dir(ipixel), energies[iebin], GTime()); 554 + GPhoton photon(dir, energies[iebin], GTime());
531 555
532 // Add model value 556 // Add model value
533 map->operator()(ipixel, iebin) += model->value(photon); 557 map->operator()(ipixel, iebin) += model->value(photon);
534 558
535 - } // endfor: looped over all pixels 559 + } // endfor: looped over all energies
536 560
537 - } // endfor: looped over all energies 561 + } // endfor: looped over all pixels
538 562
539 // Return 563 // Return
540 return; 564 return;
@@ -544,51 +568,141 @@ void ctmapcube::add_model(GModelSky* model) @@ -544,51 +568,141 @@ void ctmapcube::add_model(GModelSky* model)
544 /***********************************************************************//** 568 /***********************************************************************//**
545 * @brief Add one point source model to map cube 569 * @brief Add one point source model to map cube
546 * 570 *
  571 + * @param[in] model Pointer to point source sky model.
  572 + *
547 * Adds one point source model to map cube. 573 * Adds one point source model to map cube.
548 ***************************************************************************/ 574 ***************************************************************************/
549 void ctmapcube::add_ptsrc_model(GModelSky* model) 575 void ctmapcube::add_ptsrc_model(GModelSky* model)
550 { 576 {
551 - // Get point source spatial component  
552 - GModelSpatialPointSource* ptsrc = static_cast<GModelSpatialPointSource*>(model->spatial()); 577 + // Get pointer to sky map
  578 + GSkyMap* map = const_cast<GSkyMap*>(&m_cube.cube());
553 579
554 - // Get point source direction  
555 - GSkyDir dir = ptsrc->dir(); 580 + // If Gaussian sigma is positive then replace the point sources by a
  581 + // Gaussian with the user defined width
  582 + if (m_ptsrcsig > 0.0) {
556 583
557 - // Get cube energies  
558 - GEnergies energies = m_cube.energies(); 584 + // Get the point source centre (radius is ignored)
  585 + GSkyDir centre;
  586 + double radius;
  587 + get_bounding_circle(model, &centre, &radius);
559 588
560 - // Get pointer to sky map  
561 - GSkyMap* map = const_cast<GSkyMap*>(&m_cube.cube()); 589 + // Set the Gaussian sigma in degrees (m_ptsrcsig is in arcmin)
  590 + double sigma = m_ptsrcsig/60.0;
562 591
563 - // Get test sky map for flux computation  
564 - GSkyMap test_map(*map); 592 + // Create a Gaussian spatial model
  593 + GModelSpatialRadialGauss spatial(centre, sigma);
565 594
566 - // Continue only if map contains point source sky direction  
567 - if (map->contains(dir)) { 595 + // Create a new model reusing the spectral and temporal components
  596 + // of the original model
  597 + GModelSky skymodel(spatial, *(model->spectral()), *(model->temporal()));
568 598
569 - // Get map pixel  
570 - int ipixel = map->dir2inx(dir); 599 + // Add model
  600 + add_model(&skymodel);
571 601
572 - // Loop over all energy bins  
573 - for (int iebin = 0; iebin < energies.size(); ++iebin) { 602 + } // endif: Gaussian sigma was positive
574 603
575 - // Set photon using the point source sky direction  
576 - GPhoton photon(dir, energies[iebin], GTime()); 604 + // ... otherwise set a single map pixel
  605 + else {
577 606
578 - // Compute model value  
579 - double value = model->value(photon); 607 + // Get point source spatial component
  608 + GModelSpatialPointSource* ptsrc =
  609 + static_cast<GModelSpatialPointSource*>(model->spatial());
580 610
581 - // Compute flux normalization  
582 - test_map(ipixel, iebin) = value;  
583 - double flux = test_map.flux(ipixel, iebin);  
584 - double norm = (flux > 0.0) ? value / flux : 0.0; 611 + // Get point source direction
  612 + GSkyDir dir = ptsrc->dir();
585 613
586 - // Add model to sky map  
587 - map->operator()(ipixel, iebin) += norm * value; 614 + // Get cube energies
  615 + GEnergies energies = m_cube.energies();
588 616
589 - } // endfor: looped over all energies 617 + // Get test sky map for flux computation
  618 + GSkyMap test_map(*map);
  619 +
  620 + // Continue only if map contains point source sky direction
  621 + if (map->contains(dir)) {
  622 +
  623 + // Get map pixel
  624 + int ipixel = map->dir2inx(dir);
590 625
591 - } // endif: map contained sky direction 626 + // Loop over all energy bins
  627 + for (int iebin = 0; iebin < energies.size(); ++iebin) {
  628 +
  629 + // Set photon using the point source sky direction
  630 + GPhoton photon(dir, energies[iebin], GTime());
  631 +
  632 + // Compute model value
  633 + double value = model->value(photon);
  634 +
  635 + // Compute flux normalization
  636 + test_map(ipixel, iebin) = value;
  637 + double flux = test_map.flux(ipixel, iebin);
  638 + double norm = (flux > 0.0) ? value / flux : 0.0;
  639 +
  640 + // Add model to sky map
  641 + map->operator()(ipixel, iebin) += norm * value;
  642 +
  643 + } // endfor: looped over all energies
  644 +
  645 + } // endif: map contained sky direction
  646 +
  647 + } // endelse: Gaussian sigma was non positive
  648 +
  649 + // Return
  650 + return;
  651 +}
  652 +
  653 +
  654 +/***********************************************************************//**
  655 + * @brief Get bounding circle for a sky model
  656 + *
  657 + * @param[in] model Pointer to sky model.
  658 + * @param[out] dir Centre of bounding circle.
  659 + * @param[out] radius Radius of bounding circle (degrees).
  660 + *
  661 + * Determine for any spatial model the bounding circle. The bounding circle
  662 + * is a circular region that fully enclosed the model.
  663 + *
  664 + * The method does not verify the validity of the pointer arguments.
  665 + ***************************************************************************/
  666 +void ctmapcube::get_bounding_circle(GModelSky* model,
  667 + GSkyDir* dir,
  668 + double* radius) const
  669 +{
  670 + // Interpret the spatial model component as point source, radial source
  671 + // or elliptical source
  672 + GModelSpatialPointSource* ptsrc =
  673 + dynamic_cast<GModelSpatialPointSource*>(model->spatial());
  674 + GModelSpatialRadial* radial =
  675 + dynamic_cast<GModelSpatialRadial*>(model->spatial());
  676 + GModelSpatialElliptical* elliptical =
  677 + dynamic_cast<GModelSpatialElliptical*>(model->spatial());
  678 +
  679 + // If the spatial component as a point source then extract the source
  680 + // position and set the radius of the bounding box to 0.1 degrees
  681 + if (ptsrc != NULL) {
  682 + *dir = ptsrc->dir();
  683 + *radius = 0.1;
  684 + }
  685 +
  686 + // ... otherwise, if the spatial component is a radial source then extract
  687 + // the source position and set the radius of the bounding box from the
  688 + // value returned by theta_max() in radians
  689 + else if (radial != NULL) {
  690 + *dir = radial->dir();
  691 + *radius = radial->theta_max() * gammalib::rad2deg;
  692 + }
  693 +
  694 + // ... otherwise, if the spatial component is an elliptical source then
  695 + // extract the source position and set the radius of the bounding box from
  696 + // the value returned by theta_max() in radians
  697 + else if (elliptical != NULL) {
  698 + *dir = elliptical->dir();
  699 + *radius = elliptical->theta_max() * gammalib::rad2deg;
  700 + }
  701 +
  702 + // ... otherwise use the entire sky
  703 + else {
  704 + *radius = 180.0;
  705 + }
592 706
593 // Return 707 // Return
594 return; 708 return;
src/ctmapcube/ctmapcube.hpp
@@ -71,9 +71,13 @@ protected: @@ -71,9 +71,13 @@ protected:
71 void create_cube(void); 71 void create_cube(void);
72 void add_model(GModelSky* model); 72 void add_model(GModelSky* model);
73 void add_ptsrc_model(GModelSky* model); 73 void add_ptsrc_model(GModelSky* model);
  74 + void get_bounding_circle(GModelSky* model,
  75 + GSkyDir* dir,
  76 + double* radius) const;
74 77
75 // User parameters 78 // User parameters
76 GFilename m_outcube; //!< Output map cube filename 79 GFilename m_outcube; //!< Output map cube filename
  80 + double m_ptsrcsig; //!< Point source sigma (arcmin)
77 bool m_publish; //!< Publish map cube? 81 bool m_publish; //!< Publish map cube?
78 82
79 // Protected members 83 // Protected members
src/ctmapcube/ctmapcube.par
@@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
19 #=================== 19 #===================
20 inmodel, f, a, "$CTOOLS/share/models/crab.xml",,, "Input model XML file" 20 inmodel, f, a, "$CTOOLS/share/models/crab.xml",,, "Input model XML file"
21 outcube, f, a, "mapcube.fits",,, "Output map cube file" 21 outcube, f, a, "mapcube.fits",,, "Output map cube file"
  22 +ptsrcsig, r, h, 1.0,0,60, "Point source Gaussian sigma in arcmin"
22 23
23 # 24 #
24 # Energy binning parameters 25 # Energy binning parameters