ctools  2.0.0
 All Classes Namespaces Files Functions Variables Macros Pages
cttsmap.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * cttsmap - TS map calculation tool *
3  * ----------------------------------------------------------------------- *
4  * copyright (C) 2014-2022 by Michael Mayer *
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 cttsmap.hpp
23  * @brief TS map calculation tool interface implementation
24  * @author Michael Mayer
25  */
26 
27 /* __ Includes ___________________________________________________________ */
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 #include <cstdio>
32 #include "cttsmap.hpp"
33 #include "GTools.hpp"
34 
35 /* __ Method name definitions ____________________________________________ */
36 #define G_GET_PARAMETERS "cttsmap::get_parameters()"
37 
38 /* __ Debug definitions __________________________________________________ */
39 
40 /* __ Coding definitions _________________________________________________ */
41 
42 
43 /*==========================================================================
44  = =
45  = Constructors/destructors =
46  = =
47  ==========================================================================*/
48 
49 /***********************************************************************//**
50  * @brief Void constructor
51  *
52  * Constructs an empty cttsmap tool.
53  ***************************************************************************/
55 {
56  // Initialise members
57  init_members();
58 
59  // Return
60  return;
61 }
62 
63 
64 /***********************************************************************//**
65  * @brief Observations constructor
66  *
67  * param[in] obs Observation container.
68  *
69  * Constructs cttsmap tool from an observations container.
70  ***************************************************************************/
71 cttsmap::cttsmap(const GObservations& obs) :
72  ctlikelihood(CTTSMAP_NAME, VERSION, obs)
73 {
74  // Initialise members
75  init_members();
76 
77  // Return
78  return;
79 }
80 
81 
82 /***********************************************************************//**
83  * @brief Command line constructor
84  *
85  * @param[in] argc Number of arguments in command line.
86  * @param[in] argv Array of command line arguments.
87  *
88  * Constructs an instance of the cttsmap tool that will parse user parameters
89  * that are provided as command line arguments.
90  ***************************************************************************/
91 cttsmap::cttsmap(int argc, char *argv[]) :
92  ctlikelihood(CTTSMAP_NAME, VERSION, argc, argv)
93 {
94  // Initialise members
95  init_members();
96 
97  // Return
98  return;
99 }
100 
101 
102 /***********************************************************************//**
103  * @brief Copy constructor
104  *
105  * @param[in] app Application.
106  ***************************************************************************/
108 {
109  // Initialise members
110  init_members();
111 
112  // Copy members
113  copy_members(app);
114 
115  // Return
116  return;
117 }
118 
119 
120 /***********************************************************************//**
121  * @brief Destructor
122  ***************************************************************************/
124 {
125  // Free members
126  free_members();
127 
128  // Return
129  return;
130 }
131 
132 
133 /*==========================================================================
134  = =
135  = Operators =
136  = =
137  ==========================================================================*/
138 
139 /***********************************************************************//**
140  * @brief Assignment operator
141  *
142  * @param[in] app Application.
143  * @return Application.
144  ***************************************************************************/
146 {
147  // Execute only if object is not identical
148  if (this != &app) {
149 
150  // Copy base class members
151  this->ctlikelihood::operator=(app);
152 
153  // Free members
154  free_members();
155 
156  // Initialise members
157  init_members();
158 
159  // Copy members
160  copy_members(app);
161 
162  } // endif: object was not identical
163 
164  // Return this object
165  return *this;
166 }
167 
168 
169 /*==========================================================================
170  = =
171  = Public methods =
172  = =
173  ==========================================================================*/
174 
175 /***********************************************************************//**
176  * @brief Clear instance
177  ***************************************************************************/
178 void cttsmap::clear(void)
179 {
180  // Free members
181  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();
193  init_members();
194 
195  // Return
196  return;
197 }
198 
199 
200 /***********************************************************************//**
201  * @brief Computes the TS maps
202  *
203  * This method moves a source along a grid of coordinates and refits the
204  * given models including this additional source. The fit parameters of the
205  * source and its TS values are filled into respective position in the map.
206  ***************************************************************************/
208 {
209  // Get task parameters
210  get_parameters();
211 
212  // Set energy dispersion flags of all CTA observations and save old
213  // values in save_edisp vector
214  std::vector<bool> save_edisp = set_edisp(m_obs, m_apply_edisp);
215 
216  // Write input observation container into logger
217  log_observations(NORMAL, m_obs, "Input observation");
218 
219  // Write header
220  log_header1(TERSE, "Initialise TS map");
221 
222  // Get bins to be computed
223  // To split the computation on several jobs,
224  // the user is able to provide a subset of bins
225  // which should be computed
226  int binmin = (m_binmin == -1) ? 0 : m_binmin;
227  int binmax = (m_binmax == -1) ? m_tsmap.npix() : m_binmax;
228 
229  // Set optimizer logger
230  if (logExplicit()) {
231  static_cast<GOptimizerLM*>(&m_opt)->logger(&log);
232  }
233  else {
234  static_cast<GOptimizerLM*>(&m_opt)->logger(NULL);
235  }
236 
237  // Store initial models
238  GModels models_orig = m_obs.models();
239 
240  // Get model instance for further computations
241  GModels models = m_obs.models();
242 
243  // Remove test source
244  models.remove(m_srcname);
245 
246  // Fix spatial parameters if requested
247  if ((*this)["fix_spat"].boolean()) {
248 
249  // Loop over all models
250  for (int i = 0; i < models.size(); ++i) {
251 
252  // Continue only if model is skymodel
253  GModelSky* sky= dynamic_cast<GModelSky*>(models[i]);
254  if (sky != NULL) {
255 
256  // Fix all spatial parameters
257  GModelSpatial* spatial = sky->spatial();
258  for (int j = 0; j < spatial->size(); j++) {
259  (*spatial)[j].fix();
260  }
261 
262  } // endif: there was a sky model
263 
264  } // endfor: looped over models
265 
266  } // endif: spatial parameter should be fixed
267 
268  // Get likelihood of null hypothesis if not given before
269  if (m_logL0 == 0.0) {
270 
271  // Write header
272  log_header1(TERSE, "Compute NULL Hypothesis for TS computation");
273 
274  // Compute likelihood without the test source
275  m_obs.models(models);
276  m_obs.optimize(m_opt);
277  m_logL0 = -(m_opt.value());
278 
279  }
280 
281  // Write header
282  log_header1(TERSE, "Generate TS map");
283 
284  // Loop over grid positions
285  for (int i = binmin; i < binmax; ++i) {
286 
287  // Get the coordinate of current bin
288  GSkyDir bincentre = m_tsmap.inx2dir(i);
289 
290  // Header for verbose logging
291  log_header2(EXPLICIT, "Computing TS for bin number "+gammalib::str(i)+
292  " at "+bincentre.print());
293 
294  // Add test source at current bin position
295  (*m_testsource)["RA"].value(bincentre.ra_deg());
296  (*m_testsource)["DEC"].value(bincentre.dec_deg());
297  models.append(*m_testsource);
298 
299  // Assign models to observations
300  m_obs.models(models);
301 
302  // Make sure that no values are cached for test source
303  m_obs.remove_response_cache(m_srcname);
304 
305  // Optimize observation container
306  m_obs.optimize(m_opt);
307 
308  // Compute errors if necessary
309  if (m_errors) {
310  m_obs.errors(m_opt);
311  }
312 
313  // Get status of optimization
314  int status = m_opt.status();
315 
316  // Retrieve the Likelihood value
317  double logL1 = -(m_opt.value());
318 
319  // Compute TS value
320  double ts = 2.0 * (logL1 - m_logL0);
321 
322  // Log information
323  if (logExplicit()) {
324  log_value(EXPLICIT, "TS value", ts);
325  }
326  else if (logNormal()) {
327  log_value(NORMAL, "TS value (bin "+gammalib::str(i)+")",
328  gammalib::str(ts)+" ("+bincentre.print()+")");
329  }
330 
331  // Get test source model instance
332  GModels best_fit_model = m_obs.models();
333  GModel* testsource = best_fit_model[m_srcname];
334 
335  // Assign values to the maps
336  m_tsmap(i) = ts;
337 
338  // Extract fitted test source parameters
339  for (int j = 0; j < m_mapnames.size(); ++j) {
340 
341  // If map name start with "e_" then set the parameter error ...
342  if (m_mapnames[j].substr(0,2) == "e_") {
343 
344  // Get parameter name by removing the error prefix
345  std::string parname = m_mapnames[j].substr(2, m_mapnames[j].size());
346 
347  // Get parameter error
348  m_maps[j](i) = (*testsource)[parname].error();
349 
350  }
351 
352  // ... otherwise set the parameter value
353  else {
354  m_maps[j](i) = (*testsource)[m_mapnames[j]].value();
355  }
356 
357  } // endfor: looped over all maps
358 
359  // Set Fit status of the bin
360  m_statusmap(i) = status;
361 
362  // Remove model from container
363  models.remove(m_srcname);
364 
365  } // endfor: looped over grid positions
366 
367  // Bring models to initial state
368  m_obs.models(models_orig);
369 
370  // Restore energy dispersion flags of all CTA observations
371  restore_edisp(m_obs, save_edisp);
372 
373  // Optionally publish TS map
374  if (m_publish) {
375  publish();
376  }
377 
378  // Return
379  return;
380 }
381 
382 
383 /***********************************************************************//**
384  * @brief Save maps
385  *
386  * This method saves the TS map and additional maps into a FITS file.
387  ***************************************************************************/
388 void cttsmap::save(void)
389 {
390  // Write header
391  log_header1(TERSE, "Save TS map");
392 
393  // Save only if filename is valid and TS map is not empty
394  if ((*this)["outmap"].is_valid() && !m_tsmap.is_empty()) {
395 
396  // Get TS map filename
397  m_outmap = (*this)["outmap"].filename();
398 
399  // Create fits file
400  GFits fits;
401 
402  // Write the sky maps to the FITS file
403  m_tsmap.write(fits);
404  for (int i = 0; i < m_mapnames.size(); i++) {
405  m_maps[i].write(fits);
406  }
407 
408  // Set extension name for all maps
409  for (int i = 0; i < m_mapnames.size(); i++) {
410  fits[i+1]->extname(m_mapnames[i]);
411  }
412 
413  // Write Fit status map
414  m_statusmap.write(fits);
415  fits[fits.size()-1]->extname("STATUS MAP");
416 
417  // Stamp FITS file
418  stamp(fits);
419 
420  // Save FITS file
421  fits.saveto(m_outmap, clobber());
422 
423  } // endif: TS map filename was valid
424 
425  // Write into logger what has been done
426  std::string fname = (m_outmap.is_empty()) ? "NONE" : m_outmap.url();
427  if (m_tsmap.is_empty()) {
428  fname.append(" (TS map is empty, no file created)");
429  }
430  log_value(NORMAL, "TS map file", fname);
431 
432  // Return
433  return;
434 }
435 
436 
437 /***********************************************************************//**
438  * @brief Publish TS map
439  *
440  * @param[in] name TS map name.
441  ***************************************************************************/
442 void cttsmap::publish(const std::string& name)
443 {
444  // Write header into logger
445  log_header1(TERSE, "Publish TS map");
446 
447  // Set default name is user name is empty
448  std::string user_name(name);
449  if (user_name.empty()) {
450  user_name = CTTSMAP_NAME;
451  }
452 
453  // Write TS map name into logger
454  log_value(NORMAL, "TS map name", user_name);
455 
456  // Publish TS map
457  m_tsmap.publish(user_name);
458 
459  // Return
460  return;
461 }
462 
463 
464 /*==========================================================================
465  = =
466  = Private methods =
467  = =
468  ==========================================================================*/
469 
470 /***********************************************************************//**
471  * @brief Initialise class members
472  ***************************************************************************/
474 {
475  // Initialise members
476  m_srcname.clear();
477  m_outmap.clear();
478  m_apply_edisp = false;
479  m_publish = false;
480  m_errors = false;
481 
482  // Initialise protected members
483  m_binmin = -1;
484  m_binmax = -1;
485  m_logL0 = 0.0;
486  m_tsmap.clear();
487  m_statusmap.clear();
488  m_mapnames.clear();
489  m_maps.clear();
490  m_testsource = NULL;
491 
492  // Return
493  return;
494 }
495 
496 
497 /***********************************************************************//**
498  * @brief Copy class members
499  *
500  * @param[in] app Application.
501  ***************************************************************************/
503 {
504  // Copy attributes
505  m_srcname = app.m_srcname;
506  m_outmap = app.m_outmap;
508  m_publish = app.m_publish;
509  m_errors = app.m_errors;
510 
511  // Copy protected members
512  m_binmin = app.m_binmin;
513  m_binmax = app.m_binmax;
514  m_logL0 = app.m_logL0;
515  m_tsmap = app.m_tsmap;
516  m_statusmap = app.m_statusmap;
517  m_mapnames = app.m_mapnames;
518  m_maps = app.m_maps;
519 
520  // Clone protected members
521  m_testsource = (app.m_testsource != NULL) ? app.m_testsource->clone()
522  : NULL;
523 
524  // Return
525  return;
526 }
527 
528 
529 /***********************************************************************//**
530  * @brief Delete class members
531  ***************************************************************************/
533 {
534  // Free test source
535  if (m_testsource != NULL) {
536  delete m_testsource;
537  m_testsource = NULL;
538  }
539 
540  // Return
541  return;
542 }
543 
544 
545 /***********************************************************************//**
546  * @brief Get application parameters
547  *
548  * @exception GException::invalid_value
549  * Test source has no RA/DEC parameters.
550  *
551  * Get all task parameters from parameter file.
552  ***************************************************************************/
554 {
555  // Setup observations from "inobs" parameter
557 
558  // Set observation statistic
559  set_obs_statistic(gammalib::toupper((*this)["statistic"].string()));
560 
561  // Setup models from "inmodel" parameter
562  setup_models(m_obs, (*this)["srcname"].string());
563 
564  // Get name of test source
565  m_srcname = (*this)["srcname"].string();
566 
567  // Get model and store it as protected member. Note that the clone
568  // method will never return a NULL pointer, hence we do not need
569  // to check the pointer.
570  m_testsource = m_obs.models()[m_srcname]->clone();
571 
572  // Check if model has RA and DEC parameters which are necessary to
573  // continue
574  if (!m_testsource->has_par("RA") || !m_testsource->has_par("DEC")) {
575  std::string msg = "Source \""+m_srcname+"\" has no \"RA\" and "
576  "\"DEC\" parameters. Only sources with \"RA\" "
577  "and \"DEC\" parameters can be used as test "
578  "sources.";
579  throw GException::invalid_value(G_GET_PARAMETERS, msg);
580  }
581 
582  // Fix the spatial parameters of the test source
583  (*m_testsource)["RA"].fix();
584  (*m_testsource)["DEC"].fix();
585 
586  // Create sky map based on task parameters
587  GSkyMap map = create_map(m_obs);
588 
589  // Check if errors should be computed
590  m_errors = (*this)["errors"].boolean();
591 
592  // Initialise maps from user parameters
593  init_maps(map);
594 
595  // Read energy dispersion flag
596  m_apply_edisp = (*this)["edisp"].boolean();
597 
598  // Get optional splitting parameters
599  m_binmin = (*this)["binmin"].integer();
600  m_binmax = (*this)["binmax"].integer();
601  m_logL0 = (*this)["logL0"].real();
602  m_publish = (*this)["publish"].boolean();
603 
604  // Query other parameters
605  (*this)["fix_spat"].boolean();
606 
607  // If needed later, query output filename now
608  if (read_ahead()) {
609  (*this)["outmap"].query();
610  }
611 
612  // Write parameters into logger
613  log_parameters(TERSE);
614 
615  // Return
616  return;
617 }
618 
619 
620 /***********************************************************************//**
621  * @brief Initialise skymaps
622  *
623  * Initialises skymaps that will contain map information.
624  ***************************************************************************/
625 void cttsmap::init_maps(const GSkyMap& map)
626 {
627  // Initialise map information
628  m_tsmap.clear();
629 
630  // Create skymap
631  m_tsmap = GSkyMap(map);
632 
633  // Initialise map information
634  m_statusmap.clear();
635 
636  // Create status map and progress map
637  m_statusmap = GSkyMap(map);
638 
639  // Set status map to invalid value -1 to signal that bin wasn't computed yet
640  m_statusmap = -1.0;
641 
642  // Loop over all model parameters
643  for (int i = 0; i < m_testsource->size(); i++) {
644 
645  // Skip fixed parameters
646  if ((*m_testsource)[i].is_fixed()) {
647  continue;
648  }
649 
650  // Add sky map for free parameters. Note that push_back will
651  // create a copy.
652  m_maps.push_back(map);
653 
654  // Store parameter name
655  m_mapnames.push_back((*m_testsource)[i].name());
656 
657  // Add parameter errors if requested
658  if (m_errors) {
659 
660  // Add sky map for fit error of the free parameter
661  m_maps.push_back(map);
662 
663  // Store name of parameter error
664  m_mapnames.push_back("e_" + (*m_testsource)[i].name());
665 
666  } // endif: error calculation was requested
667 
668  } // endfor: looped over all model parameters
669 
670  // Return
671  return;
672 }
void get_parameters(void)
Get application parameters.
Definition: cttsmap.cpp:553
void init_members(void)
Initialise class members.
Definition: cttsmap.cpp:473
void clear(void)
Clear instance.
Definition: cttsmap.cpp:178
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 setup_models(GObservations &obs, const std::string &name="")
Setup model container.
Definition: ctool.cpp:545
#define CTTSMAP_NAME
Definition: cttsmap.hpp:34
void copy_members(const cttsmap &app)
Copy class members.
Definition: cttsmap.cpp:502
ctlikelihood & operator=(const ctlikelihood &app)
Assignment operator.
bool m_publish
Publish TS map?
Definition: cttsmap.hpp:87
GSkyMap create_map(const GObservations &obs)
Create a skymap from user parameters.
Definition: ctool.cpp:937
void init_members(void)
Initialise class members.
Definition: ctool.cpp:321
cttsmap(void)
Void constructor.
Definition: cttsmap.cpp:54
TS map calculation tool.
Definition: cttsmap.hpp:55
void save(void)
Save maps.
Definition: cttsmap.cpp:388
#define G_GET_PARAMETERS
Definition: cttsmap.cpp:36
std::vector< std::string > m_mapnames
Names of free parameters.
Definition: cttsmap.hpp:98
void process(void)
Computes the TS maps.
Definition: cttsmap.cpp:207
void set_obs_statistic(const std::string &statistic)
Set fit statistic for CTA observations.
void free_members(void)
Delete class members.
Definition: cttsmap.cpp:532
GSkyMap m_statusmap
Map of optimizer fit status.
Definition: cttsmap.hpp:97
GSkyMap m_tsmap
TS map.
Definition: cttsmap.hpp:96
cttsmap & operator=(const cttsmap &app)
Assignment operator.
Definition: cttsmap.cpp:145
TS map calculation tool interface implementation.
void log_parameters(const GChatter &chatter)
Log application parameters.
Definition: ctool.cpp:1208
void free_members(void)
Delete class members.
void free_members(void)
Delete class members.
bool m_errors
Compute and store parameter errors?
Definition: cttsmap.hpp:88
void free_members(void)
Delete class members.
Definition: ctool.cpp:357
bool m_apply_edisp
Apply energy dispersion?
Definition: cttsmap.hpp:86
double m_logL0
Likelihood value of null hypothesis.
Definition: cttsmap.hpp:93
void init_members(void)
Initialise class members.
std::vector< GSkyMap > m_maps
Sky maps for each free parameter.
Definition: cttsmap.hpp:99
const bool & read_ahead(void) const
Signal whether parameters should be read ahead.
Definition: ctool.hpp:177
int m_binmin
Map bin number from which computation should start.
Definition: cttsmap.hpp:91
GFilename m_outmap
Output TS map file name.
Definition: cttsmap.hpp:85
void restore_edisp(GObservations &obs, const std::vector< bool > &edisp) const
Restore energy dispersion flags of CTA observations.
Definition: ctool.cpp:1689
void init_maps(const GSkyMap &map)
Initialise skymaps.
Definition: cttsmap.cpp:625
std::vector< bool > set_edisp(GObservations &obs, const bool &edisp) const
Set energy dispersion to CTA observations.
Definition: ctool.cpp:1649
void init_members(void)
Initialise class members.
void publish(const std::string &name="")
Publish TS map.
Definition: cttsmap.cpp:442
virtual ~cttsmap(void)
Destructor.
Definition: cttsmap.cpp:123
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.
int m_binmax
Map bin number where map computation should end.
Definition: cttsmap.hpp:92
std::string m_srcname
Name of source which is moved around.
Definition: cttsmap.hpp:84
Base class for likelihood tools.
GModel * m_testsource
Pointer to test source for TS computation.
Definition: cttsmap.hpp:100
GOptimizerLM m_opt
Optimizer.