Commit 807693280258d2727183031dea30bd3585cf51e2
1 parent
011098c9
add 'expr' parameter, make time selection optional, allow for automatic use of p…
…ointing as ROI centre
Showing
2 changed files
with
169 additions
and
46 deletions
src/ctselect/ctselect.cpp
| 1 | 1 | /*************************************************************************** |
| 2 | 2 | * ctselect - CTA data selection tool * |
| 3 | 3 | * ----------------------------------------------------------------------- * |
| 4 | - * copyright (C) 2010-2011 by Jurgen Knodlseder * | |
| 4 | + * copyright (C) 2010-2011 by Juergen Knoedlseder * | |
| 5 | 5 | * ----------------------------------------------------------------------- * |
| 6 | 6 | * * |
| 7 | 7 | * This program is free software: you can redistribute it and/or modify * |
| ... | ... | @@ -21,7 +21,7 @@ |
| 21 | 21 | /** |
| 22 | 22 | * @file ctselect.cpp |
| 23 | 23 | * @brief CTA data selection tool implementation |
| 24 | - * @author J. Knodlseder | |
| 24 | + * @author J. Knoedlseder | |
| 25 | 25 | */ |
| 26 | 26 | |
| 27 | 27 | /* __ Includes ___________________________________________________________ */ |
| ... | ... | @@ -260,6 +260,9 @@ void ctselect::run(void) |
| 260 | 260 | // Loop over all observation in the container |
| 261 | 261 | for (int i = 0; i < m_obs.size(); ++i) { |
| 262 | 262 | |
| 263 | + // Initialise event filename | |
| 264 | + m_infiles.push_back(""); | |
| 265 | + | |
| 263 | 266 | // Get CTA observation |
| 264 | 267 | GCTAObservation* obs = dynamic_cast<GCTAObservation*>(&m_obs[i]); |
| 265 | 268 | |
| ... | ... | @@ -268,12 +271,17 @@ void ctselect::run(void) |
| 268 | 271 | |
| 269 | 272 | // Write header for observation |
| 270 | 273 | if (logTerse()) { |
| 271 | - if (obs->name().length() > 1) | |
| 274 | + if (obs->name().length() > 1) { | |
| 272 | 275 | log.header3("Observation "+obs->name()); |
| 273 | - else | |
| 276 | + } | |
| 277 | + else { | |
| 274 | 278 | log.header3("Observation"); |
| 279 | + } | |
| 275 | 280 | } |
| 276 | 281 | |
| 282 | + // Save event file name (for possible saving) | |
| 283 | + m_infiles[i] = obs->eventfile(); | |
| 284 | + | |
| 277 | 285 | // Get temporary file name |
| 278 | 286 | std::string filename = std::tmpnam(NULL); |
| 279 | 287 | |
| ... | ... | @@ -291,7 +299,7 @@ void ctselect::run(void) |
| 291 | 299 | |
| 292 | 300 | // Remove temporary file |
| 293 | 301 | std::remove(filename.c_str()); |
| 294 | - | |
| 302 | + | |
| 295 | 303 | } // endif: had a CTA observation |
| 296 | 304 | |
| 297 | 305 | } // endfor: looped over all observations |
| ... | ... | @@ -309,9 +317,14 @@ void ctselect::run(void) |
| 309 | 317 | |
| 310 | 318 | |
| 311 | 319 | /***********************************************************************//** |
| 312 | - * @brief Save simulated observation | |
| 320 | + * @brief Save observation(s) into event file(s) | |
| 313 | 321 | * |
| 314 | - * This method saves the results. | |
| 322 | + * This method saves the observation(s) into event file(s). Each input event | |
| 323 | + * file will be saved in a separate output event file. If a single input | |
| 324 | + * event file is present, the "outfile" parameter specifies the filename of | |
| 325 | + * the output event file. For multiple input event files, "outfile" is used | |
| 326 | + * as suffix that is added to the input event file name to create the output | |
| 327 | + * filename. | |
| 315 | 328 | ***************************************************************************/ |
| 316 | 329 | void ctselect::save(void) |
| 317 | 330 | { |
| ... | ... | @@ -321,7 +334,7 @@ void ctselect::save(void) |
| 321 | 334 | log.header1("Save observations"); |
| 322 | 335 | } |
| 323 | 336 | |
| 324 | - // Get output filename | |
| 337 | + // Get output filename (or prefix for multiple event files) | |
| 325 | 338 | m_outfile = (*this)["outfile"].value(); |
| 326 | 339 | |
| 327 | 340 | // Loop over all observation in the container |
| ... | ... | @@ -333,8 +346,34 @@ void ctselect::save(void) |
| 333 | 346 | // Save only if observation is a CTA observation |
| 334 | 347 | if (obs != NULL) { |
| 335 | 348 | |
| 336 | - // Save file | |
| 337 | - obs->save(m_outfile, clobber()); | |
| 349 | + // Get filename of events file | |
| 350 | + std::string eventfile = m_infiles[i]; | |
| 351 | + | |
| 352 | + // Set filename of output events file | |
| 353 | + //TODO: we have to strip any path before appending the prefix | |
| 354 | + //We may create a special GTools function for this. | |
| 355 | + std::string outname = m_outfile; | |
| 356 | + if (m_obs.size() > 1) { | |
| 357 | + outname += "_" + eventfile; | |
| 358 | + //TODO: strip .gz suffix | |
| 359 | + } | |
| 360 | + | |
| 361 | + // Save observation into output events file | |
| 362 | + obs->save(outname, clobber()); | |
| 363 | + | |
| 364 | + // Copy over all other extensions that were present in the | |
| 365 | + // input event file | |
| 366 | + GFits infile(eventfile); | |
| 367 | + GFits outfile(outname); | |
| 368 | + for (int extno = 1; extno < infile.size(); ++extno) { | |
| 369 | + GFitsHDU* hdu = infile.hdu(extno); | |
| 370 | + if (hdu->extname() != "EVENTS" && hdu->extname() != "GTI") { | |
| 371 | + outfile.append(*hdu); | |
| 372 | + } | |
| 373 | + } | |
| 374 | + infile.close(); | |
| 375 | + outfile.save(true); | |
| 376 | + outfile.close(); | |
| 338 | 377 | |
| 339 | 378 | } // endif: observation was valid |
| 340 | 379 | |
| ... | ... | @@ -349,7 +388,7 @@ void ctselect::save(void) |
| 349 | 388 | * @brief Get application parameters |
| 350 | 389 | * |
| 351 | 390 | * Get all task parameters from parameter file or (if required) by querying |
| 352 | - * the user. | |
| 391 | + * the user. Times are assumed to be in the native CTA MJD format. | |
| 353 | 392 | ***************************************************************************/ |
| 354 | 393 | void ctselect::get_parameters(void) |
| 355 | 394 | { |
| ... | ... | @@ -379,6 +418,11 @@ void ctselect::get_parameters(void) |
| 379 | 418 | m_tmax = (*this)["tmax"].real(); |
| 380 | 419 | m_emin = (*this)["emin"].real(); |
| 381 | 420 | m_emax = (*this)["emax"].real(); |
| 421 | + m_expr = (*this)["expr"].string(); | |
| 422 | + | |
| 423 | + // Derive time interval | |
| 424 | + m_timemin.time(m_tmin, G_CTA_MJDREF, "days"); | |
| 425 | + m_timemax.time(m_tmax, G_CTA_MJDREF, "days"); | |
| 382 | 426 | |
| 383 | 427 | // Return |
| 384 | 428 | return; |
| ... | ... | @@ -388,46 +432,119 @@ void ctselect::get_parameters(void) |
| 388 | 432 | /***********************************************************************//** |
| 389 | 433 | * @brief Select events |
| 390 | 434 | * |
| 391 | - * @param[in] obs CTA observations. | |
| 435 | + * @param[in] obs CTA observation. | |
| 392 | 436 | * @param[in] filename File name. |
| 393 | 437 | * |
| 394 | 438 | * Select events from a FITS file by making use of the selection possibility |
| 395 | - * of the cfitsio library on loading a file. | |
| 439 | + * of the cfitsio library on loading a file. A selection string is created | |
| 440 | + * from the specified criteria that is appended to the filename so that | |
| 441 | + * cfitsio will automatically filter the event data. This selection string | |
| 442 | + * is then applied when opening the FITS file. The opened FITS file is then | |
| 443 | + * saved into a temporary file which is the loaded into the actual CTA | |
| 444 | + * observation, overwriting the old CTA observation. The ROI, GTI and EBounds | |
| 445 | + * of the CTA event list are then set accordingly to the specified selection. | |
| 446 | + * Finally, the temporary file created during this process is removed. | |
| 447 | + * | |
| 448 | + * Good Time Intervals of the observation will be limited to the time | |
| 449 | + * interval [m_tmin, m_tmax]. If m_tmin=m_tmax=0, no time selection is | |
| 450 | + * performed. | |
| 396 | 451 | * |
| 397 | - * @todo Implement an observation read() method to avoid saving the | |
| 398 | - * observation to a temporary file. | |
| 452 | + * @todo Add an arbitrary selection string. | |
| 453 | + * @todo Use INDEF instead of 0.0 for pointing as RA/DEC selection | |
| 399 | 454 | ***************************************************************************/ |
| 400 | 455 | void ctselect::select_events(GCTAObservation* obs, const std::string& filename) |
| 401 | 456 | { |
| 402 | 457 | // Allocate selection string |
| 403 | 458 | std::string selection; |
| 459 | + char cmin[80]; | |
| 460 | + char cmax[80]; | |
| 461 | + char cra[80]; | |
| 462 | + char cdec[80]; | |
| 463 | + char crad[80]; | |
| 464 | + | |
| 465 | + // Set requested selections | |
| 466 | + bool select_time = (m_tmin != 0.0 || m_tmax != 0.0); | |
| 467 | + | |
| 468 | + // Set RA/DEC selection | |
| 469 | + double ra = m_ra; | |
| 470 | + double dec = m_dec; | |
| 471 | + if (m_ra == 0.0 && m_dec == 0.0) { | |
| 472 | + GTime time; | |
| 473 | + const GCTAPointing *pnt = obs->pointing(time); | |
| 474 | + ra = pnt->dir().ra_deg(); | |
| 475 | + dec = pnt->dir().dec_deg(); | |
| 476 | + } | |
| 477 | + | |
| 478 | + // Set time selection interval. We make sure here that the time selection | |
| 479 | + // interval cannot be wider than the GTIs covering the data. This is done | |
| 480 | + // using GGti's reduce() method. | |
| 481 | + if (select_time) { | |
| 482 | + | |
| 483 | + // Reduce GTIs to specified time interval. The complicated cast is | |
| 484 | + // necessary here because the gti() method is declared const, so | |
| 485 | + // we're not officially allowed to modify the GTIs. | |
| 486 | + ((GGti*)(&obs->events()->gti()))->reduce(m_timemin, m_timemax); | |
| 487 | + | |
| 488 | + } // endif: time selection was required | |
| 489 | + | |
| 490 | + // Save GTI for later usage | |
| 491 | + GGti gti = obs->events()->gti(); | |
| 404 | 492 | |
| 405 | 493 | // Make time selection |
| 406 | - selection = "TIME >= "+str(m_tmin)+" && TIME <= "+str(m_tmax); | |
| 407 | - if (logTerse()) | |
| 408 | - log << " Time range ................: " << m_tmin << "-" << m_tmax | |
| 409 | - << std::endl; | |
| 410 | - if (selection.length() > 0) | |
| 411 | - selection += " && "; | |
| 494 | + if (select_time) { | |
| 495 | + | |
| 496 | + // Extract effective time interval in native MJD reference | |
| 497 | + double tmin = gti.tstart().time(); | |
| 498 | + double tmax = gti.tstop().time(); | |
| 499 | + | |
| 500 | + // Format time with sufficient accuracy and add to selection string | |
| 501 | + sprintf(cmin, "%.8f", tmin); | |
| 502 | + sprintf(cmax, "%.8f", tmax); | |
| 503 | + selection = "TIME >= "+std::string(cmin)+" && TIME <= "+std::string(cmax); | |
| 504 | + if (logTerse()) { | |
| 505 | + log << " Time range ................: " << tmin << "-" << tmax | |
| 506 | + << std::endl; | |
| 507 | + } | |
| 508 | + if (selection.length() > 0) { | |
| 509 | + selection += " && "; | |
| 510 | + } | |
| 511 | + } | |
| 412 | 512 | |
| 413 | 513 | // Make energy selection |
| 414 | - selection += "ENERGY >= "+str(m_emin)+" && ENERGY <= "+str(m_emax); | |
| 415 | - if (logTerse()) | |
| 514 | + sprintf(cmin, "%.8f", m_emin); | |
| 515 | + sprintf(cmax, "%.8f", m_emax); | |
| 516 | + selection += "ENERGY >= "+std::string(cmin)+" && ENERGY <= "+std::string(cmax); | |
| 517 | + if (logTerse()) { | |
| 416 | 518 | log << " Energy range ..............: " << m_emin << "-" << m_emax |
| 417 | 519 | << " TeV" << std::endl; |
| 418 | - if (selection.length() > 0) | |
| 520 | + } | |
| 521 | + if (selection.length() > 0) { | |
| 419 | 522 | selection += " && "; |
| 523 | + } | |
| 420 | 524 | |
| 421 | 525 | // Make ROI selection |
| 422 | - selection += "ANGSEP("+str(m_ra)+","+str(m_dec)+",RA,DEC) <= "+str(m_rad); | |
| 526 | + sprintf(cra, "%.6f", ra); | |
| 527 | + sprintf(cdec, "%.6f", dec); | |
| 528 | + sprintf(crad, "%.6f", m_rad); | |
| 529 | + selection += "ANGSEP("+std::string(cra)+"," + | |
| 530 | + std::string(cdec)+",RA,DEC) <= " + | |
| 531 | + std::string(crad); | |
| 423 | 532 | if (logTerse()) { |
| 424 | - log << " Acceptance cone centre ....: RA=" << m_ra << ", DEC=" << m_dec | |
| 533 | + log << " Acceptance cone centre ....: RA=" << ra << ", DEC=" << dec | |
| 425 | 534 | << " deg" << std::endl; |
| 426 | 535 | log << " Acceptance cone radius ....: " << m_rad << " deg" << std::endl; |
| 427 | 536 | } |
| 428 | 537 | if (logTerse()) |
| 429 | 538 | log << " cfitsio selection .........: " << selection << std::endl; |
| 430 | 539 | |
| 540 | + // Add additional expression | |
| 541 | + if (strip_whitespace(m_expr).length() > 0) { | |
| 542 | + if (selection.length() > 0) { | |
| 543 | + selection += " && "; | |
| 544 | + } | |
| 545 | + selection += "("+strip_whitespace(m_expr)+")"; | |
| 546 | + } | |
| 547 | + | |
| 431 | 548 | // Build input filename including selection expression |
| 432 | 549 | std::string expression = filename; |
| 433 | 550 | if (selection.length() > 0) |
| ... | ... | @@ -460,18 +577,12 @@ void ctselect::select_events(GCTAObservation* obs, const std::string& filename) |
| 460 | 577 | // Set ROI |
| 461 | 578 | GCTARoi roi; |
| 462 | 579 | GCTAInstDir instdir; |
| 463 | - instdir.radec_deg(m_ra, m_dec); | |
| 580 | + instdir.radec_deg(ra, dec); | |
| 464 | 581 | roi.centre(instdir); |
| 465 | 582 | roi.radius(m_rad); |
| 466 | 583 | list->roi(roi); |
| 467 | 584 | |
| 468 | 585 | // Set GTI |
| 469 | - GGti gti; | |
| 470 | - GTime tstart; | |
| 471 | - GTime tstop; | |
| 472 | - tstart.met(m_tmin); | |
| 473 | - tstop.met(m_tmax); | |
| 474 | - gti.append(tstart, tstop); | |
| 475 | 586 | list->gti(gti); |
| 476 | 587 | |
| 477 | 588 | // Set energy boundaries |
| ... | ... | @@ -506,6 +617,9 @@ void ctselect::init_members(void) |
| 506 | 617 | m_infile.clear(); |
| 507 | 618 | m_outfile.clear(); |
| 508 | 619 | m_obs.clear(); |
| 620 | + m_infiles.clear(); | |
| 621 | + m_timemin.clear(); | |
| 622 | + m_timemax.clear(); | |
| 509 | 623 | m_ra = 0.0; |
| 510 | 624 | m_dec = 0.0; |
| 511 | 625 | m_rad = 0.0; |
| ... | ... | @@ -533,6 +647,9 @@ void ctselect::copy_members(const ctselect& app) |
| 533 | 647 | m_infile = app.m_infile; |
| 534 | 648 | m_outfile = app.m_outfile; |
| 535 | 649 | m_obs = app.m_obs; |
| 650 | + m_infiles = app.m_infiles; | |
| 651 | + m_timemin = app.m_timemin; | |
| 652 | + m_timemax = app.m_timemax; | |
| 536 | 653 | m_ra = app.m_ra; |
| 537 | 654 | m_dec = app.m_dec; |
| 538 | 655 | m_rad = app.m_rad; | ... | ... |
src/ctselect/ctselect.hpp
| 1 | 1 | /*************************************************************************** |
| 2 | 2 | * ctselect - CTA data selection tool * |
| 3 | 3 | * ----------------------------------------------------------------------- * |
| 4 | - * copyright (C) 2010-2011 by Jurgen Knodlseder * | |
| 4 | + * copyright (C) 2010-2011 by Juergen Knoedlseder * | |
| 5 | 5 | * ----------------------------------------------------------------------- * |
| 6 | 6 | * * |
| 7 | 7 | * This program is free software: you can redistribute it and/or modify * |
| ... | ... | @@ -21,19 +21,21 @@ |
| 21 | 21 | /** |
| 22 | 22 | * @file ctselect.hpp |
| 23 | 23 | * @brief CTA data selection tool definition |
| 24 | - * @author J. Knodlseder | |
| 24 | + * @author J. Knoedlseder | |
| 25 | 25 | */ |
| 26 | 26 | |
| 27 | 27 | #ifndef CTSELECT_HPP |
| 28 | 28 | #define CTSELECT_HPP |
| 29 | 29 | |
| 30 | 30 | /* __ Includes ___________________________________________________________ */ |
| 31 | +#include <vector> | |
| 32 | +#include <string> | |
| 31 | 33 | #include "GammaLib.hpp" |
| 32 | 34 | #include "GCTALib.hpp" |
| 33 | 35 | |
| 34 | 36 | /* __Definitions _________________________________________________________ */ |
| 35 | 37 | #define CTSELECT_NAME "ctselect" |
| 36 | -#define CTSELECT_VERSION "00-02-03" | |
| 38 | +#define CTSELECT_VERSION "00-03-00" | |
| 37 | 39 | |
| 38 | 40 | |
| 39 | 41 | /***********************************************************************//** |
| ... | ... | @@ -70,18 +72,22 @@ protected: |
| 70 | 72 | std::string check_infile(const std::string& filename) const; |
| 71 | 73 | |
| 72 | 74 | // User parameters |
| 73 | - std::string m_infile; //!< Input event list | |
| 74 | - std::string m_outfile; //!< Output event list | |
| 75 | - double m_ra; //!< RA of ROI centre | |
| 76 | - double m_dec; //!< DEC of ROI centre | |
| 77 | - double m_rad; //!< ROI radius | |
| 78 | - double m_tmin; //!< Start time | |
| 79 | - double m_tmax; //!< Stop time | |
| 80 | - double m_emin; //!< Lower energy | |
| 81 | - double m_emax; //!< Upper energy | |
| 75 | + std::string m_infile; //!< Input event list | |
| 76 | + std::string m_outfile; //!< Output event list | |
| 77 | + double m_ra; //!< RA of ROI centre | |
| 78 | + double m_dec; //!< DEC of ROI centre | |
| 79 | + double m_rad; //!< ROI radius | |
| 80 | + double m_tmin; //!< Start time | |
| 81 | + double m_tmax; //!< Stop time | |
| 82 | + double m_emin; //!< Lower energy | |
| 83 | + double m_emax; //!< Upper energy | |
| 84 | + std::string m_expr; //!< Selection expression | |
| 82 | 85 | |
| 83 | 86 | // Protected members |
| 84 | - GObservations m_obs; //!< Observations container | |
| 87 | + GObservations m_obs; //!< Observations container | |
| 88 | + std::vector<std::string> m_infiles; //!< Input event filenames | |
| 89 | + GTime m_timemin; //!< Earliest time | |
| 90 | + GTime m_timemax; //!< Latest time | |
| 85 | 91 | }; |
| 86 | 92 | |
| 87 | 93 | #endif /* CTSELECT_HPP */ | ... | ... |