Commit 541315183a98525bb3b819d1f6f77ca51d1852f3

Authored by knodlseder
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.
src/ctselect/ctselect.cpp
1 /*************************************************************************** 1 /***************************************************************************
2 * ctselect - CTA data selection tool * 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 * 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 *
@@ -93,7 +93,7 @@ ctselect::ctselect(GObservations obs) : GApplication(CTSELECT_NAME, CTSELECT_VER @@ -93,7 +93,7 @@ ctselect::ctselect(GObservations obs) : GApplication(CTSELECT_NAME, CTSELECT_VER
93 * @param[in] argv Array of command line arguments. 93 * @param[in] argv Array of command line arguments.
94 ***************************************************************************/ 94 ***************************************************************************/
95 ctselect::ctselect(int argc, char *argv[]) : 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 // Initialise members 98 // Initialise members
99 init_members(); 99 init_members();
@@ -232,8 +232,9 @@ void ctselect::execute(void) @@ -232,8 +232,9 @@ void ctselect::execute(void)
232 void ctselect::run(void) 232 void ctselect::run(void)
233 { 233 {
234 // Switch screen logging on in debug mode 234 // Switch screen logging on in debug mode
235 - if (logDebug()) 235 + if (logDebug()) {
236 log.cout(true); 236 log.cout(true);
  237 + }
237 238
238 // Get parameters 239 // Get parameters
239 get_parameters(); 240 get_parameters();
@@ -257,10 +258,13 @@ void ctselect::run(void) @@ -257,10 +258,13 @@ void ctselect::run(void)
257 log.header1("Event selection"); 258 log.header1("Event selection");
258 } 259 }
259 260
  261 + // Initialise counters
  262 + int n_observations = 0;
  263 +
260 // Loop over all observation in the container 264 // Loop over all observation in the container
261 for (int i = 0; i < m_obs.size(); ++i) { 265 for (int i = 0; i < m_obs.size(); ++i) {
262 266
263 - // Initialise event filename 267 + // Initialise event input and output filenames
264 m_infiles.push_back(""); 268 m_infiles.push_back("");
265 269
266 // Get CTA observation 270 // Get CTA observation
@@ -279,6 +283,9 @@ void ctselect::run(void) @@ -279,6 +283,9 @@ void ctselect::run(void)
279 } 283 }
280 } 284 }
281 285
  286 + // Increment counter
  287 + n_observations++;
  288 +
282 // Save event file name (for possible saving) 289 // Save event file name (for possible saving)
283 m_infiles[i] = obs->eventfile(); 290 m_infiles[i] = obs->eventfile();
284 291
@@ -304,6 +311,12 @@ void ctselect::run(void) @@ -304,6 +311,12 @@ void ctselect::run(void)
304 311
305 } // endfor: looped over all observations 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 // Write observation(s) into logger 320 // Write observation(s) into logger
308 if (logTerse()) { 321 if (logTerse()) {
309 log << std::endl; 322 log << std::endl;
@@ -317,14 +330,23 @@ void ctselect::run(void) @@ -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 void ctselect::save(void) 351 void ctselect::save(void)
330 { 352 {
@@ -334,50 +356,15 @@ void ctselect::save(void) @@ -334,50 +356,15 @@ void ctselect::save(void)
334 log.header1("Save observations"); 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 // Return 369 // Return
383 return; 370 return;
@@ -389,6 +376,10 @@ void ctselect::save(void) @@ -389,6 +376,10 @@ void ctselect::save(void)
389 * 376 *
390 * Get all task parameters from parameter file or (if required) by querying 377 * Get all task parameters from parameter file or (if required) by querying
391 * the user. Times are assumed to be in the native CTA MJD format. 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 void ctselect::get_parameters(void) 384 void ctselect::get_parameters(void)
394 { 385 {
@@ -402,11 +393,30 @@ void ctselect::get_parameters(void) @@ -402,11 +393,30 @@ void ctselect::get_parameters(void)
402 // Allocate CTA observation 393 // Allocate CTA observation
403 GCTAObservation obs; 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 } // endif: there was no observation in the container 421 } // endif: there was no observation in the container
412 422
@@ -612,13 +622,10 @@ void ctselect::select_events(GCTAObservation* obs, const std::string&amp; filename) @@ -612,13 +622,10 @@ void ctselect::select_events(GCTAObservation* obs, const std::string&amp; filename)
612 ***************************************************************************/ 622 ***************************************************************************/
613 void ctselect::init_members(void) 623 void ctselect::init_members(void)
614 { 624 {
615 - // Initialise members 625 + // Initialise parameters
616 m_infile.clear(); 626 m_infile.clear();
617 m_outfile.clear(); 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 m_ra = 0.0; 629 m_ra = 0.0;
623 m_dec = 0.0; 630 m_dec = 0.0;
624 m_rad = 0.0; 631 m_rad = 0.0;
@@ -626,6 +633,14 @@ void ctselect::init_members(void) @@ -626,6 +633,14 @@ void ctselect::init_members(void)
626 m_tmax = 0.0; 633 m_tmax = 0.0;
627 m_emin = 0.0; 634 m_emin = 0.0;
628 m_emax = 0.0; 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 // Set logger properties 645 // Set logger properties
631 log.date(true); 646 log.date(true);
@@ -642,13 +657,10 @@ void ctselect::init_members(void) @@ -642,13 +657,10 @@ void ctselect::init_members(void)
642 ***************************************************************************/ 657 ***************************************************************************/
643 void ctselect::copy_members(const ctselect& app) 658 void ctselect::copy_members(const ctselect& app)
644 { 659 {
645 - // Copy attributes 660 + // Copy parameters
646 m_infile = app.m_infile; 661 m_infile = app.m_infile;
647 m_outfile = app.m_outfile; 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 m_ra = app.m_ra; 664 m_ra = app.m_ra;
653 m_dec = app.m_dec; 665 m_dec = app.m_dec;
654 m_rad = app.m_rad; 666 m_rad = app.m_rad;
@@ -656,7 +668,15 @@ void ctselect::copy_members(const ctselect&amp; app) @@ -656,7 +668,15 @@ void ctselect::copy_members(const ctselect&amp; app)
656 m_tmax = app.m_tmax; 668 m_tmax = app.m_tmax;
657 m_emin = app.m_emin; 669 m_emin = app.m_emin;
658 m_emax = app.m_emax; 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 // Return 680 // Return
661 return; 681 return;
662 } 682 }
@@ -668,8 +688,9 @@ void ctselect::copy_members(const ctselect&amp; app) @@ -668,8 +688,9 @@ void ctselect::copy_members(const ctselect&amp; app)
668 void ctselect::free_members(void) 688 void ctselect::free_members(void)
669 { 689 {
670 // Write separator into logger 690 // Write separator into logger
671 - if (logTerse()) 691 + if (logTerse()) {
672 log << std::endl; 692 log << std::endl;
  693 + }
673 694
674 // Return 695 // Return
675 return; 696 return;
@@ -743,3 +764,140 @@ std::string ctselect::check_infile(const std::string&amp; filename) const @@ -743,3 +764,140 @@ std::string ctselect::check_infile(const std::string&amp; filename) const
743 return message; 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 * ctselect - CTA data selection tool * 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 * 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 *
@@ -70,10 +70,17 @@ protected: @@ -70,10 +70,17 @@ protected:
70 void copy_members(const ctselect& app); 70 void copy_members(const ctselect& app);
71 void free_members(void); 71 void free_members(void);
72 std::string check_infile(const std::string& filename) const; 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 // User parameters 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 double m_ra; //!< RA of ROI centre 84 double m_ra; //!< RA of ROI centre
78 double m_dec; //!< DEC of ROI centre 85 double m_dec; //!< DEC of ROI centre
79 double m_rad; //!< ROI radius 86 double m_rad; //!< ROI radius
@@ -88,6 +95,7 @@ protected: @@ -88,6 +95,7 @@ protected:
88 std::vector<std::string> m_infiles; //!< Input event filenames 95 std::vector<std::string> m_infiles; //!< Input event filenames
89 GTime m_timemin; //!< Earliest time 96 GTime m_timemin; //!< Earliest time
90 GTime m_timemax; //!< Latest time 97 GTime m_timemax; //!< Latest time
  98 + bool m_use_xml; //!< Use XML file instead of FITS file
91 }; 99 };
92 100
93 #endif /* CTSELECT_HPP */ 101 #endif /* CTSELECT_HPP */