GammaLib 2.0.0
Loading...
Searching...
No Matches
GLATLtCubeMap.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * GLATLtCubeMap.cpp - Fermi LAT livetime cube map class *
3 * ----------------------------------------------------------------------- *
4 * copyright (C) 2010-2021 by Juergen Knoedlseder *
5 * ----------------------------------------------------------------------- *
6 * *
7 * This program is free software: you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation, either version 3 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
19 * *
20 ***************************************************************************/
21/**
22 * @file GLATLtCubeMap.cpp
23 * @brief Fermi/LAT livetime cube map class implementation
24 * @author Juergen Knoedlseder
25 */
26
27/* __ Includes ___________________________________________________________ */
28#ifdef HAVE_CONFIG_H
29#include <config.h>
30#endif
31#include "GTools.hpp"
32#include "GMath.hpp"
33#include "GEnergy.hpp"
34#include "GFitsBinTable.hpp"
35#include "GLATAeff.hpp"
36#include "GLATPsf.hpp"
37#include "GLATLtCubeMap.hpp"
38
39/* __ Method name definitions ____________________________________________ */
40#define G_COSTHETA "GLATLtCubeMap::costheta(int&)"
41#define G_PHI "GLATLtCubeMap::phi(int&)"
42
43/* __ Macros _____________________________________________________________ */
44
45/* __ Coding definitions _________________________________________________ */
46
47/* __ Debug definitions __________________________________________________ */
48
49/* __ Constants __________________________________________________________ */
50
51
52/*==========================================================================
53 = =
54 = Constructors/destructors =
55 = =
56 ==========================================================================*/
57
58/***********************************************************************//**
59 * @brief Void constructor
60 ***************************************************************************/
62{
63 // Initialise class members
65
66 // Return
67 return;
68}
69
70
71/***********************************************************************//**
72 * @brief Copy constructor
73 *
74 * @param map Livetime cube map.
75 ***************************************************************************/
77{
78 // Initialise class members
80
81 // Copy members
82 copy_members(map);
83
84 // Return
85 return;
86}
87
88
89/***********************************************************************//**
90 * @brief Destructor
91 ***************************************************************************/
93{
94 // Free members
96
97 // Return
98 return;
99}
100
101
102/*==========================================================================
103 = =
104 = Operators =
105 = =
106 ==========================================================================*/
107
108/***********************************************************************//**
109 * @brief Assignment operator
110 *
111 * @param[in] map Livetime cube map.
112 * @return Livetime cube map.
113 ***************************************************************************/
115{
116 // Execute only if object is not identical
117 if (this != &map) {
118
119 // Free members
120 free_members();
121
122 // Initialise private members
123 init_members();
124
125 // Copy members
126 copy_members(map);
127
128 } // endif: object was not identical
129
130 // Return this object
131 return *this;
132}
133
134
135/***********************************************************************//**
136 * @brief Sum function multiplied by livetime over zenith angle
137 *
138 * @param[in] dir Sky direction.
139 * @param[in] fct Function to evaluate.
140 *
141 * Computes
142 * \f[\sum_{\cos \theta} T_{\rm live}(\cos \theta) f(\cos \theta)\f]
143 * where
144 * \f$T_{\rm live}(\cos \theta)\f$ is the livetime as a function of the
145 * cosine of the zenith angle, and
146 * \f$f(\cos \theta)\f$ is a function that depends on the cosine of the
147 * zenith angle.
148 * This method assumes that \f$T_{\rm live}(\cos \theta)\f$ is stored as a
149 * set of maps.
150 ***************************************************************************/
152{
153 // Get map index
154 int pixel = m_map.dir2pix(dir);
155
156 // Initialise sum
157 double sum = 0.0;
158
159 // Loop over zenith angles
160 for (int i = 0; i < m_num_ctheta; ++i) {
161 sum += m_map(pixel, i) * (*fct)(costheta(i));
162 }
163
164 // Return sum
165 return sum;
166}
167
168
169/***********************************************************************//**
170 * @brief Sum function multiplied by livetime over zenith and azimuth angles
171 *
172 * @param[in] dir Sky direction.
173 * @param[in] fct Function to evaluate.
174 *
175 * Computes
176 * \f[\sum_{\cos \theta, \phi} T_{\rm live}(\cos \theta, \phi)
177 * f(\cos \theta, \phi)\f]
178 * where
179 * \f$T_{\rm live}(\cos \theta, \phi)\f$ is the livetime as a function of
180 * the cosine of the zenith and of the azimuth angle, and
181 * \f$f(\cos \theta, \phi)\f$ is a function that depends on the cosine of
182 * the zenith angle and of the azimuth angle.
183 * This method assumes that \f$T_{\rm live}(\cos \theta, \phi)\f$ is
184 * stored as a set of maps in a 2D array with \f$\cos \theta\f$ being the
185 * most rapidely varying parameter and with the first map starting at
186 * index m_num_ctheta (the first m_num_ctheta maps are the livetime cube
187 * maps without any \f$\phi\f$ dependence).
188 ***************************************************************************/
190{
191 // Get map index
192 int pixel = m_map.dir2pix(dir);
193
194 // Initialise sum
195 double sum = 0.0;
196
197 // Loop over azimuth and zenith angles. Note that the map index starts
198 // with m_num_ctheta as the first m_num_ctheta maps correspond to an
199 // evaluation without any phi-dependence.
200 for (int iphi = 0, i = m_num_ctheta; iphi < m_num_phi; ++iphi) {
201 double p = phi(iphi);
202 for (int itheta = 0; itheta < m_num_ctheta; ++itheta, ++i) {
203 sum += m_map(pixel, i) * (*fct)(costheta(itheta), p);
204 }
205 }
206
207 // Return sum
208 return sum;
209}
210
211
212/***********************************************************************//**
213 * @brief Sum effective area multiplied by livetime over zenith and
214 * (optionally) azimuth angles
215 *
216 * @param[in] dir True sky direction.
217 * @param[in] energy True photon energy.
218 * @param[in] aeff Effective area.
219 *
220 * Computes
221 * \f[\sum_{\cos \theta, \phi} T_{\rm live}(\cos \theta, \phi)
222 * A_{\rm eff}(\log E, \cos \theta, \phi)\f]
223 * where
224 * \f$T_{\rm live}(\cos \theta, \phi)\f$ is the livetime as a function of
225 * the cosine of the zenith and the azimuth angle, and
226 * \f$A_{\rm eff}(\log E, \cos \theta, \phi)\f$ is the effective area that
227 * depends on
228 * the log10 of the energy (in MeV),
229 * the cosine of the zenith angle, and
230 * the azimuth angle.
231 * This method assumes that \f$T_{\rm live}(\cos \theta, \phi)\f$ is
232 * stored as a set of maps in a 2D array with \f$\cos \theta\f$ being the
233 * most rapidely varying parameter and with the first map starting at
234 * index m_num_ctheta (the first m_num_ctheta maps are the livetime cube
235 * maps without any \f$\phi\f$ dependence).
236 ***************************************************************************/
237double GLATLtCubeMap::operator()(const GSkyDir& dir, const GEnergy& energy,
238 const GLATAeff& aeff) const
239{
240 // Get map index
241 int pixel = m_map.dir2pix(dir);
242
243 // Initialise sum
244 double sum = 0.0;
245
246 // Circumvent const correctness
247 GLATAeff* fct = ((GLATAeff*)&aeff);
248
249 // If livetime cube and response have phi dependence then sum over
250 // zenith and azimuth. Note that the map index starts with m_num_ctheta
251 // as the first m_num_ctheta maps correspond to an evaluation without
252 // any phi-dependence.
253 if (has_phi() && aeff.has_phi()) {
254 for (int iphi = 0, i = m_num_ctheta; iphi < m_num_phi; ++iphi) {
255 double p = phi(iphi);
256 for (int itheta = 0; itheta < m_num_ctheta; ++itheta, ++i) {
257 sum += m_map(pixel, i) * (*fct)(energy.log10MeV(), costheta(i), p);
258 }
259 }
260 }
261
262 // ... otherwise sum only over zenith angle
263 else {
264 for (int i = 0; i < m_num_ctheta; ++i) {
265 sum += m_map(pixel, i) * (*fct)(energy.log10MeV(), costheta(i));
266 }
267 }
268
269 // Return sum
270 return sum;
271}
272
273
274/***********************************************************************//**
275 * @brief Sum effective area multiplied by livetime over zenith angles
276 *
277 * @param[in] dir True sky direction.
278 * @param[in] energy True photon energy.
279 * @param[in] offset Offset from true direction (deg).
280 * @param[in] psf Point spread function.
281 * @param[in] aeff Effective area.
282 *
283 * Computes
284 * \f[\sum_{\cos \theta} T_{\rm live}(\cos \theta)
285 * PSF(\log E, \delta, \cos \theta) A_{\rm eff}(\cos \theta, \phi)\f]
286 * where
287 * \f$T_{\rm live}(\cos \theta)\f$ is the livetime as a function of the
288 * cosine of the zenith angle, and
289 * \f$PSF(\log E, \delta, \cos \theta)\f$ is the point spread function that
290 * depends on
291 * the log10 of the energy (in MeV),
292 * the offset angle from the true direction (in degrees), and
293 * the cosine of the zenith angle, and
294 * \f$A_{\rm eff}(\cos \theta, \phi)\f$ is the effective area that depends
295 * on the cosine of the zenith angle and (optionally) of the azimuth angle.
296 ***************************************************************************/
297double GLATLtCubeMap::operator()(const GSkyDir& dir, const GEnergy& energy,
298 const double& offset, const GLATPsf& psf,
299 const GLATAeff& aeff) const
300{
301 // Get map index
302 int pixel = m_map.dir2pix(dir);
303
304 // Initialise sum
305 double sum = 0.0;
306
307 // Circumvent const correctness
308 GLATPsf* fpsf = const_cast<GLATPsf*>(&psf);
309 GLATAeff* faeff = const_cast<GLATAeff*>(&aeff);
310
311 // Get log10 of energy
312 double logE = energy.log10MeV();
313
314 // If livetime cube and response have phi dependence then sum over
315 // zenith and azimuth. Note that the map index starts with m_num_ctheta
316 // as the first m_num_ctheta maps correspond to an evaluation without
317 // any phi-dependence.
318 if (has_phi() && aeff.has_phi()) {
319 for (int iphi = 0, i = m_num_ctheta; iphi < m_num_phi; ++iphi) {
320 double p = phi(iphi);
321 for (int itheta = 0; itheta < m_num_ctheta; ++itheta, ++i) {
322 sum += m_map(pixel, i) * (*faeff)(logE, costheta(i), p) *
323 (*fpsf)(offset, logE, costheta(i));
324 }
325 }
326 }
327
328 // ... otherwise sum only over zenith angle
329 else {
330 for (int i = 0; i < m_num_ctheta; ++i) {
331 sum += m_map(pixel, i) * (*faeff)(logE, costheta(i)) *
332 (*fpsf)(offset, logE, costheta(i));
333 }
334 }
335
336 // Return sum
337 return sum;
338}
339
340
341/*==========================================================================
342 = =
343 = Public methods =
344 = =
345 ==========================================================================*/
346
347/***********************************************************************//**
348 * @brief Clear livetime cube map
349 ***************************************************************************/
351{
352 // Free class members
353 free_members();
354
355 // Initialise members
356 init_members();
357
358 // Return
359 return;
360}
361
362
363/***********************************************************************//**
364 * @brief Clone livetime cube map
365 *
366 * @return Pointer to deep copy of livetime cube map
367 ***************************************************************************/
369{
370 return new GLATLtCubeMap(*this);
371}
372
373
374/***********************************************************************//**
375 * @brief Load livetime cube from FITS file
376 *
377 * @param[in] table FITS table.
378 ***************************************************************************/
380{
381 // Clear object
382 clear();
383
384 // Read skymap
385 m_map.read(table);
386
387 // Set costheta binning scheme
388 std::string scheme =
390 m_sqrt_bin = (scheme == "SQRT(1-COSTHETA)");
391
392 // Read attributes
393 m_num_ctheta = table.integer("NBRBINS");
394 m_num_phi = table.integer("PHIBINS");
395 m_min_ctheta = table.real("COSMIN");
396
397 // Return
398 return;
399}
400
401
402/***********************************************************************//**
403 * @brief Write livetime cube map into FITS file
404 *
405 * @param[in] fits FITS file.
406 * @param[in] extname Livetime cube map extension name.
407 *
408 * Writes livetime cube map into a FITS file.
409 ***************************************************************************/
410void GLATLtCubeMap::write(GFits& fits, const std::string& extname) const
411{
412 // If the FITS file contains already an extension with the same name
413 // then remove this extension now
414 if (fits.contains(extname)) {
415 fits.remove(extname);
416 }
417
418 // Write sky map info FITS file
419 GFitsHDU* hdu = m_map.write(fits, extname);
420
421 // If HDU is valid then set sky map keywords
422 if (hdu != NULL) {
423 hdu->card("THETABIN", costhetabin(), "Costheta binning scheme");
424 hdu->card("NBRBINS", m_num_ctheta, "Number of costheta bins");
425 hdu->card("PHIBINS", m_num_phi, "Number of phi bins");
426 hdu->card("COSMIN", m_min_ctheta, "Minimum costheta value");
427 }
428
429 // Return
430 return;
431}
432
433
434/***********************************************************************//**
435 * @brief Return cos theta value for an index
436 *
437 * @param[in] index Cos theta bin index [0,...,m_num_ctheta[
438 *
439 * @exception GException::out_of_range
440 * Bin index outside value range.
441 *
442 * The cos theta value is computed using
443 * \f[\cos \theta = 1 - \left( \frac{{\rm index} + 0.5}{\rm ncostheta}
444 * \right)^N (1 - {\rm costhetamin})\f]
445 * where
446 * \f${\rm index}\f$ is the bin index,
447 * \f${\rm ncostheta}\f$ is the number of cos theta bins,
448 * \f$N\f$ is either 1 or 2, and
449 * \f${\rm costhetamin}\f$ is the minimum cos theta value.
450 * Default values for LAT are \f$N=2\f$ and \f${\rm costhetamin}=0\f$.
451 ***************************************************************************/
452double GLATLtCubeMap::costheta(const int& index) const
453{
454 // Optionally check if the index is valid
455 #if defined(G_RANGE_CHECK)
456 if (index < 0 || index >= m_num_ctheta) {
457 throw GException::out_of_range(G_COSTHETA, "cos theta bin index",
458 index, m_num_ctheta);
459 }
460 #endif
461
462 // Set cos theta scale
463 double f = (index+0.5)/m_num_ctheta;
464 if (m_sqrt_bin) {
465 f = f*f;
466 }
467
468 // Set cos theta value
469 double costheta = 1.0 - f * (1.0 - m_min_ctheta);
470
471 // Return costheta
472 return costheta;
473}
474
475
476/***********************************************************************//**
477 * @brief Return phi value (in radians) for an index
478 *
479 * @param[in] index Phi bin index [0,...,m_num_phi[
480 *
481 * @exception GException::out_of_range
482 * Bin index outside value range.
483 *
484 * The phi value is computed using
485 * \f[\phi = \frac{{\rm index} + 0.5}{\rm nphi} \frac{\pi}{4}\f]
486 * where
487 * \f${\rm index}\f$ is the bin index, and
488 * \f${\rm nphi}\f$ is the number of phi bins.
489 ***************************************************************************/
490double GLATLtCubeMap::phi(const int& index) const
491{
492 // Optionally check if the index is valid
493 #if defined(G_RANGE_CHECK)
494 if (index < 0 || index >= m_num_phi) {
495 throw GException::out_of_range(G_PHI, "Phi bin index",
496 index, m_num_phi);
497 }
498 #endif
499
500 // Set phi value
501 double phi = (index+0.5) / m_num_phi * gammalib::pi / 4.0;
502
503 // Return phi
504 return phi;
505}
506
507
508/***********************************************************************//**
509 * @brief Return cos theta binning scheme
510 *
511 * Returns either "SQRT(1-COSTHETA)" or "COSTHETA".
512 ***************************************************************************/
513std::string GLATLtCubeMap::costhetabin(void) const
514{
515 // Set string
516 std::string result = (m_sqrt_bin) ? "SQRT(1-COSTHETA)" : "COSTHETA";
517
518 // Return result
519 return result;
520}
521
522
523/***********************************************************************//**
524 * @brief Print livetime cube map information
525 *
526 * @param[in] chatter Chattiness (defaults to NORMAL).
527 * @return String containing livetime cube map information.
528 ***************************************************************************/
529std::string GLATLtCubeMap::print(const GChatter& chatter) const
530{
531 // Initialise result string
532 std::string result;
533
534 // Continue only if chatter is not silent
535 if (chatter != SILENT) {
536
537 // Append header
538 result.append("=== GLATLtCubeMap ===");
539
540 // Append information
541 result.append("\n"+gammalib::parformat("Number of cos theta bins") +
543 result.append("\n"+gammalib::parformat("Number of phi bins") +
545 result.append("\n"+gammalib::parformat("Cos theta binning"));
546 if (m_sqrt_bin) {
547 result.append("sqrt");
548 }
549 else {
550 result.append("linear");
551 }
552 result.append("\n"+gammalib::parformat("Minimum cos theta") +
554 result.append("\n"+m_map.print(gammalib::reduce(chatter)));
555
556 } // endif: chatter was not silent
557
558 // Return result
559 return result;
560}
561
562
563/*==========================================================================
564 = =
565 = Private methods =
566 = =
567 ==========================================================================*/
568
569/***********************************************************************//**
570 * @brief Initialise class members
571 ***************************************************************************/
573{
574 // Initialise members
575 m_map.clear();
576 m_num_ctheta = 0;
577 m_num_phi = 0;
578 m_min_ctheta = 0.0;
579 m_sqrt_bin = true;
580
581 // Return
582 return;
583}
584
585
586/***********************************************************************//**
587 * @brief Copy class members
588 *
589 * @param map Livetime cube map.
590 ***************************************************************************/
592{
593 // Copy members
594 m_map = map.m_map;
596 m_num_phi = map.m_num_phi;
599
600 // Return
601 return;
602}
603
604
605/***********************************************************************//**
606 * @brief Delete class members
607 ***************************************************************************/
609{
610 // Return
611 return;
612}
#define G_PHI
Energy value class definition.
FITS binary table class definition.
Fermi LAT effective area class definition.
#define G_COSTHETA
Fermi LAT livetime cube map class definition.
double(* _ltcube_ctheta_phi)(const double &costheta, const double &phi)
double(* _ltcube_ctheta)(const double &costheta)
Fermi LAT point spread function class definition.
Mathematical function definitions.
Gammalib tools definition.
GChatter
Definition GTypemaps.hpp:33
@ SILENT
Definition GTypemaps.hpp:34
double sum(const GVector &vector)
Computes vector sum.
Definition GVector.cpp:944
Class that handles energies in a unit independent way.
Definition GEnergy.hpp:48
double log10MeV(void) const
Return log10 of energy in MeV.
Definition GEnergy.cpp:423
Abstract FITS extension base class.
Definition GFitsHDU.hpp:51
double real(const std::string &keyname) const
Return card value as double precision.
Definition GFitsHDU.hpp:423
std::string string(const std::string &keyname) const
Return card value as string.
Definition GFitsHDU.hpp:410
GFitsHeaderCard & card(const int &cardno)
Return header card.
Definition GFitsHDU.hpp:259
int integer(const std::string &keyname) const
Return card value as integer.
Definition GFitsHDU.hpp:436
Abstract interface for FITS table.
FITS file class.
Definition GFits.hpp:63
bool contains(const int &extno) const
Check if HDU exists in FITS file.
Definition GFits.hpp:282
void remove(const int &extno)
Remove HDU from FITS file.
Definition GFits.cpp:862
Interface for the Fermi/LAT effective area.
Definition GLATAeff.hpp:59
bool has_phi(void) const
Signal that effective area has Phi dependence.
Definition GLATAeff.hpp:207
Fermi LAT livetime cube map class.
int m_num_ctheta
Number of bins in cos theta.
void free_members(void)
Delete class members.
GLATLtCubeMap & operator=(const GLATLtCubeMap &cube)
Assignment operator.
void write(GFits &fits, const std::string &extname=gammalib::extname_lat_ltcubemap) const
Write livetime cube map into FITS file.
const double & costhetamin(void) const
Return minimum of cosine theta.
virtual ~GLATLtCubeMap(void)
Destructor.
void copy_members(const GLATLtCubeMap &cube)
Copy class members.
double m_min_ctheta
Minimum cos theta value.
GSkyMap m_map
Lifetime cube map.
double costheta(const int &index) const
Return cos theta value for an index.
GLATLtCubeMap(void)
Void constructor.
const int & ncostheta(void) const
Return number of cosine theta bins.
void clear(void)
Clear livetime cube map.
bool m_sqrt_bin
Square root binning?
double operator()(const GSkyDir &dir, _ltcube_ctheta fct) const
Sum function multiplied by livetime over zenith angle.
std::string costhetabin(void) const
Return cos theta binning scheme.
const int & nphi(void) const
Return number of phi bins.
GLATLtCubeMap * clone(void) const
Clone livetime cube map.
std::string print(const GChatter &chatter=NORMAL) const
Print livetime cube map information.
double phi(const int &index) const
Return phi value (in radians) for an index.
int m_num_phi
Number of bins in phi.
void init_members(void)
Initialise class members.
void read(const GFitsTable &table)
Load livetime cube from FITS file.
bool has_phi(void) const
Signal if livetime cube map has phi dependence.
Interface for the Fermi LAT point spread function.
Definition GLATPsf.hpp:54
Sky direction class.
Definition GSkyDir.hpp:62
void clear(void)
Clear instance.
Definition GSkyMap.cpp:1100
void read(const GFitsHDU &hdu)
Read skymap from FITS HDU.
Definition GSkyMap.cpp:2664
GFitsHDU * write(GFits &file, const std::string &extname="") const
Write sky map into FITS file.
Definition GSkyMap.cpp:2697
GSkyPixel dir2pix(const GSkyDir &dir) const
Returns sky map pixel for a given sky direction.
Definition GSkyMap.cpp:1472
std::string print(const GChatter &chatter=NORMAL) const
Print sky map.
Definition GSkyMap.cpp:2787
std::string parformat(const std::string &s, const int &indent=0)
Convert string in parameter format.
Definition GTools.cpp:1143
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition GTools.cpp:489
const double pi
Definition GMath.hpp:35
std::string strip_whitespace(const std::string &arg)
Strip leading and trailing whitespace from string.
Definition GTools.cpp:80
GChatter reduce(const GChatter &chatter)
Reduce chattiness by one level.
Definition GTypemaps.hpp:65
std::string toupper(const std::string &s)
Convert string to upper case.
Definition GTools.cpp:941