コード例 #1
0
def raw_to_records(raw_records):
    records = np.zeros(
        len(raw_records),
        dtype=strax.record_dtype(
            record_length_from_dtype(raw_records.dtype)))
    strax.copy_to_buffer(raw_records, records, '_copy_raw_records')
    return records
コード例 #2
0
    def compute(self, records_nv, start, end):
        hits = strax.find_hits(records_nv, min_amplitude=self.config['hit_min_amplitude_nv'])
        hits = remove_switched_off_channels(hits, self.to_pe)

        temp_hitlets = strax.create_hitlets_from_hits(hits,
                                                      self.config['save_outside_hits_nv'],
                                                      self.channel_range,
                                                      chunk_start=start,
                                                      chunk_end=end)
        del hits

        # Get hitlet data and split hitlets:
        temp_hitlets = strax.get_hitlets_data(temp_hitlets, records_nv, to_pe=self.to_pe)

        temp_hitlets = strax.split_peaks(temp_hitlets,
                                         records_nv,
                                         self.to_pe,
                                         data_type='hitlets',
                                         algorithm='local_minimum',
                                         min_height=self.config['min_split_nv'],
                                         min_ratio=self.config['min_split_ratio_nv']
                                         )

        # Compute other hitlet properties:
        # We have to loop here 3 times over all hitlets...
        strax.hitlet_properties(temp_hitlets)
        entropy = strax.conditional_entropy(temp_hitlets, template='flat', square_data=False)
        temp_hitlets['entropy'][:] = entropy

        # Remove data field:
        hitlets = np.zeros(len(temp_hitlets), dtype=strax.hitlet_dtype())
        strax.copy_to_buffer(temp_hitlets, hitlets, '_copy_hitlets')
        return hitlets
コード例 #3
0
def create_hitlets_from_hits(
    hits,
    save_outside_hits,
    channel_range,
    chunk_start=0,
    chunk_end=np.inf,
):
    """
    Function which creates hitlets from a bunch of hits.

    :param hits: Hits found in records.
    :param save_outside_hits: Tuple with left and right hit extension.
    :param channel_range: Detectors change range from channel map.
    :param chunk_start: (optional) start time of a chunk. Ensures that
        no hitlet is earlier than this timestamp.
    :param chunk_end: (optional) end time of a chunk. Ensures that
        no hitlet ends later than this timestamp.

    :return: Hitlets with temporary fields (data, max_goodness_of_split...)
    """
    # Merge concatenate overlapping  within a channel. This is important
    # in case hits were split by record boundaries. In case we
    # accidentally concatenate two PMT signals we split them later again.
    hits = strax.concat_overlapping_hits(
        hits,
        save_outside_hits,
        channel_range,
        chunk_start,
        chunk_end,
    )
    hits = strax.sort_by_time(hits)

    hitlets = np.zeros(len(hits), strax.hitlet_dtype())
    strax.copy_to_buffer(hits, hitlets, '_refresh_hit_to_hitlets')
    return hitlets
コード例 #4
0
def get_records(raw_records, baseline_window):
    """
    Determine baseline as the average of the first baseline_samples
    of each pulse. Subtract the pulse float(data) from baseline.
    """

    record_length = np.shape(raw_records.dtype['data'])[0]

    _dtype = [
        (('Start time since unix epoch [ns]', 'time'), '<i8'),
        (('Length of the interval in samples', 'length'), '<i4'),
        (('Width of one sample [ns]', 'dt'), '<i2'),
        (('Channel/PMT number', 'channel'), '<i2'),
        (('Length of pulse to which the record belongs (without zero-padding)',
          'pulse_length'), '<i4'),
        (('Fragment number in the pulse', 'record_i'), '<i2'),
        (('Waveform data in raw ADC counts', 'data'), 'f4', (record_length, ))
    ]

    records = np.zeros(len(raw_records), dtype=_dtype)
    strax.copy_to_buffer(raw_records, records, "_rr_to_r_led")

    mask = np.where((records['record_i'] == 0) & (records['length'] == 160))[0]
    records = records[mask]
    bl = records['data'][:, baseline_window[0]:baseline_window[1]].mean(axis=1)
    records['data'][:, :160] = -1. * (records['data'][:, :160].transpose() -
                                      bl[:]).transpose()
    return records
コード例 #5
0
 def test_to_short_data_field(self):
     hitlets_to_short = np.zeros(len(self.hitlets),
                                 dtype=strax.hitlet_with_data_dtype(2))
     strax.copy_to_buffer(self.hitlets, hitlets_to_short,
                          '_refresh_hit_to_hitlet')
     with self.assertRaises(ValueError):
         strax.get_hitlets_data(hitlets_to_short, self.records,
                                np.ones(3000))
コード例 #6
0
    def test_get_hitlets_data_without_data_field(self):
        hitlets_empty = np.zeros(len(self.hitlets), strax.hitlet_dtype())
        strax.copy_to_buffer(self.hitlets, hitlets_empty,
                             '_copy_hitlets_to_hitlets_without_data')

        hitlets = strax.get_hitlets_data(hitlets_empty, self.records,
                                         np.ones(3000))
        self._test_data_is_identical(hitlets, [self.test_data_truth])
コード例 #7
0
    def compute(self, records_nv, start, end):
        # Search again for hits in records:
        hits = strax.find_hits(records_nv, min_amplitude=self.config['hit_min_amplitude_nv'])
        # Merge concatenate overlapping  within a channel. This is important
        # in case hits were split by record boundaries. In case we
        # accidentally concatenate two PMT signals we split them later again.
        hits = strax.concat_overlapping_hits(hits,
                                             self.config['save_outside_hits_nv'],
                                             self.channel_range,
                                             start,
                                             end)
        hits = strax.sort_by_time(hits)

        # Now convert hits into temp_hitlets including the data field:
        nsamples = 200
        if len(hits):
            nsamples = max(hits['length'].max(), nsamples)

        temp_hitlets = np.zeros(len(hits), strax.hitlet_with_data_dtype(n_samples=nsamples))
    
        # Generating hitlets and copying relevant information from hits to hitlets.
        # These hitlets are not stored in the end since this array also contains a data
        # field which we will drop later.
        strax.refresh_hit_to_hitlets(hits, temp_hitlets)
        del hits
        
        # Get hitlet data and split hitlets:
        strax.get_hitlets_data(temp_hitlets, records_nv, to_pe=self.to_pe)

        temp_hitlets = strax.split_peaks(temp_hitlets,
                                         records_nv,
                                         self.to_pe,
                                         data_type='hitlets',
                                         algorithm='local_minimum',
                                         min_height=self.config['min_split_nv'],
                                         min_ratio=self.config['min_split_ratio_nv']
                                         )

        # Compute other hitlet properties:
        # We have to loop here 3 times over all hitlets...
        strax.hitlet_properties(temp_hitlets)
        entropy = strax.conditional_entropy(temp_hitlets, template='flat', square_data=False)
        temp_hitlets['entropy'][:] = entropy

        # Remove data field:
        hitlets = np.zeros(len(temp_hitlets), dtype=strax.hitlet_dtype())
        strax.copy_to_buffer(temp_hitlets, hitlets, '_copy_hitlets')
        return hitlets
コード例 #8
0
ファイル: veto_events.py プロジェクト: XENONnT/straxen
    def compute(self, events_nv, hitlets_nv):
        event_angles = np.zeros(len(events_nv), dtype=self.dtype)

        # Split hitlets by containment, works since we updated event start/end in
        # compute_event_properties.
        hits_in_events = strax.split_by_containment(hitlets_nv, events_nv)

        # Compute hitlets within the first x ns of event:
        hits_in_events, n_prompt = first_hitlets(
            hits_in_events, self.config['position_max_time_nv'])
        event_angles['n_prompt_hitlets'] = n_prompt

        # Compute azimuthal angle and xyz positions:
        angle = get_average_angle(hits_in_events, self.pmt_properties)
        event_angles['angle'] = angle
        compute_positions(event_angles, hits_in_events, self.pmt_properties)
        strax.copy_to_buffer(events_nv, event_angles, f'_copy_events_nv')

        return event_angles
コード例 #9
0
    def compute(self, raw_records):
        '''
        The data for LED calibration are build for those PMT which belongs to channel list. 
        This is used for the different ligh levels. As defaul value all the PMTs are considered.
        '''
        mask = np.where(np.in1d(raw_records['channel'], self.config['channel_list']))[0]
        rr   = raw_records[mask]
        r    = get_records(rr, baseline_window=self.config['baseline_window'])
        del rr, raw_records

        temp = np.zeros(len(r), dtype=self.dtype)
        strax.copy_to_buffer(r, temp, "_recs_to_temp_led")

        on, off = get_amplitude(r, self.config['led_window'], self.config['noise_window'])
        temp['amplitude_led']   = on['amplitude']
        temp['amplitude_noise'] = off['amplitude']

        area = get_area(r, self.config['led_window'])
        temp['area'] = area['area']
        return temp
コード例 #10
0
def test_ext_timings_nv(records):
    """
    Little test for nVetoExtTimings.
    """
    if not straxen.utilix_is_configured():
        return
    # several fake records do not have any pulse length
    # and channel start at 0, convert to nv:
    records['pulse_length'] = records['length']
    records['channel'] += 2000

    st = straxen.contexts.xenonnt_led()
    plugin = st.get_single_plugin('1', 'ext_timings_nv')
    hits = strax.find_hits(records, min_amplitude=1)

    hitlets = np.zeros(len(hits), strax.hitlet_dtype())
    strax.copy_to_buffer(hits, hitlets, '_refresh_hit_to_hitlets')
    result = plugin.compute(hitlets, records)
    assert len(result) == len(hits)
    assert np.all(result['time'] == hits['time'])
    assert np.all(result['pulse_i'] == hits['record_i'])
    true_dt = hits['time'] - records[hits['record_i']]['time']
    assert np.all(result['delta_time'] == true_dt)
コード例 #11
0
def test_hitlet_properties(hits_n_data):
    """
    Function which tests refresh_hit_to_hitlets, hitlet_with_data_dtype,
    and hitlet_properties.

    :param hits_n_data:
    :return:
    """
    hits, data = hits_n_data

    hits['time'] += 100
    # Step 1.: Produce fake hits and convert them into hitlets:
    nsamples = 0
    if len(hits) >= 1:
        nsamples = hits['length'].max()
    nsamples = np.max((nsamples, 2))

    hitlets = np.zeros(len(hits), dtype=strax.hitlet_with_data_dtype(nsamples))
    if len(hitlets):
        assert hitlets['data'].shape[
            1] >= 2, 'Data buffer is not at least 2 samples long.'
    strax.copy_to_buffer(hits, hitlets,
                         '_refresh_hit_to_hitlet_properties_test')

    # Testing refresh_hit_to_hitlets for free:
    assert len(hits) == len(
        hitlets), 'Somehow hitlets and hits have different sizes'
    # Testing interval fields:
    dummy = np.zeros(0, dtype=strax.interval_dtype)
    for name in dummy.dtype.names:
        assert np.all(hitlets[name] == hits[name]), f'The entry of the field {name} did not match between hit and ' \
                                                    f'hitlets '

    # Step 2.: Add to each hit(let) some data
    for ind, d in enumerate(data):
        h = hitlets[ind]
        h['data'][:h['length']] = d[:h['length']]

    # Step 3.: Add np.nan in data but outside of length:
    for h in hitlets:
        if h['length'] < len(h['data']):
            h['data'][-1] = np.nan
            # It is enough to test this for a single hitlet:
            break

    # Step 4.: Compute properties and apply tests:
    strax.hitlet_properties(hitlets)
    for ind, d in enumerate(data):
        h = hitlets[ind]
        d = d[:h['length']]
        pos_max = np.argmax(d)

        # Checking amplitude things:
        assert pos_max == h[
            'time_amplitude'], 'Wrong amplitude position found!'
        assert d[pos_max] == h['amplitude'], 'Wrong amplitude value found!'

        # Checking FHWM and FWTM:
        fractions = [0.1, 0.5]
        for f in fractions:
            # Get field names for the correct test:
            if f == 0.5:
                left = 'left'
                fwxm = 'fwhm'
            else:
                left = 'low_left'
                fwxm = 'fwtm'

            amplitude = np.max(d)
            if np.all(d[0] == d) or np.all(d > amplitude * f):
                # If all samples are either the same or greater than required height FWXM is not defined:
                mes = 'All samples are the same or larger than require height.'
                assert np.isnan(
                    h[left]
                ), mes + f' Left edge for {f} should have been np.nan.'
                assert np.isnan(
                    h[left]), mes + f' FWXM for X={f} should have been np.nan.'
            else:
                le = np.argwhere(d[:pos_max] <= amplitude * f)
                if len(le):
                    le = le[-1, 0]
                    m = d[le + 1] - d[le]
                    le = le + 0.5 + (amplitude * f - d[le]) / m
                else:
                    le = 0

                re = np.argwhere(d[pos_max:] <= amplitude * f)

                if len(re) and re[0, 0] != 0:
                    re = re[0, 0] + pos_max
                    m = d[re] - d[re - 1]
                    re = re + 0.5 + (amplitude * f - d[re]) / m
                else:
                    re = len(d)

                assert math.isclose(
                    le, h[left], rel_tol=10**-4, abs_tol=10**
                    -4), f'Left edge does not match for fraction {f}'
                assert math.isclose(
                    re - le, h[fwxm], rel_tol=10**-4,
                    abs_tol=10**-4), f'FWHM does not match for {f}'
コード例 #12
0
 def compute(self, events):
     fiducial_events = events[events['cut_fiducial_cylinder_1t']]
     result = np.zeros(len(fiducial_events), dtype=self.dtype)
     # Cast the fiducual events dtype into the expected format
     strax.copy_to_buffer(fiducial_events, result, '_fiducial_copy')
     return result
コード例 #13
0
def test_raw_to_records(r):
    buffer = np.zeros(len(r), r.dtype)
    strax.copy_to_buffer(r, buffer, "_test_r_to_buffer")
    if len(r):
        assert np.all(buffer == r)
コード例 #14
0
def get_hitlets_data(hitlets, records, to_pe, min_hitlet_sample=200):
    """
    Function which searches for every hitlet in a given chunk the 
    corresponding records data. Additionally compute the total area of
    the signal.

    :param hitlets: Hitlets found in a chunk of records.
    :param records: Records of the chunk.
    :param to_pe: Array with area conversion factors from adc/sample to
        pe/sample. Please make sure that to_pe has the correct shape.
        The array index should match the channel number.
    :param min_hitlet_sample: minimal length of the hitlet data field.
        prevents numba compiling from running into race conditions.
    :returns: Hitlets including data stored in the "data" field
        (if it did not exists before it will be added.)
    """
    if len(hitlets) == 0:
        return np.zeros(0,
                        dtype=strax.hitlet_with_data_dtype(min_hitlet_sample))

    if len(hitlets) > 0 and len(records) == 0:
        raise ValueError('Cannot get data for hitlets if records are empty!')

    # Numba will not raise any exceptions if to_pe is too short, leading
    # to strange bugs.
    to_pe_has_wrong_shape = len(to_pe) < hitlets['channel'].max()
    if to_pe_has_wrong_shape:
        raise ValueError('"to_pe" has a wrong shape. Array index must'
                         ' match channel numbers.')

    hitelts_is_single_row = isinstance(hitlets, np.void)
    if hitelts_is_single_row:
        # A structured array becomes void type if a single row is called,
        # e.g. hitlets[0] which does not work in numba while, hitlets[:1]
        # does. So we have to convert the row into the correct format first.
        hitlets = np.array([hitlets])

    data_field_in_hitlets = 'data' in hitlets.dtype.names
    if data_field_in_hitlets:
        data_is_not_empty = np.any(hitlets['data'] != 0)
        if data_is_not_empty:
            raise ValueError('The data field of hitlets must be empty!')

        data_field_not_long_enough = len(
            hitlets[0]['data']) < hitlets['length'].max()
        if data_field_not_long_enough:
            raise ValueError(
                'The data field must be as large as the longest hitlet in our data.'
            )

        hitlets_with_data_field = hitlets
    else:
        n_samples = max(min_hitlet_sample, hitlets['length'].max())
        hitlets_with_data_field = np.zeros(
            len(hitlets), strax.hitlet_with_data_dtype(n_samples))
        strax.copy_to_buffer(hitlets, hitlets_with_data_field,
                             '_copy_hitlets_to_hitlets_width_data')

    _get_hitlets_data(hitlets_with_data_field, records, to_pe)
    if np.any(hitlets_with_data_field['length'] == 0):
        raise ValueError(
            'Try to create zero length hitlets which is forbidden!')

    return hitlets_with_data_field
コード例 #15
0
def copy_raw_records(old, new):
    warn('Deprecated, use strax.copy_to_buffer')
    strax.copy_to_buffer(old, new, '_copy_raw_records')