Fast computation of traditional summary statistics for neutrino telescopes
Project description
NT Summary Stats
Fast computation (C++) of traditional summary statistics for neutrino telescopes for Python. The summary stats computed are based off of this paper.
Install
pip install nt_summary_stats
The wheel ships with the C++ backend enabled by default; source installs will build the
nt_summary_stats._native extension automatically (requires a C++17 compiler and
pybind11). Set NTSS_DISABLE_NATIVE=1 if you need to fall back to the pure NumPy
implementation.
Usage
import numpy as np
from nt_summary_stats import compute_summary_stats
# Basic usage (9 standard statistics)
times = np.array([10.0, 15.0, 25.0, 100.0]) # shape: (N,), dtype: float
charges = np.array([1.0, 2.0, 1.5, 0.5]) # shape: (N,), dtype: float
stats = compute_summary_stats(times, charges) # returns: np.ndarray, shape (9,)
print(stats[0]) # total_charge: 5.0
print(stats[3]) # first_pulse_time: 10.0
print(stats[7]) # charge_weighted_mean_time: 26.0
# Extended statistics (25 total statistics)
extended_stats = compute_summary_stats(times, charges, extended=True) # returns: np.ndarray, shape (25,)
print(extended_stats.shape) # (25,)
print(extended_stats[9]) # charge_5_percent_time
print(extended_stats[21]) # n_pulses: 4.0
Process detector events that expose the required photon-level keys:
from nt_summary_stats import process_event
# Input: event dictionary with required photon fields
event_data = {
'photons': {
'sensor_pos_x': [0.0, 0.0, 100.0], # list[float], length M
'sensor_pos_y': [0.0, 0.0, 0.0], # list[float], length M
'sensor_pos_z': [0.0, 0.0, 50.0], # list[float], length M
'string_id': [1, 1, 2], # list[int], length M
'sensor_id': [1, 1, 1], # list[int], length M
't': [10.0, 15.0, 20.0] # list[float], length M
}
}
# Default: no grouping (uses all hits as-is)
sensor_positions, sensor_stats = process_event(event_data)
# Optional: group hits within time windows
sensor_positions, sensor_stats = process_event(event_data, grouping_window_ns=2.0)
# sensor_positions: np.ndarray, shape (N_sensors, 3), dtype: float64
# sensor_stats: np.ndarray, shape (N_sensors, 9), dtype: float64
# Arrays are aligned: sensor_positions[i] corresponds to sensor_stats[i]
Process individual sensor data:
from nt_summary_stats import process_sensor_data
# Input: sensor hit data
sensor_times = [10.0, 10.5, 15.0, 100.0] # list[float] or np.ndarray(N,)
sensor_charges = [1.0, 0.5, 2.0, 1.0] # list[float] or np.ndarray(N,), optional
# Default: no grouping (uses all hits as-is)
stats = process_sensor_data(sensor_times, sensor_charges) # returns: np.ndarray, shape (9,)
# Optional: group hits within time windows
stats = process_sensor_data(sensor_times, sensor_charges, grouping_window_ns=2.0)
Summary Statistics
Computes summary statistics for neutrino telescope sensors as described in the IceCube paper. All functions return numpy arrays with statistics in the following order:
Standard Statistics (9 stats, default)
stats = compute_summary_stats(times, charges) # shape: (9,)
# Array indices:
stats[0] # total_charge: Total charge collected
stats[1] # charge_100ns: Charge within 100ns of first pulse
stats[2] # charge_500ns: Charge within 500ns of first pulse
stats[3] # first_pulse_time: Time of first pulse
stats[4] # last_pulse_time: Time of last pulse
stats[5] # charge_20_percent_time: Time at which 20% of charge is collected
stats[6] # charge_50_percent_time: Time at which 50% of charge is collected
stats[7] # charge_weighted_mean_time: Charge-weighted mean time
stats[8] # charge_weighted_std_time: Charge-weighted standard deviation
Extended Statistics (25 stats, optional)
Pass extended=True to compute 16 additional statistics:
stats = compute_summary_stats(times, charges, extended=True) # shape: (25,)
# Includes all 9 standard statistics above, plus:
stats[9] # charge_5_percent_time: Time at which 5% of charge is collected
stats[10] # charge_10_percent_time: Time at which 10% of charge is collected
stats[11] # charge_25_percent_time: Time at which 25% of charge is collected
stats[12] # charge_75_percent_time: Time at which 75% of charge is collected
stats[13] # charge_90_percent_time: Time at which 90% of charge is collected
stats[14] # charge_95_percent_time: Time at which 95% of charge is collected
stats[15] # charge_10ns: Charge within 10ns of first pulse
stats[16] # charge_20ns: Charge within 20ns of first pulse
stats[17] # charge_50ns: Charge within 50ns of first pulse
stats[18] # charge_200ns: Charge within 200ns of first pulse
stats[19] # charge_1000ns: Charge within 1000ns of first pulse
stats[20] # charge_2000ns: Charge within 2000ns of first pulse
stats[21] # n_pulses: Number of input pulses (pre-grouping count)
stats[22] # q_max_frac: Peak charge fraction (max pulse charge / total charge)
stats[23] # n_string_neighbors: HLC-style neighbor count (0 outside process_event)
stats[24] # t_skewness: Charge-weighted time skewness (0 for < 3 pulses)
API
compute_summary_stats(times, charges, extended=False)
Args:
times:np.ndarrayorlist, shape(N,)- pulse arrival times in nscharges:np.ndarrayorlist, shape(N,)- pulse chargesextended:bool- ifTrue, compute 25 statistics; ifFalse(default), compute 9
Returns: np.ndarray, shape (9,) or (25,) - array with summary statistics in order shown above
process_event(event_data, grouping_window_ns=None, extended=False)
Args:
event_data:dictholding photon-level arrays (either provide a top-levelphotonsdictionary or store the required fields directly) with keyssensor_pos_x,sensor_pos_y,sensor_pos_z,string_id,sensor_id,t, and optionalchargegrouping_window_ns:floatorNone- time window for grouping hits (default: None, no grouping)extended:bool- ifTrue, compute 25 statistics per sensor; ifFalse(default), compute 9
Returns: tuple[np.ndarray, np.ndarray]
sensor_positions:np.ndarray, shape(N_sensors, 3)- sensor positionssensor_stats:np.ndarray, shape(N_sensors, 9)or(N_sensors, 25)- statistics for each sensor (aligned with positions)
process_sensor_data(sensor_times, sensor_charges=None, grouping_window_ns=None, extended=False)
Args:
sensor_times:np.ndarrayorlist, shape(N,)- hit times for sensorsensor_charges:np.ndarrayorlist, shape(N,)- hit charges (optional, defaults to 1.0)grouping_window_ns:floatorNone- time window for grouping hits (default: None, no grouping)extended:bool- ifTrue, compute 25 statistics; ifFalse(default), compute 9
Returns: np.ndarray, shape (9,) or (25,) - array with summary statistics in order shown above
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file nt_summary_stats-1.1.tar.gz.
File metadata
- Download URL: nt_summary_stats-1.1.tar.gz
- Upload date:
- Size: 20.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7cb398fb3fa88943e9fba4be82a4563d3d8488f75b20baff7ea740d85d434a2e
|
|
| MD5 |
2ea1ffec31713fc35eec1c1686bbd6ae
|
|
| BLAKE2b-256 |
2691bc491e66fd1e9980e13b484884622923a99f9246c35f15085042d59dda49
|
File details
Details for the file nt_summary_stats-1.1-cp311-cp311-manylinux_2_34_x86_64.whl.
File metadata
- Download URL: nt_summary_stats-1.1-cp311-cp311-manylinux_2_34_x86_64.whl
- Upload date:
- Size: 124.8 kB
- Tags: CPython 3.11, manylinux: glibc 2.34+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b2df154cb5143ed490d55828165557467a8764b2250c77209328e27cecdea890
|
|
| MD5 |
0846044b25c124e8a2511170d2d764a8
|
|
| BLAKE2b-256 |
e38a5e2edae713ea0a144dcd46e92c703d77fb8a3740f9786c4f5a29d38295c9
|