Source code for dddm.detectors.xenon_nt

from .experiment import Experiment
from .lindhard_factors import lindhard_quenching_factor, _get_nr_resolution
import dddm
import numpy as np
from functools import partial
from abc import ABC

export, __all__ = dddm.exporter()


class _BaseXenonNt(Experiment, ABC):
    target_material = 'Xe'
    exposure_tonne_year = 20  # https://arxiv.org/pdf/2007.08796.pdf
    location = "XENON"

    # https://arxiv.org/abs/1608.05381
    _energy_parameters = {'k': 0.1735, 'Z': 54}


[docs]@export class XenonNtNr(_BaseXenonNt): detector_name = 'XENONnT_NR' __version__ = '0.0.0' # Use https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.126.091301 energy_threshold_kev = 1.6 # keVnr # Combined cut & detection efficiency as in # https://arxiv.org/pdf/2007.08796.pdf cut_efficiency = 0.83 detection_efficiency = 1 interaction_type = 'SI'
[docs] def background_function(self, energies_in_kev): """ :return: NR background for Xe detector in events/keV/t/yr """ # From https://arxiv.org/pdf/2007.08796.pdf bg_rate = 2.2e-3 # 1/(keV * t * yr) # Assume flat background over entire energy range # True to first order below 200 keV if (e_min := energies_in_kev[0]) > (e_max := energies_in_kev[-1]) or e_max > 200: mes = f'Assume flat background only below 200 keV ({e_min}, {e_max})' raise ValueError(mes) return self._flat_background(len(energies_in_kev), bg_rate)
[docs] def resolution(self, energies_in_kev): """ Use _get_nr_resolution to calculate the energy resolution. :param energies_in_kev: NR energies to evaluate the resolution function at :return: """ energy_nr_to_energy_ee_function = partial(energy_nr_to_energy_ee, **self._energy_parameters) # Now get e_ee and sigma_ee based on that we can calculate the # energy resolution for the NRs energy_ee = energy_nr_to_energy_ee_function(energies_in_kev) energy_res_ee = xenon_1t_er_resolution(energy_ee) return _get_nr_resolution(energies_in_kev, energy_nr_to_energy_ee_function, base_resolution=energy_res_ee, )
[docs]@export class XenonNtMigdal(_BaseXenonNt): detector_name = 'XENONnT_Migdal' __version__ = '0.0.0' # assume https://arxiv.org/abs/2006.09721 energy_threshold_kev = 1 # keVer # Combined cut & detection efficiency as in # https://arxiv.org/pdf/2007.08796.pdf cut_efficiency = 0.82 detection_efficiency = 1 interaction_type = 'migdal_SI'
[docs] def resolution(self, energies_in_kev): """Assume the same as the 1T resolution""" return xenon_1t_er_resolution(energies_in_kev)
[docs] def background_function(self, energies_in_kev): """ :return: ER background for Xe detector in events/keV/t/yr """ # From https://arxiv.org/pdf/2007.08796.pdf bg_rate = 12.3 # 1/(keV * t * yr) # Assume flat background over entire energy range # True to first order below 200 keV if (e_min := energies_in_kev[0]) > (e_max := energies_in_kev[-1]) or e_max > 200: mes = f'Assume flat background only below 200 keV ({e_min}, {e_max})' raise ValueError(mes) return self._flat_background(len(energies_in_kev), bg_rate)
def xenon_1t_er_resolution(energies_in_kev_ee): """ Detector resolution of XENON1T. See e.g. 1 of https://journals.aps.org/prd/pdf/10.1103/PhysRevD.102.072004 :param energies_in_kev_ee: energy in keVee :return: resolution at energies_in_kev """ a = 0.310 b = 0.0037 return a * np.sqrt(energies_in_kev_ee) + b * energies_in_kev_ee def energy_nr_to_energy_ee(energy_nr, k, Z): return energy_nr * lindhard_quenching_factor(energy_nr, k=k, atomic_number_z=Z)