def plec(): index, a, b = ce.PLEC_Index, ce.PLEC_Expfactor, ce.PLEC_Exp_Index cutoff = (1 / a)**(1 / b) prefactor = flux * np.exp(a * pivot**b) return Models.PLSuperExpCutoff(p=[prefactor, index, cutoff, b], e0=pivot, free=free)
def lookup(self, name): """ return an ExtendedSource object by name, None if not found """ aname = self.alias.get(name,name) #alias will be the new name try: i = list(self.names).index(name) except ValueError: return None source = self.sources[i] # make a new object copied from original if source.model.name=='BrokenPowerLaw': #convert this model = Models.LogParabola() else: model = source.model if model.name=='LogParabola': model.free[-1]=False # E_break ne free ### seems to be necessary for some models created from if model.mappers[0].__class__.__name__== 'LimitMapper': print 'wrong mappers: converting model for source %s, model %s' % (name, model.name) model = eval('Models.%s(p=%s)' % (model.name, list(model.get_all_parameters()))) extsource = sources.ExtendedSource(name=self.realname(aname), skydir=source.skydir, model = model, dmodel= source.spatial_model ) if extsource.model.name=='LogParabola': assert sum( extsource.model.free)<4, 'E_break is free?' return extsource
def fit_isotropic(roi, nbands=8, folder='isotropic_fit'): """ fit only the front and back""" from uw.like import Models iso_source = roi.get_source('isotrop') old_model=iso_source.model.copy() roi.sources.set_model(Models.FrontBackConstant(), 'isotrop') iso_model=iso_source.model roi.reinitialize() cx = [] for eband in range(nbands): print '*** Energy Band {}: iso counts {}'.format( eband, [t[1].counts.round() for t in roi[2*eband:2*eband+2]]) roi.select(eband) iso_model[0]=1; iso_model[1]=1 roi.fit([0,1]); u = iso_model.get_all_parameters(); cx.append(u) roi.select() roi.sources.set_model(old_model) if folder is not None: if not os.path.exists(folder): os.mkdir(folder) filename= '{}/{}.pickle'.format(folder, roi.name) pickle.dump(np.array(cx), open(filename, 'w')) print 'wrote file {}'.format(filename) return np.array(cx)
def __init__(self, cat_entry): """return a Pandas.DataFrame for the band flux information cat_entry: pandas.Series object Adds columns with conversion to differential energy flux, in eV units """ cols = 'Flux Unc_Flux Index Npred Sqrt_TS'.split() t = [cat_entry[cname + '_Band'] for cname in cols] bf = pd.DataFrame(t, index=cols).T # add columns with energy flux # evaluate energy flux = e**2 * df/de at geometric mean, assuming powerlaw # convert to units eV/(cm**2 * s) eb = energy_bounds r = BandFlux.conversion_factors(eb.LowerEnergy, eb.UpperEnergy, bf.Index) bf['eflux'] = bf.Flux * r bf['eflux_unc'] = (bf.Unc_Flux) * r self.bf = bf # construct the spectral model object if info is there # TODO: deal with exponential s = cat_entry #self.name = cat_entry['Source_Name'] self.model = None self.nickname = cat_entry['NickName'] if 'Flux_Density' in cat_entry: if s['SpectrumType'] == 'LogParabola': self.model = Models.LogParabola( [ s['Flux_Density'], s['Spectral_Index'], s['beta'], s['Pivot_Energy'] ], free=[True, True, False, False])
def __init__(self, roi, nbands, folder): """ fit the front and back""" from uw.like import Models iso_source = roi.get_source('isotrop') old_model = iso_source.model.copy() roi.sources.set_model(Models.FrontBackConstant(), 'isotrop') iso_model = iso_source.model roi.reinitialize() cx = [] dx = [] for eband in range(nbands): roi.select(eband) print '*** Energy Band {}: iso counts {}'.format( eband, [t[1].counts.round() for t in roi.selected]) iso_model[0] = 1 iso_model[1] = 1 n = len(roi.selected) roi.fit(range(n)) u = iso_model.get_all_parameters() du = np.array([iso_model.error(i) for i in range(2)]) cx.append(u) dx.append(du) roi.select() roi.sources.set_model(old_model) if folder is not None: if not os.path.exists(folder): os.mkdir(folder) filename = '{}/{}.pickle'.format(folder, roi.name) pickle.dump(dict(val=cx, err=dx), open(filename, 'w')) print 'wrote file {}'.format(filename) self.val = cx self.err = dx
def __call__(self, s): sdir = s.skydir if hasattr(s, 'spatial_model') and s.spatial_model is not None: return True for i, t in enumerate(self.sdir): dist = np.degrees(t.difference(sdir)) if dist < self.tol and s.ts > self.ts_min: self.tags[i] = True self.assoc[i] = (s.name, dist, s.ts) if self.rename and s.name != self.psr_names[i]: print 'Skymodel: renaming %s(%d) to %s' % ( s.name, s.index, self.psr_names[i]) s.name = self.psr_names[i] if s.model.name == 'ExpCutoff': return True flux = s.model[0] if flux > 1e-18: print 'Skymodel: replacing model for: %s(%d): pulsar name: %s' % ( s.name, s.index, self.psr_names[i]) s.model = Models.ExpCutoff() s.free = s.model.free.copy() else: print 'Apparent pulsar %s(%d), %s, is very weak, flux=%.2e <1e-13: leave as powerlaw' % ( s.name, s.index, self.psr_names[i], flux) return True if s.model.name == 'ExpCutoff': print 'Skymodel setup warning: %s (%d) not in LAT pulsar list, should not be expcutoff' % ( s.name, s.index) return True
def model(st, flux, index, beta, pivot, cutoff, b): if st == 'PowerLaw': return Models.PowerLaw(p=[flux, index], e0=pivot) elif st == 'PLSuperExpCutoff': prefactor = flux * np.exp((pivot / cutoff)**b) return Models.PLSuperExpCutoff(p=[prefactor, index, cutoff, b], e0=pivot) elif st == 'PLExpCutoff': prefactor = flux * np.exp((pivot / cutoff)) return Models.PLSuperExpCutoff( p=[prefactor, index, cutoff, 1.0], e0=pivot) elif st == 'LogParabola': return Models.LogParabola(p=[flux, index, beta, pivot]) elif st == 'PowerLaw2': ### same as PowerLaw in table return Models.PowerLaw(p=[flux, index], e0=pivot) else: raise Exception( 'unexpected spectrum type {}, source name {}'.format( st, name))
def pmodel(source): """ create a pointlike model from a Series object from DataFrame row """ expandbits = lambda x: [(x & 2**i) != 0 for i in range(4)] modelname, freebits, e0, norm, norm_unc, pindex, pindex_unc, index2,index2_unc, cutoff, cutoff_unc=\ [source[x] for x in 'modelname freebits e0 flux flux_unc pindex pindex_unc index2 index2_unc cutoff cutoff_unc'.split()] free = expandbits(freebits) errors = [norm_unc, pindex_unc] if modelname == 'LogParabola': if np.abs(index2) < 2e-3: modelname = 'PowerLaw' model = Models.PowerLaw(p=[norm, pindex], e0=e0) else: # if index2<0: # print 'Source %s has beta (%.2f) <0: setting to 0.' % ( source.name, index2, ) # index2=0 model = Models.LogParabola(p=[norm, pindex, index2, e0]) model.free[-1] = False errors.append(index2_unc) elif modelname == 'PLSuperExpCutoff': prefactor = np.exp(-(e0 / cutoff)**index2) model = Models.PLSuperExpCutoff( p=[norm / prefactor, pindex, cutoff, index2], e0=e0) errors[0] /= prefactor errors += [cutoff_unc, index2_unc] elif modelname == 'ExpCutoff': prefactor = np.exp(-(e0 / cutoff)) model = Models.PLSuperExpCutoff( p=[norm / prefactor, pindex, cutoff, 0.], e0=e0) model.free[3] == False errors[0] /= prefactor errors += [cutoff_unc] else: raise Exception('model "%s" not recognized' % modelname) map(model.set_error, range(len(errors)), errors) model.free[:] = free[:model.len()] return model
def fit_diffuse(roi, nbands=8, select=[0,1,2], restore=False, folder='diffuse_fit'): """ Perform indpendent fits to the gal, iso_front, and iso_back for each of the first nbands bands select: None or list of variables """ from uw.like import Models # freeze all free sources, thaw gal and iso roi.thaw('Norm', 'ring') iso_model =roi.sources.find_source('isotrop').model.copy() roi.sources.set_model(Models.FrontBackConstant(), 'isotrop') roi.reinitialize() # do the fitting dpars=[] energies = [] for ie in range(nbands): roi.select(ie); roi.fit(select, ignore_exception=True) energies.append(int(roi.energies[0])) dpars.append( roi.sources.parameters.get_parameters()[:3]) t =np.power(10, dpars) df = pd.DataFrame(t, columns=['gal iso_front iso_back'.split()]) df.index=energies if restore: # does not seem to work, comment this out for now # restore sources roi.sources.diffuse_normalization *= df for s,f in zip(free_sources, saved_free): s.model.free=f roi.sources.find_source('ring').model.free[0]=False roi.sources.set_model(iso_model, 'isotrop') roi.reinitialize() roi.select() roi.fit() # needed to restore gradient, at least. # update the pickle file write_pickle(roi) elif folder is not None: # simply save results if not os.path.exists(folder): os.mkdir(folder) filename= '{}/{}.pickle'.format(folder, roi.name) pickle.dump(df, open(filename, 'w')) print 'wrote file {}'.format(filename) return df
def lp(): index, beta = ce.LP_Index, ce.LP_beta return Models.LogParabola(p=[flux, index, beta, pivot], free=free)
def ExpCutoff(*pars): model = Models.ExpCutoff(p=pars, free=[True, True, False]) return model
def PLSuperExpCutoff(*pars): model = Models.PLSuperExpCutoff(p=pars, free=[True, True, False, False]) return model
def ExpCutoff(*pars): model = Models.ExpCutoff(p=pars, free=[True, True, False]) sources.set_default_bounds(model) return model
def PLSuperExpCutoff(*pars): model = Models.PLSuperExpCutoff(p=pars, free={True, True, False, False}) sources.set_default_bounds(model) return model
def LogParabola(*pars): model = Models.LogParabola(p=pars, free=[True, True, False, False]) sources.set_default_bounds(model) return model
def PowerLaw(*pars): model = Models.PowerLaw(p=pars) sources.set_default_bounds(model) return model
def LogParabola(*pars, **kw): m = Models.LogParabola(p=pars, **kw) m.free[3] = False return m
def PowerLaw(*pars): model = Models.PowerLaw(p=pars) return model
def FBconstant(f, b, **kw): return Models.FrontBackConstant(f, b, **kw)
def Constant(*pars, **kw): return Models.Constant(p=pars, **kw)
def PLSuperExpCutoff(*pars, **kw): return Models.PLSuperExpCutoff(p=pars, **kw)
def ExpCutoff(*pars, **kw): return Models.ExpCutoff(p=pars, **kw)
def PowerLaw(*pars, **kw): return Models.PowerLaw(p=pars, **kw)
def PSR_default(): return Models.PLSuperExpCutoff(p=(1e-13, 1.25, 1500, 0.67), free=[True, True, True, False])
def LogParabola(*pars): model = Models.LogParabola(p=pars, free=[True, True, False, False]) return model
def pl(): index, beta = ce.PL_Index, 0 return Models.LogParabola(p=[flux, index, beta, pivot], free=free)
def load_auxcat(self, tol=0.2): """ modify the list of pointsources from entries in the auxcat: for now: * add it not there * move there, at new ra,dec * remove if ra<0 """ if self.auxcat is None or self.auxcat == '': return cat = self.auxcat if not os.path.exists(cat): cat = os.path.expandvars(os.path.join('$FERMI', 'catalog', cat)) if not os.path.exists(cat): cat = os.path.join(self.folder, self.auxcat) if not os.path.exists(cat): raise Exception( 'auxilliary source catalog "%s" not found locally (%s) or in $FERMI/catalog' % (self.auxcat, self.folder)) ext = os.path.splitext(cat)[-1] if ext == '.pickle': ss = pd.load(cat).itertuples() dataframe = True print 'loading auxcat from DataFrame' elif ext == '.csv': cc = pd.read_csv(cat) cols = list(cc.columns) ss = cc.itertuples() i_eflux = cols.index('eflux') + 1 i_pindex = cols.index('pindex') + 1 i_e0 = cols.index('e0') + 1 dataframe = True print 'loading auxcat from csv' else: ss = makerec.load(cat) dataframe = False names = [s.name for s in self.point_sources] sdirs = [s.skydir for s in self.point_sources] def check_near(sdir): closest = np.degrees(np.min(np.array(map(sdir.difference, sdirs)))) return closest toremove = [] print 'process auxcat %s' % cat for s in ss: if dataframe: # from csv: construct full model from parameters sname, sra, sdec = s[1:4] n0 = s[i_eflux] / (s[i_e0]**2 * 1e6) model = Models.LogParabola(p=[n0, s[i_pindex], 0., s[i_e0]]) model.free[2:] = False else: # for comatibility: default from pater sname, sra, sdec = s.name, s.ra, s.dec model = self.newmodel if type(self.newmodel) == types.StringType: model = eval(self.newmodel) elif model is None: pass else: model = self.newmodel.copy( ) # make sure to get a new object if not sname.startswith('SEED'): # allow underscores sname = sname.replace('_', ' ') if sname not in names: skydir = SkyDir(float(sra), float(sdec)) close = check_near(skydir) if close < tol: print '\tsource %s close to another source, reject' % sname continue index = self.hpindex(skydir) if model is not None: model.free[ 0] = True # must have at least one free parameter to be set up properly in an ROI self.point_sources.append( sources.PointSource(name=sname, skydir=skydir, index=index, model=model)) print '\tadded new source %s at ROI %d (%.1f deg )' % ( sname, index, close) else: print '\t source %s is in the model:' % sname, # will remove if ra<0' % sname ps = self.point_sources[names.index(sname)] if float(sra) <= 0: toremove.append(ps) print ' removed.' else: newskydir = SkyDir(float(sra), float(sdec)) print 'moved from %s to %s' % (ps.skydir, newskydir) ps.skydir = newskydir for ps in toremove: self.point_sources.remove(ps)