Commit b0de6b6f6f083d84b368f9144cd9af3f41778bcc

Authored by mimayer
1 parent 8caa108d

added support of edisp parameter to ctools and cscripts

cscripts/cshessobs.py
@@ -45,6 +45,7 @@ class cshessobs(ctools.cscript): @@ -45,6 +45,7 @@ class cshessobs(ctools.cscript):
45 self.name = "cshessobs" 45 self.name = "cshessobs"
46 self.version = "0.1.0" 46 self.version = "0.1.0"
47 self.datapath = "" 47 self.datapath = ""
  48 + self.m_erange = gammalib.GEbounds()
48 49
49 # Check on existence of HESSFITS environment variable 50 # Check on existence of HESSFITS environment variable
50 try: 51 try:
@@ -320,6 +321,12 @@ class cshessobs(ctools.cscript): @@ -320,6 +321,12 @@ class cshessobs(ctools.cscript):
320 # Return model 321 # Return model
321 return bck 322 return bck
322 323
  324 +
  325 + def erange(self):
  326 + """
  327 + Returns runlist energy range
  328 + """
  329 + return self.m_erange
323 330
324 def execute(self): 331 def execute(self):
325 """ 332 """
@@ -397,6 +404,10 @@ class cshessobs(ctools.cscript): @@ -397,6 +404,10 @@ class cshessobs(ctools.cscript):
397 self.log("\n") 404 self.log("\n")
398 self.log.header1("Looping over runs") 405 self.log.header1("Looping over runs")
399 406
  407 + # Initialise energy range values for logging
  408 + runlist_emin = 100.0
  409 + runlist_emax = 0.0
  410 +
400 for runnr in runlist: 411 for runnr in runlist:
401 412
402 # Unify run number string length 413 # Unify run number string length
@@ -411,7 +422,7 @@ class cshessobs(ctools.cscript): @@ -411,7 +422,7 @@ class cshessobs(ctools.cscript):
411 eventfile = runfolder + "hess_events_"+run+".fits.gz" 422 eventfile = runfolder + "hess_events_"+run+".fits.gz"
412 aefffile = runfolder + "hess_aeff_2d_"+run+".fits.gz" 423 aefffile = runfolder + "hess_aeff_2d_"+run+".fits.gz"
413 psffile = runfolder + "hess_psf_king_"+run+".fits.gz" 424 psffile = runfolder + "hess_psf_king_"+run+".fits.gz"
414 - edispfile = ""#runfolder + "hess_edisp_2d_"+run+".fits.gz" 425 + edispfile = runfolder + "hess_edisp_2d_"+run+".fits.gz"
415 bgfile = runfolder + "hess_bkg_offruns_"+run+".fits.gz" 426 bgfile = runfolder + "hess_bkg_offruns_"+run+".fits.gz"
416 427
417 # Check for existence of files 428 # Check for existence of files
@@ -429,6 +440,9 @@ class cshessobs(ctools.cscript): @@ -429,6 +440,9 @@ class cshessobs(ctools.cscript):
429 elif not os.path.isfile(psffile): 440 elif not os.path.isfile(psffile):
430 msg = "Run "+str(int(run))+" has no PSF - Run is skipped" 441 msg = "Run "+str(int(run))+" has no PSF - Run is skipped"
431 skip = True 442 skip = True
  443 + elif not os.path.isfile(edispfile):
  444 + msg = "Run "+str(int(run))+" has no energy dispersion - Run is skipped"
  445 + skip = True
432 elif not os.path.isfile(bgfile): 446 elif not os.path.isfile(bgfile):
433 msg = "Run "+str(int(run))+" has no background - Run is skipped" 447 msg = "Run "+str(int(run))+" has no background - Run is skipped"
434 skip = True 448 skip = True
@@ -458,6 +472,16 @@ class cshessobs(ctools.cscript): @@ -458,6 +472,16 @@ class cshessobs(ctools.cscript):
458 472
459 # Close FITS file 473 # Close FITS file
460 fits.close() 474 fits.close()
  475 +
  476 + # Open effective area file to look for threshold
  477 + aeff_fits = gammalib.GFits(aefffile)
  478 + run_emin = aeff_fits["EFFECTIVE AREA"].real("LO_THRES")
  479 + run_emax = aeff_fits["EFFECTIVE AREA"].real("HI_THRES")
  480 + if run_emin < runlist_emin:
  481 + runlist_emin = run_emin
  482 + if run_emax > runlist_emax:
  483 + runlist_emax = run_emax
  484 + aeff_fits.close()
461 485
462 # Append observation to XML and set attributes 486 # Append observation to XML and set attributes
463 obs = lib.append("observation"); 487 obs = lib.append("observation");
@@ -494,6 +518,15 @@ class cshessobs(ctools.cscript): @@ -494,6 +518,15 @@ class cshessobs(ctools.cscript):
494 518
495 # Append instrumental background model 519 # Append instrumental background model
496 self.models.append(self.hess_inst_background(run,aefffile,trgrate)) 520 self.models.append(self.hess_inst_background(run,aefffile,trgrate))
  521 +
  522 + # Store energy range as member
  523 + self.m_erange = gammalib.GEbounds(gammalib.GEnergy(runlist_emin,"TeV"),gammalib.GEnergy(runlist_emax,"TeV"))
  524 +
  525 + # Write energy range into log file
  526 + if self.logTerse():
  527 + self.log("\n")
  528 + self.log("Eenrgy range of obervation list: ")
  529 + self.log(("% 3.2f" % runlist_emin)+" - "+("% 3.2f" % runlist_emax)+" TeV")
497 530
498 # Append models provided by 'inmodels' of necessary 531 # Append models provided by 'inmodels' of necessary
499 if not self.inmodels == None: 532 if not self.inmodels == None:
cscripts/csresmap.py
@@ -110,6 +110,7 @@ class csresmap(ctools.cscript): @@ -110,6 +110,7 @@ class csresmap(ctools.cscript):
110 pars.append(gammalib.GApplicationPar("bkgcube","f","a","NONE","","","Background cube file (only needed for stacked analysis)")) 110 pars.append(gammalib.GApplicationPar("bkgcube","f","a","NONE","","","Background cube file (only needed for stacked analysis)"))
111 pars.append(gammalib.GApplicationPar("inmodel","f","a","$CTOOLS/share/models/crab.xml","","","Source model")) 111 pars.append(gammalib.GApplicationPar("inmodel","f","a","$CTOOLS/share/models/crab.xml","","","Source model"))
112 pars.append(gammalib.GApplicationPar("outmap","f","a","resmap.fits","","","Output residual map")) 112 pars.append(gammalib.GApplicationPar("outmap","f","a","resmap.fits","","","Output residual map"))
  113 + pars.append(gammalib.GApplicationPar("edisp","b","h","no","","","Apply energy dispersion?"))
113 pars.append(gammalib.GApplicationPar("caldb","s","a","prod2","","","Calibration database")) 114 pars.append(gammalib.GApplicationPar("caldb","s","a","prod2","","","Calibration database"))
114 pars.append(gammalib.GApplicationPar("irf","s","a","South_50h","","","Instrument response function")) 115 pars.append(gammalib.GApplicationPar("irf","s","a","South_50h","","","Instrument response function"))
115 pars.append(gammalib.GApplicationPar("ebinalg","s","h","LOG","LIN|LOG|FILE","","Binning algorithm")) 116 pars.append(gammalib.GApplicationPar("ebinalg","s","h","LOG","LIN|LOG|FILE","","Binning algorithm"))
@@ -141,7 +142,7 @@ class csresmap(ctools.cscript): @@ -141,7 +142,7 @@ class csresmap(ctools.cscript):
141 self.m_skip_binning = False 142 self.m_skip_binning = False
142 143
143 # First check if the inobs parameter is a counts cube 144 # First check if the inobs parameter is a counts cube
144 - if self["inobs"].filename() != "NONE": 145 + if self.obs.size() == 0 and self["inobs"].filename() != "NONE":
145 if gammalib.is_fits(self["inobs"].filename()): 146 if gammalib.is_fits(self["inobs"].filename()):
146 cta = gammalib.GCTAObservation() 147 cta = gammalib.GCTAObservation()
147 cta.load(self["inobs"].filename()) 148 cta.load(self["inobs"].filename())
@@ -189,6 +190,7 @@ class csresmap(ctools.cscript): @@ -189,6 +190,7 @@ class csresmap(ctools.cscript):
189 self.m_nxpix = self["nxpix"].integer() 190 self.m_nxpix = self["nxpix"].integer()
190 self.m_nypix = self["nypix"].integer() 191 self.m_nypix = self["nypix"].integer()
191 self.m_binsz = self["binsz"].real() 192 self.m_binsz = self["binsz"].real()
  193 + self.m_edisp = self["edisp"].boolean()
192 194
193 # Read necessary parameters 195 # Read necessary parameters
194 self.m_outfile = self["outmap"].filename() 196 self.m_outfile = self["outmap"].filename()
@@ -301,6 +303,7 @@ class csresmap(ctools.cscript): @@ -301,6 +303,7 @@ class csresmap(ctools.cscript):
301 model["chatter"].integer(self.m_chatter) 303 model["chatter"].integer(self.m_chatter)
302 model["clobber"].boolean(self.m_clobber) 304 model["clobber"].boolean(self.m_clobber)
303 model["debug"].boolean(self.m_debug) 305 model["debug"].boolean(self.m_debug)
  306 + model["edisp"].boolean(self.m_edisp)
304 model.run() 307 model.run()
305 308
306 # Get model map into GSkyMap object 309 # Get model map into GSkyMap object
cscripts/cssens.py
@@ -107,6 +107,7 @@ class cssens(ctools.cscript): @@ -107,6 +107,7 @@ class cssens(ctools.cscript):
107 pars.append(gammalib.GApplicationPar("outfile","f","h","sensitivity.dat","","","Output file name")) 107 pars.append(gammalib.GApplicationPar("outfile","f","h","sensitivity.dat","","","Output file name"))
108 pars.append(gammalib.GApplicationPar("duration","r","a","180000.0","","","Effective exposure time (s)")) 108 pars.append(gammalib.GApplicationPar("duration","r","a","180000.0","","","Effective exposure time (s)"))
109 pars.append(gammalib.GApplicationPar("rad","r","a","5.0","","","Radius of ROI (deg)")) 109 pars.append(gammalib.GApplicationPar("rad","r","a","5.0","","","Radius of ROI (deg)"))
  110 + pars.append(gammalib.GApplicationPar("edisp","b","h","no","","","Apply energy dispersion?"))
110 pars.append(gammalib.GApplicationPar("emin","r","a","0.020","","","Lower energy limit (TeV)")) 111 pars.append(gammalib.GApplicationPar("emin","r","a","0.020","","","Lower energy limit (TeV)"))
111 pars.append(gammalib.GApplicationPar("emax","r","a","200.0","","","Upper energy limit (TeV)")) 112 pars.append(gammalib.GApplicationPar("emax","r","a","200.0","","","Upper energy limit (TeV)"))
112 pars.append(gammalib.GApplicationPar("bins","i","a","21","","","Number of energy bins for differential sensitivity computation")) 113 pars.append(gammalib.GApplicationPar("bins","i","a","21","","","Number of energy bins for differential sensitivity computation"))
@@ -156,6 +157,7 @@ class cssens(ctools.cscript): @@ -156,6 +157,7 @@ class cssens(ctools.cscript):
156 self.m_binsz = 0.0 157 self.m_binsz = 0.0
157 158
158 # Read remaining parameters 159 # Read remaining parameters
  160 + self.m_edisp = self["edisp"].boolean()
159 self.m_ts_thres = self["sigma"].real()*self["sigma"].real() 161 self.m_ts_thres = self["sigma"].real()*self["sigma"].real()
160 self.m_max_iter = self["max_iter"].integer() 162 self.m_max_iter = self["max_iter"].integer()
161 self.m_num_avg = self["num_avg"].integer() 163 self.m_num_avg = self["num_avg"].integer()
@@ -466,7 +468,7 @@ class cssens(ctools.cscript): @@ -466,7 +468,7 @@ class cssens(ctools.cscript):
466 # Simulate events 468 # Simulate events
467 sim = obsutils.sim(obs, nbins=self.m_enumbins, seed=iter, 469 sim = obsutils.sim(obs, nbins=self.m_enumbins, seed=iter,
468 binsz=self.m_binsz, npix=self.m_npix, 470 binsz=self.m_binsz, npix=self.m_npix,
469 - log=self.m_log, debug=self.m_debug) 471 + log=self.m_log, debug=self.m_debug, edisp=self.m_edisp)
470 472
471 # Determine number of events in simulation 473 # Determine number of events in simulation
472 nevents = 0.0 474 nevents = 0.0
@@ -482,7 +484,7 @@ class cssens(ctools.cscript): @@ -482,7 +484,7 @@ class cssens(ctools.cscript):
482 484
483 # Fit background only 485 # Fit background only
484 sim.models(bkg_model) 486 sim.models(bkg_model)
485 - like = obsutils.fit(sim, log=self.m_log, debug=self.m_debug) 487 + like = obsutils.fit(sim, log=self.m_log, debug=self.m_debug, edisp=self.m_edisp)
486 result_bgm = like.obs().models().copy() 488 result_bgm = like.obs().models().copy()
487 LogL_bgm = like.opt().value() 489 LogL_bgm = like.opt().value()
488 npred_bgm = like.obs().npred() 490 npred_bgm = like.obs().npred()
@@ -520,7 +522,7 @@ class cssens(ctools.cscript): @@ -520,7 +522,7 @@ class cssens(ctools.cscript):
520 522
521 # Fit background and test source 523 # Fit background and test source
522 sim.models(src_model) 524 sim.models(src_model)
523 - like = obsutils.fit(sim, log=self.m_log, debug=self.m_debug) 525 + like = obsutils.fit(sim, log=self.m_log, debug=self.m_debug, edisp=self.m_edisp)
524 result_all = like.obs().models().copy() 526 result_all = like.obs().models().copy()
525 LogL_all = like.opt().value() 527 LogL_all = like.opt().value()
526 npred_all = like.obs().npred() 528 npred_all = like.obs().npred()
cscripts/csspec.py
@@ -107,6 +107,7 @@ class csspec(ctools.cscript): @@ -107,6 +107,7 @@ class csspec(ctools.cscript):
107 pars.append(gammalib.GApplicationPar("psfcube","f","a","NONE","","","PSF cube file (only needed for stacked analysis)")) 107 pars.append(gammalib.GApplicationPar("psfcube","f","a","NONE","","","PSF cube file (only needed for stacked analysis)"))
108 pars.append(gammalib.GApplicationPar("bkgcube","s","a","NONE","","","Background cube file (only needed for stacked analysis)")) 108 pars.append(gammalib.GApplicationPar("bkgcube","s","a","NONE","","","Background cube file (only needed for stacked analysis)"))
109 pars.append(gammalib.GApplicationPar("caldb","s","a","prod2","","","Calibration database")) 109 pars.append(gammalib.GApplicationPar("caldb","s","a","prod2","","","Calibration database"))
  110 + pars.append(gammalib.GApplicationPar("edisp","b","h","no","","","Apply energy dispersion?"))
110 pars.append(gammalib.GApplicationPar("irf","s","a","South_50h","","","Instrument response function")) 111 pars.append(gammalib.GApplicationPar("irf","s","a","South_50h","","","Instrument response function"))
111 pars.append(gammalib.GApplicationPar("emin","r","h","0.1","","","Lower energy limit for spectral points(TeV)")) 112 pars.append(gammalib.GApplicationPar("emin","r","h","0.1","","","Lower energy limit for spectral points(TeV)"))
112 pars.append(gammalib.GApplicationPar("emax","r","h","100.0","","","Upper energy limit for spectral points(TeV)")) 113 pars.append(gammalib.GApplicationPar("emax","r","h","100.0","","","Upper energy limit for spectral points(TeV)"))
@@ -153,6 +154,10 @@ class csspec(ctools.cscript): @@ -153,6 +154,10 @@ class csspec(ctools.cscript):
153 154
154 # Get binning flag 155 # Get binning flag
155 self.m_binned = self["binned"].boolean() 156 self.m_binned = self["binned"].boolean()
  157 +
  158 + # Get edisp flag
  159 + self.m_edisp = self["edisp"].boolean()
  160 +
156 if self.m_binned: 161 if self.m_binned:
157 self.m_xref = self["xref"].real() 162 self.m_xref = self["xref"].real()
158 self.m_yref = self["yref"].real() 163 self.m_yref = self["yref"].real()
@@ -368,6 +373,7 @@ class csspec(ctools.cscript): @@ -368,6 +373,7 @@ class csspec(ctools.cscript):
368 expcube["incube"] = "NONE" 373 expcube["incube"] = "NONE"
369 expcube["usepnt"] = False 374 expcube["usepnt"] = False
370 expcube["ebinalg"] = "LOG" 375 expcube["ebinalg"] = "LOG"
  376 + expcube["edisp"] = self.m_edisp
371 expcube["xref"] = self.m_xref 377 expcube["xref"] = self.m_xref
372 expcube["yref"] = self.m_yref 378 expcube["yref"] = self.m_yref
373 expcube["binsz"] = self.m_binsz 379 expcube["binsz"] = self.m_binsz
@@ -389,6 +395,7 @@ class csspec(ctools.cscript): @@ -389,6 +395,7 @@ class csspec(ctools.cscript):
389 psfcube["incube"] = "NONE" 395 psfcube["incube"] = "NONE"
390 psfcube["usepnt"] = False 396 psfcube["usepnt"] = False
391 psfcube["ebinalg"] = "LOG" 397 psfcube["ebinalg"] = "LOG"
  398 + psfcube["edisp"] = self.m_edisp
392 psfcube["xref"] = self.m_xref 399 psfcube["xref"] = self.m_xref
393 psfcube["yref"] = self.m_yref 400 psfcube["yref"] = self.m_yref
394 psfcube["binsz"] = self.m_binsz 401 psfcube["binsz"] = self.m_binsz
@@ -447,6 +454,7 @@ class csspec(ctools.cscript): @@ -447,6 +454,7 @@ class csspec(ctools.cscript):
447 454
448 # Likelihood 455 # Likelihood
449 like = ctools.ctlike(obs) 456 like = ctools.ctlike(obs)
  457 + like["edisp"].boolean(self.m_edisp)
450 like.run() 458 like.run()
451 459
452 # Skip bin if no event was present 460 # Skip bin if no event was present
src/ctbutterfly/ctbutterfly.cpp
@@ -216,6 +216,18 @@ void ctbutterfly::run(void) @@ -216,6 +216,18 @@ void ctbutterfly::run(void)
216 log << std::endl; 216 log << std::endl;
217 } 217 }
218 218
  219 + // Set energy dispersion flag for all CTA observations and save old
  220 + // values in save_edisp vector
  221 + std::vector<bool> save_edisp;
  222 + save_edisp.assign(m_obs.size(), false);
  223 + for (int i = 0; i < m_obs.size(); ++i) {
  224 + GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]);
  225 + if (obs != NULL) {
  226 + save_edisp[i] = obs->response()->apply_edisp();
  227 + obs->response()->apply_edisp(m_apply_edisp);
  228 + }
  229 + }
  230 +
219 // Write observation(s) into logger 231 // Write observation(s) into logger
220 if (logTerse()) { 232 if (logTerse()) {
221 log << std::endl; 233 log << std::endl;
@@ -347,6 +359,14 @@ void ctbutterfly::run(void) @@ -347,6 +359,14 @@ void ctbutterfly::run(void)
347 359
348 } //endfor: loop over energy bin 360 } //endfor: loop over energy bin
349 361
  362 + // Restore energy dispersion flag for all CTA observations
  363 + for (int i = 0; i < m_obs.size(); ++i) {
  364 + GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]);
  365 + if (obs != NULL) {
  366 + obs->response()->apply_edisp(save_edisp[i]);
  367 + }
  368 + }
  369 +
350 // Return 370 // Return
351 return; 371 return;
352 } 372 }
@@ -402,6 +422,7 @@ void ctbutterfly::init_members(void) @@ -402,6 +422,7 @@ void ctbutterfly::init_members(void)
402 m_srcname.clear(); 422 m_srcname.clear();
403 m_outfile.clear(); 423 m_outfile.clear();
404 m_ebounds.clear(); 424 m_ebounds.clear();
  425 + m_apply_edisp = false;
405 426
406 // Initialise protected members 427 // Initialise protected members
407 m_obs.clear(); 428 m_obs.clear();
@@ -426,6 +447,7 @@ void ctbutterfly::copy_members(const ctbutterfly&amp; app) @@ -426,6 +447,7 @@ void ctbutterfly::copy_members(const ctbutterfly&amp; app)
426 m_srcname = app.m_srcname; 447 m_srcname = app.m_srcname;
427 m_outfile = app.m_outfile; 448 m_outfile = app.m_outfile;
428 m_ebounds = app.m_ebounds; 449 m_ebounds = app.m_ebounds;
  450 + m_apply_edisp = app.m_apply_edisp;
429 451
430 // Copy protected members 452 // Copy protected members
431 m_obs = app.m_obs; 453 m_obs = app.m_obs;
@@ -511,6 +533,9 @@ void ctbutterfly::get_parameters(void) @@ -511,6 +533,9 @@ void ctbutterfly::get_parameters(void)
511 // m_covariance.load(matrixfilename); 533 // m_covariance.load(matrixfilename);
512 } 534 }
513 535
  536 + // Read energy dispersion flag
  537 + m_apply_edisp = (*this)["edisp"].boolean();
  538 +
514 // Optionally read ahead parameters so that they get correctly 539 // Optionally read ahead parameters so that they get correctly
515 // dumped into the log file 540 // dumped into the log file
516 if (read_ahead()) { 541 if (read_ahead()) {
src/ctbutterfly/ctbutterfly.hpp
@@ -83,6 +83,7 @@ protected: @@ -83,6 +83,7 @@ protected:
83 std::string m_srcname; //!< Name of source to compute butterfly 83 std::string m_srcname; //!< Name of source to compute butterfly
84 std::string m_outfile; //!< Output ascii file 84 std::string m_outfile; //!< Output ascii file
85 GEbounds m_ebounds; //!< Energy binning definition 85 GEbounds m_ebounds; //!< Energy binning definition
  86 + bool m_apply_edisp; //!< Apply energy dispersion?
86 87
87 // Protected members 88 // Protected members
88 GObservations m_obs; //!< Observation container 89 GObservations m_obs; //!< Observation container
src/ctbutterfly/ctbutterfly.par
@@ -27,6 +27,7 @@ caldb, s, a, &quot;prod2&quot;,,, &quot;Calibration database&quot; @@ -27,6 +27,7 @@ caldb, s, a, &quot;prod2&quot;,,, &quot;Calibration database&quot;
27 irf, s, a, "South_50h",,, "Instrument response function" 27 irf, s, a, "South_50h",,, "Instrument response function"
28 outfile, f, a, "butterfly.txt",,, "Output ascii file" 28 outfile, f, a, "butterfly.txt",,, "Output ascii file"
29 matrix, f, h, "NONE",,, "Input covariance Matrix FITS file" 29 matrix, f, h, "NONE",,, "Input covariance Matrix FITS file"
  30 +edisp, b, h, no,,, "Apply energy dispersion?"
30 31
31 # 32 #
32 # Energy binning parameters 33 # Energy binning parameters
src/cterror/cterror.cpp
@@ -214,6 +214,18 @@ void cterror::run(void) @@ -214,6 +214,18 @@ void cterror::run(void)
214 log << std::endl; 214 log << std::endl;
215 } 215 }
216 216
  217 + // Set energy dispersion flag for all CTA observations and save old
  218 + // values in save_edisp vector
  219 + std::vector<bool> save_edisp;
  220 + save_edisp.assign(m_obs.size(), false);
  221 + for (int i = 0; i < m_obs.size(); ++i) {
  222 + GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]);
  223 + if (obs != NULL) {
  224 + save_edisp[i] = obs->response()->apply_edisp();
  225 + obs->response()->apply_edisp(m_apply_edisp);
  226 + }
  227 + }
  228 +
217 // Write observation(s) into logger 229 // Write observation(s) into logger
218 if (logTerse()) { 230 if (logTerse()) {
219 log << std::endl; 231 log << std::endl;
@@ -355,6 +367,14 @@ void cterror::run(void) @@ -355,6 +367,14 @@ void cterror::run(void)
355 // Recover optimizer 367 // Recover optimizer
356 m_opt = best_opt; 368 m_opt = best_opt;
357 369
  370 + // Restore energy dispersion flag for all CTA observations
  371 + for (int i = 0; i < m_obs.size(); ++i) {
  372 + GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]);
  373 + if (obs != NULL) {
  374 + obs->response()->apply_edisp(save_edisp[i]);
  375 + }
  376 + }
  377 +
358 // Return 378 // Return
359 return; 379 return;
360 } 380 }
@@ -410,6 +430,7 @@ void cterror::init_members(void) @@ -410,6 +430,7 @@ void cterror::init_members(void)
410 m_dlogL = 0.0; 430 m_dlogL = 0.0;
411 m_best_logL = 0.0; 431 m_best_logL = 0.0;
412 m_model_par = NULL; 432 m_model_par = NULL;
  433 + m_apply_edisp = false;
413 434
414 // Set optimizer parameters 435 // Set optimizer parameters
415 m_opt.max_iter(m_max_iter); 436 m_opt.max_iter(m_max_iter);
@@ -432,6 +453,7 @@ void cterror::copy_members(const cterror&amp; app) @@ -432,6 +453,7 @@ void cterror::copy_members(const cterror&amp; app)
432 m_confidence = app.m_confidence; 453 m_confidence = app.m_confidence;
433 m_tol = app.m_tol; 454 m_tol = app.m_tol;
434 m_max_iter = app.m_max_iter; 455 m_max_iter = app.m_max_iter;
  456 + m_apply_edisp = app.m_apply_edisp;
435 457
436 // Copy protected members 458 // Copy protected members
437 m_obs = app.m_obs; 459 m_obs = app.m_obs;
@@ -500,6 +522,9 @@ void cterror::get_parameters(void) @@ -500,6 +522,9 @@ void cterror::get_parameters(void)
500 throw GException::invalid_value(G_GET_PARAMETERS, msg); 522 throw GException::invalid_value(G_GET_PARAMETERS, msg);
501 } 523 }
502 524
  525 + // Read energy dispersion flag
  526 + m_apply_edisp = (*this)["edisp"].boolean();
  527 +
503 // Get confidence level and transform into log-likelihood difference 528 // Get confidence level and transform into log-likelihood difference
504 m_confidence = (*this)["confidence"].real(); 529 m_confidence = (*this)["confidence"].real();
505 double sigma = gammalib::erfinv(m_confidence) * gammalib::sqrt_two; 530 double sigma = gammalib::erfinv(m_confidence) * gammalib::sqrt_two;
src/cterror/cterror.hpp
@@ -78,6 +78,7 @@ protected: @@ -78,6 +78,7 @@ protected:
78 double m_tol; //!< Tolerance for limit determination 78 double m_tol; //!< Tolerance for limit determination
79 int m_max_iter; //!< Maximum number of iterations 79 int m_max_iter; //!< Maximum number of iterations
80 double m_value; //!< Parameter value 80 double m_value; //!< Parameter value
  81 + bool m_apply_edisp; //!< Apply energy dispersion?
81 82
82 // Protected members 83 // Protected members
83 GObservations m_obs; //!< Observation container 84 GObservations m_obs; //!< Observation container
src/cterror/cterror.par
  1 +
1 ############################################################################# 2 #############################################################################
2 # # 3 # #
3 # CTA Science Analysis Tools # 4 # CTA Science Analysis Tools #
@@ -26,6 +27,7 @@ psfcube, f, a, &quot;NONE&quot;,,, &quot;PSF cube file (only needed for stacked analysis)&quot; @@ -26,6 +27,7 @@ psfcube, f, a, &quot;NONE&quot;,,, &quot;PSF cube file (only needed for stacked analysis)&quot;
26 bkgcube, f, a, "NONE",,, "Background cube file (only needed for stacked analysis)" 27 bkgcube, f, a, "NONE",,, "Background cube file (only needed for stacked analysis)"
27 caldb, s, a, "prod2",,, "Calibration database" 28 caldb, s, a, "prod2",,, "Calibration database"
28 irf, s, a, "South_50h",,, "Instrument response function" 29 irf, s, a, "South_50h",,, "Instrument response function"
  30 +edisp, b, h, no,,, "Apply energy dispersion?"
29 31
30 # 32 #
31 # Error calculation parameters 33 # Error calculation parameters
src/cttsmap/cttsmap.cpp
@@ -215,6 +215,18 @@ void cttsmap::run(void) @@ -215,6 +215,18 @@ void cttsmap::run(void)
215 log << std::endl; 215 log << std::endl;
216 } 216 }
217 217
  218 + // Set energy dispersion flag for all CTA observations and save old
  219 + // values in save_edisp vector
  220 + std::vector<bool> save_edisp;
  221 + save_edisp.assign(m_obs.size(), false);
  222 + for (int i = 0; i < m_obs.size(); ++i) {
  223 + GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]);
  224 + if (obs != NULL) {
  225 + save_edisp[i] = obs->response()->apply_edisp();
  226 + obs->response()->apply_edisp(m_apply_edisp);
  227 + }
  228 + }
  229 +
218 // Write observation(s) into logger 230 // Write observation(s) into logger
219 if (logTerse()) { 231 if (logTerse()) {
220 log << std::endl; 232 log << std::endl;
@@ -348,6 +360,14 @@ void cttsmap::run(void) @@ -348,6 +360,14 @@ void cttsmap::run(void)
348 // Bring models to initial state 360 // Bring models to initial state
349 m_obs.models(models_orig); 361 m_obs.models(models_orig);
350 362
  363 + // Restore energy dispersion flag for all CTA observations
  364 + for (int i = 0; i < m_obs.size(); ++i) {
  365 + GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]);
  366 + if (obs != NULL) {
  367 + obs->response()->apply_edisp(save_edisp[i]);
  368 + }
  369 + }
  370 +
351 // Return 371 // Return
352 return; 372 return;
353 } 373 }
@@ -411,6 +431,7 @@ void cttsmap::init_members(void) @@ -411,6 +431,7 @@ void cttsmap::init_members(void)
411 // Initialise members 431 // Initialise members
412 m_srcname.clear(); 432 m_srcname.clear();
413 m_outmap.clear(); 433 m_outmap.clear();
  434 + m_apply_edisp = false;
414 435
415 // Initialise protected members 436 // Initialise protected members
416 m_obs.clear(); 437 m_obs.clear();
@@ -438,6 +459,7 @@ void cttsmap::copy_members(const cttsmap&amp; app) @@ -438,6 +459,7 @@ void cttsmap::copy_members(const cttsmap&amp; app)
438 // Copy attributes 459 // Copy attributes
439 m_srcname = app.m_srcname; 460 m_srcname = app.m_srcname;
440 m_outmap = app.m_outmap; 461 m_outmap = app.m_outmap;
  462 + m_apply_edisp = app.m_apply_edisp;
441 463
442 // Copy protected members 464 // Copy protected members
443 m_binmin = app.m_binmin; 465 m_binmin = app.m_binmin;
@@ -542,6 +564,9 @@ void cttsmap::get_parameters(void) @@ -542,6 +564,9 @@ void cttsmap::get_parameters(void)
542 // Initialise maps from user parameters 564 // Initialise maps from user parameters
543 init_maps(map); 565 init_maps(map);
544 566
  567 + // Read energy dispersion flag
  568 + m_apply_edisp = (*this)["edisp"].boolean();
  569 +
545 // Get optional splitting parameters 570 // Get optional splitting parameters
546 m_binmin = (*this)["binmin"].integer(); 571 m_binmin = (*this)["binmin"].integer();
547 m_binmax = (*this)["binmax"].integer(); 572 m_binmax = (*this)["binmax"].integer();
src/cttsmap/cttsmap.hpp
@@ -86,6 +86,7 @@ protected: @@ -86,6 +86,7 @@ protected:
86 // User parameters 86 // User parameters
87 std::string m_srcname; //!< Name of source which is moved around 87 std::string m_srcname; //!< Name of source which is moved around
88 std::string m_outmap; //!< Output counts map or XML file 88 std::string m_outmap; //!< Output counts map or XML file
  89 + bool m_apply_edisp; //!< Apply energy dispersion?
89 90
90 // Parameters to control speed and job splitting 91 // Parameters to control speed and job splitting
91 int m_binmin; //!< Map bin number from which computation should start 92 int m_binmin; //!< Map bin number from which computation should start
src/cttsmap/cttsmap.par
@@ -26,6 +26,7 @@ bkgcube, f, a, &quot;NONE&quot;,,, &quot;Background cube file (only needed for stacked analysis @@ -26,6 +26,7 @@ bkgcube, f, a, &quot;NONE&quot;,,, &quot;Background cube file (only needed for stacked analysis
26 caldb, s, a, "prod2",,, "Calibration database" 26 caldb, s, a, "prod2",,, "Calibration database"
27 irf, s, a, "South_50h",,, "Instrument response function" 27 irf, s, a, "South_50h",,, "Instrument response function"
28 outmap, f, a, "tsmap.fits",,, "Output Test Statistic map" 28 outmap, f, a, "tsmap.fits",,, "Output Test Statistic map"
  29 +edisp, b, h, no,,, "Apply energy dispersion?"
29 30
30 # 31 #
31 # Spatial binning parameters 32 # Spatial binning parameters
src/ctulimit/ctulimit.cpp
@@ -217,6 +217,18 @@ void ctulimit::run(void) @@ -217,6 +217,18 @@ void ctulimit::run(void)
217 log << std::endl; 217 log << std::endl;
218 } 218 }
219 219
  220 + // Set energy dispersion flag for all CTA observations and save old
  221 + // values in save_edisp vector
  222 + std::vector<bool> save_edisp;
  223 + save_edisp.assign(m_obs.size(), false);
  224 + for (int i = 0; i < m_obs.size(); ++i) {
  225 + GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]);
  226 + if (obs != NULL) {
  227 + save_edisp[i] = obs->response()->apply_edisp();
  228 + obs->response()->apply_edisp(m_apply_edisp);
  229 + }
  230 + }
  231 +
220 // Write observation(s) into logger 232 // Write observation(s) into logger
221 if (logTerse()) { 233 if (logTerse()) {
222 log << std::endl; 234 log << std::endl;
@@ -343,6 +355,14 @@ void ctulimit::run(void) @@ -343,6 +355,14 @@ void ctulimit::run(void)
343 // Recover optimizer 355 // Recover optimizer
344 m_opt = best_opt; 356 m_opt = best_opt;
345 357
  358 + // Restore energy dispersion flag for all CTA observations
  359 + for (int i = 0; i < m_obs.size(); ++i) {
  360 + GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]);
  361 + if (obs != NULL) {
  362 + obs->response()->apply_edisp(save_edisp[i]);
  363 + }
  364 + }
  365 +
346 // Return 366 // Return
347 return; 367 return;
348 } 368 }
@@ -405,6 +425,7 @@ void ctulimit::init_members(void) @@ -405,6 +425,7 @@ void ctulimit::init_members(void)
405 m_emax = 0.0; 425 m_emax = 0.0;
406 m_tol = 1.0e-6; 426 m_tol = 1.0e-6;
407 m_max_iter = 50; 427 m_max_iter = 50;
  428 + m_apply_edisp = false;
408 429
409 // Initialise protected members 430 // Initialise protected members
410 m_obs.clear(); 431 m_obs.clear();
@@ -443,7 +464,7 @@ void ctulimit::copy_members(const ctulimit&amp; app) @@ -443,7 +464,7 @@ void ctulimit::copy_members(const ctulimit&amp; app)
443 m_emax = app.m_emax; 464 m_emax = app.m_emax;
444 m_tol = app.m_tol; 465 m_tol = app.m_tol;
445 m_max_iter = app.m_max_iter; 466 m_max_iter = app.m_max_iter;
446 - 467 + m_apply_edisp = app.m_apply_edisp;
447 468
448 // Copy protected members 469 // Copy protected members
449 m_obs = app.m_obs; 470 m_obs = app.m_obs;
@@ -520,6 +541,9 @@ void ctulimit::get_parameters(void) @@ -520,6 +541,9 @@ void ctulimit::get_parameters(void)
520 // Get relevant model and parameter for upper limit computation 541 // Get relevant model and parameter for upper limit computation
521 get_model_parameter(); 542 get_model_parameter();
522 543
  544 + // Read energy dispersion flag
  545 + m_apply_edisp = (*this)["edisp"].boolean();
  546 +
523 // Get confidence level and transform into log-likelihood difference 547 // Get confidence level and transform into log-likelihood difference
524 m_confidence = (*this)["confidence"].real(); 548 m_confidence = (*this)["confidence"].real();
525 double sigma = gammalib::erfinv(m_confidence) * gammalib::sqrt_two; 549 double sigma = gammalib::erfinv(m_confidence) * gammalib::sqrt_two;
src/ctulimit/ctulimit.hpp
@@ -93,6 +93,7 @@ protected: @@ -93,6 +93,7 @@ protected:
93 double m_emax; //!< Maximum energy for flux limits (TeV) 93 double m_emax; //!< Maximum energy for flux limits (TeV)
94 double m_tol; //!< Tolerance for limit determination 94 double m_tol; //!< Tolerance for limit determination
95 int m_max_iter; //!< Maximum number of iterations 95 int m_max_iter; //!< Maximum number of iterations
  96 + bool m_apply_edisp; //!< Apply energy dispersion?
96 97
97 // Protected members 98 // Protected members
98 GObservations m_obs; //!< Observation container 99 GObservations m_obs; //!< Observation container
src/ctulimit/ctulimit.par
@@ -25,6 +25,7 @@ psfcube, f, a, &quot;NONE&quot;,,, &quot;PSF cube file (only needed for stacked analysis)&quot; @@ -25,6 +25,7 @@ psfcube, f, a, &quot;NONE&quot;,,, &quot;PSF cube file (only needed for stacked analysis)&quot;
25 bkgcube, f, a, "NONE",,, "Background cube file (only needed for stacked analysis)" 25 bkgcube, f, a, "NONE",,, "Background cube file (only needed for stacked analysis)"
26 caldb, s, a, "prod2",,, "Calibration database" 26 caldb, s, a, "prod2",,, "Calibration database"
27 irf, s, a, "South_50h",,, "Instrument response function" 27 irf, s, a, "South_50h",,, "Instrument response function"
  28 +edisp, b, h, no,,, "Apply energy dispersion?"
28 29
29 # 30 #
30 # Upper limit calculation parameters 31 # Upper limit calculation parameters