def cmp_pha_intro(fit_result, p1, covarerr): assert fit_result.statval == approx(37.9079, rel=1e-4) assert fit_result.rstat == approx(0.902569, rel=1e-4) assert fit_result.qval == approx(0.651155, rel=1e-4) self.assertEqual(fit_result.nfev, 22) self.assertEqual(fit_result.numpoints, 44) self.assertEqual(fit_result.dof, 42) p1.gamma.val == approx(2.15852, rel=1e-4) p1.ampl.val == approx(0.00022484, rel=1e-4) assert ui.calc_photon_flux() == approx(0.000469964, rel=1e-4) assert ui.calc_energy_flux() == approx(9.614847e-13, rel=1e-4) assert ui.calc_data_sum() == approx(706.85714092, rel=1e-4) assert ui.calc_model_sum() == approx(638.45693377, rel=1e-4) assert ui.calc_source_sum() == approx(0.046996409, rel=1e-4) calc = ui.eqwidth(self.locals['p1'], ui.get_source()) assert calc == approx(-0.57731725, rel=1e-4) calc = ui.calc_kcorr([1, 1.2, 1.4, 1.6, 1.8, 2], 0.5, 2) # Prior to fixing #619 the expected values were # expected = [0.93341286, 0.93752836, 0.94325233, # 0.94990140, 0.95678054, 0.96393515] expected = [0.93132747, 0.9352768, 0.94085917, 0.94738472, 0.95415463, 0.96121113] assert calc == approx(expected, rel=1e-4)
def test_pha_intro(self): self.run_thread('pha_intro') # astro.ui imported as ui, instead of # being in global namespace self.assertEqualWithinTol(ui.get_fit_results().statval, 37.9079, 1e-4) self.assertEqualWithinTol(ui.get_fit_results().rstat, 0.902569, 1e-4) self.assertEqualWithinTol(ui.get_fit_results().qval, 0.651155, 1e-4) self.assertEqualWithinTol(self.locals['p1'].gamma.val, 2.15852, 1e-4) self.assertEqualWithinTol(self.locals['p1'].ampl.val, 0.00022484, 1e-4) self.assertEqualWithinTol(ui.calc_photon_flux(), 0.000469964, 1e-4) self.assertEqualWithinTol(ui.calc_energy_flux(), 9.614847e-13, 1e-4) self.assertEqualWithinTol(ui.calc_data_sum(), 706.85714092, 1e-4) self.assertEqualWithinTol(ui.calc_model_sum(), 638.45693377, 1e-4) self.assertEqualWithinTol(ui.calc_source_sum(), 0.046996409, 1e-4) self.assertEqualWithinTol( ui.eqwidth(self.locals['p1'], ui.get_source()), -0.57731725, 1e-4) self.assertEqualWithinTol( ui.calc_kcorr([1, 1.2, 1.4, 1.6, 1.8, 2], 0.5, 2), [ 0.93341286, 0.93752836, 0.94325233, 0.94990140, 0.95678054, 0.96393515 ], 1e-4) self.assertEqual(ui.get_fit_results().nfev, 22) self.assertEqual(ui.get_fit_results().numpoints, 44) self.assertEqual(ui.get_fit_results().dof, 42)
def test_pha_intro(self): self.run_thread("pha_intro") # astro.ui imported as ui, instead of # being in global namespace self.assertEqualWithinTol(ui.get_fit_results().statval, 37.9079, 1e-4) self.assertEqualWithinTol(ui.get_fit_results().rstat, 0.902569, 1e-4) self.assertEqualWithinTol(ui.get_fit_results().qval, 0.651155, 1e-4) self.assertEqualWithinTol(self.locals["p1"].gamma.val, 2.15852, 1e-4) self.assertEqualWithinTol(self.locals["p1"].ampl.val, 0.00022484, 1e-4) self.assertEqualWithinTol(ui.calc_photon_flux(), 0.000469964, 1e-4) self.assertEqualWithinTol(ui.calc_energy_flux(), 9.614847e-13, 1e-4) self.assertEqualWithinTol(ui.calc_data_sum(), 706.85714092, 1e-4) self.assertEqualWithinTol(ui.calc_model_sum(), 638.45693377, 1e-4) self.assertEqualWithinTol(ui.calc_source_sum(), 0.046996409, 1e-4) self.assertEqualWithinTol(ui.eqwidth(self.locals["p1"], ui.get_source()), -0.57731725, 1e-4) self.assertEqualWithinTol( ui.calc_kcorr([1, 1.2, 1.4, 1.6, 1.8, 2], 0.5, 2), [0.93341286, 0.93752836, 0.94325233, 0.94990140, 0.95678054, 0.96393515], 1e-4, ) self.assertEqual(ui.get_fit_results().nfev, 22) self.assertEqual(ui.get_fit_results().numpoints, 44) self.assertEqual(ui.get_fit_results().dof, 42)
def cmp_thread(fit_result, p1, covarerr): assert fit_result.statval == approx(37.9079, rel=1e-4) assert fit_result.rstat == approx(0.902569, rel=1e-4) assert fit_result.qval == approx(0.651155, rel=1e-4) assert fit_result.nfev == 22 assert fit_result.numpoints == 44 assert fit_result.dof == 42 p1.gamma.val == approx(2.15852, rel=1e-4) p1.ampl.val == approx(0.00022484, rel=1e-4) assert ui.calc_photon_flux() == approx(0.000469964, rel=1e-4) assert ui.calc_energy_flux() == approx(9.614847e-13, rel=1e-4) assert ui.calc_data_sum() == approx(706.85714092, rel=1e-4) assert ui.calc_model_sum() == approx(638.45693377, rel=1e-4) assert ui.calc_source_sum() == approx(0.046996409, rel=1e-4) calc = ui.eqwidth(p1, ui.get_source()) assert calc == approx(-0.57731725, rel=1e-4) calc = ui.calc_kcorr([1, 1.2, 1.4, 1.6, 1.8, 2], 0.5, 2) expected = [ 0.93132747, 0.9352768, 0.94085917, 0.94738472, 0.95415463, 0.96121113 ] assert calc == approx(expected, rel=1e-4)
def test_pha_intro(self): self.run_thread('pha_intro') # astro.ui imported as ui, instead of # being in global namespace fit_results = ui.get_fit_results() covarerr = sqrt(fit_results.extra_output['covar'].diagonal()) assert covarerr[0] == approx(0.0790393, rel=1e-4) assert covarerr[1] == approx(1.4564e-05, rel=1e-4) assert fit_results.statval == approx(37.9079, rel=1e-4) assert fit_results.rstat == approx(0.902569, rel=1e-4) assert fit_results.qval == approx(0.651155, rel=1e-4) assert self.locals['p1'].gamma.val == approx(2.15852, rel=1e-4) assert self.locals['p1'].ampl.val == approx(0.00022484, rel=1e-4) assert ui.calc_photon_flux() == approx(0.000469964, rel=1e-4) assert ui.calc_energy_flux() == approx(9.614847e-13, rel=1e-4) assert ui.calc_data_sum() == approx(706.85714092, rel=1e-4) assert ui.calc_model_sum() == approx(638.45693377, rel=1e-4) assert ui.calc_source_sum() == approx(0.046996409, rel=1e-4) calc = ui.eqwidth(self.locals['p1'], ui.get_source()) assert calc == approx(-0.57731725, rel=1e-4) calc = ui.calc_kcorr([1, 1.2, 1.4, 1.6, 1.8, 2], 0.5, 2) expected = [0.93341286, 0.93752836, 0.94325233, 0.94990140, 0.95678054, 0.96393515] assert calc == approx(expected, rel=1e-4) self.assertEqual(ui.get_fit_results().nfev, 22) self.assertEqual(ui.get_fit_results().numpoints, 44) self.assertEqual(ui.get_fit_results().dof, 42)
def fit_sherpa(obsid_list, redshift, nH_Gal, energy, min_counts=25, kT_guess=3, Ab_guess=1, fix_nH_Gal=True, fix_abund=False, find_errors=True): spectra = [] for obs in obsid_list: temp = glob.glob('xaf_*_' + obs + '.pi') # get spectra of regions spectra.append( temp ) # spectra will be made of lists which have xaf_*_obs.pi filenames - access with spectra[i][j] spectra.sort() num_obs = len(obsid_list) num_reg = len(temp) filename = 'spectra_wabs_mekal.dat' results_file = open(filename, "w") results_file.write( '# Fit results for wabs*mekal (zeros indicate that no fitting was performed)\n' ) results_file.write( '# Reg_no. kT kT_loerr kT_hierr Z Z_loerr Z_hierr norm norm_loerr norm_hierr nH_Gal nH_loerr nH_hierr red_chisq total_counts num_bins\n' ) for i in range(num_reg): sherpa.clean() # clean everything cnts = numpy.zeros( num_obs ) # make array of zeros with index length same as num_obs to store counts max_rate = numpy.zeros(num_obs) # max count rate [counts/s/keV] data_set = 0 # data set number good_src_ids = numpy.zeros(num_obs, dtype=int) - 1 for j in range(num_obs): sherpa.load_pha( data_set, spectra[j] [i]) # load xaf_#_obs_####.pi and .arf and .rmf files. sherpa.ignore_id(data_set, 0.0, energy[0]) sherpa.ignore_id(data_set, energy[1], None) cnts[j] = sherpa.calc_data_sum(energy[0], energy[1], data_set) cnt_rate = sherpa.get_rate(data_set, filter=True) if len(cnt_rate) == 0: max_rate[ j] = 0.0 # when few counts (<50), get_rate can return zero-length array else: max_rate[j] = numpy.max(cnt_rate) sherpa.subtract(data_set) # subtract background sherpa.set_source( data_set, sherpa.xswabs.abs1 * sherpa.xsmekal.plsm1) # 1 temperature mekal model fit good_src_ids[j] = data_set data_set += 1 # same run for region but different obs # Filter out ignored obs good_src_ids_indx = numpy.where(good_src_ids >= 0) good_src_ids = good_src_ids[good_src_ids_indx] max_rate = max_rate[good_src_ids_indx] cnts = cnts[good_src_ids_indx] totcnts = numpy.sum(cnts) if totcnts >= min_counts: print('Fitting spectra in region: ' + str(i)) abs1.nH = nH_Gal abs1.cache = 0 if fix_nH_Gal: sherpa.freeze(abs1.nH) else: sherpa.thaw(abs1.nH) plsm1.kt = kT_guess sherpa.thaw(plsm1.kt) plsm1.Abundanc = Ab_guess if fix_abund: sherpa.freeze(plsm1.Abundanc) else: sherpa.thaw(plsm1.Abundanc) plsm1.redshift = redshift sherpa.freeze(plsm1.redshift) plsm1.cache = 0 sherpa.fit() fit_result = sherpa.get_fit_results() red_chi2 = fit_result.rstat num_bins = fit_result.numpoints if fix_nH_Gal: nH = nH_Gal kT = fit_result.parvals[0] if fix_abund: Z = Ab_guess norm = fit_result.parvals[1] else: Z = fit_result.parvals[1] norm = fit_result.parvals[2] else: nH = fit_result.parvals[0] kT = fit_result.parvals[1] if fix_abund: Z = Ab_guess norm = fit_result.parvals[2] else: Z = fit_result.parvals[2] norm = fit_result.parvals[3] del fit_result if find_errors: sherpa.covar() covar_result = sherpa.get_covar_results() if fix_nH_Gal: nH_loerr = 0.0 nH_hierr = 0.0 kT_loerr = covar_result.parmins[0] kT_hierr = covar_result.parmaxes[0] if fix_abund: Z_loerr = 0.0 Z_hierr = 0.0 norm_loerr = covar_result.parmins[1] norm_hierr = covar_result.parmaxes[1] else: Z_loerr = covar_result.parmins[1] Z_hierr = covar_result.parmaxes[1] norm_loerr = covar_result.parmins[2] norm_hierr = covar_result.parmaxes[2] else: nH_loerr = covar_result.parmins[0] nH_hierr = covar_result.parmaxes[0] kT_loerr = covar_result.parmins[1] kT_hierr = covar_result.parmaxes[1] if fix_abund: Z_loerr = 0.0 Z_hierr = 0.0 norm_loerr = covar_result.parmins[2] norm_hierr = covar_result.parmaxes[2] else: Z_loerr = covar_result.parmins[2] Z_hierr = covar_result.parmaxes[2] norm_loerr = covar_result.parmins[3] norm_hierr = covar_result.parmaxes[3] del covar_result # Check for failed errors (= None) and set them to +/- best-fit value if not fix_nH_Gal: if nH_loerr is None: nH_loerr = -nH # is was == if nH_hierr is None: nH_hierr = nH if kT_loerr is None: kT_loerr = -kT if kT_hierr is None: kT_hierr = kT if not fix_abund: if Z_loerr is None: Z_loerr = -Z if Z_hierr is None: Z_hierr = Z if norm_loerr is None: norm_loerr = -norm if norm_hierr is None: norm_hierr = norm else: kT_loerr = 0.0 Z_loerr = 0.0 nH_loerr = 0.0 norm_loerr = 0.0 kT_hierr = 0.0 Z_hierr = 0.0 nH_hierr = 0.0 norm_hierr = 0.0 else: # if total counts < min_counts, just write zeros print('\n Warning: no fit performed for for region: ' + str(i)) print( '\n Spectra have insufficient counts after filtering or do not exist.' ) print('\n --> All parameters for this region set to 0.0.') kT = 0.0 Z = 0.0 nH = 0.0 norm = 0.0 kT_loerr = 0.0 Z_loerr = 0.0 nH_loerr = 0.0 norm_loerr = 0.0 kT_hierr = 0.0 Z_hierr = 0.0 nH_hierr = 0.0 norm_hierr = 0.0 red_chi2 = 0.0 num_bins = 0 reg_id = spectra[0][i].split( '_' ) # Splits string after every underscore so that region number can be accessed. reg_id[1] is accessed because that is the region number after 'xaf' results_file.write( '%7r %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %6.4e %6.4e %6.4e %7.4f %7.4f %7.4f %7.4f %8.1f %8r\n' % (int(reg_id[1]), kT, kT_loerr, kT_hierr, Z, Z_loerr, Z_hierr, norm, norm_loerr, norm_hierr, nH, nH_loerr, nH_hierr, red_chi2, totcnts, num_bins)) # Write all data to a file results_file.close()
def fit_sherpa(obsid_list, redshift, nH_Gal, energy, min_counts=25, kT_guess=3, Ab_guess=1, fix_nH_Gal=True, fix_abund=False, find_errors=True): spectra = [] for obs in obsid_list: temp = glob.glob('xaf_*_' + obs + '.pi') # get spectra of regions spectra.append(temp) # spectra will be made of lists which have xaf_*_obs.pi filenames - access with spectra[i][j] spectra.sort() num_obs = len(obsid_list) num_reg = len(temp) filename = 'spectra_wabs_mekal.dat' results_file = open(filename, "w") results_file.write('# Fit results for wabs*mekal (zeros indicate that no fitting was performed)\n') results_file.write('# Reg_no. kT kT_loerr kT_hierr Z Z_loerr Z_hierr norm norm_loerr norm_hierr nH_Gal nH_loerr nH_hierr red_chisq total_counts num_bins\n') for i in range(num_reg): sherpa.clean() # clean everything cnts = numpy.zeros(num_obs) # make array of zeros with index length same as num_obs to store counts max_rate = numpy.zeros(num_obs) # max count rate [counts/s/keV] data_set = 0 # data set number good_src_ids = numpy.zeros(num_obs, dtype=int) - 1 for j in range(num_obs): sherpa.load_pha(data_set, spectra[j][i]) # load xaf_#_obs_####.pi and .arf and .rmf files. sherpa.ignore_id(data_set, 0.0, energy[0]) sherpa.ignore_id(data_set, energy[1], None) cnts[j] = sherpa.calc_data_sum(energy[0], energy[1], data_set) cnt_rate = sherpa.get_rate(data_set, filter=True) if len(cnt_rate) == 0: max_rate[j] = 0.0 # when few counts (<50), get_rate can return zero-length array else: max_rate[j] = numpy.max(cnt_rate) sherpa.subtract(data_set) # subtract background sherpa.set_source(data_set, sherpa.xswabs.abs1 * sherpa.xsmekal.plsm1) # 1 temperature mekal model fit good_src_ids[j] = data_set data_set += 1 # same run for region but different obs # Filter out ignored obs good_src_ids_indx = numpy.where(good_src_ids >= 0) good_src_ids = good_src_ids[good_src_ids_indx] max_rate = max_rate[good_src_ids_indx] cnts = cnts[good_src_ids_indx] totcnts = numpy.sum(cnts) if totcnts >= min_counts: print('Fitting spectra in region: ' + str(i)) abs1.nH = nH_Gal abs1.cache = 0 if fix_nH_Gal: sherpa.freeze(abs1.nH) else: sherpa.thaw(abs1.nH) plsm1.kt = kT_guess sherpa.thaw(plsm1.kt) plsm1.Abundanc = Ab_guess if fix_abund: sherpa.freeze(plsm1.Abundanc) else: sherpa.thaw(plsm1.Abundanc) plsm1.redshift = redshift sherpa.freeze(plsm1.redshift) plsm1.cache = 0 sherpa.fit() fit_result = sherpa.get_fit_results() red_chi2 = fit_result.rstat num_bins = fit_result.numpoints if fix_nH_Gal: nH = nH_Gal kT = fit_result.parvals[0] if fix_abund: Z = Ab_guess norm = fit_result.parvals[1] else: Z = fit_result.parvals[1] norm = fit_result.parvals[2] else: nH = fit_result.parvals[0] kT = fit_result.parvals[1] if fix_abund: Z = Ab_guess norm = fit_result.parvals[2] else: Z = fit_result.parvals[2] norm = fit_result.parvals[3] del fit_result if find_errors: sherpa.covar() covar_result = sherpa.get_covar_results() if fix_nH_Gal: nH_loerr = 0.0 nH_hierr = 0.0 kT_loerr = covar_result.parmins[0] kT_hierr = covar_result.parmaxes[0] if fix_abund: Z_loerr = 0.0 Z_hierr = 0.0 norm_loerr = covar_result.parmins[1] norm_hierr = covar_result.parmaxes[1] else: Z_loerr = covar_result.parmins[1] Z_hierr = covar_result.parmaxes[1] norm_loerr = covar_result.parmins[2] norm_hierr = covar_result.parmaxes[2] else: nH_loerr = covar_result.parmins[0] nH_hierr = covar_result.parmaxes[0] kT_loerr = covar_result.parmins[1] kT_hierr = covar_result.parmaxes[1] if fix_abund: Z_loerr = 0.0 Z_hierr = 0.0 norm_loerr = covar_result.parmins[2] norm_hierr = covar_result.parmaxes[2] else: Z_loerr = covar_result.parmins[2] Z_hierr = covar_result.parmaxes[2] norm_loerr = covar_result.parmins[3] norm_hierr = covar_result.parmaxes[3] del covar_result # Check for failed errors (= None) and set them to +/- best-fit value if not fix_nH_Gal: if nH_loerr is None: nH_loerr = -nH # is was == if nH_hierr is None: nH_hierr = nH if kT_loerr is None: kT_loerr = -kT if kT_hierr is None: kT_hierr = kT if not fix_abund: if Z_loerr is None: Z_loerr = -Z if Z_hierr is None: Z_hierr = Z if norm_loerr is None: norm_loerr = -norm if norm_hierr is None: norm_hierr = norm else: kT_loerr = 0.0 Z_loerr = 0.0 nH_loerr = 0.0 norm_loerr = 0.0 kT_hierr = 0.0 Z_hierr = 0.0 nH_hierr = 0.0 norm_hierr = 0.0 else: # if total counts < min_counts, just write zeros print('\n Warning: no fit performed for for region: ' + str(i)) print('\n Spectra have insufficient counts after filtering or do not exist.') print('\n --> All parameters for this region set to 0.0.') kT = 0.0 Z = 0.0 nH = 0.0 norm = 0.0 kT_loerr = 0.0 Z_loerr = 0.0 nH_loerr = 0.0 norm_loerr = 0.0 kT_hierr = 0.0 Z_hierr = 0.0 nH_hierr = 0.0 norm_hierr = 0.0 red_chi2 = 0.0 num_bins = 0 reg_id = spectra[0][i].split('_') # Splits string after every underscore so that region number can be accessed. reg_id[1] is accessed because that is the region number after 'xaf' results_file.write('%7r %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %6.4e %6.4e %6.4e %7.4f %7.4f %7.4f %7.4f %8.1f %8r\n' % (int(reg_id[1]), kT, kT_loerr, kT_hierr, Z, Z_loerr, Z_hierr, norm, norm_loerr, norm_hierr, nH, nH_loerr, nH_hierr, red_chi2, totcnts, num_bins)) # Write all data to a file results_file.close()