Skip to main content

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.ndarray or list, shape (N,) - pulse arrival times in ns
  • charges: np.ndarray or list, shape (N,) - pulse charges
  • extended: bool - if True, compute 25 statistics; if False (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: dict holding photon-level arrays (either provide a top-level photons dictionary or store the required fields directly) with keys sensor_pos_x, sensor_pos_y, sensor_pos_z, string_id, sensor_id, t, and optional charge
  • grouping_window_ns: float or None - time window for grouping hits (default: None, no grouping)
  • extended: bool - if True, compute 25 statistics per sensor; if False (default), compute 9

Returns: tuple[np.ndarray, np.ndarray]

  • sensor_positions: np.ndarray, shape (N_sensors, 3) - sensor positions
  • sensor_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.ndarray or list, shape (N,) - hit times for sensor
  • sensor_charges: np.ndarray or list, shape (N,) - hit charges (optional, defaults to 1.0)
  • grouping_window_ns: float or None - time window for grouping hits (default: None, no grouping)
  • extended: bool - if True, compute 25 statistics; if False (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

nt_summary_stats-1.1.tar.gz (20.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

nt_summary_stats-1.1-cp311-cp311-manylinux_2_34_x86_64.whl (124.8 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.34+ x86-64

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

Hashes for nt_summary_stats-1.1.tar.gz
Algorithm Hash digest
SHA256 7cb398fb3fa88943e9fba4be82a4563d3d8488f75b20baff7ea740d85d434a2e
MD5 2ea1ffec31713fc35eec1c1686bbd6ae
BLAKE2b-256 2691bc491e66fd1e9980e13b484884622923a99f9246c35f15085042d59dda49

See more details on using hashes here.

File details

Details for the file nt_summary_stats-1.1-cp311-cp311-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for nt_summary_stats-1.1-cp311-cp311-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 b2df154cb5143ed490d55828165557467a8764b2250c77209328e27cecdea890
MD5 0846044b25c124e8a2511170d2d764a8
BLAKE2b-256 e38a5e2edae713ea0a144dcd46e92c703d77fb8a3740f9786c4f5a29d38295c9

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page