for file in files: os.remove(file) # Setup single observation survey #obs = survey_single() obs = survey_gplane() # Add background model obs = add_background_model(obs) # Simulate events print("Simulate events") obs = obsutils.sim(obs) # Make counts map print("Make counts map") cntmap = obsutils.cntmap(obs) # Fit observations print("Fit observations") like = obsutils.fit(obs) #print like.opt() #print like.obs().models() # Make model map print("Make model map (this step will take some time)") modmap = obsutils.modmap(obs) # Show fit results #plot_counts(like.obs())
def trial(self, seed): """ Create the pull for a single trial. Parameters: seed - Random number generator seed """ # Write header if self.logExplicit(): self.log.header2("Trial "+str(seed+1)) # Simulate events obs = obsutils.sim(self.obs, \ nbins=self.m_enumbins, \ seed=seed, \ binsz=self.m_binsz, \ npix=self.m_npix, \ log=self.m_log, debug=self.m_debug) # Determine number of events in simulation nevents = 0.0 for run in obs: nevents += run.events().number() # Write simulation results if self.logExplicit(): self.log.header3("Simulation") self.log.parformat("Number of simulated events") self.log(nevents) self.log("\n") # Fit model like = obsutils.fit(obs, log=self.m_log, debug=self.m_debug) # Store results logL = like.opt().value() npred = like.obs().npred() models = like.obs().models() # Write result header if self.logExplicit(): self.log.header3("Pulls") # Gather results colnames = [] values = {} for i in range(models.size()): model = models[i] model_name = model.name() for k in range(model.size()): par = model[k] if par.is_free(): # Set parameter name name = model_name+"_"+par.name() # Append parameter, Pull_parameter and Unc_parameter colnames.append(name) colnames.append("Pull_"+name) colnames.append("Unc_"+name) # Compute pull fitted_value = par.value() real_value = self.model[i][k].value() error = par.error() if error != 0.0: pull = (fitted_value - real_value) / error else: pull = 99.0 # Store results values[name] = fitted_value values["Pull_"+name] = pull values["Unc_"+name] = error # Write result if self.logExplicit(): self.log.parformat(name) self.log(pull) self.log(" (") self.log(fitted_value) self.log(" +/- ") self.log(error) self.log(")\n") # Bundle together results result = {'colnames': colnames, 'values': values} # Return return result
def trial(self, seed): """ Create the TS for a single trial. Parameters: seed - Random number generator seed """ # Write header if self.logExplicit(): self.log.header2("Trial "+str(seed+1)) # Simulate events sim = obsutils.sim(self.obs, \ nbins=self.m_enumbins, \ seed=seed, \ binsz=self.m_binsz, \ npix=self.m_npix, \ log=self.m_log, debug=self.m_debug) # Determine number of events in simulation nevents = 0.0 for run in sim: nevents += run.events().number() # Write simulation results if self.logExplicit(): self.log.header3("Simulation") self.log.parformat("Number of simulated events") self.log(nevents) self.log("\n") # Fit background only sim.models(self.bkg_model) like_bgm = obsutils.fit(sim, log=self.m_log, debug=self.m_debug) result_bgm = like_bgm.obs().models() LogL_bgm = like_bgm.opt().value() npred_bgm = like_bgm.obs().npred() # Write background fit results if self.logExplicit(): self.log.header3("Background model fit") self.log.parformat("log likelihood") self.log(LogL_bgm) self.log("\n") self.log.parformat("Number of predicted events") self.log(npred_bgm) self.log("\n") for model in result_bgm: self.log.parformat("Model") self.log(model.name()) self.log("\n") for par in model: self.log(str(par)+"\n") # Fit background and test source sim.models(self.full_model) like_all = obsutils.fit(sim, log=self.m_log, debug=self.m_debug) result_all = like_all.obs().models() LogL_all = like_all.opt().value() npred_all = like_all.obs().npred() ts = 2.0*(LogL_bgm-LogL_all) # Write background and test source fit results if self.logExplicit(): self.log.header3("Background and test source model fit") self.log.parformat("Test statistics") self.log(ts) self.log("\n") self.log.parformat("log likelihood") self.log(LogL_all) self.log("\n") self.log.parformat("Number of predicted events") self.log(npred_all) self.log("\n") for model in result_all: self.log.parformat("Model") self.log(model.name()) self.log("\n") for par in model: self.log(str(par)+"\n") # Write result elif self.logTerse(): self.log.parformat("Trial "+str(seed)) self.log("TS=") self.log(ts) self.log(" Prefactor=") self.log(result_all["Test"]["Prefactor"].value()) self.log("+/-") self.log(result_all["Test"]["Prefactor"].error()) self.log("\n") # Initialise results colnames = [] values = {} # Set TS value colnames.append("TS") values["TS"] = ts # Set logL for background fit colnames.append("LogL_bgm") values["LogL_bgm"] = LogL_bgm # Set logL for full fit colnames.append("LogL_all") values["LogL_all"] = LogL_all # Set Nevents colnames.append("Nevents") values["Nevents"] = nevents # Set Npred for background fit colnames.append("Npred_bkg") values["Npred_bkg"] = npred_bgm # Set Npred for full fit colnames.append("Npred_all") values["Npred_all"] = npred_all # Gather free full fit parameters for i in range(result_all.size()): model = result_all[i] model_name = model.name() for k in range(model.size()): par = model[k] if par.isfree(): # Set parameter name name = model_name+"_"+par.name() # Append value colnames.append(name) values[name] = par.value() # Append error name = "Unc_"+name colnames.append(name) values[name] = par.error() # Bundle together results result = {'colnames': colnames, 'values': values} # Return return result
def set_src_model(self, l, b, flux=1.0, index=-2.48, \ type="point", fitpos=False, fitidx=False): """ Returns a single source with Crab-like spectrum. The source flux can be scaled in Crab units. The Crab spectrum is based on MAGIC observations (Albert et al. 2008, ApJ, 674, 1037). Parameters: l - Galactic longitude of source location [deg] b - Galactic latitude of source location [deg] Keywords: flux - Source flux [Crabs] index - Spectral index type - Source type ("point", "gauss", "disk", "shell") fitpos - Fit position and size? (default: False) fitidx - Fit index? (default: False) """ # Set source location location = GSkyDir() location.lb_deg(l, b) # Set source spectrum spectrum = GModelSpectralPlaw(flux*5.7e-16, index, GEnergy(0.3, "TeV") if fitidx: spectrum["Index"].free() else: spectrum["Index"].fix() # Set source if type == "point": spatial = GModelSpatialPointSource(location) if fitpos: spatial["RA"].free() spatial["DEC"].free() else: spatial["RA"].fix() spatial["DEC"].fix() elif type == "gauss": spatial = GModelSpatialRadialGauss(location, self.m_radius) if fitpos: spatial["RA"].free() spatial["DEC"].free() spatial["Sigma"].free() else: spatial["RA"].fix() spatial["DEC"].fix() spatial["Sigma"].fix() elif type == "disk": spatial = GModelSpatialRadialDisk(location, self.m_radius) if fitpos: spatial["RA"].free() spatial["DEC"].free() spatial["Radius"].free() else: spatial["RA"].fix() spatial["DEC"].fix() spatial["Radius"].fix() elif type == "shell": spatial = GModelSpatialRadialShell(location, self.m_radius, self.m_width) if fitpos: spatial["RA"].free() spatial["DEC"].free() spatial["Radius"].free() spatial["Width"].free() else: spatial["RA"].fix() spatial["DEC"].fix() spatial["Radius"].fix() spatial["Width"].fix() else: self.log("ERROR: Unknown source type '"+type+"'.\n") return None source = GModelSky(spatial, spectrum) # Set source name source.name("Test") # Return source return source def get_sensitivity(self, obs, bkg_model, full_model): """ Determine sensitivity for a given observations. Parameters: obs - Observation container bkg_model - Background model full_model - Source model """ # Set TeV->erg conversion factor tev2erg = 1.6021764 # Determine energy boundaries from first observation in # the container for run in obs: emin = run.events().ebounds().emin() emax = run.events().ebounds().emax() loge = math.log10(math.sqrt(emin.TeV()*emax.TeV())) erg_mean = math.pow(10.0, loge) * tev2erg erg_width = (emax.TeV()-emin.TeV()) * tev2erg break # Write header if self.logTerse(): self.log("\n") self.log.header2("Energies: "+str(emin)+" - "+str(emax)) # Initialise loop flux_value = [] pflux_value = [] eflux_value = [] diffSens_value = [] iter = 0 test_flux = 0.1 # This is the initial test flux in Crab units # Loop until we break while True: # Update iteration counter iter += 1 # Write header if self.logExplicit(): self.log.header2("Iteration "+str(iter)) # Set test flux full_model["Test"]['Prefactor'].value(test_flux) obs.models(full_model) # Simulate events sim = obsutils.sim(obs, nbins=self.m_nbins, seed=iter, \ binsz=self.m_binsz, npix=self.m_npix, \ log=self.m_log, debug=self.m_debug) # Determine number of events in simulation nevents = 0.0 for run in sim: nevents += run.events().number() # Write simulation results if self.logExplicit(): self.log.header3("Simulation") self.log.parformat("Number of simulated events") self.log(nevents) self.log("\n") # Fit background only sim.models(bkg_model) like = obsutils.fit(sim, log=self.m_log, debug=self.m_debug) result_bgm = like.obs().models().copy() LogL_bgm = like.opt().value() npred_bgm = like.obs().npred() # Assess quality based on a comparison between Npred and Nevents quality_bgm = npred_bgm-nevents # Write background fit results if self.logExplicit(): self.log.header3("Background model fit") self.log.parformat("log likelihood") self.log(LogL_bgm) self.log("\n") self.log.parformat("Number of predicted events") self.log(npred_bgm) self.log("\n") self.log.parformat("Fit quality") self.log(quality_bgm) self.log("\n") # Start over if the fit quality was bad if abs(quality_bgm) > 3.0: if self.logExplicit(): self.log("Fit quality outside required range. Start over.\n") continue # Write model fit results if self.logExplicit(): for model in result_bgm: self.log.parformat("Model") self.log(model.name()) self.log("\n") for par in model: self.log(str(par)+"\n") # Fit background and test source sim.models(full_model) like = obsutils.fit(sim, log=self.m_log, debug=self.m_debug) result_all = like.obs().models().copy() LogL_all = like.opt().value() npred_all = like.obs().npred() ts = 2.0*(LogL_bgm-LogL_all) # Assess quality based on a comparison between Npred and Nevents quality_all = npred_all-nevents # Write background and test source fit results if self.logExplicit(): self.log.header3("Background and test source model fit") self.log.parformat("Test statistics") self.log(ts) self.log("\n") self.log.parformat("log likelihood") self.log(LogL_all) self.log("\n") self.log.parformat("Number of predicted events") self.log(npred_all) self.log("\n") self.log.parformat("Fit quality") self.log(quality_all) self.log("\n") # for model in result_all: self.log.parformat("Model") self.log(model.name()) self.log("\n") for par in model: self.log(str(par)+"\n") # Start over if the fit quality was bad if abs(quality_all) > 3.0: if self.logExplicit(): self.log("Fit quality outside required range. Start over.\n") continue # Start over if TS was non-positive if ts <= 0.0: if self.logExplicit(): self.log("Non positive TS. Start over.\n") continue # Get fitted Crab, photon and energy fluxes cflux = result_all["Test"]['Prefactor'].value() cflux_err = result_all["Test"]['Prefactor'].error() pflux = result_all["Test"].spectral().flux(emin, emax) eflux = result_all["Test"].spectral().eflux(emin, emax) # Compute differential sensitivity diffSens = pflux / erg_width * erg_mean*erg_mean # Compute flux correction factor based on average TS correct = 1.0 if self.m_use_ts: if ts > 0: correct = math.sqrt(self.m_ts_thres/ts) else: if cflux > 0 and cflux_err > 0: correct = math.sqrt(self.m_ts_thres)/(cflux/cflux_err) # Compute extrapolated fluxes flux = correct * cflux pflux = correct * pflux eflux = correct * eflux diffSens = correct * diffSens flux_value.append(flux) pflux_value.append(pflux) eflux_value.append(eflux) diffSens_value.append(diffSens) # Write background and test source fit results if self.logExplicit(): self.log.parformat("Photon flux") self.log(pflux) self.log(" ph/cm2/s\n") self.log.parformat("Energy flux") self.log(eflux) self.log(" erg/cm2/s\n") self.log.parformat("Crab flux") self.log(cflux*1000.0) self.log(" mCrab\n") self.log.parformat("Differential sensitivity") self.log(diffSens) self.log(" erg/cm2/s\n") for model in result_all: self.log.parformat("Model") self.log(model.name()) self.log("\n") for par in model: self.log(str(par)+"\n") elif self.logTerse(): self.log.parformat("Iteration "+str(iter)) self.log("TS=") self.log(ts) self.log(" ") self.log("corr=") self.log(correct) self.log(" ") self.log(pflux) self.log(" ph/cm2/s = ") self.log(eflux) self.log(" erg/cm2/s = ") self.log(cflux*1000.0) self.log(" mCrab = ") self.log(diffSens) self.log(" erg/cm2/s\n") # Compute sliding average of extrapolated fitted prefactor, # photon and energy flux. This damps out fluctuations and # improves convergence flux = 0.0 pflux = 0.0 eflux = 0.0 diffSens = 0.0 num = 0.0 for k in range(self.m_num_avg): inx = len(flux_value) - k - 1 if inx >= 0: flux += flux_value[inx] pflux += pflux_value[inx] eflux += eflux_value[inx] diffSens += diffSens_value[inx] num += 1.0 flux /= num pflux /= num eflux /= num diffSens /= num # Compare average flux to last average if iter > self.m_num_avg: if test_flux > 0: ratio = flux/test_flux # We have 2 convergence criteria: # 1. The average flux does not change # 2. The flux correction factor is small if ratio >= 0.99 and ratio <= 1.01 and \ correct >= 0.9 and correct <= 1.1: if self.logTerse(): self.log(" Converged ("+str(ratio)+")\n") break else: if self.logTerse(): self.log(" Flux is zero.\n") break # Use average for next iteration test_flux = flux # Exit loop if number of trials exhausted if (iter >= self.m_max_iter): if self.logTerse(): self.log(" Test ended after "+str(self.m_max_iter)+" iterations.\n") break # Write fit results if self.logTerse(): self.log.header3("Fit results") self.log.parformat("Test statistics") self.log(ts) self.log("\n") self.log.parformat("Photon flux") self.log(pflux) self.log(" ph/cm2/s\n") self.log.parformat("Energy flux") self.log(eflux) self.log(" erg/cm2/s\n") self.log.parformat("Crab flux") self.log(cflux*1000.0) self.log(" mCrab\n") self.log.parformat("Differential sensitivity") self.log(diffSens) self.log(" erg/cm2/s\n") self.log.parformat("Number of simulated events") self.log(nevents) self.log("\n") self.log.header3("Background and test source model fitting") self.log.parformat("log likelihood") self.log(LogL_all) self.log("\n") self.log.parformat("Number of predicted events") self.log(npred_all) self.log("\n") for model in result_all: self.log.parformat("Model") self.log(model.name()) self.log("\n") for par in model: self.log(str(par)+"\n") self.log.header3("Background model fit") self.log.parformat("log likelihood") self.log(LogL_bgm) self.log("\n") self.log.parformat("Number of predicted events") self.log(npred_bgm) self.log("\n") for model in result_bgm: self.log.parformat("Model") self.log(model.name()) self.log("\n") for par in model: self.log(str(par)+"\n") # Store result result = {'loge': loge, 'emin': emin.TeV(), 'emax': emax.TeV(), \ 'crab': flux, 'pflux': pflux, 'eflux': eflux, \ 'diffSens': diffSens} # Return result return result # ======================== # # Main routine entry point # # ======================== # if __name__ == '__main__': """ CTA ctlike-based sensitivity estimator. """ # Create instance of application app = cssens(sys.argv) # Run application app.execute()
for file in files: os.remove(file) # Setup single observation survey #obs = survey_single() obs = survey_gplane() # Add background model obs = add_background_model(obs) # Simulate events print("Simulate events") obs = obsutils.sim(obs) # Make counts map print("Make counts map") cntmap = obsutils.cntmap(obs) # Fit observations print("Fit observatins") like = obsutils.fit(obs) #print like.opt() #print like.obs().models() # Make model map print("Make model map (this step will take some time)") modmap = obsutils.modmap(obs) # Show fit results #plot_counts(like.obs())
def trial(self, seed): """ Create the pull for a single trial. Parameters: seed - Random number generator seed """ # Write header if self.logExplicit(): self.log.header2("Trial " + str(seed + 1)) # Simulate events obs = obsutils.sim(self.obs, \ nbins=self.m_enumbins, \ seed=seed, \ binsz=self.m_binsz, \ npix=self.m_npix, \ log=self.m_log, debug=self.m_debug) # Determine number of events in simulation nevents = 0.0 for run in obs: nevents += run.events().number() # Write simulation results if self.logExplicit(): self.log.header3("Simulation") self.log.parformat("Number of simulated events") self.log(nevents) self.log("\n") # Fit model like = obsutils.fit(obs, log=self.m_log, debug=self.m_debug) # Store results logL = like.opt().value() npred = like.obs().npred() models = like.obs().models() # Write result header if self.logExplicit(): self.log.header3("Pulls") # Gather results colnames = [] values = {} for i in range(models.size()): model = models[i] model_name = model.name() for k in range(model.size()): par = model[k] if par.isfree(): # Set parameter name name = model_name + "_" + par.name() # Append parameter, Pull_parameter and Unc_parameter colnames.append(name) colnames.append("Pull_" + name) colnames.append("Unc_" + name) # Compute pull fitted_value = par.value() real_value = self.model[i][k].value() error = par.error() if error != 0.0: pull = (fitted_value - real_value) / error else: pull = 99.0 # Store results values[name] = fitted_value values["Pull_" + name] = pull values["Unc_" + name] = error # Write result if self.logExplicit(): self.log.parformat(name) self.log(pull) self.log(" (") self.log(fitted_value) self.log(" +/- ") self.log(error) self.log(")\n") # Bundle together results result = {'colnames': colnames, 'values': values} # Return return result
def get_sensitivity(self, obs, bkg_model, full_model): """ Determine sensitivity for a given observations. Parameters: obs - Observation container bkg_model - Background model full_model - Source model """ # Set TeV->erg conversion factor tev2erg = 1.6021764 # Determine energy boundaries from first observation in # the container for run in obs: emin = run.events().ebounds().emin() emax = run.events().ebounds().emax() loge = math.log10(math.sqrt(emin.TeV()*emax.TeV())) erg_mean = math.pow(10.0, loge) * tev2erg erg_width = (emax.TeV()-emin.TeV()) * tev2erg break # Write header if self.logTerse(): self.log("\n") self.log.header2("Energies: "+str(emin)+" - "+str(emax)) # Initialise loop flux_value = [] pflux_value = [] eflux_value = [] diffSens_value = [] iter = 0 test_flux = 0.1 # This is the initial test flux in Crab units # Loop until we break while True: # Update iteration counter iter += 1 # Write header if self.logExplicit(): self.log.header2("Iteration "+str(iter)) # Set test flux full_model["Test"]['Prefactor'].value(test_flux) obs.models(full_model) # Simulate events sim = obsutils.sim(obs, nbins=self.m_nbins, seed=iter, \ binsz=self.m_binsz, npix=self.m_npix, \ log=self.m_log, debug=self.m_debug) # Determine number of events in simulation nevents = 0.0 for run in sim: nevents += run.events().number() # Write simulation results if self.logExplicit(): self.log.header3("Simulation") self.log.parformat("Number of simulated events") self.log(nevents) self.log("\n") # Fit background only sim.models(bkg_model) like = obsutils.fit(sim, log=self.m_log, debug=self.m_debug) result_bgm = like.obs().models().copy() LogL_bgm = like.opt().value() npred_bgm = like.obs().npred() # Assess quality based on a comparison between Npred and Nevents quality_bgm = npred_bgm-nevents # Write background fit results if self.logExplicit(): self.log.header3("Background model fit") self.log.parformat("log likelihood") self.log(LogL_bgm) self.log("\n") self.log.parformat("Number of predicted events") self.log(npred_bgm) self.log("\n") self.log.parformat("Fit quality") self.log(quality_bgm) self.log("\n") # Start over if the fit quality was bad if abs(quality_bgm) > 3.0: if self.logExplicit(): self.log("Fit quality outside required range. Start over.\n") continue # Write model fit results if self.logExplicit(): for model in result_bgm: self.log.parformat("Model") self.log(model.name()) self.log("\n") for par in model: self.log(str(par)+"\n") # Fit background and test source sim.models(full_model) like = obsutils.fit(sim, log=self.m_log, debug=self.m_debug) result_all = like.obs().models().copy() LogL_all = like.opt().value() npred_all = like.obs().npred() ts = 2.0*(LogL_bgm-LogL_all) # Assess quality based on a comparison between Npred and Nevents quality_all = npred_all-nevents # Write background and test source fit results if self.logExplicit(): self.log.header3("Background and test source model fit") self.log.parformat("Test statistics") self.log(ts) self.log("\n") self.log.parformat("log likelihood") self.log(LogL_all) self.log("\n") self.log.parformat("Number of predicted events") self.log(npred_all) self.log("\n") self.log.parformat("Fit quality") self.log(quality_all) self.log("\n") # for model in result_all: self.log.parformat("Model") self.log(model.name()) self.log("\n") for par in model: self.log(str(par)+"\n") # Start over if the fit quality was bad if abs(quality_all) > 3.0: if self.logExplicit(): self.log("Fit quality outside required range. Start over.\n") continue # Start over if TS was non-positive if ts <= 0.0: if self.logExplicit(): self.log("Non positive TS. Start over.\n") continue # Get fitted Crab, photon and energy fluxes cflux = result_all["Test"]['Prefactor'].value() cflux_err = result_all["Test"]['Prefactor'].error() pflux = result_all["Test"].spectral().flux(emin, emax) eflux = result_all["Test"].spectral().eflux(emin, emax) # Compute differential sensitivity diffSens = pflux / erg_width * erg_mean*erg_mean # Compute flux correction factor based on average TS correct = 1.0 if self.m_use_ts: if ts > 0: correct = math.sqrt(self.m_ts_thres/ts) else: if cflux > 0 and cflux_err > 0: correct = math.sqrt(self.m_ts_thres)/(cflux/cflux_err) # Compute extrapolated fluxes flux = correct * cflux pflux = correct * pflux eflux = correct * eflux diffSens = correct * diffSens flux_value.append(flux) pflux_value.append(pflux) eflux_value.append(eflux) diffSens_value.append(diffSens) # Write background and test source fit results if self.logExplicit(): self.log.parformat("Photon flux") self.log(pflux) self.log(" ph/cm2/s\n") self.log.parformat("Energy flux") self.log(eflux) self.log(" erg/cm2/s\n") self.log.parformat("Crab flux") self.log(cflux*1000.0) self.log(" mCrab\n") self.log.parformat("Differential sensitivity") self.log(diffSens) self.log(" erg/cm2/s\n") for model in result_all: self.log.parformat("Model") self.log(model.name()) self.log("\n") for par in model: self.log(str(par)+"\n") elif self.logTerse(): self.log.parformat("Iteration "+str(iter)) self.log("TS=") self.log(ts) self.log(" ") self.log("corr=") self.log(correct) self.log(" ") self.log(pflux) self.log(" ph/cm2/s = ") self.log(eflux) self.log(" erg/cm2/s = ") self.log(cflux*1000.0) self.log(" mCrab = ") self.log(diffSens) self.log(" erg/cm2/s\n") # Compute sliding average of extrapolated fitted prefactor, # photon and energy flux. This damps out fluctuations and # improves convergence flux = 0.0 pflux = 0.0 eflux = 0.0 diffSens = 0.0 num = 0.0 for k in range(self.m_num_avg): inx = len(flux_value) - k - 1 if inx >= 0: flux += flux_value[inx] pflux += pflux_value[inx] eflux += eflux_value[inx] diffSens += diffSens_value[inx] num += 1.0 flux /= num pflux /= num eflux /= num diffSens /= num # Compare average flux to last average if iter > self.m_num_avg: if test_flux > 0: ratio = flux/test_flux # We have 2 convergence criteria: # 1. The average flux does not change # 2. The flux correction factor is small if ratio >= 0.99 and ratio <= 1.01 and \ correct >= 0.9 and correct <= 1.1: if self.logTerse(): self.log(" Converged ("+str(ratio)+")\n") break else: if self.logTerse(): self.log(" Flux is zero.\n") break # Use average for next iteration test_flux = flux # Exit loop if number of trials exhausted if (iter >= self.m_max_iter): if self.logTerse(): self.log(" Test ended after "+str(self.m_max_iter)+" iterations.\n") break # Write fit results if self.logTerse(): self.log.header3("Fit results") self.log.parformat("Test statistics") self.log(ts) self.log("\n") self.log.parformat("Photon flux") self.log(pflux) self.log(" ph/cm2/s\n") self.log.parformat("Energy flux") self.log(eflux) self.log(" erg/cm2/s\n") self.log.parformat("Crab flux") self.log(cflux*1000.0) self.log(" mCrab\n") self.log.parformat("Differential sensitivity") self.log(diffSens) self.log(" erg/cm2/s\n") self.log.parformat("Number of simulated events") self.log(nevents) self.log("\n") self.log.header3("Background and test source model fitting") self.log.parformat("log likelihood") self.log(LogL_all) self.log("\n") self.log.parformat("Number of predicted events") self.log(npred_all) self.log("\n") for model in result_all: self.log.parformat("Model") self.log(model.name()) self.log("\n") for par in model: self.log(str(par)+"\n") self.log.header3("Background model fit") self.log.parformat("log likelihood") self.log(LogL_bgm) self.log("\n") self.log.parformat("Number of predicted events") self.log(npred_bgm) self.log("\n") for model in result_bgm: self.log.parformat("Model") self.log(model.name()) self.log("\n") for par in model: self.log(str(par)+"\n") # Store result result = {'loge': loge, 'emin': emin.TeV(), 'emax': emax.TeV(), \ 'crab': flux, 'pflux': pflux, 'eflux': eflux, \ 'diffSens': diffSens} # Return result return result
def trial(self, seed): """ Create the TS for a single trial. Parameters: seed - Random number generator seed """ # Write header if self.logExplicit(): self.log.header2("Trial " + str(seed + 1)) # Simulate events sim = obsutils.sim(self.obs, \ nbins=self.m_enumbins, \ seed=seed, \ binsz=self.m_binsz, \ npix=self.m_npix, \ log=self.m_log, debug=self.m_debug) # Determine number of events in simulation nevents = 0.0 for run in sim: nevents += run.events().number() # Write simulation results if self.logExplicit(): self.log.header3("Simulation") self.log.parformat("Number of simulated events") self.log(nevents) self.log("\n") # Fit background only sim.models(self.bkg_model) like_bgm = obsutils.fit(sim, log=self.m_log, debug=self.m_debug) result_bgm = like_bgm.obs().models() LogL_bgm = like_bgm.opt().value() npred_bgm = like_bgm.obs().npred() # Write background fit results if self.logExplicit(): self.log.header3("Background model fit") self.log.parformat("log likelihood") self.log(LogL_bgm) self.log("\n") self.log.parformat("Number of predicted events") self.log(npred_bgm) self.log("\n") for model in result_bgm: self.log.parformat("Model") self.log(model.name()) self.log("\n") for par in model: self.log(str(par) + "\n") # Fit background and test source sim.models(self.full_model) like_all = obsutils.fit(sim, log=self.m_log, debug=self.m_debug) result_all = like_all.obs().models() LogL_all = like_all.opt().value() npred_all = like_all.obs().npred() ts = 2.0 * (LogL_bgm - LogL_all) # Write background and test source fit results if self.logExplicit(): self.log.header3("Background and test source model fit") self.log.parformat("Test statistics") self.log(ts) self.log("\n") self.log.parformat("log likelihood") self.log(LogL_all) self.log("\n") self.log.parformat("Number of predicted events") self.log(npred_all) self.log("\n") for model in result_all: self.log.parformat("Model") self.log(model.name()) self.log("\n") for par in model: self.log(str(par) + "\n") # Write result elif self.logTerse(): self.log.parformat("Trial " + str(seed)) self.log("TS=") self.log(ts) self.log(" Prefactor=") self.log(result_all["Test"]["Prefactor"].value()) self.log("+/-") self.log(result_all["Test"]["Prefactor"].error()) self.log("\n") # Initialise results colnames = [] values = {} # Set TS value colnames.append("TS") values["TS"] = ts # Set logL for background fit colnames.append("LogL_bgm") values["LogL_bgm"] = LogL_bgm # Set logL for full fit colnames.append("LogL_all") values["LogL_all"] = LogL_all # Set Nevents colnames.append("Nevents") values["Nevents"] = nevents # Set Npred for background fit colnames.append("Npred_bkg") values["Npred_bkg"] = npred_bgm # Set Npred for full fit colnames.append("Npred_all") values["Npred_all"] = npred_all # Gather free full fit parameters for i in range(result_all.size()): model = result_all[i] model_name = model.name() for k in range(model.size()): par = model[k] if par.isfree(): # Set parameter name name = model_name + "_" + par.name() # Append value colnames.append(name) values[name] = par.value() # Append error name = "Unc_" + name colnames.append(name) values[name] = par.error() # Bundle together results result = {'colnames': colnames, 'values': values} # Return return result
def get_sensitivity(self, obs, bkg_model, full_model): """ Determine sensitivity for a given observations. Parameters: obs - Observation container bkg_model - Background model full_model - Source model """ # Set TeV->erg conversion factor tev2erg = 1.6021764 # Determine energy boundaries from first observation in # the container for run in obs: emin = run.events().ebounds().emin() emax = run.events().ebounds().emax() loge = math.log10(math.sqrt(emin.TeV() * emax.TeV())) erg_mean = math.pow(10.0, loge) * tev2erg erg_width = (emax.TeV() - emin.TeV()) * tev2erg break # Write header if self.logTerse(): self.log("\n") self.log.header2("Energies: " + str(emin) + " - " + str(emax)) # Initialise loop flux_value = [] pflux_value = [] eflux_value = [] diffSens_value = [] iter = 0 test_flux = 0.1 # This is the initial test flux in Crab units # Loop until we break while True: # Update iteration counter iter += 1 # Write header if self.logExplicit(): self.log.header2("Iteration " + str(iter)) # Set test flux full_model["Test"]['Prefactor'].value(test_flux) obs.models(full_model) # Simulate events sim = obsutils.sim(obs, nbins=self.m_nbins, seed=iter, \ binsz=self.m_binsz, npix=self.m_npix, \ log=self.m_log, debug=self.m_debug) # Determine number of events in simulation nevents = 0.0 for run in sim: nevents += run.events().number() # Write simulation results if self.logExplicit(): self.log.header3("Simulation") self.log.parformat("Number of simulated events") self.log(nevents) self.log("\n") # Fit background only sim.models(bkg_model) like = obsutils.fit(sim, log=self.m_log, debug=self.m_debug) result_bgm = like.obs().models().copy() LogL_bgm = like.opt().value() npred_bgm = like.obs().npred() # Assess quality based on a comparison between Npred and Nevents quality_bgm = npred_bgm - nevents # Write background fit results if self.logExplicit(): self.log.header3("Background model fit") self.log.parformat("log likelihood") self.log(LogL_bgm) self.log("\n") self.log.parformat("Number of predicted events") self.log(npred_bgm) self.log("\n") self.log.parformat("Fit quality") self.log(quality_bgm) self.log("\n") # Start over if the fit quality was bad if abs(quality_bgm) > 3.0: if self.logExplicit(): self.log( "Fit quality outside required range. Start over.\n") continue # Write model fit results if self.logExplicit(): for model in result_bgm: self.log.parformat("Model") self.log(model.name()) self.log("\n") for par in model: self.log(str(par) + "\n") # Fit background and test source sim.models(full_model) like = obsutils.fit(sim, log=self.m_log, debug=self.m_debug) result_all = like.obs().models().copy() LogL_all = like.opt().value() npred_all = like.obs().npred() ts = 2.0 * (LogL_bgm - LogL_all) # Assess quality based on a comparison between Npred and Nevents quality_all = npred_all - nevents # Write background and test source fit results if self.logExplicit(): self.log.header3("Background and test source model fit") self.log.parformat("Test statistics") self.log(ts) self.log("\n") self.log.parformat("log likelihood") self.log(LogL_all) self.log("\n") self.log.parformat("Number of predicted events") self.log(npred_all) self.log("\n") self.log.parformat("Fit quality") self.log(quality_all) self.log("\n") # for model in result_all: self.log.parformat("Model") self.log(model.name()) self.log("\n") for par in model: self.log(str(par) + "\n") # Start over if the fit quality was bad if abs(quality_all) > 3.0: if self.logExplicit(): self.log( "Fit quality outside required range. Start over.\n") continue # Start over if TS was non-positive if ts <= 0.0: if self.logExplicit(): self.log("Non positive TS. Start over.\n") continue # Get fitted Crab, photon and energy fluxes cflux = result_all["Test"]['Prefactor'].value() cflux_err = result_all["Test"]['Prefactor'].error() pflux = result_all["Test"].spectral().flux(emin, emax) eflux = result_all["Test"].spectral().eflux(emin, emax) # Compute differential sensitivity diffSens = pflux / erg_width * erg_mean * erg_mean # Compute flux correction factor based on average TS correct = 1.0 if self.m_use_ts: if ts > 0: correct = math.sqrt(self.m_ts_thres / ts) else: if cflux > 0 and cflux_err > 0: correct = math.sqrt(self.m_ts_thres) / (cflux / cflux_err) # Compute extrapolated fluxes flux = correct * cflux pflux = correct * pflux eflux = correct * eflux diffSens = correct * diffSens flux_value.append(flux) pflux_value.append(pflux) eflux_value.append(eflux) diffSens_value.append(diffSens) # Write background and test source fit results if self.logExplicit(): self.log.parformat("Photon flux") self.log(pflux) self.log(" ph/cm2/s\n") self.log.parformat("Energy flux") self.log(eflux) self.log(" erg/cm2/s\n") self.log.parformat("Crab flux") self.log(cflux * 1000.0) self.log(" mCrab\n") self.log.parformat("Differential sensitivity") self.log(diffSens) self.log(" erg/cm2/s\n") for model in result_all: self.log.parformat("Model") self.log(model.name()) self.log("\n") for par in model: self.log(str(par) + "\n") elif self.logTerse(): self.log.parformat("Iteration " + str(iter)) self.log("TS=") self.log(ts) self.log(" ") self.log("corr=") self.log(correct) self.log(" ") self.log(pflux) self.log(" ph/cm2/s = ") self.log(eflux) self.log(" erg/cm2/s = ") self.log(cflux * 1000.0) self.log(" mCrab = ") self.log(diffSens) self.log(" erg/cm2/s\n") # Compute sliding average of extrapolated fitted prefactor, # photon and energy flux. This damps out fluctuations and # improves convergence flux = 0.0 pflux = 0.0 eflux = 0.0 diffSens = 0.0 num = 0.0 for k in range(self.m_num_avg): inx = len(flux_value) - k - 1 if inx >= 0: flux += flux_value[inx] pflux += pflux_value[inx] eflux += eflux_value[inx] diffSens += diffSens_value[inx] num += 1.0 flux /= num pflux /= num eflux /= num diffSens /= num # Compare average flux to last average if iter > self.m_num_avg: if test_flux > 0: ratio = flux / test_flux # We have 2 convergence criteria: # 1. The average flux does not change # 2. The flux correction factor is small if ratio >= 0.99 and ratio <= 1.01 and \ correct >= 0.9 and correct <= 1.1: if self.logTerse(): self.log(" Converged (" + str(ratio) + ")\n") break else: if self.logTerse(): self.log(" Flux is zero.\n") break # Use average for next iteration test_flux = flux # Exit loop if number of trials exhausted if (iter >= self.m_max_iter): if self.logTerse(): self.log(" Test ended after " + str(self.m_max_iter) + " iterations.\n") break # Write fit results if self.logTerse(): self.log.header3("Fit results") self.log.parformat("Test statistics") self.log(ts) self.log("\n") self.log.parformat("Photon flux") self.log(pflux) self.log(" ph/cm2/s\n") self.log.parformat("Energy flux") self.log(eflux) self.log(" erg/cm2/s\n") self.log.parformat("Crab flux") self.log(cflux * 1000.0) self.log(" mCrab\n") self.log.parformat("Differential sensitivity") self.log(diffSens) self.log(" erg/cm2/s\n") self.log.parformat("Number of simulated events") self.log(nevents) self.log("\n") self.log.header3("Background and test source model fitting") self.log.parformat("log likelihood") self.log(LogL_all) self.log("\n") self.log.parformat("Number of predicted events") self.log(npred_all) self.log("\n") for model in result_all: self.log.parformat("Model") self.log(model.name()) self.log("\n") for par in model: self.log(str(par) + "\n") self.log.header3("Background model fit") self.log.parformat("log likelihood") self.log(LogL_bgm) self.log("\n") self.log.parformat("Number of predicted events") self.log(npred_bgm) self.log("\n") for model in result_bgm: self.log.parformat("Model") self.log(model.name()) self.log("\n") for par in model: self.log(str(par) + "\n") # Store result result = {'loge': loge, 'emin': emin.TeV(), 'emax': emax.TeV(), \ 'crab': flux, 'pflux': pflux, 'eflux': eflux, \ 'diffSens': diffSens} # Return result return result