/***********************************************************************//** * @brief Save counts map(s) in XML format. * * Save the counts map(s) into FITS files and write the file path information * into a XML file. The filename of the XML file is specified by the * m_outfile member, the filename(s) of the counts map(s) are built by * prepending the prefix given by the m_prefix member to the input counts * map(s) filenames. Any path present in the input filename will be stripped, * i.e. the counts map(s) will be written in the local working directory * (unless a path is specified in the m_prefix member). ***************************************************************************/ void ctbin::save_xml(void) { // Get output filename and prefix m_outfile = (*this)["outfile"].filename(); m_prefix = (*this)["prefix"].string(); // Loop over all observation in the container for (int i = 0; i < m_obs.size(); ++i) { // Get CTA observation GCTAObservation* obs = dynamic_cast<GCTAObservation*>(&m_obs[i]); // Handle only CTA observations if (obs != NULL) { // Set event output file name std::string outfile = set_outfile_name(m_infiles[i]); // Store output file name in observation obs->eventfile(outfile); // Save event list save_counts_map(obs, outfile); } // endif: observation was a CTA observations } // endfor: looped over observations // Save observations in XML file m_obs.save(m_outfile); // Return return; }
/***********************************************************************//** * @brief Save event list(s) in XML format. * * Save the event list(s) into FITS files and write the file path information * into a XML file. The filename of the XML file is specified by the outfile * parameter, the filename(s) of the event lists are built by prepending a * prefix to the input event list filenames. Any path present in the input * filename will be stripped, i.e. the event list(s) will be written in the * local working directory (unless a path is specified in the prefix). ***************************************************************************/ void ctobssim::save_xml(void) { // Get output filename and prefix m_outevents = (*this)["outevents"].filename(); m_prefix = (*this)["prefix"].string(); // Issue warning if output filename has no .xml suffix std::string suffix = gammalib::tolower(m_outevents.substr(m_outevents.length()-4,4)); if (suffix != ".xml") { log << "*** WARNING: Name of observation definition output file \""+ m_outevents+"\"" << std::endl; log << "*** WARNING: does not terminate with \".xml\"." << std::endl; log << "*** WARNING: This is not an error, but might be misleading." " It is recommended" << std::endl; log << "*** WARNING: to use the suffix \".xml\" for observation" " definition files." << std::endl; } // Save only if event lists have not yet been saved and disposed if (!m_save_and_dispose) { // Loop over all observation in the container for (int i = 0; i < m_obs.size(); ++i) { // Get CTA observation GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]); // Handle only CTA observations if (obs != NULL) { // Continue only if there is an event list (it may have been disposed) if (obs->events()->size() != 0) { // Set event output file name std::string outfile = m_prefix + gammalib::str(i) + ".fits"; // Store output file name in observation obs->eventfile(outfile); // Save observation into FITS file obs->save(outfile, clobber()); } } // endif: observation was a CTA observations } // endfor: looped over observations } // endif: event list has not yet been saved and disposed // Save observations in XML file m_obs.save(m_outevents); // Return return; }
/***********************************************************************//** * @brief Save event list(s) in XML format. * * Save the event list(s) into FITS files and write the file path information * into a XML file. The filename of the XML file is specified by the outfile * parameter, the filename(s) of the event lists are built by prepending a * prefix to the input event list filenames. Any path present in the input * filename will be stripped, i.e. the event list(s) will be written in the * local working directory (unless a path is specified in the prefix). ***************************************************************************/ void ctobssim::save_xml(void) { // Get output filename and prefix m_outfile = (*this)["outfile"].filename(); m_prefix = (*this)["prefix"].string(); // Issue warning if output filename has no .xml suffix std::string suffix = gammalib::tolower(m_outfile.substr(m_outfile.length()-4,4)); if (suffix != ".xml") { log << "*** WARNING: Name of observation definition output file \""+ m_outfile+"\"" << std::endl; log << "*** WARNING: does not terminate with \".xml\"." << std::endl; log << "*** WARNING: This is not an error, but might be misleading." " It is recommended" << std::endl; log << "*** WARNING: to use the suffix \".xml\" for observation" " definition files." << std::endl; } // Initialise file number int file_num = 0; // Loop over all observation in the container for (int i = 0; i < m_obs.size(); ++i) { // Get CTA observation GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]); // Handle only CTA observations if (obs != NULL) { // Set event output file name std::string outfile = m_prefix + gammalib::str(file_num) + ".fits"; // Store output file name in observation obs->eventfile(outfile); // Save observation into FITS file obs->save(outfile, clobber()); // Increment file number file_num++; } // endif: observation was a CTA observations } // endfor: looped over observations // Save observations in XML file m_obs.save(m_outfile); // Return return; }
/***********************************************************************//** * @brief Simulate event data * * This method runs the simulation. Results are not saved by this method. * Invoke "save" to save the results. ***************************************************************************/ void ctobssim::run(void) { // Switch screen logging on in debug mode if (logDebug()) { log.cout(true); } // Get parameters get_parameters(); // Write input parameters into logger if (logTerse()) { log_parameters(); log << std::endl; } // Special mode: if read ahead is specified we know that we called // the execute() method, hence files are saved immediately and event // lists are disposed afterwards. if (read_ahead()) { m_save_and_dispose = true; } // Determine the number of valid CTA observations, set energy dispersion flag // for all CTA observations and save old values in save_edisp vector int n_observations = 0; std::vector<bool> save_edisp; save_edisp.assign(m_obs.size(), false); for (int i = 0; i < m_obs.size(); ++i) { GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]); if (obs != NULL) { save_edisp[i] = obs->response()->apply_edisp(); obs->response()->apply_edisp(m_apply_edisp); n_observations++; } } // If more than a single observation has been handled then make sure that // an XML file will be used for storage if (n_observations > 1) { m_use_xml = true; } // Write execution mode into logger if (logTerse()) { log << std::endl; log.header1("Execution mode"); log << gammalib::parformat("Event list management"); if (m_save_and_dispose) { log << "Save and dispose (reduces memory needs)" << std::endl; } else { log << "Keep events in memory" << std::endl; } log << gammalib::parformat("Output format"); if (m_use_xml) { log << "Write Observation Definition XML file" << std::endl; } else { log << "Write single event list FITS file" << std::endl; } } // Write seed values into logger if (logTerse()) { log << std::endl; log.header1("Seed values"); for (int i = 0; i < m_rans.size(); ++i) { log << gammalib::parformat("Seed "+gammalib::str(i)); log << gammalib::str(m_rans[i].seed()) << std::endl; } } // Write observation(s) into logger if (logTerse()) { log << std::endl; if (m_obs.size() > 1) { log.header1("Observations"); } else { log.header1("Observation"); } log << m_obs << std::endl; } // Write header if (logTerse()) { log << std::endl; if (m_obs.size() > 1) { log.header1("Simulate observations"); } else { log.header1("Simulate observation"); } } // From here on the code can be parallelized if OpenMP support // is enabled. The code in the following block corresponds to the // code that will be executed in each thread #pragma omp parallel { // Each thread will have it's own logger to avoid conflicts GLog wrklog; if (logDebug()) { wrklog.cout(true); } // Allocate and initialize copies for multi-threading GModels models(m_obs.models()); // Copy configuration from application logger to thread logger wrklog.date(log.date()); wrklog.name(log.name()); // Set a big value to avoid flushing wrklog.max_size(10000000); // Loop over all observation in the container. If OpenMP support // is enabled, this loop will be parallelized. #pragma omp for for (int i = 0; i < m_obs.size(); ++i) { // Get pointer on CTA observation GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]); // Continue only if observation is a CTA observation if (obs != NULL) { // Write header for observation if (logTerse()) { if (obs->name().length() > 1) { wrklog.header3("Observation "+obs->name()); } else { wrklog.header3("Observation"); } } // Work on a clone of the CTA observation. This makes sure that // any memory allocated for computing (for example a response // cache) is properly de-allocated on exit of this run GCTAObservation obs_clone = *obs; // Save number of events before entering simulation int events_before = obs_clone.events()->size(); // Simulate source events simulate_source(&obs_clone, models, m_rans[i], &wrklog); // Simulate source events simulate_background(&obs_clone, models, m_rans[i], &wrklog); // Dump simulation results if (logNormal()) { wrklog << gammalib::parformat("MC events"); wrklog << obs_clone.events()->size() - events_before; wrklog << " (all models)"; wrklog << std::endl; } // Append the event list to the original observation obs->events(*(obs_clone.events())); // If requested, event lists are saved immediately if (m_save_and_dispose) { // Set event output file name. If multiple observations are // handled, build the filename from prefix and observation // index. Otherwise use the outfile parameter. std::string outfile; if (m_use_xml) { m_prefix = (*this)["prefix"].string(); outfile = m_prefix + gammalib::str(i) + ".fits"; } else { outfile = (*this)["outevents"].filename(); } // Store output file name in original observation obs->eventfile(outfile); // Save observation into FITS file. This is a critical zone // to avoid multiple threads writing simultaneously #pragma omp critical { obs_clone.save(outfile, clobber()); } // Dispose events obs->dispose_events(); } // ... otherwise append the event list to the original observation /* else { obs->events(*(obs_clone.events())); } */ } // endif: CTA observation found } // endfor: looped over observations // At the end, the content of the thread logger is added to // the application logger #pragma omp critical (log) { log << wrklog; } } // end pragma omp parallel // Restore energy dispersion flag for all CTA observations for (int i = 0; i < m_obs.size(); ++i) { GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]); if (obs != NULL) { obs->response()->apply_edisp(save_edisp[i]); } } // Return return; }
/***********************************************************************//** * @brief Generate the model map(s) * * This method reads the task parameters from the parfile, sets up the * observation container, loops over all CTA observations in the container * and generates a model map for each CTA observation. ***************************************************************************/ void ctmodel::run(void) { // If we're in debug mode then all output is also dumped on the screen if (logDebug()) { log.cout(true); } // Get task parameters get_parameters(); // Setup observation container setup_obs(); // Write parameters into logger if (logTerse()) { log_parameters(); log << std::endl; } // Write observation(s) into logger if (logTerse()) { log << std::endl; if (m_obs.size() > 1) { log.header1("Observations"); } else { log.header1("Observation"); } log << m_obs << std::endl; } // Write header if (logTerse()) { log << std::endl; if (m_obs.size() > 1) { log.header1("Generate model maps"); } else { log.header1("Generate model map"); } } // Initialise observation counter int n_observations = 0; // Loop over all observations in the container for (int i = 0; i < m_obs.size(); ++i) { // Initialise event input and output filenames m_infiles.push_back(""); // Get CTA observation GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]); // Continue only if observation is a CTA observation if (obs != NULL) { // Write header for observation if (logTerse()) { if (obs->name().length() > 1) { log.header3("Observation "+obs->name()); } else { log.header3("Observation"); } } // Increment number of observations n_observations++; // Save event file name (for possible saving) m_infiles[i] = obs->eventfile(); // Generate model map model_map(obs, m_obs.models()); } // endif: CTA observation found } // endfor: looped over observations // If more than a single observation has been handled then make sure // that an XML file will be used for storage if (n_observations > 1) { m_use_xml = true; } // Write observation(s) into logger if (logTerse()) { log << std::endl; if (m_obs.size() > 1) { log.header1("Observations after model map generation"); } else { log.header1("Observation after model map generation"); } log << m_obs << std::endl; } // Return return; }
/***********************************************************************//** * @brief Create output observation container. * * Creates an output observation container that combines all input CTA * observation into a single cube-style observation. All non CTA observations * present in the observation container are kept. The method furthermore * conserves any response information in case that a single CTA observation * is provided. This supports the original binned analysis. ***************************************************************************/ void ctbin::obs_cube(void) { // If we have only a single CTA observation in the container, then // keep that observation and just attach the event cube to it. Reset // the filename, otherwise we still will have the old event filename // in the log file. if (m_obs.size() == 1) { // Attach event cube to CTA observation GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[0]); if (obs != NULL) { obs->events(this->cube()); obs->eventfile(""); } } // ... otherwise put a single CTA observation in container else { // Allocate observation container GObservations container; // Allocate CTA observation. GCTAObservation obs; // Attach event cube to CTA observation obs.events(this->cube()); // Set map centre as pointing GSkyPixel pixel(0.5*double(m_cube.nx()), 0.5*double(m_cube.ny())); GSkyDir centre = m_cube.pix2dir(pixel); GCTAPointing pointing(centre); // Compute deadtime correction double deadc = (m_ontime > 0.0) ? m_livetime / m_ontime : 0.0; // Set CTA observation attributes obs.pointing(pointing); obs.obs_id(0); obs.ra_obj(centre.ra_deg()); //!< Dummy obs.dec_obj(centre.dec_deg()); //!< Dummy obs.ontime(m_ontime); obs.livetime(m_livetime); obs.deadc(deadc); // Set models in observation container container.models(m_obs.models()); // Append CTA observation container.append(obs); // Copy over all remaining non-CTA observations for (int i = 0; i < m_obs.size(); ++i) { GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]); if (obs == NULL) { container.append(*m_obs[i]); } } // Set observation container m_obs = container; } // endelse: there was not a single CTA observation // Return return; }
/***********************************************************************//** * @brief Generate the model map(s) * * This method reads the task parameters from the parfile, sets up the * observation container, loops over all CTA observations in the container * and generates a model map for each CTA observation. ***************************************************************************/ void ctmodel::run(void) { // If we're in debug mode then all output is also dumped on the screen if (logDebug()) { log.cout(true); } // Get task parameters get_parameters(); // Write parameters into logger if (logTerse()) { log_parameters(); log << std::endl; } // Set energy dispersion flag for all CTA observations and save old // values in save_edisp vector std::vector<bool> save_edisp; save_edisp.assign(m_obs.size(), false); for (int i = 0; i < m_obs.size(); ++i) { GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]); if (obs != NULL) { save_edisp[i] = obs->response()->apply_edisp(); obs->response()->apply_edisp(m_apply_edisp); } } // Write observation(s) into logger if (logTerse()) { log << std::endl; if (m_obs.size() > 1) { log.header1("Observations"); } else { log.header1("Observation"); } log << m_obs << std::endl; } // Write models into logger if (logTerse()) { log << std::endl; log.header1("Models"); log << m_obs.models() << std::endl; } // Write header if (logTerse()) { log << std::endl; log.header1("Generate model cube"); } // Loop over all observations in the container for (int i = 0; i < m_obs.size(); ++i) { // Write header for observation if (logTerse()) { std::string header = m_obs[i]->instrument() + " observation"; if (m_obs[i]->name().length() > 1) { header += " \"" + m_obs[i]->name() + "\""; } if (m_obs[i]->id().length() > 1) { header += " (id=" + m_obs[i]->id() +")"; } log.header3(header); } // Get CTA observation GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]); // Skip observation if it's not CTA if (obs == NULL) { if (logTerse()) { log << " Skipping "; log << m_obs[i]->instrument(); log << " observation" << std::endl; } continue; } // Fill cube and leave loop if we are binned mode (meaning we // only have one binned observation) if (m_binned) { fill_cube(obs); break; } // Skip observation if we have a binned observation if (obs->eventtype() == "CountsCube") { if (logTerse()) { log << " Skipping binned "; log << obs->instrument(); log << " observation" << std::endl; } continue; } // Fill the cube fill_cube(obs); // Dispose events to free memory if event file exists on disk if (obs->eventfile().length() > 0 && gammalib::file_exists(obs->eventfile())) { obs->dispose_events(); } } // endfor: looped over observations // Log cube if (logTerse()) { log << std::endl; log.header1("Model cube"); log << m_cube << std::endl; } // Restore energy dispersion flag for all CTA observations for (int i = 0; i < m_obs.size(); ++i) { GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]); if (obs != NULL) { obs->response()->apply_edisp(save_edisp[i]); } } // Return return; }
/***********************************************************************//** * @brief Select event data * * This method reads in the application parameters and loops over all * observations that were found to perform an event selection. Event * selection is done by writing each observation to a temporary file and * re-opening the temporary file using the cfitsio event filter syntax. * The temporary file is deleted after this action so that no disk overflow * will occur. ***************************************************************************/ void ctselect::run(void) { // Switch screen logging on in debug mode if (logDebug()) { log.cout(true); } // Get parameters get_parameters(); // Write parameters into logger if (logTerse()) { log_parameters(); log << std::endl; } // Write observation(s) into logger if (logTerse()) { log << std::endl; log.header1("Observations before selection"); log << m_obs << std::endl; } // Write header if (logTerse()) { log << std::endl; log.header1("Event selection"); } // Initialise counters int n_observations = 0; // Loop over all observation in the container for (int i = 0; i < m_obs.size(); ++i) { // Initialise event input and output filenames m_infiles.push_back(""); // Get CTA observation GCTAObservation* obs = dynamic_cast<GCTAObservation*>(&m_obs[i]); // Continue only if observation is a CTA observation if (obs != NULL) { // Write header for observation if (logTerse()) { if (obs->name().length() > 1) { log.header3("Observation "+obs->name()); } else { log.header3("Observation"); } } // Increment counter n_observations++; // Save event file name (for possible saving) m_infiles[i] = obs->eventfile(); // Get temporary file name std::string filename = std::tmpnam(NULL); // Save observation in temporary file obs->save(filename, true); // Log saved FITS file if (logExplicit()) { GFits tmpfile(filename); log << std::endl; log.header1("FITS file content of temporary file"); log << tmpfile << std::endl; tmpfile.close(); } // Check temporary file std::string message = check_infile(filename); if (message.length() > 0) { throw GException::app_error(G_RUN, message); } // Load observation from temporary file, including event selection select_events(obs, filename); // Remove temporary file std::remove(filename.c_str()); } // endif: had a CTA observation } // endfor: looped over all observations // If more than a single observation has been handled then make sure that // an XML file will be used for storage if (n_observations > 1) { m_use_xml = true; } // Write observation(s) into logger if (logTerse()) { log << std::endl; log.header1("Observations after selection"); log << m_obs << std::endl; } // Return return; }