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 20 ctbutterfly --- Compute butterfly <ctbutterfly>
21 21 ctcubemask --- Filter counts cube <ctcubemask>
22 22 ctedispcube --- Generates energy dispersion cube <ctedispcube>
  23 + cterror --- Calculates likelihood profile errors <cterror>
23 24 ctexpcube --- Generates exposure cube <ctexpcube>
24 25 ctlike --- Performs maximum likelihood fitting <ctlike>
  26 + ctmapcube --- Generates a map cube <ctmapcube>
25 27 ctmodel --- Computes model counts cube <ctmodel>
26   - ctobssim --- Simulate CTA observations <ctobssim>
  28 + ctobssim --- Simulate observations <ctobssim>
27 29 ctpsfcube --- Generates point spread function cube <ctpsfcube>
28 30 ctselect --- Selects event data <ctselect>
29 31 ctskymap --- Generates sky map <ctskymap>
30   - cttsmap --- Generates Test Statistics map <cttsmap>
  32 + cttsmap --- Generates Test Statistic map <cttsmap>
31 33 ctulimit --- Calculates upper limit <ctulimit>
32   - cterror --- Calculates likelihood profile errors <cterror>
33 34  
34 35  
35 36 General cscripts
... ...
src/ctmapcube/ctmapcube.cpp
... ... @@ -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 156 void ctmapcube::clear(void)
157 157 {
... ... @@ -245,6 +245,8 @@ void ctmapcube::save(void)
245 245 * @brief Publish map cube
246 246 *
247 247 * @param[in] name Map cube name.
  248 + *
  249 + * Publishes the map cube on a VO Hub.
248 250 ***************************************************************************/
249 251 void ctmapcube::publish(const std::string& name)
250 252 {
... ... @@ -287,7 +289,8 @@ void ctmapcube::init_members(void)
287 289 {
288 290 // Initialise members
289 291 m_outcube.clear();
290   - m_publish = false;
  292 + m_ptsrcsig = 1.0;
  293 + m_publish = false;
291 294  
292 295 // Initialise protected members
293 296 m_models.clear();
... ... @@ -306,8 +309,9 @@ void ctmapcube::init_members(void)
306 309 void ctmapcube::copy_members(const ctmapcube& app)
307 310 {
308 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 316 // Copy protected members
313 317 m_models = app.m_models;
... ... @@ -332,10 +336,21 @@ void ctmapcube::free_members(void)
332 336 * @brief Get application parameters
333 337 *
334 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 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 354 // Get energy binning parameters
340 355 GEnergies energies = create_energies();
341 356  
... ... @@ -348,19 +363,9 @@ void ctmapcube::get_parameters(void)
348 363 int nxpix = (*this)["nxpix"].integer();
349 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 370 // Read optionally output cube filenames
366 371 if (read_ahead()) {
... ... @@ -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 408 GEnergies ctmapcube::create_energies(void)
403 409 {
... ... @@ -510,6 +516,8 @@ void ctmapcube::create_cube(void)
510 516 /***********************************************************************//**
511 517 * @brief Add one model to map cube
512 518 *
  519 + * @param[in] model Pointer to point source sky model.
  520 + *
513 521 * Adds one model to map cube.
514 522 ***************************************************************************/
515 523 void ctmapcube::add_model(GModelSky* model)
... ... @@ -520,21 +528,37 @@ void ctmapcube::add_model(GModelSky* model)
520 528 // Get pointer to sky map
521 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 553 // Set photon
530   - GPhoton photon(map->inx2dir(ipixel), energies[iebin], GTime());
  554 + GPhoton photon(dir, energies[iebin], GTime());
531 555  
532 556 // Add model value
533 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 563 // Return
540 564 return;
... ... @@ -544,51 +568,141 @@ void ctmapcube::add_model(GModelSky* model)
544 568 /***********************************************************************//**
545 569 * @brief Add one point source model to map cube
546 570 *
  571 + * @param[in] model Pointer to point source sky model.
  572 + *
547 573 * Adds one point source model to map cube.
548 574 ***************************************************************************/
549 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 707 // Return
594 708 return;
... ...
src/ctmapcube/ctmapcube.hpp
... ... @@ -71,9 +71,13 @@ protected:
71 71 void create_cube(void);
72 72 void add_model(GModelSky* model);
73 73 void add_ptsrc_model(GModelSky* model);
  74 + void get_bounding_circle(GModelSky* model,
  75 + GSkyDir* dir,
  76 + double* radius) const;
74 77  
75 78 // User parameters
76 79 GFilename m_outcube; //!< Output map cube filename
  80 + double m_ptsrcsig; //!< Point source sigma (arcmin)
77 81 bool m_publish; //!< Publish map cube?
78 82  
79 83 // Protected members
... ...
src/ctmapcube/ctmapcube.par
... ... @@ -19,6 +19,7 @@
19 19 #===================
20 20 inmodel, f, a, "$CTOOLS/share/models/crab.xml",,, "Input model XML file"
21 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 25 # Energy binning parameters
... ...