ctools 2.1.0
Loading...
Searching...
No Matches
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
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 ***************************************************************************/
71ctphase::ctphase(const GObservations& obs) :
72 ctobservation(CTPHASE_NAME, VERSION, obs)
73{
74 // Initialise 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 ***************************************************************************/
90ctphase::ctphase(int argc, char *argv[]) :
91 ctobservation(CTPHASE_NAME, VERSION, argc, argv)
92{
93 // Initialise 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 ***************************************************************************/
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
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
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 ***************************************************************************/
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) {
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 ***************************************************************************/
298void 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 ***************************************************************************/
503void 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}
Base class for observation tools.
void free_members(void)
Delete class members.
ctobservation & operator=(const ctobservation &app)
Assignment operator.
GCTAObservation * next_unbinned_observation(void)
Return next unbinned CTA observation.
GObservations m_obs
Observation container.
GCTAObservation * first_unbinned_observation(void)
Return first unbinned CTA observation.
void save_events_fits(void)
Save event list in FITS format.
const GObservations & obs(void) const
Return observation container.
void save_events_xml(void)
Save event list(s) in XML format.
void init_members(void)
Initialise class members.
bool m_use_xml
Use XML file instead of FITS file for observations.
Definition ctool.hpp:162
void free_members(void)
Delete class members.
Definition ctool.cpp:357
void log_observations(const GChatter &chatter, const GObservations &obs, const std::string &what="Observation")
Log observation container.
Definition ctool.cpp:1251
const bool & read_ahead(void) const
Signal whether parameters should be read ahead.
Definition ctool.hpp:177
void log_parameters(const GChatter &chatter)
Log application parameters.
Definition ctool.cpp:1208
void init_members(void)
Initialise class members.
Definition ctool.cpp:321
void setup_observations(GObservations &obs, const bool &response=true, const bool &list=true, const bool &cube=true)
Setup observation container.
Definition ctool.cpp:431
Event phase computation tool.
Definition ctphase.hpp:48
ctphase & operator=(const ctphase &app)
Assignment operator.
Definition ctphase.cpp:144
void phase_events(GCTAObservation *obs)
Compute event phase for an observation.
Definition ctphase.cpp:503
void copy_members(const ctphase &app)
Copy class members.
Definition ctphase.cpp:371
void publish(const std::string &name="")
Publish event lists.
Definition ctphase.cpp:298
void process(void)
Process the ctprob tool.
Definition ctphase.cpp:209
virtual ~ctphase(void)
Destructor.
Definition ctphase.cpp:122
void get_parameters(void)
Get application parameters.
Definition ctphase.cpp:397
ctphase(void)
Void constructor.
Definition ctphase.cpp:53
void init_members(void)
Initialise class members.
Definition ctphase.cpp:356
void save(void)
Save the output event list(s)
Definition ctphase.cpp:273
void free_members(void)
Delete class members.
Definition ctphase.cpp:384
GModelTemporalPhaseCurve m_phase
Phase curve model.
Definition ctphase.hpp:76
void clear(void)
Clear ctphase tool.
Definition ctphase.cpp:179
#define G_GET_PARAMETERS
Definition ctbin.cpp:42
#define G_PHASE_EVENTS
Definition ctphase.cpp:37
Event phase computation tool interface definition.
#define CTPHASE_NAME
Definition ctphase.hpp:38