コード例 #1
0
def test_mc_wrapper_elife(
    run_id='009000',
    cmt_id='016000',
    mc_id='mc_0',
):
    """
    Test that for two different run ids, we get different elifes using
    the MC wrapper.
    :param run_id: First run-id (used for normal query)
    :param cmt_id: Second run-id used as a CMT id (should not be the
        same as run_id! otherwise the values might actually be the same
        and the test does not work).
    :return: None
    """
    if not straxen.utilix_is_configured():
        return
    assert np.abs(int(run_id) - int(cmt_id)) > 500, 'runs must be far apart'

    # First for the run-id let's get the value
    elife = straxen.get_correction_from_cmt(run_id, ("elife", "ONLINE", True))

    # Now, we repeat the same query using the MC wrapper, this should
    # give us a different result since we are now asking for a very
    # different run-number.
    mc_elife_diff = straxen.get_correction_from_cmt(
        mc_id, ('MC', cmt_id, "elife", "ONLINE", True))

    # Repeat the query from above to verify, let's see if we are getting
    # the same results as for `elife` above
    mc_elife_same = straxen.get_correction_from_cmt(
        mc_id, ('MC', run_id, "elife", "ONLINE", True))

    assert elife != mc_elife_diff
    assert elife == mc_elife_same
コード例 #2
0
    def set_config(self, ):
        self.config.update(
            straxen.get_resource(self.config['fax_config'], fmt='json'))
        overrides = self.config['fax_config_override']
        if overrides is not None:
            self.config.update(overrides)

        # backwards compatibility
        if 'field_distortion_on' in self.config and not 'field_distortion_model' in self.config:
            self.config.update({
                'field_distortion_model':
                "inverse_fdc" if self.config['field_distortion_on'] else "none"
            })

        # Update gains to the nT defaults
        self.to_pe = straxen.get_correction_from_cmt(
            self.run_id, self.config['gain_model_mc'])

        adc_2_current = (self.config['digitizer_voltage_range'] /
                         2**(self.config['digitizer_bits']) /
                         self.config['pmt_circuit_load_resistor'])

        self.config['gains'] = np.divide(adc_2_current,
                                         self.to_pe,
                                         out=np.zeros_like(self.to_pe),
                                         where=self.to_pe != 0)

        if self.config['seed']:
            np.random.seed(self.config['seed'])

        # We hash the config to load resources. Channel map is immutable and cannot be hashed
        self.config['channel_map'] = dict(self.config['channel_map'])
        self.config['channel_map']['sum_signal'] = 800
        self.config['channels_bottom'] = np.arange(self.config['n_top_pmts'],
                                                   self.config['n_tpc_pmts'])

        # Update some values stored in CMT
        if self.config['fax_config_override_from_cmt'] is not None:
            for fax_field, cmt_option in self.config[
                    'fax_config_override_from_cmt'].items():
                if (fax_field in ['fdc_3d', 's1_light_yield_map']
                        and self.config.get('default_reconstruction_algorithm',
                                            False)):
                    cmt_option = tuple([
                        'suffix',
                        self.config['default_reconstruction_algorithm'],
                        *cmt_option
                    ])

                cmt_value = straxen.get_correction_from_cmt(
                    self.run_id, cmt_option)
                log.warning(
                    f'Replacing {fax_field} with CMT option {cmt_option} to {cmt_value}'
                )
                self.config[fax_field] = cmt_value
コード例 #3
0
ファイル: event_patternfit.py プロジェクト: zhut19/straxen
 def setup(self):
     self.mean_pe_photon = self.config['mean_pe_per_photon']
     
     # Getting S1 AFT maps
     self.s1_aft_map = straxen.InterpolatingMap(
         straxen.get_resource(
             self.config['s1_aft_map'],
             fmt=self._infer_map_format(self.config['s1_aft_map'])))
                 
     # Getting optical maps
     self.s1_pattern_map = straxen.InterpolatingMap(
         straxen.get_resource(
             self.config['s1_optical_map'],
             fmt=self._infer_map_format(self.config['s1_optical_map'])))
     self.s2_pattern_map = straxen.InterpolatingMap(
         straxen.get_resource(
             self.config['s2_optical_map'],
             fmt=self._infer_map_format(self.config['s2_optical_map'])))
     
     # Getting gain model to get dead PMTs
     self.to_pe = straxen.get_correction_from_cmt(self.run_id, self.config['gain_model'])
     self.dead_PMTs = np.where(self.to_pe == 0)[0]
     self.pmtbool = ~np.in1d(np.arange(0, self.config['n_tpc_pmts']), self.dead_PMTs)
     self.pmtbool_top = self.pmtbool[:self.config['n_top_pmts']]
     self.pmtbool_bottom = self.pmtbool[self.config['n_top_pmts']:self.config['n_tpc_pmts']]
コード例 #4
0
    def setup(self):
        self.to_pe = straxen.get_correction_from_cmt(self.run_id,
                                                     self.config['gain_model'])

        buffer_pmts = np.zeros(self.config['he_channel_offset'])
        self.to_pe = np.concatenate((buffer_pmts, self.to_pe))
        self.to_pe *= self.config['le_to_he_amplification']
コード例 #5
0
    def setup(self):
        self.to_pe = straxen.get_correction_from_cmt(self.run_id,
                                                     self.config['gain_model'])
        self.hit_left_extension, self.hit_right_extension = self.config[
            'save_outside_hits']

        # Check config of `hit_min_amplitude` and define hit thresholds
        # if cmt config
        if is_cmt_option(self.config['hit_min_amplitude']):
            self.hit_thresholds = straxen.get_correction_from_cmt(
                self.run_id, self.config['hit_min_amplitude'])
        # if hitfinder_thresholds config
        elif isinstance(self.config['hit_min_amplitude'], str):
            self.hit_thresholds = straxen.hit_min_amplitude(
                self.config['hit_min_amplitude'])
        else:  # int or array
            self.hit_thresholds = self.config['hit_min_amplitude']
コード例 #6
0
def test_cmt_conf_option(option='mlp_model', version='ONLINE', is_nT=True):
    """
    Test CMT conf options
    If wrong conf is passed it would raise an error accordingly
    """
    conf = option, version, is_nT
    correction = straxen.get_correction_from_cmt(test_run_id_nT, conf)
    assert isinstance(correction, (float, int, str, np.ndarray))
コード例 #7
0
 def setup(self):
     if isinstance(self.config['baseline_samples_nv'], int):
         self.baseline_samples = self.config['baseline_samples_nv']
     else:
         self.baseline_samples = straxen.get_correction_from_cmt(
             self.run_id, self.config['baseline_samples_nv'])
     
     # Check config of `hit_min_amplitude_nv` and define hit thresholds
     # if cmt config
     if is_cmt_option(self.config['hit_min_amplitude_nv']):
         self.hit_thresholds = straxen.get_correction_from_cmt(self.run_id,
             self.config['hit_min_amplitude_nv'])
     # if hitfinder_thresholds config
     elif isinstance(self.config['hit_min_amplitude_nv'], str):
         self.hit_thresholds = straxen.hit_min_amplitude(
             self.config['hit_min_amplitude_nv'])
     else: # int or array
         self.hit_thresholds = self.config['hit_min_amplitude_nv']
コード例 #8
0
ファイル: pulse_processing.py プロジェクト: jorana/straxen
    def setup(self):
        self.hev_enabled = ((self.config['hev_gain_model'][0] != 'disabled')
                            and self.config['tail_veto_threshold'])
        if self.hev_enabled:
            self.to_pe = straxen.get_correction_from_cmt(
                self.run_id, self.config['hev_gain_model'])

        # Check config of `hit_min_amplitude` and define hit thresholds
        # if cmt config
        if is_cmt_option(self.config['hit_min_amplitude']):
            self.hit_thresholds = straxen.get_correction_from_cmt(
                self.run_id, self.config['hit_min_amplitude'])
        # if hitfinder_thresholds config
        elif isinstance(self.config['hit_min_amplitude'], str):
            self.hit_thresholds = straxen.hit_min_amplitude(
                self.config['hit_min_amplitude'])
        else:  # int or array
            self.hit_thresholds = self.config['hit_min_amplitude']
コード例 #9
0
def get_correction(name: str,
                   run_id: str = None,
                   version: str = 'ONLINE',
                   detector: str = 'nt',
                   **kwargs):
    """Get value for name from CMT"""
    if run_id is None:
        raise ValueError('Attempting to fetch a correction without a run id.')
    return straxen.get_correction_from_cmt(run_id, (name, version, detector == 'nt'))
コード例 #10
0
    def setup(self):
        if self.config['peak_min_pmts'] > 2:
            # Can fix by re-splitting,
            raise NotImplementedError(
                f"Raising the peak_min_pmts to {self.config['peak_min_pmts']} "
                f"interferes with lone_hit definition. "
                f"See github.com/XENONnT/straxen/issues/295")

        self.to_pe = straxen.get_correction_from_cmt(self.run_id,
                                                     self.config['gain_model'])
コード例 #11
0
    def setup(self):
        self.channel_range = self.config['channel_map']['mv']
        self.n_channel = (self.channel_range[1] - self.channel_range[0]) + 1

        to_pe = straxen.get_correction_from_cmt(self.run_id,
                                  self.config['gain_model_mv'])

        # Create to_pe array of size max channel:
        self.to_pe = np.zeros(self.channel_range[1] + 1, dtype=np.float32)
        self.to_pe[self.channel_range[0]:] = to_pe[:]
コード例 #12
0
def test_cmt_conf_option(option='mlp_model', version='ONLINE', is_nT=True):
    """
    Test CMT conf options 
    If wrong conf is passed it would raise an error accordingly
    """
    if not straxen.utilix_is_configured():
        warn('Cannot do test becaus  ' 'no have access to the database.')
        return

    conf = option, version, is_nT
    correction = straxen.get_correction_from_cmt(test_run_id_nT, conf)
    assert isinstance(correction, (float, int, str, np.ndarray))
コード例 #13
0
def test_1T_elife():
    """
    Test elife from CMT DB against historical data(aux file)
    """
    elife_conf = ('elife_xenon1t', 'ONLINE', False)
    elife_cmt = straxen.get_correction_from_cmt(test_run_id_1T, elife_conf)
    elife_file = aux_repo + '3548132b55f81a43654dba5141366041e1daaf01/strax_files/elife.npy'
    x = straxen.get_resource(elife_file, fmt='npy')
    run_index = np.where(x['run_id'] == int(test_run_id_1T))[0]
    elife = x[run_index[0]]['e_life']
    mes = 'Elife values do not match. Please check'
    assert elife_cmt == elife, mes
コード例 #14
0
    def setup(self):
        self.to_pe = straxen.get_correction_from_cmt(self.run_id,
                                                     self.config['gain_model'])

        buffer_pmts = np.zeros(self.config['he_channel_offset'])
        self.to_pe = np.concatenate((buffer_pmts, self.to_pe))
        self.to_pe *= self.config['le_to_he_amplification']

        # Check config of `hit_min_amplitude_he` and define hit thresholds
        # if cmt config
        if is_cmt_option(self.config['hit_min_amplitude_he']):
            self.hit_thresholds = straxen.get_correction_from_cmt(
                self.run_id, self.config['hit_min_amplitude_he'])
        # if hitfinder_thresholds config
        elif isinstance(self.config['hit_min_amplitude_he'], str):
            self.hit_thresholds = straxen.hit_min_amplitude(
                self.config['hit_min_amplitude_he'])
        else:  # int or array
            self.hit_thresholds = self.config['hit_min_amplitude_he']

        self.channel_range = self.config['channel_map']['he']
コード例 #15
0
def test_mc_wrapper_gains(
    run_id='009000',
    cmt_id='016000',
    mc_id='mc_0',
    execute=True,
):
    """
    Test that for two different run ids, we get different gains using
    the MC wrapper.
    :param run_id: First run-id (used for normal query)
    :param cmt_id: Second run-id used as a CMT id (should not be the
        same as run_id! otherwise the values might actually be the same
        and the test does not work).
    :param execute: Execute this test (this is set to False since the
        test takes 9 minutes which is too long. We can activate this if
        the testing time due to faster CMT queries is reduced).
    :return: None
    """
    if not straxen.utilix_is_configured() or not execute:
        return

    assert np.abs(int(run_id) - int(cmt_id)) > 500, 'runs must be far apart'

    # First for the run-id let's get the value
    gains = straxen.get_correction_from_cmt(run_id,
                                            ('to_pe_model', 'ONLINE', True))

    # Now, we repeat the same query using the MC wrapper, this should
    # give us a different result since we are now asking for a very
    # different run-number.
    mc_gains_diff = straxen.get_correction_from_cmt(
        mc_id, ('MC', cmt_id, 'to_pe_model', 'ONLINE', True))

    # Repeat the query from above to verify, let's see if we are getting
    # the same results as for `gains` above
    mc_gains_same = straxen.get_correction_from_cmt(
        mc_id, ('MC', run_id, 'to_pe_model', 'ONLINE', True))

    assert not np.all(gains == mc_gains_diff)
    assert np.all(gains == mc_gains_same)
コード例 #16
0
ファイル: veto_hitlets.py プロジェクト: jorana/straxen
    def setup(self):
        self.channel_range = self.config['channel_map']['nveto']
        self.n_channel = (self.channel_range[1] - self.channel_range[0]) + 1

        to_pe = straxen.get_correction_from_cmt(self.run_id,
                                                self.config['gain_model_nv'])

        # Create to_pe array of size max channel:
        self.to_pe = np.zeros(self.channel_range[1] + 1, dtype=np.float32)
        self.to_pe[self.channel_range[0]:] = to_pe[:]

        # Check config of `hit_min_amplitude_nv` and define hit thresholds
        # if cmt config
        if is_cmt_option(self.config['hit_min_amplitude_nv']):
            self.hit_thresholds = straxen.get_correction_from_cmt(
                self.run_id, self.config['hit_min_amplitude_nv'])
        # if hitfinder_thresholds config
        elif isinstance(self.config['hit_min_amplitude_nv'], str):
            self.hit_thresholds = straxen.hit_min_amplitude(
                self.config['hit_min_amplitude_nv'])
        else:  # int or array
            self.hit_thresholds = self.config['hit_min_amplitude_nv']
コード例 #17
0
ファイル: event_patternfit.py プロジェクト: jorana/straxen
    def setup(self):
        self.electron_drift_velocity = get_correction_from_cmt(
            self.run_id, self.config['electron_drift_velocity'])
        self.electron_drift_time_gate = get_correction_from_cmt(
            self.run_id, self.config['electron_drift_time_gate'])
        self.mean_pe_photon = self.config['mean_pe_per_photon']

        # Getting S1 AFT maps
        self.s1_aft_map = straxen.InterpolatingMap(
            straxen.get_resource(self.config['s1_aft_map'],
                                 fmt=self._infer_map_format(
                                     self.config['s1_aft_map'])))

        # Getting optical maps
        self.s1_pattern_map = straxen.InterpolatingMap(
            straxen.get_resource(self.config['s1_optical_map'],
                                 fmt=self._infer_map_format(
                                     self.config['s1_optical_map'])))
        self.s2_pattern_map = straxen.InterpolatingMap(
            straxen.get_resource(self.config['s2_optical_map'],
                                 fmt=self._infer_map_format(
                                     self.config['s2_optical_map'])))

        # Getting S2 data-driven tensorflow models
        downloader = straxen.MongoDownloader()
        self.model_file = downloader.download_single(
            self.config['s2_tf_model'])
        with tempfile.TemporaryDirectory() as tmpdirname:
            tar = tarfile.open(self.model_file, mode="r:gz")
            tar.extractall(path=tmpdirname)

            import tensorflow as tf

            def _logl_loss(patterns_true, likelihood):
                return likelihood / 10.

            self.model = tf.keras.models.load_model(
                tmpdirname, custom_objects={"_logl_loss": _logl_loss})
            self.model_chi2 = tf.keras.Model(
                self.model.inputs,
                self.model.get_layer('Likelihood').output)

        # Getting gain model to get dead PMTs
        self.to_pe = straxen.get_correction_from_cmt(self.run_id,
                                                     self.config['gain_model'])
        self.dead_PMTs = np.where(self.to_pe == 0)[0]
        self.pmtbool = ~np.in1d(np.arange(0, self.config['n_tpc_pmts']),
                                self.dead_PMTs)
        self.pmtbool_top = self.pmtbool[:self.config['n_top_pmts']]
        self.pmtbool_bottom = self.pmtbool[self.config['n_top_pmts']:self.
                                           config['n_tpc_pmts']]
コード例 #18
0
    def setup(self):
        if self.config['peak_min_pmts'] > 2:
            # Can fix by re-splitting,
            raise NotImplementedError(
                f"Raising the peak_min_pmts to {self.config['peak_min_pmts']} "
                f"interferes with lone_hit definition. "
                f"See github.com/XENONnT/straxen/issues/295")

        self.to_pe = straxen.get_correction_from_cmt(self.run_id,
                                                     self.config['gain_model'])

        # Check config of `hit_min_amplitude` and define hit thresholds
        # if cmt config
        if is_cmt_option(self.config['hit_min_amplitude']):
            self.hit_thresholds = straxen.get_correction_from_cmt(
                self.run_id, self.config['hit_min_amplitude'])
        # if hitfinder_thresholds config
        elif isinstance(self.config['hit_min_amplitude'], str):
            self.hit_thresholds = straxen.hit_min_amplitude(
                self.config['hit_min_amplitude'])
        else:  # int or array
            self.hit_thresholds = self.config['hit_min_amplitude']

        self.channel_range = self.config['channel_map']['tpc']
コード例 #19
0
ファイル: pulse_processing.py プロジェクト: jorana/straxen
    def setup(self):
        self.hev_enabled = False
        self.config['n_tpc_pmts'] = self.config['n_he_pmts']

        # Check config of `hit_min_amplitude` and define hit thresholds
        # if cmt config
        if is_cmt_option(self.config['hit_min_amplitude_he']):
            self.hit_thresholds = straxen.get_correction_from_cmt(
                self.run_id, self.config['hit_min_amplitude_he'])
        # if hitfinder_thresholds config
        elif isinstance(self.config['hit_min_amplitude_he'], str):
            self.hit_thresholds = straxen.hit_min_amplitude(
                self.config['hit_min_amplitude_he'])
        else:  # int or array
            self.hit_thresholds = self.config['hit_min_amplitude_he']
コード例 #20
0
def test_1T_elife():
    """
    Test elife from CMT DB against historical data(aux file)
    """
    if not straxen.utilix_is_configured():
        warn('Cannot do test becaus  ' 'no have access to the database.')
        return

    elife_conf = ('elife', 'ONLINE', False)
    elife_cmt = straxen.get_correction_from_cmt(test_run_id_1T, elife_conf)
    elife_file = elife_conf = aux_repo + '3548132b55f81a43654dba5141366041e1daaf01/strax_files/elife.npy'
    x = straxen.get_resource(elife_file, fmt='npy')
    run_index = np.where(x['run_id'] == int(test_run_id_1T))[0]
    elife = x[run_index[0]]['e_life']
    mes = 'Elife values do not match. Please check'
    assert elife_cmt == elife, mes
コード例 #21
0
    def _get_model_file_name(self):

        config_file = f'{self.algorithm}_model'
        model_from_config = self.config.get(config_file, 'No file')
        if model_from_config == 'No file':
            raise ValueError(f'{__class__.__name__} should have {config_file} '
                             f'provided as an option.')
        if isinstance(model_from_config,
                      str) and os.path.exists(model_from_config):
            # Allow direct path specification
            return model_from_config
        if model_from_config is None:
            # Allow None to be specified (disables processing for given posrec)
            return model_from_config

        # Use CMT
        model_file = straxen.get_correction_from_cmt(self.run_id,
                                                     model_from_config)
        return model_file
コード例 #22
0
    def set_config(self, ):
        super().set_config()

        if 'nveto' in self.config['targets']:
            self.config_nveto = deepcopy(self.config)
            self.config_nveto.update(
                straxen.get_resource(self.config_nveto['fax_config_nveto'],
                                     fmt='json'))
            self.config_nveto['detector'] = 'XENONnT_neutron_veto'
            self.config_nveto['channel_map'] = dict(
                self.config_nveto['channel_map'])
            overrides = self.config['fax_config_override_nveto']
            if overrides is not None:
                self.config_nveto.update(overrides)

            self.to_pe_nveto = straxen.get_correction_from_cmt(
                self.run_id, self.config['gain_model_nv'])

            self.config_nveto['gains'] = np.divide(
                (2e-9 * 2 / 2**14) / (1.6e-19 * 1 * 50),
                self.to_pe_nveto,
                out=np.zeros_like(self.to_pe_nveto),
                where=self.to_pe_nveto != 0)
            self.config_nveto['channels_bottom'] = np.array([], np.int64)
コード例 #23
0
 def setup(self):
     self.hev_enabled = ((self.config['hev_gain_model'][0] != 'disabled')
                         and self.config['tail_veto_threshold'])
     if self.hev_enabled:
         self.to_pe = straxen.get_correction_from_cmt(
             self.run_id, self.config['hev_gain_model'])
コード例 #24
0
 def setup(self):
     self.to_pe = straxen.get_correction_from_cmt(self.run_id,
                                                  self.config['gain_model'])
コード例 #25
0
def load_corrected_positions(context,
                             run_id,
                             events,
                             alt_s1=False,
                             alt_s2=False,
                             cmt_version=None,
                             posrec_algos=('mlp', 'gcn', 'cnn')):
    """
    Returns the corrected position for each position algorithm available,
        without the need to reprocess event_basics, as the needed
        information is already stored in event_basics.
    
    :param alt_s1: False by default, if True it uses alternative S1 as main one
    :param alt_s2: False by default, if True it uses alternative S2 as main one
    :param cmt_version: CMT version to use (it can be a list of same
        length as posrec_algos, if different versions are required for
        different posrec algorithms, default 'local_ONLINE')
    :param posrec_algos: list of position reconstruction algorithms to
        use (default ['mlp', 'gcn', 'cnn'])
    """

    posrec_algos = strax.to_str_tuple(posrec_algos)

    if cmt_version is None:
        fdc_config = context.get_single_plugin(
            run_id, 'event_positions').config['fdc_map']
        if isinstance(fdc_config, str) and 'cmt://' in fdc_config:
            cmt_version = straxen.URLConfig.split_url_kwargs(fdc_config)
        elif straxen.is_cmt_option(fdc_config):
            cmt_version = fdc_config[1]
        else:
            raise ValueError(
                'FDC map is not a CMT option, cannot infer cmt version.')

    if (isinstance(cmt_version, (tuple, list))
            and len(cmt_version) != len(posrec_algos)):
        raise TypeError(f"cmt_version is a list but does not match the "
                        f"posrec_algos ({posrec_algos}) length.")

    cmt_version = ((cmt_version, ) * len(posrec_algos) if isinstance(
        cmt_version, str) else cmt_version)

    # Get drift from CMT
    ep = context.get_single_plugin(run_id, 'event_positions')
    drift_speed = ep.electron_drift_velocity
    drift_time_gate = ep.electron_drift_time_gate

    dtype = load_dtypes(posrec_algos)
    result = np.zeros(len(events), dtype=dtype)

    s1_pre = 'alt_' if alt_s1 else ''
    s2_pre = 'alt_' if alt_s2 else ''
    drift_time = events['drift_time'] if not (alt_s1 or alt_s2) else events[
        s2_pre + 's2_center_time'] - events[s1_pre + 's1_center_time']

    z_obs = -drift_speed * drift_time

    for algo, v_cmt in zip(posrec_algos, cmt_version):
        fdc_tmp = (f'fdc_map_{algo}', v_cmt, True)
        map_tmp = straxen.get_correction_from_cmt(run_id, fdc_tmp)
        itp_tmp = straxen.InterpolatingMap(
            straxen.common.get_resource(map_tmp, fmt='binary'))
        itp_tmp.scale_coordinates([1., 1., -drift_speed])

        orig_pos = np.vstack([
            events[f'{s2_pre}s2_x_{algo}'], events[f'{s2_pre}s2_y_{algo}'],
            z_obs
        ]).T
        r_obs = np.linalg.norm(orig_pos[:, :2], axis=1)
        delta_r = itp_tmp(orig_pos)
        z_obs = z_obs + drift_speed * drift_time_gate

        # apply radial correction
        with np.errstate(invalid='ignore', divide='ignore'):
            r_cor = r_obs + delta_r
            scale = r_cor / r_obs

        with np.errstate(invalid='ignore'):
            z_cor = -(z_obs**2 - delta_r**2)**0.5
            invalid = np.abs(z_obs) < np.abs(delta_r)
        z_cor[invalid] = z_obs[invalid]

        result[f'x_{algo}'] = orig_pos[:, 0] * scale
        result[f'y_{algo}'] = orig_pos[:, 1] * scale
        result[f'r_{algo}'] = r_cor
        result[f'r_naive_{algo}'] = r_obs
        result[f'r_field_distortion_correction_{algo}'] = delta_r
        result[f'theta_{algo}'] = np.arctan2(orig_pos[:, 1], orig_pos[:, 0])
        result[f'z_{algo}'] = z_cor

    result['z_naive'] = z_obs
    return result
コード例 #26
0
def plot_pulses(context,
                raw_records,
                run_id,
                time_range,
                plot_hits=False,
                plot_median=False,
                max_plots=20,
                store_pdf=False,
                path='',
                detector_ending=''):
    """
    Plots nveto pulses for a list of records.
    :param context: Context to be used.
    :param plot_hits: If True plot hit boundaries including the left
        and right extension as orange shaded regions.
    :param plot_median: If true plots pulses sample median as dotted
        line.
    :param max_plots: Limits the number of figures. If you would like
        to plot more pulses you should put the plots in a PDF.
    :param store_pdf: If true figures are put to a PDF instead of
        plotting them to your notebook. The file name is automatically
        generated including the time range and run_id.
    :param path: Relative path where the PDF should be stored. By default
        it is the directory of the notebook.
    :param detector_ending: Ending of the corresponding detector. Empty
        string for TPC '_nv' for neutron-veto and '_mv' muon-veto. 
    """
    # Register records plugin to get settings
    p = context.get_single_plugin(run_id, 'records' + detector_ending)

    # Compute strax baseline and baseline_rms:
    records = strax.raw_to_records(raw_records)
    records = strax.sort_by_time(records)
    strax.zero_out_of_bounds(records)

    baseline_key = [
        key for key in p.config.keys() if 'baseline_samples' in key
    ][0]

    if isinstance(p.config[baseline_key], int):
        baseline_samples = p.config[baseline_key]
    else:
        baseline_samples = straxen.get_correction_from_cmt(
            run_id, p.config[baseline_key])

    strax.baseline(records, baseline_samples=baseline_samples, flip=True)

    nfigs = 1
    if store_pdf and time_range is None:
        raise ValueError(f'Specify time range!')
    if store_pdf:
        from matplotlib.backends.backend_pdf import PdfPages
        fname = f'pulses_{run_id}_{time_range[0]}_{time_range[1]}.pdf'
        fname = os.path.join(path, fname)
        pdf = PdfPages(fname)

    hits = None  # needed for delete if false

    for inds in _yield_pulse_indices(raw_records):
        # Grouped our pulse so now plot:
        rr_pulse = raw_records[inds]
        r_pulse = records[inds]

        fig, axes = straxen.plot_single_pulse(rr_pulse, run_id)
        if detector_ending == '_nv':
            # We only store for the nv digitizer baseline values:
            axes.axhline(rr_pulse[0]['baseline'],
                         ls='dashed',
                         color='k',
                         label=f'D. Bas.: {rr_pulse[0]["baseline"]} ADC')

        baseline = r_pulse[0]['baseline']
        baseline_rms = r_pulse[0]['baseline_rms']
        axes.axhline(
            baseline,
            ls='solid',
            color='k',
            label=
            f'Strax Bas. +/-RMS:\n ({baseline:.2f}+/-{baseline_rms:.2f}) ADC')
        xlim = axes.get_xlim()
        axes.fill_between(xlim, [baseline + baseline_rms] * 2,
                          [baseline - baseline_rms] * 2,
                          color='gray',
                          alpha=0.4)

        # check type of p.hit_thresholds
        if isinstance(p.hit_thresholds, int):
            thr = p.hit_thresholds
        elif isinstance(p.hit_thresholds, np.ndarray):
            thr = p.hit_thresholds[rr_pulse['channel']][0]

        if plot_median:
            # Plot median if asked.
            # Have to make pulse again:
            pulse = straxen.matplotlib_utils._make_pulse(rr_pulse)
            median = np.median(pulse)
            axes.axhline(median,
                         ls='dotted',
                         color='k',
                         label=f'Median Bas.: {median:.0f} ADC')

            axes.axhline(median - thr, ls='dotted', color='orange')

        if plot_hits:
            min_amplitude = thr

            axes.axhline(baseline - min_amplitude,
                         color='orange',
                         label='Hitfinder threshold')

            hits = strax.find_hits(r_pulse, min_amplitude=min_amplitude)
            if detector_ending != '_he':
                # We don't have 'save_outside_hits_he' at all!
                le, re = p.config['save_outside_hits' + detector_ending]
            else:
                le, re = p.config['save_outside_hits']
            start = (hits['time'] - r_pulse[0]['time']) / r_pulse[0]['dt'] - le
            end = (strax.endtime(hits) -
                   r_pulse[0]['time']) / r_pulse[0]['dt'] + re

            ylim = axes.get_ylim()
            for s, e in zip(start, end):
                plt.fill_between((s, e), *ylim, alpha=0.2, color='orange')
            axes.set_ylim(*ylim)

        plt.legend()
        axes.set_xlim(*xlim)

        if store_pdf:
            plt.close()
            pdf.savefig(fig)

        nfigs += 1
        if max_plots is not None and nfigs > max_plots:
            break

    if store_pdf:
        pdf.close()
    del records, hits
コード例 #27
0
ファイル: mini_analysis.py プロジェクト: jorana/straxen
        def wrapped_f(context: strax.Context, run_id: str, **kwargs):
            # Validate arguments
            known_kwargs = (
                'time_range seconds_range time_within time_selection '
                'ignore_time_warning '
                'selection_str t_reference to_pe config').split()
            for k in kwargs:
                if k not in known_kwargs and k not in parameters:
                    # Python itself also raises TypeError for invalid kwargs
                    raise TypeError(f"Unknown argument {k} for {f.__name__}")

            if 'config' in kwargs:
                context = context.new_context(config=kwargs['config'])
            if 'config' in parameters:
                kwargs['config'] = context.config

            # Say magic words to enable holoviews
            if hv_bokeh:
                # Generally using globals is not great, but it would be
                # the same as doing a slow import on the top of this file
                # pylint: disable=global-statement
                global _hv_bokeh_initialized
                if not _hv_bokeh_initialized:
                    import holoviews
                    holoviews.extension('bokeh')
                    _hv_bokeh_initialized = True

            if 'to_pe' in parameters and 'to_pe' not in kwargs:
                kwargs['to_pe'] = straxen.get_correction_from_cmt(
                    run_id, context.config['gain_model'])

            # Prepare selection arguments
            kwargs['time_range'] = context.to_absolute_time_range(
                run_id,
                targets=requires,
                **{
                    k: kwargs.get(k)
                    for k in ('time_range seconds_range time_within'.split())
                })
            kwargs.setdefault('time_selection', default_time_selection)
            kwargs.setdefault('selection_str', None)

            kwargs['t_reference'], _ = context.estimate_run_start_and_end(
                run_id, requires)

            if warn_beyond_sec is not None and not kwargs.get(
                    'ignore_time_warning'):
                tr = kwargs['time_range']
                if tr is None:
                    sec_requested = float('inf')
                else:
                    sec_requested = (tr[1] - tr[0]) / int(1e9)
                if sec_requested > warn_beyond_sec:
                    tr_str = "the entire run" if tr is None else f"{sec_requested} seconds"
                    raise ValueError(
                        f"The author of this mini analysis recommends "
                        f"not requesting more than {warn_beyond_sec} seconds. "
                        f"You are requesting {tr_str}. If you wish to proceed, "
                        "pass ignore_time_warning = True.")

            # Load required data, if any
            if len(requires):
                deps_by_kind = strax.group_by_kind(requires, context=context)
                for dkind, dtypes in deps_by_kind.items():
                    if dkind in kwargs:
                        # Already have data, just apply cuts
                        kwargs[dkind] = strax.apply_selection(
                            kwargs[dkind],
                            selection_str=kwargs['selection_str'],
                            time_range=kwargs['time_range'],
                            time_selection=kwargs['time_selection'])
                    else:
                        kwargs[dkind] = context.get_array(
                            run_id,
                            dtypes,
                            selection_str=kwargs['selection_str'],
                            time_range=kwargs['time_range'],
                            time_selection=kwargs['time_selection'],
                            # Arguments for new context, if needed
                            config=kwargs.get('config'),
                            register=kwargs.get('register'),
                            storage=kwargs.get('storage', tuple()),
                            progress_bar=False,
                        )

                # If user did not give time kwargs, but the function expects
                # a time_range, try to add one based on the time range of the data
                base_dkind = list(deps_by_kind.keys())[0]
                x = kwargs[base_dkind]
                if len(x) and kwargs.get('time_range') is None:
                    x0 = x.iloc[0] if isinstance(x, pd.DataFrame) else x[0]
                    try:
                        kwargs.setdefault('time_range',
                                          (x0['time'], strax.endtime(x).max()))

                    except AttributeError:
                        # If x is a holoviews dataset, this will fail.
                        pass

            if 'seconds_range' in parameters:
                if kwargs.get('time_range') is None:
                    scr = None
                else:
                    scr = tuple([(t - kwargs['t_reference']) / int(1e9)
                                 for t in kwargs['time_range']])
                kwargs.setdefault('seconds_range', scr)

            kwargs.setdefault('run_id', run_id)
            kwargs.setdefault('context', context)

            if 'kwargs' in parameters:
                # Likely this will be passed to another mini-analysis
                to_pass = kwargs
                # Do not pass time_range and seconds_range both (unless explicitly requested)
                # strax does not like that
                if 'seconds_range' in to_pass and not 'seconds_range' in parameters:
                    del to_pass['seconds_range']
                if 'time_within' in to_pass and not 'time_within' in parameters:
                    del to_pass['time_within']
            else:
                # Pass only arguments the function wants
                to_pass = {k: v for k, v in kwargs.items() if k in parameters}
            return f(**to_pass)
コード例 #28
0
 def setup(self):
     if isinstance(self.config['baseline_samples_nv'], int):
         self.baseline_samples = self.config['baseline_samples_nv']
     else:
         self.baseline_samples = straxen.get_correction_from_cmt(
             self.run_id, self.config['baseline_samples_nv'])
コード例 #29
0
ファイル: posrec_comparison.py プロジェクト: jorana/straxen
def load_corrected_positions(context,
                             run_id,
                             events,
                             cmt_version=None,
                             posrec_algos=('mlp', 'gcn', 'cnn')):
    """
    Returns the corrected position for each position algorithm available,
        without the need to reprocess event_basics, as the needed
        information is already stored in event_basics.
    
    :param cmt_version: CMT version to use (it can be a list of same
        length as posrec_algos, if different versions are required for
        different posrec algorithms, default 'local_ONLINE')
    :param posrec_algos: list of position reconstruction algorithms to
        use (default ['mlp', 'gcn', 'cnn'])
    """

    posrec_algos = strax.to_str_tuple(posrec_algos)

    if cmt_version is None:
        fdc_config = None
        try:
            fdc_config = context.get_single_plugin(
                run_id, 'event_positions').config['fdc_map']
            cmt_version = fdc_config[1]
        except IndexError as e:
            raise ValueError(
                f'CMT is not set? Your fdc config is {fdc_config}') from e

    if (isinstance(cmt_version, (tuple, list))
            and len(cmt_version) != len(posrec_algos)):
        raise TypeError(f"cmt_version is a list but does not match the "
                        f"posrec_algos ({posrec_algos}) length.")

    cmt_version = ((cmt_version, ) * len(posrec_algos) if isinstance(
        cmt_version, str) else cmt_version)

    # Get drift from CMT
    ep = context.get_single_plugin(run_id, 'event_positions')
    drift_conf = ep.config.get('electron_drift_velocity')
    drift_speed = straxen.get_correction_from_cmt(run_id, drift_conf)
    dtype = []

    for algo in posrec_algos:
        for xyzr in 'x y z r'.split():
            dtype += [
                ((f'Interaction {xyzr}-position, field-distortion corrected (cm) - '
                  f'{algo.upper()} posrec algorithm', f'{xyzr}_{algo}'),
                 np.float32),
            ]
        dtype += [((
            f'Interaction r-position using observed S2 positions directly (cm) -'
            f' {algo.upper()} posrec algorithm', f'r_naive_{algo}'),
                   np.float32),
                  ((f'Correction added to r_naive for field distortion (cm) - '
                    f'{algo.upper()} posrec algorithm',
                    f'r_field_distortion_correction_{algo}'), np.float32),
                  ((f'Interaction angular position (radians) - {algo.upper()} '
                    f'posrec algorithm', f'theta_{algo}'), np.float32)]

    dtype += [(('Interaction z-position using mean drift velocity only (cm)',
                'z_naive'), np.float32)]
    result = np.zeros(len(events), dtype=dtype)

    z_obs = -drift_speed * events['drift_time']

    for algo, v_cmt in zip(posrec_algos, cmt_version):
        fdc_tmp = (f'fdc_map_{algo}', v_cmt, True)
        map_tmp = straxen.get_correction_from_cmt(run_id, fdc_tmp)
        itp_tmp = straxen.InterpolatingMap(
            straxen.common.get_resource(map_tmp, fmt='binary'))
        itp_tmp.scale_coordinates([1., 1., -drift_speed])

        orig_pos = np.vstack(
            [events[f's2_x_{algo}'], events[f's2_y_{algo}'], z_obs]).T
        r_obs = np.linalg.norm(orig_pos[:, :2], axis=1)
        delta_r = itp_tmp(orig_pos)

        # apply radial correction
        with np.errstate(invalid='ignore', divide='ignore'):
            r_cor = r_obs + delta_r
            scale = r_cor / r_obs

        with np.errstate(invalid='ignore'):
            z_cor = -(z_obs**2 - delta_r**2)**0.5
            invalid = np.abs(z_obs) < np.abs(delta_r)
        z_cor[invalid] = z_obs[invalid]

        result[f'x_{algo}'] = orig_pos[:, 0] * scale
        result[f'y_{algo}'] = orig_pos[:, 1] * scale
        result[f'r_{algo}'] = r_cor
        result[f'r_naive_{algo}'] = r_obs
        result[f'r_field_distortion_correction_{algo}'] = delta_r
        result[f'theta_{algo}'] = np.arctan2(orig_pos[:, 1], orig_pos[:, 0])
        result[f'z_{algo}'] = z_cor

    result['z_naive'] = z_obs
    return result