Commit 541315183a98525bb3b819d1f6f77ca51d1852f3
1 parent
e2435050
Add handling of XML files instead of input and output event lists. This allows p…
…rocessing collections of event lists with a single ctselect run.
Showing
2 changed files
with
239 additions
and
73 deletions
src/ctselect/ctselect.cpp
| 1 | 1 | /*************************************************************************** |
| 2 | 2 | * ctselect - CTA data selection tool * |
| 3 | 3 | * ----------------------------------------------------------------------- * |
| 4 | - * copyright (C) 2010-2011 by Juergen Knoedlseder * | |
| 4 | + * copyright (C) 2010-2012 by Juergen Knoedlseder * | |
| 5 | 5 | * ----------------------------------------------------------------------- * |
| 6 | 6 | * * |
| 7 | 7 | * This program is free software: you can redistribute it and/or modify * |
| ... | ... | @@ -93,7 +93,7 @@ ctselect::ctselect(GObservations obs) : GApplication(CTSELECT_NAME, CTSELECT_VER |
| 93 | 93 | * @param[in] argv Array of command line arguments. |
| 94 | 94 | ***************************************************************************/ |
| 95 | 95 | ctselect::ctselect(int argc, char *argv[]) : |
| 96 | - GApplication(CTSELECT_NAME, CTSELECT_VERSION, argc, argv) | |
| 96 | + GApplication(CTSELECT_NAME, CTSELECT_VERSION, argc, argv) | |
| 97 | 97 | { |
| 98 | 98 | // Initialise members |
| 99 | 99 | init_members(); |
| ... | ... | @@ -232,8 +232,9 @@ void ctselect::execute(void) |
| 232 | 232 | void ctselect::run(void) |
| 233 | 233 | { |
| 234 | 234 | // Switch screen logging on in debug mode |
| 235 | - if (logDebug()) | |
| 235 | + if (logDebug()) { | |
| 236 | 236 | log.cout(true); |
| 237 | + } | |
| 237 | 238 | |
| 238 | 239 | // Get parameters |
| 239 | 240 | get_parameters(); |
| ... | ... | @@ -257,10 +258,13 @@ void ctselect::run(void) |
| 257 | 258 | log.header1("Event selection"); |
| 258 | 259 | } |
| 259 | 260 | |
| 261 | + // Initialise counters | |
| 262 | + int n_observations = 0; | |
| 263 | + | |
| 260 | 264 | // Loop over all observation in the container |
| 261 | 265 | for (int i = 0; i < m_obs.size(); ++i) { |
| 262 | 266 | |
| 263 | - // Initialise event filename | |
| 267 | + // Initialise event input and output filenames | |
| 264 | 268 | m_infiles.push_back(""); |
| 265 | 269 | |
| 266 | 270 | // Get CTA observation |
| ... | ... | @@ -279,6 +283,9 @@ void ctselect::run(void) |
| 279 | 283 | } |
| 280 | 284 | } |
| 281 | 285 | |
| 286 | + // Increment counter | |
| 287 | + n_observations++; | |
| 288 | + | |
| 282 | 289 | // Save event file name (for possible saving) |
| 283 | 290 | m_infiles[i] = obs->eventfile(); |
| 284 | 291 | |
| ... | ... | @@ -304,6 +311,12 @@ void ctselect::run(void) |
| 304 | 311 | |
| 305 | 312 | } // endfor: looped over all observations |
| 306 | 313 | |
| 314 | + // If more than a single observation has been handled then make sure that | |
| 315 | + // an XML file will be used for storage | |
| 316 | + if (n_observations > 1) { | |
| 317 | + m_use_xml = true; | |
| 318 | + } | |
| 319 | + | |
| 307 | 320 | // Write observation(s) into logger |
| 308 | 321 | if (logTerse()) { |
| 309 | 322 | log << std::endl; |
| ... | ... | @@ -317,14 +330,23 @@ void ctselect::run(void) |
| 317 | 330 | |
| 318 | 331 | |
| 319 | 332 | /***********************************************************************//** |
| 320 | - * @brief Save observation(s) into event file(s) | |
| 333 | + * @brief Save the selected event list(s) | |
| 321 | 334 | * |
| 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. | |
| 335 | + * This method saves the selected event list(s) into FITS file(s). There are | |
| 336 | + * two modes, depending on the m_use_xml flag. | |
| 337 | + * | |
| 338 | + * If m_use_xml is true, all selected event list(s) will be saved into FITS | |
| 339 | + * files, where the output filenames are constructued from the input | |
| 340 | + * filenames by prepending the m_prefix string to name. Any path information | |
| 341 | + * will be stripped form the input name, hence event files will be written | |
| 342 | + * into the local working directory (unless some path information is present | |
| 343 | + * in the prefix). In addition, an XML file will be created that gathers | |
| 344 | + * the filename information for the selected event list(s). If an XML file | |
| 345 | + * was present on input, all metadata information will be copied from this | |
| 346 | + * input file. | |
| 347 | + * | |
| 348 | + * If m_use_xml is false, the selected event list will be saved into a FITS | |
| 349 | + * file. | |
| 328 | 350 | ***************************************************************************/ |
| 329 | 351 | void ctselect::save(void) |
| 330 | 352 | { |
| ... | ... | @@ -334,50 +356,15 @@ void ctselect::save(void) |
| 334 | 356 | log.header1("Save observations"); |
| 335 | 357 | } |
| 336 | 358 | |
| 337 | - // Get output filename (or prefix for multiple event files) | |
| 338 | - m_outfile = (*this)["outfile"].value(); | |
| 339 | - | |
| 340 | - // Loop over all observation in the container | |
| 341 | - for (int i = 0; i < m_obs.size(); ++i) { | |
| 342 | - | |
| 343 | - // Get CTA observation | |
| 344 | - GCTAObservation* obs = dynamic_cast<GCTAObservation*>(&m_obs[i]); | |
| 345 | - | |
| 346 | - // Save only if observation is a CTA observation | |
| 347 | - if (obs != NULL) { | |
| 348 | - | |
| 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(); | |
| 377 | - | |
| 378 | - } // endif: observation was valid | |
| 359 | + // Case A: Save event file(s) and XML metadata information | |
| 360 | + if (m_use_xml) { | |
| 361 | + save_xml(); | |
| 362 | + } | |
| 379 | 363 | |
| 380 | - } // endfor: looped over observations | |
| 364 | + // Case B: Save event file as FITS file | |
| 365 | + else { | |
| 366 | + save_fits(); | |
| 367 | + } | |
| 381 | 368 | |
| 382 | 369 | // Return |
| 383 | 370 | return; |
| ... | ... | @@ -389,6 +376,10 @@ void ctselect::save(void) |
| 389 | 376 | * |
| 390 | 377 | * Get all task parameters from parameter file or (if required) by querying |
| 391 | 378 | * the user. Times are assumed to be in the native CTA MJD format. |
| 379 | + * | |
| 380 | + * This method also loads observations if no observations are yet allocated. | |
| 381 | + * Observations are either loaded from a single CTA even list, or from a | |
| 382 | + * XML file using the metadata information that is stored in that file. | |
| 392 | 383 | ***************************************************************************/ |
| 393 | 384 | void ctselect::get_parameters(void) |
| 394 | 385 | { |
| ... | ... | @@ -402,11 +393,30 @@ void ctselect::get_parameters(void) |
| 402 | 393 | // Allocate CTA observation |
| 403 | 394 | GCTAObservation obs; |
| 404 | 395 | |
| 405 | - // Load CTA observation from file | |
| 406 | - obs.load_unbinned(m_infile); | |
| 396 | + // Try first to open as FITS file | |
| 397 | + try { | |
| 398 | + | |
| 399 | + // Load event list in CTA observation | |
| 400 | + obs.load_unbinned(m_infile); | |
| 401 | + | |
| 402 | + // Append CTA observation to container | |
| 403 | + m_obs.append(obs); | |
| 407 | 404 | |
| 408 | - // Append CTA observation to container | |
| 409 | - m_obs.append(obs); | |
| 405 | + // Signal that no XML file should be used for storage | |
| 406 | + m_use_xml = false; | |
| 407 | + | |
| 408 | + } | |
| 409 | + | |
| 410 | + // ... otherwise try to open as XML file | |
| 411 | + catch (GException::fits_open_error) { | |
| 412 | + | |
| 413 | + // Load observations from XML file | |
| 414 | + m_obs.load(m_infile); | |
| 415 | + | |
| 416 | + // Signal that XML file should be used for storage | |
| 417 | + m_use_xml = true; | |
| 418 | + | |
| 419 | + } | |
| 410 | 420 | |
| 411 | 421 | } // endif: there was no observation in the container |
| 412 | 422 | |
| ... | ... | @@ -612,13 +622,10 @@ void ctselect::select_events(GCTAObservation* obs, const std::string& filename) |
| 612 | 622 | ***************************************************************************/ |
| 613 | 623 | void ctselect::init_members(void) |
| 614 | 624 | { |
| 615 | - // Initialise members | |
| 625 | + // Initialise parameters | |
| 616 | 626 | m_infile.clear(); |
| 617 | 627 | m_outfile.clear(); |
| 618 | - m_obs.clear(); | |
| 619 | - m_infiles.clear(); | |
| 620 | - m_timemin.clear(); | |
| 621 | - m_timemax.clear(); | |
| 628 | + m_infile.clear(); | |
| 622 | 629 | m_ra = 0.0; |
| 623 | 630 | m_dec = 0.0; |
| 624 | 631 | m_rad = 0.0; |
| ... | ... | @@ -626,6 +633,14 @@ void ctselect::init_members(void) |
| 626 | 633 | m_tmax = 0.0; |
| 627 | 634 | m_emin = 0.0; |
| 628 | 635 | m_emax = 0.0; |
| 636 | + m_expr.clear(); | |
| 637 | + | |
| 638 | + // Initialise protected members | |
| 639 | + m_obs.clear(); | |
| 640 | + m_infiles.clear(); | |
| 641 | + m_timemin.clear(); | |
| 642 | + m_timemax.clear(); | |
| 643 | + m_use_xml = false; | |
| 629 | 644 | |
| 630 | 645 | // Set logger properties |
| 631 | 646 | log.date(true); |
| ... | ... | @@ -642,13 +657,10 @@ void ctselect::init_members(void) |
| 642 | 657 | ***************************************************************************/ |
| 643 | 658 | void ctselect::copy_members(const ctselect& app) |
| 644 | 659 | { |
| 645 | - // Copy attributes | |
| 660 | + // Copy parameters | |
| 646 | 661 | m_infile = app.m_infile; |
| 647 | 662 | m_outfile = app.m_outfile; |
| 648 | - m_obs = app.m_obs; | |
| 649 | - m_infiles = app.m_infiles; | |
| 650 | - m_timemin = app.m_timemin; | |
| 651 | - m_timemax = app.m_timemax; | |
| 663 | + m_infile = app.m_infile; | |
| 652 | 664 | m_ra = app.m_ra; |
| 653 | 665 | m_dec = app.m_dec; |
| 654 | 666 | m_rad = app.m_rad; |
| ... | ... | @@ -656,7 +668,15 @@ void ctselect::copy_members(const ctselect& app) |
| 656 | 668 | m_tmax = app.m_tmax; |
| 657 | 669 | m_emin = app.m_emin; |
| 658 | 670 | m_emax = app.m_emax; |
| 659 | - | |
| 671 | + m_expr = app.m_expr; | |
| 672 | + | |
| 673 | + // Copy protected members | |
| 674 | + m_obs = app.m_obs; | |
| 675 | + m_infiles = app.m_infiles; | |
| 676 | + m_timemin = app.m_timemin; | |
| 677 | + m_timemax = app.m_timemax; | |
| 678 | + m_use_xml = app.m_use_xml; | |
| 679 | + | |
| 660 | 680 | // Return |
| 661 | 681 | return; |
| 662 | 682 | } |
| ... | ... | @@ -668,8 +688,9 @@ void ctselect::copy_members(const ctselect& app) |
| 668 | 688 | void ctselect::free_members(void) |
| 669 | 689 | { |
| 670 | 690 | // Write separator into logger |
| 671 | - if (logTerse()) | |
| 691 | + if (logTerse()) { | |
| 672 | 692 | log << std::endl; |
| 693 | + } | |
| 673 | 694 | |
| 674 | 695 | // Return |
| 675 | 696 | return; |
| ... | ... | @@ -743,3 +764,140 @@ std::string ctselect::check_infile(const std::string& filename) const |
| 743 | 764 | return message; |
| 744 | 765 | } |
| 745 | 766 | |
| 767 | + | |
| 768 | +/***********************************************************************//** | |
| 769 | + * @brief Set output file name. | |
| 770 | + * | |
| 771 | + * @param[in] filename Input file name. | |
| 772 | + * | |
| 773 | + * This converts an input filename into an output filename by prepending a | |
| 774 | + * prefix to the input filename. Any path will be stripped from the input | |
| 775 | + * filename. | |
| 776 | + ***************************************************************************/ | |
| 777 | +std::string ctselect::set_outfile_name(const std::string& filename) const | |
| 778 | +{ | |
| 779 | + // Split input filename into path elements | |
| 780 | + std::vector<std::string> elements = split(filename, "/"); | |
| 781 | + | |
| 782 | + // The last path element is the filename | |
| 783 | + std::string outname = m_prefix + elements[elements.size()-1]; | |
| 784 | + | |
| 785 | + // Return output filename | |
| 786 | + return outname; | |
| 787 | +} | |
| 788 | + | |
| 789 | + | |
| 790 | +/***********************************************************************//** | |
| 791 | + * @brief Save event list in FITS format. | |
| 792 | + * | |
| 793 | + * Save the event list as a FITS file. The filename of the FITS file is | |
| 794 | + * specified by the outfile parameter. | |
| 795 | + ***************************************************************************/ | |
| 796 | +void ctselect::save_fits(void) | |
| 797 | +{ | |
| 798 | + // Get output filename | |
| 799 | + m_outfile = (*this)["outfile"].value(); | |
| 800 | + | |
| 801 | + // Get CTA observation from observation container | |
| 802 | + GCTAObservation* obs = dynamic_cast<GCTAObservation*>(&m_obs[0]); | |
| 803 | + | |
| 804 | + // Save event list | |
| 805 | + save_event_list(obs, m_infiles[0], m_outfile); | |
| 806 | + | |
| 807 | + // Return | |
| 808 | + return; | |
| 809 | +} | |
| 810 | + | |
| 811 | + | |
| 812 | +/***********************************************************************//** | |
| 813 | + * @brief Save event list(s) in XML format. | |
| 814 | + * | |
| 815 | + * Save the event list(s) into FITS files and write the file path information | |
| 816 | + * into a XML file. The filename of the XML file is specified by the outfile | |
| 817 | + * parameter, the filename(s) of the event lists are built by prepending a | |
| 818 | + * prefix to the input event list filenames. Any path present in the input | |
| 819 | + * filename will be stripped, i.e. the event list(s) will be written in the | |
| 820 | + * local working directory (unless a path is specified in the prefix). | |
| 821 | + ***************************************************************************/ | |
| 822 | +void ctselect::save_xml(void) | |
| 823 | +{ | |
| 824 | + // Get output filename and prefix | |
| 825 | + m_outfile = (*this)["outfile"].value(); | |
| 826 | + m_prefix = (*this)["prefix"].value(); | |
| 827 | + | |
| 828 | + // Loop over all observation in the container | |
| 829 | + for (int i = 0; i < m_obs.size(); ++i) { | |
| 830 | + | |
| 831 | + // Get CTA observation | |
| 832 | + GCTAObservation* obs = dynamic_cast<GCTAObservation*>(&m_obs[i]); | |
| 833 | + | |
| 834 | + // Handle only CTA observations | |
| 835 | + if (obs != NULL) { | |
| 836 | + | |
| 837 | + // Set event output file name | |
| 838 | + std::string outfile = set_outfile_name(m_infiles[i]); | |
| 839 | + | |
| 840 | + // Store output file name in observation | |
| 841 | + obs->eventfile(outfile); | |
| 842 | + | |
| 843 | + // Save event list | |
| 844 | + save_event_list(obs, m_infiles[i], outfile); | |
| 845 | + | |
| 846 | + } // endif: observation was a CTA observations | |
| 847 | + | |
| 848 | + } // endfor: looped over observations | |
| 849 | + | |
| 850 | + // Save observations in XML file | |
| 851 | + m_obs.save(m_outfile); | |
| 852 | + | |
| 853 | + // Return | |
| 854 | + return; | |
| 855 | +} | |
| 856 | + | |
| 857 | + | |
| 858 | +/***********************************************************************//** | |
| 859 | + * @brief Save event list into FITS file | |
| 860 | + * | |
| 861 | + * @param[in] obs Pointer to CTA observation. | |
| 862 | + * @param[in] infile Input file name. | |
| 863 | + * @param[in] outfile Output file name. | |
| 864 | + * | |
| 865 | + * Saves an event list into a FITS file and copy all others extensions from | |
| 866 | + * the input file to the output file. | |
| 867 | + ***************************************************************************/ | |
| 868 | +void ctselect::save_event_list(const GCTAObservation* obs, | |
| 869 | + const std::string& infile, | |
| 870 | + const std::string& outfile) const | |
| 871 | +{ | |
| 872 | + // Save only if observation is valid | |
| 873 | + if (obs != NULL) { | |
| 874 | + | |
| 875 | + // Save observation into FITS file | |
| 876 | + obs->save(outfile, clobber()); | |
| 877 | + | |
| 878 | + // Copy all extensions other than EVENTS and GTI from the input to | |
| 879 | + // the output event list. The EVENTS and GTI extensions are written | |
| 880 | + // by the save method, all others that may eventually be present | |
| 881 | + // have to be copied by hand. | |
| 882 | + GFits infits(infile); | |
| 883 | + GFits outfits(outfile); | |
| 884 | + for (int extno = 1; extno < infits.size(); ++extno) { | |
| 885 | + GFitsHDU* hdu = infits.hdu(extno); | |
| 886 | + if (hdu->extname() != "EVENTS" && hdu->extname() != "GTI") { | |
| 887 | + outfits.append(*hdu); | |
| 888 | + } | |
| 889 | + } | |
| 890 | + | |
| 891 | + // Close input file | |
| 892 | + infits.close(); | |
| 893 | + | |
| 894 | + // Save file to disk and close it (we need both operations) | |
| 895 | + outfits.save(true); | |
| 896 | + outfits.close(); | |
| 897 | + | |
| 898 | + } // endif: observation was valid | |
| 899 | + | |
| 900 | + // Return | |
| 901 | + return; | |
| 902 | +} | |
| 903 | + | ... | ... |
src/ctselect/ctselect.hpp
| 1 | 1 | /*************************************************************************** |
| 2 | 2 | * ctselect - CTA data selection tool * |
| 3 | 3 | * ----------------------------------------------------------------------- * |
| 4 | - * copyright (C) 2010-2011 by Juergen Knoedlseder * | |
| 4 | + * copyright (C) 2010-2012 by Juergen Knoedlseder * | |
| 5 | 5 | * ----------------------------------------------------------------------- * |
| 6 | 6 | * * |
| 7 | 7 | * This program is free software: you can redistribute it and/or modify * |
| ... | ... | @@ -70,10 +70,17 @@ protected: |
| 70 | 70 | void copy_members(const ctselect& app); |
| 71 | 71 | void free_members(void); |
| 72 | 72 | std::string check_infile(const std::string& filename) const; |
| 73 | + std::string set_outfile_name(const std::string& filename) const; | |
| 74 | + void save_fits(void); | |
| 75 | + void save_xml(void); | |
| 76 | + void save_event_list(const GCTAObservation* obs, | |
| 77 | + const std::string& infile, | |
| 78 | + const std::string& outfile) const; | |
| 73 | 79 | |
| 74 | 80 | // User parameters |
| 75 | - std::string m_infile; //!< Input event list | |
| 76 | - std::string m_outfile; //!< Output event list | |
| 81 | + std::string m_infile; //!< Input event list or XML file | |
| 82 | + std::string m_outfile; //!< Output event list or XML file | |
| 83 | + std::string m_prefix; //!< Prefix for multiple event lists | |
| 77 | 84 | double m_ra; //!< RA of ROI centre |
| 78 | 85 | double m_dec; //!< DEC of ROI centre |
| 79 | 86 | double m_rad; //!< ROI radius |
| ... | ... | @@ -88,6 +95,7 @@ protected: |
| 88 | 95 | std::vector<std::string> m_infiles; //!< Input event filenames |
| 89 | 96 | GTime m_timemin; //!< Earliest time |
| 90 | 97 | GTime m_timemax; //!< Latest time |
| 98 | + bool m_use_xml; //!< Use XML file instead of FITS file | |
| 91 | 99 | }; |
| 92 | 100 | |
| 93 | 101 | #endif /* CTSELECT_HPP */ | ... | ... |