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