Source code for jetset.jet_emitters_factory

__author__ = "Andrea Tramacere"

import numpy as np
import pprint
from jetset.jet_emitters import EmittersDistribution, InjEmittersDistribution
__all__=['EmittersFactory']

_available_dict = {'lp': 'log-parabola',
                   'pl': 'powerlaw',
                   'lppl': 'log-parabola with low-energy powerlaw branch',
                   'lpep': 'log-parabola defined by peak energy',
                   'lppl_pileup': 'log-parabola with low-energy powerlaw branch and pileup',
                   'plc': 'powerlaw with cut-off',
                   'bkn': 'broken powerlaw',
                   'superexp': 'powerlaw with super-exp cut-off'}


def distr_func_bkn(gamma_break, gamma, p, p_1):
    """Distr func bkn.
    
    Parameters
    ----------
    gamma_break : object
        Frequency/energy control value for gamma break.
    gamma : object
        Frequency/energy control value for gamma.
    p : object
        Parameter controlling p.
    p_1 : object
        Parameter controlling p 1.
    
    Returns
    -------
    object
        Computed result.
    """
    f = np.zeros(gamma.shape)
    m = gamma < gamma_break
    f[m] = np.power(gamma[m], -p)
    f[~m] = np.power(gamma_break, -(p - p_1)) * np.power(gamma[~m], -p_1)
    return f


def distr_func_pl(gamma, p, ):
    """Distr func pl.
    
    Parameters
    ----------
    gamma : object
        Frequency/energy control value for gamma.
    p : object
        Parameter controlling p.
    
    Returns
    -------
    object
        Computed result.
    """
    return np.power(gamma, -p)


def distr_func_plc(gamma, gamma_cut, p,):
    """Distr func plc.
    
    Parameters
    ----------
    gamma : object
        Frequency/energy control value for gamma.
    gamma_cut : object
        Frequency/energy control value for gamma cut.
    p : object
        Parameter controlling p.
    
    Returns
    -------
    object
        Computed result.
    """
    return np.power(gamma, -p) * np.exp(-(gamma / gamma_cut) )


def distr_func_super_exp(gamma, gamma_cut, p, a):
    """Distr func super exp.
    
    Parameters
    ----------
    gamma : object
        Frequency/energy control value for gamma.
    gamma_cut : object
        Frequency/energy control value for gamma cut.
    p : object
        Parameter controlling p.
    a : object
        Parameter controlling a.
    
    Returns
    -------
    object
        Computed result.
    """
    return np.power(gamma, -p) * np.exp(-(1 / a) * (gamma / gamma_cut) ** a)

def distr_func_lp(gamma, gamma0_log_parab, r, s):
    """Distr func lp.
    
    Parameters
    ----------
    gamma : object
        Frequency/energy control value for gamma.
    gamma0_log_parab : object
        Frequency/energy control value for gamma0 log parab.
    r : object
        Parameter controlling r.
    s : object
        Parameter controlling s.
    
    Returns
    -------
    object
        Computed result.
    """
    return np.power((gamma / gamma0_log_parab), (-s - r * np.log10(gamma / gamma0_log_parab)))


def distr_func_lep(gamma, gamma_p, r):
    """Distr func lep.
    
    Parameters
    ----------
    gamma : object
        Frequency/energy control value for gamma.
    gamma_p : object
        Frequency/energy control value for gamma p.
    r : object
        Parameter controlling r.
    
    Returns
    -------
    object
        Computed result.
    """
    return np.power(10., (-r * np.power(np.log10(gamma / gamma_p), 2)))

def distr_func_lppl(gamma, gamma0_log_parab, r, s):
    """Distr func lppl.
    
    Parameters
    ----------
    gamma : object
        Frequency/energy control value for gamma.
    gamma0_log_parab : object
        Frequency/energy control value for gamma0 log parab.
    r : object
        Parameter controlling r.
    s : object
        Parameter controlling s.
    
    Returns
    -------
    object
        Computed result.
    """
    f = np.zeros(gamma.shape)
    m = gamma < gamma0_log_parab
    f[m] = np.power(gamma[m]/gamma0_log_parab, -s)
    f[~m] = np.power(gamma[~m]/gamma0_log_parab, (-s -r*np.log10(gamma[~m] / gamma0_log_parab )))
    return f


def distr_func_lppl_pileup(gamma, gamma0_log_parab,  gamma_inj, r,  s, gamma_eq,  ratio_pile_up , alpha, gamma_cut_acc):
    """Distr func lppl pileup.
    
    Parameters
    ----------
    gamma : object
        Frequency/energy control value for gamma.
    gamma0_log_parab : object
        Frequency/energy control value for gamma0 log parab.
    gamma_inj : object
        Frequency/energy control value for gamma inj.
    r : object
        Parameter controlling r.
    s : object
        Parameter controlling s.
    gamma_eq : object
        Frequency/energy control value for gamma eq.
    ratio_pile_up : object
        Parameter controlling ratio pile up.
    alpha : object
        Parameter controlling alpha.
    gamma_cut_acc : object
        Frequency/energy control value for gamma cut acc.
    
    Returns
    -------
    object
        Computed result.
    """
    b = np.zeros(gamma.shape)
    a = np.zeros(gamma.shape)
    m = gamma < gamma_inj
    s1=s+0.5
    b[m] = np.power(gamma[m]/gamma0_log_parab, s1)
    
    
    f1 = np.zeros(gamma.shape)
    m1 = np.logical_and(gamma < gamma0_log_parab,gamma>gamma_inj)
    f1[m1] = np.power(gamma[m1]/gamma0_log_parab, -s)
    f1[~m1] = np.power(gamma[~m1]/gamma0_log_parab, (-s -r*np.log10(gamma[~m1] / gamma0_log_parab )))
    b[~m] = np.power(gamma_inj/gamma0_log_parab,s1+s)*f1[~m]*np.exp(-np.power((gamma[~m]/gamma_cut_acc),alpha)/alpha)
    
    pile_up=gamma*gamma*np.exp(-np.power((gamma/gamma_eq),alpha)/alpha)
    pile_up=pile_up/(gamma_eq*gamma_eq*np.exp(-np.power((gamma_eq/gamma_eq),alpha)/alpha))
    g_ID=np.argmin(np.fabs(gamma-gamma_eq))
    c=b[g_ID]*ratio_pile_up
    a=pile_up*c
    return a+b


[docs] class EmittersFactory: """Factory for analytical emitter distribution objects. Notes ----- Builds configured :class:`~jetset.jet_emitters.EmittersDistribution` instances for supported spectral shapes (power law, broken power law, log-parabola variants, and cutoff forms). """ def __repr__(self): return str(pprint.pprint(self._available_dict)) def __init__(self): """Create a new `EmittersFactory` instance.""" self._available_dict=_available_dict self._func_dict = {'pl': self._create_pl, 'bkn': self._create_bkn, 'plc': self._create_plc, 'lp': self._create_lp, 'lppl': self._create_lppl, 'lppl_pileup': self._create_lppl_pileup, 'lpep': self._create_lpep, 'superexp': self._create_super_exp} self._set_emitters_class() def _set_emitters_class(self): if type(self) == EmittersFactory: self._emitters_class=EmittersDistribution elif type(self) ==InjEmittersFactory: self._emitters_class = InjEmittersDistribution else: raise RuntimeError('class instance', type(self), 'not valid')
[docs] @staticmethod def available_distributions(): """Available distributions.""" for k in _available_dict.keys(): print('%s: %s' % (k, _available_dict[k]))
[docs] @staticmethod def available_distributions_list(): """Available distributions list. Returns ------- object Computed result. """ return _available_dict.keys()
[docs] def create_emitters(self, name, gamma_grid_size=200, log_values=False, emitters_type='electrons', normalize=True, skip_build=False): """Create emitters. Parameters ---------- name : object Name identifier. gamma_grid_size : int, optional Array/grid values for gamma grid size. log_values : bool, optional Parameter controlling log values. emitters_type : str, optional Parameter controlling emitters type. normalize : bool, optional Parameter controlling normalize. skip_build : bool, optional If ``True``, skip build. Returns ------- object Computed result. """ if name not in self._available_dict.keys(): raise RuntimeError('name', name, 'not among available', self._available_dict.keys()) return self._func_dict[name](gamma_grid_size=gamma_grid_size, log_values=log_values, normalize=normalize, skip_build=skip_build, emitters_type=emitters_type)
def _create_bkn(self,gamma_grid_size,log_values,normalize,skip_build,emitters_type): n_e_bkn = self._emitters_class(name='bkn', spectral_type='bkn', normalize=normalize, emitters_type=emitters_type, log_values=log_values, skip_build=skip_build, gamma_grid_size=gamma_grid_size) a_t, b_t = n_e_bkn.set_bounds(1, 1E9, log_val=n_e_bkn._log_values) gamma_break_val = n_e_bkn._set_log_val(1E4,log_val=log_values) n_e_bkn.add_par('gamma_break', par_type='turn-over-energy', val=gamma_break_val, vmin=a_t, vmax=b_t, unit='lorentz-factor',log=log_values) n_e_bkn.add_par('p', par_type='LE_spectral_slope', val=2.5, vmin=-10., vmax=10, unit='') n_e_bkn.add_par('p_1', par_type='HE_spectral_slope', val=3.5, vmin=-10., vmax=10, unit='') n_e_bkn.set_distr_func(distr_func_bkn) return n_e_bkn def _create_pl(self,gamma_grid_size, log_values, normalize, skip_build, emitters_type): n_e_pl = self._emitters_class(name='pl', spectral_type='pl', normalize=normalize, emitters_type=emitters_type, log_values=log_values, skip_build=skip_build, gamma_grid_size=gamma_grid_size) a_t, b_t = n_e_pl.set_bounds(1, 1E9, log_val=n_e_pl._log_values) n_e_pl.add_par('p', par_type='LE_spectral_slope', val=2.0, vmin=-10., vmax=10, unit='') n_e_pl.set_distr_func(distr_func_pl) return n_e_pl def _create_plc(self, gamma_grid_size,log_values,normalize,skip_build,emitters_type): n_e_plc = n_e_bkn = self._emitters_class(name='plc', spectral_type='plc', normalize=normalize, emitters_type=emitters_type, log_values=log_values, skip_build=skip_build, gamma_grid_size=gamma_grid_size) a_t, b_t = n_e_plc.set_bounds(1, 1E9, log_val=n_e_plc._log_values) gamma_cut_val = n_e_plc._set_log_val(1E4,log_val=log_values) n_e_plc.add_par('gamma_cut', par_type='turn-over-energy', val=gamma_cut_val, vmin=a_t, vmax=b_t, unit='lorentz-factor',log=log_values) n_e_plc.add_par('p', par_type='LE_spectral_slope', val=2.0, vmin=-10., vmax=10, unit='') n_e_plc.set_distr_func(distr_func_plc) return n_e_plc def _create_super_exp(self, gamma_grid_size, log_values, normalize, skip_build, emitters_type): n_e_super_exp = self._emitters_class(name='super_exp', spectral_type='plc', normalize=normalize, emitters_type=emitters_type, log_values=log_values, skip_build=skip_build, gamma_grid_size=gamma_grid_size) a_t, b_t = n_e_super_exp.set_bounds(1, 1E9, log_val=n_e_super_exp._log_values) gamma_cut_val = n_e_super_exp._set_log_val(1E4,log_val=log_values) n_e_super_exp.add_par('gamma_cut', par_type='turn-over-energy', val=gamma_cut_val, vmin=a_t, vmax=b_t, unit='lorentz-factor',log=log_values) n_e_super_exp.add_par('p', par_type='LE_spectral_slope', val=2.0, vmin=-10., vmax=10, unit='') n_e_super_exp.add_par('a', par_type='spectral_curvature', val=1.0, vmin=0., vmax=100., unit='') n_e_super_exp.set_distr_func(distr_func_super_exp) return n_e_super_exp def _create_lp(self, gamma_grid_size,log_values,normalize,skip_build,emitters_type): n_lp = self._emitters_class(name='lp', spectral_type='lp', normalize=normalize, emitters_type=emitters_type, log_values=log_values, skip_build=skip_build, gamma_grid_size=gamma_grid_size) a_t, b_t = n_lp.set_bounds(1, 1E9, log_val=n_lp._log_values) gamma0_log_parab_val = n_lp._set_log_val(1E4,log_val=log_values) n_lp.add_par('gamma0_log_parab', par_type='turn-over-energy', val=gamma0_log_parab_val, vmin=a_t, vmax=b_t, unit='lorentz-factor',log=log_values) n_lp.add_par('s', par_type='LE_spectral_slope', val=2.0, vmin=-10., vmax=10, unit='') n_lp.add_par('r', par_type='spectral_curvature', val=0.4, vmin=-15., vmax=15., unit='') n_lp.set_distr_func(distr_func_lp) return n_lp def _create_lpep(self,gamma_grid_size, log_values, normalize, skip_build, emitters_type): n_lep = self._emitters_class(name='lpep', spectral_type='lp', normalize=normalize, emitters_type=emitters_type, log_values=log_values, skip_build=skip_build, gamma_grid_size=gamma_grid_size) a_t, b_t = n_lep.set_bounds(1, 1E9, log_val=n_lep._log_values) gamma_p_val = n_lep._set_log_val(1E4,log_val=log_values) n_lep.add_par('gamma_p', par_type='turn-over-energy', val=gamma_p_val, vmin=a_t, vmax=b_t, unit='lorentz-factor',log=log_values) n_lep.add_par('r', par_type='spectral_curvature', val=0.4, vmin=-15., vmax=15., unit='') n_lep.set_distr_func(distr_func_lep) return n_lep def _create_lppl(self, gamma_grid_size, log_values, normalize, skip_build, emitters_type): n_lppl = self._emitters_class(name='lppl', spectral_type='lp', normalize=normalize, emitters_type=emitters_type, log_values=log_values, skip_build=skip_build, gamma_grid_size=gamma_grid_size) a_t, b_t = n_lppl.set_bounds(1, 1E9, log_val=n_lppl._log_values) gamma0_log_parab_val = n_lppl._set_log_val(1E4,log_val=log_values) n_lppl.add_par('gamma0_log_parab', par_type='turn-over-energy', val=gamma0_log_parab_val, vmin=a_t, vmax=b_t, unit='lorentz-factor',log=log_values) n_lppl.add_par('s', par_type='LE_spectral_slope', val=2.0, vmin=-10., vmax=10, unit='') n_lppl.add_par('r', par_type='spectral_curvature', val=0.4, vmin=-15., vmax=15., unit='') n_lppl.set_distr_func(distr_func_lppl) return n_lppl def _create_lppl_pileup(self, gamma_grid_size, log_values, normalize, skip_build, emitters_type): n_lppl_pileup = self._emitters_class(name='lppl_pileup', spectral_type='lp', normalize=normalize, emitters_type=emitters_type, log_values=log_values, skip_build=skip_build, gamma_grid_size=gamma_grid_size) a_t, b_t = n_lppl_pileup.set_bounds(1, 1E9, log_val=n_lppl_pileup._log_values) gamma0_log_parab_val = n_lppl_pileup._set_log_val(1E4,log_val=log_values) n_lppl_pileup.add_par('gamma0_log_parab', par_type='turn-over-energy', val=gamma0_log_parab_val, vmin=a_t, vmax=b_t, unit='lorentz-factor',log=log_values) n_lppl_pileup.add_par('s', par_type='LE_spectral_slope', val=2.0, vmin=-10., vmax=10, unit='') n_lppl_pileup.add_par('r', par_type='spectral_curvature', val=0.4, vmin=-15., vmax=15., unit='') n_lppl_pileup.add_par('alpha', par_type='spectral_curvature', val=0.4, vmin=1E-3, vmax=2., unit='') n_lppl_pileup.add_par('gamma_inj', par_type='low-energy-cut-off', val=1E2, vmin=1, vmax=1E6, unit='') n_lppl_pileup.add_par('gamma_eq', par_type='turn-over-energy', val=1E5, vmin=1E1, vmax=1E9, unit='') n_lppl_pileup.add_par('gamma_cut_acc', par_type='high-energy-cut-off', val=1E6, vmin=1E1, vmax=1E9, unit='') n_lppl_pileup.add_par('ratio_pile_up', par_type='scaling_factor', val=1E-3, vmin=1E-10, vmax=1E3, unit='') n_lppl_pileup.set_distr_func(distr_func_lppl_pileup) return n_lppl_pileup
class InjEmittersFactory(EmittersFactory): """Factory specialized for injection distributions ``Q(gamma)``. Notes ----- Reuses the distribution-shape registry from :class:`EmittersFactory` but instantiates injection-oriented emitter classes. """ def __init__(self): """Create a new `InjEmittersFactory` instance.""" super(InjEmittersFactory, self).__init__() def create_inj_emitters(self, name, gamma_grid_size=200, log_values=False, emitters_type='electrons', normalize=True, skip_build=False): """Create inj emitters. Parameters ---------- name : object Name identifier. gamma_grid_size : int, optional Array/grid values for gamma grid size. log_values : bool, optional Parameter controlling log values. emitters_type : str, optional Parameter controlling emitters type. normalize : bool, optional Parameter controlling normalize. skip_build : bool, optional If ``True``, skip build. Returns ------- object Computed result. """ if name not in self._available_dict.keys(): raise RuntimeError('name', name, 'not among available', self._available_dict.keys()) return self._func_dict[name](gamma_grid_size=gamma_grid_size, log_values=log_values, normalize=normalize, skip_build=skip_build, emitters_type=emitters_type)