Commit 0c70d44e9ef42b58a3ed881ec2b18a58da57607b
1 parent
e8719183
Add "addbounds" parameter to response cube tools
Showing
19 changed files
with
607 additions
and
101 deletions
cscripts/cspull.py
| @@ -20,6 +20,7 @@ | @@ -20,6 +20,7 @@ | ||
| 20 | # ========================================================================== | 20 | # ========================================================================== |
| 21 | import sys | 21 | import sys |
| 22 | import csv | 22 | import csv |
| 23 | +import math | ||
| 23 | import gammalib | 24 | import gammalib |
| 24 | import ctools | 25 | import ctools |
| 25 | from cscripts import obsutils | 26 | from cscripts import obsutils |
| @@ -163,6 +164,12 @@ class cspull(ctools.cscript): | @@ -163,6 +164,12 @@ class cspull(ctools.cscript): | ||
| 163 | self._log('\n') | 164 | self._log('\n') |
| 164 | self._log.header1('Compute stacked response') | 165 | self._log.header1('Compute stacked response') |
| 165 | 166 | ||
| 167 | + # Set number of energy bins to at least 30 per energy decade | ||
| 168 | + enumbins = int((math.log10(self['emax'].real()) - | ||
| 169 | + math.log10(self['emin'].real())) * 30.0) | ||
| 170 | + if self._enumbins > enumbins: | ||
| 171 | + enumbins = self._enumbins | ||
| 172 | + | ||
| 166 | # Get stacked exposure | 173 | # Get stacked exposure |
| 167 | expcube = ctools.ctexpcube(self._obs) | 174 | expcube = ctools.ctexpcube(self._obs) |
| 168 | expcube['incube'] = 'NONE' | 175 | expcube['incube'] = 'NONE' |
| @@ -171,7 +178,7 @@ class cspull(ctools.cscript): | @@ -171,7 +178,7 @@ class cspull(ctools.cscript): | ||
| 171 | expcube['binsz'] = self._binsz | 178 | expcube['binsz'] = self._binsz |
| 172 | expcube['nxpix'] = self._npix | 179 | expcube['nxpix'] = self._npix |
| 173 | expcube['nypix'] = self._npix | 180 | expcube['nypix'] = self._npix |
| 174 | - expcube['enumbins'] = self._enumbins | 181 | + expcube['enumbins'] = enumbins |
| 175 | expcube['emin'] = self['emin'].real() | 182 | expcube['emin'] = self['emin'].real() |
| 176 | expcube['emax'] = self['emax'].real() | 183 | expcube['emax'] = self['emax'].real() |
| 177 | expcube['coordsys'] = self._coordsys | 184 | expcube['coordsys'] = self._coordsys |
| @@ -195,7 +202,7 @@ class cspull(ctools.cscript): | @@ -195,7 +202,7 @@ class cspull(ctools.cscript): | ||
| 195 | psfcube['binsz'] = self._binsz*10.0 | 202 | psfcube['binsz'] = self._binsz*10.0 |
| 196 | psfcube['nxpix'] = self._npix/10 | 203 | psfcube['nxpix'] = self._npix/10 |
| 197 | psfcube['nypix'] = self._npix/10 | 204 | psfcube['nypix'] = self._npix/10 |
| 198 | - psfcube['enumbins'] = self._enumbins | 205 | + psfcube['enumbins'] = enumbins |
| 199 | psfcube['emin'] = self['emin'].real() | 206 | psfcube['emin'] = self['emin'].real() |
| 200 | psfcube['emax'] = self['emax'].real() | 207 | psfcube['emax'] = self['emax'].real() |
| 201 | psfcube['coordsys'] = self._coordsys | 208 | psfcube['coordsys'] = self._coordsys |
| @@ -220,7 +227,7 @@ class cspull(ctools.cscript): | @@ -220,7 +227,7 @@ class cspull(ctools.cscript): | ||
| 220 | edispcube['binsz'] = self._binsz*10.0 | 227 | edispcube['binsz'] = self._binsz*10.0 |
| 221 | edispcube['nxpix'] = self._npix/10 | 228 | edispcube['nxpix'] = self._npix/10 |
| 222 | edispcube['nypix'] = self._npix/10 | 229 | edispcube['nypix'] = self._npix/10 |
| 223 | - edispcube['enumbins'] = self._enumbins | 230 | + edispcube['enumbins'] = enumbins |
| 224 | edispcube['emin'] = self['emin'].real() | 231 | edispcube['emin'] = self['emin'].real() |
| 225 | edispcube['emax'] = self['emax'].real() | 232 | edispcube['emax'] = self['emax'].real() |
| 226 | edispcube['coordsys'] = self._coordsys | 233 | edispcube['coordsys'] = self._coordsys |
| @@ -244,7 +251,7 @@ class cspull(ctools.cscript): | @@ -244,7 +251,7 @@ class cspull(ctools.cscript): | ||
| 244 | bkgcube['binsz'] = self._binsz | 251 | bkgcube['binsz'] = self._binsz |
| 245 | bkgcube['nxpix'] = self._npix | 252 | bkgcube['nxpix'] = self._npix |
| 246 | bkgcube['nypix'] = self._npix | 253 | bkgcube['nypix'] = self._npix |
| 247 | - bkgcube['enumbins'] = self._enumbins | 254 | + bkgcube['enumbins'] = enumbins |
| 248 | bkgcube['emin'] = self['emin'].real() | 255 | bkgcube['emin'] = self['emin'].real() |
| 249 | bkgcube['emax'] = self['emax'].real() | 256 | bkgcube['emax'] = self['emax'].real() |
| 250 | bkgcube['coordsys'] = self._coordsys | 257 | bkgcube['coordsys'] = self._coordsys |
doc/source/users/reference_manual/ctbkgcube.rst
| @@ -25,10 +25,14 @@ cube as ``incube`` parameter. This will instruct ctbkgcube to extract the | @@ -25,10 +25,14 @@ cube as ``incube`` parameter. This will instruct ctbkgcube to extract the | ||
| 25 | background cube definition (such as sky coordinates and projection, number | 25 | background cube definition (such as sky coordinates and projection, number |
| 26 | of pixels, pixel scale, energy binning) from the counts cube. | 26 | of pixels, pixel scale, energy binning) from the counts cube. |
| 27 | 27 | ||
| 28 | +Note that there should at least be 25 bins per energy decade in the background | ||
| 29 | +cube to assure that the energy dependence of the background rate is sufficiently | ||
| 30 | +well sampled (in particular at low energies). | ||
| 31 | + | ||
| 28 | ctbkgcube generates a background cube FITS file comprising two extensions. | 32 | ctbkgcube generates a background cube FITS file comprising two extensions. |
| 29 | The primary extension contains a 3-dimensional image that contains the | 33 | The primary extension contains a 3-dimensional image that contains the |
| 30 | -background cube values. The next extension named ``EBOUNDS`` contains a | ||
| 31 | -binary table that defines the energy boundaries of the background cube. | 34 | +background cube values. The next extension named ``ENERGIES`` contains a |
| 35 | +binary table that defines the energies of the background cube. | ||
| 32 | 36 | ||
| 33 | ctbkgcube generates also an output model XML file that can serve as input | 37 | ctbkgcube generates also an output model XML file that can serve as input |
| 34 | for a maximum likelihood analysis. The output model XML file is a copy of | 38 | for a maximum likelihood analysis. The output model XML file is a copy of |
| @@ -82,7 +86,10 @@ General parameters | @@ -82,7 +86,10 @@ General parameters | ||
| 82 | 86 | ||
| 83 | ``ebinfile [file]`` | 87 | ``ebinfile [file]`` |
| 84 | Name of the file containing the energy bin definition. | 88 | Name of the file containing the energy bin definition. |
| 85 | - | 89 | + |
| 90 | +``(addbounds = yes) [boolean]`` | ||
| 91 | + Add energies to the background cube at the observation energy boundaries? | ||
| 92 | + | ||
| 86 | ``(usepnt = no) [boolean]`` | 93 | ``(usepnt = no) [boolean]`` |
| 87 | Use CTA pointing direction for cube centre instead of xref/yref parameters? | 94 | Use CTA pointing direction for cube centre instead of xref/yref parameters? |
| 88 | 95 |
doc/source/users/reference_manual/ctedispcube.rst
| @@ -29,13 +29,12 @@ rather coarse spatial binning to keep the file size manageable (with a typical | @@ -29,13 +29,12 @@ rather coarse spatial binning to keep the file size manageable (with a typical | ||
| 29 | value of ``binsz=1.0``). | 29 | value of ``binsz=1.0``). |
| 30 | 30 | ||
| 31 | ctedispcube generates an energy dispersion cube FITS file comprising three | 31 | ctedispcube generates an energy dispersion cube FITS file comprising three |
| 32 | -extensions. The primary extension contains a 3-dimensional image that contains | ||
| 33 | -the energy disperison values. The energy and fraction dimensions of the enrgy | ||
| 34 | -dispersion cube are folded into the 3rd dimension of the FITS image. The next | ||
| 35 | -extension named ``ENERGIES`` contains a binary table that defines the energy | ||
| 36 | -values of the energy dispersion cube. The last extension named ``MIGRAS`` | ||
| 37 | -contains a binary table that defines the migration values of the cube which | ||
| 38 | -is the ratio between reconstructed and true photon energy. | 32 | +extensions. The primary extension contains a 4-dimensional image that contains |
| 33 | +the energy disperison values. The next extension named ``ENERGIES`` contains | ||
| 34 | +a binary table that defines the energies of the energy dispersion cube. The | ||
| 35 | +last extension named ``MIGRAS`` contains a binary table that defines the | ||
| 36 | +migration values of the cube which is the ratio between reconstructed and true | ||
| 37 | +photon energy. | ||
| 39 | 38 | ||
| 40 | 39 | ||
| 41 | General parameters | 40 | General parameters |
| @@ -71,6 +70,9 @@ General parameters | @@ -71,6 +70,9 @@ General parameters | ||
| 71 | ``ebinfile [file]`` | 70 | ``ebinfile [file]`` |
| 72 | Name of the file containing the energy bin definition. | 71 | Name of the file containing the energy bin definition. |
| 73 | 72 | ||
| 73 | +``(addbounds = yes) [boolean]`` | ||
| 74 | + Add energies to the energy dispersion cube at the observation energy boundaries? | ||
| 75 | + | ||
| 74 | ``(usepnt = no) [boolean]`` | 76 | ``(usepnt = no) [boolean]`` |
| 75 | Use CTA pointing direction for cube centre instead of xref/yref parameters? | 77 | Use CTA pointing direction for cube centre instead of xref/yref parameters? |
| 76 | 78 |
doc/source/users/reference_manual/ctexpcube.rst
| @@ -20,7 +20,7 @@ that has been used in the generation of the counts cube using :doc:`ctbin`. | @@ -20,7 +20,7 @@ that has been used in the generation of the counts cube using :doc:`ctbin`. | ||
| 20 | 20 | ||
| 21 | The binning of an exposure cube does not need to correspond to the binning | 21 | The binning of an exposure cube does not need to correspond to the binning |
| 22 | of a counts cube, as exposure values will in any case be determined by linear | 22 | of a counts cube, as exposure values will in any case be determined by linear |
| 23 | -interpolation. For the user's convenience, howver, the counts cube can be | 23 | +interpolation. For the user's convenience, however, the counts cube can be |
| 24 | specified as ``incube`` parameter which will instruct ctexpcube to extract | 24 | specified as ``incube`` parameter which will instruct ctexpcube to extract |
| 25 | the exposure cube definition (such as sky coordinates and projection, number | 25 | the exposure cube definition (such as sky coordinates and projection, number |
| 26 | of pixels, pixel scale, energy binning) from the counts cube. Note, however, | 26 | of pixels, pixel scale, energy binning) from the counts cube. Note, however, |
| @@ -32,13 +32,16 @@ due to the point spread function and energy dispersion. By computing the | @@ -32,13 +32,16 @@ due to the point spread function and energy dispersion. By computing the | ||
| 32 | exposure cube on the same grid as the counts cube, the spill over of events | 32 | exposure cube on the same grid as the counts cube, the spill over of events |
| 33 | from sources at the edge of cube will not be handled correctly. | 33 | from sources at the edge of cube will not be handled correctly. |
| 34 | 34 | ||
| 35 | +Note that there should at least be 25 bins per energy decade in the exposure | ||
| 36 | +cube to assure that the energy dependence of the exposure is sufficiently | ||
| 37 | +well sampled (in particular at low energies). | ||
| 38 | + | ||
| 35 | ctexpcube generates an exposure cube FITS file comprising three extensions. | 39 | ctexpcube generates an exposure cube FITS file comprising three extensions. |
| 36 | The primary extension contains a 3-dimensional image that contains the | 40 | The primary extension contains a 3-dimensional image that contains the |
| 37 | -exposure values. The next extension named ``EBOUNDS`` contains a binary table | ||
| 38 | -that defines the energy boundaries of the exposure cube. The last extension | ||
| 39 | -named ``GTI`` contains a binary table that provides the Good Time Intervals | ||
| 40 | -of all observations that have been used for the computation of the exposure | ||
| 41 | -cube. | 41 | +exposure values. The next extension named ``ENERGIES`` contains a binary table |
| 42 | +that defines the energies of the exposure cube. The last extension named ``GTI`` | ||
| 43 | +contains a binary table that provides the Good Time Intervals of all | ||
| 44 | +observations that have been used for the computation of the exposure cube. | ||
| 42 | 45 | ||
| 43 | 46 | ||
| 44 | General parameters | 47 | General parameters |
| @@ -73,7 +76,10 @@ General parameters | @@ -73,7 +76,10 @@ General parameters | ||
| 73 | 76 | ||
| 74 | ``ebinfile [file]`` | 77 | ``ebinfile [file]`` |
| 75 | Name of the file containing the energy bin definition. | 78 | Name of the file containing the energy bin definition. |
| 76 | - | 79 | + |
| 80 | +``(addbounds = yes) [boolean]`` | ||
| 81 | + Add energies to the exposure cube at the observation energy boundaries? | ||
| 82 | + | ||
| 77 | ``(usepnt = no) [boolean]`` | 83 | ``(usepnt = no) [boolean]`` |
| 78 | Use CTA pointing direction for cube centre instead of xref/yref parameters? | 84 | Use CTA pointing direction for cube centre instead of xref/yref parameters? |
| 79 | 85 |
doc/source/users/reference_manual/ctpsfcube.rst
| @@ -29,13 +29,11 @@ recommended to use a rather coarse spatial binning to keep the file size | @@ -29,13 +29,11 @@ recommended to use a rather coarse spatial binning to keep the file size | ||
| 29 | manageable (with a typical value of ``binsz=1.0``). | 29 | manageable (with a typical value of ``binsz=1.0``). |
| 30 | 30 | ||
| 31 | ctpsfcube generates a point spread function cube FITS file comprising three | 31 | ctpsfcube generates a point spread function cube FITS file comprising three |
| 32 | -extensions. The primary extension contains a 3-dimensional image that contains | ||
| 33 | -the point spread function values. The energy and offset angle dimensions | ||
| 34 | -of the point spread function cube are folded into the 3rd dimension of the | ||
| 35 | -FITS image. The next extension named ``EBOUNDS`` contains a binary table | ||
| 36 | -that defines the energy boundaries of the exposure cube. The last extension | ||
| 37 | -named ``DELTAS`` contains a binary table that defines the offset angles | ||
| 38 | -between true and measured arrival direction of the photon. | 32 | +extensions. The primary extension contains a 4-dimensional image that contains |
| 33 | +the point spread function values. The next extension named ``ENERGIES`` contains | ||
| 34 | +a binary table that defines the energies of the point spread function cube. | ||
| 35 | +The last extension named ``DELTAS`` contains a binary table that defines the | ||
| 36 | +offset angles between true and measured arrival direction of the photon. | ||
| 39 | 37 | ||
| 40 | 38 | ||
| 41 | General parameters | 39 | General parameters |
| @@ -71,6 +69,9 @@ General parameters | @@ -71,6 +69,9 @@ General parameters | ||
| 71 | ``ebinfile [file]`` | 69 | ``ebinfile [file]`` |
| 72 | Name of the file containing the energy bin definition. | 70 | Name of the file containing the energy bin definition. |
| 73 | 71 | ||
| 72 | +``(addbounds = yes) [boolean]`` | ||
| 73 | + Add energies to the point spread function cube at the observation energy boundaries? | ||
| 74 | + | ||
| 74 | ``(usepnt = no) [boolean]`` | 75 | ``(usepnt = no) [boolean]`` |
| 75 | Use CTA pointing direction for cube centre instead of xref/yref parameters? | 76 | Use CTA pointing direction for cube centre instead of xref/yref parameters? |
| 76 | 77 |
src/ctbkgcube/ctbkgcube.cpp
| @@ -217,23 +217,46 @@ void ctbkgcube::run(void) | @@ -217,23 +217,46 @@ void ctbkgcube::run(void) | ||
| 217 | log << std::endl; | 217 | log << std::endl; |
| 218 | } | 218 | } |
| 219 | 219 | ||
| 220 | + // Warn if there are not enough energy bins | ||
| 221 | + int n = m_background.energies().size(); | ||
| 222 | + double logEmin = std::log10(m_background.energies()[0].TeV()); | ||
| 223 | + double logEmax = std::log10(m_background.energies()[n-1].TeV()); | ||
| 224 | + int nrequired = int((logEmax - logEmin) * 25.0); | ||
| 225 | + if ((n < nrequired) && logTerse()) { | ||
| 226 | + log << std::endl; | ||
| 227 | + log << "WARNING: "; | ||
| 228 | + log << "Only " << n-1 << " energy bins have been requested. This may be " | ||
| 229 | + "too few energy bins."; | ||
| 230 | + log << std::endl << " "; | ||
| 231 | + log << "At least 25 bins per decade in energy are recommended, which " | ||
| 232 | + "in your case"; | ||
| 233 | + log << std::endl << " "; | ||
| 234 | + log << "would be " << nrequired-1 << " bins. Consider increasing the " | ||
| 235 | + "number of energy bins."; | ||
| 236 | + log << std::endl; | ||
| 237 | + } | ||
| 238 | + | ||
| 239 | + // Write header | ||
| 240 | + if (logTerse()) { | ||
| 241 | + log << std::endl; | ||
| 242 | + log.header1("Initialise background cube"); | ||
| 243 | + } | ||
| 244 | + | ||
| 245 | + // Initialise exposure cube | ||
| 246 | + init_cube(); | ||
| 247 | + | ||
| 220 | // Write observation(s) into logger | 248 | // Write observation(s) into logger |
| 221 | if (logTerse()) { | 249 | if (logTerse()) { |
| 222 | log << std::endl; | 250 | log << std::endl; |
| 223 | - if (m_obs.size() > 1) { | ||
| 224 | - log.header1("Observations"); | ||
| 225 | - } | ||
| 226 | - else { | ||
| 227 | - log.header1("Observation"); | ||
| 228 | - } | ||
| 229 | - log << m_obs << std::endl; | 251 | + log.header1(gammalib::number("Observation",m_obs.size())); |
| 252 | + log << m_obs.print(m_chatter) << std::endl; | ||
| 230 | } | 253 | } |
| 231 | 254 | ||
| 232 | // Log input model | 255 | // Log input model |
| 233 | if (logTerse()) { | 256 | if (logTerse()) { |
| 234 | log << std::endl; | 257 | log << std::endl; |
| 235 | log.header1("Input model"); | 258 | log.header1("Input model"); |
| 236 | - log << m_obs.models() << std::endl; | 259 | + log << m_obs.models().print(m_chatter) << std::endl; |
| 237 | } | 260 | } |
| 238 | 261 | ||
| 239 | // Write header | 262 | // Write header |
| @@ -330,6 +353,11 @@ void ctbkgcube::run(void) | @@ -330,6 +353,11 @@ void ctbkgcube::run(void) | ||
| 330 | // Append model to output container | 353 | // Append model to output container |
| 331 | m_outmdl.append(model); | 354 | m_outmdl.append(model); |
| 332 | 355 | ||
| 356 | + // Log background cube | ||
| 357 | + if (logTerse()) { | ||
| 358 | + log << m_background.print(m_chatter) << std::endl; | ||
| 359 | + } | ||
| 360 | + | ||
| 333 | // Log output model | 361 | // Log output model |
| 334 | if (logTerse()) { | 362 | if (logTerse()) { |
| 335 | log << std::endl; | 363 | log << std::endl; |
| @@ -445,10 +473,14 @@ void ctbkgcube::publish(const std::string& name) | @@ -445,10 +473,14 @@ void ctbkgcube::publish(const std::string& name) | ||
| 445 | ***************************************************************************/ | 473 | ***************************************************************************/ |
| 446 | void ctbkgcube::init_members(void) | 474 | void ctbkgcube::init_members(void) |
| 447 | { | 475 | { |
| 448 | - // Initialise members | 476 | + // Initialise user parameters |
| 449 | m_outcube.clear(); | 477 | m_outcube.clear(); |
| 450 | m_outmodel.clear(); | 478 | m_outmodel.clear(); |
| 451 | - m_publish = false; | 479 | + m_addbounds = true; |
| 480 | + m_publish = false; | ||
| 481 | + m_chatter = static_cast<GChatter>(2); | ||
| 482 | + | ||
| 483 | + // Initialise protected members | ||
| 452 | m_obs.clear(); | 484 | m_obs.clear(); |
| 453 | m_background.clear(); | 485 | m_background.clear(); |
| 454 | m_bkgmdl.clear(); | 486 | m_bkgmdl.clear(); |
| @@ -466,10 +498,14 @@ void ctbkgcube::init_members(void) | @@ -466,10 +498,14 @@ void ctbkgcube::init_members(void) | ||
| 466 | ***************************************************************************/ | 498 | ***************************************************************************/ |
| 467 | void ctbkgcube::copy_members(const ctbkgcube& app) | 499 | void ctbkgcube::copy_members(const ctbkgcube& app) |
| 468 | { | 500 | { |
| 469 | - // Copy members | ||
| 470 | - m_outmodel = app.m_outmodel; | ||
| 471 | - m_outcube = app.m_outcube; | ||
| 472 | - m_publish = app.m_publish; | 501 | + // Copy user parameters |
| 502 | + m_outmodel = app.m_outmodel; | ||
| 503 | + m_outcube = app.m_outcube; | ||
| 504 | + m_addbounds = app.m_addbounds; | ||
| 505 | + m_publish = app.m_publish; | ||
| 506 | + m_chatter = app.m_chatter; | ||
| 507 | + | ||
| 508 | + // Copy protected members | ||
| 473 | m_obs = app.m_obs; | 509 | m_obs = app.m_obs; |
| 474 | m_background = app.m_background; | 510 | m_background = app.m_background; |
| 475 | m_bkgmdl = app.m_bkgmdl; | 511 | m_bkgmdl = app.m_bkgmdl; |
| @@ -558,7 +594,9 @@ void ctbkgcube::get_parameters(void) | @@ -558,7 +594,9 @@ void ctbkgcube::get_parameters(void) | ||
| 558 | } | 594 | } |
| 559 | 595 | ||
| 560 | // Get remaining parameters | 596 | // Get remaining parameters |
| 561 | - m_publish = (*this)["publish"].boolean(); | 597 | + m_addbounds = (*this)["addbounds"].boolean(); |
| 598 | + m_publish = (*this)["publish"].boolean(); | ||
| 599 | + m_chatter = static_cast<GChatter>((*this)["chatter"].integer()); | ||
| 562 | 600 | ||
| 563 | // Read output filenames (if needed) | 601 | // Read output filenames (if needed) |
| 564 | if (read_ahead()) { | 602 | if (read_ahead()) { |
| @@ -569,3 +607,70 @@ void ctbkgcube::get_parameters(void) | @@ -569,3 +607,70 @@ void ctbkgcube::get_parameters(void) | ||
| 569 | // Return | 607 | // Return |
| 570 | return; | 608 | return; |
| 571 | } | 609 | } |
| 610 | + | ||
| 611 | + | ||
| 612 | +/***********************************************************************//** | ||
| 613 | + * @brief Initialise background cube | ||
| 614 | + * | ||
| 615 | + * Initialise the background cube. | ||
| 616 | + ***************************************************************************/ | ||
| 617 | +void ctbkgcube::init_cube(void) | ||
| 618 | +{ | ||
| 619 | + // Extract exposure cube definition | ||
| 620 | + const GWcs* proj = static_cast<const GWcs*>(m_background.cube().projection()); | ||
| 621 | + std::string wcs = m_background.cube().projection()->code(); | ||
| 622 | + std::string coords = m_background.cube().projection()->coordsys(); | ||
| 623 | + double x = proj->crval(0); | ||
| 624 | + double y = proj->crval(1); | ||
| 625 | + double dx = proj->cdelt(0); | ||
| 626 | + double dy = proj->cdelt(1); | ||
| 627 | + int nx = m_background.cube().nx(); | ||
| 628 | + int ny = m_background.cube().ny(); | ||
| 629 | + | ||
| 630 | + // Extract energies | ||
| 631 | + GEnergies energies = m_background.energies(); | ||
| 632 | + | ||
| 633 | + // If requested, insert energies at all event list energy boundaries | ||
| 634 | + if (m_addbounds) { | ||
| 635 | + | ||
| 636 | + // Set logger | ||
| 637 | + GLog* logger = NULL; | ||
| 638 | + if (logTerse()) { | ||
| 639 | + logger = &log; | ||
| 640 | + } | ||
| 641 | + | ||
| 642 | + // Loop over all observations | ||
| 643 | + for (int i = 0; i < m_obs.size(); ++i) { | ||
| 644 | + | ||
| 645 | + // Get observation and continue only if it is a CTA observation | ||
| 646 | + const GCTAObservation* cta = dynamic_cast<const GCTAObservation*> | ||
| 647 | + (m_obs[i]); | ||
| 648 | + | ||
| 649 | + // Skip observation if it's not a CTA observation | ||
| 650 | + if (cta == NULL) { | ||
| 651 | + continue; | ||
| 652 | + } | ||
| 653 | + | ||
| 654 | + // Skip observation if it does not contain an event list | ||
| 655 | + if (cta->eventtype() != "EventList") { | ||
| 656 | + continue; | ||
| 657 | + } | ||
| 658 | + | ||
| 659 | + // Insert energy boundaries | ||
| 660 | + energies = insert_energy_boundaries(energies, *cta, logger); | ||
| 661 | + | ||
| 662 | + } // endfor: looped over all observations | ||
| 663 | + | ||
| 664 | + } // endif: energy bin insertion requested | ||
| 665 | + | ||
| 666 | + // Setup background cube | ||
| 667 | + m_background = GCTACubeBackground(wcs, coords, x, y, dx, dy, nx, ny, energies); | ||
| 668 | + | ||
| 669 | + // Log background cube | ||
| 670 | + if (logTerse()) { | ||
| 671 | + log << m_background.print(m_chatter) << std::endl; | ||
| 672 | + } | ||
| 673 | + | ||
| 674 | + // Return | ||
| 675 | + return; | ||
| 676 | +}; |
src/ctbkgcube/ctbkgcube.hpp
| @@ -69,12 +69,15 @@ protected: | @@ -69,12 +69,15 @@ protected: | ||
| 69 | void copy_members(const ctbkgcube& app); | 69 | void copy_members(const ctbkgcube& app); |
| 70 | void free_members(void); | 70 | void free_members(void); |
| 71 | void get_parameters(void); | 71 | void get_parameters(void); |
| 72 | - void fill_cube(GCTAObservation* obs); | 72 | + void init_cube(void); |
| 73 | + //void fill_cube(GCTAObservation* obs); | ||
| 73 | 74 | ||
| 74 | // User parameters | 75 | // User parameters |
| 75 | GFilename m_outcube; //!< Filename of output cube | 76 | GFilename m_outcube; //!< Filename of output cube |
| 76 | GFilename m_outmodel; //!< Filename of output XML model | 77 | GFilename m_outmodel; //!< Filename of output XML model |
| 78 | + bool m_addbounds; //!< Add energies at boundaries? | ||
| 77 | bool m_publish; //!< Publish background cube? | 79 | bool m_publish; //!< Publish background cube? |
| 80 | + GChatter m_chatter; //!< Chattiness | ||
| 78 | 81 | ||
| 79 | // Protected members | 82 | // Protected members |
| 80 | GObservations m_obs; //!< Observation container | 83 | GObservations m_obs; //!< Observation container |
src/ctbkgcube/ctbkgcube.par
| @@ -28,11 +28,12 @@ outmodel, f, a, "NONE",,, "Output model XML file" | @@ -28,11 +28,12 @@ outmodel, f, a, "NONE",,, "Output model XML file" | ||
| 28 | # | 28 | # |
| 29 | # Energy binning parameters | 29 | # Energy binning parameters |
| 30 | #========================== | 30 | #========================== |
| 31 | -ebinalg, s, h, "LOG",FILE|LIN|LOG,, "Algorithm for defining energy bins" | ||
| 32 | -emin, r, a, 0.1,,, "Lower energy limit (TeV)" | ||
| 33 | -emax, r, a, 100.0,,, "Upper energy limit (TeV)" | ||
| 34 | -enumbins, i, a, 20,,, "Number of energy bins" | ||
| 35 | -ebinfile, f, h, "NONE",,, "Name of the file containing the energy bin definition" | 31 | +ebinalg, s, h, "LOG",FILE|LIN|LOG,, "Algorithm for defining energy bins" |
| 32 | +emin, r, a, 0.1,,, "Lower energy limit (TeV)" | ||
| 33 | +emax, r, a, 100.0,,, "Upper energy limit (TeV)" | ||
| 34 | +enumbins, i, a, 20,,, "Number of energy bins" | ||
| 35 | +ebinfile, f, h, "NONE",,, "Name of the file containing the energy bin definition" | ||
| 36 | +addbounds, b, h, yes,,, "Add energies at observation energy boundaries?" | ||
| 36 | 37 | ||
| 37 | # | 38 | # |
| 38 | # Spatial binning parameters | 39 | # Spatial binning parameters |
src/ctedispcube/ctedispcube.cpp
| @@ -229,16 +229,20 @@ void ctedispcube::run(void) | @@ -229,16 +229,20 @@ void ctedispcube::run(void) | ||
| 229 | log << std::endl; | 229 | log << std::endl; |
| 230 | } | 230 | } |
| 231 | 231 | ||
| 232 | + // Write header | ||
| 233 | + if (logTerse()) { | ||
| 234 | + log << std::endl; | ||
| 235 | + log.header1("Initialise energy dispersion cube"); | ||
| 236 | + } | ||
| 237 | + | ||
| 238 | + // Initialise energy dispersion cube | ||
| 239 | + init_cube(); | ||
| 240 | + | ||
| 232 | // Write observation(s) into logger | 241 | // Write observation(s) into logger |
| 233 | if (logTerse()) { | 242 | if (logTerse()) { |
| 234 | log << std::endl; | 243 | log << std::endl; |
| 235 | - if (m_obs.size() > 1) { | ||
| 236 | - log.header1("Observations"); | ||
| 237 | - } | ||
| 238 | - else { | ||
| 239 | - log.header1("Observation"); | ||
| 240 | - } | ||
| 241 | - log << m_obs << std::endl; | 244 | + log.header1(gammalib::number("Observation",m_obs.size())); |
| 245 | + log << m_obs.print(m_chatter) << std::endl; | ||
| 242 | } | 246 | } |
| 243 | 247 | ||
| 244 | // Write header | 248 | // Write header |
| @@ -247,9 +251,14 @@ void ctedispcube::run(void) | @@ -247,9 +251,14 @@ void ctedispcube::run(void) | ||
| 247 | log.header1("Generate energy dispersion cube"); | 251 | log.header1("Generate energy dispersion cube"); |
| 248 | } | 252 | } |
| 249 | 253 | ||
| 250 | - // Fill Edisp | 254 | + // Fill energy dispersion cube |
| 251 | m_edispcube.fill(m_obs, &log); | 255 | m_edispcube.fill(m_obs, &log); |
| 252 | 256 | ||
| 257 | + // Log energy dispersion cube | ||
| 258 | + if (logTerse()) { | ||
| 259 | + log << m_edispcube.print(m_chatter) << std::endl; | ||
| 260 | + } | ||
| 261 | + | ||
| 253 | // Return | 262 | // Return |
| 254 | return; | 263 | return; |
| 255 | } | 264 | } |
| @@ -302,8 +311,12 @@ void ctedispcube::save(void) | @@ -302,8 +311,12 @@ void ctedispcube::save(void) | ||
| 302 | ***************************************************************************/ | 311 | ***************************************************************************/ |
| 303 | void ctedispcube::init_members(void) | 312 | void ctedispcube::init_members(void) |
| 304 | { | 313 | { |
| 305 | - // Initialise members | 314 | + // Initialise user parameters |
| 306 | m_outcube.clear(); | 315 | m_outcube.clear(); |
| 316 | + m_addbounds = true; | ||
| 317 | + m_chatter = static_cast<GChatter>(2); | ||
| 318 | + | ||
| 319 | + // Initialise protected members | ||
| 307 | m_obs.clear(); | 320 | m_obs.clear(); |
| 308 | m_edispcube.clear(); | 321 | m_edispcube.clear(); |
| 309 | 322 | ||
| @@ -319,8 +332,12 @@ void ctedispcube::init_members(void) | @@ -319,8 +332,12 @@ void ctedispcube::init_members(void) | ||
| 319 | ***************************************************************************/ | 332 | ***************************************************************************/ |
| 320 | void ctedispcube::copy_members(const ctedispcube& app) | 333 | void ctedispcube::copy_members(const ctedispcube& app) |
| 321 | { | 334 | { |
| 322 | - // Copy members | 335 | + // Copy user parameters |
| 323 | m_outcube = app.m_outcube; | 336 | m_outcube = app.m_outcube; |
| 337 | + m_addbounds = app.m_addbounds; | ||
| 338 | + m_chatter = app.m_chatter; | ||
| 339 | + | ||
| 340 | + // Copy protected members | ||
| 324 | m_obs = app.m_obs; | 341 | m_obs = app.m_obs; |
| 325 | m_edispcube = app.m_edispcube; | 342 | m_edispcube = app.m_edispcube; |
| 326 | 343 | ||
| @@ -380,7 +397,7 @@ void ctedispcube::get_parameters(void) | @@ -380,7 +397,7 @@ void ctedispcube::get_parameters(void) | ||
| 380 | 397 | ||
| 381 | } | 398 | } |
| 382 | 399 | ||
| 383 | - // ... otherwise setup the exposure cube from the counts map | 400 | + // ... otherwise setup the energy disperison cube from the counts map |
| 384 | else { | 401 | else { |
| 385 | 402 | ||
| 386 | // Load event cube from filename | 403 | // Load event cube from filename |
| @@ -391,6 +408,10 @@ void ctedispcube::get_parameters(void) | @@ -391,6 +408,10 @@ void ctedispcube::get_parameters(void) | ||
| 391 | 408 | ||
| 392 | } // endelse: cube loaded from file | 409 | } // endelse: cube loaded from file |
| 393 | 410 | ||
| 411 | + // Get remaining parameters | ||
| 412 | + m_addbounds = (*this)["addbounds"].boolean(); | ||
| 413 | + m_chatter = static_cast<GChatter>((*this)["chatter"].integer()); | ||
| 414 | + | ||
| 394 | // Read output filename (if needed) | 415 | // Read output filename (if needed) |
| 395 | if (read_ahead()) { | 416 | if (read_ahead()) { |
| 396 | m_outcube = (*this)["outcube"].filename(); | 417 | m_outcube = (*this)["outcube"].filename(); |
| @@ -399,3 +420,73 @@ void ctedispcube::get_parameters(void) | @@ -399,3 +420,73 @@ void ctedispcube::get_parameters(void) | ||
| 399 | // Return | 420 | // Return |
| 400 | return; | 421 | return; |
| 401 | } | 422 | } |
| 423 | + | ||
| 424 | + | ||
| 425 | +/***********************************************************************//** | ||
| 426 | + * @brief Initialise energy dispersion cube | ||
| 427 | + * | ||
| 428 | + * Initialise the energy dispersion cube. | ||
| 429 | + ***************************************************************************/ | ||
| 430 | +void ctedispcube::init_cube(void) | ||
| 431 | +{ | ||
| 432 | + // Extract energy dispersion definition | ||
| 433 | + const GWcs* proj = static_cast<const GWcs*>(m_edispcube.cube().projection()); | ||
| 434 | + std::string wcs = m_edispcube.cube().projection()->code(); | ||
| 435 | + std::string coords = m_edispcube.cube().projection()->coordsys(); | ||
| 436 | + double x = proj->crval(0); | ||
| 437 | + double y = proj->crval(1); | ||
| 438 | + double dx = proj->cdelt(0); | ||
| 439 | + double dy = proj->cdelt(1); | ||
| 440 | + int nx = m_edispcube.cube().nx(); | ||
| 441 | + int ny = m_edispcube.cube().ny(); | ||
| 442 | + double mmax = (*this)["migramax"].real(); | ||
| 443 | + int nmbins = (*this)["migrabins"].integer(); | ||
| 444 | + | ||
| 445 | + // Extract energies | ||
| 446 | + GEnergies energies = m_edispcube.energies(); | ||
| 447 | + | ||
| 448 | + // If requested, insert energies at all event list energy boundaries | ||
| 449 | + if (m_addbounds) { | ||
| 450 | + | ||
| 451 | + // Set logger | ||
| 452 | + GLog* logger = NULL; | ||
| 453 | + if (logTerse()) { | ||
| 454 | + logger = &log; | ||
| 455 | + } | ||
| 456 | + | ||
| 457 | + // Loop over all observations | ||
| 458 | + for (int i = 0; i < m_obs.size(); ++i) { | ||
| 459 | + | ||
| 460 | + // Get observation and continue only if it is a CTA observation | ||
| 461 | + const GCTAObservation* cta = dynamic_cast<const GCTAObservation*> | ||
| 462 | + (m_obs[i]); | ||
| 463 | + | ||
| 464 | + // Skip observation if it's not a CTA observation | ||
| 465 | + if (cta == NULL) { | ||
| 466 | + continue; | ||
| 467 | + } | ||
| 468 | + | ||
| 469 | + // Skip observation if it does not contain an event list | ||
| 470 | + if (cta->eventtype() != "EventList") { | ||
| 471 | + continue; | ||
| 472 | + } | ||
| 473 | + | ||
| 474 | + // Insert energy boundaries | ||
| 475 | + energies = insert_energy_boundaries(energies, *cta, logger); | ||
| 476 | + | ||
| 477 | + } // endfor: looped over all observations | ||
| 478 | + | ||
| 479 | + } // endif: energy bin insertion requested | ||
| 480 | + | ||
| 481 | + // Setup energy dispersion cube | ||
| 482 | + m_edispcube = GCTACubeEdisp(wcs, coords, x, y, dx, dy, nx, ny, energies, | ||
| 483 | + mmax, nmbins); | ||
| 484 | + | ||
| 485 | + // Log energy dispersion cube | ||
| 486 | + if (logTerse()) { | ||
| 487 | + log << m_edispcube.print(m_chatter) << std::endl; | ||
| 488 | + } | ||
| 489 | + | ||
| 490 | + // Return | ||
| 491 | + return; | ||
| 492 | +}; |
src/ctedispcube/ctedispcube.hpp
| @@ -67,9 +67,12 @@ protected: | @@ -67,9 +67,12 @@ protected: | ||
| 67 | void copy_members(const ctedispcube& app); | 67 | void copy_members(const ctedispcube& app); |
| 68 | void free_members(void); | 68 | void free_members(void); |
| 69 | void get_parameters(void); | 69 | void get_parameters(void); |
| 70 | + void init_cube(void); | ||
| 70 | 71 | ||
| 71 | // User parameters | 72 | // User parameters |
| 72 | - GFilename m_outcube; //!< Output energy dispersion cube file name | 73 | + GFilename m_outcube; //!< Output exposure cube file |
| 74 | + bool m_addbounds; //!< Add energies at boundaries? | ||
| 75 | + GChatter m_chatter; //!< Chattiness | ||
| 73 | 76 | ||
| 74 | // Protected members | 77 | // Protected members |
| 75 | GObservations m_obs; //!< Observation container | 78 | GObservations m_obs; //!< Observation container |
src/ctedispcube/ctedispcube.par
| @@ -26,11 +26,12 @@ outcube, f, a, "edispcube.fits",,, "Output energy dispersion cube file" | @@ -26,11 +26,12 @@ outcube, f, a, "edispcube.fits",,, "Output energy dispersion cube file" | ||
| 26 | # | 26 | # |
| 27 | # Energy binning parameters | 27 | # Energy binning parameters |
| 28 | #========================== | 28 | #========================== |
| 29 | -ebinalg, s, h, "LOG", FILE|LIN|LOG,, "Algorithm for defining energy bins" | ||
| 30 | -emin, r, a, 0.1,,, "Lower energy limit (TeV)" | ||
| 31 | -emax, r, a, 100.0,,, "Upper energy limit (TeV)" | ||
| 32 | -enumbins, i, a, 20,,, "Number of energy bins" | ||
| 33 | -ebinfile, f, h, "NONE",,, "Name of the file containing the energy bin definition" | 29 | +ebinalg, s, h, "LOG", FILE|LIN|LOG,, "Algorithm for defining energy bins" |
| 30 | +emin, r, a, 0.1,,, "Lower energy limit (TeV)" | ||
| 31 | +emax, r, a, 100.0,,, "Upper energy limit (TeV)" | ||
| 32 | +enumbins, i, a, 20,,, "Number of energy bins" | ||
| 33 | +ebinfile, f, h, "NONE",,, "Name of the file containing the energy bin definition" | ||
| 34 | +addbounds, b, h, yes,,, "Add energies at observation energy boundaries?" | ||
| 34 | 35 | ||
| 35 | # | 36 | # |
| 36 | # Spatial binning parameters | 37 | # Spatial binning parameters |
src/ctexpcube/ctexpcube.cpp
| @@ -217,11 +217,39 @@ void ctexpcube::run(void) | @@ -217,11 +217,39 @@ void ctexpcube::run(void) | ||
| 217 | log << std::endl; | 217 | log << std::endl; |
| 218 | } | 218 | } |
| 219 | 219 | ||
| 220 | + // Warn if there are not enough energy bins | ||
| 221 | + int n = m_expcube.energies().size(); | ||
| 222 | + double logEmin = std::log10(m_expcube.energies()[0].TeV()); | ||
| 223 | + double logEmax = std::log10(m_expcube.energies()[n-1].TeV()); | ||
| 224 | + int nrequired = int((logEmax - logEmin) * 25.0); | ||
| 225 | + if ((n < nrequired) && logTerse()) { | ||
| 226 | + log << std::endl; | ||
| 227 | + log << "WARNING: "; | ||
| 228 | + log << "Only " << n-1 << " energy bins have been requested. This may be " | ||
| 229 | + "too few energy bins."; | ||
| 230 | + log << std::endl << " "; | ||
| 231 | + log << "At least 25 bins per decade in energy are recommended, which " | ||
| 232 | + "in your case"; | ||
| 233 | + log << std::endl << " "; | ||
| 234 | + log << "would be " << nrequired-1 << " bins. Consider increasing the " | ||
| 235 | + "number of energy bins."; | ||
| 236 | + log << std::endl; | ||
| 237 | + } | ||
| 238 | + | ||
| 239 | + // Write header | ||
| 240 | + if (logTerse()) { | ||
| 241 | + log << std::endl; | ||
| 242 | + log.header1("Initialise exposure cube"); | ||
| 243 | + } | ||
| 244 | + | ||
| 245 | + // Initialise exposure cube | ||
| 246 | + init_cube(); | ||
| 247 | + | ||
| 220 | // Write observation(s) into logger | 248 | // Write observation(s) into logger |
| 221 | if (logTerse()) { | 249 | if (logTerse()) { |
| 222 | log << std::endl; | 250 | log << std::endl; |
| 223 | log.header1(gammalib::number("Observation",m_obs.size())); | 251 | log.header1(gammalib::number("Observation",m_obs.size())); |
| 224 | - log << m_obs << std::endl; | 252 | + log << m_obs.print(m_chatter) << std::endl; |
| 225 | } | 253 | } |
| 226 | 254 | ||
| 227 | // Write header | 255 | // Write header |
| @@ -230,9 +258,14 @@ void ctexpcube::run(void) | @@ -230,9 +258,14 @@ void ctexpcube::run(void) | ||
| 230 | log.header1("Generate exposure cube"); | 258 | log.header1("Generate exposure cube"); |
| 231 | } | 259 | } |
| 232 | 260 | ||
| 233 | - // Fill exposure | 261 | + // Fill exposure cube |
| 234 | m_expcube.fill(m_obs, &log); | 262 | m_expcube.fill(m_obs, &log); |
| 235 | 263 | ||
| 264 | + // Log exposure cube | ||
| 265 | + if (logTerse()) { | ||
| 266 | + log << m_expcube.print(m_chatter) << std::endl; | ||
| 267 | + } | ||
| 268 | + | ||
| 236 | // Optionally publish exposure cube | 269 | // Optionally publish exposure cube |
| 237 | if (m_publish) { | 270 | if (m_publish) { |
| 238 | publish(); | 271 | publish(); |
| @@ -321,9 +354,11 @@ void ctexpcube::publish(const std::string& name) | @@ -321,9 +354,11 @@ void ctexpcube::publish(const std::string& name) | ||
| 321 | ***************************************************************************/ | 354 | ***************************************************************************/ |
| 322 | void ctexpcube::init_members(void) | 355 | void ctexpcube::init_members(void) |
| 323 | { | 356 | { |
| 324 | - // Initialise members | 357 | + // Initialise user parameters |
| 325 | m_outcube.clear(); | 358 | m_outcube.clear(); |
| 326 | - m_publish = false; | 359 | + m_addbounds = true; |
| 360 | + m_publish = false; | ||
| 361 | + m_chatter = static_cast<GChatter>(2); | ||
| 327 | 362 | ||
| 328 | // Initialise protected members | 363 | // Initialise protected members |
| 329 | m_obs.clear(); | 364 | m_obs.clear(); |
| @@ -341,9 +376,11 @@ void ctexpcube::init_members(void) | @@ -341,9 +376,11 @@ void ctexpcube::init_members(void) | ||
| 341 | ***************************************************************************/ | 376 | ***************************************************************************/ |
| 342 | void ctexpcube::copy_members(const ctexpcube& app) | 377 | void ctexpcube::copy_members(const ctexpcube& app) |
| 343 | { | 378 | { |
| 344 | - // Copy attributes | ||
| 345 | - m_outcube = app.m_outcube; | ||
| 346 | - m_publish = app.m_publish; | 379 | + // Copy user parameters |
| 380 | + m_outcube = app.m_outcube; | ||
| 381 | + m_addbounds = app.m_addbounds; | ||
| 382 | + m_publish = app.m_publish; | ||
| 383 | + m_chatter = app.m_chatter; | ||
| 347 | 384 | ||
| 348 | // Copy protected members | 385 | // Copy protected members |
| 349 | m_obs = app.m_obs; | 386 | m_obs = app.m_obs; |
| @@ -413,7 +450,9 @@ void ctexpcube::get_parameters(void) | @@ -413,7 +450,9 @@ void ctexpcube::get_parameters(void) | ||
| 413 | } // endelse: cube loaded from file | 450 | } // endelse: cube loaded from file |
| 414 | 451 | ||
| 415 | // Get remaining parameters | 452 | // Get remaining parameters |
| 416 | - m_publish = (*this)["publish"].boolean(); | 453 | + m_addbounds = (*this)["addbounds"].boolean(); |
| 454 | + m_publish = (*this)["publish"].boolean(); | ||
| 455 | + m_chatter = static_cast<GChatter>((*this)["chatter"].integer()); | ||
| 417 | 456 | ||
| 418 | // Read output filename (if needed) | 457 | // Read output filename (if needed) |
| 419 | if (read_ahead()) { | 458 | if (read_ahead()) { |
| @@ -423,3 +462,70 @@ void ctexpcube::get_parameters(void) | @@ -423,3 +462,70 @@ void ctexpcube::get_parameters(void) | ||
| 423 | // Return | 462 | // Return |
| 424 | return; | 463 | return; |
| 425 | } | 464 | } |
| 465 | + | ||
| 466 | + | ||
| 467 | +/***********************************************************************//** | ||
| 468 | + * @brief Initialise exposure cube | ||
| 469 | + * | ||
| 470 | + * Initialise the exposure cube. | ||
| 471 | + ***************************************************************************/ | ||
| 472 | +void ctexpcube::init_cube(void) | ||
| 473 | +{ | ||
| 474 | + // Extract exposure cube definition | ||
| 475 | + const GWcs* proj = static_cast<const GWcs*>(m_expcube.cube().projection()); | ||
| 476 | + std::string wcs = m_expcube.cube().projection()->code(); | ||
| 477 | + std::string coords = m_expcube.cube().projection()->coordsys(); | ||
| 478 | + double x = proj->crval(0); | ||
| 479 | + double y = proj->crval(1); | ||
| 480 | + double dx = proj->cdelt(0); | ||
| 481 | + double dy = proj->cdelt(1); | ||
| 482 | + int nx = m_expcube.cube().nx(); | ||
| 483 | + int ny = m_expcube.cube().ny(); | ||
| 484 | + | ||
| 485 | + // Extract energies | ||
| 486 | + GEnergies energies = m_expcube.energies(); | ||
| 487 | + | ||
| 488 | + // If requested, insert energies at all event list energy boundaries | ||
| 489 | + if (m_addbounds) { | ||
| 490 | + | ||
| 491 | + // Set logger | ||
| 492 | + GLog* logger = NULL; | ||
| 493 | + if (logTerse()) { | ||
| 494 | + logger = &log; | ||
| 495 | + } | ||
| 496 | + | ||
| 497 | + // Loop over all observations | ||
| 498 | + for (int i = 0; i < m_obs.size(); ++i) { | ||
| 499 | + | ||
| 500 | + // Get observation and continue only if it is a CTA observation | ||
| 501 | + const GCTAObservation* cta = dynamic_cast<const GCTAObservation*> | ||
| 502 | + (m_obs[i]); | ||
| 503 | + | ||
| 504 | + // Skip observation if it's not a CTA observation | ||
| 505 | + if (cta == NULL) { | ||
| 506 | + continue; | ||
| 507 | + } | ||
| 508 | + | ||
| 509 | + // Skip observation if it does not contain an event list | ||
| 510 | + if (cta->eventtype() != "EventList") { | ||
| 511 | + continue; | ||
| 512 | + } | ||
| 513 | + | ||
| 514 | + // Insert energy boundaries | ||
| 515 | + energies = insert_energy_boundaries(energies, *cta, logger); | ||
| 516 | + | ||
| 517 | + } // endfor: looped over all observations | ||
| 518 | + | ||
| 519 | + } // endif: energy bin insertion requested | ||
| 520 | + | ||
| 521 | + // Setup exposure cube | ||
| 522 | + m_expcube = GCTACubeExposure(wcs, coords, x, y, dx, dy, nx, ny, energies); | ||
| 523 | + | ||
| 524 | + // Log exposure cube | ||
| 525 | + if (logTerse()) { | ||
| 526 | + log << m_expcube.print(m_chatter) << std::endl; | ||
| 527 | + } | ||
| 528 | + | ||
| 529 | + // Return | ||
| 530 | + return; | ||
| 531 | +}; |
src/ctexpcube/ctexpcube.hpp
| @@ -68,10 +68,13 @@ protected: | @@ -68,10 +68,13 @@ protected: | ||
| 68 | void copy_members(const ctexpcube& app); | 68 | void copy_members(const ctexpcube& app); |
| 69 | void free_members(void); | 69 | void free_members(void); |
| 70 | void get_parameters(void); | 70 | void get_parameters(void); |
| 71 | + void init_cube(void); | ||
| 71 | 72 | ||
| 72 | // User parameters | 73 | // User parameters |
| 73 | - GFilename m_outcube; //!< Output exposure cube file | ||
| 74 | - bool m_publish; //!< Publish exposure cube? | 74 | + GFilename m_outcube; //!< Output exposure cube file |
| 75 | + bool m_addbounds; //!< Add energies at boundaries? | ||
| 76 | + bool m_publish; //!< Publish exposure cube? | ||
| 77 | + GChatter m_chatter; //!< Chattiness | ||
| 75 | 78 | ||
| 76 | // Protected members | 79 | // Protected members |
| 77 | GObservations m_obs; //!< Observation container | 80 | GObservations m_obs; //!< Observation container |
src/ctexpcube/ctexpcube.par
| @@ -26,11 +26,12 @@ outcube, f, a, "expcube.fits",,, "Output exposure cube file" | @@ -26,11 +26,12 @@ outcube, f, a, "expcube.fits",,, "Output exposure cube file" | ||
| 26 | # | 26 | # |
| 27 | # Energy binning parameters | 27 | # Energy binning parameters |
| 28 | #========================== | 28 | #========================== |
| 29 | -ebinalg, s, h, "LOG", FILE|LIN|LOG,,"Algorithm for defining energy bins" | ||
| 30 | -emin, r, a, 0.1,,,"Lower energy limit (TeV)" | ||
| 31 | -emax, r, a, 100.0,,, "Upper energy limit (TeV)" | ||
| 32 | -enumbins, i, a, 20,,, "Number of energy bins" | ||
| 33 | -ebinfile, f, h, "NONE",,, "Name of the file containing the energy bin definition" | 29 | +ebinalg, s, h, "LOG", FILE|LIN|LOG,,"Algorithm for defining energy bins" |
| 30 | +emin, r, a, 0.1,,,"Lower energy limit (TeV)" | ||
| 31 | +emax, r, a, 100.0,,, "Upper energy limit (TeV)" | ||
| 32 | +enumbins, i, a, 20,,, "Number of energy bins" | ||
| 33 | +ebinfile, f, h, "NONE",,, "Name of the file containing the energy bin definition" | ||
| 34 | +addbounds, b, h, yes,,, "Add energies at observation energy boundaries?" | ||
| 34 | 35 | ||
| 35 | # | 36 | # |
| 36 | # Spatial binning parameters | 37 | # Spatial binning parameters |
src/ctpsfcube/ctpsfcube.cpp
| @@ -216,16 +216,20 @@ void ctpsfcube::run(void) | @@ -216,16 +216,20 @@ void ctpsfcube::run(void) | ||
| 216 | log << std::endl; | 216 | log << std::endl; |
| 217 | } | 217 | } |
| 218 | 218 | ||
| 219 | + // Write header | ||
| 220 | + if (logTerse()) { | ||
| 221 | + log << std::endl; | ||
| 222 | + log.header1("Initialise PSF cube"); | ||
| 223 | + } | ||
| 224 | + | ||
| 225 | + // Initialise exposure cube | ||
| 226 | + init_cube(); | ||
| 227 | + | ||
| 219 | // Write observation(s) into logger | 228 | // Write observation(s) into logger |
| 220 | if (logTerse()) { | 229 | if (logTerse()) { |
| 221 | log << std::endl; | 230 | log << std::endl; |
| 222 | - if (m_obs.size() > 1) { | ||
| 223 | - log.header1("Observations"); | ||
| 224 | - } | ||
| 225 | - else { | ||
| 226 | - log.header1("Observation"); | ||
| 227 | - } | ||
| 228 | - log << m_obs << std::endl; | 231 | + log.header1(gammalib::number("Observation",m_obs.size())); |
| 232 | + log << m_obs.print(m_chatter) << std::endl; | ||
| 229 | } | 233 | } |
| 230 | 234 | ||
| 231 | // Write header | 235 | // Write header |
| @@ -234,9 +238,14 @@ void ctpsfcube::run(void) | @@ -234,9 +238,14 @@ void ctpsfcube::run(void) | ||
| 234 | log.header1("Generate PSF cube"); | 238 | log.header1("Generate PSF cube"); |
| 235 | } | 239 | } |
| 236 | 240 | ||
| 237 | - // Fill PSF | 241 | + // Fill PSF cube |
| 238 | m_psfcube.fill(m_obs, &log); | 242 | m_psfcube.fill(m_obs, &log); |
| 239 | 243 | ||
| 244 | + // Log PSF cube | ||
| 245 | + if (logTerse()) { | ||
| 246 | + log << m_psfcube.print(m_chatter) << std::endl; | ||
| 247 | + } | ||
| 248 | + | ||
| 240 | // Return | 249 | // Return |
| 241 | return; | 250 | return; |
| 242 | } | 251 | } |
| @@ -286,8 +295,10 @@ void ctpsfcube::save(void) | @@ -286,8 +295,10 @@ void ctpsfcube::save(void) | ||
| 286 | ***************************************************************************/ | 295 | ***************************************************************************/ |
| 287 | void ctpsfcube::init_members(void) | 296 | void ctpsfcube::init_members(void) |
| 288 | { | 297 | { |
| 289 | - // Initialise members | 298 | + // Initialise user parameters |
| 290 | m_outcube.clear(); | 299 | m_outcube.clear(); |
| 300 | + m_addbounds = true; | ||
| 301 | + m_chatter = static_cast<GChatter>(2); | ||
| 291 | 302 | ||
| 292 | // Initialise protected members | 303 | // Initialise protected members |
| 293 | m_obs.clear(); | 304 | m_obs.clear(); |
| @@ -305,12 +316,14 @@ void ctpsfcube::init_members(void) | @@ -305,12 +316,14 @@ void ctpsfcube::init_members(void) | ||
| 305 | ***************************************************************************/ | 316 | ***************************************************************************/ |
| 306 | void ctpsfcube::copy_members(const ctpsfcube& app) | 317 | void ctpsfcube::copy_members(const ctpsfcube& app) |
| 307 | { | 318 | { |
| 308 | - // Copy attributes | ||
| 309 | - m_outcube = app.m_outcube; | 319 | + // Copy user parameters |
| 320 | + m_outcube = app.m_outcube; | ||
| 321 | + m_addbounds = app.m_addbounds; | ||
| 322 | + m_chatter = app.m_chatter; | ||
| 310 | 323 | ||
| 311 | // Copy protected members | 324 | // Copy protected members |
| 312 | - m_obs = app.m_obs; | ||
| 313 | - m_psfcube = app.m_psfcube; | 325 | + m_obs = app.m_obs; |
| 326 | + m_psfcube = app.m_psfcube; | ||
| 314 | 327 | ||
| 315 | // Return | 328 | // Return |
| 316 | return; | 329 | return; |
| @@ -379,6 +392,10 @@ void ctpsfcube::get_parameters(void) | @@ -379,6 +392,10 @@ void ctpsfcube::get_parameters(void) | ||
| 379 | 392 | ||
| 380 | } // endelse: cube loaded from file | 393 | } // endelse: cube loaded from file |
| 381 | 394 | ||
| 395 | + // Get remaining parameters | ||
| 396 | + m_addbounds = (*this)["addbounds"].boolean(); | ||
| 397 | + m_chatter = static_cast<GChatter>((*this)["chatter"].integer()); | ||
| 398 | + | ||
| 382 | // Read output filename (if needed) | 399 | // Read output filename (if needed) |
| 383 | if (read_ahead()) { | 400 | if (read_ahead()) { |
| 384 | m_outcube = (*this)["outcube"].filename(); | 401 | m_outcube = (*this)["outcube"].filename(); |
| @@ -387,3 +404,73 @@ void ctpsfcube::get_parameters(void) | @@ -387,3 +404,73 @@ void ctpsfcube::get_parameters(void) | ||
| 387 | // Return | 404 | // Return |
| 388 | return; | 405 | return; |
| 389 | } | 406 | } |
| 407 | + | ||
| 408 | + | ||
| 409 | +/***********************************************************************//** | ||
| 410 | + * @brief Initialise PSF cube | ||
| 411 | + * | ||
| 412 | + * Initialise the PSF cube. | ||
| 413 | + ***************************************************************************/ | ||
| 414 | +void ctpsfcube::init_cube(void) | ||
| 415 | +{ | ||
| 416 | + // Extract exposure cube definition | ||
| 417 | + const GWcs* proj = static_cast<const GWcs*>(m_psfcube.cube().projection()); | ||
| 418 | + std::string wcs = m_psfcube.cube().projection()->code(); | ||
| 419 | + std::string coords = m_psfcube.cube().projection()->coordsys(); | ||
| 420 | + double x = proj->crval(0); | ||
| 421 | + double y = proj->crval(1); | ||
| 422 | + double dx = proj->cdelt(0); | ||
| 423 | + double dy = proj->cdelt(1); | ||
| 424 | + int nx = m_psfcube.cube().nx(); | ||
| 425 | + int ny = m_psfcube.cube().ny(); | ||
| 426 | + double dmax = (*this)["amax"].real(); | ||
| 427 | + int ndbins = (*this)["anumbins"].integer(); | ||
| 428 | + | ||
| 429 | + // Extract energies | ||
| 430 | + GEnergies energies = m_psfcube.energies(); | ||
| 431 | + | ||
| 432 | + // If requested, insert energies at all event list energy boundaries | ||
| 433 | + if (m_addbounds) { | ||
| 434 | + | ||
| 435 | + // Set logger | ||
| 436 | + GLog* logger = NULL; | ||
| 437 | + if (logTerse()) { | ||
| 438 | + logger = &log; | ||
| 439 | + } | ||
| 440 | + | ||
| 441 | + // Loop over all observations | ||
| 442 | + for (int i = 0; i < m_obs.size(); ++i) { | ||
| 443 | + | ||
| 444 | + // Get observation and continue only if it is a CTA observation | ||
| 445 | + const GCTAObservation* cta = dynamic_cast<const GCTAObservation*> | ||
| 446 | + (m_obs[i]); | ||
| 447 | + | ||
| 448 | + // Skip observation if it's not a CTA observation | ||
| 449 | + if (cta == NULL) { | ||
| 450 | + continue; | ||
| 451 | + } | ||
| 452 | + | ||
| 453 | + // Skip observation if it does not contain an event list | ||
| 454 | + if (cta->eventtype() != "EventList") { | ||
| 455 | + continue; | ||
| 456 | + } | ||
| 457 | + | ||
| 458 | + // Insert energy boundaries | ||
| 459 | + energies = insert_energy_boundaries(energies, *cta, logger); | ||
| 460 | + | ||
| 461 | + } // endfor: looped over all observations | ||
| 462 | + | ||
| 463 | + } // endif: energy bin insertion requested | ||
| 464 | + | ||
| 465 | + // Setup PSF cube | ||
| 466 | + m_psfcube = GCTACubePsf(wcs, coords, x, y, dx, dy, nx, ny, energies, | ||
| 467 | + dmax, ndbins); | ||
| 468 | + | ||
| 469 | + // Log PSF cube | ||
| 470 | + if (logTerse()) { | ||
| 471 | + log << m_psfcube.print(m_chatter) << std::endl; | ||
| 472 | + } | ||
| 473 | + | ||
| 474 | + // Return | ||
| 475 | + return; | ||
| 476 | +}; |
src/ctpsfcube/ctpsfcube.hpp
| @@ -67,9 +67,12 @@ protected: | @@ -67,9 +67,12 @@ protected: | ||
| 67 | void copy_members(const ctpsfcube& app); | 67 | void copy_members(const ctpsfcube& app); |
| 68 | void free_members(void); | 68 | void free_members(void); |
| 69 | void get_parameters(void); | 69 | void get_parameters(void); |
| 70 | + void init_cube(void); | ||
| 70 | 71 | ||
| 71 | // User parameters | 72 | // User parameters |
| 72 | - GFilename m_outcube; //!< Output PSF cube file name | 73 | + GFilename m_outcube; //!< Output PSF cube file name |
| 74 | + bool m_addbounds; //!< Add energies at boundaries? | ||
| 75 | + GChatter m_chatter; //!< Chattiness | ||
| 73 | 76 | ||
| 74 | // Protected members | 77 | // Protected members |
| 75 | GObservations m_obs; //!< Observation container | 78 | GObservations m_obs; //!< Observation container |
src/ctpsfcube/ctpsfcube.par
| @@ -5,7 +5,7 @@ | @@ -5,7 +5,7 @@ | ||
| 5 | # ------------------------------------------------------------------------- # | 5 | # ------------------------------------------------------------------------- # |
| 6 | # # | 6 | # # |
| 7 | # File: ctpsfcube.par # | 7 | # File: ctpsfcube.par # |
| 8 | -# Version: 1.0.0 # | 8 | +# Version: 1.1.0 # |
| 9 | # # | 9 | # # |
| 10 | # Author: Chia-Chun Lu # | 10 | # Author: Chia-Chun Lu # |
| 11 | # c.lu@mpi-hd.mpg.de # | 11 | # c.lu@mpi-hd.mpg.de # |
| @@ -26,11 +26,12 @@ outcube, f, a, "psfcube.fits",,, "Output PSF cube file" | @@ -26,11 +26,12 @@ outcube, f, a, "psfcube.fits",,, "Output PSF cube file" | ||
| 26 | # | 26 | # |
| 27 | # Energy binning parameters | 27 | # Energy binning parameters |
| 28 | #========================== | 28 | #========================== |
| 29 | -ebinalg, s, h, "LOG", FILE|LIN|LOG,, "Algorithm for defining energy bins" | ||
| 30 | -emin, r, a, 0.1,,, "Lower energy limit (TeV)" | ||
| 31 | -emax, r, a, 100.0,,, "Upper energy limit (TeV)" | ||
| 32 | -enumbins, i, a, 20,,, "Number of energy bins" | ||
| 33 | -ebinfile, f, h, "NONE",,, "Name of the file containing the energy bin definition" | 29 | +ebinalg, s, h, "LOG", FILE|LIN|LOG,, "Algorithm for defining energy bins" |
| 30 | +emin, r, a, 0.1,,, "Lower energy limit (TeV)" | ||
| 31 | +emax, r, a, 100.0,,, "Upper energy limit (TeV)" | ||
| 32 | +enumbins, i, a, 20,,, "Number of energy bins" | ||
| 33 | +ebinfile, f, h, "NONE",,, "Name of the file containing the energy bin definition" | ||
| 34 | +addbounds, b, h, yes,,, "Add energies at observation energy boundaries?" | ||
| 34 | 35 | ||
| 35 | # | 36 | # |
| 36 | # Spatial binning parameters | 37 | # Spatial binning parameters |
src/support/ctool.cpp
| @@ -1303,6 +1303,81 @@ std::string ctool::get_obs_header(const GObservation* obs) | @@ -1303,6 +1303,81 @@ std::string ctool::get_obs_header(const GObservation* obs) | ||
| 1303 | 1303 | ||
| 1304 | 1304 | ||
| 1305 | /***********************************************************************//** | 1305 | /***********************************************************************//** |
| 1306 | + * @brief Insert observation energy boundaries into list of energies | ||
| 1307 | + * | ||
| 1308 | + * @param[in] energies Energies. | ||
| 1309 | + * @param[in] obs Observation container. | ||
| 1310 | + * @return Energies. | ||
| 1311 | + ***************************************************************************/ | ||
| 1312 | +GEnergies ctool::insert_energy_boundaries(const GEnergies& energies, | ||
| 1313 | + const GCTAObservation& obs, | ||
| 1314 | + GLog* log) const | ||
| 1315 | +{ | ||
| 1316 | + // Create copy of input energies | ||
| 1317 | + GEnergies engs = energies; | ||
| 1318 | + | ||
| 1319 | + // Get the energy boundaries of the event list | ||
| 1320 | + GEbounds ebounds = obs.ebounds(); | ||
| 1321 | + | ||
| 1322 | + // Loop over all boundary energies | ||
| 1323 | + for (int iebin = 0; iebin <= ebounds.size(); ++iebin) { | ||
| 1324 | + | ||
| 1325 | + // Get boundary energy | ||
| 1326 | + GEnergy energy; | ||
| 1327 | + if (iebin < ebounds.size()) { | ||
| 1328 | + energy = ebounds.emin(iebin); | ||
| 1329 | + } | ||
| 1330 | + else { | ||
| 1331 | + energy = ebounds.emax(); | ||
| 1332 | + } | ||
| 1333 | + | ||
| 1334 | + // Get index before which the energy should be appended | ||
| 1335 | + bool insert = true; | ||
| 1336 | + int index = -1; | ||
| 1337 | + for (int k = 0; k < engs.size(); ++k) { | ||
| 1338 | + | ||
| 1339 | + // If energy exists already then skip the boundary and examine the | ||
| 1340 | + // next one. We consider here 1 MeV as being sufficiently close. | ||
| 1341 | + if (std::abs(engs[k].MeV()-energy.MeV()) < 1.0) { | ||
| 1342 | + insert = false; | ||
| 1343 | + break; | ||
| 1344 | + } | ||
| 1345 | + | ||
| 1346 | + // If energy is above the boundary energy we found the index | ||
| 1347 | + if (engs[k] > energy) { | ||
| 1348 | + index = k; | ||
| 1349 | + break; | ||
| 1350 | + } | ||
| 1351 | + | ||
| 1352 | + } // endfor: search index for insertion | ||
| 1353 | + | ||
| 1354 | + // Insert energy if requested | ||
| 1355 | + if (insert) { | ||
| 1356 | + | ||
| 1357 | + // Insert or append energy | ||
| 1358 | + if (index != -1) { | ||
| 1359 | + engs.insert(index, energy); | ||
| 1360 | + } | ||
| 1361 | + else { | ||
| 1362 | + engs.append(energy); | ||
| 1363 | + } | ||
| 1364 | + | ||
| 1365 | + // Log energy insertion | ||
| 1366 | + if (log != NULL) { | ||
| 1367 | + *log << gammalib::parformat("Insert energy"); | ||
| 1368 | + *log << energy.print() << std::endl; | ||
| 1369 | + } | ||
| 1370 | + | ||
| 1371 | + } // endif: energy insertion requested | ||
| 1372 | + | ||
| 1373 | + } // endfor: looped over all energy boundaries | ||
| 1374 | + | ||
| 1375 | + // Return energies | ||
| 1376 | + return engs; | ||
| 1377 | +} | ||
| 1378 | + | ||
| 1379 | + | ||
| 1380 | +/***********************************************************************//** | ||
| 1306 | * @brief Dumps help text in the console | 1381 | * @brief Dumps help text in the console |
| 1307 | ***************************************************************************/ | 1382 | ***************************************************************************/ |
| 1308 | void ctool::provide_help(void) const | 1383 | void ctool::provide_help(void) const |
src/support/ctool.hpp
| @@ -92,6 +92,9 @@ protected: | @@ -92,6 +92,9 @@ protected: | ||
| 92 | GSkyDir get_mean_pointing(const GObservations& obs); | 92 | GSkyDir get_mean_pointing(const GObservations& obs); |
| 93 | size_t get_current_rss(void); | 93 | size_t get_current_rss(void); |
| 94 | std::string get_obs_header(const GObservation* obs); | 94 | std::string get_obs_header(const GObservation* obs); |
| 95 | + GEnergies insert_energy_boundaries(const GEnergies& energies, | ||
| 96 | + const GCTAObservation& obs, | ||
| 97 | + GLog* log = NULL) const; | ||
| 95 | 98 | ||
| 96 | // Protected members | 99 | // Protected members |
| 97 | bool m_read_ahead; //!< Read ahead output parameters | 100 | bool m_read_ahead; //!< Read ahead output parameters |