/***********************************************************************//** * @brief Test CTA Npred computation * * Tests the Npred computation for the diffuse source model. This is done * by loading the model from the XML file and by calling the * GCTAObservation::npred method which in turn calls the * GCTAResponse::npred_diffuse method. The test takes a few seconds. ***************************************************************************/ void TestGCTAResponse::test_response_npred_diffuse(void) { // Set reference value double ref = 11212.26274; // Set parameters double src_ra = 201.3651; double src_dec = -43.0191; double roi_rad = 4.0; // Setup ROI centred on Cen A with a radius of 4 deg GCTARoi roi; GCTAInstDir instDir; instDir.radec_deg(src_ra, src_dec); roi.centre(instDir); roi.radius(roi_rad); // Setup pointing on Cen A GSkyDir skyDir; skyDir.radec_deg(src_ra, src_dec); GCTAPointing pnt; pnt.dir(skyDir); // Setup dummy event list GGti gti; GEbounds ebounds; GTime tstart(0.0); GTime tstop(1800.0); GEnergy emin; GEnergy emax; emin.TeV(0.1); emax.TeV(100.0); gti.append(tstart, tstop); ebounds.append(emin, emax); GCTAEventList events; events.roi(roi); events.gti(gti); events.ebounds(ebounds); // Setup dummy CTA observation GCTAObservation obs; obs.ontime(1800.0); obs.livetime(1600.0); obs.deadc(1600.0/1800.0); obs.response(cta_irf, cta_caldb); obs.events(&events); obs.pointing(pnt); // Load models for Npred computation GModels models(cta_rsp_xml); // Perform Npred computation double npred = obs.npred(models, NULL); // Test Npred test_value(npred, ref, 1.0e-5, "Diffuse Npred computation"); // 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 Test unbinned observation handling ***************************************************************************/ void TestGCTAObservation::test_unbinned_obs(void) { // Set filenames const std::string file1 = "test_cta_obs_unbinned.xml"; // Declare observations GObservations obs; GCTAObservation run; // Load unbinned CTA observation test_try("Load unbinned CTA observation"); try { run.load_unbinned(cta_events); run.response(cta_irf,cta_caldb); test_try_success(); } catch (std::exception &e) { test_try_failure(e); } // Add observation (twice) to data test_try("Load unbinned CTA observation"); try { obs.append(run); obs.append(run); test_try_success(); } catch (std::exception &e) { test_try_failure(e); } // Loop over all events using iterators int num = 0; for (GObservations::iterator event = obs.begin(); event != obs.end(); ++event) { num++; } test_value(num, 8794, 1.0e-20, "Test observation iterator"); // Loop over all events using iterator num = 0; GCTAEventList *ptr = static_cast<GCTAEventList*>(const_cast<GEvents*>(run.events())); for (GCTAEventList::iterator event = ptr->begin(); event != ptr->end(); ++event) { num++; } test_value(num, 4397, 1.0e-20, "Test event iterator"); // Test XML loading test_try("Test XML loading"); try { obs = GObservations(cta_unbin_xml); obs.save(file1); test_try_success(); } catch (std::exception &e) { test_try_failure(e); } // Exit test return; }
/***********************************************************************//** * @brief Test CTA IRF computation for diffuse source model * * Tests the IRF computation for the diffuse source model. This is done * by calling the GCTAObservation::model method which in turn calls the * GCTAResponse::irf_diffuse method. The test is done for a small counts * map to keep the test executing reasonably fast. ***************************************************************************/ void TestGCTAResponse::test_response_irf_diffuse(void) { // Set reference value double ref = 13803.800313356; // Set parameters double src_ra = 201.3651; double src_dec = -43.0191; int nebins = 5; // Setup pointing on Cen A GSkyDir skyDir; skyDir.radec_deg(src_ra, src_dec); GCTAPointing pnt; pnt.dir(skyDir); // Setup skymap (10 energy layers) GSkymap map("CAR", "CEL", src_ra, src_dec, 0.5, 0.5, 10, 10, nebins); // Setup time interval GGti gti; GTime tstart(0.0); GTime tstop(1800.0); gti.append(tstart, tstop); // Setup energy boundaries GEbounds ebounds; GEnergy emin; GEnergy emax; emin.TeV(0.1); emax.TeV(100.0); ebounds.setlog(emin, emax, nebins); // Setup event cube centered on Cen A GCTAEventCube cube(map, ebounds, gti); // Setup dummy CTA observation GCTAObservation obs; obs.ontime(1800.0); obs.livetime(1600.0); obs.deadc(1600.0/1800.0); obs.response(cta_irf, cta_caldb); obs.events(&cube); obs.pointing(pnt); // Load model for IRF computation GModels models(cta_rsp_xml); // Reset sum double sum = 0.0; // Iterate over all bins in event cube for (int i = 0; i < obs.events()->size(); ++i) { // Get event pointer const GEventBin* bin = (*(static_cast<const GEventCube*>(obs.events())))[i]; // Get model and add to sum double model = obs.model(models, *bin, NULL) * bin->size(); sum += model; } // Test sum test_value(sum, ref, 1.0e-5, "Diffuse IRF computation"); // 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 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; } // 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"); } } // Initialise counters int n_observations = 0; // 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); } // 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 looped will be parallelized. #pragma omp for for (int i = 0; i < m_obs.size(); ++i) { // 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) { wrklog.header3("Observation "+obs->name()); } else { wrklog.header3("Observation"); } } // Increment counter n_observations++; // Save number of events before entering simulation int events_before = obs->events()->size(); // Simulate source events simulate_source(obs, m_obs.models(), m_rans[i], &wrklog); // Simulate source events simulate_background(obs, m_obs.models(), m_rans[i], &wrklog); // Dump simulation results if (logNormal()) { wrklog << gammalib::parformat("MC events"); wrklog << obs->events()->size() - events_before; wrklog << " (all models)"; wrklog << std::endl; } } // 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 // 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; } // Return return; }
/***********************************************************************//** * @brief Setup observation container * * @exception GException::no_cube * No event cube found in CTA observation. * * This method sets up the observation container for processing. There are * two cases: * * If there are no observations in the actual observation container, the * method will check in "infile" parameter. If this parameter is "NONE" or * empty, the task parameters will be used to construct a model map. * Otherwise, the method first tries to interpret the "infile" parameter as * a counts map, and attemps loading of the file in an event cube. If this * fails, the method tries to interpret the "infile" parameter as an * observation definition XML file. If this also fails, an exception will * be thrown. * * If observations exist already in the observation container, the method * will simply keep them. * * Test if all CTA observations contain counts maps. * * Finally, if no models exist so far in the observation container, the * models will be loaded from the model XML file. ***************************************************************************/ void ctmodel::setup_obs(void) { // If there are no observations in the container then try to build some if (m_obs.size() == 0) { // If no input filename has been specified, then create a model map // from the task parameters if ((m_infile == "NONE") || (gammalib::strip_whitespace(m_infile) == "")) { // Set pointing direction GCTAPointing pnt; GSkyDir skydir; skydir.radec_deg(m_ra, m_dec); pnt.dir(skydir); // Setup energy range covered by model GEnergy emin(m_emin, "TeV"); GEnergy emax(m_emax, "TeV"); GEbounds ebds(m_enumbins, emin, emax); // Setup time interval covered by model GGti gti; GTime tmin(m_tmin); GTime tmax(m_tmax); gti.append(tmin, tmax); // Setup skymap GSkymap map = GSkymap(m_proj, m_coordsys, m_xref, m_yref, -m_binsz, m_binsz, m_nxpix, m_nypix, m_enumbins); // Create model cube from sky map GCTAEventCube cube(map, ebds, gti); // Allocate CTA observation GCTAObservation obs; // Set CTA observation attributes obs.pointing(pnt); obs.ontime(gti.ontime()); obs.livetime(gti.ontime()*m_deadc); obs.deadc(m_deadc); // Set event cube in observation obs.events(cube); // Append CTA observation to container m_obs.append(obs); // Signal that no XML file should be used for storage m_use_xml = false; } // endif: created model map from task parameters // ... otherwise try to load information from the file else { // First try to open the file as a counts map try { // Allocate CTA observation GCTAObservation obs; // Load counts map in CTA observation obs.load_binned(m_infile); // Append CTA observation to container m_obs.append(obs); // Signal that no XML file should be used for storage m_use_xml = false; } // ... otherwise try to open as XML file catch (GException::fits_open_error &e) { // Load observations from XML file. This will throw // an exception if it fails. m_obs.load(m_infile); // Signal that XML file should be used for storage m_use_xml = true; } } // endelse: loaded information from input file } // endif: there was no observation in the container // If there are no models associated with the observations then // load now the model definition from the XML file if (m_obs.models().size() == 0) { m_obs.models(GModels(m_srcmdl)); } // Check if all CTA observations contain an event cube and setup response // for all observations for (int i = 0; i < m_obs.size(); ++i) { // Is this observation a CTA observation? GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]); // Yes ... if (obs != NULL) { // Throw an exception if this observation does not contain // an event cube if (dynamic_cast<const GCTAEventCube*>(obs->events()) == NULL) { throw GException::no_cube(G_SETUP_OBS); } // Set response if it isn't set already if (obs->response().aeff() == NULL) { // Set calibration database. If specified parameter is a // directory then use this as the pathname to the calibration // database. Otherwise interpret this as the instrument name, // the mission being "cta" GCaldb caldb; if (gammalib::dir_exists(m_caldb)) { caldb.rootdir(m_caldb); } else { caldb.open("cta", m_caldb); } // Set reponse obs->response(m_irf, caldb); } // endif: observation already has a response } // endif: observation was a CTA observation } // endfor: looped over all observations // 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 Get observation container * * Get an observation container according to the user parameters. The method * supports loading of a individual FITS file or an observation definition * file in XML format. * * If the input filename is empty, the method checks for the existence of the * "expcube", "psfcube" and "bkgcube" parameters. If file names have been * specified, the method loads the files and creates a dummy events cube that * is appended to the observation container. * * If no file names are specified for the "expcube", "psfcube" or "bkgcube" * parameters, the method reads the necessary parameters to build a CTA * observation from scratch. * * The method sets m_append_cube = true and m_binned = true in case that * a stacked observation is requested (as detected by the presence of the * "expcube", "psfcube", and "bkgcube" parameters). In that case, it appended * a dummy event cube to the observation. ***************************************************************************/ void ctmodel::get_obs(void) { // Get the filename from the input parameters std::string filename = (*this)["inobs"].filename(); // If no observation definition file has been specified then read all // parameters that are necessary to create an observation from scratch if ((filename == "NONE") || (gammalib::strip_whitespace(filename) == "")) { // Get response cube filenames std::string expcube = (*this)["expcube"].filename(); std::string psfcube = (*this)["psfcube"].filename(); std::string bkgcube = (*this)["bkgcube"].filename(); // If the filenames are valid then build an observation from cube // response information if ((expcube != "NONE") && (psfcube != "NONE") && (bkgcube != "NONE") && (gammalib::strip_whitespace(expcube) != "") && (gammalib::strip_whitespace(psfcube) != "") && (gammalib::strip_whitespace(bkgcube) != "")) { // Get exposure, PSF and background cubes GCTACubeExposure exposure(expcube); GCTACubePsf psf(psfcube); GCTACubeBackground background(bkgcube); // Create energy boundaries GEbounds ebounds = create_ebounds(); // Create dummy sky map cube GSkyMap map("CAR","GAL",0.0,0.0,1.0,1.0,1,1,ebounds.size()); // Create event cube GCTAEventCube cube(map, ebounds, exposure.gti()); // Create CTA observation GCTAObservation cta; cta.events(cube); cta.response(exposure, psf, background); // Append observation to container m_obs.append(cta); // Signal that we are in binned mode m_binned = true; // Signal that we appended a cube m_append_cube = true; } // endif: cube response information was available // ... otherwise build an observation from IRF response information else { // Create CTA observation GCTAObservation cta = create_cta_obs(); // Set response set_obs_response(&cta); // Append observation to container m_obs.append(cta); } } // endif: filename was "NONE" or "" // ... otherwise we have a file name else { // If file is a FITS file then create an empty CTA observation // and load file into observation if (gammalib::is_fits(filename)) { // Allocate empty CTA observation GCTAObservation cta; // Load data cta.load(filename); // Set response set_obs_response(&cta); // Append observation to container m_obs.append(cta); // Signal that no XML file should be used for storage m_use_xml = false; } // ... otherwise load file into observation container else { // Load observations from XML file m_obs.load(filename); // For all observations that have no response, set the response // from the task parameters set_response(m_obs); // Set observation boundary parameters (emin, emax, rad) set_obs_bounds(m_obs); // Signal that XML file should be used for storage m_use_xml = true; } // endelse: file was an XML file } // Return return; }
/***********************************************************************//** * @brief Get application parameters * * Get all task parameters from parameter file or (if required) by querying * the user. The parameters are read in the correct order. ***************************************************************************/ void ctmodel::get_parameters(void) { // Reset cube append flag m_append_cube = false; // If there are no observations in container then load them via user // parameters. if (m_obs.size() == 0) { get_obs(); } // If we have now excactly one CTA observation (but no cube has yet been // appended to the observation) then check whether this observation // is a binned observation, and if yes, extract the counts cube for // model generation if ((m_obs.size() == 1) && (m_append_cube == false)) { // Get CTA observation GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[0]); // Continue only if observation is a CTA observation if (obs != NULL) { // Check for binned observation if (obs->eventtype() == "CountsCube") { // Set cube from binned observation GCTAEventCube* evtcube = dynamic_cast<GCTAEventCube*>(const_cast<GEvents*>(obs->events())); cube(*evtcube); // Signal that cube has been set m_has_cube = true; // Signal that we are in binned mode m_binned = true; } // endif: observation was binned } // endif: observation was CTA } // endif: had exactly one observation // Read model definition file if required if (m_obs.models().size() == 0) { // Get model filename std::string inmodel = (*this)["inmodel"].filename(); // Load models from file m_obs.models(inmodel); } // endif: there were no models // Get energy dispersion flag parameters m_apply_edisp = (*this)["edisp"].boolean(); // If we do not have yet a counts cube for model computation then check // whether we should read it from the "incube" parameter or whether we // should create it from scratch using the task parameters if (!m_has_cube) { // Read cube definition file std::string incube = (*this)["incube"].filename(); // If no cube file has been specified then create a cube from // the task parameters ... if ((incube == "NONE") || (gammalib::strip_whitespace(incube) == "")) { // Create cube from scratch m_cube = create_cube(m_obs); } // ... otherwise load the cube from file and reset all bins // to zero else { // Load cube from given file m_cube.load(incube); // Set all cube bins to zero for (int i = 0; i < m_cube.size(); ++i) { m_cube[i]->counts(0.0); } } // Signal that cube has been set m_has_cube = true; } // endif: we had no cube yet // Read optionally output cube filenames if (read_ahead()) { m_outcube = (*this)["outcube"].filename(); } // If cube should be appended to first observation then do that now. // This is a kluge that makes sure that the cube is passed as part // of the observation in case that a cube response is used. The kluge // is needed because the GCTACubeSourceDiffuse::set method needs to // get the full event cube from the observation. It is also at this // step that the GTI, which may just be a dummy GTI when create_cube() // has been used, will be set. if (m_append_cube) { //TODO: Check that energy boundaries are compatible // Attach GTI of observations to model cube m_cube.gti(m_obs[0]->events()->gti()); // Attach model cube to observations m_obs[0]->events(m_cube); } // endif: cube was scheduled for appending // Return return; }