Commit 8256fabc49ca2b8ae9a509f06a510dbf3283f930

Authored by knodlseder
1 parent f06798cd

adapt to new GObservation/GEvents interfaces

src/ctselect/ctselect.cpp
... ... @@ -20,18 +20,13 @@
20 20 #ifdef HAVE_CONFIG_H
21 21 #include <config.h>
22 22 #endif
23   -#include <stdio.h>
  23 +#include <cstdio>
24 24 #include "ctselect.hpp"
25 25 #include "GTools.hpp"
26 26  
27 27 /* __ Debug definitions __________________________________________________ */
28   -#define BIT_COLUMN_TEST 0
29   -#define STRING_COLUMN_TEST 1
30 28  
31 29 /* __ Coding definitions _________________________________________________ */
32   -#define SELECT_TIME 1
33   -#define SELECT_ENERGY 1
34   -#define SELECT_ROI 1
35 30  
36 31  
37 32 /*==========================================================================
... ... @@ -57,6 +52,30 @@ ctselect::ctselect(void) : GApplication(CTSELECT_NAME, CTSELECT_VERSION)
57 52  
58 53  
59 54 /***********************************************************************//**
  55 + * @brief Observations constructor
  56 + *
  57 + * This constructor creates an instance of the class that is initialised from
  58 + * an observation container.
  59 + ***************************************************************************/
  60 +ctselect::ctselect(GObservations obs) : GApplication(CTSELECT_NAME, CTSELECT_VERSION)
  61 +{
  62 + // Initialise members
  63 + init_members();
  64 +
  65 + // Set observations
  66 + m_obs = obs;
  67 +
  68 + // Write header into logger
  69 + log_header();
  70 +
  71 + // Return
  72 + return;
  73 +}
  74 +
  75 +
  76 +
  77 +
  78 +/***********************************************************************//**
60 79 * @brief Command line constructor
61 80 *
62 81 * @param[in] argc Number of arguments in command line.
... ... @@ -77,6 +96,24 @@ ctselect::ctselect(int argc, char *argv[]) :
77 96  
78 97  
79 98 /***********************************************************************//**
  99 + * @brief Copy constructor
  100 + *
  101 + * @param[in] app Application.
  102 + ***************************************************************************/
  103 +ctselect::ctselect(const ctselect& app) : GApplication(app)
  104 +{
  105 + // Initialise members
  106 + init_members();
  107 +
  108 + // Copy members
  109 + copy_members(app);
  110 +
  111 + // Return
  112 + return;
  113 +}
  114 +
  115 +
  116 +/***********************************************************************//**
80 117 * @brief Destructor
81 118 ***************************************************************************/
82 119 ctselect::~ctselect(void)
... ... @@ -95,6 +132,35 @@ ctselect::~ctselect(void)
95 132 = =
96 133 ==========================================================================*/
97 134  
  135 +/***********************************************************************//**
  136 + * @brief Assignment operator
  137 + *
  138 + * @param[in] app Application.
  139 + ***************************************************************************/
  140 +ctselect& ctselect::operator= (const ctselect& app)
  141 +{
  142 + // Execute only if object is not identical
  143 + if (this != &app) {
  144 +
  145 + // Copy base class members
  146 + this->GApplication::operator=(app);
  147 +
  148 + // Free members
  149 + free_members();
  150 +
  151 + // Initialise members
  152 + init_members();
  153 +
  154 + // Copy members
  155 + copy_members(app);
  156 +
  157 + } // endif: object was not identical
  158 +
  159 + // Return this object
  160 + return *this;
  161 +}
  162 +
  163 +
98 164 /*==========================================================================
99 165 = =
100 166 = Public methods =
... ... @@ -102,10 +168,55 @@ ctselect::~ctselect(void)
102 168 ==========================================================================*/
103 169  
104 170 /***********************************************************************//**
  171 + * @brief Clear instance
  172 + ***************************************************************************/
  173 +void ctselect::clear(void)
  174 +{
  175 + // Free members
  176 + free_members();
  177 + this->GApplication::free_members();
  178 +
  179 + // Initialise members
  180 + this->GApplication::init_members();
  181 + init_members();
  182 +
  183 + // Return
  184 + return;
  185 +}
  186 +
  187 +
  188 +/***********************************************************************//**
  189 + * @brief Execute application
  190 + *
  191 + * This method performs the event selection and saves the result
  192 + ***************************************************************************/
  193 +void ctselect::execute(void)
  194 +{
  195 + // Read ahead output filename so that it gets dumped correctly in the
  196 + // parameters log
  197 + m_outfile = par("outfile")->value();
  198 +
  199 + // Perform event selection
  200 + run();
  201 +
  202 + // Save results
  203 + save();
  204 +
  205 + // Return
  206 + return;
  207 +}
  208 +
  209 +
  210 +
  211 +/***********************************************************************//**
105 212 * @brief Select event data
106 213 *
107   - * A GTI is appended to the FITS file as in the actual data format no GTI
108   - * exists.
  214 + * This method reads in the application parameters and loops over all
  215 + * observations that were found to perform an event selection. Event
  216 + * selection is done by writing each observation to a temporary file and
  217 + * re-opening the temporary file using the cfitsio event filter syntax.
  218 + * The temporary file is deleted after this action so that no disk overflow
  219 + * will occur.
109 220 ***************************************************************************/
110 221 void ctselect::run(void)
111 222 {
... ... @@ -122,24 +233,95 @@ void ctselect::run(void)
122 233 log << std::endl;
123 234 }
124 235  
125   - // Select events
126   - select();
  236 + // Write observation(s) into logger
  237 + if (logTerse()) {
  238 + log << std::endl;
  239 + log.header1("Observations before selection");
  240 + log << m_obs << std::endl;
  241 + }
127 242  
128   - // Append GTI to FITS file
129   - append_gti();
  243 + // Write header
  244 + if (logTerse()) {
  245 + log << std::endl;
  246 + log.header1("Event selection");
  247 + }
130 248  
131   - // Set data selection keywords
132   - write_ds_keys();
  249 + // Loop over all observation in the container
  250 + for (int i = 0; i < m_obs.size(); ++i) {
133 251  
134   - // Save output FITS file
135   - m_file.saveto(m_outfile, clobber());
  252 + // Get CTA observation
  253 + GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs(i));
136 254  
137   - // Close FITS file
138   - m_file.close();
  255 + // Continue only if observation is a CTA observation
  256 + if (obs != NULL) {
139 257  
140   - // Write separator into logger
141   - if (logTerse())
  258 + // Write header for observation
  259 + if (logTerse()) {
  260 + if (obs->name().length() > 1)
  261 + log.header3("Observation "+obs->name());
  262 + else
  263 + log.header3("Observation");
  264 + }
  265 +
  266 + // Get temporary file name
  267 + std::string filename = std::tmpnam(NULL);
  268 +
  269 + // Save observation in temporary file
  270 + obs->save(filename, true);
  271 +
  272 + // Load observation from temporary file, including event selection
  273 + select_events(obs, filename);
  274 +
  275 + // Remove temporary file
  276 + std::remove(filename.c_str());
  277 +
  278 + } // endif: had a CTA observation
  279 +
  280 + } // endfor: looped over all observations
  281 +
  282 + // Write observation(s) into logger
  283 + if (logTerse()) {
142 284 log << std::endl;
  285 + log.header1("Observations after selection");
  286 + log << m_obs << std::endl;
  287 + }
  288 +
  289 + // Return
  290 + return;
  291 +}
  292 +
  293 +
  294 +/***********************************************************************//**
  295 + * @brief Save simulated observation
  296 + *
  297 + * This method saves the results.
  298 + ***************************************************************************/
  299 +void ctselect::save(void)
  300 +{
  301 + // Write header
  302 + if (logTerse()) {
  303 + log << std::endl;
  304 + log.header1("Save observations");
  305 + }
  306 +
  307 + // Get output filename
  308 + m_outfile = par("outfile")->value();
  309 +
  310 + // Loop over all observation in the container
  311 + for (int i = 0; i < m_obs.size(); ++i) {
  312 +
  313 + // Get CTA observation
  314 + GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs(i));
  315 +
  316 + // Save only if observation is a CTA observation
  317 + if (obs != NULL) {
  318 +
  319 + // Save file
  320 + obs->save(m_outfile, clobber());
  321 +
  322 + } // endif: observation was valid
  323 +
  324 + } // endfor: looped over observations
143 325  
144 326 // Return
145 327 return;
... ... @@ -154,16 +336,32 @@ void ctselect::run(void)
154 336 ***************************************************************************/
155 337 void ctselect::get_parameters(void)
156 338 {
  339 + // If there are no observations in container then add a single CTA
  340 + // observation using the parameters from the parameter file
  341 + if (m_obs.size() == 0) {
  342 +
  343 + // Get CTA event list file name
  344 + m_infile = par("infile")->value();
  345 +
  346 + // Allocate CTA observation
  347 + GCTAObservation obs;
  348 +
  349 + // Load CTA observation from file
  350 + obs.load_unbinned(m_infile);
  351 +
  352 + // Append CTA observation to container
  353 + m_obs.append(obs);
  354 +
  355 + } // endif: there was no observation in the container
  356 +
157 357 // Get parameters
158   - m_infile = par("infile")->value();
159   - m_outfile = par("outfile")->value();
160   - m_ra = par("ra")->real();
161   - m_dec = par("dec")->real();
162   - m_rad = par("rad")->real();
163   - m_tmin = par("tmin")->real();
164   - m_tmax = par("tmax")->real();
165   - m_emin = par("emin")->real();
166   - m_emax = par("emax")->real();
  358 + m_ra = par("ra")->real();
  359 + m_dec = par("dec")->real();
  360 + m_rad = par("rad")->real();
  361 + m_tmin = par("tmin")->real();
  362 + m_tmax = par("tmax")->real();
  363 + m_emin = par("emin")->real();
  364 + m_emax = par("emax")->real();
167 365  
168 366 // Return
169 367 return;
... ... @@ -174,170 +372,99 @@ void ctselect::get_parameters(void)
174 372 * @brief Select events
175 373 *
176 374 * Select events from a FITS file by making use of the selection possibility
177   - * of the cfitsio library on loading a file into memory. Event selection is
178   - * kept optional (on compile time) as the data format may still evolve (for
179   - * the time being the TIME information is not valid).
  375 + * of the cfitsio library on loading a file.
180 376 *
181   - * @todo Set data selection keywords.
  377 + * @todo Implement a observation read() method to avoid saving the
  378 + * observation to a temporary file.
182 379 ***************************************************************************/
183   -void ctselect::select(void)
  380 +void ctselect::select_events(GCTAObservation* obs, const std::string& filename)
184 381 {
185   - // Write Header for event selection
186   - if (logTerse()) {
187   - log << std::endl;
188   - log.header1("Event selection");
189   - }
190   -
191   - // Build selection string
  382 + // Allocate selection string
192 383 std::string selection;
193   - #if SELECT_TIME
  384 +
  385 + // Make time selection
194 386 selection = "TIME >= "+str(m_tmin)+" && TIME <= "+str(m_tmax);
195 387 if (logTerse())
196 388 log << " Time range ................: " << m_tmin << "-" << m_tmax
197 389 << std::endl;
198   - #endif
199   - #if SELECT_ENERGY
200 390 if (selection.length() > 0)
201 391 selection += " && ";
  392 +
  393 + // Make energy selection
202 394 selection += "ENERGY >= "+str(m_emin)+" && ENERGY <= "+str(m_emax);
203 395 if (logTerse())
204 396 log << " Energy range ..............: " << m_emin << "-" << m_emax
205 397 << " TeV" << std::endl;
206   - #endif
207   - #if SELECT_ROI
208 398 if (selection.length() > 0)
209 399 selection += " && ";
  400 +
  401 + // Make ROI selection
210 402 selection += "ANGSEP("+str(m_ra)+","+str(m_dec)+",RA,DEC) <= "+str(m_rad);
211 403 if (logTerse()) {
212 404 log << " Acceptance cone centre ....: RA=" << m_ra << ", DEC=" << m_dec
213 405 << " deg" << std::endl;
214 406 log << " Acceptance cone radius ....: " << m_rad << " deg" << std::endl;
215 407 }
216   - #endif
217 408 if (logTerse())
218 409 log << " cfitsio selection .........: " << selection << std::endl;
219 410  
220 411 // Build input filename including selection expression
221   - std::string expression = m_infile;
  412 + std::string expression = filename;
222 413 if (selection.length() > 0)
223 414 expression += "[EVENTS]["+selection+"]";
224 415 if (logTerse())
225 416 log << " FITS filename .............: " << expression << std::endl;
226 417  
227 418 // Open FITS file
228   - m_file.open(expression);
  419 + GFits file(expression);
229 420  
230 421 // Log selected FITS file
231 422 if (logExplicit()) {
232 423 log << std::endl;
233 424 log.header1("FITS file content after selection");
234   - log << m_file << std::endl;
  425 + log << file << std::endl;
235 426 }
236 427  
237   - // Return
238   - return;
239   -}
240   -
241   -
242   -/***********************************************************************//**
243   - * @brief Append GTI to FITS file
244   - *
245   - * @todo We implement here a dummy method that overwrites an existing GTI
246   - * entry but that only works if a single time interval exists. This
247   - * is not clean, but since we have no method so far that allows
248   - * deleting a HDU from a FITS file we have no other choice. Ideally,
249   - * we would like to first delete an existing HDU and then append
250   - * a new one. If this is not possible, we would like to delete the
251   - * rows from an existing GTI and then fill it up anew. But in any
252   - * case, the actual data selection method does not check the
253   - * existing GTI, which we have to do to merge any subselection
254   - * information in. In fact, we need a GTI merge method as well ...
255   - ***************************************************************************/
256   -void ctselect::append_gti(void)
257   -{
258   - // Setup selected time range
  428 + // Get temporary file name
  429 + std::string tmpname = std::tmpnam(NULL);
  430 +
  431 + // Save FITS file to temporary file
  432 + file.saveto(tmpname, true);
  433 +
  434 + // Load observation from temporary file
  435 + obs->load_unbinned(tmpname);
  436 +
  437 + // Get CTA event list pointer
  438 + GCTAEventList* list = (GCTAEventList*)(obs->events());
  439 +
  440 + // Set ROI
  441 + GCTARoi roi;
  442 + GCTAInstDir instdir;
  443 + instdir.radec_deg(m_ra, m_dec);
  444 + roi.centre(instdir);
  445 + roi.radius(m_rad);
  446 + list->roi(roi);
  447 +
  448 + // Set GTI
  449 + GGti gti;
259 450 GTime tstart;
260 451 GTime tstop;
261 452 tstart.met(m_tmin);
262 453 tstop.met(m_tmax);
  454 + gti.append(tstart, tstop);
  455 + list->gti(gti);
263 456  
264   - // Initialise empty GTI table HDU
265   - GFitsTable* hdu = NULL;
266   -
267   - // Write selected time interval, either in an existing GTI or in a new
268   - // GTI that is appended to the FITS file
269   - try {
270   - hdu = m_file.table("GTI");
271   - GFitsTableDoubleCol* start = (GFitsTableDoubleCol*)hdu->column("START");
272   - GFitsTableDoubleCol* stop = (GFitsTableDoubleCol*)hdu->column("STOP");
273   - (*start)(0) = tstart.met();
274   - (*stop)(0) = tstop.met();
275   - }
276   - catch (GException::fits_hdu_not_found) {
277   - // Allocate Gti
278   - GGti gti;
279   -
280   - // Setup single GTI covering the selected time range
281   - gti.add(tstart, tstop);
  457 + // Set energy boundaries
  458 + GEbounds ebounds;
  459 + GEnergy emin;
  460 + GEnergy emax;
  461 + emin.TeV(m_emin);
  462 + emax.TeV(m_emax);
  463 + ebounds.append(emin, emax);
  464 + list->ebounds(ebounds);
282 465  
283   - // Write GTI
284   - gti.write(&m_file);
285   - }
286   -
287   - // Log final FITS file
288   - if (logExplicit()) {
289   - log << std::endl;
290   - log.header1("Final FITS file content");
291   - log << m_file << std::endl;
292   - }
293   -
294   - // Return
295   - return;
296   -}
297   -
298   -
299   -/***********************************************************************//**
300   - * @brief Write data selection keywords
301   - *
302   - * @todo This is a very dumb data selection keyword writing routine that does
303   - * not take into account any existing keywords. We definitely want a
304   - * more secure logic that checks for existing keywords and possible
305   - * conflicts. But for this prototype software, this code does the job.
306   - ***************************************************************************/
307   -void ctselect::write_ds_keys(void)
308   -{
309   - // Get event list header
310   - GFitsHDU* hdu = m_file.hdu("EVENTS");
311   -
312   - // Continue only if HDU is valid
313   - if (hdu != NULL) {
314   -
315   - // Set cone selection string
316   - std::string dsval2 = "CIRCLE("+str(m_ra)+","+str(m_dec)+","+str(m_rad)+")";
317   -
318   - // Set energy selection string
319   - std::string dsval3 = str(m_emin)+":"+str(m_emax);
320   -
321   - // Add time selection keywords
322   - hdu->card("DSTYP1", "TIME", "Data selection type");
323   - hdu->card("DSUNI1", "s", "Data selection unit");
324   - hdu->card("DSVAL1", "TABLE", "Data selection value");
325   - hdu->card("DSREF1", ":GTI", "Data selection reference");
326   -
327   - // Add acceptance cone selection
328   - hdu->card("DSTYP2", "POS(RA,DEC)", "Data selection type");
329   - hdu->card("DSUNI2", "deg", "Data selection unit");
330   - hdu->card("DSVAL2", dsval2, "Data selection value");
331   -
332   - // Add energy range selection
333   - hdu->card("DSTYP3", "ENERGY", "Data selection type");
334   - hdu->card("DSUNI3", "TeV", "Data selection unit");
335   - hdu->card("DSVAL3", dsval3, "Data selection value");
336   -
337   - // Set number of data selection keys
338   - hdu->card("NDSKEYS", 3, "Number of data selections");
339   -
340   - } // endif: HDU was valid
  466 + // Remove temporary file
  467 + std::remove(tmpname.c_str());
341 468  
342 469 // Return
343 470 return;
... ... @@ -358,6 +485,7 @@ void ctselect::init_members(void)
358 485 // Initialise members
359 486 m_infile.clear();
360 487 m_outfile.clear();
  488 + m_obs.clear();
361 489 m_ra = 0.0;
362 490 m_dec = 0.0;
363 491 m_rad = 0.0;
... ... @@ -375,11 +503,37 @@ void ctselect::init_members(void)
375 503  
376 504  
377 505 /***********************************************************************//**
  506 + * @brief Copy class members
  507 + *
  508 + * @param[in] app Application.
  509 + ***************************************************************************/
  510 +void ctselect::copy_members(const ctselect& app)
  511 +{
  512 + // Copy attributes
  513 + m_infile = app.m_infile;
  514 + m_outfile = app.m_outfile;
  515 + m_obs = app.m_obs;
  516 + m_ra = app.m_ra;
  517 + m_dec = app.m_dec;
  518 + m_rad = app.m_rad;
  519 + m_tmin = app.m_tmin;
  520 + m_tmax = app.m_tmax;
  521 + m_emin = app.m_emin;
  522 + m_emax = app.m_emax;
  523 +
  524 + // Return
  525 + return;
  526 +}
  527 +
  528 +
  529 +/***********************************************************************//**
378 530 * @brief Delete class members
379 531 ***************************************************************************/
380 532 void ctselect::free_members(void)
381 533 {
382   - // Free members
  534 + // Write separator into logger
  535 + if (logTerse())
  536 + log << std::endl;
383 537  
384 538 // Return
385 539 return;
... ...
src/ctselect/ctselect.hpp
... ... @@ -21,10 +21,11 @@
21 21  
22 22 /* __ Includes ___________________________________________________________ */
23 23 #include "GammaLib.hpp"
  24 +#include "GCTALib.hpp"
24 25  
25 26 /* __Definitions _________________________________________________________ */
26 27 #define CTSELECT_NAME "ctselect"
27   -#define CTSELECT_VERSION "00-01-00"
  28 +#define CTSELECT_VERSION "00-02-00"
28 29  
29 30  
30 31 /***********************************************************************//**
... ... @@ -36,19 +37,27 @@ class ctselect : public GApplication {
36 37 public:
37 38 // Constructors and destructors
38 39 ctselect(void);
  40 + explicit ctselect(GObservations obs);
39 41 ctselect(int argc, char *argv[]);
40   - ~ctselect(void);
  42 + ctselect(const ctselect& app);
  43 + virtual ~ctselect(void);
  44 +
  45 + // Operators
  46 + ctselect& operator= (const ctselect& app);
41 47  
42 48 // Methods
43   - void run(void);
44   - void get_parameters(void);
45   - void select(void);
46   - void append_gti(void);
47   - void write_ds_keys(void);
  49 + void clear(void);
  50 + void execute(void);
  51 + void run(void);
  52 + void save(void);
  53 + GObservations& obs(void) { return m_obs; }
  54 + void get_parameters(void);
  55 + void select_events(GCTAObservation* obs, const std::string& filename);
48 56  
49 57 protected:
50 58 // Protected methods
51 59 void init_members(void);
  60 + void copy_members(const ctselect& app);
52 61 void free_members(void);
53 62  
54 63 // User parameters
... ... @@ -61,7 +70,9 @@ protected:
61 70 double m_tmax; //!< Stop time
62 71 double m_emin; //!< Lower energy
63 72 double m_emax; //!< Upper energy
64   - GFits m_file; //!< FITS file
  73 +
  74 + // Protected members
  75 + GObservations m_obs; //!< Observations container
65 76 };
66 77  
67 78 #endif /* CTSELECT_HPP */
... ...
src/ctselect/main.cpp
1 1 /***************************************************************************
2 2 * ctselect - CTA data selection tool main code *
3 3 * ----------------------------------------------------------------------- *
4   - * copyright (C) 2010 by Jurgen Knodlseder *
  4 + * copyright (C) 2010-2011 by Jurgen Knodlseder *
5 5 * ----------------------------------------------------------------------- *
6 6 * *
7 7 * This program is free software; you can redistribute it and/or modify *
... ... @@ -20,7 +20,7 @@
20 20 #ifdef HAVE_CONFIG_H
21 21 #include <config.h>
22 22 #endif
23   -#include <stdio.h>
  23 +#include <cstdio>
24 24 #include "ctselect.hpp"
25 25  
26 26  
... ... @@ -40,7 +40,10 @@ int main (int argc, char *argv[])
40 40  
41 41 // Run application
42 42 try {
43   - application.run();
  43 + // Execute application
  44 + application.execute();
  45 +
  46 + // Signal success
44 47 rc = 0;
45 48 }
46 49 catch (std::exception &e) {
... ... @@ -48,7 +51,7 @@ int main (int argc, char *argv[])
48 51 // Extract error message
49 52 std::string message = e.what();
50 53 std::string signal = "*** ERROR encounterted in the execution of"
51   - " ctselect. Run aborted ...";
  54 + " ctselect. Run aborted ...";
52 55  
53 56 // Write error in logger
54 57 application.log << signal << std::endl;
... ...