def ElectronIC(pars, data): # Match parameters to ECPL properties, and give them the appropriate units amplitude = pars[0] / u.eV alpha = pars[1] e_cutoff = (10**pars[2]) * u.TeV # Initialize instances of the particle distribution and radiative model ECPL = ExponentialCutoffPowerLaw(amplitude, 10. * u.TeV, alpha, e_cutoff) IC = InverseCompton(ECPL, seed_photon_fields=[ 'CMB', ['FIR', 26.5 * u.K, 0.415 * u.eV / u.cm**3] ]) # compute flux at the energies given in data['energy'], and convert to # units of flux data model = IC.flux(data, distance=1.0 * u.kpc) # Save this realization of the particle distribution function elec_energy = np.logspace(11, 15, 100) * u.eV nelec = ECPL(elec_energy) # Compute and save total energy in electrons above 1 TeV We = IC.compute_We(Eemin=1 * u.TeV) # The first array returned will be compared to the observed spectrum for # fitting. All subsequent objects will be stores in the sampler metadata # blobs. return model, (elec_energy, nelec), We
def ElectronSynIC(pars, data): # Match parameters to ECPL properties, and give them the appropriate units amplitude = 10**pars[0] / u.eV alpha = pars[1] e_cutoff = (10**pars[2]) * u.TeV B = pars[3] * u.uG # Initialize instances of the particle distribution and radiative models ECPL = ExponentialCutoffPowerLaw(amplitude, 10. * u.TeV, alpha, e_cutoff) # Compute IC on CMB and on a FIR component with values from GALPROP for the # position of RXJ1713 IC = InverseCompton(ECPL, seed_photon_fields=[ 'CMB', ['FIR', 26.5 * u.K, 0.415 * u.eV / u.cm**3] ], Eemin=100 * u.GeV) SYN = Synchrotron(ECPL, B=B) # compute flux at the energies given in data['energy'] model = (IC.flux(data, distance=1.0 * u.kpc) + SYN.flux(data, distance=1.0 * u.kpc)) # The first array returned will be compared to the observed spectrum for # fitting. All subsequent objects will be stored in the sampler metadata # blobs. return model, IC.compute_We(Eemin=1 * u.TeV)
def diff_spectrum_leptonic(self, time): self.dist = self.distance() ELECTRONS = self.spectrum_electron(time) IC = InverseCompton(ELECTRONS, seed_photon_fields=['CMB']) GAMMAS = IC.sed(self.ENERGY, self.dist * u.kpc) GAMMAS_TeV = GAMMAS.to(u.TeV / (u.cm**2 * u.s)) return GAMMAS_TeV
def ElectronEblAbsorbedSynIC(pars, data): # Match parameters to ECPL properties, and give them the appropriate units amplitude = 10**pars[0] / u.eV e_break = (10**pars[1]) * u.TeV alpha1 = pars[2] alpha2 = pars[3] B = pars[4] * u.uG # Define the redshift of the source, and absorption model redshift = pars[5] * u.dimensionless_unscaled EBL_transmitance = EblAbsorptionModel(redshift, 'Dominguez') # Initialize instances of the particle distribution and radiative models BPL = BrokenPowerLaw(amplitude, 1. * u.TeV, e_break, alpha1, alpha2) # Compute IC on a CMB component IC = InverseCompton( BPL, seed_photon_fields=['CMB'], Eemin=10 * u.GeV) SYN = Synchrotron(BPL, B=B) # compute flux at the energies given in data['energy'] model = (EBL_transmitance.transmission(data) * IC.flux(data, distance=1.0 * u.kpc) + SYN.flux(data, distance=1.0 * u.kpc)) # The first array returned will be compared to the observed spectrum for # fitting. All subsequent objects will be stored in the sampler metadata # blobs. return model, IC.compute_We(Eemin=1 * u.TeV)
def ElectronSynIC(pars, data): # Match parameters to ECPL properties, and give them the appropriate units amplitude = 10 ** pars[0] / u.eV alpha = pars[1] e_cutoff = (10 ** pars[2]) * u.TeV B = pars[3] * u.uG # Initialize instances of the particle distribution and radiative models ECPL = ExponentialCutoffPowerLaw(amplitude, 10.0 * u.TeV, alpha, e_cutoff) # Compute IC on CMB and on a FIR component with values from GALPROP for the # position of RXJ1713 IC = InverseCompton( ECPL, seed_photon_fields=[ "CMB", ["FIR", 26.5 * u.K, 0.415 * u.eV / u.cm ** 3], ], Eemin=100 * u.GeV, ) SYN = Synchrotron(ECPL, B=B) # compute flux at the energies given in data['energy'] model = IC.flux(data, distance=1.0 * u.kpc) + SYN.flux( data, distance=1.0 * u.kpc ) # The first array returned will be compared to the observed spectrum for # fitting. All subsequent objects will be stored in the sampler metadata # blobs. return model, IC.compute_We(Eemin=1 * u.TeV)
def ElectronEblAbsorbedSynIC(pars, data): # Match parameters to ECPL properties, and give them the appropriate units amplitude = 10**pars[0] / u.eV e_break = (10**pars[1]) * u.TeV alpha1 = pars[2] alpha2 = pars[3] B = pars[4] * u.uG # Define the redshift of the source, and absorption model redshift = pars[5] * u.dimensionless_unscaled EBL_transmitance = EblAbsorptionModel(redshift, "Dominguez") # Initialize instances of the particle distribution and radiative models BPL = BrokenPowerLaw(amplitude, 1.0 * u.TeV, e_break, alpha1, alpha2) # Compute IC on a CMB component IC = InverseCompton(BPL, seed_photon_fields=["CMB"], Eemin=10 * u.GeV) SYN = Synchrotron(BPL, B=B) # compute flux at the energies given in data['energy'] model = EBL_transmitance.transmission(data) * IC.flux( data, distance=1.0 * u.kpc) + SYN.flux(data, distance=1.0 * u.kpc) # The first array returned will be compared to the observed spectrum for # fitting. All subsequent objects will be stored in the sampler metadata # blobs. return model, IC.compute_We(Eemin=1 * u.TeV)
def ElectronIC(pars, data): # Match parameters to ECPL properties, and give them the appropriate units amplitude = pars[0] / u.eV alpha = pars[1] e_cutoff = (10 ** pars[2]) * u.TeV # Initialize instances of the particle distribution and radiative model ECPL = ExponentialCutoffPowerLaw(amplitude, 10.0 * u.TeV, alpha, e_cutoff) # Compute IC on CMB and on a FIR component with values from GALPROP for the # position of RXJ1713 IC = InverseCompton( ECPL, seed_photon_fields=[ "CMB", ["FIR", 26.5 * u.K, 0.415 * u.eV / u.cm ** 3], ], Eemin=100 * u.GeV, ) # compute flux at the energies given in data['energy'], and convert to units # of flux data model = IC.flux(data, distance=1.0 * u.kpc).to(data["flux"].unit) # Save this realization of the particle distribution function elec_energy = np.logspace(11, 15, 100) * u.eV nelec = ECPL(elec_energy) # Compute and save total energy in electrons above 1 TeV We = IC.compute_We(Eemin=1 * u.TeV) # The first array returned will be compared to the observed spectrum for # fitting. All subsequent objects will be stores in the sampler metadata # blobs. return model, (elec_energy, nelec), We
def ElectronIC(pars, data): """ Define particle distribution model, radiative model, and return model flux at data energy values """ ECPL = ExponentialCutoffPowerLaw(pars[0] / u.eV, 10. * u.TeV, pars[1], 10**pars[2] * u.TeV) IC = InverseCompton(ECPL, seed_photon_fields=['CMB']) return IC.flux(data, distance=1.0 * u.kpc)
def ElectronIC(pars, data): """ Define particle distribution model, radiative model, and return model flux at data energy values """ ECPL = ExponentialCutoffPowerLaw(pars[0] / u.eV, 10.0 * u.TeV, pars[1], 10**pars[2] * u.TeV) IC = InverseCompton(ECPL, seed_photon_fields=["CMB"]) return IC.flux(data, distance=1.0 * u.kpc)
def emission(electrons, B, Rb, ssc): warnings.filterwarnings('ignore', category=DeprecationWarning) SYN = Synchrotron( electrons, B=B.to((u.erg * pcm)**(1 / 2)).value * u.G, Eemax=max(electrons.e_break, electrons.e_cutoff), Eemin=electrons.e_0, nEed=50, ) E_ph = np.logspace(-7, 9, 100) * u.eV L_syn = SYN.flux(E_ph, distance=0 * u.cm) phn_syn = L_syn / (4 * np.pi * Rb**2 * c) * 2.24 * float(ssc) IC = InverseCompton( electrons, seed_photon_fields=[ ["SSC", E_ph, phn_syn], ], Eemax=max(electrons.e_break, electrons.e_cutoff), Eemin=electrons.e_0, nEed=50, ) return SYN, IC
def setup(self): self.functionName = "ElectronIC" self.formula = r"$f(E)=A(E/E_{\rm piv}}^\gamma}$" self.parameters = collections.OrderedDict() self.parameters["gamma"] = Parameter("gamma", -2., -10., 10, 0.1, fixed=False, nuisance=False, dataset=None) self.parameters["logA"] = Parameter("logA", -4., -40., 30, 0.1, fixed=False, nuisance=False, dataset=None) self.parameters["Epiv"] = Parameter("Epiv", 1., 1e-10, 1e10, 1., fixed=True, unit="keV") self.parameters["dist"] = Parameter("dist", 1., 1e-10, 1e10, 1., fixed=True) self.ncalls = 0 self.pdist_unit = 1. / u.Unit(m_e * c**2) self.PL = PowerLaw(1 * self.pdist_unit, 1 * u.keV, -2.5) self.IC = InverseCompton( self.PL, seed_photon_fields=[ 'CMB', ['FIR', 26.5 * u.K, 0.415 * u.eV / u.cm**3] ], Eemin=1 * u.TeV)
def f(rho, B): ECPL = ExponentialCutoffPowerLaw(1e36 * rho * u.Unit('1/eV'), 1 * u.TeV, 2.0, 13 * u.TeV) SYN = Synchrotron(ECPL, B=1000 * B * u.uG) # Define energy array for synchrotron seed photon field and compute # Synchroton luminosity by setting distance to 0. Esy = np.logspace(-6, 6, 100) * u.eV Lsy = SYN.flux(Esy, distance=0 * u.cm) # Define source radius and compute photon density R = 2 * u.pc phn_sy = Lsy / (4 * np.pi * R**2 * c) * 2.26 # Create IC instance with CMB and synchrotron seed photon fields: IC = InverseCompton( ECPL, seed_photon_fields=['CMB', 'FIR', 'NIR', ['SSC', Esy, phn_sy]]) # Compute SEDs spectrum_energy = np.logspace(13, 14, 1) * u.eV sed_IC = IC.sed(spectrum_energy, distance=1.5 * u.kpc) return sed_IC.value
def flare_rad(index, LE_cutoff, Ee_syn_max, B_flare, Ecut_0): ECPL = ExponentialCutoffPowerLaw(amplitude=amp0 / u.eV, e_0=1 * u.TeV, alpha=index, e_cutoff=Ecut_0) SYN = Synchrotron(ECPL, B=B_flare, Eemin=LE_cutoff, Eemax=Ee_syn_max) amp_cor = fitfactor(data_flare, SYN) # Fit particle distribution prefactor # Fit particle cutoff, with analytic initial value Ecut_flare = fitcutoff(Ecut_0, data_flare, amp0 * amp_cor, index, B_flare, LE_cutoff, Ee_syn_max) print('Correct ecut: ', Ecut_flare.to(u.PeV)) # Final particle spectrum and synchrotron ECPL = ExponentialCutoffPowerLaw(amplitude=amp0 * amp_cor / u.eV, e_0=1 * u.TeV, alpha=index, e_cutoff=Ecut_flare) SYN = Synchrotron(ECPL, B=B_flare, Eemin=LE_cutoff, Eemax=Ee_syn_max) if flarename == '2011': Rflare = 2.8e-4 * u.pc ## 3.2 * u.pc, 2.8e-4, 1.7e-4 elif flarename == '2013': Rflare = 1.7e-4 * u.pc else: Rflare == 3.2 * u.pc Esy = np.logspace(0.0, 12, 100) * u.eV #np.exp(14) Lsy = SYN.flux(Esy, distance=0 * u.cm) # use distance 0 to get luminosity phn_sy = Lsy / (4 * np.pi * Rflare**2 * c) * 2.24 fields = [ 'CMB', ['FIR', 70 * u.K, 0.5 * u.eV / u.cm**3], ['NIR', 5000 * u.K, 1 * u.eV / u.cm**3], ['SSC', Esy, phn_sy] ] IC = InverseCompton(ECPL, seed_photon_fields=fields, Eemin=LE_cutoff, Eemax=Ee_syn_max) We = IC.compute_We(Eemin=1 * u.TeV) print('Estoy aqui: ', We) return SYN, IC, amp_cor, We, Ecut_flare
def ssc_model_components(parameters, precision=20): log_amplitude = parameters[0] alpha = parameters[1] beta = parameters[2] log_e_max = parameters[3] log_e_min = parameters[4] B = parameters[5] d_meyer = dict(a=(10**log_amplitude) / u.erg, alpha=alpha, beta=beta, e_max=10**log_e_max * u.eV, e_min=10**log_e_min * u.eV) T = meyer_model(**d_meyer) SYN = Synchrotron(T, B=B * u.uG, Eemax=50 * u.PeV, Eemin=0.01 * u.GeV, nEed=precision) # Compute photon density spectrum from synchrotron emission assuming R=2.1 pc Rpwn = 2.1 * u.pc Esy = np.logspace(-10, 10, 50) * u.MeV Lsy = SYN.flux(Esy, distance=0 * u.cm) # use distance 0 to get luminosity phn_sy = Lsy / ( 4 * np.pi * Rpwn**2 * constants.c ) * 2.25 # see section 1.6.2 in Ghiselini, Radiative Processes. IC = InverseCompton( T, seed_photon_fields=[ "CMB", ["FIR", 70 * u.K, 0.5 * u.eV / u.cm**3], ["NIR", 5000 * u.K, 1 * u.eV / u.cm**3], ["SSC", Esy, phn_sy], ], Eemax=50 * u.PeV, Eemin=0.01 * u.GeV, nEed=precision, ) return SYN, IC
def do_fit( periods, # [0, 1], ThetaIC, # np.array([90, 90]), Pos3D, # [[1, 1, 1], [1, 1, 1]], Dist, # np.array([2, 2]), Alpha, # np.array([2.58, 2.16]) label='', do_abs=True, lgEdot_min=31, lgEdot_max=37.5, lgEdot_bins=10, lgSigma_min=-3, lgSigma_max=-1, lgSigma_bins=10, Tstar=pars.TSTAR, Rstar=pars.RSTAR, AlphaSigma=1, Mdot=1e-8, Vw=1500 ): logging.info('Starting fitting') OutFit = open('fit_results/fit_results_' + label + '.txt', 'w') NEdot = (lgEdot_max - lgEdot_min) * lgEdot_bins NSigma = (lgSigma_max - lgSigma_min) * lgSigma_bins Edot_list = np.logspace(lgEdot_min, lgEdot_max, int(NEdot)) Sigma_list = np.logspace(lgSigma_min, lgSigma_max, int(NSigma)) logging.info('{} iterations'.format(NEdot * NSigma)) print(Edot_list) print(Sigma_list) n_periods = len(periods) if len(ThetaIC) != n_periods: logging.error('Argument with wrong dimensions - aborting') return None # Absorption if not do_abs: logging.info('Skipping absorption') else: # Computing Taus logging.info('Computing absorption') start = time.time() Obs = np.array([0, 0, -1]) Abs = abso.Absorption(Tstar=Tstar, Rstar=Rstar) data_en, data_fl, data_fl_er = list(), list(), list() Tau = list() DistTau = list() for iper in periods: en, fl, fl_er = data.get_data(iper, GT=True) data_en.append(en) data_fl.append(fl) data_fl_er.append(fl_er) DistTau.append(list()) tt = dict() for i in range(len(en)): tt[i] = list() Tau.append(tt) DistFrac = np.linspace(0.01, 1, 50) for ff in DistFrac: for i_per in range(n_periods): dist = ff * norm(Pos3D[i_per]) PosStar = Pos3D[i_per] * dist / norm(Pos3D[i_per]) for i_en in range(len(data_en[i_per])): tau = Abs.TauGG(en=data_en[i_per][i_en] * u.keV.to(u.TeV), obs=Obs, pos=PosStar) Tau[i_per][i_en].append(tau) DistTau[i_per].append(dist) logging.info('Abs done, dt/s = {}'.format(time.time() - start)) # # Ploting tau vs dist # plt.figure(figsize=(8, 6), tight_layout=True) # ax = plt.gca() # ax.set_yscale('log') # ax.set_ylabel(r'$\tau_{\gamma \gamma}$') # ax.set_xlabel(r'$D$ [AU]') # ax.plot(DistTau0, Tau0[92], marker='o', linestyle='-') # ax.plot(DistTau0, Tau0[95], marker='o', linestyle='-') # plt.show() for (Edot, Sigma) in itertools.product(Edot_list, Sigma_list): logging.debug('Starting Edot={}, Sigma={}'.format(Edot, Sigma)) # Computed parameters DistPulsar = [psr.Rshock(Edot=Edot, Mdot=Mdot, Vw=Vw, D=d) for d in Dist] DistStar = Dist - DistPulsar DistRef = 4. # SigmaFac = [pow(Dist[0] / d, AlphaSigma) for d in Dist] SigmaFac = [pow(DistRef / d, AlphaSigma) for d in Dist] SigmaShock = [Sigma * f for f in SigmaFac] Bfield = [psr.B2_KC(Edot=Edot, Rs=dp, sigma=s) for (dp, s) in zip(DistPulsar, SigmaShock)] Density = [psr.PhotonDensity(Tstar=Tstar, Rstar=Rstar, d=d) for d in DistStar] if 0 in Bfield: logging.info('Bfield is 0 - skipping') continue # Normalization Norm0 = np.array([1e24 / b for b in Bfield]) # Fitting fix_n = [True for p in range(pars.MAX_PERIOD)] fit_n = [Norm0[0] for p in range(pars.MAX_PERIOD)] for idx, iper in enumerate(periods): fix_n[iper] = False fit_n[iper] = Norm0[idx] logging.info('fix_n:') logging.info(fix_n) logging.info('fit_n:') logging.info(fit_n) npar = 5 - sum([int(f) for f in fix_n]) #################### # Further parameters Eref = 1 * u.TeV Ecut = 50 * u.TeV Emax = 20 * u.PeV Emin = 10 * u.GeV SourceDist = pars.SRC_DIST * u.kpc EnergyToPlot = np.logspace(-2, 11, 500) * u.keV ###################### # Loading data data_en, data_fl, data_fl_er = list(), list(), list() tau = list() model = list() for ii in range(pars.MAX_PERIOD): idx = periods.index(ii) if (ii in periods) else 0 en, fl, fl_er = data.get_data(ii, GT=True) data_en.append(en) data_fl.append(fl) data_fl_er.append(fl_er) thisTau = list() if do_abs and (ii in periods): for ien in range(len(en)): thisTau.append(np.interp(DistStar[idx], xp=DistTau[idx], fp=Tau[idx][ien])) else: thisTau = [0] * len(en) tau.append(thisTau) ECPL = ExponentialCutoffPowerLaw( amplitude=1e20 / u.eV, e_0=Eref, alpha=Alpha[idx], e_cutoff=Ecut ) SYN = Synchrotron( particle_distribution=ECPL, B=Bfield[idx] * u.G, Eemax=Emax, Eemin=Emin ) IC = InverseCompton( particle_distribution=ECPL, seed_photon_fields=[[ 'STAR', Tstar * u.K, Density[idx] * u.erg / u.cm**3, ThetaIC[idx] * u.deg ]], Eemax=Emax, Eemin=Emin ) thisModel = ( SYN.sed(photon_energy=[e * u.keV for e in en], distance=SourceDist) + IC.sed(photon_energy=[e * u.keV for e in en], distance=SourceDist) ) if do_abs: thisModel = [math.exp(-t) * m for (m, t) in zip(thisModel, thisTau)] model.append(thisModel) # END for def least_square(n0, n1, n2, n3, n4): chisq = 0 for ii, nn in enumerate([n0, n1, n2, n3, n4]): if fix_n[ii]: continue chisq += sum(util.vecChiSq( [(nn / 1e20) * m.value for m in model[ii]], data_fl[ii], data_fl_er[ii]) ) return chisq minuit = Minuit( least_square, n0=fit_n[0], fix_n0=fix_n[0], n1=fit_n[1], fix_n1=fix_n[1], n2=fit_n[2], fix_n2=fix_n[2], n3=fit_n[3], fix_n3=fix_n[3], n4=fit_n[4], fix_n4=fix_n[4], limit_n0=(fit_n[0] * 0.001, fit_n[0] * 1000), limit_n1=(fit_n[1] * 0.001, fit_n[1] * 1000), limit_n2=(fit_n[2] * 0.001, fit_n[2] * 1000), limit_n3=(fit_n[3] * 0.001, fit_n[3] * 1000), limit_n4=(fit_n[4] * 0.001, fit_n[4] * 1000) ) fmin, param = minuit.migrad() logging.info(minuit.matrix(correlation=True)) chisq_min = minuit.fval n_fit, n_err = list(), list() ndf = 0 for ii in range(pars.MAX_PERIOD): n_fit.append(param[ii]['value']) n_err.append(param[ii]['error']) if not fix_n[ii]: ndf += len(data_en[ii]) ndf -= npar # p_value = 1 - stats.chi2.cdf(chisq_min, ndf) logging.info('Fit') logging.info('ChiSq/ndf = {}'.format(chisq_min / ndf)) logging.info('ChiSq - ndf = {}'.format(chisq_min - ndf)) # # plot testing # for ii, nn in enumerate(n_fit): # if fix_n[ii]: # continue # plt.figure(figsize=(8, 6), tight_layout=True) # ax = plt.gca() # ax.set_xscale('log') # ax.set_yscale('log') # ax.set_title(ii) # ax.errorbar( # data_en[ii], # data_fl[ii], # yerr=data_fl_er[ii], # marker='o', # linestyle='none' # ) # ax.plot( # data_en[ii], # [(nn / 1e20) * m.value for m in model[ii]], # marker='o', # linestyle='none' # ) # plt.show() # print('p-value', p_value) # if do_abs: # TauPrint0 = [tau0[len(data_en0) - 4], tau0[len(data_en0) - 1]] # TauPrint1 = [tau1[len(data_en1) - 3], tau1[len(data_en1) - 1]] # else: # TauPrint0 = [0, 0] # TauPrint1 = [0, 0] if chisq_min - ndf < 1e3: OutFit.write(str(chisq_min) + ' ') OutFit.write(str(ndf) + ' ') for ii in range(pars.MAX_PERIOD): if not fix_n[ii]: OutFit.write(str(math.log10(n_fit[ii])) + ' ') OutFit.write(str(math.log10(Edot)) + ' ') OutFit.write(str(math.log10(Sigma)) + ' ') for ii in range(pars.MAX_PERIOD): if not fix_n[ii]: idx = periods.index(ii) OutFit.write(str(Dist[idx]) + ' ') OutFit.write(str(DistPulsar[idx]) + ' ') OutFit.write(str(Bfield[idx]) + ' ') # OutFit.write(str(TauPrint0[0]) + ' ') # OutFit.write(str(TauPrint0[1]) + ' ') # OutFit.write(str(TauPrint1[0]) + ' ') # OutFit.write(str(TauPrint1[1]) + '\n') OutFit.write('\n') OutFit.close()
# blob emission SYN = Synchrotron(comoving, B=B, Eemax=Emax, Eemin=Emin) # Compute photon density spectrum from synchrotron emission Esy = np.logspace( np.log10(((Emin / u.TeV)**2 * (B / u.Gauss)).cgs.value) + 3, np.log10( ((e_cutoff / u.TeV)**2 * (B / u.Gauss)).cgs.value) + 5, 300) * u.eV Lsy = SYN.flux(Esy, distance=0 * u.cm) # use distance 0 to get luminosity phn_sy = Lsy * 2.25 / (4 * np.pi * R**2 * c) SSC = InverseCompton( comoving, seed_photon_fields=[ ["SSC", Esy, phn_sy], ], Eemax=Emax, Eemin=Emin, ) EIC = InverseCompton( lab, seed_photon_fields=[ "CMB", ["BLR", T, w], ], Eemax=Emax * delta, Eemin=Emin * delta, ) # Use matplotlib to plot the spectra
eopts = {"Eemax": 50 * u.PeV, "Eemin": 0.1 * u.GeV} SYN = Synchrotron(ECBPL, B=125 * u.uG, Eemax=50 * u.PeV, Eemin=0.1 * u.GeV) # Compute photon density spectrum from synchrotron emission assuming R=2.1 pc Rpwn = 2.1 * u.pc Esy = np.logspace(-7, 9, 100) * u.eV Lsy = SYN.flux(Esy, distance=0 * u.cm) # use distance 0 to get luminosity phn_sy = Lsy / (4 * np.pi * Rpwn**2 * c) * 2.24 IC = InverseCompton( ECBPL, seed_photon_fields=[ "CMB", ["FIR", 70 * u.K, 0.5 * u.eV / u.cm**3], ["NIR", 5000 * u.K, 1 * u.eV / u.cm**3], ["SSC", Esy, phn_sy], ], Eemax=50 * u.PeV, Eemin=0.1 * u.GeV, ) # Use plot_data from naima to plot the observed spectra data = ascii.read("CrabNebula_spectrum.ecsv") figure = naima.plot_data(data, e_unit=u.eV) ax = figure.axes[0] # Plot the computed model emission energy = np.logspace(-7, 15, 100) * u.eV ax.loglog( energy,
def plot_sed( self, iperiod=0, period=0, best_solution=True, Edot=1e36, theta_ic=90, dist=2, pos=np.array([1, 1, 1]), ls='-', lw=1, label='None', Tstar=pars.TSTAR, Rstar=pars.RSTAR, emin=0.1, ecut=50, fast=False ): Alpha = pars.ELEC_SPEC_INDEX[period] Eref = 1 * u.TeV Ecut = ecut * u.TeV Emax = 20 * u.PeV Emin = emin * u.TeV SourceDist = pars.SRC_DIST * u.kpc n_en = 1 if fast else 2 Obs = np.array([0, 0, -1]) Abs = absorption.Absorption(Tstar=Tstar, Rstar=Rstar) if best_solution: b_sed = self.bMin[iperiod] norm_sed = self.normMin[iperiod] dist_sed = self.distPulsarMin[iperiod] dist_star = dist - dist_sed density_sed = psr.PhotonDensity(Tstar=Tstar, Rstar=Rstar, d=dist_star) else: idx = np.argmin(np.array([math.fabs(l - math.log10(Edot)) for l in self.lgEdotLine])) b_sed = self.bLine[iperiod][idx] norm_sed = 10**self.lgNormLine[iperiod][idx] dist_sed = self.distPulsarLine[iperiod][idx] dist_star = dist * (1 - dist_sed) density_sed = psr.PhotonDensity(Tstar=Tstar, Rstar=Rstar, d=dist_star) EnergyToPlot = np.logspace(-0.5, 9.6, n_en * 300) * u.keV ECPL = ExponentialCutoffPowerLaw( amplitude=norm_sed / u.eV, e_0=Eref, alpha=Alpha, e_cutoff=Ecut ) SYN = Synchrotron( particle_distribution=ECPL, B=b_sed * u.G, Eemax=Emax, Eemin=Emin ) IC = InverseCompton( particle_distribution=ECPL, seed_photon_fields=[[ 'STAR', Tstar * u.K, density_sed * u.erg / u.cm**3, theta_ic * u.deg ]], Eemax=Emax, Eemin=Emin ) tau = list() for e in EnergyToPlot: if e.value * u.keV.to(u.TeV) < 1e-4: tau.append(0) else: tau.append(Abs.TauGG( en=e.value * u.keV.to(u.TeV), obs=Obs, pos=pos * dist_star / norm(pos) )) model = ( SYN.sed(photon_energy=EnergyToPlot, distance=SourceDist) + IC.sed(photon_energy=EnergyToPlot, distance=SourceDist) ) model_abs = [math.exp(-t) * m.value for (m, t) in zip(model, tau)] EnergyToPlot, model_abs = util.fix_naima_bug(EnergyToPlot, model_abs) model_abs = util.smooth_break(EnergyToPlot, model_abs) ax = plt.gca() ax.plot(EnergyToPlot, model_abs, ls=ls, lw=lw, c=self.color, label=label)
print "dN/dE(", E, ") = ", electrons(E) # In[46]: #now, to get the total emission from those electrons. #naima supports three emission modes: Synchrotron, Bremsstrahlung, Inverse Compton synch = Synchrotron(electrons, B=3 * u.uG, Eemin=1 * u.GeV, Eemax=510 * u.TeV, nEed=100) IC = InverseCompton(electrons, seed_photon_fields=["CMB", "NIR", "FIR"], Eemin=1 * u.GeV, Eemax=510 * u.TeV, nEed=300) brems = Bremsstrahlung(electrons, n0=1.0 / u.cm**3, Eemin=1 * u.GeV, Eemax=510 * u.TeV, nEed=100) #set normalization by fixing the total electron energy. For some reason, this is done #via the emission spectrum. synch.set_We(10**50 * u.erg) #units check... print "Flux dN/dE:", synch.flux([1] * u.keV, distance=2 * u.kpc)
beta=2.) eopts = {'Eemax': 50 * u.PeV, 'Eemin': 0.1 * u.GeV} SYN = Synchrotron(ECBPL, B=125 * u.uG, Eemax=50 * u.PeV, Eemin=0.1 * u.GeV) # Compute photon density spectrum from synchrotron emission assuming R=2.1 pc Rpwn = 2.1 * u.pc Esy = np.logspace(-7, 9, 100) * u.eV Lsy = SYN.flux(Esy, distance=0 * u.cm) # use distance 0 to get luminosity phn_sy = Lsy / (4 * np.pi * Rpwn**2 * c) * 2.24 IC = InverseCompton(ECBPL, seed_photon_fields=[ 'CMB', ['FIR', 70 * u.K, 0.5 * u.eV / u.cm**3], ['NIR', 5000 * u.K, 1 * u.eV / u.cm**3], ['SSC', Esy, phn_sy] ], Eemax=50 * u.PeV, Eemin=0.1 * u.GeV) # Use plot_data from naima to plot the observed spectra data = ascii.read('CrabNebula_spectrum.ecsv') figure = naima.plot_data(data, e_unit=u.eV) ax = figure.axes[0] # Plot the computed model emission energy = np.logspace(-7, 15, 100) * u.eV ax.loglog(energy, IC.sed(energy, 2 * u.kpc) + SYN.sed(energy, 2 * u.kpc), lw=3, c='k',
ECPL = ExponentialCutoffPowerLaw(1e36 * u.Unit('1/eV'), 1 * u.TeV, 2.0, 13 * u.TeV) SYN = Synchrotron(ECPL, B=100 * u.uG) # Define energy array for synchrotron seed photon field and compute # Synchroton luminosity by setting distance to 0. Esy = np.logspace(-6, 6, 100) * u.eV Lsy = SYN.flux(Esy, distance=0 * u.cm) # Define source radius and compute photon density R = 2 * u.pc phn_sy = Lsy / (4 * np.pi * R**2 * c) * 2.26 # Create IC instance with CMB and synchrotron seed photon fields: IC = InverseCompton( ECPL, seed_photon_fields=['CMB', 'FIR', 'NIR', ['SSC', Esy, phn_sy]]) # Compute SEDs spectrum_energy = np.logspace(-8, 14, 100) * u.eV sed_IC = IC.sed(spectrum_energy, distance=1.5 * u.kpc) sed_SYN = SYN.sed(spectrum_energy, distance=1.5 * u.kpc) # Plot plt.figure(figsize=(8, 5)) #plt.rc('font', family='sans') #plt.rc('mathtext', fontset='custom') ssc = IC.sed(spectrum_energy, seed='SSC', distance=1.5 * u.kpc) plt.loglog(spectrum_energy, ssc, lw=1.5, ls='-',
#naima models are phyical and accept/return astropy quantities. #Try: electrons( 2.0 ) without a unit... for E in [ 1*u.GeV, 1000*u.GeV, 1*u.TeV]: print "dN/dE(", E, ") = ", electrons(E) # In[46]: #now, to get the total emission from those electrons. #naima supports three emission modes: Synchrotron, Bremsstrahlung, Inverse Compton synch = Synchrotron(electrons, B=3*u.uG, Eemin = 1*u.GeV, Eemax = 510*u.TeV, nEed = 100) IC = InverseCompton(electrons, seed_photon_fields=["CMB", "NIR", "FIR"], Eemin = 1*u.GeV, Eemax = 510*u.TeV, nEed = 300) brems = Bremsstrahlung(electrons, n0=1.0/u.cm**3, Eemin = 1*u.GeV, Eemax = 510*u.TeV, nEed = 100) #set normalization by fixing the total electron energy. For some reason, this is done #via the emission spectrum. synch.set_We(10**50 * u.erg) #units check... print "Flux dN/dE:", synch.flux([1]*u.keV, distance=2*u.kpc) print "SED E^2dN/dE:", synch.sed([1]*u.keV, distance=2*u.kpc) # In[47]:
e_cutoff=1863 * u.TeV, beta=2.) eopts = {'Eemax': 50 * u.PeV, 'Eemin': 0.1 * u.GeV} SYN = Synchrotron(ECBPL, B=125 * u.uG, Eemax=50 * u.PeV, Eemin=0.1 * u.GeV) # Compute photon density spectrum from synchrotron emission assuming R=2.1 pc Rpwn = 2.1 * u.pc Esy = np.logspace(-7, 9, 100) * u.eV Lsy = SYN.flux(Esy, distance=0 * u.cm) # use distance 0 to get luminosity phn_sy = Lsy / (4 * np.pi * Rpwn**2 * c) * 2.24 IC = InverseCompton(ECBPL, seed_photon_fields=['CMB', ['FIR', 70 * u.K, 0.5 * u.eV / u.cm**3], ['NIR', 5000 * u.K, 1 * u.eV / u.cm**3], ['SSC', Esy, phn_sy]], Eemax=50 * u.PeV, Eemin=0.1 * u.GeV) # Use plot_data from naima to plot the observed spectra data = ascii.read('CrabNebula_spectrum.ecsv') figure = naima.plot_data(data, e_unit=u.eV) ax = figure.axes[0] # Plot the computed model emission energy = np.logspace(-7, 15, 100) * u.eV ax.loglog(energy, IC.sed(energy, 2 * u.kpc) + SYN.sed(energy, 2 * u.kpc), lw=3, c='k', label='Total') for i, seed, ls in zip( range(4), ['CMB', 'FIR', 'NIR', 'SSC'], ['--', '-.', ':', '-']): ax.loglog(energy, IC.sed(energy, 2 * u.kpc, seed=seed),
def do_fit( ThetaIC, # np.array([90, 90]), Pos3D, # [[1, 1, 1], [1, 1, 1]], Dist, # np.array([2, 2]), label='', do_abs=True, lgEdot_min=31, lgEdot_max=37.5, lgEdot_bins=10, lgSigma_min=-3, lgSigma_max=-1, lgSigma_bins=10, Tstar=pars.TSTAR_LS, Rstar=pars.RSTAR_LS, AlphaSigma=1, Mdot=pars.MDOT_LS, Vw=pars.VW_LS): logging.info('Starting fitting') OutFit = open('fit_results/fit_results_ls5039_' + label + '.txt', 'w') # Loading data phaseData, fluxSuzaku, fluxErrSuzaku, gammaSuzaku, gammaErrSuzaku = get_data_ls5039( 'SUZAKU') phaseData, fluxHESS, fluxErrHESS, gammaHESS, gammaErrHESS = get_data_ls5039( 'HESS') logging.debug('PhaseData') logging.debug(phaseData) # Loading energy energyXrays = np.logspace(0, 1, 5) energyGamma = np.logspace(math.log10(0.2e9), math.log10(5e9), 10) energyAll = np.concatenate((energyXrays, energyGamma)) logging.debug('Energies') logging.debug(energyXrays) logging.debug(energyGamma) logging.debug(energyAll) # Loading grid NEdot = int((lgEdot_max - lgEdot_min) * lgEdot_bins) NSigma = int((lgSigma_max - lgSigma_min) * lgSigma_bins) Edot_list = np.logspace(lgEdot_min, lgEdot_max, int(NEdot)) Sigma_list = np.logspace(lgSigma_min, lgSigma_max, int(NSigma)) logging.info('{} iterations'.format(len(Edot_list) * len(Sigma_list))) if (len(ThetaIC) != len(phaseData) or len(Pos3D) != len(phaseData) or len(Dist) != len(phaseData)): logging.error('Argument with wrong dimensions - aborting') return None # Absorption if not do_abs: logging.info('Skipping absorption') else: if Path('abs_pars.json').exists(): logging.debug('Reading abs pars') with open('abs_pars.json', 'r') as file: data = json.load(file) DistFrac = data['DistFrac'] DistTau = data['DistTau'] Tau = data['Tau'] else: # Computing Taus logging.info('Computing absorption') start = time.time() Obs = np.array([0, 0, -1]) Abs = abso.Absorption(Tstar=Tstar, Rstar=Rstar, name_table='absorption_table_ls5039.dat') Tau = list() DistTau = list() for iph in range(len(phaseData)): DistTau.append(list()) tt = dict() for i in range(len(energyAll)): tt[i] = list() Tau.append(tt) DistFrac = np.concatenate( (np.linspace(0.005, 0.2, 20), np.linspace(0.201, 1.0, 10))) for ff in DistFrac: for iph in range(len(phaseData)): dist = ff * norm(Pos3D[iph]) PosStar = Pos3D[iph] * dist / norm(Pos3D[iph]) for ien in range(len(energyAll)): tau = Abs.TauGG(en=energyAll[ien] * u.keV.to(u.TeV), obs=Obs, pos=PosStar) Tau[iph][ien].append(tau) DistTau[iph].append(dist) logging.info('Abs done, dt/s = {}'.format(time.time() - start)) absToSave = dict() absToSave['DistFrac'] = list(DistFrac) absToSave['DistTau'] = list(DistTau) absToSave['Tau'] = list(Tau) logging.debug('Writing abs to json file') with open('abs_pars.json', 'w') as file: json.dump(absToSave, file) # # Ploting tau vs dist # plt.figure(figsize=(8, 6), tight_layout=True) # ax = plt.gca() # ax.set_yscale('log') # ax.set_ylabel(r'$\tau_{\gamma \gamma}$') # ax.set_xlabel(r'$D$ [AU]') # ax.plot(DistTau[7], Tau[7][str(5)], marker='o', linestyle='-') # ax.plot(DistTau[7], Tau[7][str(13)], marker='o', linestyle='-') # plt.show() chisqMin = 1e10 minEdot = 0 minSigma = 0 for (Edot, Sigma) in itertools.product(Edot_list, Sigma_list): print('Starting Edot={}, Sigma={}'.format(Edot, Sigma)) # Computed parameters DistPulsar = [ psr.Rshock(Edot=Edot, Mdot=Mdot, Vw=Vw, D=d) for d in Dist ] DistStar = Dist - DistPulsar SigmaFac = [pow(0.1 / d, AlphaSigma) for d in DistPulsar] SigmaShock = [Sigma * f for f in SigmaFac] Bfield = [ psr.B2_KC(Edot=Edot, Rs=dp, sigma=s) for (dp, s) in zip(DistPulsar, SigmaShock) ] Density = [ psr.PhotonDensity(Tstar=Tstar, Rstar=Rstar, d=d) for d in DistStar ] # plt.figure(figsize=(8, 6), tight_layout=True) # ax = plt.gca() # ax.set_yscale('log') # ax.set_ylabel(r'$\tau_{\gamma \gamma}$') # ax.set_xlabel(r'$D$ [AU]') # ax.plot(DistPulsar, SigmaShock, marker='o', linestyle='-') # plt.show() # logging.debug('DistPulsar') # logging.debug(DistPulsar) # logging.debug('DistStar') # logging.debug(DistStar) # logging.debug('SigmaShock') # logging.debug(SigmaShock) # logging.debug('SigmaFac') # logging.debug(SigmaFac) logging.debug('Bfield') logging.debug(Bfield) logging.debug('MeanBfield') logging.debug(sum(Bfield) / len(Bfield)) if 0 in Bfield: logging.info('Bfield is 0 - skipping') continue # Normalization NormStart = np.array([1e23 / b for b in Bfield]) npar = len(phaseData) # Further parameters Ecut = [rad.Emax(b, 1) * u.TeV for b in Bfield] Eref = 1 * u.TeV Emax = 100 * u.PeV Emin = 10 * u.GeV SourceDist = pars.SRC_DIST_LS * u.kpc # Computing Alpha Alpha = [2 * g - 1 for g in gammaSuzaku] # print('Alpha') # print(Alpha) # print('gamma') # print(gammaSuzaku) # Computing Model tau = list() modelAll = list() for iph in range(len(phaseData)): thisTau = list() if do_abs: for ien in range(len(energyAll)): thisTau.append( np.interp(DistStar[iph], xp=DistTau[iph], fp=Tau[iph][str(ien)])) else: thisTau = [0] * len(energyAll) tau.append(thisTau) ECPL = ExponentialCutoffPowerLaw(amplitude=1e20 / u.eV, e_0=Eref, alpha=Alpha[iph], e_cutoff=Ecut[iph]) SYN = Synchrotron(particle_distribution=ECPL, B=Bfield[iph] * u.G, Eemax=Emax, Eemin=Emin) IC = InverseCompton(particle_distribution=ECPL, seed_photon_fields=[[ 'STAR', Tstar * u.K, Density[iph] * u.erg / u.cm**3, ThetaIC[iph] * u.deg ]], Eemax=Emax, Eemin=Emin) thisModel = (SYN.sed(photon_energy=[e * u.keV for e in energyAll], distance=SourceDist) + IC.sed(photon_energy=[e * u.keV for e in energyAll], distance=SourceDist)) if do_abs: thisModel = [ math.exp(-t) * m for (m, t) in zip(thisModel, thisTau) ] # Ploting tau vs dist # plt.figure(figsize=(8, 6), tight_layout=True) # ax = plt.gca() # ax.set_yscale('log') # ax.set_xscale('log') # ax.set_ylabel(r'$\tau_{\gamma \gamma}$') # ax.set_xlabel(r'$E$ [keV]') # print(energyAll) # print(thisTau) # ax.plot(energyAll[5:], thisTau[5:], marker='o', linestyle='-') # ax.set_xlim(1e8, 1e10) # plt.show() modelAll.append(thisModel) # END for fluxModelSuzaku, fluxModelHESS, gammaModelHESS = list(), list(), list() for thisModel in modelAll: sedSuzaku = [f for (f, e) in zip(thisModel, energyAll) if e < 1e3] energySuzaku = [e for e in energyAll if e < 1e3] sedHESS = [f for (f, e) in zip(thisModel, energyAll) if e > 1e3] energyHESS = [e for e in energyAll if e > 1e3] fluxModelSuzaku.append(getSuzakuFlux(sedSuzaku, energySuzaku)) n, g = getHESSFluxAndGamma(sedHESS, energyHESS) fluxModelHESS.append(n) gammaModelHESS.append(g) def computeModelPars(N, model, energy): thisModel = [(N / 1e20) * m for m in model] sedSuzaku = [f for (f, e) in zip(thisModel, energy) if e < 1e3] energySuzaku = [e for e in energyAll if e < 1e3] sedHESS = [f for (f, e) in zip(thisModel, energy) if e > 1e3] energyHESS = [e for e in energyAll if e > 1e3] thisFluxModelSuzaku = getSuzakuFlux(sedSuzaku, energySuzaku) thisFluxModelHESS, thisGammaModelHESS = getHESSFluxAndGamma( sedHESS, energyHESS) return thisFluxModelSuzaku, thisFluxModelHESS, thisGammaModelHESS chisqFit, nFit = list(), list() fluxFitSuzaku, fluxFitHESS, gammaFitHESS = list(), list(), list() for ii in range(len(phaseData)): def least_square(n): chisq = 0 fitFluxModelSuzaku, fitFluxModelHESS, fitGammaModelHESS = computeModelPars( n, modelAll[ii], energyAll) chisq += ((fitFluxModelSuzaku.value * 1e12 - fluxSuzaku[ii]) / fluxErrSuzaku[ii])**2 chisq += ((fitFluxModelHESS.value * 1e12 - fluxHESS[ii]) / fluxErrHESS[ii])**2 # chisq += ((fitGammaModelHESS - gammaHESS[ii]) / gammaErrHESS[ii])**2 return chisq minuit = Minuit(least_square, n=NormStart[ii], fix_n=False, limit_n=(NormStart[ii] * 0.0001, NormStart[ii] * 10000), errordef=1.) fmin, param = minuit.migrad() chisqFit.append(minuit.fval) nFit.append(param[0]['value']) fitFS, fitFH, fitGH = computeModelPars(param[0]['value'], modelAll[ii], energyAll) fluxFitSuzaku.append(fitFS) fluxFitHESS.append(fitFH) gammaFitHESS.append(fitGH) # print('N*B') # print([n * b for (n,b) in zip(nFit, Bfield)]) # print([c / 2 for c in chisqFit]) totalChiSq = sum(chisqFit) / 10. if totalChiSq < chisqMin: chisqMin = totalChiSq minEdot = Edot minSigma = Sigma print('ChiSq = {}'.format(totalChiSq)) if totalChiSq < 1e20: plotResults(phaseData=phaseData, nFit=nFit, fluxFitSuzaku=fluxFitSuzaku, fluxSuzaku=fluxSuzaku, fluxErrSuzaku=fluxErrSuzaku, fluxFitHESS=fluxFitHESS, fluxHESS=fluxHESS, fluxErrHESS=fluxErrHESS, gammaFitHESS=gammaFitHESS, gammaHESS=gammaHESS, gammaErrHESS=gammaErrHESS, modelAll=modelAll, energyAll=energyAll) continue # logging.info('Fit') # logging.info('ChiSq/ndf = {}'.format(chisq_min / ndf)) # logging.info('ChiSq - ndf = {}'.format(chisq_min - ndf)) # # plot testing # for ii, nn in enumerate(n_fit): # if fix_n[ii]: # continue # plt.figure(figsize=(8, 6), tight_layout=True) # ax = plt.gca() # ax.set_xscale('log') # ax.set_yscale('log') # ax.set_title(ii) # ax.errorbar( # data_en[ii], # data_fl[ii], # yerr=data_fl_er[ii], # marker='o', # linestyle='none' # ) # ax.plot( # data_en[ii], # [(nn / 1e20) * m.value for m in model[ii]], # marker='o', # linestyle='none' # ) # plt.show() # print('p-value', p_value) # if do_abs: # TauPrint0 = [tau0[len(data_en0) - 4], tau0[len(data_en0) - 1]] # TauPrint1 = [tau1[len(data_en1) - 3], tau1[len(data_en1) - 1]] # else: # TauPrint0 = [0, 0] # TauPrint1 = [0, 0] if chisq_min - ndf < 1e3: OutFit.write(str(chisq_min) + ' ') OutFit.write(str(ndf) + ' ') for ii in range(pars.MAX_PERIOD): if not fix_n[ii]: OutFit.write(str(math.log10(n_fit[ii])) + ' ') OutFit.write(str(math.log10(Edot)) + ' ') OutFit.write(str(math.log10(Sigma)) + ' ') for ii in range(pars.MAX_PERIOD): if not fix_n[ii]: idx = periods.index(ii) OutFit.write(str(Dist[idx]) + ' ') OutFit.write(str(DistPulsar[idx]) + ' ') OutFit.write(str(Bfield[idx]) + ' ') # OutFit.write(str(TauPrint0[0]) + ' ') # OutFit.write(str(TauPrint0[1]) + ' ') # OutFit.write(str(TauPrint1[0]) + ' ') # OutFit.write(str(TauPrint1[1]) + '\n') OutFit.write('\n') print('ChiSqMin {}'.format(chisqMin)) print('lgEdot {}'.format(math.log10(minEdot))) print('Sigma {}'.format(minSigma)) OutFit.close()
class ElectronIC(SpectralModel): """This class inherits from SpectralModel in 3ML, and can be used to infer the population of electrons in a source. The fit works as follows: 1. Choose a parametric form for the electron spectrum, e.g., a power law with an exponential cutoff. 2. Use Inverse Compton scattering to calculate the gamma-ray flux. 3. Fit the calculated gamma-ray flux to the data using one of the plugins available in 3ML. The free parameters of this model include the parameters of the electron spectrum and the distance to the source. Additional quantities which affect the calculation are the components of the interstellar radiation field (ISRF) which contribute to the IC flux. These are not floated in the fit. Users may wish to obtain an estimate of the ISRF in the vicinity of the source of interest using GALPROP. """ def setup(self): self.functionName = "ElectronIC" self.formula = r"$f(E)=A(E/E_{\rm piv}}^\gamma}$" self.parameters = collections.OrderedDict() self.parameters["gamma"] = Parameter("gamma", -2., -10., 10, 0.1, fixed=False, nuisance=False, dataset=None) self.parameters["logA"] = Parameter("logA", -4., -40., 30, 0.1, fixed=False, nuisance=False, dataset=None) self.parameters["Epiv"] = Parameter("Epiv", 1., 1e-10, 1e10, 1., fixed=True, unit="keV") self.parameters["dist"] = Parameter("dist", 1., 1e-10, 1e10, 1., fixed=True) self.ncalls = 0 self.pdist_unit = 1. / u.Unit(m_e * c**2) self.PL = PowerLaw(1 * self.pdist_unit, 1 * u.keV, -2.5) self.IC = InverseCompton( self.PL, seed_photon_fields=[ 'CMB', ['FIR', 26.5 * u.K, 0.415 * u.eV / u.cm**3] ], Eemin=1 * u.TeV) # def integral(E1, E2): # a = self.parameters["gamma"].value # Ep = self.parameters["Epiv"].value # A = 10.**self.parameters["logA"].value # # if a == -1.: # def f(energy): # return A * E0 * np.log(energy) # else: # def f(energy): # return A * energy * (energy/Ep)**a / (a + 1.) # return f(E2) - f(E1) # # self.integral = integral def __call__(self, energy): # pdist_unit = 1. / u.Unit(m_e * c**2) self.ncalls += 1 # Convert spectral index to naima sign convention a = -self.parameters["gamma"].value # Convert to naima base units: all energies in keV Ep = self.parameters["Epiv"].value * u.keV # Normalization is actually for electron differential spectrum A = 10.**self.parameters["logA"].value * self.pdist_unit # Initialize the electron particle distribution self.PL.amplitude = A self.PL.e_0 = Ep self.PL.alpha = a # Fix the distance of the source, in kpc dist = self.parameters["dist"].value * u.kpc if type(energy) is float or type(energy) is int: E = [energy] * u.keV else: E = energy * u.keV icFlux = self.IC.flux(E, distance=dist) return icFlux.to(1. / (u.keV * u.cm**2 * u.s)).value def electronFlux(self, energy): # Convert spectral index to naima sign convention a = -self.parameters["gamma"].value # Convert to naima base units: all energies in keV Ep = self.parameters["Epiv"].value * u.keV # Normalization is actually for electron differential spectrum A = 10.**self.parameters["logA"].value * self.pdist_unit # Initialize the electron particle distribution PL = PowerLaw(A, Ep, a) if type(energy) is float or type(energy) is int: E = [energy] * u.keV else: E = energy * u.keV return PL(E).to(1. / u.keV).value def photonFlux(self, E1, E2): return self.integral(E1, E2) def energyFlux(self, E1, E2): a = self.parameters["gamma"].value Ep = self.parameters["Epiv"].value A = 10.**self.parameters["logA"].value if a == 2: def eF(E): return np.maximum(A * np.log(E / Ep), 1e-100) else: def eF(E): return np.maximum(A * np.power(E / Ep, 2 - a) / (2 - a), 1e-100) return (eF(E2) - eF(E1)) * self.keVtoErg