Exemplo n.º 1
0
 def setUpClass(cls):
     cls.detector = nestpy.VDetector()
     cls.detector.Initialization()
     cls.it = nestpy.INTERACTION_TYPE(0)
     cls.nestcalc = nestpy.NESTcalc(cls.detector)
     cls.nuisance = cls.nestcalc.default_NuisParam
     cls.free = cls.nestcalc.default_FreeParam
     cls.nestcalc = nestpy.NESTcalc(cls.detector)
Exemplo n.º 2
0
    def setUpClass(cls):
        cls.detector = nestpy.VDetector()
        cls.detector.Initialization()
        cls.it = nestpy.INTERACTION_TYPE(0)

        cls.nestcalc = nestpy.NESTcalc(cls.detector)

        cls.nuisance = cls.nestcalc.default_NuisParam
        cls.free = cls.nestcalc.default_FreeParam

        cls.nestcalc = nestpy.NESTcalc(cls.detector)
        cls.result = cls.nestcalc.FullCalculation(cls.it, 10., 3., 100., 131,
                                                  56, cls.nuisance, cls.free,
                                                  True)

        cls.position = [2, 3, 4]
Exemplo n.º 3
0
    def test_readme_example(self):
        # This is same as C++ NEST with naming
        nc = nestpy.NESTcalc()

        A = 131.293
        Z = 54.
        density = 2.9  # g/cm^3

        interaction = nestpy.INTERACTION_TYPE(0)  # NR
        E = 10  # keV
        print('For an %s keV %s' % (E, interaction))

        # Get particle yields
        y = nc.GetYields(
            interaction,
            E,
            density,
            124,  # Drift field, V/cm
            A,
            Z,
            (1, 1))

        print('The photon yield is:', y.PhotonYield)

        print('With statistical fluctuations',
              nc.GetQuanta(y, density).photons)
Exemplo n.º 4
0
 def setUpClass(cls):
     cls.detector = nestpy.VDetector()
     cls.detector.Initialization()
     cls.it = nestpy.INTERACTION_TYPE(0)
     cls.nestcalc = nestpy.NESTcalc(cls.detector)
     cls.result = cls.nestcalc.FullCalculation(
         cls.it, 10., 3., 100., 131, 56,
         [11., 1.1, 0.0480, -0.0533, 12.6, 0.3, 2., 0.3, 2., 0.5, 1.],
         [1., 1., 0.1, 0.5, 0.07], True)
Exemplo n.º 5
0
def kr83m_instructions(c):
    """
    Instruction that is meant to simulate Kr83m events in the TPC.
    """
    import nestpy
    half_life = 156.94e-9  # Kr intermediate state half-life in ns
    decay_energies = [32.2, 9.4]  # Decay energies in KeV

    n = c['nevents'] = c['event_rate'] * c['chunk_size'] * c['nchunk']
    c['total_time'] = c['chunk_size'] * c['nchunk']

    # Uses 4*n to get the two energies for S1 and S2
    instructions = np.zeros(4 * n, dtype=wfsim.instruction_dtype)
    instructions['event_number'] = np.digitize(
        instructions['time'],
        1e9 * np.arange(c['nchunk']) * c['chunk_size']) - 1

    instructions['type'] = np.tile([1, 2], 2 * n)
    instructions['recoil'] = ['er' for i in range(4 * n)]

    # Random positioning
    r = np.sqrt(np.random.uniform(0, c['tpc_radius']**2, n))
    t = np.random.uniform(-np.pi, np.pi, n)
    instructions['x'] = np.repeat(r * np.cos(t), 4)
    instructions['y'] = np.repeat(r * np.sin(t), 4)
    instructions['z'] = -10 * np.ones(4 * n)
    # Choosing shallow z positioning

    # For correct times need to include the 156.94 ns half life of the intermediate state
    uniform_times = c['total_time'] * (np.arange(n) + 0.5) / n
    delayed_times = uniform_times + np.random.exponential(
        half_life / np.log(2), len(uniform_times))
    instructions['time'] = np.repeat(list(zip(uniform_times, delayed_times)),
                                     2) * 1e9

    # Defining XENON-like detector
    nc = nestpy.NESTcalc(nestpy.VDetector())
    A = 131.293
    Z = 54
    density = 2.862  # g/cm^3    # SR1 Value
    drift_field = 82  # V/cm     # SR1 Value
    interaction = nestpy.INTERACTION_TYPE(7)  # gamma

    energy = np.tile(decay_energies, n)
    quanta = []
    for en in energy:
        y = nc.GetYields(interaction, en, density, drift_field, A, Z, (1, 1))
        quanta.append(nc.GetQuanta(y, density).photons)
        quanta.append(nc.GetQuanta(y, density).electrons)

    instructions['amp'] = quanta

    return instructions
Exemplo n.º 6
0
    def test_readme_example(self):
        import nestpy

        # This is same as C++ NEST with naming
        nc = nestpy.NESTcalc(nestpy.VDetector())
        
        interaction = nestpy.INTERACTION_TYPE(0)  # NR
        
        E = 10  # keV
        print('For an %s keV %s' % (E, interaction))
        
        # Get particle yields
        y = nc.GetYields(interaction, E)
        
        print('The photon yield is:', y.PhotonYield)
        print('With statistical fluctuations', nc.GetQuanta(y).photons)
Exemplo n.º 7
0
Arquivo: s1.py Projeto: XENONnT/WFSim
    def __init__(self, config):
        super().__init__(config)
        self.phase = 'liquid'  # To distinguish singlet/triplet time delay.
        if 'nest' in self.config['s1_model_type'] and (self.nestpy_calc is
                                                       None):
            log.info(
                'Using NEST for scintillation time without set calculator\n'
                'Creating new nestpy calculator')
            self.nestpy_calc = nestpy.NESTcalc(
                nestpy.DetectorExample_XENON10())

        # Check if user specified s1 model type exist
        S1VALIDTYPE = ['', 'simple', 'custom', 'optical_propagation', 'nest']

        def s1_valid_type(s, c='+ ,'):
            if len(c) > 0:
                for k in s.split(c[0]):
                    s1_valid_type(k, c[1:])
            else:
                assert s in S1VALIDTYPE, f'Model type "{s}" not in {S1VALIDTYPE}'

        s1_valid_type(self.config['s1_model_type'])
Exemplo n.º 8
0
def read_g4(file):

    nc = nestpy.NESTcalc(nestpy.VDetector())
    A = 131.293
    Z = 54.
    density = 2.9  # g/cm^3
    drift_field = 124  # V/cm
    interaction = nestpy.INTERACTION_TYPE(7)

    data = uproot.open(file)
    all_ttrees = dict(
        data.allitems(
            filterclass=lambda cls: issubclass(cls, uproot.tree.TTreeMethods)))
    e = all_ttrees[b'events/events;1']

    ins = np.zeros(2 * len(e), dtype=instruction_dtype)

    sort_key = np.argsort(e.array('time')[:, 0])

    e_dep, ins['x'], ins['y'], ins['z'], ins['t'] = e.array('etot')[sort_key], \
                                                    np.repeat(e.array('xp_pri')[sort_key], 2) / 10, \
                                                    np.repeat(e.array('yp_pri')[sort_key], 2) / 10, \
                                                    np.repeat(e.array('zp_pri')[sort_key], 2) / 10, \
                                                    1e9*np.repeat(e.array('time')[:, 0][sort_key], 2)

    ins['event_number'] = 0
    ins['type'] = np.tile(('s1', 's2'), len(e))
    ins['recoil'] = np.repeat('er', 2 * len(e))
    quanta = []

    for en in e_dep:
        y = nc.GetYields(interaction, en, density, drift_field, A, Z, (1, 1))
        quanta.append(nc.GetQuanta(y, density).photons)
        quanta.append(nc.GetQuanta(y, density).electrons)
    ins['amp'] = quanta
    return ins
Exemplo n.º 9
0
 def test_nestcalc_constructor_vdetect(self):
     detector = nestpy.VDetector()
     detector.Initialization()
     nestcalc = nestpy.NESTcalc(detector)
     assert nestcalc is not None
     assert isinstance(nestcalc, nestpy.nestpy.NESTcalc)
Exemplo n.º 10
0
 def test_nestcalc_constructor(self):
     nestcalc = nestpy.NESTcalc()
     assert nestcalc is not None
     assert isinstance(nestcalc, nestpy.nestpy.NESTcalc)
Exemplo n.º 11
0
 def setUpClass(cls):
     cls.detector = nestpy.VDetector()
     cls.detector.Initialization()
     cls.it = nestpy.INTERACTION_TYPE(0)
     cls.nestcalc = nestpy.NESTcalc(cls.detector)
Exemplo n.º 12
0
 def test_nestcalc_get_xyresolution(self):
     self.detector = nestpy.DetectorExample_XENON10()
     self.detector.Initialization()
     self.nestcalc = nestpy.NESTcalc(self.detector)
     self.nestcalc.xyResolution(
                         0., 1.,2.)
Exemplo n.º 13
0
import nestpy
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.axes as axes
import os

#Detector identification
detector = nestpy.DetectorExample_XENON10()
# detector = nestpy.VDetector()
# Performing NEST calculations according to the given detector example
nc = nestpy.NESTcalc(detector)  #can also be left empty


#GetInteractionObject grabs the number for the interaction you want so you don't have to always reference the dictionary. Just type e.g., 'ion'
#It just changes the name to a number for nestpy to do its work.
def GetInteractionObject(name):
    name = name.lower()

    if name == 'er':
        raise ValueError("For 'er', specify either 'gammaray' or 'beta'")

    nest_interaction_number = dict(
        nr=0,
        wimp=1,
        b8=2,
        dd=3,
        ambe=4,
        cf=5,
        ion=6,
        gammaray=7,
        beta=8,
Exemplo n.º 14
0
# Figure parameters common throughout all plots
version_textbox = " NEST v{0} \n nestpy v{1}".format(nestpy.__nest_version__,
                                                     nestpy.__version__)
bbox = dict(boxstyle="round", fc="1.00", edgecolor='none')
params = {
    'xtick.labelsize': 'x-large',
    'ytick.labelsize': 'x-large',
}
# Updates plots to apply the above formatting to all plots in doc
pylab.rcParams.update(params)

# Detector identification
detector = nestpy.DetectorExample_XENON10()
# Performing NEST calculations according to the given detector example
nc = nestpy.NESTcalc(detector)
#Once you have interaction, you can get yields
'''
Below are field and energy arrays.
- Energies are broadcase to be repeated by the dimensions of the fields, 
owing to the nature of vectorized functions below. 
- Functions will loop over each energy and field simultaneously that way,
rather than nesting for loops inside each other.
'''
fields = [1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000]
energies = np.logspace(-1, 4, 2000)
energies = np.broadcast_to(energies, (len(fields), len(energies)))


@np.vectorize
def GetYieldsVectorized(interaction, yield_type, **kwargs):
Exemplo n.º 15
0
def _rand_instructions(
    event_rate: int,
    chunk_size: int,
    n_chunk: int,
    drift_field: float,
    energy_range: ty.Union[tuple, list, np.ndarray],
    tpc_length: float = straxen.tpc_z,
    tpc_radius: float = straxen.tpc_r,
    nest_inst_types: ty.Union[ty.List[int], ty.Tuple[ty.List], np.ndarray,
                              None] = None,
) -> np.ndarray:
    import nestpy
    if nest_inst_types is None:
        nest_inst_types = [7]

    n_events = event_rate * chunk_size * n_chunk
    total_time = chunk_size * n_chunk

    inst = np.zeros(2 * n_events, dtype=instruction_dtype)
    inst[:] = -1

    uniform_times = total_time * (np.arange(n_events) + 0.5) / n_events

    inst['time'] = np.repeat(uniform_times, 2) * int(1e9)
    inst['event_number'] = np.digitize(
        inst['time'], 1e9 * np.arange(n_chunk) * chunk_size) - 1
    inst['type'] = np.tile([1, 2], n_events)

    r = np.sqrt(np.random.uniform(0, tpc_radius**2, n_events))
    t = np.random.uniform(-np.pi, np.pi, n_events)
    inst['x'] = np.repeat(r * np.cos(t), 2)
    inst['y'] = np.repeat(r * np.sin(t), 2)
    inst['z'] = np.repeat(np.random.uniform(-tpc_length, 0, n_events), 2)

    # Here we'll define our XENON-like detector
    nest_calc = nestpy.NESTcalc(nestpy.VDetector())
    nucleus_A = 131.293
    nucleus_Z = 54.
    lxe_density = 2.862  # g/cm^3   #SR1 Value

    energy = np.random.uniform(*energy_range, n_events)
    quanta = []
    exciton = []
    recoil = []
    e_dep = []
    for energy_deposit in tqdm(energy,
                               desc='generating instructions from nest'):
        interaction_type = np.random.choice(nest_inst_types)
        interaction = nestpy.INTERACTION_TYPE(interaction_type)
        y = nest_calc.GetYields(
            interaction,
            energy_deposit,
            lxe_density,
            drift_field,
            nucleus_A,
            nucleus_Z,
        )
        q = nest_calc.GetQuanta(y, lxe_density)
        quanta.append(q.photons)
        quanta.append(q.electrons)
        exciton.append(q.excitons)
        exciton.append(0)
        # both S1 and S2
        recoil += [interaction_type, interaction_type]
        e_dep += [energy_deposit, energy_deposit]

    inst['amp'] = quanta
    inst['local_field'] = drift_field
    inst['n_excitons'] = exciton
    inst['recoil'] = recoil
    inst['e_dep'] = e_dep
    for field in inst.dtype.names:
        if np.any(inst[field] == -1):
            log.warn(f'{field} is not (fully) filled')
    return inst
Exemplo n.º 16
0
def GetFlowImage(pid,
                 eDep,
                 field,
                 savefig=True,
                 output_dir='./',
                 output_filename='test.png'):

    if not os.path.exists(output_dir):
        os.makedirs(output_dir)
    fig, ax = plt.subplots(1, 1, figsize=(XC.fig_width, XC.fig_height))
    ax.set_xlim([0, XC.axes_xmax])
    ax.set_ylim([XC.axes_ymin, 0])

    SetColors(pid)

    if pid == 'NR':
        interaction = nestpy.INTERACTION_TYPE(0)
    elif pid == 'gamma':
        interaction = nestpy.INTERACTION_TYPE(7)
    elif pid == 'beta' or pid == 'ER':
        interaction = nestpy.INTERACTION_TYPE(8)

    yields = nestpy.NESTcalc(nestpy.VDetector()).GetYields(interaction,
                                                           energy=eDep,
                                                           density=DC.Density,
                                                           drift_field=field)
    Ni = (yields.PhotonYield + yields.ElectronYield) / yields.ExcitonRatio / (
        1. + 1. / yields.ExcitonRatio)
    Nex = yields.PhotonYield + yields.ElectronYield - Ni
    Nph = yields.PhotonYield
    Ne = yields.ElectronYield
    L = yields.Lindhard
    if (pid == 'ER' or pid == 'beta' or pid == 'gamma'):
        # An estimate of how much energy goes into heat for ERs
        L = 1. - XC.ER_heat_fraction
    SingTripRatio = NESThelper.GetSingTripRatio(pid, eDep, field)

    SetText(pid, eDep, field, Ni, Nex, Nph, Ne, SingTripRatio)
    SetArrowWidths(pid, Ni, Nex, Nph, Ne, L, SingTripRatio)

    for a in range(len(XC.arrow_properties['name'])):
        DrawArrow(fig, ax, a)

    for t in range(len(XC.text_properties['name'])):
        DrawText(fig, ax, t)

    DrawAtom(fig, ax, pid)

    ax.set_xlim([0, XC.axes_xmax])
    ax.set_ylim([XC.axes_ymin, 0])
    ax.axis('off')
    fig.tight_layout()
    if savefig:
        fig.savefig(output_dir + output_filename, transparent=False)
        im_out = Image.open(output_dir + output_filename)
    else:
        buf = io.BytesIO()
        fig.savefig(buf, format='png')
        buf.seek(0)
        im_out = Image.open(buf)

    plt.close('all')
    return im_out
Exemplo n.º 17
0
def quanta_from_NEST(en, model, e_field, A, Z, create_s2, **kwargs):
    """
    Function which uses NEST to yield photons and electrons
    for a given set of parameters.

    Note:
        In case the energy deposit is outside of the range of NEST a -1
        is returned.

    Args:
        en (numpy.array): Energy deposit of the interaction [keV]
        model (numpy.array): Nest Id for qunata generation (integers)
        e_field (numpy.array): Field value in the interaction site [V/cm]
        A (numpy.array): Atomic mass number
        Z (numpy.array): Atomic number
        create_s2 (bool): Specifies if S2 can be produced by interaction,
            in this case electrons are generated.
        kwargs: Additional keyword arguments which can be taken by
            GetYields e.g. density.

    Returns:
        photons (numpy.array): Number of generated photons
        electrons (numpy.array): Number of generated electrons
        excitons (numpy.array): Number of generated excitons
    """
    nc = nestpy.NESTcalc(nestpy.VDetector())
    density = 2.862  # g/cm^3

    # Fix for Kr83m events.
    # Energies have to be very close to 32.1 keV or 9.4 keV
    # See: https://github.com/NESTCollaboration/nest/blob/master/src/NEST.cpp#L567
    # and: https://github.com/NESTCollaboration/nest/blob/master/src/NEST.cpp#L585
    max_allowed_energy_difference = 1  # keV
    if model == 11:
        if abs(en - 32.1) < max_allowed_energy_difference:
            en = 32.1
        if abs(en - 9.4) < max_allowed_energy_difference:
            en = 9.4

    # Some addition taken from
    # https://github.com/NESTCollaboration/nestpy/blob/e82c71f864d7362fee87989ed642cd875845ae3e/src/nestpy/helpers.py#L94-L100
    if model == 0 and en > 2e2:
        warnings.warn(
            f"Energy deposition of {en} keV beyond NEST validity for NR model of 200 keV - Remove Interaction"
        )
        return -1, -1, -1
    if model == 7 and en > 3e3:
        warnings.warn(
            f"Energy deposition of {en} keV beyond NEST validity for gamma model of 3 MeV - Remove Interaction"
        )
        return -1, -1, -1
    if model == 8 and en > 3e3:
        warnings.warn(
            f"Energy deposition of {en} keV beyond NEST validity for beta model of 3 MeV - Remove Interaction"
        )
        return -1, -1, -1

    y = nc.GetYields(interaction=nestpy.INTERACTION_TYPE(model),
                     energy=en,
                     drift_field=e_field,
                     A=A,
                     Z=Z,
                     **kwargs)

    event_quanta = nc.GetQuanta(
        y)  # Density argument is not use in function...

    photons = event_quanta.photons
    excitons = event_quanta.excitons
    electrons = 0
    if create_s2:
        electrons = event_quanta.electrons

    return photons, electrons, excitons