def _test_python(self): """ Test ctcubemask from Python """ # Set-up ctcubemask mask = ctools.ctcubemask() mask['inobs'] = self._cntcube mask['regfile'] = self._exclusion mask['outcube'] = 'ctcubemask_py1.fits' mask['ra'] = 83.63 mask['dec'] = 22.01 mask['rad'] = 2.0 mask['emin'] = 0.1 mask['emax'] = 100.0 mask['logfile'] = 'ctcubemask_py1.log' mask['chatter'] = 2 # Run ctcubemask tool mask.logFileOpen() # Make sure we get a log file mask.run() mask.save() # Check result file self._check_result_file('ctcubemask_py1.fits') # Return return
def test_functional(self): """ Test ctcubemask functionnality. """ # Set-up ctcubemask mask = ctools.ctcubemask() mask["inobs"].filename(self.cntmap_name) mask["regfile"].filename(self.regfile) mask["outcube"].filename("filtered_cntmap.fits") mask["ra"].real(83.63) mask["dec"].real(22.01) mask["rad"].real(2.0) mask["emin"].real(0.1) mask["emax"].real(100.0) # Run tool self.test_try("Run ctcubemask") try: mask.run() self.test_try_success() except: self.test_try_failure("Exception occured in ctcubemask.") # Save counts cube self.test_try("Save counts cube") try: mask.save() self.test_try_success() except: self.test_try_failure("Exception occured in saving counts cube.") # Return return
def _masked_cube(self, cube, ra, dec, rad, emin='INDEF', emax='INDEF', regfile='NONE'): """ Mask an event cube and returns the masked cube Parameters ---------- cube : `~gammalib.GCTAEventCube` Event cube ra : float (str 'INDEF' for no selection on direction) Right Ascension (deg) dec : float (str 'INDEF' for no selection on direction) Declination (deg) rad : float (str 'INDEF' for no selection on direction) Radius (deg) emin : float (str 'INDEF' for no selection on energy) Minimum energy (TeV) emax : float (str 'INDEF' for no selection on energy) Maximum energy (TeV) Returns ------- cube : `~gammalib.GCTAEventCube` Event cube """ # Turn cube into observation container to feed to ctcubemask obs = gammalib.GCTAObservation() obs.events(cube) obs_cont = gammalib.GObservations() obs_cont.append(obs) # Use ctcubemask to mask event cube pixels cubemask = ctools.ctcubemask(obs_cont) cubemask['ra'] = ra cubemask['dec'] = dec cubemask['rad'] = rad cubemask['emin'] = emin cubemask['emax'] = emax cubemask['regfile'] = regfile cubemask.run() # Extract copy of cube from observation container (copy is needed to # avoid memory leaks in SWIG) cube = cubemask.obs()[0].events().copy() # Return cube return cube
def mask_cube(): """ Compute a mask cube. http://cta.irap.omp.eu/ctools/users/reference_manual/ctcubemask.html Parameters ---------- Outputs -------- """ maskcube = ctools.ctcubemask() maskcube.execute() return maskcube
def _select_obs(self, emin, emax): """ Select observations for energy interval Parameters ---------- emin : `~gammalib.GEnergy()` Minimum energy emax : `~gammalib.GEnergy()` Maximum energy Returns ------- obs : `~gammalib.GObservations` Observation container """ # Use ctcubemask for binned analysis if self._binned_mode: # Write header self._log_header3(gammalib.EXPLICIT, 'Filtering cube') # Select layers cubemask = ctools.ctcubemask(self.obs()) cubemask['regfile'] = 'NONE' cubemask['ra'] = 'UNDEFINED' cubemask['dec'] = 'UNDEFINED' cubemask['rad'] = 'UNDEFINED' cubemask['emin'] = emin.TeV() cubemask['emax'] = emax.TeV() # If chatter level is verbose and debugging is requested then # switch also on the debug model in ctcubemask if self._logVerbose() and self._logDebug(): cubemask['debug'] = True # Select layers cubemask.run() # Set new binned observation obs = cubemask.obs().copy() # Use ... elif self._onoff_mode: # Write header self._log_header3(gammalib.EXPLICIT, 'Filtering PHA, ARF and RMF') # Initialise observation container obs = gammalib.GObservations() # Loop over all input observations and select energy bins for # all On/Off observations for run in self.obs(): if run.classname() == 'GCTAOnOffObservation': obs.append(self._select_onoff_obs(run, emin, emax)) # Append models obs.models(self.obs().models()) # Use ctselect for unbinned analysis else: # Write header self._log_header3(gammalib.EXPLICIT, 'Selecting events') # Select events select = ctools.ctselect(self.obs()) select['ra'] = 'UNDEFINED' select['dec'] = 'UNDEFINED' select['rad'] = 'UNDEFINED' select['emin'] = emin.TeV() select['emax'] = emax.TeV() select['tmin'] = 'UNDEFINED' select['tmax'] = 'UNDEFINED' # If chatter level is verbose and debugging is requested then # switch also on the debug model in ctselect if self._logVerbose() and self._logDebug(): select['debug'] = True # Run ctselect select.run() # Retrieve observation obs = select.obs().copy() # Return observation container return obs
def _test_python(self): """ Test ctcubemask from Python """ # Allocate ctcubemask mask = ctools.ctcubemask() # Check that empty ctcubemask tool holds an empty observation self._check_obs(mask.obs(), nobs=0) # Check that saving saves an empty counts cube mask['outcube'] = 'ctcubemask_py0.fits' mask['logfile'] = 'ctcubemask_py0.log' mask.logFileOpen() mask.save() self.test_assert(not os.path.isfile('ctcubemask_py0.fits'), 'Check that no counts cube has been created') # Check that clearing does not lead to an exception or segfault mask.clear() # Now set ctcubemask parameters mask['inobs'] = self._cntcube mask['regfile'] = self._exclusion mask['ra'] = 83.63 mask['dec'] = 22.01 mask['rad'] = 1.0 mask['emin'] = 1.0 mask['emax'] = 100.0 mask['outcube'] = 'ctcubemask_py1.fits' mask['logfile'] = 'ctcubemask_py1.log' mask['chatter'] = 2 # Run ctcubemask tool mask.logFileOpen() # Make sure we get a log file mask.run() mask.save() # Check result file self._check_result_file('ctcubemask_py1.fits') # Set-up ctcubemask without exclusion regions but tighter energy # selection mask = ctools.ctcubemask() mask['inobs'] = self._cntcube mask['regfile'] = 'NONE' mask['ra'] = 83.63 mask['dec'] = 22.01 mask['rad'] = 3.0 mask['emin'] = 2.0 mask['emax'] = 10.0 mask['outcube'] = 'ctcubemask_py2.fits' mask['logfile'] = 'ctcubemask_py2.log' mask['chatter'] = 3 mask['publish'] = True # Execute ctcubemask tool mask.logFileOpen() # Make sure we get a log file mask.execute() # Check result file self._check_result_file('ctcubemask_py2.fits', events=65) # Copy ctcubemask tool cpy_mask = mask.copy() # Check that ctcubemask tool holds one observation self._check_obs(cpy_mask.obs()) # Execute copy of ctcubemask tool again, now with a higher chatter # level than before cpy_mask['outcube'] = 'ctcubemask_py3.fits' cpy_mask['logfile'] = 'ctcubemask_py3.log' cpy_mask['chatter'] = 4 cpy_mask.execute() # Check result file self._check_result_file('ctcubemask_py3.fits', events=65) # Clear ctcubemask tool cpy_mask.clear() # Check that empty ctcubemask tool holds an empty observation self._check_obs(cpy_mask.obs(), nobs=0) # Prepare observation container obs = self._obs_mixed() obs.models(gammalib.GModels(self._model)) # Set-up ctcubemask from observation container, don't perform any # energy selection mask = ctools.ctcubemask(obs) mask['regfile'] = 'NONE' mask['ra'] = 83.63 mask['dec'] = 22.01 mask['rad'] = 1.0 mask['emin'] = 'NONE' mask['emax'] = 'NONE' mask['outcube'] = 'ctcubemask_py4.xml' mask['logfile'] = 'ctcubemask_py4.log' mask['chatter'] = 3 # Execute ctcubemask tool mask.logFileOpen() # Make sure we get a log file mask.execute() # Check result file self._check_result_file('filtered_crab_cntmap.fits', events=132) # Return return
def _select_obs(self, emin, emax): """ Select observations for energy interval Parameters ---------- emin : `~gammalib.GEnergy()` Minimum energy emax : `~gammalib.GEnergy()` Maximum energy Returns ------- obs : `~gammalib.GObservations` Observation container """ # Use ctcubemask for binned analysis if self._binned_mode: # Write header self._log_header3(gammalib.EXPLICIT, 'Filtering cube') # Select layers cubemask = ctools.ctcubemask(self.obs()) cubemask['regfile'] = 'NONE' cubemask['ra'] = 'UNDEFINED' cubemask['dec'] = 'UNDEFINED' cubemask['rad'] = 'UNDEFINED' cubemask['emin'] = emin.TeV() cubemask['emax'] = emax.TeV() cubemask.run() # Set new binned observation obs = cubemask.obs().copy() # Use ... elif self._onoff_mode: # Write header self._log_header3(gammalib.EXPLICIT, 'Filtering PHA, ARF and RMF') # Initialise observation container obs = gammalib.GObservations() # Loop over all input observations and select energy bins for # all On/Off observations for run in self.obs(): if run.classname() == 'GCTAOnOffObservation': obs.append(self._select_onoff_obs(run, emin, emax)) # Append models obs.models(self.obs().models()) # Use ctselect for unbinned analysis else: # Write header self._log_header3(gammalib.EXPLICIT, 'Selecting events') # Select events select = ctools.ctselect(self.obs()) select['ra'] = 'UNDEFINED' select['dec'] = 'UNDEFINED' select['rad'] = 'UNDEFINED' select['emin'] = emin.TeV() select['emax'] = emax.TeV() select['tmin'] = 'UNDEFINED' select['tmax'] = 'UNDEFINED' select.run() # Retrieve observation obs = select.obs().copy() # Return observation container return obs
def run(self): """ Run the script. """ # Switch screen logging on in debug mode if self.logDebug(): self.log.cout(True) # Get parameters self.get_parameters() # Write input parameters into logger if self.logTerse(): self.log_parameters() self.log("\n") # Write spectral binning into header if self.logTerse(): self.log("\n") self.log.header1("Spectral binning") if self.m_binned_mode: cube_ebounds = self.obs[0].events().ebounds() self.log.parformat("Counts cube energy range") self.log(str(cube_ebounds.emin())) self.log(" - ") self.log(str(cube_ebounds.emax())) self.log("\n") for i in range(self.m_ebounds.size()): self.log.parformat("Bin "+str(i+1)) self.log(str(self.m_ebounds.emin(i))) self.log(" - ") self.log(str(self.m_ebounds.emax(i))) self.log("\n") # Write observation into logger if self.logTerse(): self.log("\n") self.log.header1("Observation") self.log(str(self.obs)) self.log("\n") # Write header if self.logTerse(): self.log("\n") self.log.header1("Adjust model parameters") # Adjust model parameters dependent on input user parameters for model in self.obs.models(): # Set TS flag for all models to false. # Source of interest will be set to true later model.tscalc(False) # Log model name if self.logExplicit(): self.log.header3(model.name()) # Deal with the source of interest if model.name() == self.m_srcname: for par in model: if par.is_free() and self.logExplicit(): self.log(" Fixing \""+par.name()+"\"\n") par.fix() normpar = model.spectral()[0] if normpar.is_fixed() and self.logExplicit(): self.log(" Freeing \""+normpar.name()+"\"\n") normpar.free() if self.m_calc_ts: model.tscalc(True) elif self.m_fix_bkg and not model.classname() == "GModelSky": for par in model: if par.is_free() and self.logExplicit(): self.log(" Fixing \""+par.name()+"\"\n") par.fix() elif self.m_fix_srcs and model.classname() == "GModelSky": for par in model: if par.is_free() and self.logExplicit(): self.log(" Fixing \""+par.name()+"\"\n") par.fix() # Write header if self.logTerse(): self.log("\n") self.log.header1("Generate spectrum") self.log(str(self.m_ebounds)) # Initialise FITS Table with extension "SPECTRUM" table = gammalib.GFitsBinTable(self.m_ebounds.size()) table.extname("SPECTRUM") # Add Header for compatibility with gammalib.GMWLSpectrum table.card("INSTRUME", "CTA", "Name of Instrument") table.card("TELESCOP", "CTA", "Name of Telescope") # Create FITS table columns energy = gammalib.GFitsTableDoubleCol("Energy", self.m_ebounds.size()) energy_low = gammalib.GFitsTableDoubleCol("ed_Energy", self.m_ebounds.size()) energy_high = gammalib.GFitsTableDoubleCol("eu_Energy", self.m_ebounds.size()) flux = gammalib.GFitsTableDoubleCol("Flux", self.m_ebounds.size()) flux_err = gammalib.GFitsTableDoubleCol("e_Flux", self.m_ebounds.size()) TSvalues = gammalib.GFitsTableDoubleCol("TS", self.m_ebounds.size()) ulim_values = gammalib.GFitsTableDoubleCol("UpperLimit", self.m_ebounds.size()) Npred_values = gammalib.GFitsTableDoubleCol("Npred", self.m_ebounds.size()) energy.unit("TeV") energy_low.unit("TeV") energy_high.unit("TeV") flux.unit("erg/cm2/s") flux_err.unit("erg/cm2/s") ulim_values.unit("erg/cm2/s") # Loop over energy bins for i in range(self.m_ebounds.size()): # Log information if self.logExplicit(): self.log("\n") self.log.header2("Energy bin "+str(i+1)) # Get energy boundaries emin = self.m_ebounds.emin(i) emax = self.m_ebounds.emax(i) elogmean = self.m_ebounds.elogmean(i) elogmean2 = elogmean.MeV() * elogmean.MeV() # Store energy as TeV energy[i] = elogmean.TeV() # Store energy errors energy_low[i] = (elogmean - emin).TeV() energy_high[i] = (emax - elogmean).TeV() # use ctselect for unbinned analysis if not self.m_binned_mode: # Log information if self.logExplicit(): self.log.header3("Selecting events") # Select events select = ctools.ctselect(self.obs) select["emin"] = emin.TeV() select["emax"] = emax.TeV() select["tmin"] = "UNDEFINED" select["tmax"] = "UNDEFINED" select["rad"] = "UNDEFINED" select["ra"] = "UNDEFINED" select["dec"] = "UNDEFINED" select.run() # Retrieve observation obs = select.obs() # use ctcubemask for binned analysis else: # Header if self.logExplicit(): self.log.header3("Filtering cube") # Select layers cubemask = ctools.ctcubemask(self.obs) cubemask["regfile"] = "NONE" cubemask["ra"] = "UNDEFINED" cubemask["dec"] = "UNDEFINED" cubemask["rad"] = "UNDEFINED" cubemask["emin"] = emin.TeV() cubemask["emax"] = emax.TeV() cubemask.run() # Set new binned observation obs = cubemask.obs() # Header if self.logExplicit(): self.log.header3("Performing fit") # Likelihood like = ctools.ctlike(obs) like["edisp"] = self.m_edisp like.run() # Skip bin if no event was present if like.obs().logL() == 0.0: # Log information if self.logExplicit(): self.log("No event in this bin. ") self.log("Likelihood is zero. ") self.log("Bin is skipped.") # Set all values to 0 flux[i] = 0.0 flux_err[i] = 0.0 TSvalues[i] = 0.0 ulim_values[i] = 0.0 Npred_values[i] = 0.0 continue # Get results fitted_models = like.obs().models() source = fitted_models[self.m_srcname] # Calculate Upper Limit ulimit_value = -1.0 if self.m_calc_ulimit: # Logging information if self.logExplicit(): self.log.header3("Computing upper limit") # Create upper limit object ulimit = ctools.ctulimit(like.obs()) ulimit["srcname"] = self.m_srcname ulimit["eref"] = elogmean.TeV() # Try to run upper limit and catch exceptions try: ulimit.run() ulimit_value = ulimit.diff_ulimit() except: if self.logExplicit(): self.log("Upper limit calculation failed.") ulimit_value = -1.0 # Get TS value TS = -1.0 if self.m_calc_ts: TS = source.ts() # Compute Npred value (only works for unbinned analysis) Npred = 0.0 if not self.m_binned_mode: for observation in like.obs(): Npred += observation.npred(source) # Get differential flux fitted_flux = source.spectral().eval(elogmean,gammalib.GTime()) # Compute flux error parvalue = source.spectral()[0].value() rel_error = source.spectral()[0].error() / parvalue e_flux = fitted_flux * rel_error # Set values for storage TSvalues[i] = TS # Set npred values Npred_values[i] = Npred # Convert fluxes to nuFnu flux[i] = fitted_flux * elogmean2 * gammalib.MeV2erg flux_err[i] = e_flux * elogmean2 * gammalib.MeV2erg if ulimit_value > 0.0: ulim_values[i] = ulimit_value * elogmean2 * gammalib.MeV2erg # Log information if self.logTerse(): self.log("\n") self.log.parformat("Bin "+str(i+1)) self.log(str(flux[i])) self.log(" +/- ") self.log(str(flux_err[i])) if self.m_calc_ulimit and ulim_values[i] > 0.0: self.log(" [< "+str(ulim_values[i])+"]") self.log(" erg/cm2/s") if self.m_calc_ts and TSvalues[i] > 0.0: self.log(" (TS = "+str(TS)+")") # Append filled columns to fits table table.append(energy) table.append(energy_low) table.append(energy_high) table.append(flux) table.append(flux_err) table.append(TSvalues) table.append(ulim_values) table.append(Npred_values) # Create the FITS file now self.fits = gammalib.GFits() self.fits.append(table) # Return return
def _test_python(self): """ Test ctcubemask from Python """ # Allocate ctcubemask mask = ctools.ctcubemask() # Check that empty ctcubemask tool holds an empty observation self._check_obs(mask.obs(), nobs=0) # Check that saving saves an empty counts cube mask['outcube'] = 'ctcubemask_py0.fits' mask['logfile'] = 'ctcubemask_py0.log' mask.logFileOpen() mask.save() self.test_assert(not os.path.isfile('ctcubemask_py0.fits'), 'Check that no counts cube has been created') # Check that clearing does not lead to an exception or segfault mask.clear() # Now set ctcubemask parameters mask['inobs'] = self._cntcube mask['regfile'] = self._exclusion mask['ra'] = 83.63 mask['dec'] = 22.01 mask['rad'] = 2.0 mask['emin'] = 0.1 mask['emax'] = 100.0 mask['outcube'] = 'ctcubemask_py1.fits' mask['logfile'] = 'ctcubemask_py1.log' mask['chatter'] = 2 # Run ctcubemask tool mask.logFileOpen() # Make sure we get a log file mask.run() mask.save() # Check result file self._check_result_file('ctcubemask_py1.fits') # Set-up ctcubemask without exclusion regions but tighter energy # selection mask = ctools.ctcubemask() mask['inobs'] = self._cntcube mask['regfile'] = 'NONE' mask['ra'] = 83.63 mask['dec'] = 22.01 mask['rad'] = 3.0 mask['emin'] = 1.0 mask['emax'] = 100.0 mask['outcube'] = 'ctcubemask_py2.fits' mask['logfile'] = 'ctcubemask_py2.log' mask['chatter'] = 3 mask['publish'] = True # Execute ctcubemask tool mask.logFileOpen() # Make sure we get a log file mask.execute() # Check result file self._check_result_file('ctcubemask_py2.fits', events=573) # Copy ctcubemask tool cpy_mask = mask.copy() # Check that ctcubemask tool holds one observation self._check_obs(cpy_mask.obs()) # Execute copy of ctcubemask tool again, now with a higher chatter # level than before cpy_mask['outcube'] = 'ctcubemask_py3.fits' cpy_mask['logfile'] = 'ctcubemask_py3.log' cpy_mask['chatter'] = 4 cpy_mask.execute() # Check result file self._check_result_file('ctcubemask_py3.fits', events=573) # Clear ctcubemask tool cpy_mask.clear() # Check that empty ctcubemask tool holds an empty observation self._check_obs(cpy_mask.obs(), nobs=0) # Prepare observation container obs = self._obs_mixed() obs.models(gammalib.GModels(self._model)) # Set-up ctcubemask from observation container, don't perform any # energy selection mask = ctools.ctcubemask(obs) mask['regfile'] = 'NONE' mask['ra'] = 83.63 mask['dec'] = 22.01 mask['rad'] = 3.0 mask['emin'] = 'NONE' mask['emax'] = 'NONE' mask['outcube'] = 'ctcubemask_py4.xml' mask['logfile'] = 'ctcubemask_py4.log' mask['chatter'] = 3 # Execute ctcubemask tool mask.logFileOpen() # Make sure we get a log file mask.execute() # Check result file self._check_result_file('filtered_crab_cntmap.fits', events=5542) # Return return
def run(self): """ Run the script. """ # Switch screen logging on in debug mode if self._logDebug(): self._log.cout(True) # Get parameters self._get_parameters() # Write spectral binning into header if self._logTerse(): self._log("\n") self._log.header1("Spectral binning") if self._binned_mode: cube_ebounds = self._obs[0].events().ebounds() self._log.parformat("Counts cube energy range") self._log(str(cube_ebounds.emin())) self._log(" - ") self._log(str(cube_ebounds.emax())) self._log("\n") for i in range(self._ebounds.size()): self._log.parformat("Bin " + str(i + 1)) self._log(str(self._ebounds.emin(i))) self._log(" - ") self._log(str(self._ebounds.emax(i))) self._log("\n") # Write observation into logger if self._logTerse(): self._log("\n") self._log.header1("Observation") self._log(str(self._obs)) self._log("\n") # Write header if self._logTerse(): self._log("\n") self._log.header1("Adjust model parameters") # Adjust model parameters dependent on input user parameters for model in self._obs.models(): # Set TS flag for all models to false. # Source of interest will be set to true later model.tscalc(False) # Log model name if self._logExplicit(): self._log.header3(model.name()) # Deal with the source of interest if model.name() == self._srcname: for par in model: if par.is_free() and self._logExplicit(): self._log(" Fixing \"" + par.name() + "\"\n") par.fix() normpar = model.spectral()[0] if normpar.is_fixed() and self._logExplicit(): self._log(" Freeing \"" + normpar.name() + "\"\n") normpar.free() if self._calc_ts: model.tscalc(True) elif self._fix_bkg and not model.classname() == "GModelSky": for par in model: if par.is_free() and self._logExplicit(): self._log(" Fixing \"" + par.name() + "\"\n") par.fix() elif self._fix_srcs and model.classname() == "GModelSky": for par in model: if par.is_free() and self._logExplicit(): self._log(" Fixing \"" + par.name() + "\"\n") par.fix() # Write header if self._logTerse(): self._log("\n") self._log.header1("Generate spectrum") self._log(str(self._ebounds)) # Initialise FITS Table with extension "SPECTRUM" table = gammalib.GFitsBinTable(self._ebounds.size()) table.extname("SPECTRUM") # Add Header for compatibility with gammalib.GMWLSpectrum table.card("INSTRUME", "CTA", "Name of Instrument") table.card("TELESCOP", "CTA", "Name of Telescope") # Create FITS table columns nrows = self._ebounds.size() energy = gammalib.GFitsTableDoubleCol("Energy", nrows) energy_low = gammalib.GFitsTableDoubleCol("ed_Energy", nrows) energy_high = gammalib.GFitsTableDoubleCol("eu_Energy", nrows) flux = gammalib.GFitsTableDoubleCol("Flux", nrows) flux_err = gammalib.GFitsTableDoubleCol("e_Flux", nrows) TSvalues = gammalib.GFitsTableDoubleCol("TS", nrows) ulim_values = gammalib.GFitsTableDoubleCol("UpperLimit", nrows) Npred_values = gammalib.GFitsTableDoubleCol("Npred", nrows) energy.unit("TeV") energy_low.unit("TeV") energy_high.unit("TeV") flux.unit("erg/cm2/s") flux_err.unit("erg/cm2/s") ulim_values.unit("erg/cm2/s") # Loop over energy bins for i in range(nrows): # Log information if self._logExplicit(): self._log("\n") self._log.header2("Energy bin " + str(i + 1)) # Get energy boundaries emin = self._ebounds.emin(i) emax = self._ebounds.emax(i) elogmean = self._ebounds.elogmean(i) elogmean2 = elogmean.MeV() * elogmean.MeV() # Store energy as TeV energy[i] = elogmean.TeV() # Store energy errors energy_low[i] = (elogmean - emin).TeV() energy_high[i] = (emax - elogmean).TeV() # Use ctselect for unbinned analysis if not self._binned_mode: # Log information if self._logExplicit(): self._log.header3("Selecting events") # Select events select = ctools.ctselect(self._obs) select["emin"] = emin.TeV() select["emax"] = emax.TeV() select["tmin"] = "UNDEFINED" select["tmax"] = "UNDEFINED" select["rad"] = "UNDEFINED" select["ra"] = "UNDEFINED" select["dec"] = "UNDEFINED" select.run() # Retrieve observation obs = select.obs() # Use ctcubemask for binned analysis else: # Header if self._logExplicit(): self._log.header3("Filtering cube") # Select layers cubemask = ctools.ctcubemask(self._obs) cubemask["regfile"] = "NONE" cubemask["ra"] = "UNDEFINED" cubemask["dec"] = "UNDEFINED" cubemask["rad"] = "UNDEFINED" cubemask["emin"] = emin.TeV() cubemask["emax"] = emax.TeV() cubemask.run() # Set new binned observation obs = cubemask.obs() # Header if self._logExplicit(): self._log.header3("Performing fit") # Likelihood like = ctools.ctlike(obs) like["edisp"] = self._edisp like.run() # Skip bin if no event was present if like.obs().logL() == 0.0: # Log information if self._logExplicit(): self._log("No event in this bin. ") self._log("Likelihood is zero. ") self._log("Bin is skipped.") # Set all values to 0 flux[i] = 0.0 flux_err[i] = 0.0 TSvalues[i] = 0.0 ulim_values[i] = 0.0 Npred_values[i] = 0.0 continue # Get results fitted_models = like.obs().models() source = fitted_models[self._srcname] # Calculate Upper Limit ulimit_value = -1.0 if self._calc_ulimit: # Logging information if self._logExplicit(): self._log.header3("Computing upper limit") # Create upper limit object ulimit = ctools.ctulimit(like.obs()) ulimit["srcname"] = self._srcname ulimit["eref"] = elogmean.TeV() # Try to run upper limit and catch exceptions try: ulimit.run() ulimit_value = ulimit.diff_ulimit() except: if self._logExplicit(): self._log("Upper limit calculation failed.") ulimit_value = -1.0 # Get TS value TS = -1.0 if self._calc_ts: TS = source.ts() # Compute Npred value (only works for unbinned analysis) Npred = 0.0 if not self._binned_mode: for observation in like.obs(): Npred += observation.npred(source) # Get differential flux fitted_flux = source.spectral().eval(elogmean) # Compute flux error parvalue = source.spectral()[0].value() rel_error = source.spectral()[0].error() / parvalue e_flux = fitted_flux * rel_error # Set values for storage TSvalues[i] = TS # Set npred values Npred_values[i] = Npred # Convert fluxes to nuFnu flux[i] = fitted_flux * elogmean2 * gammalib.MeV2erg flux_err[i] = e_flux * elogmean2 * gammalib.MeV2erg if ulimit_value > 0.0: ulim_values[i] = ulimit_value * elogmean2 * gammalib.MeV2erg # Log information if self._logTerse(): self._log("\n") self._log.parformat("Bin " + str(i + 1)) self._log(str(flux[i])) self._log(" +/- ") self._log(str(flux_err[i])) if self._calc_ulimit and ulim_values[i] > 0.0: self._log(" [< " + str(ulim_values[i]) + "]") self._log(" erg/cm2/s") if self._calc_ts and TSvalues[i] > 0.0: self._log(" (TS = " + str(TS) + ")") # Append filled columns to fits table table.append(energy) table.append(energy_low) table.append(energy_high) table.append(flux) table.append(flux_err) table.append(TSvalues) table.append(ulim_values) table.append(Npred_values) # Create the FITS file now self._fits = gammalib.GFits() self._fits.append(table) # Return return