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 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&amp; 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&amp; 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&amp; 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&amp; 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 */
... ...