def __init__( self, i, # input energy bin nphot, # number of photons geometry, verbose=False): self.verbose = verbose self.rad = numpy.zeros(nphot) self.phi = numpy.zeros(nphot) # initial left-right angle for position self.theta = numpy.zeros(nphot) # initial up-down angle for position self.alpha = rng.uniform( 0, 2 * pi, size=nphot ) # initial left-right direction for direction -- value does not matter due to symmetry #mu = numpy.linspace(-1, 1, nphot) # uniform distribution mu = rng.uniform(-1, 1, size=nphot) self.beta = acos(mu) # up-down angle for direction # self.beta = acos(numpy.linspace(-cone_in, cone_in, nphot)) # up-down angle for direction self.geometry = geometry energy_lo, energy_hi = bin2energy(i) e = (energy_lo + energy_hi) / 2. if self.verbose: print('PhotonBunch of size %d with energy %.2f keV' % (nphot, e)) #self.energy = e * numpy.ones(nphot) self.energy = rng.uniform(low=energy_lo, high=energy_hi, size=nphot) #bin = energy2bin(self.energy) #assert (bin == i).all(), (bin.min(), bin.max(), self.energy.min(), self.energy.max(), energy_lo, energy_hi, self.energy[bin!=i]) self.bin = i * numpy.ones(nphot, dtype=numpy.uint) self.stuck = self.rad != 0 # False
def run(prefix, nphot, nmu, n_nh_bins, geometry, binmapfunction, verbose=False): rdata_transmit = numpy.zeros((nbins, nbins, nmu*n_nh_bins)) rdata_reflect = numpy.zeros((nbins, nbins, nmu*n_nh_bins)) #rdata = [0] * nbins energy_lo, energy_hi = bin2energy(list(range(nbins))) binrange = [list(range(nbins+1)), list(range(nmu*n_nh_bins+1))] for i in tqdm.trange(nbins-1, -1, -1): photons = PhotonBunch(i=i, nphot=nphot, verbose=verbose, geometry=geometry) for n_interactions in range(1000): emission, more = photons.pump() if emission is None and not more: break if emission is None: continue if len(emission['energy']) == 0: if not more: break continue if verbose: print(' received %d emitted photons (after %d interactions)' % (len(emission['energy']), n_interactions)) beta = emission['beta'] alpha = emission['alpha'] assert (beta <= pi).all(), beta assert (beta >= 0).all(), beta # vertical bin, i.e. which viewing angle can see this photon? mbin = numpy.asarray(binmapfunction(beta=beta, alpha=alpha)).astype(numpy.uint) # highest bin exceeded due to rounding mbin[mbin == nmu] = nmu - 1 # bin in NH nh = geometry.compute_los_nh(beta, alpha) nh[nh<1e-2] = 1e-2 kbin = ((log10(nh) + 2) * n_nh_bins / (4 + 2)).astype(int) kbin[kbin == n_nh_bins] = n_nh_bins - 1 mkbin = kbin * nmu + mbin bins = emission['bin'] # produce unique array bins, mbin which contains counts counts, xedges, yedges = numpy.histogram2d(bins, mkbin, bins=binrange) # record into histogram if it landed within relevant range if n_interactions < 1: rdata_transmit[i] += counts else: rdata_reflect[i] += counts del counts, emission, bins if not more: break del photons return (rdata_transmit, rdata_reflect), nphot
from __future__ import print_function, division import numpy from numpy import pi, exp import h5py import astropy.io.fits as pyfits import sys import progressbar from binning import nbins, energy2bin, bin2energy energy_lo, energy_hi = bin2energy(numpy.arange(nbins)) energy = (energy_hi + energy_lo) / 2 deltae = energy_hi - energy_lo table = [] PhoIndices = [ 1., 1.20000005, 1.39999998, 1.60000002, 1.79999995, 2., 2.20000005, 2.4000001, 2.5999999, 2.79999995, 3. ] Ecuts = [20., 30, 40, 60, 100, 140, 200, 400] nh_bins = numpy.array([ 9.99999978e-03, 1.41000003e-02, 1.99999996e-02, 2.82000005e-02, 3.97999994e-02, 5.62000014e-02, 7.94000030e-02, 1.12000003e-01, 1.58000007e-01, 2.24000007e-01, 3.16000015e-01, 4.46999997e-01, 6.30999982e-01, 8.90999973e-01, 1.25999999e+00, 1.77999997e+00, 2.50999999e+00, 3.54999995e+00, 5.01000023e+00, 7.07999992e+00, 1.00000000e+01, 1.41000004e+01, 2.00000000e+01, 2.82000008e+01, 3.97999992e+01, 5.62000008e+01, 7.94000015e+01, 1.12000000e+02, 1.58000000e+02, 2.24000000e+02, 3.16000000e+02, 4.47000000e+02, 6.31000000e+02, 8.91000000e+02, 1.26000000e+03, 1.78000000e+03, 2.51000000e+03, 3.55000000e+03, 5.01000000e+03, 7.08000000e+03,
--------------- Loading and computation of neutral, solar-abundance cross-sections. """ import numpy import scipy from numpy import pi, arccos as acos, tan, round, exp, log, log10, sin, cos, logical_and, logical_or import binning import os electmass = 511. # electron rest mass in keV/c^2 xscatt = numpy.zeros(binning.nbins) energy_lo, energy_hi = binning.bin2energy(numpy.arange(binning.nbins)) energy = (energy_hi + energy_lo) / 2. deltae = energy_hi - energy_lo xthom = 6.7e-4 # Thomson cross section x = energy / electmass # energy in units of electron rest mass # compute scattering cross section # Thomson regime xscatt_thomson = xthom * (1. - (2. * x) + (26. * (x**2.) / 5.)) t1 = 1. + 2. * x t2 = 1. + x term1 = t2 / (x**3.) term2 = (2. * x * t2) / t1 term3 = (1. / (2. * x)) * log(t1) term4 = (1. + 3. * x) / (t1**2)
def run(prefix, nphot, nmu, geometry, binmapfunction, plot_paths=False, plot_interactions=False, verbose=False): if plot_paths or plot_interactions: import matplotlib.pyplot as plt rdata_transmit = numpy.zeros((nbins, nbins, nmu)) rdata_reflect = numpy.zeros((nbins, nbins, nmu)) #rdata = [0] * nbins energy_lo, energy_hi = bin2energy(list(range(nbins))) energy = (energy_hi + energy_lo) / 2. deltae = energy_hi - energy_lo binrange = [list(range(nbins + 1)), list(range(nmu + 1))] for i in tqdm.trange(nbins - 1, -1, -1): photons = PhotonBunch(i=i, nphot=nphot, verbose=verbose, geometry=geometry) remainder = [(photons.rad, photons.theta)] if plot_paths: plt.figure("paths", figsize=(4, 4)) for n_interactions in range(1000): emission, more = photons.pump() if emission is None and not more: break if emission is None: continue if len(emission['energy']) == 0: if not more: break continue if verbose: print(' received %d emitted photons (after %d interactions)' % (len(emission['energy']), n_interactions)) beta = emission['beta'] alpha = emission['alpha'] #beta = numpy.abs(beta) #beta[beta > pi] = pi - beta[beta > pi] #beta[beta > pi/2.] = pi/2. - beta[beta > pi/2.] assert (beta <= pi).all(), beta assert (beta >= 0).all(), beta #bins = energy2bin(energy) # vertical bin, i.e. which viewing angle can see this photon? mbin = numpy.asarray(binmapfunction( beta=beta, alpha=alpha)).astype(numpy.uint) # highest bin exceeded due to rounding mbin[mbin == nmu] = nmu - 1 bins = emission['bin'] # produce unique array bins, mbin which contains counts counts, xedges, yedges = numpy.histogram2d(bins, mbin, bins=binrange) # record into histogram if it landed within relevant range if n_interactions < 1: rdata_transmit[i] += counts else: rdata_reflect[i] += counts #if (emission['energy'] == 6.40).any(): # print ' %f: %d/%d are lines' % (energy[i], (emission['energy'] == 7.06).sum(), (emission['energy'] == 6.40).sum()) # linebin = set(bins[emission['energy'] == 6.40]) # print linebin, rdata[i][724,:], rdata[900][724,4] if i > 900 else '' # remove the emitted photons from the remainder if plot_paths: mask = emission['mask'] path = [(prev_rad[mask], prev_theta[mask]) for prev_rad, prev_theta in remainder] remainder = [(prev_rad[~mask], prev_theta[~mask]) for prev_rad, prev_theta in remainder ] + [(photons.rad, photons.theta)] rad_paths = numpy.transpose( [path_rad for path_rad, path_theta in path] + [2 * numpy.ones(mask.sum())]) theta_paths = numpy.transpose( [path_theta for path_rad, path_theta in path] + [beta]) plt.figure("paths") plot_path(rad_paths[:100], theta_paths[:100], color=(['b', 'r', 'g', 'y', 'k', 'm', 'w'] * 5)[n_interactions], alpha=1 - 0.75 * numpy.exp(-n_interactions / 5.)) if plot_interactions: print('plotting %d photons ...' % len(beta)) plot_interaction(nphot=nphot, n_interactions=n_interactions, **emission) #plt.savefig(prefix + "rdata_%d_%d.pdf" % (i, n_interactions)) plt.savefig(prefix + "rdata_%d_%d.png" % (i, n_interactions)) plt.close() print('plotting ... done') if not more: break if plot_paths: plt.figure("paths") plt.xlim(-1, 1) plt.ylim(-1, 1) plt.title('Energy: %.2f, %d interactions' % (energy[i], n_interactions)) #plt.savefig(prefix + "paths_%d.pdf" % (i)) plt.savefig(prefix + "paths_%d.png" % (i)) plt.close() return (rdata_transmit, rdata_reflect), nphot
def store(prefix, nphot, rdata, nmu, extra_fits_header={}, plot=False): energy_lo, energy_hi = bin2energy(list(range(nbins))) energy = (energy_hi + energy_lo) / 2. deltae = energy_hi - energy_lo import h5py try: print('Loading previous file "%s" if exists ...' % (prefix + "rdata.hdf5")) with h5py.File(prefix + "rdata.hdf5", 'r') as old_file: print(' reading values') rdata_old = old_file['rdata'][()] print(' reading header value') prev_nphot = old_file.attrs['NPHOT'] print('Accumulating onto previous result ...') rdata = rdata + rdata_old del rdata_old except Exception as e: if "error message = 'no such file or directory'" not in str(e).lower(): print('updating file failed; writing fresh. Error:', e) prev_nphot = 0 nphot_total = nphot + prev_nphot print(' storing ...') import datetime, time now = datetime.datetime.fromtimestamp(time.time()) nowstr = now.isoformat() nowstr = nowstr[:nowstr.rfind('.')] with h5py.File(prefix + "rdata.hdf5", 'w') as f: f.create_dataset('rdata', data=rdata, compression='gzip', shuffle=True) f.create_dataset('energy_lo', data=energy_lo, compression='gzip', shuffle=True) f.create_dataset('energy_hi', data=energy_hi, compression='gzip', shuffle=True) f.attrs[ 'CREATOR'] = """Johannes Buchner <*****@*****.**>""" f.attrs['DATE'] = nowstr f.attrs['METHOD'] = 'Monte-Carlo simulation code' f.attrs['NPHOT'] = nphot_total for k, v in extra_fits_header.items(): f.attrs[k] = v print(' total of %d input / %d output photons across %d bins' % (nphot_total, rdata.sum(), nbins)) if not plot: return nphot_total, rdata import matplotlib.pyplot as plt import sys PhoIndex = 2 matrix = rdata total = nphot_total deltae0 = deltae[energy >= 1][0] NH = 1e24 / 1e22 weights = (energy**-PhoIndex * deltae / deltae0).reshape( (-1, 1)) # * deltae.reshape((1, -1)) / deltae.reshape((-1, 1)) yall = (weights * matrix.sum(axis=2)).sum(axis=0) / deltae * deltae0 for mu in range(nmu): y = (weights * matrix[:, :, mu]).sum(axis=0) / deltae * deltae0 sys.stdout.write('plotting %d/%d ...\r' % (mu + 1, nmu)) sys.stdout.flush() plt.figure(figsize=(10, 10)) plt.plot(energy, exp(-xphot * NH) * energy**-PhoIndex, '-', color='red', linewidth=1) plt.plot(energy, exp(-xscatt * NH) * energy**-PhoIndex, '-', color='pink') plt.plot(energy, exp(-xlines_cumulative[:, 0] * NH) * energy**-PhoIndex, '-', color='orange') plt.plot(energy, energy**-PhoIndex, '--', color='gray') plt.plot(energy, y / total * nmu, '-', color='k') #, drawstyle='steps') plt.plot(energy, yall / total, '-', color='gray', alpha=0.3, linewidth=3) #, drawstyle='steps') #plt.plot(energy, exp(-xboth) * energy**-PhoIndex, '-', color='yellow') plt.gca().set_xscale('log') plt.gca().set_yscale('log') #plt.xlim(0.1, 10 * (1 + 10)) plt.xlim(1, 40) lo, hi = 1e-8, 1 plt.vlines(6.40, lo, hi, linestyles=[':'], color='grey', alpha=0.5) plt.vlines(7.06, lo, hi, linestyles=[':'], color='grey', alpha=0.5) #plt.vlines(8.33, lo, hi, linestyles=[':'], color='grey', alpha=0.5) #plt.vlines(9.4, lo, hi, linestyles=[':'], color='grey', alpha=0.5) #plt.vlines(10.4, lo, hi, linestyles=[':'], color='grey', alpha=0.5) plt.ylim(lo, hi) #plt.ylim(1e-5, 1e-3) #plt.xlim(6, 15) #plt.show() #plt.savefig(prefix + "_%d.pdf" % mu) plt.savefig(prefix + "_%d.png" % mu) #numpy.savetxt(prefix + "_%d.txt" % mu, numpy.vstack([energy, y]).transpose()) plt.close() print() return nphot_total, rdata