ctools  2.0.0
 All Classes Namespaces Files Functions Variables Macros Pages
ctprob.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * ctprob - Computes event probability for a given model *
3  * ----------------------------------------------------------------------- *
4  * copyright (C) 2017-2022 by Leonardo Di Venere *
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 ctprob.cpp
23  * @brief Event probability computation tool implementation
24  * @author Leonardo Di Venere
25  */
26 
27 /* __ Includes ___________________________________________________________ */
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 #include <cstdlib>
32 #include "ctprob.hpp"
33 #include "GTools.hpp"
34 
35 /* __ Method name definitions ____________________________________________ */
36 #define G_EVALUATE_PROB "ctprob::evaluate_probability(GCTAObservation*)"
37 
38 /* __ Debug definitions __________________________________________________ */
39 
40 /* __ Coding definitions _________________________________________________ */
41 
42 
43 /*==========================================================================
44  = =
45  = Constructors/destructors =
46  = =
47  ==========================================================================*/
48 
49 /***********************************************************************//**
50  * @brief Void constructor
51  ***************************************************************************/
53 {
54  // Initialise members
55  init_members();
56 
57  // Return
58  return;
59 }
60 
61 
62 /***********************************************************************//**
63  * @brief Observations constructor
64  *
65  * param[in] obs Observation container.
66  *
67  * Creates an instance of the class that is initialised using the information
68  * provided in an observation container.
69  ***************************************************************************/
70 ctprob::ctprob(const GObservations& obs) :
71  ctobservation(CTPROB_NAME, VERSION, obs)
72 {
73  // Initialise members
74  init_members();
75 
76  // Return
77  return;
78 }
79 
80 
81 
82 
83 /***********************************************************************//**
84  * @brief Command line constructor
85  *
86  * @param[in] argc Number of arguments in command line.
87  * @param[in] argv Array of command line arguments.
88  ***************************************************************************/
89 ctprob::ctprob(int argc, char *argv[]) :
90  ctobservation(CTPROB_NAME, VERSION, argc, argv)
91 {
92  // Initialise members
93  init_members();
94 
95  // Return
96  return;
97 }
98 
99 
100 /***********************************************************************//**
101  * @brief Copy constructor
102  *
103  * @param[in] app Application.
104  ***************************************************************************/
106 {
107  // Initialise members
108  init_members();
109 
110  // Copy members
111  copy_members(app);
112 
113  // Return
114  return;
115 }
116 
117 
118 /***********************************************************************//**
119  * @brief Destructor
120  ***************************************************************************/
122 {
123  // Free members
124  free_members();
125 
126  // Return
127  return;
128 }
129 
130 
131 /*==========================================================================
132  = =
133  = Operators =
134  = =
135  ==========================================================================*/
136 
137 /***********************************************************************//**
138  * @brief Assignment operator
139  *
140  * @param[in] app Application.
141  * @return Application.
142  ***************************************************************************/
144 {
145  // Execute only if object is not identical
146  if (this != &app) {
147 
148  // Copy base class members
149  this->ctobservation::operator=(app);
150 
151  // Free members
152  free_members();
153 
154  // Initialise members
155  init_members();
156 
157  // Copy members
158  copy_members(app);
159 
160  } // endif: object was not identical
161 
162  // Return this object
163  return *this;
164 }
165 
166 
167 /*==========================================================================
168  = =
169  = Public methods =
170  = =
171  ==========================================================================*/
172 
173 /***********************************************************************//**
174  * @brief Clear ctprob tool
175  *
176  * Clears ctprob tool.
177  ***************************************************************************/
178 void ctprob::clear(void)
179 {
180  // Free members
181  free_members();
183  this->ctool::free_members();
184 
185  // Clear base class (needed to conserve tool name and version)
186  this->GApplication::clear();
187 
188  // Initialise members
189  this->ctool::init_members();
191  init_members();
192 
193  // Write header into logger
194  log_header();
195 
196  // Return
197  return;
198 }
199 
200 
201 /***********************************************************************//**
202  * @brief Process the ctprob tool
203  *
204  * This method reads in the application parameters and loops over all
205  * unbinned observations to compute the probability for each event that it
206  * comes from one of the model components.
207  ***************************************************************************/
208 void ctprob::process(void)
209 {
210  // Get parameters
211  get_parameters();
212 
213  // Set energy dispersion flags of all CTA observations and save old
214  // values in save_edisp vector
215  std::vector<bool> save_edisp = set_edisp(m_obs, m_apply_edisp);
216 
217  // Write input observation container into logger
218  log_observations(NORMAL, m_obs, "Input observation");
219 
220  // Write header into logger
221  log_header1(TERSE, "Compute event probabilities");
222 
223  // Initialise counters
224  int n_observations = 0;
225 
226  // Loop over all unbinned CTA observations in the container
227  for (GCTAObservation* obs = first_unbinned_observation(); obs != NULL;
229 
230  // Increment counter
231  n_observations++;
232 
233  // Evaluate event probabilities
235 
236  } // endfor: looped over observations
237 
238  // If more than a single observation has been handled then make sure that
239  // an XML file will be used for storage
240  if (n_observations > 1) {
241  m_use_xml = true;
242  }
243 
244  // Write observation(s) into logger
245  log_observations(NORMAL, m_obs, "Output observation");
246 
247  // Restore energy dispersion flags of all CTA observations
248  restore_edisp(m_obs, save_edisp);
249 
250  // Optionally publish event list(s)
251  if ((*this)["publish"].boolean()) {
252  publish();
253  }
254 
255  // Return
256  return;
257 }
258 
259 
260 /***********************************************************************//**
261  * @brief Save the selected event list(s)
262  *
263  * This method saves the selected event list(s) into FITS file(s). There are
264  * two modes, depending on the m_use_xml flag.
265  *
266  * If m_use_xml is true, all selected event list(s) will be saved into FITS
267  * files, where the output filenames are constructued from the input
268  * filenames by prepending the m_prefix string to name. Any path information
269  * will be stripped form the input name, hence event files will be written
270  * into the local working directory (unless some path information is present
271  * in the prefix). In addition, an XML file will be created that gathers
272  * the filename information for the selected event list(s). If an XML file
273  * was present on input, all metadata information will be copied from this
274  * input file.
275  *
276  * If m_use_xml is false, the selected event list will be saved into a FITS
277  * file.
278  ***************************************************************************/
279 void ctprob::save(void)
280 {
281  // Write header into logger
282  log_header1(TERSE, gammalib::number("Save event list", m_obs.size()));
283 
284  // Case A: Save event file(s) and XML metadata information
285  if (m_use_xml) {
286  save_events_xml();
287  }
288 
289  // Case B: Save event file as FITS file
290  else {
292  }
293 
294  // Return
295  return;
296 }
297 
298 
299 /***********************************************************************//**
300  * @brief Publish event lists
301  *
302  * @param[in] name Event list name.
303  ***************************************************************************/
304 void ctprob::publish(const std::string& name)
305 {
306  // Write header into logger
307  log_header1(TERSE, gammalib::number("Publish event list", m_obs.size()));
308 
309  // Loop over all observation in the container
310  for (int i = 0; i < m_obs.size(); ++i) {
311 
312  // Get CTA observation
313  GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]);
314 
315  // Handle only CTA observations
316  if (obs != NULL) {
317 
318  // Continue only if there is an event list
319  if (obs->events()->size() != 0) {
320 
321  // Set default name if user name is empty
322  std::string user_name(name);
323  if (user_name.empty()) {
324  user_name = CTPROB_NAME;
325  }
326 
327  // If there are several event lists then add an index
328  if (m_use_xml) {
329  user_name += gammalib::str(i);
330  }
331 
332  // Write event list name into logger
333  log_value(NORMAL, "Event list name", user_name);
334 
335  // Write events into in-memory FITS file
336  GFits fits;
337  obs->write(fits);
338 
339  // Publish
340  fits.publish(gammalib::extname_cta_events, user_name);
341 
342  } // endif: there were events
343 
344  } // endif: observation was a CTA observation
345 
346  } // endfor: looped over observations
347 
348  // Return
349  return;
350 }
351 
352 
353 /*==========================================================================
354  = =
355  = Private methods =
356  = =
357  ==========================================================================*/
358 
359 /***********************************************************************//**
360  * @brief Initialise class members
361  ***************************************************************************/
363 {
364  // Initialise parameters
365  m_apply_edisp = false;
366  m_publish = false;
367  m_chatter = static_cast<GChatter>(2);
368 
369  // Return
370  return;
371 }
372 
373 
374 /***********************************************************************//**
375  * @brief Copy class members
376  *
377  * @param[in] app Application.
378  ***************************************************************************/
380 {
381  // Copy parameters
383  m_publish = app.m_publish;
384  m_chatter = app.m_chatter;
385 
386  // Return
387  return;
388 }
389 
390 
391 /***********************************************************************//**
392  * @brief Delete class members
393  ***************************************************************************/
395 {
396  // Return
397  return;
398 }
399 
400 
401 /***********************************************************************//**
402  * @brief Get application parameters
403  *
404  * Get all application parameters by either querying the parameters or by
405  * retrieving the parameters for the parameter file.
406  ***************************************************************************/
408 {
409  // Setup observations from "inobs" parameter. Request response
410  // information, accept event lists but do not accept counts cubes.
411  setup_observations(m_obs, true, true, false);
412 
413  // Read model definition file if required
414  if (m_obs.models().size() == 0) {
415 
416  // Get model filename
417  std::string inmodel = (*this)["inmodel"].filename();
418 
419  // Load models from file
420  m_obs.models(inmodel);
421 
422  } // endif: there were no models
423 
424  // Get energy dispersion flag parameters
425  m_apply_edisp = (*this)["edisp"].boolean();
426 
427  // Get remaining parameters
428  m_publish = (*this)["publish"].boolean();
429  m_chatter = static_cast<GChatter>((*this)["chatter"].integer());
430 
431  // If needed later, query output filename and prefix now
432  if (read_ahead()) {
433  (*this)["outobs"].query();
434  (*this)["prefix"].query();
435  }
436 
437  // Write parameters into logger
438  log_parameters(TERSE);
439 
440  // Return
441  return;
442 }
443 
444 
445 /***********************************************************************//**
446  * @brief Evaluate probability for events
447  *
448  * @param[in,out] obs CTA observation.
449  *
450  * @exception GException::invalid_value
451  * Observation does not contain an event list.
452  *
453  * Computes for all events the probability that an event arises from a
454  * specific model component. The computation is done by by evaluating the
455  * differential event probability for a given model and normalizing these
456  * probabilities so that the sum of the probabilities for all model
457  * components is unity for each event.
458  *
459  * The method appends for each model component a single precision column to
460  * the event list that contains the event probabilities. The name of the
461  * column is build from the model name prefixed with `PROB_`.
462  ***************************************************************************/
463 void ctprob::evaluate_probability(GCTAObservation* obs)
464 {
465  // Write header into logger
466  log_header3(NORMAL, "Evaluate events probabilities");
467 
468  // Make sure that the observation holds a CTA event list. If this
469  // is not the case then throw an exception.
470  GCTAEventList* events = dynamic_cast<GCTAEventList*>(const_cast<GEvents*>
471  (obs->events()));
472  if (events == NULL) {
473  std::string msg = "CTA Observation does not contain an event list. An "
474  "event list is needed to compute the event "
475  "probabilities.";
476  throw GException::invalid_value(G_EVALUATE_PROB, msg);
477  }
478 
479  // Continue only if there are model components
480  int nmodels = m_obs.models().size();
481  if (nmodels > 0) {
482 
483  // Allocate single precision FITS table columns for all model components
484  std::vector<GFitsTableFloatCol*> columns;
485  for (int k = 0; k < nmodels; ++k) {
486  const std::string colname = "PROB_" + m_obs.models()[k] ->name();
487  GFitsTableFloatCol* col =
488  new GFitsTableFloatCol(colname, events->size());
489  columns.push_back(col);
490  }
491 
492  // Loop over all events in the event list
493  for (int i = 0; i < events->size(); ++i) {
494 
495  // Initialise total probability
496  double total = 0.0;
497 
498  // Get point to event
499  const GEvent* event = (*events)[i];
500 
501  // Initialise probability vector
502  std::vector<double> probabilities(nmodels, 0.0);
503 
504  // Loop over models
505  for (int k = 0; k < nmodels; ++k) {
506  double value = m_obs.models()[k]->eval(*event, *obs);
507  probabilities[k] = value;
508  total += value;
509  }
510 
511  // Normalize probabilities to unity
512  if (total > 0.0) {
513  for (int k = 0; k < nmodels; ++k) {
514  probabilities[k] /= total;
515  }
516  }
517 
518  // Store probabilities in FITS columns
519  for (int k = 0; k < nmodels; ++k) {
520  (*(columns[k]))(i) = probabilities[k];
521  }
522 
523  } // endfor: looped over all events
524 
525  // Append columns to event list
526  for (int k = 0; k < nmodels; ++k) {
527  events->append_column(*columns[k]);
528  }
529 
530  } // endif: there were model components
531 
532  // Return
533  return;
534 }
void copy_members(const ctprob &app)
Copy class members.
Definition: ctprob.cpp:379
void clear(void)
Clear ctprob tool.
Definition: ctprob.cpp:178
Event probability computation tool.
Definition: ctprob.hpp:46
void setup_observations(GObservations &obs, const bool &response=true, const bool &list=true, const bool &cube=true)
Setup observation container.
Definition: ctool.cpp:431
#define G_EVALUATE_PROB
Definition: ctprob.cpp:36
bool m_publish
Publish event list?
Definition: ctprob.hpp:75
void init_members(void)
Initialise class members.
Definition: ctprob.cpp:362
void init_members(void)
Initialise class members.
Definition: ctool.cpp:321
const GObservations & obs(void) const
Return observation container.
GCTAObservation * next_unbinned_observation(void)
Return next unbinned CTA observation.
ctprob(void)
Void constructor.
Definition: ctprob.cpp:52
void free_members(void)
Delete class members.
Definition: ctprob.cpp:394
bool m_apply_edisp
Apply energy dispersion?
Definition: ctprob.hpp:74
#define CTPROB_NAME
Definition: ctprob.hpp:38
void get_parameters(void)
Get application parameters.
Definition: ctprob.cpp:407
void log_parameters(const GChatter &chatter)
Log application parameters.
Definition: ctool.cpp:1208
Base class for observation tools.
void save_events_fits(void)
Save event list in FITS format.
void evaluate_probability(GCTAObservation *obs)
Evaluate probability for events.
Definition: ctprob.cpp:463
void free_members(void)
Delete class members.
Event probability computation tool interface definition.
void save(void)
Save the selected event list(s)
Definition: ctprob.cpp:279
void free_members(void)
Delete class members.
Definition: ctool.cpp:357
void init_members(void)
Initialise class members.
virtual ~ctprob(void)
Destructor.
Definition: ctprob.cpp:121
GCTAObservation * first_unbinned_observation(void)
Return first unbinned CTA observation.
ctprob & operator=(const ctprob &app)
Assignment operator.
Definition: ctprob.cpp:143
GChatter m_chatter
Chattiness.
Definition: ctprob.hpp:76
ctobservation & operator=(const ctobservation &app)
Assignment operator.
const bool & read_ahead(void) const
Signal whether parameters should be read ahead.
Definition: ctool.hpp:177
void restore_edisp(GObservations &obs, const std::vector< bool > &edisp) const
Restore energy dispersion flags of CTA observations.
Definition: ctool.cpp:1689
std::vector< bool > set_edisp(GObservations &obs, const bool &edisp) const
Set energy dispersion to CTA observations.
Definition: ctool.cpp:1649
void process(void)
Process the ctprob tool.
Definition: ctprob.cpp:208
void publish(const std::string &name="")
Publish event lists.
Definition: ctprob.cpp:304
bool m_use_xml
Use XML file instead of FITS file for observations.
Definition: ctool.hpp:162
void log_observations(const GChatter &chatter, const GObservations &obs, const std::string &what="Observation")
Log observation container.
Definition: ctool.cpp:1251
GObservations m_obs
Observation container.
void save_events_xml(void)
Save event list(s) in XML format.