GammaLib  2.1.0.dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
GCTAAeffPerfTable.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * GCTAAeffPerfTable.hpp - CTA performance table effective area 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 GCTAAeffPerfTable.hpp
23  * @brief CTA performance table effective area class definition
24  * @author Juergen Knoedlseder
25  */
26 
27 /* __ Includes ___________________________________________________________ */
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 #include <cstdio> // std::fopen, std::fgets, and std::fclose
32 #include "GException.hpp"
33 #include "GTools.hpp"
34 #include "GMath.hpp"
35 #include "GFitsTable.hpp"
36 #include "GCTAAeffPerfTable.hpp"
37 
38 /* __ Method name definitions ____________________________________________ */
39 #define G_LOAD "GCTAAeffPerfTable::load(std::string&)"
40 
41 /* __ Macros _____________________________________________________________ */
42 
43 /* __ Coding definitions _________________________________________________ */
44 
45 /* __ Debug definitions __________________________________________________ */
46 
47 /* __ Constants __________________________________________________________ */
48 
49 
50 /*==========================================================================
51  = =
52  = Constructors/destructors =
53  = =
54  ==========================================================================*/
55 
56 /***********************************************************************//**
57  * @brief Void constructor
58  ***************************************************************************/
60 {
61  // Initialise class members
62  init_members();
63 
64  // Return
65  return;
66 }
67 
68 
69 /***********************************************************************//**
70  * @brief File constructor
71  *
72  * @param[in] filename Performance table file name.
73  *
74  * Construct instance by loading the effective area information from an
75  * ASCII performance table.
76  ***************************************************************************/
78 {
79  // Initialise class members
80  init_members();
81 
82  // Load effective area from file
83  load(filename);
84 
85  // Return
86  return;
87 }
88 
89 
90 /***********************************************************************//**
91  * @brief Copy constructor
92  *
93  * @param[in] aeff Effective area.
94  ***************************************************************************/
96 {
97  // Initialise class members
98  init_members();
99 
100  // Copy members
101  copy_members(aeff);
102 
103  // Return
104  return;
105 }
106 
107 
108 /***********************************************************************//**
109  * @brief Destructor
110  ***************************************************************************/
112 {
113  // Free members
114  free_members();
115 
116  // Return
117  return;
118 }
119 
120 
121 /*==========================================================================
122  = =
123  = Operators =
124  = =
125  ==========================================================================*/
126 
127 /***********************************************************************//**
128  * @brief Assignment operator
129  *
130  * @param[in] aeff Effective area.
131  * @return Effective area.
132  ***************************************************************************/
134 {
135  // Execute only if object is not identical
136  if (this != &aeff) {
137 
138  // Copy base class members
139  this->GCTAAeff::operator=(aeff);
140 
141  // Free members
142  free_members();
143 
144  // Initialise private members
145  init_members();
146 
147  // Copy members
148  copy_members(aeff);
149 
150  } // endif: object was not identical
151 
152  // Return this object
153  return *this;
154 }
155 
156 
157 /***********************************************************************//**
158  * @brief Return effective area in units of cm2
159  *
160  * @param[in] logE Log10 of the true photon energy (TeV).
161  * @param[in] theta Offset angle in camera system (rad).
162  * @param[in] phi Azimuth angle in camera system (rad). Not used.
163  * @param[in] zenith Zenith angle in Earth system (rad). Not used.
164  * @param[in] azimuth Azimuth angle in Earth system (rad). Not used.
165  * @param[in] etrue Use true energy (true/false). Not used.
166  *
167  * Returns the effective area in units of cm2 for a given energy and
168  * offset angle. The effective area is linearily interpolated in
169  * log10(energy). The method assures that the effective area value never
170  * becomes negative.
171  *
172  * Outside the energy range that is covered by the performance table the
173  * effective area will be set to zero.
174  ***************************************************************************/
175 double GCTAAeffPerfTable::operator()(const double& logE,
176  const double& theta,
177  const double& phi,
178  const double& zenith,
179  const double& azimuth,
180  const bool& etrue) const
181 {
182  // Initialise effective area
183  double aeff = 0.0;
184 
185  // Continue only if logE is in validity range
186  if ((logE >= m_logE_min) && (logE <= m_logE_max)) {
187 
188  // Get effective area value in cm2
189  aeff = m_logE.interpolate(logE, m_aeff);
190 
191  // Make sure that effective area is not negative
192  if (aeff < 0.0) {
193  aeff = 0.0;
194  }
195 
196  // Optionally add in Gaussian offset angle dependence
197  if (m_sigma != 0.0) {
198  double offset = theta * gammalib::rad2deg;
199  double arg = offset * offset / m_sigma;
200  double scale = std::exp(-0.5 * arg * arg);
201  aeff *= scale;
202  }
203 
204  } // endif: logE in validity range
205 
206  // Return effective area value
207  return aeff;
208 }
209 
210 
211 /*==========================================================================
212  = =
213  = Public methods =
214  = =
215  ==========================================================================*/
216 
217 /***********************************************************************//**
218  * @brief Clear instance
219  *
220  * This method properly resets the object to an initial state.
221  ***************************************************************************/
223 {
224  // Free class members (base and derived classes, derived class first)
225  free_members();
226  this->GCTAAeff::free_members();
227 
228  // Initialise members
229  this->GCTAAeff::init_members();
230  init_members();
231 
232  // Return
233  return;
234 }
235 
236 
237 /***********************************************************************//**
238  * @brief Clone instance
239  *
240  * @return Deep copy of effective area instance.
241  ***************************************************************************/
243 {
244  return new GCTAAeffPerfTable(*this);
245 }
246 
247 
248 /***********************************************************************//**
249  * @brief Load effective area from performance table
250  *
251  * @param[in] filename Performance table file name.
252  *
253  * @exception GException::file_error
254  * File could not be opened for read access.
255  *
256  * This method loads the effective area information from an ASCII
257  * performance table.
258  ***************************************************************************/
259 void GCTAAeffPerfTable::load(const GFilename& filename)
260 {
261  // Clear arrays
262  m_logE.clear();
263  m_aeff.clear();
264 
265  // Allocate line buffer
266  const int n = 1000;
267  char line[n];
268 
269  // Open performance table readonly
270  FILE* fptr = std::fopen(filename.url().c_str(), "r");
271  if (fptr == NULL) {
272  std::string msg = "Effective area file \""+filename.url()+"\" not "
273  "found or readable. Please specify a valid and "
274  "readable effective area file.";
275  throw GException::file_error(G_LOAD, msg);
276  }
277 
278  // Read lines
279  while (std::fgets(line, n, fptr) != NULL) {
280 
281  // Split line in elements. Strip empty elements from vector.
282  std::vector<std::string> elements = gammalib::split(line, " ");
283  for (int i = elements.size()-1; i >= 0; i--) {
284  if (gammalib::strip_whitespace(elements[i]).length() == 0) {
285  elements.erase(elements.begin()+i);
286  }
287  }
288 
289  // Skip header
290  if (elements[0].find("log(E)") != std::string::npos) {
291  continue;
292  }
293 
294  // Break loop if end of data table has been reached
295  if (elements[0].find("----------") != std::string::npos) {
296  break;
297  }
298 
299  // Push elements in node array and vector
300  m_logE.append(gammalib::todouble(elements[0]));
301  m_aeff.push_back(gammalib::todouble(elements[1])*10000.0);
302 
303  } // endwhile: looped over lines
304 
305  // Close file
306  std::fclose(fptr);
307 
308  // Store filename
310 
311  // Set the energy boundaries
312  set_boundaries();
313 
314  // Return
315  return;
316 }
317 
318 
319 /***********************************************************************//**
320  * @brief Return maximum effective area at a given energy
321  *
322  * @param[in] logE Log10 of the true photon energy (TeV).
323  * @param[in] zenith Zenith angle in Earth system (rad). Not used in this method.
324  * @param[in] azimuth Azimuth angle in Earth system (rad). Not used in this method.
325  * @param[in] etrue Use true energy (true/false). Not used.
326  * @return Maximum effective area (cm2).
327  ***************************************************************************/
328 double GCTAAeffPerfTable::max(const double& logE,
329  const double& zenith,
330  const double& azimuth,
331  const bool& etrue) const
332 {
333  // Get effective area value in cm2
334  double aeff_max = m_logE.interpolate(logE, m_aeff);
335 
336  // Make sure that effective area is not negative
337  if (aeff_max < 0.0) {
338  aeff_max = 0.0;
339  }
340 
341  // Return result
342  return aeff_max;
343 }
344 
345 
346 /***********************************************************************//**
347  * @brief Print effective area information
348  *
349  * @param[in] chatter Chattiness.
350  * @return String containing effective area information.
351  ***************************************************************************/
352 std::string GCTAAeffPerfTable::print(const GChatter& chatter) const
353 {
354  // Initialise result string
355  std::string result;
356 
357  // Continue only if chatter is not silent
358  if (chatter != SILENT) {
359 
360  // Append header
361  result.append("=== GCTAAeffPerfTable ===");
362 
363  // Append information
364  result.append("\n"+gammalib::parformat("Filename")+m_filename);
365  result.append("\n"+gammalib::parformat("Number of energy bins") +
366  gammalib::str(size()));
367  result.append("\n"+gammalib::parformat("Energy range"));
368  result.append(m_ebounds.emin().print() + " - " +
369  m_ebounds.emax().print());
370 
371  // Append offset angle dependence
372  if (m_sigma == 0) {
373  result.append("\n"+gammalib::parformat("Offset angle dependence") +
374  "none");
375  }
376  else {
377  std::string txt = "Fixed sigma=" + gammalib::str(m_sigma);
378  result.append("\n"+gammalib::parformat("Offset angle dependence") +
379  txt);
380  }
381 
382  } // endif: chatter was not silent
383 
384  // Return result
385  return result;
386 }
387 
388 
389 /*==========================================================================
390  = =
391  = Private methods =
392  = =
393  ==========================================================================*/
394 
395 /***********************************************************************//**
396  * @brief Initialise class members
397  ***************************************************************************/
399 {
400  // Initialise members
401  m_filename.clear();
402  m_logE.clear();
403  m_aeff.clear();
404  m_ebounds.clear();
405  m_sigma = 3.0;
406  m_logE_min = 0.0;
407  m_logE_max = 0.0;
408 
409  // Return
410  return;
411 }
412 
413 
414 /***********************************************************************//**
415  * @brief Copy class members
416  *
417  * @param[in] aeff Effective area.
418  ***************************************************************************/
420 {
421  // Copy members
422  m_filename = aeff.m_filename;
423  m_logE = aeff.m_logE;
424  m_aeff = aeff.m_aeff;
425  m_ebounds = aeff.m_ebounds;
426  m_sigma = aeff.m_sigma;
427  m_logE_min = aeff.m_logE_min;
428  m_logE_max = aeff.m_logE_max;
429 
430  // Return
431  return;
432 }
433 
434 
435 /***********************************************************************//**
436  * @brief Delete class members
437  ***************************************************************************/
439 {
440  // Return
441  return;
442 }
443 
444 
445 /***********************************************************************//**
446  * @brief Set effective area boundaries
447  *
448  * Sets the data members m_ebounds, m_logE_min and m_logE_max that define
449  * the validity range of the effective area.
450  ***************************************************************************/
452 {
453  // Clear energy boundaries
454  m_ebounds.clear();
455 
456  // Set log10 of minimum and maximum energies. Since the energy values are
457  // given at the bin centre we subtract half of the distance to the second
458  // bin from the minimum energy and we add half of the distance to the before
459  // last bin to the maximum energy
460  m_logE_min = m_logE[0] - 0.5*(m_logE[1] - m_logE[0]);
461  m_logE_max = m_logE[m_logE.size()-1] + 0.5*(m_logE[m_logE.size()-1] -
462  m_logE[m_logE.size()-2]);
463 
464  // Set energy boundaries
465  GEnergy emin;
466  GEnergy emax;
467  emin.log10TeV(m_logE_min);
468  emax.log10TeV(m_logE_max);
469  m_ebounds.append(emin, emax);
470 
471  // Return
472  return;
473 }
void load(const GFilename &filename)
Load effective area from performance table.
int size(void) const
Return number of nodes in node array.
Definition: GNodeArray.hpp:192
GCTAAeffPerfTable & operator=(const GCTAAeffPerfTable &aeff)
Assignment operator.
double operator()(const double &logE, const double &theta=0.0, const double &phi=0.0, const double &zenith=0.0, const double &azimuth=0.0, const bool &etrue=true) const
Return effective area in units of cm2.
CTA performance table effective area class.
GEbounds m_ebounds
Energy boundaries.
double m_logE_min
Minimum logE (log10(E/TeV))
void set_boundaries(void)
Set effective area boundaries.
void free_members(void)
Delete class members.
std::string print(const GChatter &chatter=NORMAL) const
Print effective area information.
void append(const GEnergy &emin, const GEnergy &emax)
Append energy interval.
Definition: GEbounds.cpp:301
GNodeArray m_logE
log(E) nodes for Aeff interpolation
double m_logE_max
Maximum logE (log10(E/TeV))
void clear(void)
Clear node array.
Definition: GNodeArray.cpp:235
virtual ~GCTAAeffPerfTable(void)
Destructor.
GCTAAeffPerfTable * clone(void) const
Clone instance.
double log10TeV(void) const
Return log10 of energy in TeV.
Definition: GEnergy.cpp:457
std::vector< std::string > split(const std::string &s, const std::string &sep)
Split string.
Definition: GTools.cpp:983
Gammalib tools definition.
GCTAAeff & operator=(const GCTAAeff &aeff)
Assignment operator.
Definition: GCTAAeff.cpp:106
void copy_members(const GCTAAeffPerfTable &aeff)
Copy class members.
double max(const double &logE, const double &zenith, const double &azimuth, const bool &etrue=true) const
Return maximum effective area at a given energy.
GFilename filename(void) const
Return filename.
std::string strip_whitespace(const std::string &arg)
Strip leading and trailing whitespace from string.
Definition: GTools.cpp:80
void free_members(void)
Delete class members.
Definition: GCTAAeff.cpp:164
#define G_LOAD
CTA performance table effective area class definition.
double m_sigma
Sigma for offset angle computation (0=none)
std::string print(const GChatter &chatter=NORMAL) const
Print energy.
Definition: GEnergy.cpp:748
GFilename m_filename
Name of Aeff response file.
Filename class.
Definition: GFilename.hpp:62
const GEnergy & emin(void) const
Return minimum energy of all intervals.
Definition: GEbounds.hpp:187
void clear(void)
Clear instance.
void init_members(void)
Initialise class members.
Definition: GCTAAeff.cpp:142
void init_members(void)
Initialise class members.
double interpolate(const double &value, const std::vector< double > &vector) const
Interpolate value.
Definition: GNodeArray.cpp:536
GChatter
Definition: GTypemaps.hpp:33
GCTAAeffPerfTable(void)
Void constructor.
void clear(void)
Clear energy boundaries.
Definition: GEbounds.cpp:268
Abstract base class for the CTA effective area.
Definition: GCTAAeff.hpp:54
std::vector< double > m_aeff
Effective area in cm2.
std::string url(void) const
Return Uniform Resource Locator (URL)
Definition: GFilename.hpp:189
void clear(void)
Clear file name.
Definition: GFilename.cpp:188
Exception handler interface definition.
GVector exp(const GVector &vector)
Computes exponential of vector elements.
Definition: GVector.cpp:1232
const GEnergy & emax(void) const
Return maximum energy of all intervals.
Definition: GEbounds.hpp:199
const double rad2deg
Definition: GMath.hpp:44
std::string parformat(const std::string &s, const int &indent=0)
Convert string in parameter format.
Definition: GTools.cpp:1143
void append(const double &node)
Append one node to array.
Definition: GNodeArray.cpp:351
int size(void) const
Return number of node energies in response.
Mathematical function definitions.
double todouble(const std::string &arg)
Convert string into double precision value.
Definition: GTools.cpp:926
Class that handles energies in a unit independent way.
Definition: GEnergy.hpp:48
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition: GTools.cpp:489
FITS table abstract base class interface definition.