Esempio n. 1
0
 # Remove any existing result files
 list = [glob.glob("*.fits"), glob.glob("*.log"), glob.glob("*.xml")]
 for files in list:
     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)
 
Esempio n. 2
0
	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
Esempio n. 3
0
	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
Esempio n. 4
0
	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()
	
Esempio n. 5
0
    # Remove any existing result files
    list = [glob.glob("*.fits"), glob.glob("*.log"), glob.glob("*.xml")]
    for files in list:
        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)
Esempio n. 6
0
    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
Esempio n. 7
0
	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
Esempio n. 8
0
    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
Esempio n. 9
0
    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