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 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 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 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 log_likelihood(e_cutoff, data, amplitude, alpha, B, Eemin, Eemax): crab_distance = 2.2 * u.kpc ECPL = ExponentialCutoffPowerLaw(amplitude=amplitude / u.eV, e_0=1 * u.TeV, alpha=alpha, e_cutoff=abs(e_cutoff) * u.erg) SYN = Synchrotron(ECPL, B=B, Eemin=Eemin, Eemax=Eemax) model = SYN.sed(data['energy'].quantity, distance=crab_distance) sigma = (data['flux_error_lo'].quantity + data['flux_error_hi'].quantity) / 2 sigma2 = np.where(sigma != 0, sigma, np.ones_like(sigma)) loglik = np.sum(np.log((model.value - data['flux'].data)**2)) return loglik - 2 * np.sum(np.log(sigma2))
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 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 tryecut(ecut_arr, data, amplitude, alpha, B, Eemin, Eemax): liktrial = np.zeros(len(ecut_arr)) for i in range(len(ecut_arr)): ECPL = ExponentialCutoffPowerLaw(amplitude=amplitude / u.eV, e_0=1 * u.TeV, alpha=alpha, e_cutoff=ecut_arr[i]) SYN = Synchrotron(ECPL, B=B, Eemin=Eemin, Eemax=Eemax) amp_cor = fitfactor(data, SYN) liktrial[i] = trylik(ecut_arr[i], data, amplitude * amp_cor, alpha, B, Eemin, Eemax) result = ecut_arr[np.where(liktrial == np.min(liktrial))] #print(liktrial) dof = len(np.asarray(data['flux'].data)) if np.min(liktrial) > dof: print('Warning: Minimum Log-likelihood > degrees of freedom') return result
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()
InverseCompton, ) ECBPL = ExponentialCutoffBrokenPowerLaw( amplitude=3.699e36 / u.eV, e_0=1 * u.TeV, e_break=0.265 * u.TeV, alpha_1=1.5, alpha_2=3.233, e_cutoff=1863 * u.TeV, beta=2.0, ) 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], ],
import numpy as np import matplotlib.pyplot as plt import naima from naima.models import (ExponentialCutoffPowerLaw, Synchrotron, InverseCompton) from astropy.constants import c import astropy.units as u 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)
import astropy.units as u import naima from naima.models import (ExponentialCutoffBrokenPowerLaw, Synchrotron, InverseCompton) ECBPL = ExponentialCutoffBrokenPowerLaw(amplitude=3.699e36 / u.eV, e_0=1 * u.TeV, e_break=0.265 * u.TeV, alpha_1=1.5, alpha_2=3.233, 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
beta=beta, ) lab = ExponentialCutoffBrokenPowerLaw( amplitude=amplitude * delta**3, e_0=e_0 * delta, e_break=e_break * delta, alpha_1=alpha_1, alpha_2=alpha_2, e_cutoff=e_cutoff * delta, beta=beta, ) # 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,
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)
def tophat(E0, g0, energy, time, theta_obs, D_L): mu_obs = np.cos(theta_obs) z = z_at_value(Planck15.luminosity_distance, D_L) if isinstance(energy.to_value(u.eV), float): energy = np.array([energy.to_value(u.eV)]) * u.eV # calc: R_b, t_b, Gamma_sh u0, b0 = np.sqrt(g0**2 - 1), np.sqrt(1 - 1 / g0**2) if g0 == 1.0: return 0 * u.erg / u.cm**2 / u.s R_dec = ((3. * E0 / (4. * np.pi * n_amb * m_p * c**2 * (g0**2 - 1)))**(1 / 3)).to(u.pc) xi_z = (c * time / (1 + z) / R_dec).cgs if np.isposinf(alpha_stf): u_xi = lambda xi: u0 if xi < 1e-1 else (u0 * xi**( -3 / 2) if xi > 1e1 else np.sqrt( ((g0 + 1) / 2 * xi**(-3) * (np.sqrt(1 + 4 * g0 / (g0 + 1) * xi**3 + 4 / (g0 + 1)**2 * xi**6) - 1))**2 - 1)) else: ui = np.inf eiso_u = lambda u: (max(u0, min(ui, u))**(-alpha_stf) - ui**( -alpha_stf)) / (u0**(-alpha_stf) - ui**(-alpha_stf)) I = lambda u: alpha_stf / (alpha_stf + 2) * u**(-alpha_stf - 2) * ( 1 + hyp2f1(-1 / 2, -1 - alpha_stf / 2, -alpha_stf / 2, -u**2)) miso_u = lambda u: (I(max(u0, min(ui, u))) - I(ui)) / (u0**( -alpha_stf) - ui**(-alpha_stf)) u_xi = lambda xi: fsolve( lambda _u: xi**3 * (_u[0] / u0)**2 - eiso_u(_u[0]) + miso_u(_u[0]) * (np.sqrt(_u[0]**2 + 1) - 1), u0)[0] eats = lambda xi: -mu_obs * xi + quad( lambda _xi: np.sqrt(u_xi(_xi)**2 + 1) / u_xi(_xi), 0, xi)[0] xi = fsolve(lambda _xi: eats(_xi[0]) - xi_z, b0 * xi_z / (1 - b0 * mu_obs))[0] R_b = xi * R_dec t_b = (R_dec / c).cgs * quad( lambda _xi: np.sqrt(u_xi(_xi)**2 + 1) / u_xi(_xi), 0, xi)[0] Gamma_sh = np.sqrt(u_xi(xi)**2 + 1) if Gamma_sh == 1.0: return 0 * u.erg / u.cm**2 / u.s # calc: electron distribution specific_heat_ratio = 4 / 3 + 1 / Gamma_sh compression_ratio = (specific_heat_ratio * Gamma_sh + 1) / (specific_heat_ratio - 1) B = (np.sqrt(8 * np.pi * eps_B * compression_ratio * n_amb * m_p * c**2 * (Gamma_sh - 1))).to((u.erg * pcm)**(1 / 2)) Ne = zeta_e * 4 / 3 * np.pi * R_b**3 * n_amb gm = (eps_e / zeta_e * (p_e - 2) / (p_e - 1) * m_p / m_e * (Gamma_sh - 1)).cgs _gc = 6 * np.pi * mec * Gamma_sh / (sigma_T * B**2 * t_b) Y = (-1 + np.sqrt(1 + 4 * min(1, (gm / _gc)**(p_e - 2)) * eps_e / eps_B)) / 2 gc = _gc.cgs / (1 + Y) # rough estimate from Sari & Esin (2001) e_syn_max = (min(np.sqrt(3 * e / (sigma_T * B * (1 + Y))), (e * B * R_b) / (12 * 2 * np.pi * Gamma_sh * mec2)) * mec2).to(u.TeV) electrons = ExponentialCutoffBrokenPowerLaw( amplitude=(Ne * (p_e - 1) / (max(2., gm) * mec2) * min(1., (gm / 2.)**(p_e - 1)) if gm < gc else Ne / (max(2., gc) * mec2) * min(1., gc / 2.)).to(1 / u.eV), e_0=(max(2., min(gm, gc)) * mec2).to(u.TeV), e_break=(max(2., max(gm, gc)) * mec2).to(u.TeV), alpha_1=p_e if gm < gc else 2., alpha_2=p_e + 1, e_cutoff=max(((max(2., min(gm, gc)) + 1) * mec2).to(u.TeV), e_syn_max), beta=2.0, ) # calc: syn+ic flux SYN = Synchrotron( electrons, B=B.to_value((u.erg * pcm)**(1 / 2)) * u.G, Eemax=electrons.e_cutoff, Eemin=electrons.e_0, nEed=50, ) '''E_ph = np.logspace(-7, 14, 22) * u.eV L_syn = self.SYN.flux(E_ph, distance=0 * u.cm) phn_syn = L_syn / (4 * np.pi * self.R ** 2 * c) * 2.24 IC = InverseCompton( self.electrons, 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", E_ph, phn_syn], ], Eemax=self.electrons.e_cutoff, Eemin=self.electrons.e_0, nEed=50, )''' Doppler = 1 / (Gamma_sh * (1 - np.sqrt(1 - 1 / Gamma_sh**2) * mu_obs)) flx = Doppler**4 * SYN.sed((1 + z) * energy / Doppler, D_L)[0] tran = EblAbsorptionModel(redshift=z).transmission(e=energy)[0] return (flx * tran).to(u.erg / u.cm**2 / u.s)
# In[8]: #to illustrate the use of units and how to access the spectra. #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)
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()
# In[8]: #to illustrate the use of units and how to access the spectra. #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)