37#define G_GET_PARAMETERS "ctbutterfly::get_parameters()"
38#define G_SAVE "ctbutterfly::save()"
39#define G_CHECK_MODEL "ctbutterfly::check_model()"
189 this->GApplication::clear();
218 std::vector<bool> save_edisp;
219 save_edisp.assign(
m_obs.size(),
false);
220 for (
int i = 0; i <
m_obs.size(); ++i) {
221 GCTAObservation*
obs =
dynamic_cast<GCTAObservation*
>(
m_obs[i]);
223 save_edisp[i] =
obs->response()->apply_edisp();
235 log_header1(TERSE,
"Compute best-fit likelihood");
244 GObservations::likelihood likelihood =
m_obs.function();
260 GModels models =
m_obs.models();
267 log_header1(TERSE,
"Compute covariance matrix");
270 GOptimizerPars pars = models.pars();
271 GObservations::likelihood likelihood =
m_obs.function();
272 likelihood.eval(pars);
301 log_header1(TERSE,
"Results");
304 for (
int k = 0; k <
m_ebounds.size(); ++k) {
307 std::string key =
"Intensity at " +
310 std::string value = gammalib::str(
m_intensities[k]*1.0e6) +
" (" +
316 log_value(NORMAL, key, value);
321 for (
int i = 0; i <
m_obs.size(); ++i) {
322 GCTAObservation*
obs =
dynamic_cast<GCTAObservation*
>(
m_obs[i]);
324 obs->response()->apply_edisp(save_edisp[i]);
341 log_header1(TERSE,
"Save Butterfly diagram");
344 if ((*
this)[
"outfile"].is_valid()) {
347 m_outfile = (*this)[
"outfile"].filename();
350 log_value(NORMAL,
"Butterfly file",
m_outfile.url());
463 if ((*
this)[
"matrix"].is_valid()) {
464 std::string msg =
"Loading of matrix from file not implemented yet. "
465 "Use filename = \"NONE\" to induce a recomputation "
466 "of the matrix internally.";
472 m_opt.eps((*
this)[
"like_accuracy"].real());
473 m_opt.max_iter((*
this)[
"max_iter"].integer());
477 m_method = (*this)[
"method"].string();
479 m_fit = (*this)[
"fit"].boolean();
480 m_chatter =
static_cast<GChatter
>((*this)[
"chatter"].integer());
487 (*this)[
"outfile"].query();
506 log_header1(TERSE,
"Prepare butterfly computation");
510 GModelSky* skymodel =
dynamic_cast<GModelSky*
>(models[
m_srcname]);
511 GModelPar* par_prefactor = &(*skymodel)[
"Prefactor"];
512 GModelPar* par_index = &(*skymodel)[
"Index"];
513 int inx_prefactor = -1;
515 for (
int i = 0; i < models.npars(); ++i) {
516 if (models.pars()[i] == par_prefactor) {
519 if (models.pars()[i] == par_index) {
525 double prefactor_mean = (*skymodel)[
"Prefactor"].value();
526 double index_mean = (*skymodel)[
"Index"].value();
527 double pivot_mean = (*skymodel)[
"PivotEnergy"].value();
528 double prefactor_scale = (*skymodel)[
"Prefactor"].scale();
529 double index_scale = (*skymodel)[
"Index"].scale();
530 GEnergy pivot(pivot_mean,
"MeV");
533 log_value(NORMAL,
"Prefactor", gammalib::str(prefactor_mean)+
535 gammalib::str(inx_prefactor)+
")");
536 log_value(NORMAL,
"Index", gammalib::str(index_mean)+
537 " ("+gammalib::str(inx_index)+
")");
538 log_value(NORMAL,
"Pivot energy", pivot.print());
541 double cov_pp =
m_covariance(inx_prefactor,inx_prefactor);
551 &lambda1, &lambda2, &vector1, &vector2);
554 log_value(NORMAL,
"Eigenvalue 1", lambda1);
555 log_value(NORMAL,
"Eigenvalue 2", lambda2);
556 log_value(NORMAL,
"Eigenvector 1", vector1.print());
557 log_value(NORMAL,
"Eigenvector 2", vector2.print());
561 double scale = std::sqrt(-2.0 * std::log(1.0-
m_confidence));
565 log_value(NORMAL,
"Corresponding scaling", scale);
568 double major = scale*std::sqrt(lambda1);
569 double minor = scale*std::sqrt(lambda2);
572 log_header1(TERSE,
"Generate butterfly");
582 double dt = gammalib::twopi/double(nt);
584 for (
int i = 0; i < nt; ++i, t += dt) {
587 double sin_t = std::sin(t);
588 double cos_t = std::cos(t);
591 double prefactor = (major * cos_t * vector1[0] +
592 minor * sin_t * vector2[0]) * prefactor_scale +
594 double index = (major * cos_t * vector1[1] +
595 minor * sin_t * vector2[1]) * index_scale +
599 log_value(EXPLICIT,
"Angle "+gammalib::str(t*gammalib::rad2deg),
600 gammalib::str(prefactor)+
" ph/cm2/s/MeV; "+
601 gammalib::str(index));
604 GModelSpectralPlaw plaw(prefactor, index, pivot);
608 for (
int k = 0; k <
m_ebounds.size(); ++k) {
615 double intensity = plaw.eval(energy, time);
630 GModelSpectralPlaw plaw(prefactor_mean, index_mean, pivot);
633 for (
int k = 0; k <
m_ebounds.size(); ++k) {
640 double intensity = plaw.eval(energy, time);
664 log_header1(TERSE,
"Prepare butterfly computation");
667 double scale = gammalib::erfinv(
m_confidence) * gammalib::sqrt_two;
671 log_value(NORMAL,
"Corresponding scaling", scale);
674 log_header1(TERSE,
"Generate butterfly");
683 GTime time = GTime();
686 GVector grad = GVector(
m_obs.models().npars());
689 for (
int i = 0; i <
m_ebounds.size(); ++i) {
692 int num_gradient = 0;
698 double model_flux = 0.0;
701 for (
int j = 0; j < models.size(); ++j) {
704 GModelSky* skymodel =
dynamic_cast<GModelSky*
>(models[j]);
707 if (skymodel != NULL) {
713 GModelSpectral *spectral = skymodel->spectral();
716 model_flux = spectral->eval(energy, time,
true);
719 for (
int k = 0; k < skymodel->size(); ++k) {
724 bool parIsSpectral =
false;
725 for (
int l = 0; l < spectral->size(); ++l) {
726 if ((&((*spectral)[l])) == (&((*skymodel)[k]))) {
727 grad[num_gradient] = (*spectral)[l].gradient();
729 parIsSpectral =
true;
735 if (!parIsSpectral) {
743 num_gradient += skymodel->size();
750 num_gradient += models[j]->size();
760 double arg = grad * vector;
761 double error = (arg > 0.0) ? std::sqrt(arg) : 0.0;
794 GModels& models =
const_cast<GModels&
>(
m_obs.models());
795 GModelSky* model =
dynamic_cast<GModelSky*
>(models[
m_srcname]);
797 std::string msg =
"Source \""+
m_srcname+
"\" is not a sky model. "
798 "Please specify the name of a sky model for "
799 "butterfly computation.";
806 if (model->spectral()->type() !=
"PowerLaw") {
807 std::string msg =
"\""+model->spectral()->type()+
"\" cannot be "
808 "used as spectral model for an butterfly "
809 "computation with method=ENVELOPE. Please "
810 "specify a power law model or switch to "
820 std::string msg =
"Source \""+
m_srcname+
"\" not found in model "
821 "container. Please add a source with that name "
822 "or check for possible typos.";
856 double trace = a + d;
857 double det = a*d - b*c;
860 double arg1 = 0.5*trace;
861 double arg2 = std::sqrt(0.25*trace*trace - det);
862 *lambda1 = arg1 + arg2;
863 *lambda2 = arg1 - arg2;
867 (*vector1)[0] = *lambda1 - det;
869 (*vector2)[0] = *lambda2 - det;
874 (*vector1)[1] = *lambda1 - a;
876 (*vector2)[1] = *lambda2 - a;
886 *vector1 /= norm(*vector1);
887 *vector2 /= norm(*vector2);
905 GFitsTableDoubleCol col_energy(
"ENERGY", nrows);
906 GFitsTableDoubleCol col_intensity(
"INTENSITY", nrows);
907 GFitsTableDoubleCol col_intensity_min(
"INTENSITY_MIN", nrows);
908 GFitsTableDoubleCol col_intensity_max(
"INTENSITY_MAX", nrows);
911 col_energy.unit(
"TeV");
912 col_intensity.unit(
"ph/cm2/s/TeV");
913 col_intensity_min.unit(
"ph/cm2/s/TeV");
914 col_intensity_max.unit(
"ph/cm2/s/TeV");
917 for (
int i = 0; i < nrows; ++i) {
926 table.extname(
"BUTTERFLY");
932 table.card(
"INSTRUME",
"CTA",
"Name of Instrument");
933 table.card(
"TELESCOP",
"CTA",
"Name of Telescope");
936 table.append(col_energy);
937 table.append(col_intensity);
938 table.append(col_intensity_min);
939 table.append(col_intensity_max);
Butterfly calculation tool.
void copy_members(const ctbutterfly &app)
Copy class members.
void get_parameters(void)
Get application parameters.
bool m_apply_edisp
Apply energy dispersion?
void save(void)
Save butterfly diagram.
ctbutterfly & operator=(const ctbutterfly &app)
Assignment operator.
GChatter m_chatter
Chattiness.
GMatrixSparse m_covariance
Covariance matrix.
void create_fits(void)
Set result FITS file.
std::vector< double > m_energies
Energy values.
void eigenvectors(const double &a, const double &b, const double &c, const double &d, double *lambda1, double *lambda2, GVector *vector1, GVector *vector2)
Compute normalized eigenvectors and eigenvalues.
std::vector< double > m_intensities
Power law intensity.
std::vector< double > m_max_intensities
Maximum intensities.
std::string m_method
Computation method.
void init_members(void)
Initialise class members.
GFilename m_outfile
Output ASCII file name.
GFits m_fits
FITS file holding butterfly.
int m_max_iter
Maximum number of iterations.
void process(void)
Computes the butterfly.
void gaussian_error_propagation(GModels &models)
Compute butterfly using Gaussian error propagation.
void free_members(void)
Delete class members.
void clear(void)
Clear ctbutterfly tool.
void ellipsoid_boundary(GModels &models)
Compute butterfly using the ellipsoid boundary method.
ctbutterfly(void)
Void constructor.
virtual ~ctbutterfly(void)
Destructor.
double m_confidence
Confidence level.
void check_model(void)
Check if sky model is valid.
std::vector< double > m_min_intensities
Minimum intensities.
std::string m_srcname
Name of source to compute butterfly.
GEbounds m_ebounds
Energy binning definition.
Base class for likelihood tools.
GOptimizerLM m_opt
Optimizer.
ctlikelihood & operator=(const ctlikelihood &app)
Assignment operator.
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 GObservations & obs(void) const
Return observation container.
void init_members(void)
Initialise class members.
void set_obs_statistic(const std::string &statistic)
Set fit statistic for CTA observations.
Butterfly calculation tool interface definition.