Module firesong.Firesong
The main module for simulating neutrino sources.
Expand source code
#!/usr/bin/python
# Authors: Chris Tung
# Ignacio Taboada
#
"""The main module for simulating neutrino sources."""
import argparse
import numpy as np
# Firesong code
from firesong.Evolution import get_evolution, SourcePopulation
from firesong.Evolution import TransientSourcePopulation, cosmology
from firesong.Luminosity import get_LuminosityFunction
from firesong.input_output import output_writer, print_config, get_outputdir
from firesong.sampling import InverseCDF
def firesong_simulation(outputdir,
filename='Firesong.out',
density=1e-9,
Evolution="MD2014SFR",
Transient=False,
timescale=1000.,
zmin=0.0005,
zmax=10.,
bins=10000,
fluxnorm=1.44e-8,
index=2.28,
LF="SC",
sigma=1.0,
luminosity=0.0,
emin=1e4,
emax=1e7,
seed=None,
verbose=True):
"""
Simulate a universe of neutrino sources
Args:
outputdir (str or None): path to write output. If None, return results
without writing a file
filename (str or None): name of the output file. If None, return
results without writing a file
density (float, optional, default=1e-9): local density of neutrino
sources. Units of Mpc^-3 (Mpc^-3 yr^-1 if Transient=True)
Transient (bool, optional, default=False): If true, simulate
transient neutrino sources instead of steady sources
timescale (bool, optional, default=1000): Timescale in seconds
for transient sources
zmin (float, optional, default=0.0005): Closest redshift to consider
zmax (float, optional, default=10.): Farthest redshift to consider
bins (int, optional, default=1000): Number of bins used when creating
the redshift PDF
fluxnorm (float, optional, default=1.44e-8): Normalization on the total
astrophysical diffuse flux, E^2dPhi/dE. Units of GeV s^-1 sr^-1
index (float, optional, default=2.28): Spectral index of diffuse flux
LF (string, optional, default="SC"): Luminosity function, choose
between standard candle (SC), LogNormal (LG)
sigma (float, optional, default=1.0): Width of lognormal distribution
if LF="LG"
luminosity (float, optional, default=0.0): Manually fix the
luminosity of sources if not equal to 0. Overrides fluxnorm.
Units of erg/yr
emin (float, optional, default=1e4): Minimum neutrino energy in GeV
emax (float, optional, default=1e7): Maximum neutrino energy in GeV
seed (int or None, optional, default=None): random number seed
verbose (bool, optional, default=True): print simulation paramaters
if True else suppress printed output
Returns:
dict: keys contain simulation results, including the input params
as well as the sources. Only returned if filename is None
"""
if Transient:
population = TransientSourcePopulation(cosmology,
get_evolution(Evolution),
timescale=timescale)
else:
population = SourcePopulation(cosmology, get_evolution(Evolution))
N_sample = int(population.Nsources(density, zmax))
if luminosity == 0.0:
## If luminosity not specified calculate luminosity from diffuse flux
luminosity = population.StandardCandleLuminosity(fluxnorm,
density,
zmax,
index,
emin=emin,
emax=emax)
luminosity_function = get_LuminosityFunction(luminosity, LF=LF,
sigma=sigma)
delta_gamma = 2-index
if verbose:
print_config(LF, Transient, timescale, Evolution, density, N_sample,
luminosity, fluxnorm, delta_gamma, zmax, luminosity,
mode=" - Calculating Neutrino CDFs ")
##################################################
# Simulation starts here
##################################################
rng = np.random.RandomState(seed)
redshift_bins = np.arange(zmin, zmax, zmax/float(bins))
RedshiftPDF = [population.RedshiftDistribution(redshift_bins[i])
for i in range(0, len(redshift_bins))]
invCDF = InverseCDF(redshift_bins, RedshiftPDF)
if filename is None:
results = {}
results['header'] = {'LF': LF, 'Transient': Transient,
'timescale': timescale, 'fluxnorm': fluxnorm,
'delta_gamma': delta_gamma,
'luminosity': luminosity}
sources = {}
else:
out = output_writer(outputdir, filename)
out.write_header(LF, Transient, timescale, fluxnorm,
delta_gamma, luminosity)
# IMPORTANT notice, in the following "flux" means fluence in
# Transient mode, but flux in steady source mode,
# until TotalFlux(TotalFluence) is calculated
# sample sources
zs = invCDF(rng.uniform(low=0.0, high=1.0, size = N_sample))
lumis = luminosity_function.sample_distribution(nsources=N_sample, rng=rng)
if np.ndim(lumis) < 1:
lumis = np.array([lumis]*N_sample)
fluxes = population.Lumi2Flux(lumis, index, emin, emax, zs)
# Random declination over the entire sky
sinDecs = rng.uniform(-1, 1, size=N_sample)
declins = np.degrees(np.arcsin(sinDecs))
TotalFlux = np.sum(fluxes)
# For transient sources, the flux measured on Earth will be
# red-shifted-fluence/{(1+z)*burst duration}
if Transient:
fluxes = population.fluence2flux(fluxes, zs)
if filename is None:
sources['dec'] = declins
sources['flux'] = fluxes
sources['z'] = zs
else:
out.write(declins, zs, fluxes)
# For transient sources, we calculate the total fluence from all sources,
# then obtain the diffuse flux by doing a time average over a year
if Transient:
TotalFlux = TotalFlux / population.yr2sec
TotalFlux /= 4*np.pi # give in per sr
if filename is None:
results['total_flux'] = TotalFlux
results['sources'] = sources
else:
out.finish(TotalFlux)
if verbose:
print("Actual diffuse flux simulated :")
log = "E^2 dNdE = {TotalFlux} (E/100 TeV)^({delta_gamma}) [GeV/cm^2.s.sr]"
print(log.format(**locals()))
if filename is None:
return results
if __name__ == "__main__":
outputdir = get_outputdir()
# Process command line options
parser = argparse.ArgumentParser()
parser.add_argument('-o', action='store', dest='filename',
default='Firesong.out', help='Output filename')
parser.add_argument('-d', action='store', dest='density',
type=float, default=1e-9,
help='Local neutrino source density [1/Mpc^3] (default 1e-9 / Mpc^3)')
parser.add_argument("--evolution", action="store",
dest="Evolution", default='MD2014SFR',
help="Source evolution options: HB2006SFR, YMKBH2008SFR, CC2015SNR , MD2014SFR (default), NoEvolution")
parser.add_argument("--transient", action='store_true',
dest='Transient', default=False,
help='Simulate transient sources (default False)')
parser.add_argument("--timescale", action='store',
dest='timescale', type=float,
default=1000., help='time scale of transient sources in seconds (default 1000 seconds)')
parser.add_argument("--zmax", action="store", type=float,
dest="zmax", default=10.,
help="Highest redshift to be simulated (default 10.)")
parser.add_argument("--fluxnorm", action="store", dest='fluxnorm',
type=float, default=1.44e-8,
help="Astrophysical neutrino flux normalization A on E^2 dN/dE = A (E/100 TeV)^(-index) GeV/cm^2.s.sr (default 1.44e-8)")
parser.add_argument("--index", action="store", dest='index',
type=float, default=2.28,
help="Astrophysical neutrino spectral index on E^2 dN/dE = A (E/100 TeV)^(-index) GeV/cm^2.s.sr (default 2.28)")
parser.add_argument("--LF", action="store", dest="LF", default="SC",
help="Luminosity function, SC for standard candles (default), LG for lognormal, PL for powerlaw")
parser.add_argument("--sigma", action="store",
dest="sigma", type=float, default=1.0,
help="Width of a log normal Luminosity function in dex (default 1.0)")
parser.add_argument("--L", action="store",
dest="luminosity", type=float, default=0.0,
help="Set luminosity for each source [erg/year]. Resets fluxnorm option")
options = parser.parse_args()
firesong_simulation(outputdir,
filename=options.filename,
density=options.density,
Evolution=options.Evolution,
Transient=options.Transient,
timescale=options.timescale,
zmax=options.zmax,
fluxnorm=options.fluxnorm,
index=options.index,
LF=options.LF,
sigma=options.sigma,
luminosity=options.luminosity)
Functions
def firesong_simulation(outputdir, filename='Firesong.out', density=1e-09, Evolution='MD2014SFR', Transient=False, timescale=1000.0, zmin=0.0005, zmax=10.0, bins=10000, fluxnorm=1.44e-08, index=2.28, LF='SC', sigma=1.0, luminosity=0.0, emin=10000.0, emax=10000000.0, seed=None, verbose=True)
-
Simulate a universe of neutrino sources
Args
outputdir
:str
orNone
- path to write output. If None, return results without writing a file
filename
:str
orNone
- name of the output file. If None, return results without writing a file
density
:float
, optional, default=1e-9
- local density of neutrino sources. Units of Mpc^-3 (Mpc^-3 yr^-1 if Transient=True)
Transient
:bool
, optional, default=False
- If true, simulate transient neutrino sources instead of steady sources
timescale
:bool
, optional, default=1000
- Timescale in seconds for transient sources
zmin
:float
, optional, default=0.0005
- Closest redshift to consider
zmax
:float
, optional, default=10.
- Farthest redshift to consider
bins
:int
, optional, default=1000
- Number of bins used when creating the redshift PDF
fluxnorm
:float
, optional, default=1.44e-8
- Normalization on the total astrophysical diffuse flux, E^2dPhi/dE. Units of GeV s^-1 sr^-1
index
:float
, optional, default=2.28
- Spectral index of diffuse flux
- LF (string, optional, default="SC"): Luminosity function, choose
- between standard candle (SC), LogNormal (LG)
sigma
:float
, optional, default=1.0
- Width of lognormal distribution if LF="LG"
luminosity
:float
, optional, default=0.0
- Manually fix the luminosity of sources if not equal to 0. Overrides fluxnorm. Units of erg/yr
emin
:float
, optional, default=1e4
- Minimum neutrino energy in GeV
emax
:float
, optional, default=1e7
- Maximum neutrino energy in GeV
seed
:int
orNone
, optional, default=None
- random number seed
verbose
:bool
, optional, default=True
- print simulation paramaters if True else suppress printed output
Returns
dict
- keys contain simulation results, including the input params as well as the sources. Only returned if filename is None
Expand source code
def firesong_simulation(outputdir, filename='Firesong.out', density=1e-9, Evolution="MD2014SFR", Transient=False, timescale=1000., zmin=0.0005, zmax=10., bins=10000, fluxnorm=1.44e-8, index=2.28, LF="SC", sigma=1.0, luminosity=0.0, emin=1e4, emax=1e7, seed=None, verbose=True): """ Simulate a universe of neutrino sources Args: outputdir (str or None): path to write output. If None, return results without writing a file filename (str or None): name of the output file. If None, return results without writing a file density (float, optional, default=1e-9): local density of neutrino sources. Units of Mpc^-3 (Mpc^-3 yr^-1 if Transient=True) Transient (bool, optional, default=False): If true, simulate transient neutrino sources instead of steady sources timescale (bool, optional, default=1000): Timescale in seconds for transient sources zmin (float, optional, default=0.0005): Closest redshift to consider zmax (float, optional, default=10.): Farthest redshift to consider bins (int, optional, default=1000): Number of bins used when creating the redshift PDF fluxnorm (float, optional, default=1.44e-8): Normalization on the total astrophysical diffuse flux, E^2dPhi/dE. Units of GeV s^-1 sr^-1 index (float, optional, default=2.28): Spectral index of diffuse flux LF (string, optional, default="SC"): Luminosity function, choose between standard candle (SC), LogNormal (LG) sigma (float, optional, default=1.0): Width of lognormal distribution if LF="LG" luminosity (float, optional, default=0.0): Manually fix the luminosity of sources if not equal to 0. Overrides fluxnorm. Units of erg/yr emin (float, optional, default=1e4): Minimum neutrino energy in GeV emax (float, optional, default=1e7): Maximum neutrino energy in GeV seed (int or None, optional, default=None): random number seed verbose (bool, optional, default=True): print simulation paramaters if True else suppress printed output Returns: dict: keys contain simulation results, including the input params as well as the sources. Only returned if filename is None """ if Transient: population = TransientSourcePopulation(cosmology, get_evolution(Evolution), timescale=timescale) else: population = SourcePopulation(cosmology, get_evolution(Evolution)) N_sample = int(population.Nsources(density, zmax)) if luminosity == 0.0: ## If luminosity not specified calculate luminosity from diffuse flux luminosity = population.StandardCandleLuminosity(fluxnorm, density, zmax, index, emin=emin, emax=emax) luminosity_function = get_LuminosityFunction(luminosity, LF=LF, sigma=sigma) delta_gamma = 2-index if verbose: print_config(LF, Transient, timescale, Evolution, density, N_sample, luminosity, fluxnorm, delta_gamma, zmax, luminosity, mode=" - Calculating Neutrino CDFs ") ################################################## # Simulation starts here ################################################## rng = np.random.RandomState(seed) redshift_bins = np.arange(zmin, zmax, zmax/float(bins)) RedshiftPDF = [population.RedshiftDistribution(redshift_bins[i]) for i in range(0, len(redshift_bins))] invCDF = InverseCDF(redshift_bins, RedshiftPDF) if filename is None: results = {} results['header'] = {'LF': LF, 'Transient': Transient, 'timescale': timescale, 'fluxnorm': fluxnorm, 'delta_gamma': delta_gamma, 'luminosity': luminosity} sources = {} else: out = output_writer(outputdir, filename) out.write_header(LF, Transient, timescale, fluxnorm, delta_gamma, luminosity) # IMPORTANT notice, in the following "flux" means fluence in # Transient mode, but flux in steady source mode, # until TotalFlux(TotalFluence) is calculated # sample sources zs = invCDF(rng.uniform(low=0.0, high=1.0, size = N_sample)) lumis = luminosity_function.sample_distribution(nsources=N_sample, rng=rng) if np.ndim(lumis) < 1: lumis = np.array([lumis]*N_sample) fluxes = population.Lumi2Flux(lumis, index, emin, emax, zs) # Random declination over the entire sky sinDecs = rng.uniform(-1, 1, size=N_sample) declins = np.degrees(np.arcsin(sinDecs)) TotalFlux = np.sum(fluxes) # For transient sources, the flux measured on Earth will be # red-shifted-fluence/{(1+z)*burst duration} if Transient: fluxes = population.fluence2flux(fluxes, zs) if filename is None: sources['dec'] = declins sources['flux'] = fluxes sources['z'] = zs else: out.write(declins, zs, fluxes) # For transient sources, we calculate the total fluence from all sources, # then obtain the diffuse flux by doing a time average over a year if Transient: TotalFlux = TotalFlux / population.yr2sec TotalFlux /= 4*np.pi # give in per sr if filename is None: results['total_flux'] = TotalFlux results['sources'] = sources else: out.finish(TotalFlux) if verbose: print("Actual diffuse flux simulated :") log = "E^2 dNdE = {TotalFlux} (E/100 TeV)^({delta_gamma}) [GeV/cm^2.s.sr]" print(log.format(**locals())) if filename is None: return results