Commit c4c3ef0d03affb1b7a42d608b0eee0b1efe3f499

Authored by Jürgen Knödlseder
1 parent 8dab5cb9

Complete ctexpcube tools and add unit test.

The ctexpcube tool is now functional, a unit test has been added.
pyext/ctexpcube.i 0 → 100644
  1 +/***************************************************************************
  2 + * ctexpcube - CTA exposure cube tool *
  3 + * ----------------------------------------------------------------------- *
  4 + * copyright (C) 2014 by Juergen Knoedlseder *
  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 ctexpcube.i
  23 + * @brief CTA exposure cube tool definition
  24 + * @author Juergen Knoedlseder
  25 + */
  26 +%{
  27 +/* Put headers and other declarations here that are needed for compilation */
  28 +#include "ctexpcube.hpp"
  29 +#include "GTools.hpp"
  30 +%}
  31 +
  32 +
  33 +/***********************************************************************//**
  34 + * @class ctexpcube
  35 + *
  36 + * @brief CTA exposure cube tool
  37 + ***************************************************************************/
  38 +class ctexpcube : public GApplication {
  39 +
  40 +public:
  41 + // Constructors and destructors
  42 + ctexpcube(void);
  43 + explicit ctexpcube(GObservations obs);
  44 + ctexpcube(int argc, char *argv[]);
  45 + ctexpcube(const ctexpcube& app);
  46 + virtual ~ctexpcube(void);
  47 +
  48 + // Operators
  49 + ctexpcube& operator=(const ctexpcube& app);
  50 +
  51 + // Methods
  52 + void clear(void);
  53 + void execute(void);
  54 + void run(void);
  55 + void save(void);
  56 + GObservations& obs(void);
  57 + void get_parameters(void);
  58 + void get_obs(void);
  59 + void set_response(void);
  60 + void get_ebounds(void);
  61 + void set_from_cntmap(const std::string& filename);
  62 +};
  63 +
  64 +
  65 +/***********************************************************************//**
  66 + * @brief CTA exposure map tool Python extension
  67 + ***************************************************************************/
  68 +%extend ctexpcube {
  69 + ctexpcube copy() {
  70 + return (*self);
  71 + }
  72 +}
pyext/ctools/ctools.i
1 /*************************************************************************** 1 /***************************************************************************
2 * ctools - SWIG file * 2 * ctools - SWIG file *
3 * ----------------------------------------------------------------------- * 3 * ----------------------------------------------------------------------- *
4 - * copyright (C) 2010-2013 by Juergen Knoedlseder * 4 + * copyright (C) 2010-2014 by Juergen Knoedlseder *
5 * ----------------------------------------------------------------------- * 5 * ----------------------------------------------------------------------- *
6 * * 6 * *
7 * This program is free software: you can redistribute it and/or modify * 7 * This program is free software: you can redistribute it and/or modify *
@@ -51,3 +51,4 @@ @@ -51,3 +51,4 @@
51 %include "ctmodel.i" 51 %include "ctmodel.i"
52 %include "ctselect.i" 52 %include "ctselect.i"
53 %include "ctskymap.i" 53 %include "ctskymap.i"
  54 +%include "ctexpcube.i"
src/ctexpcube/ctexpcube
No preview for this file type
src/ctexpcube/ctexpcube.cpp
@@ -31,13 +31,12 @@ @@ -31,13 +31,12 @@
31 #include <cstdio> 31 #include <cstdio>
32 #include "ctexpcube.hpp" 32 #include "ctexpcube.hpp"
33 #include "GTools.hpp" 33 #include "GTools.hpp"
  34 +#include "GWcs.hpp"
34 35
35 /* __ Method name definitions ____________________________________________ */ 36 /* __ Method name definitions ____________________________________________ */
36 #define G_GET_EBOUNDS "ctexpcube::get_ebounds()" 37 #define G_GET_EBOUNDS "ctexpcube::get_ebounds()"
37 -  
38 -  
39 -#define G_SETUP_OBS "ctexpcube::setup_obs()"  
40 -#define G_MODEL_MAP "ctexpcube::model_map(GCTAObservation*)" 38 +#define G_GET_PARAMETERS "ctexpcube::get_parameters()"
  39 +#define G_SET_FROM_CNTMAP "ctexpcube::set_from_cntmap(std::string&)"
41 40
42 /* __ Debug definitions __________________________________________________ */ 41 /* __ Debug definitions __________________________________________________ */
43 42
@@ -276,37 +275,8 @@ void ctexpcube::run(void) @@ -276,37 +275,8 @@ void ctexpcube::run(void)
276 log.header1("Generate exposure cube"); 275 log.header1("Generate exposure cube");
277 } 276 }
278 277
279 - // Initialise observation counter  
280 - int n_observations = 0;  
281 -  
282 - // Loop over all observations in the container  
283 - for (int i = 0; i < m_obs.size(); ++i) {  
284 -  
285 - // Get CTA observation  
286 - GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]);  
287 -  
288 - // Continue only if observation is a CTA observation  
289 - if (obs != NULL) {  
290 -  
291 - // Write header for observation  
292 - if (logTerse()) {  
293 - if (obs->name().length() > 1) {  
294 - log.header3("Observation "+obs->name());  
295 - }  
296 - else {  
297 - log.header3("Observation");  
298 - }  
299 - }  
300 -  
301 - // Increment number of observations  
302 - n_observations++;  
303 -  
304 - // Generate exposure cube  
305 - //model_map(obs, m_obs.models());  
306 -  
307 - } // endif: CTA observation found  
308 -  
309 - } // endfor: looped over observations 278 + // Fill exposure
  279 + m_expcube.fill(m_obs);
310 280
311 // Restore energy dispersion flag for all CTA observations 281 // Restore energy dispersion flag for all CTA observations
312 for (int i = 0; i < m_obs.size(); ++i) { 282 for (int i = 0; i < m_obs.size(); ++i) {
@@ -349,24 +319,27 @@ void ctexpcube::save(void) @@ -349,24 +319,27 @@ void ctexpcube::save(void)
349 * 319 *
350 * Get all task parameters from parameter file or (if required) by querying 320 * Get all task parameters from parameter file or (if required) by querying
351 * the user. The parameters are read in the correct order. 321 * the user. The parameters are read in the correct order.
  322 + *
  323 + * @todo Setup exposure cube from counts map
352 ***************************************************************************/ 324 ***************************************************************************/
353 void ctexpcube::get_parameters(void) 325 void ctexpcube::get_parameters(void)
354 { 326 {
355 // If we do not have any observations in the container then get an 327 // If we do not have any observations in the container then get an
356 // input file name or observation descriptor file 328 // input file name or observation descriptor file
357 if (m_obs.size() == 0) { 329 if (m_obs.size() == 0) {
358 - m_infile = (*this)["infile"].filename(); 330 + get_obs();
359 } 331 }
360 332
361 - // Read response parameters  
362 - m_caldb = (*this)["caldb"].string();  
363 - m_irf = (*this)["irf"].string(); 333 + // Make sure that response is set
  334 + set_response();
  335 +
  336 + // Read energy dispersion flag
364 m_apply_edisp = (*this)["edisp"].boolean(); 337 m_apply_edisp = (*this)["edisp"].boolean();
365 338
366 // If no counts map is specified then setup the exposure cube from 339 // If no counts map is specified then setup the exposure cube from
367 // the user parameters 340 // the user parameters
368 - m_cntmap = (*this)["cntmap"].filename();  
369 - if ((m_cntmap == "NONE") || (gammalib::strip_whitespace(m_cntmap) == "")) { 341 + std::string cntmap = (*this)["cntmap"].filename();
  342 + if ((cntmap == "NONE") || (gammalib::strip_whitespace(cntmap) == "")) {
370 343
371 // Get user parameters for counts map definition 344 // Get user parameters for counts map definition
372 std::string wcs = (*this)["proj"].string(); 345 std::string wcs = (*this)["proj"].string();
@@ -388,6 +361,10 @@ void ctexpcube::get_parameters(void) @@ -388,6 +361,10 @@ void ctexpcube::get_parameters(void)
388 361
389 // ... otherwise setup the exposure cube from the counts map 362 // ... otherwise setup the exposure cube from the counts map
390 else { 363 else {
  364 +
  365 + // Set exposure cube from counts map
  366 + set_from_cntmap(cntmap);
  367 +
391 } 368 }
392 369
393 // Read output filename (if needed) 370 // Read output filename (if needed)
@@ -401,8 +378,98 @@ void ctexpcube::get_parameters(void) @@ -401,8 +378,98 @@ void ctexpcube::get_parameters(void)
401 378
402 379
403 /***********************************************************************//** 380 /***********************************************************************//**
  381 + * @brief Get observation definition
  382 + *
  383 + * Get observation definition from the user parameters.
  384 + ***************************************************************************/
  385 +void ctexpcube::get_obs(void)
  386 +{
  387 + // Get input filename
  388 + std::string filename = (*this)["infile"].filename();
  389 +
  390 + // Try first to open as FITS file
  391 + try {
  392 +
  393 + // Allocate CTA observation
  394 + GCTAObservation obs;
  395 +
  396 + // Load input file in CTA observation
  397 + obs.load(filename);
  398 +
  399 + // Append CTA observation to container
  400 + m_obs.append(obs);
  401 +
  402 +
  403 + }
  404 +
  405 + // ... otherwise try to open as XML file
  406 + catch (GException::fits_open_error &e) {
  407 +
  408 + // Load observations from XML file
  409 + m_obs.load(filename);
  410 +
  411 + }
  412 +
  413 + // Return
  414 + return;
  415 +}
  416 +
  417 +
  418 +/***********************************************************************//**
  419 + * @brief Set observation response
  420 + *
  421 + * Set response for all observations that so have no response.
  422 + ***************************************************************************/
  423 +void ctexpcube::set_response(void)
  424 +{
  425 + // Loop over all observations
  426 + for (int i = 0; i < m_obs.size(); ++i) {
  427 +
  428 + // Is this observation a CTA observation?
  429 + GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]);
  430 +
  431 + // Yes ...
  432 + if (obs != NULL) {
  433 +
  434 + // Set response if it isn't set already
  435 + if (obs->response().aeff() == NULL) {
  436 +
  437 + // Load response information
  438 + std::string database = (*this)["caldb"].string();
  439 + std::string irf = (*this)["irf"].string();
  440 +
  441 + // Set calibration database. If specified parameter is a
  442 + // directory then use this as the pathname to the calibration
  443 + // database. Otherwise interpret this as the instrument name,
  444 + // the mission being "cta"
  445 + GCaldb caldb;
  446 + if (gammalib::dir_exists(database)) {
  447 + caldb.rootdir(database);
  448 + }
  449 + else {
  450 + caldb.open("cta", database);
  451 + }
  452 +
  453 + // Set reponse
  454 + obs->response(irf, caldb);
  455 +
  456 + } // endif: observation already has a response
  457 +
  458 + } // endif: observation was a CTA observation
  459 +
  460 + } // endfor: looped over all observations
  461 +
  462 + // Return
  463 + return;
  464 +}
  465 +
  466 +
  467 +/***********************************************************************//**
404 * @brief Get energy boundaries from parameters 468 * @brief Get energy boundaries from parameters
405 * 469 *
  470 + * @exception GException::invalid_value
  471 + * Invalid extension name encountered.
  472 + *
406 * Get the energy boundaries from the user parameters. 473 * Get the energy boundaries from the user parameters.
407 ***************************************************************************/ 474 ***************************************************************************/
408 void ctexpcube::get_ebounds(void) 475 void ctexpcube::get_ebounds(void)
@@ -467,6 +534,74 @@ void ctexpcube::get_ebounds(void) @@ -467,6 +534,74 @@ void ctexpcube::get_ebounds(void)
467 } 534 }
468 535
469 536
  537 +/***********************************************************************//**
  538 + * @brief Set exposure cube definition from counts map
  539 + *
  540 + * @exception GException::invalid_value
  541 + * Invalid counts map projection or invalid events encountered.
  542 + *
  543 + * Set exposure cube definition from counts map.
  544 + ***************************************************************************/
  545 +void ctexpcube::set_from_cntmap(const std::string& filename)
  546 +{
  547 + // Allocate CTA observation
  548 + GCTAObservation obs;
  549 +
  550 + // Load counts map in CTA observation
  551 + obs.load(filename);
  552 +
  553 + // Set exposure cube from counts map
  554 + const GCTAEventCube* cube = dynamic_cast<const GCTAEventCube*>(obs.events());
  555 +
  556 + // Continue only if cube is valid
  557 + if (cube != NULL) {
  558 +
  559 + // Get sky map projection
  560 + const GWcs* wcs = dynamic_cast<const GWcs*>(cube->map().projection());
  561 +
  562 + // Continue only if projection is valid
  563 + if (wcs != NULL) {
  564 +
  565 + // Get user parameters for counts map definition
  566 + std::string proj = wcs->code();
  567 + std::string coordsys = wcs->coordsys();
  568 + double xref = wcs->crval(0);
  569 + double yref = wcs->crval(1);
  570 + double dx = wcs->cdelt(0);
  571 + double dy = wcs->cdelt(1);
  572 + int nx = cube->map().nx();
  573 + int ny = cube->map().ny();
  574 +
  575 + // Get energy definition
  576 + m_ebounds = cube->ebounds();
  577 +
  578 + // Define exposure cube
  579 + m_expcube = GCTAExposure(proj, coordsys, xref, yref,
  580 + dx, dy, nx, ny,
  581 + m_ebounds);
  582 +
  583 + } // endif: WCS projection was valid
  584 +
  585 + // ... projection is not of WCS type
  586 + else {
  587 + std::string msg = "Counts map project is not of WCS type.";
  588 + throw GException::invalid_value(G_SET_FROM_CNTMAP, msg);
  589 + }
  590 +
  591 + } // endif: observation contained an events cube
  592 +
  593 + // ... there is not events cube
  594 + else {
  595 + std::string msg = "No events cube found in file \""
  596 + ""+filename+"\".";
  597 + throw GException::invalid_value(G_SET_FROM_CNTMAP, msg);
  598 + }
  599 +
  600 + // Return
  601 + return;
  602 +}
  603 +
  604 +
470 /*========================================================================== 605 /*==========================================================================
471 = = 606 = =
472 = Private methods = 607 = Private methods =
@@ -479,10 +614,7 @@ void ctexpcube::get_ebounds(void) @@ -479,10 +614,7 @@ void ctexpcube::get_ebounds(void)
479 void ctexpcube::init_members(void) 614 void ctexpcube::init_members(void)
480 { 615 {
481 // Initialise members 616 // Initialise members
482 - m_infile.clear();  
483 m_outfile.clear(); 617 m_outfile.clear();
484 - m_caldb.clear();  
485 - m_irf.clear();  
486 m_apply_edisp = false; 618 m_apply_edisp = false;
487 619
488 // Initialise protected members 620 // Initialise protected members
@@ -507,10 +639,7 @@ void ctexpcube::init_members(void) @@ -507,10 +639,7 @@ void ctexpcube::init_members(void)
507 void ctexpcube::copy_members(const ctexpcube& app) 639 void ctexpcube::copy_members(const ctexpcube& app)
508 { 640 {
509 // Copy attributes 641 // Copy attributes
510 - m_infile = app.m_infile;  
511 m_outfile = app.m_outfile; 642 m_outfile = app.m_outfile;
512 - m_caldb = app.m_caldb;  
513 - m_irf = app.m_irf;  
514 m_apply_edisp = app.m_apply_edisp; 643 m_apply_edisp = app.m_apply_edisp;
515 644
516 // Copy protected members 645 // Copy protected members
src/ctexpcube/ctexpcube.hpp
@@ -61,7 +61,10 @@ public: @@ -61,7 +61,10 @@ public:
61 void save(void); 61 void save(void);
62 GObservations& obs(void) { return m_obs; } 62 GObservations& obs(void) { return m_obs; }
63 void get_parameters(void); 63 void get_parameters(void);
  64 + void get_obs(void);
  65 + void set_response(void);
64 void get_ebounds(void); 66 void get_ebounds(void);
  67 + void set_from_cntmap(const std::string& filename);
65 68
66 protected: 69 protected:
67 // Protected methods 70 // Protected methods
@@ -70,11 +73,7 @@ protected: @@ -70,11 +73,7 @@ protected:
70 void free_members(void); 73 void free_members(void);
71 74
72 // User parameters 75 // User parameters
73 - std::string m_infile; //!< Input counts map or XML file  
74 - std::string m_cntmap; //!< Counts map for exposure cube definition  
75 std::string m_outfile; //!< Output exposure cube file 76 std::string m_outfile; //!< Output exposure cube file
76 - std::string m_caldb; //!< Calibration database  
77 - std::string m_irf; //!< Instrument response functions  
78 bool m_apply_edisp; //!< Apply energy dispersion? 77 bool m_apply_edisp; //!< Apply energy dispersion?
79 78
80 // Protected members 79 // Protected members
src/ctexpcube/ctexpcube.par
@@ -17,7 +17,7 @@ @@ -17,7 +17,7 @@
17 # 17 #
18 # General parameters 18 # General parameters
19 #=================== 19 #===================
20 -infile, f, a, "NONE",,, "Input event list, counts map or observation definition file" 20 +infile, f, a, "NONE",,, "Observation definition file"
21 cntmap, f, a, "NONE",,, "Counts map for exposure cube definition" 21 cntmap, f, a, "NONE",,, "Counts map for exposure cube definition"
22 outfile, f, a, "expcube.fits",,, "Output exposure cube file" 22 outfile, f, a, "expcube.fits",,, "Output exposure cube file"
23 caldb, s, a, "dummy",,, "Calibration database" 23 caldb, s, a, "dummy",,, "Calibration database"
test/test_ctools.sh
@@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
2 # ========================================================================== 2 # ==========================================================================
3 # This script tests all ctools 3 # This script tests all ctools
4 # 4 #
5 -# Copyright (C) 2011-2012 Juergen Knoedlseder 5 +# Copyright (C) 2011-2014 Juergen Knoedlseder
6 # 6 #
7 # This program is free software: you can redistribute it and/or modify 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 8 # it under the terms of the GNU General Public License as published by
@@ -40,6 +40,7 @@ ctmodel=../src/ctmodel/ctmodel @@ -40,6 +40,7 @@ ctmodel=../src/ctmodel/ctmodel
40 ctobssim=../src/ctobssim/ctobssim 40 ctobssim=../src/ctobssim/ctobssim
41 ctselect=../src/ctselect/ctselect 41 ctselect=../src/ctselect/ctselect
42 ctskymap=../src/ctskymap/ctskymap 42 ctskymap=../src/ctskymap/ctskymap
  43 +ctexpcube=../src/ctexpcube/ctexpcube
43 44
44 45
45 # 46 #
@@ -340,4 +341,49 @@ else @@ -340,4 +341,49 @@ else
340 exit 1 341 exit 1
341 fi 342 fi
342 $ECHO " ok" 343 $ECHO " ok"
343 -#sleep 100 344 +
  345 +
  346 +#
  347 +# Test ctexpcube
  348 +# ==============
  349 +$ECHO -n "Test ctexpcube: "
  350 +#
  351 +# Run 1
  352 +$ctexpcube infile="data/crab_events.fits" \
  353 + cntmap="NONE" \
  354 + outfile="expcube1.fits" \
  355 + caldb="irf" \
  356 + irf="cta_dummy_irf" \
  357 + emin=0.1 \
  358 + emax=100.0 \
  359 + enumbins=20 \
  360 + nxpix=200 \
  361 + nypix=200 \
  362 + binsz=0.02 \
  363 + coordsys="CEL" \
  364 + xref=83.63 \
  365 + yref=22.01 \
  366 + proj="CAR"
  367 +$ECHO -n "."
  368 +if [ -s "expcube1.fits" ]
  369 +then
  370 + $ECHO -n "."
  371 +else
  372 + $ECHO " expcube1.fits file is not valid"
  373 + exit 1
  374 +fi
  375 +#
  376 +# Run 2
  377 +$ctexpcube infile="data/crab_events.fits" \
  378 + cntmap="data/crab_cntmap.fits" \
  379 + outfile="expcube2.fits" \
  380 + caldb="irf" \
  381 + irf="cta_dummy_irf"
  382 +$ECHO -n "."
  383 +if [ -s "expcube2.fits" ]
  384 +then
  385 + $ECHO -n "."
  386 +else
  387 + $ECHO " expcube2.fits file is not valid"
  388 + exit 1
  389 +fi