def run(self): """Performs the spectrum extraction Returns ------- spectrum_observation : `~gammapy.spectrum.SpectrumObservation` Spectrum observation """ self.make_empty_vectors(self.bkg_estimate) self.extract_counts(self.bkg_estimate) aeff = extract_aeff(self.exposure, self.target_position, self.energy) if self.containment_correction: containment_factor = extract_psf_containment( self.psf, self.on_radius, self.energy ) aeff.data.data *= containment_factor edisp = extract_edisp(self.energy) self._aeff = aeff self._edisp = edisp return SpectrumObservation( on_vector=self._on_vector, aeff=self._aeff, off_vector=self._off_vector, edisp=self._edisp, )
def check_edisp_normalisation(): import matplotlib.pyplot as plt obs = SpectrumObservation.read(obs_path) p = obs.edisp.data.data.sum(axis=1) e = obs.edisp.data.axis("e_true").nodes plt.plot(e, p) plt.semilogx() plt.show()
def setup(self): self.model = PowerLaw( index=Quantity(2, ""), amplitude=Quantity(1e-11, "m-2 s-1 TeV-1"), reference=Quantity(1, "TeV") ) # TODO: simulate known spectrum instead of using this example: filename = "$GAMMAPY_EXTRA/datasets/hess-crab4_pha/pha_obs23523.fits" self.obs = SpectrumObservation.read(filename) self.seg = SpectrumEnergyGroupMaker(obs=self.obs) ebounds = [0.3, 1.001, 3, 10.001, 30] * u.TeV self.seg.compute_range_safe() self.seg.compute_groups_fixed(ebounds=ebounds) self.groups = self.seg.groups
def setup(self): self.model = PowerLaw( index=Quantity(2, ''), amplitude=Quantity(1e-11, 'm-2 s-1 TeV-1'), reference=Quantity(1, 'TeV'), ) # TODO: simulate known spectrum instead of using this example: filename = '$GAMMAPY_EXTRA/datasets/hess-crab4_pha/pha_obs23523.fits' self.obs = SpectrumObservation.read(filename) self.seg = SpectrumEnergyGroupMaker(obs=self.obs) ebounds = [0.3, 1.001, 3, 10.001, 30] * u.TeV self.seg.compute_range_safe() self.seg.compute_groups_fixed(ebounds=ebounds) self.groups = self.seg.groups
def fit_gammapy(): """ Current results Parameters: name value error unit min max frozen --------- --------- --------- --------------- --- --- ------ index 2.602e+00 1.555e-01 nan nan False amplitude 2.441e-11 3.452e-12 1 / (cm2 s TeV) nan nan False reference 1.000e+00 0.000e+00 TeV nan nan True Covariance: name/name index amplitude --------- -------- --------- index 0.0242 3.79e-13 amplitude 3.79e-13 1.19e-23 Statistic: -157.719 (cash) Fit Range: [1.0000000e+09 2.7825594e+10] keV """ obs = SpectrumObservation.read(obs_path) # obs.peek() # plt.show() model = PowerLaw( amplitude=1.23 * 1e-11 * u.Unit("cm-2 s-1 TeV-1"), reference=1 * u.Unit("TeV"), index=2.14 * u.Unit(""), ) fit = SpectrumFit(obs_list=obs, model=model, fit_range=energy_range, stat="cash") fit.run() print(fit.result[0]) pprint(fit.__dict__) obs = fit.obs_list[0] print(obs) print("This is fit_gammapy") obs.peek() import matplotlib.pyplot as plt plt.savefig("fit_gammapy.png")
def setup(self): pha = gammapy_extra.filename("datasets/hess-crab4_pha/pha_obs23592.fits") self.obs = SpectrumObservation.read(pha) self.best_fit_model = models.PowerLaw(index=2 * u.Unit(''), amplitude=1e-11 * u.Unit('cm-2 s-1 TeV-1'), reference=1 * u.TeV) self.npred = self.obs.predicted_counts(self.best_fit_model).data.value self.covar_axis = ['index', 'amplitude'] self.covar = np.diag([0.1 ** 2, 1e-12 ** 2]) self.fit_range = [0.1, 50] * u.TeV self.fit_result = SpectrumFitResult( model=self.best_fit_model, covariance=self.covar, covar_axis=self.covar_axis, fit_range=self.fit_range, statname='wstat', statval=42, npred=self.npred, obs=self.obs, )
def run(self): self.make_empty_vectors(self.bkg_estimate) self.extract_counts(self.bkg_estimate) aeff = extract_aeff(self.exposure, self.target_position, self.energy) containment_factor = extract_psf_containment( self.psf, self.on_radius, self.energy ) aeff.data.data *= containment_factor # Not the real Fermi-LAT EDISP # Use 5% energy resolution as approximation edisp = EnergyDispersion.from_gauss( e_true=self.energy, e_reco=self.energy, sigma=0.05, bias=0 ) return SpectrumObservation( on_vector=self._on_vector, aeff=aeff, off_vector=self._off_vector, edisp=edisp, )
def check_energy_binning_effects(): """Check how spectral fit results change with energy binnings. Actually this is still using the default: In [14]: print(analysis.extraction.observations[0].edisp) EnergyDispersion NDDataArray summary info e_true : size = 108, min = 0.010 TeV, max = 301.416 TeV e_reco : size = 72, min = 0.011 TeV, max = 93.804 TeV Data : size = 7776, min = 0.000, max = 1.000 But now, the fit results from SpectrumAnalysisIACT, which is just driving Fitspectrum, are different, almost the same as Sherpa. Current results Parameters: name value error unit min max frozen --------- --------- --------- --------------- --- --- ------ index 2.620e+00 1.540e-01 nan nan False amplitude 3.849e-11 5.407e-12 1 / (cm2 s TeV) nan nan False reference 1.000e+00 0.000e+00 TeV nan nan True Covariance: name/name index amplitude --------- -------- --------- index 0.0237 5.85e-13 amplitude 5.85e-13 2.92e-23 Statistic: -157.166 (cash) Fit Range: [ 1. 27.82559402] TeV ??? """ data_store = DataStore.from_dir("data/hess") obs_list = data_store.obs_list([23523]) on_region = CircleSkyRegion(conf.crab_position, conf.on_radius["hess"]) fp_binning = [1, 10, 30] * u.TeV exclusion_mask = get_exclusion_mask(conf.crab_position) model = PowerLaw( amplitude=1.23 * 1e-11 * u.Unit("cm-2 s-1 TeV-1"), reference=1 * u.Unit("TeV"), index=2.14 * u.Unit(""), ) cfg = dict( outdir=None, background=dict( on_region=on_region, exclusion_mask=exclusion_mask, # min_distance=0.1 * u.rad, ), extraction=dict(containment_correction=True), fit=dict( model=model, stat="cash", # forward_folded=True, fit_range=energy_range, ), fp_binning=fp_binning, ) analysis = SpectrumAnalysisIACT(obs_list, cfg) analysis.run() analysis.fit.est_errors() print("BEFORE", analysis.fit.result[0]) # print(analysis.extraction.observations[0].edisp) # pprint(analysis.fit.__dict__) # obs = analysis.fit.obs_list[0] # print(obs) # # import IPython; IPython.embed() # obs.peek() # import matplotlib.pyplot as plt # plt.savefig('check_energy_binning_effects.png') # print('This is check_energy_binning_effects') # Try to see if the I/O causes a change in results. analysis.extraction.observations.write("temp123") analysis.extraction.observations.write("temp123", use_sherpa=True) obs = SpectrumObservation.read("temp123/pha_obs23523.fits") model = PowerLaw( amplitude=1.23 * 1e-11 * u.Unit("cm-2 s-1 TeV-1"), reference=1 * u.Unit("TeV"), index=2.14 * u.Unit(""), ) fit = SpectrumFit(obs_list=obs, model=model, fit_range=energy_range, stat="cash") fit.run() print("AFTER", fit.result[0])
"""Compute flux points This is an example script that show how to compute flux points in Gammapy. TODO: Refactor and add to FluxPointsComputation class or so """ from gammapy.spectrum import (SpectrumObservation, SpectrumFit, FluxPoints, SpectrumResult) import astropy.units as u from astropy.table import Table import numpy as np import copy import matplotlib.pyplot as plt plt.style.use('ggplot') obs = SpectrumObservation.read( '$GAMMAPY_EXTRA/datasets/hess-crab4_pha/pha_obs23523.fits') fit = SpectrumFit(obs) fit.run() best_fit = copy.deepcopy(fit.result[0].fit) # Define Flux points binning emin = np.log10(obs.lo_threshold.to('TeV').value) emax = np.log10(40) binning = np.logspace(emin, emax, 8) * u.TeV # Fix index fit.model.gamma.freeze() # Fit norm in bands diff_flux = list()
aeff=aeff, edisp=edisp, livetime=livetime) bkg = 0.2 * npred.data alpha = 0.1 counts_kwargs = dict(energy=npred.energy, exposure=livetime, obs_id=31415, creator='Simulation', hi_threshold=50 * u.TeV, lo_threshold=lo_threshold) rand = get_random_state(42) on_counts = rand.poisson(npred.data) + rand.poisson(bkg) on_vector = PHACountsSpectrum(data=on_counts, backscal=1, **counts_kwargs) off_counts = rand.poisson(1. / alpha * bkg) off_vector = PHACountsSpectrum(data=off_counts, backscal=1. / alpha, is_bkg=True, **counts_kwargs) obs = SpectrumObservation(on_vector=on_vector, off_vector=off_vector, aeff=aeff, edisp=edisp) obs.write()
"""Test spectrum energy grouping. """ import warnings import astropy.units as u from gammapy.spectrum import SpectrumObservation, SpectrumEnergyGroupMaker warnings.filterwarnings('ignore') filename = '$GAMMAPY_EXTRA/datasets/hess-crab4_pha/pha_obs23523.fits' obs = SpectrumObservation.read(filename) table = obs.stats_table() seg = SpectrumEnergyGroupMaker(obs=obs) ebounds = [0.03, 1, 3, 10, 30] * u.TeV seg.compute_range_safe() seg.compute_groups_fixed(ebounds=ebounds) print('\nTable of original energy bins:') seg.table[['energy_group_idx', 'bin_idx', 'energy_min', 'energy_max']].pprint(max_lines=-1) print('\nTable of grouped energy bins:') seg.groups.to_group_table().pprint(max_lines=-1) print('\nTable of grouped energy bins:') seg.groups.to_total_table().pprint(max_lines=-1) print(seg)
from gammapy.spectrum import ( SpectrumObservation, SpectrumFit, DifferentialFluxPoints, SpectrumFitResult, SpectrumResult ) import astropy.units as u import numpy as np import copy import matplotlib.pyplot as plt plt.style.use('ggplot') obs = SpectrumObservation.read('$GAMMAPY_EXTRA/datasets/hess-crab4_pha/pha_obs23523.fits') fit = SpectrumFit(obs) fit.run() best_fit = copy.deepcopy(fit.result[0].fit) # Define Flux points binning emin = np.log10(obs.lo_threshold.to('TeV').value) emax = np.log10(40) binning = np.logspace(emin, emax, 8) * u.TeV # Fix index fit.model.gamma.freeze() # Fit norm in bands diff_flux = list()
def simulate_obs(perf, target, obs_param, obs_id=0, random_state='random-seed'): """Simulate observation with given parameters. Parameters ---------- perf : `~gammapy.scripts.CTAPerf` CTA performance target : `~gammapy.scripts.Target` Source obs_param : `~gammapy.scripts.ObservationParameters` Observation parameters obs_id : `int`, optional Observation Id random_state : {int, 'random-seed', 'global-rng', `~numpy.random.RandomState`} Defines random number generator initialisation. Passed to `~gammapy.utils.random.get_random_state`. """ livetime = obs_param.livetime alpha = obs_param.alpha.value emin = obs_param.emin emax = obs_param.emax model = target.model # Compute expected counts reco_energy = perf.bkg.energy bkg_rate_values = perf.bkg.data.data * livetime.to('s') predicted_counts = CountsPredictor(model=model, aeff=perf.aeff, livetime=livetime, edisp=perf.rmf) predicted_counts.run() npred = predicted_counts.npred # set negative values to zero (interpolation issue) idx = np.where(npred.data.data < 0.) npred.data.data[idx] = 0 # Randomise counts random_state = get_random_state(random_state) on_counts = random_state.poisson(npred.data.data.value) # excess bkg_counts = random_state.poisson( bkg_rate_values.value) # bkg in ON region off_counts = random_state.poisson(bkg_rate_values.value / alpha) # bkg in OFF region on_counts += bkg_counts # evts in ON region on_vector = PHACountsSpectrum( data=on_counts, backscal=1, energy_lo=reco_energy.lo, energy_hi=reco_energy.hi, ) on_vector.livetime = livetime off_vector = PHACountsSpectrum( energy_lo=reco_energy.lo, energy_hi=reco_energy.hi, data=off_counts, backscal=1. / alpha, is_bkg=True, ) off_vector.livetime = livetime obs = SpectrumObservation(on_vector=on_vector, off_vector=off_vector, aeff=perf.aeff, edisp=perf.rmf) obs.obs_id = obs_id # Set threshold according to the closest energy reco from bkg bins idx_min = np.abs(reco_energy.lo - emin).argmin() idx_max = np.abs(reco_energy.lo - emax).argmin() obs.lo_threshold = reco_energy.lo[idx_min] obs.hi_threshold = reco_energy.lo[idx_max] return obs
# MODEL model = PowerLaw(index=2.3 * u.Unit(""), amplitude=2.5 * 1e-12 * u.Unit("cm-2 s-1 TeV-1"), reference=1 * u.TeV) # COUNTS livetime = 2 * u.h npred = calculate_predicted_counts(model=model, aeff=aeff, edisp=edisp, livetime=livetime) bkg = 0.2 * npred.data alpha = 0.1 counts_kwargs = dict( energy=npred.energy, exposure=livetime, obs_id=31415, creator="Simulation", hi_threshold=50 * u.TeV, lo_threshold=lo_threshold, ) rand = get_random_state(42) on_counts = rand.poisson(npred.data) + rand.poisson(bkg) on_vector = PHACountsSpectrum(data=on_counts, backscal=1, **counts_kwargs) off_counts = rand.poisson(1.0 / alpha * bkg) off_vector = PHACountsSpectrum(data=off_counts, backscal=1.0 / alpha, is_bkg=True, **counts_kwargs) obs = SpectrumObservation(on_vector=on_vector, off_vector=off_vector, aeff=aeff, edisp=edisp) obs.write()
def simulate_obs(perf, target, obs_param, obs_id=0, random_state='random-seed'): """Simulate observation with given parameters. Parameters ---------- perf : `~gammapy.scripts.CTAPerf` CTA performance target : `~gammapy.scripts.Target` Source obs_param : `~gammapy.scripts.ObservationParameters` Observation parameters obs_id : `int`, optional Observation Id random_state : {int, 'random-seed', 'global-rng', `~numpy.random.RandomState`} Defines random number generator initialisation. Passed to `~gammapy.utils.random.get_random_state`. """ livetime = obs_param.livetime alpha = obs_param.alpha.value emin = obs_param.emin emax = obs_param.emax model = target.model # Compute expected counts reco_energy = perf.bkg.energy bkg_rate_values = perf.bkg.data.data * livetime.to('s') predicted_counts = CountsPredictor(model=model, aeff=perf.aeff, livetime=livetime, edisp=perf.rmf) predicted_counts.run() npred = predicted_counts.npred # set negative values to zero (interpolation issue) idx = np.where(npred.data.data < 0.) npred.data.data[idx] = 0 # Randomise counts random_state = get_random_state(random_state) on_counts = random_state.poisson(npred.data.data.value) # excess bkg_counts = random_state.poisson(bkg_rate_values.value) # bkg in ON region off_counts = random_state.poisson(bkg_rate_values.value / alpha) # bkg in OFF region on_counts += bkg_counts # evts in ON region on_vector = PHACountsSpectrum( data=on_counts, backscal=1, energy_lo=reco_energy.lo, energy_hi=reco_energy.hi, ) on_vector.livetime = livetime off_vector = PHACountsSpectrum(energy_lo=reco_energy.lo, energy_hi=reco_energy.hi, data=off_counts, backscal=1. / alpha, is_bkg=True, ) off_vector.livetime = livetime obs = SpectrumObservation(on_vector=on_vector, off_vector=off_vector, aeff=perf.aeff, edisp=perf.rmf) obs.obs_id = obs_id # Set threshold according to the closest energy reco from bkg bins idx_min = np.abs(reco_energy.lo - emin).argmin() idx_max = np.abs(reco_energy.lo - emax).argmin() obs.lo_threshold = reco_energy.lo[idx_min] obs.hi_threshold = reco_energy.lo[idx_max] return obs
lw=2, label=name) ax.step(x[start:stop], bkg_counts[start:stop], where='post', lw=1, color=line.get_color(), alpha=0.5) return ax fig, ax = plt.subplots(1, 1) # filenames = glob.glob('./plots/data/joint_crab/spectra/magic/pha_*.fits') filenames = glob.glob('./build/pymc_results/spectra/magic/pha_*.fits') obs = [SpectrumObservation.read(f) for f in filenames] plot_counts(ax, obs, 'MAGIC') filenames = glob.glob('./build/pymc_results/spectra/fact/pha_*.fits') obs = [SpectrumObservation.read(f) for f in filenames] plot_counts(ax, obs, 'FACT') filenames = glob.glob('./build/pymc_results/spectra/veritas/pha_*.fits') obs = [SpectrumObservation.read(f) for f in filenames] plot_counts(ax, obs, 'VERITAS') filenames = glob.glob('./build/pymc_results/spectra/hess/pha_*.fits') obs = [SpectrumObservation.read(f) for f in filenames] plot_counts(ax, obs, 'H.E.S.S') ax.legend()
from gammapy.spectrum import SpectrumFit, SpectrumObservation, SpectrumFitResult import matplotlib.pyplot as plt import astropy.units as u obs = SpectrumObservation.read('pha_obs31415.fits') fit = SpectrumFit(obs) obs.peek() plt.savefig('observation.png') plt.cla() fit.run() fit.result[0].plot_fit() plt.savefig('debug_fit.png') # TODO: implement properly plt.cla() fig = plt.figure() ax = fig.add_subplot(111) fit.result[0].fit.plot_butterfly(ax=ax, label='Fit result') input_parameters = dict(index = 2.3 * u.Unit(''), norm = 2.5 * 1e-12 * u.Unit('cm-2 s-1 TeV-1'), reference = 1 * u.TeV) input_parameter_errors = dict(index = 0 * u.TeV, norm = 0 * u.Unit('cm-2 s-1 TeV-1'), reference = 0 * u.TeV) input_model = SpectrumFitResult(spectral_model = 'PowerLaw', parameters = input_parameters, parameter_errors = input_parameter_errors)
def main(): #Low energy of spectral fitting range. lo_fit_energ = 0.1 * u.Unit('TeV') hi_fit_energ = 10 * u.Unit('TeV') #If you want an internal estimation of a high energy limit for the fitting range: est_hi_lim = 'yes'. If 'no' the hi_fit_energ will be used. est_hi_lim = 'yes' # Read ON and OFF cubes filename_on = 'non_cube.fits.gz' # non_cube_convolved.fits cube_on = SkyCube.read(filename_on) ann_filename_off = 'noff_withpuls_cube.fits.gz' ann_cube_off = SkyCube.read(ann_filename_off) circ_filename_off = 'noff_withneb_cube.fits.gz' circ_cube_off = SkyCube.read(circ_filename_off) # Read config and IRFs config = read_config('config.yaml') irfs = get_irfs(config) offset = Angle(config['selection']['offset_fov'] * u.deg) livetime = u.Quantity(config['pointing']['livetime']).to('second') alpha_obs = 1. binsz = config['binning']['binsz'] aeff = irfs['aeff'].to_effective_area_table(offset = offset, energy = cube_on.energies('edges')) edisp = irfs['edisp'].to_energy_dispersion(offset = offset, e_true = aeff.energy.bins, e_reco = cube_on.energies('edges') ) # Define circular on/off Regions parameters on_pos = SkyCoord(83.6333 * u.deg, 22.0144 * u.deg, frame='icrs') on_sizes = np.ones(20) * binsz * u.deg off_pos = SkyCoord(83.6333 * u.deg, 22.0144 * u.deg, frame='icrs') off_sizes = on_sizes * np.sqrt(1./alpha_obs) # Make Annular region on_rad_sizes = np.ones(len(on_sizes)) * 0.1 * binsz * u.deg off_rad_sizes = on_rad_sizes * np.sqrt(1./alpha_obs) widths = np.ones(len(on_sizes)) * 22 * binsz * u.deg out_rad_sizes = on_rad_sizes + widths ann_on_data, ann_off_data, ann_stats = make_annular_spectrum(on_pos, off_pos, on_rad_sizes, off_rad_sizes, out_rad_sizes, cube_on, ann_cube_off, alpha_obs) # Make circular region circ_on_data, circ_off_data, circ_stats = make_circular_spectrum(on_pos, off_pos, on_sizes, off_sizes, cube_on, circ_cube_off, alpha_obs) # Undo "holes" in circ/ann_stats if np.max(np.where(circ_stats == 1)) + 1 != circ_stats.sum(): circ_stats[0:np.max(np.where(circ_stats == 1)) + 1][circ_stats[0:np.max(np.where(circ_stats == 1)) + 1] == 0] = 1. if np.max(np.where(ann_stats == 1)) + 1 != ann_stats.sum(): ann_stats[0:np.max(np.where(ann_stats == 1)) + 1][ann_stats[0:np.max(np.where(ann_stats == 1)) + 1] == 0] = 1. # Make on/off vector ann_on_vector = PHACountsSpectrum(energy_lo = cube_on.energies('edges')[:-1], energy_hi= cube_on.energies('edges')[1:], data= ann_on_data['value'].data * ann_stats * u.ct, backscal = on_sizes[0].value, meta={'EXPOSURE' : livetime.value}) circ_on_vector = PHACountsSpectrum(energy_lo = cube_on.energies('edges')[:-1], energy_hi= cube_on.energies('edges')[1:], data= circ_on_data['value'].data * circ_stats * u.ct, backscal = on_sizes[0].value, meta={'EXPOSURE' : livetime.value}) ann_off_vector = PHACountsSpectrum(energy_lo = ann_cube_off.energies('edges')[:-1], energy_hi= ann_cube_off.energies('edges')[1:], data= ann_off_data['value'].data * ann_stats * u.ct, backscal = off_sizes[0].value, meta={'EXPOSURE' : livetime.value, 'OFFSET' : 0.3 * u.deg}) circ_off_vector = PHACountsSpectrum(energy_lo = circ_cube_off.energies('edges')[:-1], energy_hi= circ_cube_off.energies('edges')[1:], data= circ_off_data['value'].data * circ_stats * u.ct, backscal = off_sizes[0].value, meta={'EXPOSURE' : livetime.value, 'OFFSET' : 0.3 * u.deg}) # Make SpectrumObservation ann_sed_table = SpectrumObservation(on_vector = ann_on_vector, off_vector = ann_off_vector, aeff = aeff, edisp = edisp) circ_sed_table = SpectrumObservation(on_vector = circ_on_vector, off_vector = circ_off_vector, aeff = aeff, edisp = edisp) ##Debug #print(ann_stats) #print(circ_stats) # Define Spectral Model model2fit1 = LogParabola(amplitude=1e-11 * u.Unit('cm-2 s-1 TeV-1'), reference=1 * u.TeV, alpha=2.5 * u.Unit(''), beta=0.1 * u.Unit('')) model2fit2 = ExponentialCutoffPowerLaw(index = 1. * u.Unit(''), amplitude = 1e-11 * u.Unit('cm-2 s-1 TeV-1'), reference= 1 * u.TeV, lambda_= 0. * u.Unit('TeV-1')) model2fit3 = PowerLaw(index= 2.5 * u.Unit(''), amplitude= 5e-11 * u.Unit('cm-2 s-1 TeV-1'), reference= 0.15 * u.TeV) model2fit3.parameters['amplitude'].parmin = 1e-12 model2fit3.parameters['amplitude'].parmax = 1e-10 model2fit3.parameters['index'].parmin = 2.0 model2fit3.parameters['index'].parmax = 4.0 #Models to fit the circular and annular observations models_ann_fit = [model2fit1, model2fit2, model2fit3] models_circ_fit = [model2fit1, model2fit2, model2fit3] # Fit if est_hi_lim = 'yes': hi_fit_energ = cube_on.energies('edges')[int(np.sum(ann_stats))]