Commit 8989586967494e586eb90f00f98c3acd3875840f

Authored by Michael Mayer
1 parent a2954be5

added first version of ctbutterfly including a unit test

configure.ac
@@ -887,6 +887,7 @@ AC_CONFIG_FILES([Makefile @@ -887,6 +887,7 @@ AC_CONFIG_FILES([Makefile
887 src/ctbkgcube/Makefile 887 src/ctbkgcube/Makefile
888 src/ctcubemask/Makefile 888 src/ctcubemask/Makefile
889 src/cttsmap/Makefile 889 src/cttsmap/Makefile
  890 + src/ctbutterfly/Makefile
890 src/support/Makefile 891 src/support/Makefile
891 src/ctools-setup 892 src/ctools-setup
892 test/Makefile 893 test/Makefile
pyext/ctbutterfly.i 0 → 100644
  1 +/***************************************************************************
  2 + * ctbutterfly - butterfly calculation tool *
  3 + * ----------------------------------------------------------------------- *
  4 + * copyright (C) 2014 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 ctbutterfly.i
  23 + * @brief tool for butterfly calculations
  24 + * @author Michael Mayer
  25 + */
  26 +%{
  27 +/* Put headers and other declarations here that are needed for compilation */
  28 +#include "ctbutterfly.hpp"
  29 +%}
  30 +
  31 +
  32 +/***********************************************************************//**
  33 + * @class ctbutterfly
  34 + *
  35 + * @brief butterfly calculation tool
  36 + ***************************************************************************/
  37 +class ctbutterfly : public ctool {
  38 +public:
  39 + // Constructors and destructors
  40 + ctbutterfly(void);
  41 + explicit ctbutterfly(const GObservations& obs);
  42 + ctbutterfly(int argc, char *argv[]);
  43 + ctbutterfly(const ctbutterfly& app);
  44 + virtual ~ctbutterfly(void);
  45 +
  46 + // Methods
  47 + void clear(void);
  48 + void run(void);
  49 + void save(void);
  50 + const GObservations& obs(void) const;
  51 +
  52 +};
  53 +
  54 +
  55 +/***********************************************************************//**
  56 + * @brief butterfly calculation tool Python extensions
  57 + ***************************************************************************/
  58 +%extend ctbutterfly {
  59 + ctbutterfly copy() {
  60 + return (*self);
  61 + }
  62 +}
pyext/ctools/ctools.i
@@ -57,3 +57,4 @@ @@ -57,3 +57,4 @@
57 %include "ctbkgcube.i" 57 %include "ctbkgcube.i"
58 %include "ctcubemask.i" 58 %include "ctcubemask.i"
59 %include "cttsmap.i" 59 %include "cttsmap.i"
  60 +%include "ctbutterfly.i"
src/Makefile.am
@@ -16,7 +16,8 @@ SUBDIRS = support \ @@ -16,7 +16,8 @@ SUBDIRS = support \
16 ctpsfcube \ 16 ctpsfcube \
17 ctbkgcube \ 17 ctbkgcube \
18 ctcubemask \ 18 ctcubemask \
19 - cttsmap 19 + cttsmap \
  20 + ctbutterfly
20 21
21 # Scripts to be distributed 22 # Scripts to be distributed
22 scripts = ctools-setup \ 23 scripts = ctools-setup \
@@ -39,7 +40,8 @@ libctools_la_LIBADD = support/libsupport.la \ @@ -39,7 +40,8 @@ libctools_la_LIBADD = support/libsupport.la \
39 ctpsfcube/libctpsfcube.la \ 40 ctpsfcube/libctpsfcube.la \
40 ctbkgcube/libctbkgcube.la \ 41 ctbkgcube/libctbkgcube.la \
41 ctcubemask/libctcubemask.la \ 42 ctcubemask/libctcubemask.la \
42 - cttsmap/libcttsmap.la 43 + cttsmap/libcttsmap.la \
  44 + ctbutterfly/libctbutterfly.la
43 45
44 46
45 # Distribute scripts 47 # Distribute scripts
src/ctbutterfly/ctbutterfly.cpp 0 → 100644
  1 +/***************************************************************************
  2 + * ctbutterfly - butterfly calculation tool *
  3 + * ----------------------------------------------------------------------- *
  4 + * copyright (C) 2014 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 ctbutterfly.hpp
  23 + * @brief Butterfly computation tool
  24 + * @author Michael Mayer
  25 + */
  26 +
  27 +/* __ Includes ___________________________________________________________ */
  28 +#ifdef HAVE_CONFIG_H
  29 +#include <config.h>
  30 +#endif
  31 +#include <cstdio>
  32 +#include <fstream>
  33 +#include "ctbutterfly.hpp"
  34 +#include "GTools.hpp"
  35 +
  36 +/* __ Method name definitions ____________________________________________ */
  37 +#define G_GET_PARAMETERS "ctbutterfly::get_parameters()"
  38 +#define G_SAVE "ctbutterfly::save()"
  39 +
  40 +/* __ Debug definitions __________________________________________________ */
  41 +
  42 +/* __ Coding definitions _________________________________________________ */
  43 +
  44 +
  45 +/*==========================================================================
  46 + = =
  47 + = Constructors/destructors =
  48 + = =
  49 + ==========================================================================*/
  50 +
  51 +/***********************************************************************//**
  52 + * @brief Void constructor
  53 + ***************************************************************************/
  54 +ctbutterfly::ctbutterfly(void) : ctool(CTBUTTERFLY_NAME, CTBUTTERFLY_VERSION)
  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 + * This method creates an instance of the class by copying an existing
  70 + * observations container.
  71 + ***************************************************************************/
  72 +ctbutterfly::ctbutterfly(const GObservations& obs) :
  73 + ctool(CTBUTTERFLY_NAME, CTBUTTERFLY_VERSION)
  74 +{
  75 + // Initialise members
  76 + init_members();
  77 +
  78 + // Set observations
  79 + m_obs = obs;
  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 +ctbutterfly::ctbutterfly(int argc, char *argv[]) :
  94 + ctool(CTBUTTERFLY_NAME, CTBUTTERFLY_VERSION, argc, argv)
  95 +{
  96 + // Initialise members
  97 + init_members();
  98 +
  99 + // Return
  100 + return;
  101 +}
  102 +
  103 +
  104 +/***********************************************************************//**
  105 + * @brief Copy constructor
  106 + *
  107 + * @param[in] app Application.
  108 + ***************************************************************************/
  109 +ctbutterfly::ctbutterfly(const ctbutterfly& app) : ctool(app)
  110 +{
  111 + // Initialise members
  112 + init_members();
  113 +
  114 + // Copy members
  115 + copy_members(app);
  116 +
  117 + // Return
  118 + return;
  119 +}
  120 +
  121 +
  122 +/***********************************************************************//**
  123 + * @brief Destructor
  124 + ***************************************************************************/
  125 +ctbutterfly::~ctbutterfly(void)
  126 +{
  127 + // Free members
  128 + free_members();
  129 +
  130 + // Return
  131 + return;
  132 +}
  133 +
  134 +
  135 +/*==========================================================================
  136 + = =
  137 + = Operators =
  138 + = =
  139 + ==========================================================================*/
  140 +
  141 +/***********************************************************************//**
  142 + * @brief Assignment operator
  143 + *
  144 + * @param[in] app Application.
  145 + * @return Application.
  146 + ***************************************************************************/
  147 +ctbutterfly& ctbutterfly::operator=(const ctbutterfly& app)
  148 +{
  149 + // Execute only if object is not identical
  150 + if (this != &app) {
  151 +
  152 + // Copy base class members
  153 + this->ctool::operator=(app);
  154 +
  155 + // Free members
  156 + free_members();
  157 +
  158 + // Initialise members
  159 + init_members();
  160 +
  161 + // Copy members
  162 + copy_members(app);
  163 +
  164 + } // endif: object was not identical
  165 +
  166 + // Return this object
  167 + return *this;
  168 +}
  169 +
  170 +
  171 +/*==========================================================================
  172 + = =
  173 + = Public methods =
  174 + = =
  175 + ==========================================================================*/
  176 +
  177 +/***********************************************************************//**
  178 + * @brief Clear instance
  179 + ***************************************************************************/
  180 +void ctbutterfly::clear(void)
  181 +{
  182 + // Free members
  183 + free_members();
  184 + this->ctool::free_members();
  185 + this->GApplication::free_members();
  186 +
  187 + // Initialise members
  188 + this->GApplication::init_members();
  189 + this->ctool::init_members();
  190 + init_members();
  191 +
  192 + // Return
  193 + return;
  194 +}
  195 +
  196 +
  197 +/***********************************************************************//**
  198 + * @brief Computes the butterfly
  199 + *
  200 + * This method takes the spectral fit and its covariance matrix to compute
  201 + * the confidence band via Gaussian error propagation
  202 + ***************************************************************************/
  203 +void ctbutterfly::run(void)
  204 +{
  205 + // If we're in debug mode then all output is also dumped on the screen
  206 + if (logDebug()) {
  207 + log.cout(true);
  208 + }
  209 +
  210 + // Get task parameters
  211 + get_parameters();
  212 +
  213 + // Write parameters into logger
  214 + if (logTerse()) {
  215 + log_parameters();
  216 + log << std::endl;
  217 + }
  218 +
  219 + // Write observation(s) into logger
  220 + if (logTerse()) {
  221 + log << std::endl;
  222 + if (m_obs.size() > 1) {
  223 + log.header1("Observations");
  224 + }
  225 + else {
  226 + log.header1("Observation");
  227 + }
  228 + log << m_obs << std::endl;
  229 + }
  230 +
  231 + // Get model instance for further computations
  232 + GModels models = m_obs.models();
  233 +
  234 + // Compute covariance matrix if necessary
  235 + if (m_covariance.size() == 0) {
  236 +
  237 + // Write header
  238 + if (logTerse()) {
  239 + log << std::endl;
  240 + log.header1("Compute covariance matrix");
  241 + }
  242 +
  243 + GOptimizerPars pars = models.pars();
  244 + GObservations::likelihood likelihood = m_obs.function();
  245 + likelihood.eval(pars);
  246 + GMatrixSparse* curvature = dynamic_cast<GMatrixSparse*>(likelihood.curvature());
  247 + m_covariance = curvature->invert();
  248 +
  249 + }
  250 +
  251 + // Write header
  252 + if (logTerse()) {
  253 + log << std::endl;
  254 + log.header1("Generate butterfly");
  255 + }
  256 +
  257 + // Initialise dummy time to evaluate spectral model
  258 + GTime time = GTime();
  259 +
  260 + // Initialise vector of gradients
  261 + GVector grad = GVector(m_obs.models().npars());
  262 +
  263 + // Loop over energy bins positions
  264 + for (int i = 0; i < m_ebounds.size(); ++i) {
  265 +
  266 + int num_gradient = 0;
  267 +
  268 + // Get the energy of current bin
  269 + GEnergy energy = m_ebounds.elogmean(i);
  270 +
  271 + // Header for verbose logging
  272 + if (logExplicit()) {
  273 + std::string msg = "Computing butterfly for bin number "+gammalib::str(i)+
  274 + " at "+energy.print();
  275 + log << std::endl;
  276 + log.header2(msg);
  277 + }
  278 +
  279 + // Initialise model flux value
  280 + double model_flux = 0.0;
  281 +
  282 + // Loop over models
  283 + for (int j = 0; j < models.size(); ++j ) {
  284 +
  285 + // Check wether model is a skymodel
  286 + GModelSky* skymodel = dynamic_cast<GModelSky*>(models[j]);
  287 +
  288 + // Yes ...
  289 + if (skymodel != NULL) {
  290 +
  291 + // Skip spatial models
  292 + num_gradient += skymodel->spatial()->size();
  293 +
  294 + // Get pointer to spectral model
  295 + GModelSpectral* spectral = skymodel->spectral();
  296 +
  297 + // Set flux value of source of interest
  298 + if (skymodel->name() == m_srcname) {
  299 + model_flux = spectral->eval_gradients(energy, time);
  300 + } // endif: model was source of interest
  301 +
  302 + // Loop over model parameters, get gradients
  303 + // and assign them to the vector
  304 + for (int k = 0; k < spectral->size(); ++k) {
  305 +
  306 + grad[num_gradient] = (*spectral)[k].gradient();
  307 + num_gradient += 1;
  308 +
  309 + }// endfor: loop over spectral parameters
  310 +
  311 + // Skip temporal models
  312 + num_gradient += skymodel->temporal()->size();
  313 +
  314 + } // endif: model was sky model
  315 +
  316 + else {
  317 +
  318 + // Skip other models (e.g. GModelData instances)
  319 + num_gradient += models[j]->size();
  320 +
  321 + } // endelse: Model was not GModelSky
  322 +
  323 + } // endfor: Looped over models
  324 +
  325 + // Multiply covariance to the gradient vector
  326 + GVector vector = m_covariance * grad;
  327 +
  328 + // Get the error from the scalar product
  329 + double error = std::sqrt(grad * vector);
  330 +
  331 + // Store flux, value and energy for saving
  332 + m_fluxes.push_back(model_flux);
  333 + m_energies.push_back(energy.MeV());
  334 + m_errors.push_back(error);
  335 +
  336 + // Log information
  337 + if (logExplicit()) {
  338 + log << " Flux at ";
  339 + log << energy.print();
  340 + log << ": ";
  341 + log << model_flux;
  342 + log << " +- ";
  343 + log << error;
  344 + log << " ph/cm2/s/MeV";
  345 + }
  346 +
  347 + } //endfor: loop over energy bin
  348 +
  349 + // Return
  350 + return;
  351 +}
  352 +
  353 +
  354 +/***********************************************************************//**
  355 + * @brief Save maps
  356 + *
  357 + * This method saves the butterfly into an ascii file
  358 + ***************************************************************************/
  359 +void ctbutterfly::save(void)
  360 +{
  361 + // Write header
  362 + if (logTerse()) {
  363 + log << std::endl;
  364 + log.header1("Save Butterfly to file");
  365 + }
  366 +
  367 + // Get output filename
  368 + m_outfile = (*this)["outfile"].filename();
  369 +
  370 + if (gammalib::file_exists(m_outfile)) {
  371 +
  372 + if ((*this)["clobber"].boolean()) {
  373 + std::remove(m_outfile.c_str());
  374 + }
  375 + else {
  376 + std::string msg = "File \""+m_outfile+"\" already exists and clobber is set to \"false\"";
  377 + throw GException::file_open_error(G_SAVE,msg);
  378 + }
  379 + }
  380 +
  381 + // Create file instance
  382 + std::fstream file;
  383 +
  384 + file.open(m_outfile, std::fstream::out | std::fstream::app);
  385 +
  386 + // Write short header
  387 + file << "# Energy [MeV] | flux [ph/cm2/s/MeV] | e_flux [ph/cm2/s/MeV]" << std::endl;
  388 +
  389 + // Write values to file
  390 + for (int i = 0; i < m_fluxes.size(); ++i) {
  391 +
  392 + file << m_energies[i] << " " << m_fluxes[i] << " " << m_errors[i] << std::endl;
  393 + }
  394 +
  395 + // close file
  396 + file.close();
  397 +
  398 + // Return
  399 + return;
  400 +}
  401 +
  402 +
  403 +/*==========================================================================
  404 + = =
  405 + = Private methods =
  406 + = =
  407 + ==========================================================================*/
  408 +
  409 +/***********************************************************************//**
  410 + * @brief Initialise class members
  411 + ***************************************************************************/
  412 +void ctbutterfly::init_members(void)
  413 +{
  414 + // Initialise members
  415 + m_infile.clear();
  416 + m_outfile.clear();
  417 + m_srcname.clear();
  418 + m_ebounds.clear();
  419 +
  420 + // Initialise protected members
  421 + m_obs.clear();
  422 + m_covariance.clear();
  423 + m_fluxes.clear();
  424 + m_energies.clear();
  425 + m_errors.clear();
  426 +
  427 + // Return
  428 + return;
  429 +}
  430 +
  431 +
  432 +/***********************************************************************//**
  433 + * @brief Copy class members
  434 + *
  435 + * @param[in] app Application.
  436 + ***************************************************************************/
  437 +void ctbutterfly::copy_members(const ctbutterfly& app)
  438 +{
  439 + // Copy attributes
  440 + m_infile = app.m_infile;
  441 + m_outfile = app.m_outfile;
  442 + m_srcname = app.m_srcname;
  443 + m_ebounds = app.m_ebounds;
  444 +
  445 + // Copy protected members
  446 + m_obs = app.m_obs;
  447 + m_covariance = app.m_covariance;
  448 + m_fluxes = app.m_fluxes;
  449 + m_energies = app.m_energies;
  450 + m_errors = app.m_errors;
  451 +
  452 + // Return
  453 + return;
  454 +}
  455 +
  456 +
  457 +/***********************************************************************//**
  458 + * @brief Delete class members
  459 + ***************************************************************************/
  460 +void ctbutterfly::free_members(void)
  461 +{
  462 + // Return
  463 + return;
  464 +}
  465 +
  466 +
  467 +/***********************************************************************//**
  468 + * @brief Get application parameters
  469 + *
  470 + * @exception GException::invalid_value
  471 + * Test source not found or no RA/DEC parameters found for test
  472 + * source.
  473 + *
  474 + * Get all task parameters from parameter file or (if required) by querying
  475 + * the user. Most parameters are only required if no observation exists so
  476 + * far in the observation container. In this case, a single CTA observation
  477 + * will be added to the container, using the definition provided in the
  478 + * parameter file.
  479 + ***************************************************************************/
  480 +void ctbutterfly::get_parameters(void)
  481 +{
  482 + // If there are no observations in container then add a single CTA
  483 + // observation using the parameters from the parameter file
  484 + if (m_obs.size() == 0) {
  485 +
  486 + // Allocate CTA observation
  487 + GCTAObservation obs;
  488 +
  489 + // Get event file name
  490 + std::string filename = (*this)["infile"].filename();
  491 +
  492 + // Try first to open as FITS file
  493 + try {
  494 +
  495 + // Load data
  496 + obs.load(filename);
  497 +
  498 + // Set response
  499 + set_obs_response(&obs);
  500 +
  501 + // Append observation to container
  502 + m_obs.append(obs);
  503 +
  504 + }
  505 +
  506 + // ... otherwise try to open as XML file
  507 + catch (GException::fits_open_error &e) {
  508 +
  509 + // Load observations from XML file
  510 + m_obs.load(filename);
  511 +
  512 + // Check if all observations have response information. If
  513 + // not, get the calibration database parameters and set
  514 + // the response properly
  515 + set_response(m_obs);
  516 +
  517 + } // endcatch: file was an XML file
  518 +
  519 + } // endif: there was no observation in the container
  520 +
  521 + // If there is are no models associated with the observations then
  522 + // load now the model definition
  523 + if (m_obs.models().size() == 0) {
  524 +
  525 + // Get models XML filename
  526 + std::string filename = (*this)["srcmdl"].filename();
  527 +
  528 + // Setup models for optimizing.
  529 + m_obs.models(GModels(filename));
  530 +
  531 + } // endif: no models were associated with observations
  532 +
  533 + // Get name of test source and check container for this name
  534 + m_srcname = (*this)["srcname"].string();
  535 + if (!m_obs.models().contains(m_srcname)) {
  536 + std::string msg = "Source \""+m_srcname+"\" not found in model "
  537 + "container. Please add a source with that name "
  538 + "or check for a possible typos.";
  539 + throw GException::invalid_value(G_GET_PARAMETERS, msg);
  540 + }
  541 +
  542 + // get binning information
  543 + m_ebounds = get_ebounds();
  544 +
  545 + // Get matrix file name and load if possible
  546 + std::string matrixfilename = (*this)["matrix"].filename();
  547 + if (matrixfilename != "NONE") {
  548 + std::string msg = "Loading of matrix from file not implemented yet. "
  549 + "Use filename = \"NONE\" to induce a recomputation of "
  550 + "the matrix internally.";
  551 + throw GException::feature_not_implemented(G_GET_PARAMETERS, msg);
  552 + // m_covariance.load(matrixfilename);
  553 + }
  554 +
  555 + // Optionally read ahead parameters so that they get correctly
  556 + // dumped into the log file
  557 + if (read_ahead()) {
  558 + m_outfile = (*this)["outfile"].filename();
  559 + }
  560 +
  561 + // Return
  562 + return;
  563 +}
  564 +
src/ctbutterfly/ctbutterfly.hpp 0 → 100644
  1 +/***************************************************************************
  2 + * ctbutterfly - butterfly calculation tool *
  3 + * ----------------------------------------------------------------------- *
  4 + * copyright (C) 2014 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 ctbutterfly.hpp
  23 + * @brief Butterfly calculation tool interface definition
  24 + * @author Michael Mayer
  25 + */
  26 +
  27 +#ifndef CTBUTTERFLY_HPP
  28 +#define CTBUTTERFLY_HPP
  29 +
  30 +/* __ Includes ___________________________________________________________ */
  31 +#include "GammaLib.hpp"
  32 +#include "GCTALib.hpp"
  33 +#include "ctool.hpp"
  34 +
  35 +/* __Definitions _________________________________________________________ */
  36 +#define CTBUTTERFLY_NAME "ctbutterfly"
  37 +#define CTBUTTERFLY_VERSION "00-01-00"
  38 +
  39 +
  40 +/***********************************************************************//**
  41 + * @class ctbutterfly
  42 + *
  43 + * @brief butterfly calculation tool
  44 + *
  45 + * This class computes the confidence interval of a fitted spectrum
  46 + * (butterfly) for a given set of observations
  47 + *
  48 + * The class operates on predefined observation containers, an individual
  49 + * event list or an observation definition XML file.
  50 + *
  51 + * During the computation the covariance matrix of the fit is used to propagate
  52 + * uncertainties and their correlations through the entire energy range.
  53 + * The output is saved as an ascii files containing the confidence band boundaries
  54 + ***************************************************************************/
  55 +class ctbutterfly : public ctool {
  56 +
  57 +public:
  58 + // Constructors and destructors
  59 + ctbutterfly(void);
  60 + explicit ctbutterfly(const GObservations& obs);
  61 + ctbutterfly(int argc, char *argv[]);
  62 + ctbutterfly(const ctbutterfly& app);
  63 + virtual ~ctbutterfly(void);
  64 +
  65 + // Operators
  66 + ctbutterfly& operator=(const ctbutterfly& app);
  67 +
  68 + // Methods
  69 + void clear(void);
  70 + void run(void);
  71 + void save(void);
  72 + const GObservations& obs(void) const;
  73 +
  74 +protected:
  75 + // Protected methods
  76 + void init_members(void);
  77 + void copy_members(const ctbutterfly& app);
  78 + void free_members(void);
  79 + void get_parameters(void);
  80 +
  81 + // User parameters
  82 + std::string m_infile; //!< Input file
  83 + std::string m_srcname; //!< Name of source to compute butterfly
  84 + std::string m_outfile; //!< Output ascii file
  85 +
  86 + GEbounds m_ebounds; //!< Energy binning definition
  87 +
  88 + // Protected members
  89 + GObservations m_obs; //!< Observation container
  90 + GMatrixSparse m_covariance; //!< covariance matrix
  91 +
  92 + std::vector<double> m_energies; //!< energy values for storage
  93 + std::vector<double> m_fluxes; //!< flux values per energy bin
  94 + std::vector<double> m_errors; //!< flux errors per energy bin
  95 +};
  96 +
  97 +/***********************************************************************//**
  98 + * @brief Return observation container
  99 + *
  100 + * @return Reference to observation container
  101 + ***************************************************************************/
  102 +inline
  103 +const GObservations& ctbutterfly::obs(void) const
  104 +{
  105 + return m_obs;
  106 +}
  107 +
  108 +#endif /* CTBUTTERFLY_HPP */
src/ctbutterfly/ctbutterfly.par 0 → 100644
  1 +#############################################################################
  2 +# #
  3 +# CTA Science Analysis Tools #
  4 +# #
  5 +# ------------------------------------------------------------------------- #
  6 +# #
  7 +# File: ctbutterfly #
  8 +# Version: 00-01-00 #
  9 +# #
  10 +# Author: Michael Mayer #
  11 +# michael.mayer@physik.hu-berlin.de #
  12 +# HU Berlin #
  13 +# #
  14 +# Purpose: Parameter file for the ctbutterfly application #
  15 +# #
  16 +#############################################################################
  17 +#
  18 +# General parameters
  19 +#===================
  20 +infile, f, a, "events.fits",,,"Input event list, cube or observation definition file"
  21 +srcmdl, f, a, "$CTOOLS/share/models/crab.xml",,, "Source model"
  22 +srcname, s, a, "CrabNebula",,,"Source of interest"
  23 +caldb, s, a, "dummy",,, "Calibration database"
  24 +irf, s, a, "cta_dummy_irf",,, "Instrument response function"
  25 +outfile, f, a, "butterfly.txt",,, "Output ascii file"
  26 +matrix, f, h, "NONE",,, "Input covariance Matrix FITS file"
  27 +
  28 +#
  29 +# Energy binning parameters
  30 +#==========================
  31 +ebinalg, s, h, "LOG", FILE|LIN|LOG,,"Algorithm for defining energy bins"
  32 +emin, r, a, 0.1,,,"Start value for first energy bin in TeV"
  33 +emax, r, a, 100.0,,,"Stop value for last energy bin in TeV"
  34 +enumbins, i, h, 100,,,"Number of energy bins"
  35 +ebinfile, f, h, "NONE",,,"Name of the file containing the energy bin definition"
  36 +
  37 +#
  38 +# Standard parameters
  39 +#====================
  40 +chatter, i, h, 2,0,4, "Chattiness of output"
  41 +clobber, b, h, yes,,, "Overwrite existing output files with new output files?"
  42 +debug, b, h, no,,, "Debugging mode activated"
  43 +mode, s, h, "ql",,, "Mode of automatic parameters"
  44 +logfile, f, h, "ctbutterfly.log",,, "Log filename"
src/ctbutterfly/main.cpp 0 → 100644
  1 +/***************************************************************************
  2 + * ctbutterfly - TS map calculation tool *
  3 + * ----------------------------------------------------------------------- *
  4 + * copyright (C) 2014 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 ctbutterfly/main.cpp
  23 + * @brief CTA butterfly computation tool
  24 + * @author Michael Mayer
  25 + */
  26 +
  27 +/* __ Includes ___________________________________________________________ */
  28 +#ifdef HAVE_CONFIG_H
  29 +#include <config.h>
  30 +#endif
  31 +#include <cstdio>
  32 +#include "ctbutterfly.hpp"
  33 +
  34 +
  35 +/***********************************************************************//**
  36 + * @brief Main entry point of application
  37 + *
  38 + * @param[in] argc Number of command line arguments.
  39 + * @param[in] argv Command line arguments.
  40 + *
  41 + * This is the main entry point of the ctbutterfly application. It allocates a
  42 + * ctbutterfly object and runs the application.
  43 + ***************************************************************************/
  44 +int main (int argc, char *argv[])
  45 +{
  46 + // Initialise return code
  47 + int rc = 1;
  48 +
  49 + // Create instance of application
  50 + ctbutterfly application(argc, argv);
  51 +
  52 + // Run application
  53 + try {
  54 + // Execute application
  55 + application.execute();
  56 +
  57 + // Signal success
  58 + rc = 0;
  59 + }
  60 + catch (std::exception &e) {
  61 +
  62 + // Extract error message
  63 + std::string message = e.what();
  64 + std::string signal = "*** ERROR encounterted in the execution of"
  65 + " ctbutterfly. Run aborted ...";
  66 +
  67 + // Write error in logger
  68 + application.log << signal << std::endl;
  69 + application.log << message << std::endl;
  70 +
  71 + // Write error on standard output
  72 + std::cout << signal << std::endl;
  73 + std::cout << message << std::endl;
  74 +
  75 + } // endcatch: catched any application error
  76 +
  77 + // Return
  78 + return rc;
  79 +}
src/ctobssim/ctobssim.cpp
@@ -791,6 +791,7 @@ void ctobssim::simulate_source(GCTAObservation* obs, const GModels&amp; models, @@ -791,6 +791,7 @@ void ctobssim::simulate_source(GCTAObservation* obs, const GModels&amp; models,
791 photons[i], 791 photons[i],
792 *obs, 792 *obs,
793 ran); 793 ran);
  794 +
794 if (event != NULL) { 795 if (event != NULL) {
795 796
796 // Use event only if it falls within ROI 797 // Use event only if it falls within ROI
test/test_ctbutterfly.py 0 → 100755
  1 +#! /usr/bin/env python
  2 +# ==========================================================================
  3 +# This scripts performs unit tests for the ctbutterfly tool.
  4 +#
  5 +# Copyright (C) 2014 Juergen Knoedlseder
  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 +import gammalib
  22 +import ctools
  23 +
  24 +
  25 +# ========================== #
  26 +# Test class for ctbutterfly tool #
  27 +# ========================== #
  28 +class Test(gammalib.GPythonTestSuite):
  29 + """
  30 + Test class for ctbutterfly tool.
  31 + """
  32 + # Constructor
  33 + def __init__(self):
  34 + """
  35 + Constructor.
  36 + """
  37 + # Call base class constructor
  38 + gammalib.GPythonTestSuite.__init__(self)
  39 +
  40 + # Set members
  41 + self.events_name = "data/crab_events.fits"
  42 + self.model_name = "data/crab.xml"
  43 + self.caldb = "irf"
  44 + self.irf = "cta_dummy_irf"
  45 +
  46 + # Return
  47 + return
  48 +
  49 + # Set test functions
  50 + def set(self):
  51 + """
  52 + Set all test functions.
  53 + """
  54 + # Set test name
  55 + self.name("ctbutterfly")
  56 +
  57 + # Append tests
  58 + self.append(self.test_functional, "Test ctbutterfly functionality")
  59 +
  60 + # Return
  61 + return
  62 +
  63 + # Test ctbutterfly functionnality
  64 + def test_functional(self):
  65 + """
  66 + Test ctbutterfly functionnality.
  67 + """
  68 + # Set-up ctbutterfly
  69 + butterfly = ctools.ctbutterfly()
  70 + butterfly["infile"].filename(self.events_name)
  71 + butterfly["srcmdl"].filename(self.model_name)
  72 + butterfly["srcname"].string("Crab")
  73 + butterfly["caldb"].string(self.caldb)
  74 + butterfly["irf"].string(self.irf)
  75 + butterfly["emin"].real(0.1)
  76 + butterfly["emax"].real(100)
  77 + butterfly["outfile"].filename("butterfly.txt")
  78 +
  79 + # Run tool
  80 + self.test_try("Run ctbutterfly")
  81 + try:
  82 + butterfly.run()
  83 + self.test_try_success()
  84 + except:
  85 + self.test_try_failure("Exception occured in butterfly.")
  86 +
  87 + # Save results
  88 + self.test_try("Save results")
  89 + try:
  90 + butterfly.save()
  91 + self.test_try_success()
  92 + except:
  93 + self.test_try_failure("Exception occured in saving results.")
  94 +
  95 + # Return
  96 + return
test/test_ctools.sh
@@ -45,6 +45,7 @@ ctexpcube=../src/ctexpcube/ctexpcube @@ -45,6 +45,7 @@ ctexpcube=../src/ctexpcube/ctexpcube
45 ctpsfcube=../src/ctpsfcube/ctpsfcube 45 ctpsfcube=../src/ctpsfcube/ctpsfcube
46 ctbkgcube=../src/ctbkgcube/ctbkgcube 46 ctbkgcube=../src/ctbkgcube/ctbkgcube
47 ctcubemask=../src/ctcubemask/ctcubemask 47 ctcubemask=../src/ctcubemask/ctcubemask
  48 +ctbutterfly=../src/ctbutterfly/ctbutterfly
48 49
49 50
50 # 51 #
@@ -542,3 +543,27 @@ else @@ -542,3 +543,27 @@ else
542 exit 1 543 exit 1
543 fi 544 fi
544 $ECHO " ok" 545 $ECHO " ok"
  546 +
  547 +
  548 +
  549 +#
  550 +# Test ctbutterfly
  551 +# ===============
  552 +$ECHO -n "Test ctbutterfly: "
  553 +$ctbutterfly infile="data/crab_events.fits.gz" \
  554 +srcmdl="data/crab.xml" \
  555 +srcname="Crab" \
  556 +outfile="butterfly.txt" \
  557 +caldb="irf" \
  558 +irf="cta_dummy_irf" \
  559 +emin=0.1 \
  560 +emax=100.0
  561 +$ECHO -n "."
  562 +if [ -s "butterfly.txt" ]
  563 +then
  564 + $ECHO -n "."
  565 +else
  566 + $ECHO " butterfly.txt file is not valid"
  567 + exit 1
  568 +fi
  569 +$ECHO " ok"
test/test_cttsmap.py
@@ -40,7 +40,7 @@ class Test(gammalib.GPythonTestSuite): @@ -40,7 +40,7 @@ class Test(gammalib.GPythonTestSuite):
40 # Set members 40 # Set members
41 self.events_name = "data/crab_events.fits" 41 self.events_name = "data/crab_events.fits"
42 self.model_name = "data/crab.xml" 42 self.model_name = "data/crab.xml"
43 - self.caldb = "irf" 43 + self.caldb = "dummy"
44 self.irf = "cta_dummy_irf" 44 self.irf = "cta_dummy_irf"
45 45
46 # Return 46 # Return
test/test_python.py
@@ -34,6 +34,7 @@ import test_ctpsfcube @@ -34,6 +34,7 @@ import test_ctpsfcube
34 import test_ctbkgcube 34 import test_ctbkgcube
35 import test_ctcubemask 35 import test_ctcubemask
36 import test_pipelines 36 import test_pipelines
  37 +import test_ctbutterfly
37 38
38 39
39 # ======================== # 40 # ======================== #
@@ -59,6 +60,7 @@ if __name__ == &#39;__main__&#39;: @@ -59,6 +60,7 @@ if __name__ == &#39;__main__&#39;:
59 suite_ctbkgcube = test_ctbkgcube.Test() 60 suite_ctbkgcube = test_ctbkgcube.Test()
60 suite_ctcubemask = test_ctcubemask.Test() 61 suite_ctcubemask = test_ctcubemask.Test()
61 suite_pipelines = test_pipelines.Test() 62 suite_pipelines = test_pipelines.Test()
  63 + suite_ctbutterfly = test_ctbutterfly.Test()
62 64
63 # Setup unit tests 65 # Setup unit tests
64 suite_ctobssim.set() 66 suite_ctobssim.set()
@@ -73,6 +75,7 @@ if __name__ == &#39;__main__&#39;: @@ -73,6 +75,7 @@ if __name__ == &#39;__main__&#39;:
73 suite_ctbkgcube.set() 75 suite_ctbkgcube.set()
74 suite_ctcubemask.set() 76 suite_ctcubemask.set()
75 suite_pipelines.set() 77 suite_pipelines.set()
  78 + suite_ctbutterfly.set()
76 79
77 # Append tests to container 80 # Append tests to container
78 suites.append(suite_ctobssim) 81 suites.append(suite_ctobssim)
@@ -87,6 +90,7 @@ if __name__ == &#39;__main__&#39;: @@ -87,6 +90,7 @@ if __name__ == &#39;__main__&#39;:
87 suites.append(suite_ctbkgcube) 90 suites.append(suite_ctbkgcube)
88 suites.append(suite_ctcubemask) 91 suites.append(suite_ctcubemask)
89 suites.append(suite_pipelines) 92 suites.append(suite_pipelines)
  93 + suites.append(suite_ctbutterfly)
90 94
91 # Set PFILES environment variable 95 # Set PFILES environment variable
92 try: 96 try: