GammaLib 2.1.0.dev
Loading...
Searching...
No Matches
GLATPsfV3.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * GLATPsfV3.cpp - Fermi/LAT point spread function version 3 class *
3 * ----------------------------------------------------------------------- *
4 * copyright (C) 2012-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 GLATPsfV3.cpp
23 * @brief Fermi/LAT point spread function version 3 class implementation
24 * @author Juergen Knoedlseder
25 */
26
27/* __ Includes ___________________________________________________________ */
28#ifdef HAVE_CONFIG_H
29#include <config.h>
30#endif
31#include "GException.hpp"
32#include "GMath.hpp"
33#include "GFitsBinTable.hpp"
35#include "GIntegral.hpp"
36#include "GLATPsfV3.hpp"
37
38/* __ Method name definitions ____________________________________________ */
39#define G_READ "GLATPsfV3::read(GFitsTable&)"
40
41/* __ Macros _____________________________________________________________ */
42
43/* __ Coding definitions _________________________________________________ */
44//#define G_APPROXIMATE_PSF_INTEGRAL //!< Use approximate PSF integral
45
46/* __ Debug definitions __________________________________________________ */
47//#define G_CHECK_PSF_NORM //!< Check PSF normalization
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[in] psf Point spread function.
75 ***************************************************************************/
77{
78 // Initialise class members
80
81 // Copy members
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] psf Point spread function.
112 * @return Point spread function.
113 ***************************************************************************/
115{
116 // Execute only if object is not identical
117 if (this != &psf) {
118
119 // Copy base class members
120 this->GLATPsfBase::operator=(psf);
121
122 // Free members
123 free_members();
124
125 // Initialise private members
126 init_members();
127
128 // Copy members
130
131 } // endif: object was not identical
132
133 // Return this object
134 return *this;
135}
136
137
138/*==========================================================================
139 = =
140 = Public methods =
141 = =
142 ==========================================================================*/
143
144/***********************************************************************//**
145 * @brief Clear point spread function
146 ***************************************************************************/
148{
149 // Free class members (base and derived classes, derived class first)
150 free_members();
152
153 // Initialise members
155 init_members();
156
157 // Return
158 return;
159}
160
161
162/***********************************************************************//**
163 * @brief Clone point spread function
164 *
165 * @return Pointer to deep copy of point spread function
166 ***************************************************************************/
168{
169 return new GLATPsfV3(*this);
170}
171
172
173/***********************************************************************//**
174 * @brief Read point spread function from FITS table
175 *
176 * @param[in] table FITS table.
177 *
178 * @exception GException::invalid_argument
179 * Inconsistent response table encountered
180 *
181 * Reads point spread function information from FITS HDU. In addition to the
182 * energy and costheta binning information, 6 columns are expected:
183 * NCORE, NTAIL, SCORE, STAIL, GCORE, and GTAIL.
184 *
185 * The method assures that NCORE is set properly for each energy and
186 * cos(theta) bin so that the integral over the PSF amount to unity. This
187 * normalization is done by the method normalize_psf.
188 ***************************************************************************/
189void GLATPsfV3::read(const GFitsTable& table)
190{
191 // Clear arrays
192 m_ncore.clear();
193 m_ntail.clear();
194 m_score.clear();
195 m_stail.clear();
196 m_gcore.clear();
197 m_gtail.clear();
198
199 // Get energy and cos theta binning
200 m_rpsf_bins.read(table);
201
202 // Set minimum cos(theta)
204
205 // Continue only if there are bins
206 int size = m_rpsf_bins.size();
207 if (size > 0) {
208
209 // Allocate arrays
210 m_ncore.reserve(size);
211 m_ntail.reserve(size);
212 m_score.reserve(size);
213 m_stail.reserve(size);
214 m_gcore.reserve(size);
215 m_gtail.reserve(size);
216
217 // Get pointer to columns
218 const GFitsTableCol* ncore = table["NCORE"];
219 const GFitsTableCol* ntail = table["NTAIL"];
220 const GFitsTableCol* score = table["SCORE"];
221 const GFitsTableCol* stail = table["STAIL"];
222 const GFitsTableCol* gcore = table["GCORE"];
223 const GFitsTableCol* gtail = table["GTAIL"];
224
225 // Check consistency of columns
226 if (ncore->number() != size) {
227 std::string msg = "Number of elements in \"NCORE\" column ("+
228 gammalib::str(ncore->number())+") is incompatible "
229 "with the expected size ("+
230 gammalib::str(size)+"). Please specify a valid "
231 "point spread function table.";
233 }
234 if (ntail->number() != size) {
235 std::string msg = "Number of elements in \"NTAIL\" column ("+
236 gammalib::str(ntail->number())+") is incompatible "
237 "with the expected size ("+
238 gammalib::str(size)+"). Please specify a valid "
239 "point spread function table.";
241 }
242 if (score->number() != size) {
243 std::string msg = "Number of elements in \"SCORE\" column ("+
244 gammalib::str(score->number())+") is incompatible "
245 "with the expected size ("+
246 gammalib::str(size)+"). Please specify a valid "
247 "point spread function table.";
249 }
250 if (stail->number() != size) {
251 std::string msg = "Number of elements in \"STAIL\" column ("+
252 gammalib::str(stail->number())+") is incompatible "
253 "with the expected size ("+
254 gammalib::str(size)+"). Please specify a valid "
255 "point spread function table.";
257 }
258 if (gcore->number() != size) {
259 std::string msg = "Number of elements in \"GCORE\" column ("+
260 gammalib::str(gcore->number())+") is incompatible "
261 "with the expected size ("+
262 gammalib::str(size)+"). Please specify a valid "
263 "point spread function table.";
265 }
266 if (gtail->number() != size) {
267 std::string msg = "Number of elements in \"GTAIL\" column ("+
268 gammalib::str(gtail->number())+") is incompatible "
269 "with the expected size ("+
270 gammalib::str(size)+"). Please specify a valid "
271 "point spread function table.";
273 }
274
275 // Copy data
276 for (int i = 0; i < size; ++i) {
277 m_ncore.push_back(ncore->real(0,i));
278 m_ntail.push_back(ntail->real(0,i));
279 m_score.push_back(score->real(0,i));
280 m_stail.push_back(stail->real(0,i));
281 m_gcore.push_back(gcore->real(0,i));
282 m_gtail.push_back(gtail->real(0,i));
283 }
284
285 // Normalize PSF for all parameters
287
288 } // endif: there were bins
289
290 // Return
291 return;
292}
293
294
295/***********************************************************************//**
296 * @brief Write point spread function into FITS file
297 *
298 * @param[in] file FITS file.
299 *
300 * Writes the PSF into the extension "RPSF" of a FITS file. This method
301 * does not check if a "RPSF" extension exists so far, it simply adds one
302 * each time it is called.
303 *
304 * Nothing is done if the PSF size is 0.
305 *
306 * @todo Check if a RPSF extension exists already in FITS file
307 ***************************************************************************/
308void GLATPsfV3::write(GFits& file) const
309{
310 // Continue only if there are bins
311 int size = m_rpsf_bins.size();
312 if (size > 0) {
313
314 // Create new binary table
315 GFitsBinTable* hdu_rpsf = new GFitsBinTable;
316
317 // Set table attributes
318 hdu_rpsf->extname("RPSF");
319
320 // Write boundaries into table
321 m_rpsf_bins.write(*hdu_rpsf);
322
323 // Allocate floating point vector columns
324 GFitsTableFloatCol col_ncore = GFitsTableFloatCol("NCORE", 1, size);
325 GFitsTableFloatCol col_ntail = GFitsTableFloatCol("NTAIL", 1, size);
326 GFitsTableFloatCol col_score = GFitsTableFloatCol("SCORE", 1, size);
327 GFitsTableFloatCol col_stail = GFitsTableFloatCol("STAIL", 1, size);
328 GFitsTableFloatCol col_gcore = GFitsTableFloatCol("GCORE", 1, size);
329 GFitsTableFloatCol col_gtail = GFitsTableFloatCol("GTAIL", 1, size);
330
331 // Fill columns
332 for (int i = 0; i < size; ++i) {
333 col_ncore(0,i) = m_ncore[i];
334 col_ntail(0,i) = m_ntail[i];
335 col_score(0,i) = m_score[i];
336 col_stail(0,i) = m_stail[i];
337 col_gcore(0,i) = m_gcore[i];
338 col_gtail(0,i) = m_gtail[i];
339 }
340
341 // Append columns to table
342 hdu_rpsf->append(col_ncore);
343 hdu_rpsf->append(col_ntail);
344 hdu_rpsf->append(col_score);
345 hdu_rpsf->append(col_stail);
346 hdu_rpsf->append(col_gcore);
347 hdu_rpsf->append(col_gtail);
348
349 // Set detector section
350 std::string detnam = (front()) ? "FRONT" : "BACK";
351
352 // Set header keywords
353 hdu_rpsf->card("PSFVER", 3, "File format version");
354 hdu_rpsf->card("DETNAM", detnam, "Detector section");
355
356 // Append HDU to FITS file
357 file.append(*hdu_rpsf);
358
359 // Free binary table
360 delete hdu_rpsf;
361
362 } // endif: there were data to write
363
364 // Return
365 return;
366}
367
368
369/***********************************************************************//**
370 * @brief Return point spread function value
371 *
372 * @param[in] offset Offset angle (deg).
373 * @param[in] logE Log10 of the true photon energy (MeV).
374 * @param[in] ctheta Cosine of zenith angle.
375 *
376 * Evaluates point spread function by doing a bi-linear interpolation of
377 * PSF values obtained at the 4 corners that bound the specified energy and
378 * cos(theta) value.
379 *
380 * This method is inspired by the Fermi/LAT Science Tools method Psf3::value.
381 ***************************************************************************/
382double GLATPsfV3::psf(const double& offset, const double& logE,
383 const double& ctheta)
384{
385 // Initialise response
386 double psf = 0.0;
387
388 // Compute point spread function
389 if (ctheta >= m_min_ctheta) {
390
391 // Set interpolation indices and weights
392 m_rpsf_bins.set(logE, ctheta);
393
394 // Recover information for interpolation
395 std::vector<int> index = m_rpsf_bins.indices();
396 std::vector<double> energy = m_rpsf_bins.energies();
397 std::vector<double> weight = m_rpsf_bins.weights();
398
399 // Compute offset angle in radians
400 double offset_rad = offset * gammalib::deg2rad;
401
402 // Compute PSF values for the four corners
403 double psf0 = eval_psf(offset_rad, energy[0], index[0]);
404 double psf1 = eval_psf(offset_rad, energy[1], index[1]);
405 double psf2 = eval_psf(offset_rad, energy[2], index[2]);
406 double psf3 = eval_psf(offset_rad, energy[3], index[3]);
407
408 // Perform bi-linear interpolation
409 psf = weight[0] * psf0 + weight[1] * psf1 +
410 weight[2] * psf2 + weight[3] * psf3;
411
412 } // endif: cos(theta) was in valid range
413
414 // Return point spread function
415 return psf;
416}
417
418
419/***********************************************************************//**
420 * @brief Print point spread function
421 *
422 * @param[in] chatter Chattiness (defaults to NORMAL).
423 * @return String containing point spread function information.
424 ***************************************************************************/
425std::string GLATPsfV3::print(const GChatter& chatter) const
426{
427 // Initialise result string
428 std::string result;
429
430 // Continue only if chatter is not silent
431 if (chatter != SILENT) {
432
433 // Append header
434 result.append("=== GLATPsfV3 ===");
435
436 } // endif: chatter was not silent
437
438 // Return result
439 return result;
440}
441
442
443/*==========================================================================
444 = =
445 = Private methods =
446 = =
447 ==========================================================================*/
448
449/***********************************************************************//**
450 * @brief Initialise class members
451 ***************************************************************************/
453{
454 // Initialise members
455 m_ncore.clear();
456 m_ntail.clear();
457 m_score.clear();
458 m_stail.clear();
459 m_gcore.clear();
460 m_gtail.clear();
461
462 // Return
463 return;
464}
465
466
467/***********************************************************************//**
468 * @brief Copy class members
469 *
470 * @param[in] psf Point spread function.
471 ***************************************************************************/
473{
474 // Copy members
475 m_ncore = psf.m_ncore;
476 m_ntail = psf.m_ntail;
477 m_score = psf.m_score;
478 m_stail = psf.m_stail;
479 m_gcore = psf.m_gcore;
480 m_gtail = psf.m_gtail;
481
482 // Return
483 return;
484}
485
486
487/***********************************************************************//**
488 * @brief Delete class members
489 ***************************************************************************/
491{
492 // Return
493 return;
494}
495
496
497/***********************************************************************//**
498 * @brief Return point spread base function value
499 *
500 * @param[in] u Function argument.
501 * @param[in] gamma Index.
502 *
503 * The version 3 PSF base function is given by
504 * \f[\left(1 - \frac{1}{\Gamma} \right)
505 * \left(1 + \frac{u}{\Gamma} \right)^{-\Gamma}\f]
506 ***************************************************************************/
507double GLATPsfV3::base_fct(const double& u, const double& gamma)
508{
509 // Get base function value. The special case of gamma==1 is a ugly
510 // kluge because of sloppy programming in handoff response when
511 // setting boundaries of fit parameters for the PSF.
512 double base = (gamma == 1)
513 ? (1.0 - 1.0/1.001) * std::pow(1.0 + u/1.001, -1.001)
514 : (1.0 - 1.0/gamma) * std::pow(1.0 + u/gamma, -gamma);
515
516 // Return base function
517 return base;
518}
519
520
521/***********************************************************************//**
522 * @brief Return approximation of point spread base function integral
523 *
524 * @param[in] u Function argument.
525 * @param[in] gamma Index.
526 *
527 * The version 3 PSF base function integral is approximated by
528 * \f[1 - \left(1 + \frac{u}{\Gamma} \right)^{1-\Gamma}\f]
529 * which is valid for small angles \f$u\f$. For larger angles a numerical
530 * integration of the base function has to be performed.
531 *
532 * @todo Verify that 1+u/gamma is not negative
533 ***************************************************************************/
534double GLATPsfV3::base_int(const double& u, const double& gamma)
535{
536 // Compute integral of base function
537 double integral = 1.0 - std::pow(1.0 + u/gamma, 1.0 - gamma);
538
539 // Return integral
540 return integral;
541}
542
543
544/***********************************************************************//**
545 * @brief Evaluate PSF for a specific set of parameters
546 *
547 * @param[in] offset Offset angle (radians).
548 * @param[in] energy Energy (MeV).
549 * @param[in] index Parameter array index.
550 *
551 * Evaluates PSF as function of offset angle and energy for a specific set
552 * of PSF parameters. The parameter set that is used is specified by the
553 * index parameter. The energy parameter only serves to scale the score and
554 * stail parameters of the PSF.
555 *
556 * This method is inspired from the Fermi/LAT Science Tools method
557 * Psf3::evaluate.
558 ***************************************************************************/
559double GLATPsfV3::eval_psf(const double& offset, const double& energy,
560 const int& index)
561{
562 // Get energy scaling
563 double scale = scale_factor(energy);
564
565 // Get parameters
566 double ncore(m_ncore[index]);
567 double ntail(m_ntail[index]);
568 double score(m_score[index] * scale);
569 double stail(m_stail[index] * scale);
570 double gcore(m_gcore[index]);
571 double gtail(m_gtail[index]);
572
573 // Compute argument
574 double rc = offset / score;
575 double uc = 0.5 * rc * rc;
576 double rt = offset / stail;
577 double ut = 0.5 * rt * rt;
578
579 // Evaluate PSF
580 double psf = ncore * (base_fct(uc, gcore) + ntail * base_fct(ut, gtail));
581
582 // Return PSF
583 return psf;
584}
585
586
587/***********************************************************************//**
588 * @brief Integrates PSF for a specific set of parameters
589 *
590 * @param[in] energy Energy (MeV).
591 * @param[in] index Parameter array index.
592 *
593 * Integrates PSF for a specific set of parameters.
594 *
595 * Compile option G_APPROXIMATE_PSF_INTEGRAL:
596 * If defined, a numerical PSF integral is only performed for energies
597 * < 120 MeV, while for larger energies the small angle approximation is
598 * used. In not defined, a numerical PSF integral is performed for all
599 * energies.
600 * This option is kept for comparison with the Fermi/LAT ScienceTools who
601 * select the integration method based on the true photon energy. As the
602 * normalization is only performed once upon loading of the PSF, CPU time
603 * is not really an issue here, and we can afford the more precise numerical
604 * integration. Note that the uncertainties of the approximation at energies
605 * near to 120 MeV reaches 0.1%.
606 *
607 * @todo Implement gcore and gtail checking
608 ***************************************************************************/
609double GLATPsfV3::integrate_psf(const double& energy, const int& index)
610{
611 // Initialise integral
612 double psf = 0.0;
613
614 // Get energy scaling
615 double scale = scale_factor(energy);
616
617 // Get parameters
618 double ncore(m_ncore[index]);
619 double ntail(m_ntail[index]);
620 double score(m_score[index] * scale);
621 double stail(m_stail[index] * scale);
622 double gcore(m_gcore[index]);
623 double gtail(m_gtail[index]);
624
625 // Make sure that gcore and gtail are not negative
626 //if (gcore < 0 || gtail < 0) {
627 //}
628
629 // Do we need an exact integral?
630 #if defined(G_APPROXIMATE_PSF_INTEGRAL)
631 if (energy < 120) {
632 #endif
633
634 // Allocate integrand
635 GLATPsfV3::base_integrand integrand(ncore, ntail, score, stail, gcore, gtail);
636
637 // Allocate integral
638 GIntegral integral(&integrand);
639
640 // Integrate radially from 0 to 90 degrees
641 psf = integral.romberg(0.0, gammalib::pihalf) * gammalib::twopi;
642
643 #if defined(G_APPROXIMATE_PSF_INTEGRAL)
644 } // endif: exact integral was performed
645
646 // No, so we use the small angle approximation
647 else {
648
649 // Compute arguments
650 double rc = gammalib::pihalf / score;
651 double uc = 0.5 * rc * rc;
652 double sc = gammalib::twopi * score * score;
653 double rt = gammalib::pihalf / stail;
654 double ut = 0.5 * rt * rt;
655 double st = gammalib::twopi * stail * stail;
656
657 // Evaluate PSF integral (from 0 to 90 degrees)
658 psf = ncore * (base_int(uc, gcore) * sc +
659 base_int(ut, gtail) * st * ntail);
660
661 }
662 #endif
663
664 // Return PSF integral
665 return psf;
666}
667
668
669/***********************************************************************//**
670 * @brief Normalize PSF for all parameters
671 *
672 * Makes sure that PSF is normalized for all parameters. We assure this by
673 * looping over all parameter nodes, integrating the PSF for each set of
674 * parameters, and dividing the NCORE parameter by the integral.
675 *
676 * Compile option G_CHECK_PSF_NORM:
677 * If defined, checks that the PSF is normalized correctly.
678 ***************************************************************************/
680{
681 // Loop over all energy bins
682 for (int ie = 0; ie < m_rpsf_bins.nenergies(); ++ie) {
683
684 // Extract energy value (in MeV)
685 double energy = m_rpsf_bins.energy(ie);
686
687 // Loop over all cos(theta) bins
688 for (int ic = 0; ic < m_rpsf_bins.ncostheta(); ++ic) {
689
690 // Get parameter index
691 int index = m_rpsf_bins.index(ie, ic);
692
693 // Integrate PSF
694 double norm = integrate_psf(energy, index);
695
696 // Normalize PSF
697 m_ncore[index] /= norm;
698
699 // Compile option: check PSF normalization
700 #if defined(G_CHECK_PSF_NORM)
701 double scale = scale_factor(energy);
702 double ncore(m_ncore[index]);
703 double ntail(m_ntail[index]);
704 double score(m_score[index] * scale);
705 double stail(m_stail[index] * scale);
706 double gcore(m_gcore[index]);
707 double gtail(m_gtail[index]);
708 GLATPsfV3::base_integrand integrand(ncore, ntail, score, stail, gcore, gtail);
709 GIntegral integral(&integrand);
710 double sum = integral.romberg(0.0, pihalf) * twopi;
711 std::cout << "Energy=" << energy;
712 std::cout << " cos(theta)=" << m_rpsf_bins.costheta_lo(ic);
713 std::cout << " error=" << sum-1.0 << std::endl;
714 #endif
715
716 } // endfor: looped over cos(theta)
717
718 } // endfor: looped over energies
719
720 // Return
721 return;
722}
#define G_READ
Exception handler interface definition.
FITS binary table class definition.
FITS table float column class interface definition.
Integration class interface definition.
Fermi/LAT point spread function version 3 class definition.
Mathematical function definitions.
GChatter
Definition GTypemaps.hpp:33
@ SILENT
Definition GTypemaps.hpp:34
double norm(const GVector &vector)
Computes vector norm.
Definition GVector.cpp:932
double sum(const GVector &vector)
Computes vector sum.
Definition GVector.cpp:1012
FITS binary table class.
const std::string & extname(void) const
Return extension name.
Definition GFitsHDU.hpp:162
GFitsHeaderCard & card(const int &cardno)
Return header card.
Definition GFitsHDU.hpp:259
Abstract interface for FITS table column.
void number(const int &number)
Set number of elements in column.
virtual double real(const int &row, const int &inx=0) const =0
FITS table float column.
Abstract interface for FITS table.
GFitsTableCol * append(const GFitsTableCol &column)
Append column to the table.
FITS file class.
Definition GFits.hpp:63
GFitsHDU * append(const GFitsHDU &hdu)
Append HDU to FITS file.
Definition GFits.cpp:678
GIntegral class interface definition.
Definition GIntegral.hpp:46
double romberg(std::vector< double > bounds, const int &order=5)
Perform Romberg integration.
Abstract Fermi/LAT point spread function base class.
GLATResponseTable m_rpsf_bins
PSF energy and cos theta binning.
void free_members(void)
Delete class members.
void init_members(void)
Initialise class members.
const bool & front(void) const
Signal that point spread function is for front section.
int size(void) const
Return number of bins in point spread function.
GLATPsfBase & operator=(const GLATPsfBase &psf)
Assignment operator.
double m_min_ctheta
Minimum valid cos(theta)
double scale_factor(const double &energy) const
Return scale factor for energy (in MeV)
Fermi/LAT point spread function version 3 class.
Definition GLATPsfV3.hpp:51
static double base_fct(const double &u, const double &gamma)
Return point spread base function value.
GLATPsfV3 & operator=(const GLATPsfV3 &psf)
Assignment operator.
double integrate_psf(const double &energy, const int &index)
Integrates PSF for a specific set of parameters.
std::vector< double > m_ntail
PSF ntail parameter.
std::vector< double > m_gcore
PSF gcore parameter.
double psf(const double &offset, const double &logE, const double &ctheta)
Return point spread function value.
std::vector< double > m_stail
PSF stail parameter.
GLATPsfV3 * clone(void) const
Clone point spread function.
std::vector< double > m_score
PSF score parameter.
void init_members(void)
Initialise class members.
void clear(void)
Clear point spread function.
double eval_psf(const double &offset, const double &energy, const int &index)
Evaluate PSF for a specific set of parameters.
std::vector< double > m_gtail
PSF gtail parameter.
static double base_int(const double &u, const double &gamma)
Return approximation of point spread base function integral.
GLATPsfV3(void)
Void constructor.
Definition GLATPsfV3.cpp:61
std::string print(const GChatter &chatter=NORMAL) const
Print point spread function.
std::vector< double > m_ncore
PSF ncore parameter.
void normalize_psf(void)
Normalize PSF for all parameters.
void copy_members(const GLATPsfV3 &psf)
Copy class members.
void write(GFits &file) const
Write point spread function into FITS file.
virtual ~GLATPsfV3(void)
Destructor.
Definition GLATPsfV3.cpp:92
void read(const GFitsTable &table)
Read point spread function from FITS table.
void free_members(void)
Delete class members.
double costheta_lo(const int &inx) const
Return lower bin cos theta [.
void set(const double &logE, const double &ctheta)
Set indices and weighting for bi-linear interpolation of 2D array.
std::vector< double > energies(void) const
Return energies of 4 corners used for interpolation.
int index(const int &ie, const int &ic) const
Return table index.
void read(const GFitsTable &hdu)
Read response table from FITS table HDU.
const int & ncostheta(void) const
Return number of cosine theta bins in response table.
void write(GFitsTable &hdu) const
Write response table into FITS table.
std::vector< double > weights(void) const
Return weights of 4 corners used for interpolation.
const int & nenergies(void) const
Return number of energies in response table.
int size(void) const
Return number of bins in response table.
double energy(const int &ie) const
Return mean energy of bin (units: MeV)
std::vector< int > indices(void) const
Return indices of 4 corners used for interpolation.
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition GTools.cpp:508
const double pihalf
Definition GMath.hpp:38
const double deg2rad
Definition GMath.hpp:43
const double twopi
Definition GMath.hpp:36