def test_proj_bubble(self): def cmp_proj_bubble(mylocals, convarerr, proj, conf): mek1 = mylocals['mek1'] assert covarerr[0] == approx(0, rel=1e-4) assert covarerr[1] == approx(8.74608e-07, rel=1e-3) assert mek1.kt.val == approx(17.8849, rel=1e-2) assert mek1.norm.val == approx(4.15418e-06, rel=1e-2) # Proj -- Upper bound of kT can't be found # assert proj.parmins[0] == approx(-12.048069, rel=0.01) assert proj.parmins[1] == approx(-9.510913e-07, rel=0.01) assert proj.parmaxes[1] == approx(2.403640e-06, rel=0.01) assert proj.parmaxes[0] is None assert conf.parmins[0] == approx(-12.1073, rel=0.01) assert conf.parmaxes[0] == approx(62.0585, rel=0.01) assert conf.parmins[1] == approx(-9.5568e-07, rel=0.01) assert conf.parmaxes[1] == approx(2.39937e-06, rel=0.01) self.run_thread('proj_bubble') fit_results = ui.get_fit_results() covarerr = sqrt(fit_results.extra_output['covar'].diagonal()) proj = ui.get_proj_results() conf = ui.get_conf_results() cmp_proj_bubble(self.locals, covarerr, proj, conf) self.run_thread('proj_bubble_ncpus') fit_results = ui.get_fit_results() covarerr = sqrt(fit_results.extra_output['covar'].diagonal()) proj = ui.get_proj_results() conf = ui.get_conf_results() cmp_proj_bubble(self.locals, covarerr, proj, conf)
def fit(self, conf = False): ui.ignore(None, None) ui.notice(self.start, self.stop) self.set_source() ui.fit(1) if conf: ui.conf() res = ui.get_fit_results() for line in (self.H2lines + self.nonH2lines): sourcename = line['source'].split('.')[1] print sourcename for p in ['pos', 'fwhm', 'ampl']: n = '{0}.{1}'.format(sourcename, p) _place_val(line, p, ui.get_par(n).val) self.const = ui.get_par('c1.c0').val self.redchi2 = res.rstat if conf: res = ui.get_conf_results() for line in (self.H2lines + self.nonH2lines): sourcename = line['source'].split('.')[1] for p in ['pos', 'fwhm', 'ampl']: n = '{0}.{1}'.format(sourcename, p) parmin, parmax = _parminmax(res, n) line[p+'_max'] = parmax line[p+'_min'] = parmin # deal with error on const parmin, parmax = _parminmax(res, 'c1.c0') self.const_min = parmin self.const_max = parmax
def save_conf(filename, energy_flux=None, absorbpars=[]): ''' Parameters ---------- filename : string energy_flux : string or integer Identifier of Sherpa model for which the energy flux will be calculated. absorbpars : sherpa parameter instances These parameters are set to 0 before the flux is calculated. ''' confres = ui.get_conf_results() fitres = ui.get_fit_results() if energy_flux is not None: oldval = [getattr(a, 'val') for a in absorbpars] for a in absorbpars: setattr(a, 'val', 0.) energy_flux = ui.calc_energy_flux(0.3, 9., energy_flux) for a, v in zip(absorbpars, oldval): setattr(a, 'val', v) with open(join(articlepath, filename), 'w') as f: json.dump( { 'name': confres.parnames, 'val': confres.parvals, 'up': confres.parmaxes, 'down': confres.parmins, 'redchi2': fitres.rstat, 'dof': fitres.dof, 'flux': energy_flux }, f)
def test_proj_bubble(parallel, clean_astro_ui, fix_xspec, run_thread): # How sensitive are the results to the change from bcmc to vern # made in XSPEC 12.10.1? It looks like the mekal best-fit # temperature can jump from ~17.9 to 18.6, so require bcmc # in this test (handled by fix_xspec). # # Note that the error on kT is large, so we can expect that # changes to the system could change these results. In particular, # the covariance errors on kt are < 1 but from other error # analysis they are > 10 or even unbound, so it is likely that the # covariance error results can change significantly. # # The fit results change in XSPEC 12.10.0 since the mekal model # was changed (FORTRAN to C++). A 1% difference is used for the # parameter ranges from covar and proj (matches the tolerance for # the fit results). Note that this tolerance has been relaced to # 10% for the kT errors, as there is a significant change seen # with different XSPEC versions for the covariance results. # # fit_results is unused def cmp_thread(fit_results, mek1, covarerr): assert covarerr[0] == approx(0, rel=1e-4) assert covarerr[1] == approx(8.74608e-07, rel=1e-3) assert mek1.kt.val == approx(17.8849, rel=1e-2) assert mek1.norm.val == approx(4.15418e-06, rel=1e-2) check_thread(run_thread, 'proj_bubble', parallel, cmp_thread, ['mek1']) # Covar # # TODO: should this check that parmaxes is -1 * parmins instead? covar = ui.get_covar_results() assert covar.parmins[0] == approx(-0.653884, rel=0.1) assert covar.parmins[1] == approx(-8.94436e-07, rel=0.01) assert covar.parmaxes[0] == approx(0.653884, rel=0.1) assert covar.parmaxes[1] == approx(8.94436e-07, rel=0.01) # Proj -- Upper bound of kT can't be found # proj = ui.get_proj_results() assert proj.parmins[0] == approx(-12.048069, rel=0.01) assert proj.parmins[1] == approx(-9.510913e-07, rel=0.01) assert proj.parmaxes[0] is None assert proj.parmaxes[1] == approx(2.403640e-06, rel=0.01) # Conf # conf = ui.get_conf_results() assert conf.parmins[0] == approx(-12.1073, rel=0.01) assert conf.parmins[1] == approx(-9.5568e-07, rel=0.01) assert conf.parmaxes[0] is None assert conf.parmaxes[1] == approx(2.39937e-06, rel=0.01)
def get_gamma_param(params, fitstats, fixgamma): if fixgamma: params["PhoIndex"] = fixgamma else: if fitstats.rstat <= 3: dsmod.conf(po1.PhoIndex) confstats = shp.get_conf_results() params["PhoIndex"] = confstats.parvals[0] params["PhoIndex_ErrMin"] = confstats.parmins[0] params["PhoIndex_ErrMax"] = confstats.parmaxes[0] else: params["PhoIndex"] = fitstats.parvals[1] return params
def fit_multiplets(multipletlist, id = None, outpath = None, plot = False, delta_lam = .2): # n_lines = np.sum([len(mult['wave']) for mult in multipletlist]) result = np.zeros(n_lines, dtype = {'names': ['multname', 'linename', 'wave', 'flux', 'errup', 'errdown', 'photons', 'photonflux'], 'formats': ['S30', 'S30', 'f4', 'f4', 'f4', 'f4', 'f4', 'f4']}) currentline = 0 # for mult in multipletlist: if outpath is not None: outfile = os.path.join(outpath, filter(lambda x: x.isalnum(), mult['name'])) else: outfile = None fit_lines(mult, id, delta_lam = delta_lam, plot = plot, outfile = outfile) # ui.conf(id) conf_res = ui.get_conf_results() source = ui.get_source(id) #set all ampl to 0 and only for 1 line to real value set_all_val('c0', 0., id) for lname, lfili, lwave in zip(mult['linename'], mult['fililiname'], mult['wave']): print 'Fitting line '+str(currentline+1)+'/'+str(n_lines) par = ui.get_model_component(lfili) indconf_res = ( np.array(conf_res.parnames) == lfili+'.ampl').nonzero()[0] set_all_val('ampl', 0., id) par.ampl.val = conf_res.parvals[indconf_res] counts = ui.calc_model_sum(None, None, id) # print(lname, counts) photonflux = ui.calc_photon_flux(None, None, id) # determine scaling between ampl and flux par.ampl.val = 1 amp2flux = ui.calc_energy_flux(None, None, id) par.ampl.val = conf_res.parvals[indconf_res] # val = conf_res.parvals[indconf_res] * amp2flux errdown = conf_res.parmins[indconf_res] * amp2flux if conf_res.parmins[indconf_res] else np.nan errup = conf_res.parmaxes[indconf_res] * amp2flux if conf_res.parmaxes[indconf_res] else np.nan # result[currentline] = (mult['name'], lname, lwave, val, errup, errdown, counts, photonflux) # currentline +=1 return result
def get_nh_param(params, fitstats, fixgamma): nH = fitstats.parvals[0] if fitstats.rstat <= 3.0: dsmod.conf(abs1.nH) confstats = shp.get_conf_results() nHmin = confstats.parmins[0] nHmax = confstats.parmaxes[0] # Estimate nH upper-limit if nH=0, or nH-nHmin<0, or nHmin = nan if (nH == 0) or (nHmin is None) or (nH - nHmin <= 0): params["nH"] = _nH_uplimit(fixgamma) else: params["nH"] = nH params["nH_ErrMin"] = nHmin params["nH_ErrMax"] = nHmax else: params["nH"] = nH return params
def conf(self): """ Run conf on each of the model parameters using the "onion-peeling" method: - First conf the outside shell model using the outer annulus spectrum - Freeze the model parameters for the outside shell - get confidences for the next inward shell / annulus and freeze those parameters - Repeat until all datasets have been conf()-ed and all shell-by-shell error parameters determined. - Return model parameters to original thawed/frozen status - WARNING: This ignores the correlations between parameters :rtype: None """ thawed = [] # Parameter objects that are not already frozen conf_results = [] this_conf_result = [] for annulus in reversed(range(self.nshell)): dataids = [x['id'] for x in self.datasets if x['annulus'] == annulus] print 'Getting shell-by-shell confidence for dataset ', dataids SherpaUI.conf(*dataids) this_conf_result = SherpaUI.get_conf_results() conf_results.insert(0, this_conf_result) for model_comp in self.model_comps: name = model_comp['name'] if model_comp['shell'] == annulus: # Remember parameters that are currently thawed for par in [SherpaUI.get_par('%s.%s'%(name, x)) for x in SherpaUI.get_model_pars(name)]: if not par.frozen: thawed.append(par) print 'Freezing', model_comp['name'] SherpaUI.freeze(model_comp['name']) # Unfreeze parameters for par in thawed: print 'Thawing', par.fullname par.thaw() return conf_results
def write_all(filename='results.json'): """Dump source, fit results and conf results to a JSON file. http://www.astropython.org/snippet/2010/7/Save-sherpa-fit-and-conf-results-to-a-JSON-file """ import sherpa.astro.ui as sau out = dict() if 0: src = sau.get_source() src_par_attrs = ('name', 'frozen', 'modelname', 'units', 'val', 'fullname') out['src'] = dict(name=src.name, pars=[ dict((attr, getattr(par, attr)) for attr in src_par_attrs) for par in src.pars ]) try: fit_attrs = ('methodname', 'statname', 'succeeded', 'statval', 'numpoints', 'dof', 'rstat', 'qval', 'nfev', 'message', 'parnames', 'parvals') fit = sau.get_fit_results() out['fit'] = dict((attr, getattr(fit, attr)) for attr in fit_attrs) except Exception as err: print(err) try: conf_attrs = ('datasets', 'methodname', 'fitname', 'statname', 'sigma', 'percent', 'parnames', 'parvals', 'parmins', 'parmaxes', 'nfits') conf = sau.get_conf_results() out['conf'] = dict((attr, getattr(conf, attr)) for attr in conf_attrs) except Exception as err: print(err) try: covar_attrs = ('datasets', 'methodname', 'fitname', 'statname', 'sigma', 'percent', 'parnames', 'parvals', 'parmins', 'parmaxes', 'nfits') covar = sau.get_covar_results() out['covar'] = dict( (attr, getattr(covar, attr)) for attr in covar_attrs) except Exception as err: print(err) if 0: out['pars'] = [] for par in src.pars: fullname = par.fullname if any(fullname == x['name'] for x in out['pars']): continue # Parameter was already processed outpar = dict(name=fullname, kind=par.name) # None implies no calculated confidence interval for Measurement parmin = None parmax = None try: if fullname in conf.parnames: # Confidence limits available from conf i = conf.parnames.index(fullname) parval = conf.parvals[i] parmin = conf.parmins[i] parmax = conf.parmaxes[i] if parmin is None: parmin = -float( 'inf' ) # None from conf means infinity, so set accordingly if parmax is None: parmax = float('inf') elif fullname in fit.parnames: # Conf failed or par is uninteresting and wasn't sent to conf i = fit.parnames.index(fullname) parval = fit.parvals[i] else: # No fit or conf value (maybe frozen) parval = par.val except Exception as err: print(err) out['pars'].append(outpar) if filename is None: return out else: json.dump(out, open(filename, 'w'), sort_keys=True, indent=4)
def print_conf(): res = sau.get_conf_results() print("Confidence limits on fitted parameters:") for index, parn in enumerate(res.parnames): print(parn, "\t\t{0:.3e}".format(res.parvals[index]), "\t{0:.3e}".format(res.parmins[index]), "\t{0:.3e}".format(res.parmaxes[index]))
def write_all(filename='results.json'): """Dump source, fit results and conf results to a JSON file. http://www.astropython.org/snippet/2010/7/Save-sherpa-fit-and-conf-results-to-a-JSON-file """ import sherpa.astro.ui as sau out = dict() if 0: src = sau.get_source() src_par_attrs = ('name', 'frozen', 'modelname', 'units', 'val', 'fullname') out['src'] = dict(name=src.name, pars=[dict((attr, getattr(par, attr)) for attr in src_par_attrs) for par in src.pars]) try: fit_attrs = ('methodname', 'statname', 'succeeded', 'statval', 'numpoints', 'dof', 'rstat', 'qval', 'nfev', 'message', 'parnames', 'parvals') fit = sau.get_fit_results() out['fit'] = dict((attr, getattr(fit, attr)) for attr in fit_attrs) except Exception as err: print(err) try: conf_attrs = ('datasets', 'methodname', 'fitname', 'statname', 'sigma', 'percent', 'parnames', 'parvals', 'parmins', 'parmaxes', 'nfits') conf = sau.get_conf_results() out['conf'] = dict((attr, getattr(conf, attr)) for attr in conf_attrs) except Exception as err: print(err) try: covar_attrs = ('datasets', 'methodname', 'fitname', 'statname', 'sigma', 'percent', 'parnames', 'parvals', 'parmins', 'parmaxes', 'nfits') covar = sau.get_covar_results() out['covar'] = dict((attr, getattr(covar, attr)) for attr in covar_attrs) except Exception as err: print(err) if 0: out['pars'] = [] for par in src.pars: fullname = par.fullname if any(fullname == x['name'] for x in out['pars']): continue # Parameter was already processed outpar = dict(name=fullname, kind=par.name) # None implies no calculated confidence interval for Measurement parmin = None parmax = None try: if fullname in conf.parnames: # Confidence limits available from conf i = conf.parnames.index(fullname) parval = conf.parvals[i] parmin = conf.parmins[i] parmax = conf.parmaxes[i] if parmin is None: parmin = -float('inf') # None from conf means infinity, so set accordingly if parmax is None: parmax = float('inf') elif fullname in fit.parnames: # Conf failed or par is uninteresting and wasn't sent to conf i = fit.parnames.index(fullname) parval = fit.parvals[i] else: # No fit or conf value (maybe frozen) parval = par.val except Exception as err: print(err) out['pars'].append(outpar) if filename is None: return out else: json.dump(out, open(filename, 'w'), sort_keys=True, indent=4)