ctools 2.2.0.dev
Loading...
Searching...
No Matches
ctulimit.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * ctulimit - Upper limit calculation tool *
3 * ----------------------------------------------------------------------- *
4 * copyright (C) 2015-2025 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 ctulimit.hpp
23 * @brief Upper limit 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 "ctulimit.hpp"
33#include "GTools.hpp"
34#include "GOptimizer.hpp"
35
36/* __ Method name definitions ____________________________________________ */
37#define G_GET_MODEL_PARAMETER "ctulimit::get_model_parameter()"
38#define G_GET_PARAMETER_BRACKETS "ctulimit::get_parameter_brackets(double&, "\
39 "double&)"
40#define G_UL_BISECTION "ctulimit::ul_bisection(double&, double&)"
41
42/* __ Debug definitions __________________________________________________ */
43
44/* __ Coding definitions _________________________________________________ */
45
46
47/*==========================================================================
48 = =
49 = Constructors/destructors =
50 = =
51 ==========================================================================*/
52
53/***********************************************************************//**
54 * @brief Void constructor
55 *
56 * Constructs an empty ctulimit tool.
57 ***************************************************************************/
59{
60 // Initialise members
62
63 // Return
64 return;
65}
66
67
68/***********************************************************************//**
69 * @brief Observations constructor
70 *
71 * param[in] obs Observation container.
72 *
73 * Constructs ctulimit tool from an observations container.
74 ***************************************************************************/
75ctulimit::ctulimit(const GObservations& obs) :
76 ctlikelihood(CTULIMIT_NAME, VERSION, obs)
77{
78 // Initialise members
80
81 // Return
82 return;
83}
84
85
86
87/***********************************************************************//**
88 * @brief Command line constructor
89 *
90 * @param[in] argc Number of arguments in command line.
91 * @param[in] argv Array of command line arguments.
92 *
93 * Constructs an instance of the ctulimit tool that will parse user
94 * parameters that are provided as command line arguments.
95 ***************************************************************************/
96ctulimit::ctulimit(int argc, char *argv[]) :
97 ctlikelihood(CTULIMIT_NAME, VERSION, argc, argv)
98{
99 // Initialise members
100 init_members();
101
102 // Return
103 return;
104}
105
106
107/***********************************************************************//**
108 * @brief Copy constructor
109 *
110 * @param[in] app Application.
111 *
112 * Constructs an instance of the ctulimit tool by copying information from
113 * another ctulimit tool.
114 ***************************************************************************/
116{
117 // Initialise members
118 init_members();
119
120 // Copy members
121 copy_members(app);
122
123 // Return
124 return;
125}
126
127
128/***********************************************************************//**
129 * @brief Destructor
130 *
131 * Destructs the ctulimit tool.
132 ***************************************************************************/
134{
135 // Free members
136 free_members();
137
138 // Return
139 return;
140}
141
142
143/*==========================================================================
144 = =
145 = Operators =
146 = =
147 ==========================================================================*/
148
149/***********************************************************************//**
150 * @brief Assignment operator
151 *
152 * @param[in] app Application.
153 * @return Application.
154 *
155 * Assigns a ctulimit tool.
156 ***************************************************************************/
158{
159 // Execute only if object is not identical
160 if (this != &app) {
161
162 // Copy base class members
163 this->ctlikelihood::operator=(app);
164
165 // Free members
166 free_members();
167
168 // Initialise members
169 init_members();
170
171 // Copy members
172 copy_members(app);
173
174 } // endif: object was not identical
175
176 // Return this object
177 return *this;
178}
179
180
181/*==========================================================================
182 = =
183 = Public methods =
184 = =
185 ==========================================================================*/
186
187/***********************************************************************//**
188 * @brief Clear ctulimit tool
189 *
190 * Resets the ctulimit tool to a clean initial state.
191 ***************************************************************************/
193{
194 // Free members
195 free_members();
198 this->ctool::free_members();
199
200 // Clear base class (needed to conserve tool name and version)
201 this->GApplication::clear();
202
203 // Initialise members
204 this->ctool::init_members();
207 init_members();
208
209 // Write header into logger
210 log_header();
211
212 // Return
213 return;
214}
215
216
217/***********************************************************************//**
218 * @brief Compute upper limit
219 *
220 * Computes the upper limit depending on the given algorithm
221 ***************************************************************************/
223{
224 // Get task parameters
226
227 // Set energy dispersion flags of all CTA observations and save old
228 // values in save_edisp vector
229 std::vector<bool> save_edisp = set_edisp(m_obs, m_apply_edisp);
230
231 // Write input observation container into logger
232 log_observations(NORMAL, m_obs, "Input observation");
233
234 // Save original models
235 GModels models_orig = m_obs.models();
236
237 // Write header into logger
238 log_header1(TERSE, "Compute best-fit likelihood");
239
240 // Make sure that requested model parameter is free
241 m_model_par->free();
242
243 // Optimize, compute errors and save best log-likelihood
244 m_obs.optimize(m_opt);
245 m_obs.errors(m_opt);
246 m_best_logL = m_obs.logL();
247
248 // Save optimizer for later recovery
249 GOptimizerLM best_opt = m_opt;
250
251 // Write optimised model into logger
252 log_string(NORMAL, m_opt.print(m_chatter));
253 log_value(NORMAL,"Maximum log likelihood",gammalib::str(m_best_logL,3));
254 log_string(NORMAL, m_obs.models().print(m_chatter));
255
256 // Get parameter brackets
257 double parmin;
258 double parmax;
259 get_parameter_brackets(parmin, parmax);
260
261 // Write header into logger
262 log_header1(TERSE, "Compute upper limit");
263
264 // Write some parameters into logger
265 log_value(NORMAL, "Model name", m_skymodel->name());
266 log_value(NORMAL, "Parameter name", m_model_par->name());
267 log_value(NORMAL, "Best factor value", m_best_value);
268 log_value(NORMAL, "Confidence level", gammalib::str(m_confidence*100.0)+"%");
269 log_value(NORMAL, "Maximum log likelihood",gammalib::str(m_best_logL,3));
270 log_value(NORMAL, "Log-likelihood difference", m_dlogL);
271 log_value(NORMAL, "Initial factor value range",
272 "["+gammalib::str(parmin)+", "+gammalib::str(parmax)+"]");
273
274 // Compute upper limit
275 ulimit_bisection(parmin, parmax);
276
277 // Write final parameter into logger
278 log_value(NORMAL, "Upper limit factor value", m_model_par->factor_value());
279 log_value(NORMAL, "Upper limit param. value", m_model_par->value());
280
281 // Compute upper limit intensity and fluxes
283
284 // Write header into logger
285 log_header1(TERSE, "Upper limit results");
286
287 // Write result into logger
288 log_value(TERSE, "Differential flux limit",
289 gammalib::str(m_diff_ulimit)+" ph/cm2/s/MeV at "+
290 gammalib::str(m_eref)+" TeV");
291 log_value(TERSE, "Integral flux limit",
292 gammalib::str(m_flux_ulimit)+" ph/cm2/s within ["+
293 gammalib::str(m_emin)+"-"+
294 gammalib::str(m_emax)+"] TeV");
295 log_value(TERSE, "Energy flux limit",
296 gammalib::str(m_eflux_ulimit)+" erg/cm2/s within ["+
297 gammalib::str(m_emin)+"-"+
298 gammalib::str(m_emax)+"] TeV");
299
300 // Recover original models
301 m_obs.models(models_orig);
302
303 // Recover optimizer
304 m_opt = best_opt;
305
306 // Restore energy dispersion flags of all CTA observations
307 restore_edisp(m_obs, save_edisp);
308
309 // Return
310 return;
311}
312
313
314/***********************************************************************//**
315 * @brief Save upper limits
316 *
317 * Saves the upper limit to an ASCII file in comma-separated value format.
318 *
319 * @todo No yet implemented as we have no clear use case yet for saving
320 * the result.
321 ***************************************************************************/
323{
324 // Return
325 return;
326}
327
328
329/*==========================================================================
330 = =
331 = Private methods =
332 = =
333 ==========================================================================*/
334
335/***********************************************************************//**
336 * @brief Initialise class members
337 ***************************************************************************/
339{
340 // Initialise user parameters
341 m_srcname.clear();
342 m_parname.clear();
343 m_confidence = 0.95;
344 m_sigma_min = 0.0;
345 m_sigma_max = 0.0;
346 m_eref = 0.0;
347 m_emin = 0.0;
348 m_emax = 0.0;
349 m_tol = 1.0e-6;
350 m_max_iter = 50;
351 m_apply_edisp = false;
352 m_chatter = static_cast<GChatter>(2);
353
354 // Initialise protected members
355 m_dlogL = 0.0;
356 m_best_logL = 0.0;
357 m_best_value = 0.0;
358 m_best_error = 0.0;
359 m_flux_ulimit = 0.0;
360 m_diff_ulimit = 0.0;
361 m_eflux_ulimit = 0.0;
362 m_skymodel = NULL;
363 m_model_par = NULL;
364 m_is_spatial = false;
365
366 // Return
367 return;
368}
369
370
371/***********************************************************************//**
372 * @brief Copy class members
373 *
374 * @param[in] app Application.
375 ***************************************************************************/
377{
378 // Copy user parameters
379 m_srcname = app.m_srcname;
380 m_parname = app.m_parname;
381 m_confidence = app.m_confidence;
382 m_sigma_min = app.m_sigma_min;
383 m_sigma_max = app.m_sigma_max;
384 m_eref = app.m_eref;
385 m_emin = app.m_emin;
386 m_emax = app.m_emax;
387 m_tol = app.m_tol;
388 m_max_iter = app.m_max_iter;
389 m_apply_edisp = app.m_apply_edisp;
390 m_chatter = app.m_chatter;
391
392 // Copy protected members
393 m_dlogL = app.m_dlogL;
394 m_best_logL = app.m_best_logL;
395 m_best_value = app.m_best_value;
396 m_best_error = app.m_best_error;
397 m_diff_ulimit = app.m_diff_ulimit;
398 m_flux_ulimit = app.m_flux_ulimit;
399 m_eflux_ulimit = app.m_eflux_ulimit;
400
401 // Extract model parameter
403
404 // Return
405 return;
406}
407
408
409/***********************************************************************//**
410 * @brief Delete class members
411 ***************************************************************************/
413{
414 // Return
415 return;
416}
417
418
419/***********************************************************************//**
420 * @brief Get application parameters
421 *
422 * Get all task parameters from parameter file.
423 ***************************************************************************/
425{
426 // Setup observations from "inobs" parameter
428
429 // Set observation statistic
430 set_obs_statistic(gammalib::toupper((*this)["statistic"].string()));
431
432 // Setup models from "inmodel" parameter
433 setup_models(m_obs, (*this)["srcname"].string());
434
435 // Get name of test source and optional parameter
436 m_srcname = (*this)["srcname"].string();
437 m_parname = (*this)["parname"].string();
438
439 // Get relevant model and parameter for upper limit computation
441
442 // Read energy dispersion flag
443 m_apply_edisp = (*this)["edisp"].boolean();
444
445 // Get confidence level and transform into log-likelihood difference
446 m_confidence = (*this)["confidence"].real();
447 double sigma = gammalib::erfinv(m_confidence) * gammalib::sqrt_two;
448 m_dlogL = (sigma*sigma) / 2.0;
449
450 // Read starting boundaries for bisection
451 m_sigma_min = (*this)["sigma_min"].real();
452 m_sigma_max = (*this)["sigma_max"].real();
453
454 // Read energy values
455 m_eref = (*this)["eref"].real();
456 m_emin = (*this)["emin"].real();
457 m_emax = (*this)["emax"].real();
458
459 // Set optimizer characteristics from user parameters
460 m_opt.eps((*this)["like_accuracy"].real());
461 m_opt.max_iter((*this)["max_iter"].integer());
462
463 // Read precision
464 m_tol = (*this)["tol"].real();
465 m_max_iter = (*this)["max_iter"].integer();
466
467 // Get remaining parameters
468 m_chatter = static_cast<GChatter>((*this)["chatter"].integer());
469
470 // Write parameters into logger
471 log_parameters(TERSE);
472
473 // Return
474 return;
475}
476
477
478/***********************************************************************//**
479 * @brief Get model parameter
480 *
481 * @exception GException::invalid_value
482 * Did not find a valid model or model parameter
483 *
484 * Extracts a pointer to the sky model (m_skymodel) and a pointer to the
485 * model parameter (m_model_par) that should be varied for the upper limit
486 * determination from the model container.
487 ***************************************************************************/
489{
490 // Define list of valid spectral model parameters, terminated with a
491 // NULL pointer to signal the end of the list
492 const char* pars[] = {"Normalization", "Value", "Prefactor",
493 "Integral", "PhotonFlux", "EnergyFlux",
494 NULL};
495
496 // Initialises sky model and model parameters pointers
497 m_skymodel = NULL;
498 m_model_par = NULL;
499 m_is_spatial = false;
500
501 // If the model container does not container the specified source then
502 // throw an exception
503 if (!m_obs.models().contains(m_srcname)) {
504 std::string msg = "Source \""+m_srcname+"\" not found in model "
505 "container. Please add a source with that name "
506 "or check for possible typos.";
507 throw GException::invalid_value(G_GET_MODEL_PARAMETER, msg);
508 }
509
510 // Get relevant sky model for upper limit computation. If the model is not
511 // a sky model or if the model has a "NodeFunction" as spectral component
512 // then throw an exception.
513 GModels& models = const_cast<GModels&>(m_obs.models());
514 m_skymodel = dynamic_cast<GModelSky*>(models[m_srcname]);
515 if (m_skymodel == NULL) {
516 std::string msg = "Source \""+m_srcname+"\" is not a sky model. Please "
517 "specify the name of a sky model for upper limit "
518 "computation.";
519 throw GException::invalid_value(G_GET_MODEL_PARAMETER, msg);
520 }
521
522 // If a parameter name was specified then use that parameter
523 if (!m_parname.empty()) {
524 if (m_skymodel->spatial()->has_par(m_parname)) {
525 m_model_par = &(m_skymodel->spatial()->operator[](m_parname));
526 m_is_spatial = true;
527 }
528 else if (m_skymodel->spectral()->has_par(m_parname)) {
529 m_model_par = &(m_skymodel->spectral()->operator[](m_parname));
530 }
531 else {
532 std::string msg = "Spatial or spectral model of source \""+
533 m_srcname+"\" has no parameter \""+m_parname+
534 "\". Please specify a valid parameter name "
535 "or leave the parameter name blank for "
536 "autodetermination of an intensity- or "
537 "flux-like parameter.";
538 throw GException::invalid_value(G_GET_MODEL_PARAMETER, msg);
539 }
540 }
541
542 // ... otherwise find the appropriate model parameter
543 else {
544
545 // If a node function was specified then a valid parameter name is
546 // needed
547 if (m_skymodel->spectral()->type() == "NodeFunction") {
548 std::string msg = "Spectral model of source \""+m_srcname+"\" is "
549 "a \"NodeFunction\" but no parameter name was "
550 "specified. Please use the \"parname\" parameter "
551 "to specify the parameter that should be used "
552 "for the upper limit computation.";
553 throw GException::invalid_value(G_GET_MODEL_PARAMETER, msg);
554 }
555
556 // Find appropriate model parameter and store its pointer in the
557 // m_model_par member
558 for (const char** par = pars; *par != NULL; ++par) {
559 if (m_skymodel->spectral()->has_par(*par)) {
560 m_model_par = &(m_skymodel->spectral()->operator[](*par));
561 break;
562 }
563 }
564
565 } // endelse: searched for parameter
566
567 // If no model parameter was found then throw an exception
568 if (m_model_par == NULL) {
569 std::string msg = "Require one of the following spectral "
570 "parameters for upper limit computation: ";
571 for (const char** par = pars; *par != NULL; ++par) {
572 if (par != pars) {
573 msg.append(", ");
574 }
575 msg.append("\""+std::string(*par)+"\"");
576 }
577 msg.append(". The specified source \""+m_srcname+"\" does not "
578 "have such a parameter.");
579 throw GException::invalid_value(G_GET_MODEL_PARAMETER, msg);
580 }
581
582 // Return
583 return;
584}
585
586
587/***********************************************************************//**
588 * @brief Determine parameter brackets
589 *
590 * @param[out] parmin Minimum parameter value.
591 * @param[out] parmax Maximum parameter value.
592 *
593 * @exception GException::invalid_value
594 * Exceeded maximum number of iterations in the bracket search.
595 *
596 * Determines the brackets for the parameter of interest.
597 ***************************************************************************/
598void ctulimit::get_parameter_brackets(double& parmin, double& parmax)
599{
600 // Write header into logger
601 log_header1(TERSE, "Find parameter brackets");
602
603 // Extract current value and error
604 m_best_value = m_model_par->factor_value();
605 m_best_error = m_model_par->factor_error();
606
607 // If parameter error is zero then take parameter value as error
608 if (m_best_error == 0.0) {
610 }
611
612 // Compute parameter bracketing
615 if (m_model_par->has_min() && m_model_par->factor_min() > parmin) {
616 parmin = m_model_par->factor_min();
617 }
618 if (m_model_par->has_max() && m_model_par->factor_max() < parmax) {
619 parmax = m_model_par->factor_max();
620 }
621
622 // Initialise iteration counter
623 int iter = 0;
624
625 // Make sure that upper limit is bracketed
626 while (true) {
627
628 // Throw exception if maximum iterations are reached
629 if (iter > m_max_iter) {
630 std::string msg = "The maximum number of "+gammalib::str(m_max_iter)+
631 " has been reached. You may consider to increase"
632 " the \"max_iter\" parameter and re-run ctulimit.";
633 throw GException::invalid_value(G_GET_PARAMETER_BRACKETS, msg);
634 }
635
636 // If model parameter is spatial parameter then make sure that no
637 // values are cached for source
638 if (m_is_spatial) {
639 m_obs.remove_response_cache(m_srcname);
640 }
641
642 // Evaluate logL at upper boundary
643 double logL = evaluate(*m_model_par, parmax);
644 double eval_mid = (m_best_logL - m_dlogL) - logL;
645
646 // Write current parameter range into logger
647 log_value(NORMAL, "Parameter range",
648 "["+gammalib::str(parmin)+", "+gammalib::str(parmax)+"] "
649 "logL("+gammalib::str(parmax)+")="+gammalib::str(logL));
650
651 // If the logL increase is not enough, increase maximum parameter
652 // value, otherwise break
653 if (eval_mid < 0.0) {
654 parmax *= 10.0;
655 }
656 else {
657 break;
658 }
659
660 // Increase number of iterations
661 iter++;
662
663 } // endwhile
664
665 // Return
666 return;
667}
668
669
670/***********************************************************************//**
671 * @brief Calculate upper limit using a bisection method
672 *
673 * @param[in] parmin Minimum parameter value
674 * @param[in] parmax Maximum parameter value
675 *
676 * @exception GException::invalid_value
677 * Exceeded maximum number of iterations in the upper limit
678 * search.
679 *
680 * Calculates the upper limit using a bisection method. The bisection is
681 * stopped if the log-likelihood value is within the tolerance of the target
682 * value. The bisection is also stopped putting a warning in the log file if
683 * the parameter interval becomes smaller than a tolerance of 1.0e-6. The
684 * method stops with an exception if the maximum number of iterations is
685 * exhausted.
686 ***************************************************************************/
687void ctulimit::ulimit_bisection(const double& parmin, const double& parmax)
688{
689 // Copy values to working values
690 double wrk_min = parmin;
691 double wrk_max = parmax;
692
693 // Initialise iteration counter and restart flag
694 int iter = 0;
695 bool restart = false;
696
697 // Loop until breaking condition is reached
698 while (true) {
699
700 // Throw exception if maximum iterations are reached
701 if (iter > m_max_iter) {
702 std::string msg = "The maximum number of "+gammalib::str(m_max_iter)+
703 " has been reached. You may consider to increase"
704 " the \"max_iter\" parameter and re-run ctulimit.";
705 throw GException::invalid_value(G_UL_BISECTION, msg);
706 }
707
708 // If model parameter is spatial parameter then make sure that no
709 // values are cached for source
710 if (m_is_spatial) {
711 m_obs.remove_response_cache(m_srcname);
712 }
713
714 // Compute center of boundary
715 double mid = (wrk_min + wrk_max) / 2.0;
716
717 // Calculate function value
718 double logL = evaluate(*m_model_par, mid);
719 double eval_mid = (m_best_logL - m_dlogL) - logL;
720
721 // Log information
722 log_value(NORMAL, "Iteration "+gammalib::str(iter),
723 "["+gammalib::str(wrk_min)+", "+gammalib::str(wrk_max)+"] "
724 "logL("+gammalib::str(mid)+")="+gammalib::str(logL)+" "
725 "dlogL="+gammalib::str(eval_mid));
726
727 // Check for convergence inside tolerance
728 if (std::abs(eval_mid) < m_tol) {
729 break;
730 }
731
732 // Assess status
733 int status = 0;
734
735 // Check whether mid-point is close to best parameter value
736 double eps = (mid != 0.0) ? (mid - m_best_value)/mid : mid - m_best_value;
737 if (std::abs(eps) < 1.0e-6) {
738 std::string msg =
739 " *** WARNING: Parameter range mid-point "+gammalib::str(mid)+" is "
740 "close to best factor\n"
741 " value "+gammalib::str(m_best_value)+" yet the "
742 "log-likelihood value "+gammalib::str(logL)+"\n"
743 " at the mid-point differs significantly from the "
744 "log-likelihood value\n"
745 " "+gammalib::str(m_best_logL)+" for the best factor "
746 "value.";
747 log_string(TERSE, msg);
748 status = 1;
749 }
750
751 // Check for vanishing parameter range
752 eps = (mid != 0.0) ? (wrk_min - wrk_max)/mid : wrk_min - wrk_max;
753 if (std::abs(eps) < 1.0e-6) {
754 std::string msg =
755 " *** WARNING: Parameter range ["+gammalib::str(wrk_min)+", "+
756 gammalib::str(wrk_max)+"] has reduced\n"
757 " to a narrow interval without reaching convergence! "
758 "The best\n"
759 " log-likelihood value is probably not an absolute "
760 "but only a local\n"
761 " minimum.";
762 log_string(TERSE, msg);
763 status = 2;
764 }
765
766 // Restart bisection if a restart is required
767 if (!restart && status != 0) {
768
769 // Adopt current logL as best log-likelihood
770 restart = true;
771 iter = 0;
772 wrk_min = parmin;
773 wrk_max = parmax;
774 m_best_logL = logL;
775
776 // Signal restart
777 std::string msg =
778 " Adopt "+gammalib::str(logL)+" as best log-likelihood and restart "
779 "bisection";
780 log_string(TERSE, msg);
781
782 // Restart
783 continue;
784
785 } // endif: restart bisection if required
786
787 // Change boundaries for further iteration
788 if (eval_mid > 0.0) {
789 wrk_max = mid; // logL too large, new range = [wrk_min, mid]
790 }
791 else {
792 wrk_min = mid; // logL too small, new range = [mid, wrk_max]
793 }
794
795 // Increment counter
796 iter++;
797
798 } // endwhile
799
800 // Return
801 return;
802
803}
804
805
806/***********************************************************************//**
807 * @brief Compute upper limit intensity and fluxes
808 *
809 * Compute upper limit intensity and fluxes, including a correct computation
810 * for the diffuse map cube models.
811 ***************************************************************************/
813{
814 // Initialise upper limit intensity and fluxes
815 m_diff_ulimit = 0.0;
816 m_flux_ulimit = 0.0;
817 m_eflux_ulimit = 0.0;
818
819 // Get reference energy for differential upper limit
820 GEnergy eref = GEnergy(m_eref, "TeV");
821
822 // Create energy range for flux limits
823 GEnergy emin = GEnergy(m_emin, "TeV");
824 GEnergy emax = GEnergy(m_emax, "TeV");
825
826 // Set pointer to spectral model and initialise spectral nodes model
827 // pointer
828 GModelSpectral* spectral = m_skymodel->spectral();
829 GModelSpectralNodes* nodes = NULL;
830
831 // If the spectral model is a diffuse cube then create a node function
832 // spectral model that is the product of the diffuse cube node function
833 // and the spectral model evaluated at the energies of the node function
834 GModelSpatialDiffuseCube* cube =
835 dynamic_cast<GModelSpatialDiffuseCube*>(m_skymodel->spatial());
836 if (cube != NULL) {
837
838 // Set MC cone to the entire sky. This method call is needed to
839 // set-up the cube spectrum
840 cube->mc_cone(GSkyRegionCircle(0.0, 0.0, 180.0));
841
842 // Allocate node function to replace the spectral component
843 nodes = new GModelSpectralNodes(cube->spectrum());
844 for (int i = 0; i < nodes->nodes(); ++i) {
845 GEnergy energy = nodes->energy(i);
846 double intensity = nodes->intensity(i);
847 double value = spectral->eval(energy);
848 nodes->intensity(i, value*intensity);
849 }
850
851 // Set the spectral model pointer to the node function. If there are
852 // no nodes the spectral pointer is set to NULL since in this case the
853 // spectral->flux method will throw an exception
854 if (nodes->nodes() > 0) {
855 spectral = nodes;
856 }
857 else {
858 spectral = NULL;
859 }
860
861 } // endif: spatial model was a diffuse cube
862
863 // Compute upper limit intensity and fluxes
864 if (spectral != NULL) {
865 m_diff_ulimit = spectral->eval(eref);
866 m_flux_ulimit = spectral->flux(emin, emax);
867 m_eflux_ulimit = spectral->eflux(emin, emax);
868 }
869
870 // Free spectral nodes if they have been allocated
871 if (nodes != NULL) {
872 delete nodes;
873 }
874
875 // Return
876 return;
877}
Base class for likelihood tools.
GOptimizerLM m_opt
Optimizer.
ctlikelihood & operator=(const ctlikelihood &app)
Assignment operator.
double evaluate(GModelPar &par, const double &value)
Evaluates the log-likelihood function.
void free_members(void)
Delete class members.
void init_members(void)
Initialise class members.
void free_members(void)
Delete class members.
GObservations m_obs
Observation container.
const GModels & models(void) const
Return model container.
void init_members(void)
Initialise class members.
void set_obs_statistic(const std::string &statistic)
Set fit statistic for CTA observations.
void restore_edisp(GObservations &obs, const std::vector< bool > &edisp) const
Restore energy dispersion flags of CTA observations.
Definition ctool.cpp:1689
void setup_models(GObservations &obs, const std::string &name="")
Setup model container.
Definition ctool.cpp:545
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
std::vector< bool > set_edisp(GObservations &obs, const bool &edisp) const
Set energy dispersion to CTA observations.
Definition ctool.cpp:1649
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
Upper limit calculation tool.
Definition ctulimit.hpp:50
ctulimit & operator=(const ctulimit &app)
Assignment operator.
Definition ctulimit.cpp:157
double m_sigma_min
Starting value minimum (multiple fit errors above fit values)
Definition ctulimit.hpp:86
bool m_apply_edisp
Apply energy dispersion?
Definition ctulimit.hpp:93
void save(void)
Save upper limits.
Definition ctulimit.cpp:322
double m_flux_ulimit
Flux upper limit value.
Definition ctulimit.hpp:102
double m_best_value
Best parameter value factor.
Definition ctulimit.hpp:99
void get_parameters(void)
Get application parameters.
Definition ctulimit.cpp:424
virtual ~ctulimit(void)
Destructor.
Definition ctulimit.cpp:133
GModelPar * m_model_par
Pointer to model parameter.
Definition ctulimit.hpp:105
double m_eflux_ulimit
Energy flux upper limits.
Definition ctulimit.hpp:103
void process(void)
Compute upper limit.
Definition ctulimit.cpp:222
void ulimit_bisection(const double &parmin, const double &parmax)
Calculate upper limit using a bisection method.
Definition ctulimit.cpp:687
double m_eref
Reference energy for flux limits (TeV)
Definition ctulimit.hpp:88
void free_members(void)
Delete class members.
Definition ctulimit.cpp:412
ctulimit(void)
Void constructor.
Definition ctulimit.cpp:58
void get_model_parameter(void)
Get model parameter.
Definition ctulimit.cpp:488
double m_confidence
Confidence level.
Definition ctulimit.hpp:85
std::string m_srcname
Name of source for upper limit computation.
Definition ctulimit.hpp:83
void compute_ulimit(void)
Compute upper limit intensity and fluxes.
Definition ctulimit.cpp:812
double m_diff_ulimit
Differential upper limit value.
Definition ctulimit.hpp:101
GModelSky * m_skymodel
Pointer to sky model.
Definition ctulimit.hpp:104
void copy_members(const ctulimit &app)
Copy class members.
Definition ctulimit.cpp:376
int m_max_iter
Maximum number of iterations.
Definition ctulimit.hpp:92
double m_emax
Maximum energy for flux limits (TeV)
Definition ctulimit.hpp:90
void clear(void)
Clear ctulimit tool.
Definition ctulimit.cpp:192
std::string m_parname
Name of parameter for upper limit computation.
Definition ctulimit.hpp:84
double m_dlogL
Likelihood difference for upper limit computation.
Definition ctulimit.hpp:97
double m_best_logL
Best fit log likelihood of given model.
Definition ctulimit.hpp:98
double m_best_error
Best parameter value error.
Definition ctulimit.hpp:100
double m_sigma_max
Starting value maximum (multiple fit errors above fit values)
Definition ctulimit.hpp:87
double m_tol
Tolerance for limit determination.
Definition ctulimit.hpp:91
double m_emin
Minimum energy for flux limits (TeV)
Definition ctulimit.hpp:89
bool m_is_spatial
Signal that model parameter is spatial parameter.
Definition ctulimit.hpp:106
void init_members(void)
Initialise class members.
Definition ctulimit.cpp:338
void get_parameter_brackets(double &parmin, double &parmax)
Determine parameter brackets.
Definition ctulimit.cpp:598
GChatter m_chatter
Chattiness.
Definition ctulimit.hpp:94
#define G_UL_BISECTION
Definition ctulimit.cpp:40
#define G_GET_PARAMETER_BRACKETS
Definition ctulimit.cpp:38
#define G_GET_MODEL_PARAMETER
Definition ctulimit.cpp:37
Upper limit calculation tool interface implementation.
#define CTULIMIT_NAME
Definition ctulimit.hpp:34