34#include "GOptimizer.hpp"
42#define G_ERR_BISECTION "cterror::error_bisection(double&, double&)"
202 this->GApplication::clear();
236 log_header1(TERSE,
"Compute best-fit likelihood");
244 GOptimizerLM best_opt =
m_opt;
251 log_value(NORMAL,
"Maximum log likelihood", gammalib::str(
m_best_logL,3));
255 GModels models_best =
m_obs.models();
261 int npars = model->size();
264 for (
int i = 0; i < npars; ++i) {
267 if (model->at(i).is_fixed()) {
272 m_obs.models(models_best);
275 GModels& current_models =
const_cast<GModels&
>(
m_obs.models());
282 double parmin = std::max(
m_model_par->factor_min(),
284 double parmax = std::min(
m_model_par->factor_max(),
288 log_header1(TERSE,
"Compute error for source \""+
m_srcname+
"\""
290 log_value(NORMAL,
"Confidence level",
292 log_value(NORMAL,
"Log-likelihood difference",
m_dlogL);
293 log_value(NORMAL,
"Initial factor range",
294 "["+gammalib::str(parmin)+
", "+gammalib::str(parmax)+
"]");
298 GModels models_lo =
m_obs.models();
303 GModels models_hi =
m_obs.models();
307 double error = 0.5 * (value_hi - value_lo);
308 double error_neg =
m_value - value_lo;
309 double error_pos = value_hi -
m_value;
310 double error_value = std::abs(error*
m_model_par->scale());
311 double error_value_neg = std::abs(error_neg*
m_model_par->scale());
312 double error_value_pos = std::abs(error_pos*
m_model_par->scale());
316 log_value(NORMAL,
"Lower parameter factor", value_lo);
317 log_value(NORMAL,
"Upper parameter factor", value_hi);
318 log_value(NORMAL,
"Error from curvature",
320 log_value(NORMAL,
"Error from profile",
321 gammalib::str(error_value) + unit);
322 log_value(NORMAL,
"Negative profile error",
323 gammalib::str(error_value_neg) + unit);
324 log_value(NORMAL,
"Positive profile error",
325 gammalib::str(error_value_pos) + unit);
329 log_header3(NORMAL,
"Model at lower parameter value");
330 log_string(NORMAL, models_lo[
m_srcname]->print());
331 log_header3(NORMAL,
"Model at upper parameter value");
332 log_string(NORMAL, models_hi[
m_srcname]->print());
335 model->at(i).factor_error(error);
340 m_obs.models(models_best);
352 log_header1(TERSE,
"Butterfly");
358 std::string key =
"Intensity at " +
361 std::string value = gammalib::str(
m_intensities[k]*1.0e6) +
" (" +
367 log_value(NORMAL, key, value);
384 log_header1(TERSE,
"Save results");
387 if ((*
this)[
"outmodel"].is_valid()) {
390 GFilename outmodel = (*this)[
"outmodel"].filename();
393 log_value(NORMAL,
"Model definition file", outmodel.url());
396 m_obs.models().save(outmodel.url());
402 log_value(NORMAL,
"Model definition file",
"NONE");
406 if ((*
this)[
"outfile"].is_valid()) {
409 GFilename outfile = (*this)[
"outfile"].filename();
412 log_value(NORMAL,
"Butterfly file", outfile.url());
415 m_fits.saveto(outfile.url(), clobber());
421 log_value(NORMAL,
"Butterfly file",
"NONE");
533 double sigma = gammalib::erfinv(
m_confidence) * gammalib::sqrt_two;
537 m_opt.eps((*
this)[
"like_accuracy"].real());
538 m_opt.max_iter((*
this)[
"max_iter"].integer());
541 m_tol = (*this)[
"tol"].real();
543 m_chatter =
static_cast<GChatter
>((*this)[
"chatter"].integer());
550 (*this)[
"outmodel"].query();
551 (*this)[
"outfile"].query();
556 int nthreads = (*this)[
"nthreads"].integer();
558 omp_set_num_threads(nthreads);
581 double wrk_min = min;
582 double wrk_max = max;
588 double mid = (wrk_min + wrk_max) / 2.0;
596 std::string msg =
"The \""+
m_model_par->name()+
"\" parameter "
597 "minimum has been reached during error "
598 "calculation. To obtain accurate errors, "
599 "consider setting the minimum parameter "
600 "value to a lower value, and re-run "
602 log_string(TERSE, msg);
606 std::string msg =
"The \""+
m_model_par->name()+
"\" parameter "
607 "maximum has been reached during error "
608 "calculation. To obtain accurate errors, "
609 "consider setting the maximum parameter "
610 "value to a higher value, and re-run "
612 log_string(TERSE, msg);
616 std::string msg =
"The maximum number of "+
618 "been reached. Please increase the "
619 "\"max_iter\" parameter, and re-run "
626 mid = (wrk_min + wrk_max) / 2.0;
632 log_value(EXPLICIT,
" Iteration "+gammalib::str(iter),
633 "["+gammalib::str(wrk_min)+
", "+gammalib::str(wrk_max)+
"]");
636 if (std::abs(eval_mid) <
m_tol) {
641 if (std::abs(wrk_max-wrk_min) < 1.0e-6) {
649 if (eval_mid > 0.0) {
652 else if (eval_mid < 0.0) {
661 if (eval_mid > 0.0) {
664 else if (eval_mid < 0.0) {
697 log_header3(TERSE,
"Initialise intensities for butterfly");
701 const GModelSky* skymodel =
dynamic_cast<const GModelSky*
>(
m_obs.models()[
m_srcname]);
704 if (skymodel != NULL) {
707 GModelSpectral* spectral = skymodel->spectral();
757 GFitsTableDoubleCol col_energy(
"ENERGY", nrows);
758 GFitsTableDoubleCol col_intensity(
"INTENSITY", nrows);
759 GFitsTableDoubleCol col_intensity_min(
"INTENSITY_MIN", nrows);
760 GFitsTableDoubleCol col_intensity_max(
"INTENSITY_MAX", nrows);
763 col_energy.unit(
"TeV");
764 col_intensity.unit(
"ph/cm2/s/TeV");
765 col_intensity_min.unit(
"ph/cm2/s/TeV");
766 col_intensity_max.unit(
"ph/cm2/s/TeV");
769 for (
int i = 0; i < nrows; ++i) {
778 table.extname(
"BUTTERFLY");
784 table.card(
"INSTRUME",
"CTA",
"Name of Instrument");
785 table.card(
"TELESCOP",
"CTA",
"Name of Telescope");
788 table.append(col_energy);
789 table.append(col_intensity);
790 table.append(col_intensity_min);
791 table.append(col_intensity_max);
Parameter error calculation tool.
void clear(void)
Clear cterror tool.
std::string m_srcname
Name of source.
void init_members(void)
Initialise class members.
std::vector< double > m_min_intensities
Minimum intensities.
virtual ~cterror(void)
Destructor.
void process(void)
Compute parameter errors using a likelihood profile method.
double m_value
Parameter value.
std::vector< double > m_intensities
Model intensity.
GFits m_fits
FITS file holding butterfly.
cterror(void)
Void constructor.
GEnergies m_energies
Energy values.
double m_best_logL
Best fit log likelihood of given model.
bool m_apply_edisp
Apply energy dispersion?
void save(void)
Save model.
std::vector< double > m_max_intensities
Maximum intensities.
cterror & operator=(const cterror &app)
Assignment operator.
void free_members(void)
Delete class members.
void update_intensities(void)
Update intensities.
double error_bisection(const double &min, const double &max)
Calculate error using a bisection method.
GModelPar * m_model_par
Pointer to model parameter.
double m_dlogL
Likelihood difference for upper limit computation.
double m_tol
Tolerance for limit determination.
void get_parameters(void)
Get application parameters.
int m_max_iter
Maximum number of iterations.
GChatter m_chatter
Chattiness.
double m_confidence
Confidence level.
void copy_members(const cterror &app)
Copy class members.
void create_fits(void)
Set result FITS file.
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.
void init_members(void)
Initialise class members.
void set_obs_statistic(const std::string &statistic)
Set fit statistic for CTA observations.
Parameter error calculation tool interface definition.