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 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 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 pl(): index, beta = ce.PL_Index, 0 return Models.LogParabola(p=[flux, index, beta, pivot], free=free)
def lp(): index, beta = ce.LP_Index, ce.LP_beta return Models.LogParabola(p=[flux, index, beta, pivot], free=free)
def LogParabola(*pars): model = Models.LogParabola(p=pars, free=[True, True, False, False]) sources.set_default_bounds(model) return model
def LogParabola(*pars, **kw): m = Models.LogParabola(p=pars, **kw) m.free[3] = False return m
def LogParabola(*pars): model = Models.LogParabola(p=pars, free=[True, True, False, False]) return model
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)