Commit b82ee38d87444dc6991a492e1c97e744ff761c3d
1 parent
3af8c312
Handle non-default event and Good Time Interval extension names (should fix #1598).
Showing
5 changed files
with
275 additions
and
77 deletions
ChangeLog
| 1 | -2016-01-11 Juergen Knoedlseder <jurgen.knodlseder@irap.omp.eu> | |
| 1 | +2016-01-20 Juergen Knoedlseder <jurgen.knodlseder@irap.omp.eu> | |
| 2 | 2 | |
| 3 | 3 | * Version 1.1.0 released |
| 4 | 4 | ======================== |
| 5 | 5 | |
| 6 | + ctselect allows usage of non-default events and GTI extensions (#1598) | |
| 7 | + | |
| 6 | 8 | |
| 7 | 9 | 2016-01-11 Juergen Knoedlseder <jurgen.knodlseder@irap.omp.eu> |
| 8 | 10 | ... | ... |
NEWS
| ... | ... | @@ -2,7 +2,7 @@ New Features and Important Changes in ctools 1.1.0 |
| 2 | 2 | |
| 3 | 3 | Author(s) : Juergen Knoedlseder |
| 4 | 4 | |
| 5 | -11 January 2016 | |
| 5 | +20 January 2016 | |
| 6 | 6 | |
| 7 | 7 | |
| 8 | 8 | 1. Introduction |
| ... | ... | @@ -33,7 +33,36 @@ None |
| 33 | 33 | |
| 34 | 34 | 6. ctselect - CTA event selection |
| 35 | 35 | --------------------------------- |
| 36 | -None | |
| 36 | +The tool now allows the usage of non-default extension names for the event | |
| 37 | +and Good Time Intervals. If the events are not located in the "EVENTS" | |
| 38 | +extension, the extension name can be provided by appending the extension | |
| 39 | +name to the input file name using the syntax | |
| 40 | + | |
| 41 | + <filename>[<event extension name>] | |
| 42 | + | |
| 43 | +where <filename> needs to be replaced by the name of the FITS file and | |
| 44 | +<event extension name> by the name of the FITS extension. ctselect also | |
| 45 | +extracts the name of the Good Time Intervals extension from the data sub- | |
| 46 | +space keywords provided in the header of the event file. | |
| 47 | + | |
| 48 | +The user has now also the possibility to specify other extension names for | |
| 49 | +the events and the Good Time intervals upon writing of the selected output | |
| 50 | +file. The format of the "outobs" parameter for this is | |
| 51 | + | |
| 52 | + <filename>[<event extension name;GTI extension name>] | |
| 53 | + | |
| 54 | +If only an event extension name is provided using | |
| 55 | + | |
| 56 | + <filename>[<event extension name>] | |
| 57 | + | |
| 58 | +the original extension name will be kept for the GTIs. Changing only the | |
| 59 | +GTI extension name can be achieved using | |
| 60 | + | |
| 61 | + <filename>[;GTI extension name>] | |
| 62 | + | |
| 63 | +The ctselect tool now can also write the output into the same file that | |
| 64 | +was input, replacing the initial event (and eventually also Good Time | |
| 65 | +Intervals) extensions. | |
| 37 | 66 | |
| 38 | 67 | |
| 39 | 68 | 7. ctbin - CTA event binning | ... | ... |
src/ctselect/ctselect.cpp
| 1 | 1 | /*************************************************************************** |
| 2 | 2 | * ctselect - Data selection tool * |
| 3 | 3 | * ----------------------------------------------------------------------- * |
| 4 | - * copyright (C) 2010-2015 by Juergen Knoedlseder * | |
| 4 | + * copyright (C) 2010-2016 by Juergen Knoedlseder * | |
| 5 | 5 | * ----------------------------------------------------------------------- * |
| 6 | 6 | * * |
| 7 | 7 | * This program is free software: you can redistribute it and/or modify * |
| ... | ... | @@ -35,7 +35,7 @@ |
| 35 | 35 | /* __ Method name definitions ____________________________________________ */ |
| 36 | 36 | #define G_RUN "ctselect::run()" |
| 37 | 37 | #define G_SELECT_EVENTS "ctselect::select_events(GCTAObservation*, "\ |
| 38 | - "std::string&)" | |
| 38 | + "std::string&, std::string&, std::string&)" | |
| 39 | 39 | #define G_SET_EBOUNDS "ctselect::set_ebounds(GCTAObservation*, GEbounds&)" |
| 40 | 40 | #define G_GET_PARAMETERS "ctselect::get_parameters()" |
| 41 | 41 | |
| ... | ... | @@ -69,8 +69,8 @@ ctselect::ctselect(void) : ctool(CTSELECT_NAME, CTSELECT_VERSION) |
| 69 | 69 | * |
| 70 | 70 | * param[in] obs Observation container. |
| 71 | 71 | * |
| 72 | - * This constructor creates an instance of the class that is initialised from | |
| 73 | - * an observation container. | |
| 72 | + * Creates an instance of the class that is initialised using the information | |
| 73 | + * provided in an observation container. | |
| 74 | 74 | ***************************************************************************/ |
| 75 | 75 | ctselect::ctselect(const GObservations& obs) : |
| 76 | 76 | ctool(CTSELECT_NAME, CTSELECT_VERSION) |
| ... | ... | @@ -206,7 +206,7 @@ void ctselect::clear(void) |
| 206 | 206 | * selection is done by writing each observation to a temporary file and |
| 207 | 207 | * re-opening the temporary file using the cfitsio event filter syntax. |
| 208 | 208 | * The temporary file is deleted after this action so that no disk overflow |
| 209 | - * will occur. | |
| 209 | + * will occur. | |
| 210 | 210 | ***************************************************************************/ |
| 211 | 211 | void ctselect::run(void) |
| 212 | 212 | { |
| ... | ... | @@ -255,8 +255,11 @@ void ctselect::run(void) |
| 255 | 255 | log.header3(header); |
| 256 | 256 | } |
| 257 | 257 | |
| 258 | - // Initialise event input and output filenames | |
| 258 | + // Initialise event input and output filenames and the event | |
| 259 | + // and GTI extension names | |
| 259 | 260 | m_infiles.push_back(""); |
| 261 | + m_evtname.push_back("EVENTS"); | |
| 262 | + m_gtiname.push_back("GTI"); | |
| 260 | 263 | |
| 261 | 264 | // Get CTA observation |
| 262 | 265 | GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]); |
| ... | ... | @@ -287,6 +290,23 @@ void ctselect::run(void) |
| 287 | 290 | // Save event file name (for possible saving) |
| 288 | 291 | m_infiles[i] = obs->eventfile(); |
| 289 | 292 | |
| 293 | + // Extract event and GTI extension names from input FITS file | |
| 294 | + GFilename fname(m_infiles[i]); | |
| 295 | + if (fname.has_extname()) { | |
| 296 | + m_evtname[i] = fname.extname(); | |
| 297 | + } | |
| 298 | + m_gtiname[i] = get_gtiname(fname.filename(), m_evtname[i]); | |
| 299 | + | |
| 300 | + // Log input file information | |
| 301 | + if (logTerse()) { | |
| 302 | + log << gammalib::parformat("Input filename"); | |
| 303 | + log << m_infiles[i] << std::endl; | |
| 304 | + log << gammalib::parformat("Event extension name"); | |
| 305 | + log << m_evtname[i] << std::endl; | |
| 306 | + log << gammalib::parformat("GTI extension name"); | |
| 307 | + log << m_gtiname[i] << std::endl; | |
| 308 | + } | |
| 309 | + | |
| 290 | 310 | // Fall through in case that the event file is empty |
| 291 | 311 | if (obs->events()->size() == 0) { |
| 292 | 312 | if (logTerse()) { |
| ... | ... | @@ -297,6 +317,14 @@ void ctselect::run(void) |
| 297 | 317 | continue; |
| 298 | 318 | } |
| 299 | 319 | |
| 320 | + // If we have an input file then check it | |
| 321 | + if (!m_infiles[i].empty()) { | |
| 322 | + std::string message = check_infile(m_infiles[i], m_evtname[i]); | |
| 323 | + if (message.length() > 0) { | |
| 324 | + throw GException::app_error(G_RUN, message); | |
| 325 | + } | |
| 326 | + } | |
| 327 | + | |
| 300 | 328 | // Get temporary file name |
| 301 | 329 | #if G_USE_MKSTEMP |
| 302 | 330 | char tpl[] = "ctselectXXXXXX"; |
| ... | ... | @@ -306,10 +334,13 @@ void ctselect::run(void) |
| 306 | 334 | std::string filename = std::tmpnam(NULL); |
| 307 | 335 | #endif |
| 308 | 336 | |
| 309 | - // Save observation in temporary file | |
| 310 | - obs->save(filename, true); | |
| 337 | + // Save observation in temporary file. We add here the events and | |
| 338 | + // GTI extension name so that the GCTAObservation::save method can | |
| 339 | + // use this information for writing the proper extension names into | |
| 340 | + // the temporary file | |
| 341 | + obs->save(filename+"["+m_evtname[i]+";"+ m_gtiname[i]+"]", true); | |
| 311 | 342 | |
| 312 | - // Log saved FITS file | |
| 343 | + // Log saved FITS file. | |
| 313 | 344 | if (logExplicit()) { |
| 314 | 345 | GFits tmpfile(filename); |
| 315 | 346 | log << std::endl; |
| ... | ... | @@ -318,14 +349,16 @@ void ctselect::run(void) |
| 318 | 349 | tmpfile.close(); |
| 319 | 350 | } |
| 320 | 351 | |
| 321 | - // Check temporary file | |
| 322 | - std::string message = check_infile(filename); | |
| 323 | - if (message.length() > 0) { | |
| 324 | - throw GException::app_error(G_RUN, message); | |
| 352 | + // If we have a temporary file then check it | |
| 353 | + if (!filename.empty()) { | |
| 354 | + std::string message = check_infile(filename, m_evtname[i]); | |
| 355 | + if (message.length() > 0) { | |
| 356 | + throw GException::app_error(G_RUN, message); | |
| 357 | + } | |
| 325 | 358 | } |
| 326 | 359 | |
| 327 | 360 | // Load observation from temporary file, including event selection |
| 328 | - select_events(obs, filename); | |
| 361 | + select_events(obs, filename, m_evtname[i], m_gtiname[i]); | |
| 329 | 362 | |
| 330 | 363 | // Close temporary file |
| 331 | 364 | #if G_USE_MKSTEMP |
| ... | ... | @@ -430,6 +463,8 @@ void ctselect::init_members(void) |
| 430 | 463 | // Initialise protected members |
| 431 | 464 | m_obs.clear(); |
| 432 | 465 | m_infiles.clear(); |
| 466 | + m_evtname.clear(); | |
| 467 | + m_gtiname.clear(); | |
| 433 | 468 | m_timemin.clear(); |
| 434 | 469 | m_timemax.clear(); |
| 435 | 470 | m_select_energy = true; |
| ... | ... | @@ -449,7 +484,7 @@ void ctselect::init_members(void) |
| 449 | 484 | void ctselect::copy_members(const ctselect& app) |
| 450 | 485 | { |
| 451 | 486 | // Copy parameters |
| 452 | - m_outobs = app.m_outobs; | |
| 487 | + m_outobs = app.m_outobs; | |
| 453 | 488 | m_prefix = app.m_prefix; |
| 454 | 489 | m_usepnt = app.m_usepnt; |
| 455 | 490 | m_ra = app.m_ra; |
| ... | ... | @@ -465,6 +500,8 @@ void ctselect::copy_members(const ctselect& app) |
| 465 | 500 | // Copy protected members |
| 466 | 501 | m_obs = app.m_obs; |
| 467 | 502 | m_infiles = app.m_infiles; |
| 503 | + m_evtname = app.m_evtname; | |
| 504 | + m_gtiname = app.m_gtiname; | |
| 468 | 505 | m_timemin = app.m_timemin; |
| 469 | 506 | m_timemax = app.m_timemax; |
| 470 | 507 | m_select_energy = app.m_select_energy; |
| ... | ... | @@ -594,27 +631,29 @@ void ctselect::get_parameters(void) |
| 594 | 631 | /***********************************************************************//** |
| 595 | 632 | * @brief Select events |
| 596 | 633 | * |
| 597 | - * @param[in] obs CTA observation. | |
| 634 | + * @param[in,out] obs CTA observation. | |
| 598 | 635 | * @param[in] filename File name. |
| 636 | + * @param[in] evtname Event extension name. | |
| 637 | + * @param[in] gtiname GTI extension name. | |
| 599 | 638 | * |
| 600 | 639 | * @exception GException::invalid_value |
| 601 | - * No EVENTS extension found in FITS file. | |
| 640 | + * No events extension found in FITS file. | |
| 602 | 641 | * |
| 603 | 642 | * Select events from a FITS file by making use of the selection possibility |
| 604 | 643 | * of the cfitsio library on loading a file. A selection string is created |
| 605 | 644 | * from the specified criteria that is appended to the filename so that |
| 606 | 645 | * cfitsio will automatically filter the event data. This selection string |
| 607 | - * is then applied when opening the FITS file. The opened FITS file is then | |
| 608 | - * saved into a temporary file which is the loaded into the actual CTA | |
| 609 | - * observation, overwriting the old CTA observation. The ROI, GTI and Ebounds | |
| 610 | - * of the CTA event list are then set accordingly to the specified selection. | |
| 611 | - * Finally, the temporary file created during this process is removed. | |
| 646 | + * is then applied when opening the FITS file. The event list in the current | |
| 647 | + * observation is replaced by selected event list read from the FITS file. | |
| 612 | 648 | * |
| 613 | 649 | * Good Time Intervals of the observation will be limited to the time |
| 614 | 650 | * interval [m_tmin, m_tmax]. If m_tmin=m_tmax=0, no time selection is |
| 615 | 651 | * performed. |
| 616 | 652 | ***************************************************************************/ |
| 617 | -void ctselect::select_events(GCTAObservation* obs, const std::string& filename) | |
| 653 | +void ctselect::select_events(GCTAObservation* obs, | |
| 654 | + const std::string& filename, | |
| 655 | + const std::string& evtname, | |
| 656 | + const std::string& gtiname) | |
| 618 | 657 | { |
| 619 | 658 | // Initialise selection string |
| 620 | 659 | std::string selection; |
| ... | ... | @@ -642,7 +681,7 @@ void ctselect::select_events(GCTAObservation* obs, const std::string& filename) |
| 642 | 681 | } |
| 643 | 682 | |
| 644 | 683 | // Analyse expression to see if a selection is required |
| 645 | - bool select_expr = (gammalib::strip_whitespace(m_expr).length() > 0); | |
| 684 | + bool select_expr = (gammalib::strip_whitespace(m_expr).length() > 0); | |
| 646 | 685 | |
| 647 | 686 | // Set RA/DEC selection. If the "usepnt" parameter is set to true then |
| 648 | 687 | // use the pointing direction as the ROI centre. |
| ... | ... | @@ -835,7 +874,7 @@ void ctselect::select_events(GCTAObservation* obs, const std::string& filename) |
| 835 | 874 | // Build input filename including selection expression |
| 836 | 875 | std::string expression = filename; |
| 837 | 876 | if (selection.length() > 0) { |
| 838 | - expression += "[EVENTS]["+selection+"]"; | |
| 877 | + expression += "["+evtname+"]["+selection+"]"; | |
| 839 | 878 | } |
| 840 | 879 | |
| 841 | 880 | // Dump FITS filename including selection expression |
| ... | ... | @@ -854,15 +893,16 @@ void ctselect::select_events(GCTAObservation* obs, const std::string& filename) |
| 854 | 893 | log << file << std::endl; |
| 855 | 894 | } |
| 856 | 895 | |
| 857 | - // Check if we have an EVENTS HDU | |
| 858 | - if (!file.contains("EVENTS")) { | |
| 859 | - std::string msg = "No \"EVENTS\" extension found in FITS file \""+ | |
| 860 | - expression+"\"."; | |
| 896 | + // Check if we have an events HDU | |
| 897 | + if (!file.contains(evtname)) { | |
| 898 | + std::string msg = "No events extension \""+evtname+"\" found in " | |
| 899 | + "FITS file. The expression \""+expression+"\" " | |
| 900 | + "was used to open the FITS file."; | |
| 861 | 901 | throw GException::invalid_value(G_SELECT_EVENTS, msg); |
| 862 | 902 | } |
| 863 | 903 | |
| 864 | - // Determine number of events in EVENTS HDU | |
| 865 | - int nevents = file.table("EVENTS")->nrows(); | |
| 904 | + // Determine number of events in the events HDU | |
| 905 | + int nevents = file.table(evtname)->nrows(); | |
| 866 | 906 | |
| 867 | 907 | // If the selected event list is empty or if removal of all events |
| 868 | 908 | // has been requested then append an empty event list to the observation. |
| ... | ... | @@ -1060,23 +1100,30 @@ GEbounds ctselect::set_ebounds(GCTAObservation* obs, const GEbounds& ebounds) co |
| 1060 | 1100 | * @brief Check input filename |
| 1061 | 1101 | * |
| 1062 | 1102 | * @param[in] filename File name. |
| 1103 | + * @param[in] evtname Event extension name. | |
| 1063 | 1104 | * |
| 1064 | 1105 | * This method checks if the input FITS file is correct. |
| 1065 | 1106 | ***************************************************************************/ |
| 1066 | -std::string ctselect::check_infile(const std::string& filename) const | |
| 1107 | +std::string ctselect::check_infile(const std::string& filename, | |
| 1108 | + const std::string& evtname) const | |
| 1067 | 1109 | { |
| 1068 | 1110 | // Initialise message string |
| 1069 | 1111 | std::string message = ""; |
| 1070 | 1112 | |
| 1071 | 1113 | // Open FITS file |
| 1072 | - GFits file(filename); | |
| 1114 | + GFits fits(filename); | |
| 1115 | + | |
| 1116 | + // Check for existence of events extensions | |
| 1117 | + if (!fits.contains(evtname)) { | |
| 1118 | + message = "No \""+evtname+"\" extension found in input file \""+ | |
| 1119 | + filename + "\"."; | |
| 1120 | + } | |
| 1073 | 1121 | |
| 1074 | - // Check for EVENTS HDU | |
| 1075 | - GFitsTable* table = NULL; | |
| 1076 | - try { | |
| 1122 | + // ... otherwise check column names | |
| 1123 | + else { | |
| 1077 | 1124 | |
| 1078 | 1125 | // Get pointer to FITS table |
| 1079 | - table = file.table("EVENTS"); | |
| 1126 | + GFitsTable* table = fits.table(evtname); | |
| 1080 | 1127 | |
| 1081 | 1128 | // Initialise list of missing columns |
| 1082 | 1129 | std::vector<std::string> missing; |
| ... | ... | @@ -1103,9 +1150,9 @@ std::string ctselect::check_infile(const std::string& filename) const |
| 1103 | 1150 | |
| 1104 | 1151 | // Set error message for missing columns |
| 1105 | 1152 | if (!missing.empty()) { |
| 1106 | - message = "The following columns are missing in the" | |
| 1107 | - " \"EVENTS\" extension of input file \"" | |
| 1108 | - + m_outobs + "\": "; | |
| 1153 | + message = "The following columns are missing in the " | |
| 1154 | + "\""+evtname+"\" extension of input file \""+ | |
| 1155 | + filename + "\": "; | |
| 1109 | 1156 | for (int i = 0; i < missing.size(); ++i) { |
| 1110 | 1157 | message += "\"" + missing[i] + "\""; |
| 1111 | 1158 | if (i < missing.size()-1) { |
| ... | ... | @@ -1114,11 +1161,7 @@ std::string ctselect::check_infile(const std::string& filename) const |
| 1114 | 1161 | } |
| 1115 | 1162 | } |
| 1116 | 1163 | |
| 1117 | - } | |
| 1118 | - catch (GException::fits_hdu_not_found& e) { | |
| 1119 | - message = "No \"EVENTS\" extension found in input file \"" | |
| 1120 | - + m_outobs + "\"."; | |
| 1121 | - } | |
| 1164 | + } // endelse: checked column names | |
| 1122 | 1165 | |
| 1123 | 1166 | // Return |
| 1124 | 1167 | return message; |
| ... | ... | @@ -1130,15 +1173,18 @@ std::string ctselect::check_infile(const std::string& filename) const |
| 1130 | 1173 | * |
| 1131 | 1174 | * @param[in] filename Input file name. |
| 1132 | 1175 | * |
| 1133 | - * Converts an input filename into an output filename by prepending the | |
| 1134 | - * prefix stored in the member m_prefix to the input filename. Any path will | |
| 1135 | - * be stripped from the input filename. Also a trailing ".gz" will be | |
| 1136 | - * stripped. | |
| 1176 | + * Converts an input file name into an output filename by prepending the | |
| 1177 | + * prefix stored in the member m_prefix to the input file name. Any path as | |
| 1178 | + * well as extension will be stripped from the input file name. Also a | |
| 1179 | + * trailing ".gz" will be stripped as one cannot write into gzipped files. | |
| 1137 | 1180 | ***************************************************************************/ |
| 1138 | 1181 | std::string ctselect::set_outfile_name(const std::string& filename) const |
| 1139 | 1182 | { |
| 1140 | - // Split input filename into path elements | |
| 1141 | - std::vector<std::string> elements = gammalib::split(filename, "/"); | |
| 1183 | + // Create filename | |
| 1184 | + GFilename fname(filename); | |
| 1185 | + | |
| 1186 | + // Split input filename without any extensions into path elements | |
| 1187 | + std::vector<std::string> elements = gammalib::split(fname.filename(), "/"); | |
| 1142 | 1188 | |
| 1143 | 1189 | // The last path element is the filename |
| 1144 | 1190 | std::string outname = m_prefix + elements[elements.size()-1]; |
| ... | ... | @@ -1152,10 +1198,43 @@ std::string ctselect::set_outfile_name(const std::string& filename) const |
| 1152 | 1198 | |
| 1153 | 1199 | |
| 1154 | 1200 | /***********************************************************************//** |
| 1201 | + * @brief Get Good Time Intervals extension name | |
| 1202 | + * | |
| 1203 | + * @param[in] filename Input file name. | |
| 1204 | + * @param[in] evtname Events extension name. | |
| 1205 | + * | |
| 1206 | + * Extracts the Good Time Intervals extension name from the event file. We | |
| 1207 | + * do this by loading the events and accessing the Good Time Intervals | |
| 1208 | + * extension name using the GCTAEventList::gtiname() method. If the file name | |
| 1209 | + * is empty, the method returns "GTI". | |
| 1210 | + ***************************************************************************/ | |
| 1211 | +std::string ctselect::get_gtiname(const std::string& filename, | |
| 1212 | + const std::string& evtname) const | |
| 1213 | +{ | |
| 1214 | + // Initialise GTI name | |
| 1215 | + std::string gtiname = "GTI"; | |
| 1216 | + | |
| 1217 | + // Continue only if the filename is not empty | |
| 1218 | + if (!filename.empty()) { | |
| 1219 | + | |
| 1220 | + // Load events | |
| 1221 | + GCTAEventList events(filename+"["+evtname+"]"); | |
| 1222 | + | |
| 1223 | + // Get GTI name | |
| 1224 | + gtiname = events.gtiname(); | |
| 1225 | + | |
| 1226 | + } | |
| 1227 | + | |
| 1228 | + // Return GTI name | |
| 1229 | + return (gtiname); | |
| 1230 | +} | |
| 1231 | + | |
| 1232 | + | |
| 1233 | +/***********************************************************************//** | |
| 1155 | 1234 | * @brief Save event list in FITS format. |
| 1156 | 1235 | * |
| 1157 | - * Save the event list as a FITS file. The filename of the FITS file is | |
| 1158 | - * specified by the outfile parameter. | |
| 1236 | + * Save the event list as a FITS file. The file name of the FITS file is | |
| 1237 | + * specified by the "outobs" parameter. | |
| 1159 | 1238 | ***************************************************************************/ |
| 1160 | 1239 | void ctselect::save_fits(void) |
| 1161 | 1240 | { |
| ... | ... | @@ -1168,16 +1247,32 @@ void ctselect::save_fits(void) |
| 1168 | 1247 | // Save only if it's a CTA observation |
| 1169 | 1248 | if (obs != NULL) { |
| 1170 | 1249 | |
| 1171 | - // Save only if filename is non-empty | |
| 1250 | + // Save only if file name is non-empty | |
| 1172 | 1251 | if (m_infiles[0].length() > 0) { |
| 1173 | 1252 | |
| 1174 | - // Dump filename | |
| 1253 | + // Create file name object | |
| 1254 | + GFilename fname(m_outobs); | |
| 1255 | + | |
| 1256 | + // Extract filename and event extension name | |
| 1257 | + std::string outfile = fname.filename(); | |
| 1258 | + | |
| 1259 | + // Append event extension name. We handle here the possibility | |
| 1260 | + // to write the events into a different extension. | |
| 1261 | + if (fname.has_extname()) { | |
| 1262 | + outfile += "["+fname.extname()+"]"; | |
| 1263 | + } | |
| 1264 | + else { | |
| 1265 | + outfile += "["+m_evtname[0]+"]"; | |
| 1266 | + } | |
| 1267 | + | |
| 1268 | + // Log filename | |
| 1175 | 1269 | if (logTerse()) { |
| 1176 | - log << "Save \""+m_infiles[0]+"\"" << std::endl; | |
| 1270 | + log << "Save \""+outfile+"\"" << std::endl; | |
| 1177 | 1271 | } |
| 1178 | 1272 | |
| 1179 | 1273 | // Save event list |
| 1180 | - save_event_list(obs, m_infiles[0], m_outobs); | |
| 1274 | + save_event_list(obs, m_infiles[0], m_evtname[0], m_gtiname[0], | |
| 1275 | + outfile); | |
| 1181 | 1276 | |
| 1182 | 1277 | } // endif: filename was non empty |
| 1183 | 1278 | |
| ... | ... | @@ -1235,7 +1330,10 @@ void ctselect::save_xml(void) |
| 1235 | 1330 | // Set event output file name |
| 1236 | 1331 | std::string outfile = set_outfile_name(m_infiles[i]); |
| 1237 | 1332 | |
| 1238 | - // Dump filename | |
| 1333 | + // Append event extension name | |
| 1334 | + outfile += "["+m_evtname[i]+"]"; | |
| 1335 | + | |
| 1336 | + // Log filename | |
| 1239 | 1337 | if (logTerse()) { |
| 1240 | 1338 | log << "Save \""+outfile+"\"" << std::endl; |
| 1241 | 1339 | } |
| ... | ... | @@ -1244,7 +1342,8 @@ void ctselect::save_xml(void) |
| 1244 | 1342 | obs->eventfile(outfile); |
| 1245 | 1343 | |
| 1246 | 1344 | // Save event list |
| 1247 | - save_event_list(obs, m_infiles[i], outfile); | |
| 1345 | + save_event_list(obs, m_infiles[i], m_evtname[i], m_gtiname[i], | |
| 1346 | + outfile); | |
| 1248 | 1347 | |
| 1249 | 1348 | } // endfor: looped over observations |
| 1250 | 1349 | |
| ... | ... | @@ -1266,13 +1365,45 @@ void ctselect::save_xml(void) |
| 1266 | 1365 | * |
| 1267 | 1366 | * @param[in] obs Pointer to CTA observation. |
| 1268 | 1367 | * @param[in] infile Input file name. |
| 1368 | + * @param[in] evtname Event extension name. | |
| 1369 | + * @param[in] gtiname GTI extension name. | |
| 1269 | 1370 | * @param[in] outfile Output file name. |
| 1270 | 1371 | * |
| 1271 | - * Saves an event list into a FITS file and copy all others extensions from | |
| 1272 | - * the input file to the output file. | |
| 1372 | + * Saves an event list and the corresponding Good Time Intervals into a FITS | |
| 1373 | + * file and copy all others extensions from the input file to the output | |
| 1374 | + * file. | |
| 1375 | + * | |
| 1376 | + * If an extension name is specified in the @p outfile argument, the events | |
| 1377 | + * and eventually also the Good Time Intervals will be extracted from the | |
| 1378 | + * argument and used for writing the events. The format is | |
| 1379 | + * | |
| 1380 | + * <filename>[<event extension name;GTI extension name>] | |
| 1381 | + * | |
| 1382 | + * where <filename> needs to be replaced by the name of the FITS file, | |
| 1383 | + * and <event extension name;GTI extension name> by the name of the events | |
| 1384 | + * and Good Time Intervals extensions. For example | |
| 1385 | + * | |
| 1386 | + * myfits.fits[EVENTS1;GTI1] | |
| 1387 | + * | |
| 1388 | + * will write the selected events into the "EVENTS1" extension and the | |
| 1389 | + * Good Time Intervals into the "GTI1" extension of the "myfits.fits" FITS | |
| 1390 | + * file. If the Good Time Intervals extension name is skipped, e.g. | |
| 1391 | + * | |
| 1392 | + * myfits.fits[EVENTS1] | |
| 1393 | + * | |
| 1394 | + * the original extension name for the Good Time Intervals will be kept. | |
| 1395 | + * Analogously, only the Good Time Intervals extension name can be changed | |
| 1396 | + * by specifying | |
| 1397 | + * | |
| 1398 | + * myfits.fits[;GTI1] | |
| 1399 | + * | |
| 1400 | + * In none of the cases will the original events and Good Time Intervals be | |
| 1401 | + * copied over to the output file. | |
| 1273 | 1402 | ***************************************************************************/ |
| 1274 | 1403 | void ctselect::save_event_list(const GCTAObservation* obs, |
| 1275 | 1404 | const std::string& infile, |
| 1405 | + const std::string& evtname, | |
| 1406 | + const std::string& gtiname, | |
| 1276 | 1407 | const std::string& outfile) const |
| 1277 | 1408 | { |
| 1278 | 1409 | // Save only if observation is valid |
| ... | ... | @@ -1281,18 +1412,44 @@ void ctselect::save_event_list(const GCTAObservation* obs, |
| 1281 | 1412 | // Save only if we have an event list |
| 1282 | 1413 | if (obs->eventtype() == "EventList") { |
| 1283 | 1414 | |
| 1284 | - // Save observation into FITS file | |
| 1285 | - obs->save(outfile, clobber()); | |
| 1415 | + // Set output FITS file event extension names | |
| 1416 | + GFilename outname(outfile); | |
| 1417 | + std::string outevt = evtname; | |
| 1418 | + std::string outgti = gtiname; | |
| 1419 | + if (outname.has_extname()) { | |
| 1420 | + std::vector<std::string> extnames = gammalib::split(outname.extname(), ";"); | |
| 1421 | + if (extnames.size() > 0) { | |
| 1422 | + std::string extname = gammalib::strip_whitespace(extnames[0]); | |
| 1423 | + if (!extname.empty()) { | |
| 1424 | + outevt = extname; | |
| 1425 | + } | |
| 1426 | + } | |
| 1427 | + if (extnames.size() > 1) { | |
| 1428 | + std::string extname = gammalib::strip_whitespace(extnames[1]); | |
| 1429 | + if (!extname.empty()) { | |
| 1430 | + outgti = extname; | |
| 1431 | + } | |
| 1432 | + } | |
| 1433 | + } | |
| 1434 | + | |
| 1435 | + // Create output FITS file | |
| 1436 | + GFits outfits; | |
| 1437 | + | |
| 1438 | + // Write observation into FITS file | |
| 1439 | + obs->write(outfits, outevt, outgti); | |
| 1286 | 1440 | |
| 1287 | - // Copy all extensions other than EVENTS and GTI from the input to | |
| 1288 | - // the output event list. The EVENTS and GTI extensions are written | |
| 1289 | - // by the save method, all others that may eventually be present | |
| 1290 | - // have to be copied by hand. | |
| 1441 | + // Copy all extensions other than evtname and gtiname extensions | |
| 1442 | + // from the input to the output event list. The evtname and | |
| 1443 | + // gtiname extensions are written by the save method, all others | |
| 1444 | + // that may eventually be present have to be copied over | |
| 1445 | + // explicitly. | |
| 1291 | 1446 | GFits infits(infile); |
| 1292 | - GFits outfits(outfile); | |
| 1293 | 1447 | for (int extno = 1; extno < infits.size(); ++extno) { |
| 1294 | 1448 | GFitsHDU* hdu = infits.at(extno); |
| 1295 | - if (hdu->extname() != "EVENTS" && hdu->extname() != "GTI") { | |
| 1449 | + if (hdu->extname() != evtname && | |
| 1450 | + hdu->extname() != gtiname && | |
| 1451 | + hdu->extname() != outevt && | |
| 1452 | + hdu->extname() != outgti) { | |
| 1296 | 1453 | outfits.append(*hdu); |
| 1297 | 1454 | } |
| 1298 | 1455 | } |
| ... | ... | @@ -1301,7 +1458,7 @@ void ctselect::save_event_list(const GCTAObservation* obs, |
| 1301 | 1458 | infits.close(); |
| 1302 | 1459 | |
| 1303 | 1460 | // Save file to disk and close it (we need both operations) |
| 1304 | - outfits.save(true); | |
| 1461 | + outfits.saveto(outname.filename(), clobber()); | |
| 1305 | 1462 | outfits.close(); |
| 1306 | 1463 | |
| 1307 | 1464 | } // endif: observation was unbinned | ... | ... |
src/ctselect/ctselect.hpp
| 1 | 1 | /*************************************************************************** |
| 2 | 2 | * ctselect - Data selection tool * |
| 3 | 3 | * ----------------------------------------------------------------------- * |
| 4 | - * copyright (C) 2010-2015 by Juergen Knoedlseder * | |
| 4 | + * copyright (C) 2010-2016 by Juergen Knoedlseder * | |
| 5 | 5 | * ----------------------------------------------------------------------- * |
| 6 | 6 | * * |
| 7 | 7 | * This program is free software: you can redistribute it and/or modify * |
| ... | ... | @@ -70,15 +70,23 @@ protected: |
| 70 | 70 | void copy_members(const ctselect& app); |
| 71 | 71 | void free_members(void); |
| 72 | 72 | void get_parameters(void); |
| 73 | - void select_events(GCTAObservation* obs, const std::string& filename); | |
| 73 | + void select_events(GCTAObservation* obs, | |
| 74 | + const std::string& filename, | |
| 75 | + const std::string& evtname, | |
| 76 | + const std::string& gtiname); | |
| 74 | 77 | GEbounds set_ebounds(GCTAObservation* obs, |
| 75 | 78 | const GEbounds& ebounds) const; |
| 76 | - std::string check_infile(const std::string& filename) const; | |
| 79 | + std::string check_infile(const std::string& filename, | |
| 80 | + const std::string& evtname) const; | |
| 77 | 81 | std::string set_outfile_name(const std::string& filename) const; |
| 82 | + std::string get_gtiname(const std::string& filename, | |
| 83 | + const std::string& evtname) const; | |
| 78 | 84 | void save_fits(void); |
| 79 | 85 | void save_xml(void); |
| 80 | 86 | void save_event_list(const GCTAObservation* obs, |
| 81 | 87 | const std::string& infile, |
| 88 | + const std::string& evtname, | |
| 89 | + const std::string& gtiname, | |
| 82 | 90 | const std::string& outfile) const; |
| 83 | 91 | |
| 84 | 92 | // User parameters |
| ... | ... | @@ -98,12 +106,13 @@ protected: |
| 98 | 106 | // Protected members |
| 99 | 107 | GObservations m_obs; //!< Observations container |
| 100 | 108 | std::vector<std::string> m_infiles; //!< Input event filenames |
| 109 | + std::vector<std::string> m_evtname; //!< Event extension names | |
| 110 | + std::vector<std::string> m_gtiname; //!< GTI extension names | |
| 101 | 111 | GTime m_timemin; //!< Earliest time |
| 102 | 112 | GTime m_timemax; //!< Latest time |
| 103 | 113 | bool m_select_energy; //!< Perform energy selection |
| 104 | 114 | bool m_select_roi; //!< Perform ROI selection |
| 105 | 115 | bool m_select_time; //!< Perform time selection |
| 106 | - | |
| 107 | 116 | }; |
| 108 | 117 | |
| 109 | 118 | ... | ... |