Pixel-Track Projection

Module that finds which pixels lie on the projection on the anode plane of each track segment. It can eventually include also the neighboring pixels.

larndsim.pixels_from_track.pixel2id(pixel_x, pixel_y, pixel_plane)[source]

Convert the (x, y, plane) pixel coordinate tuple to a unique integer identifier.

The identifier is computed as a linearised index over the pixel grid: pixel_x + N_PIXELS[0] * (pixel_y + N_PIXELS[1] * pixel_plane).

Parameters:
  • pixel_x (int) – Pixel index along the x-dimension (number of pixel pitches from the TPC border).

  • pixel_y (int) – Pixel index along the y-dimension (number of pixel pitches from the TPC border).

  • pixel_plane (int) – Pixel plane number (anode plane index).

Returns:

Unique integer identifier for the pixel.

Return type:

int

larndsim.pixels_from_track.id2pixel(pid)[source]

Convert a unique pixel identifier back to its (x, y, plane) coordinate tuple.

This is the inverse of pixel2id().

Parameters:

pid (int) – Unique integer pixel identifier as returned by pixel2id().

Returns:

A 3-tuple (pixel_x, pixel_y, pixel_plane) where

  • pixel_x – pixel index along the x-dimension,

  • pixel_y – pixel index along the y-dimension,

  • pixel_plane – anode plane index.

Return type:

tuple[int, int, int]

larndsim.pixels_from_track.max_pixels(tracks, n_max_pixels)[source]

CUDA kernel that calculates the maximum number of pixels intercepted across all supplied track segments.

Each CUDA thread handles one track. The per-track pixel count is computed with get_num_active_pixels() and the global maximum is updated atomically so the result is safe for concurrent execution.

Parameters:
  • tracks (numpy.ndarray) – Structured array of track segments. Each element must contain at least the fields x_start, x_end, y_start, y_end, and pixel_plane.

  • n_max_pixels (numpy.ndarray) – Single-element integer array used to accumulate the maximum pixel count via cuda.atomic.max. The result is written to index 0.

larndsim.pixels_from_track.get_pixels(tracks, active_pixels, neighboring_pixels, neighboring_radius, n_pixels_list)[source]

CUDA kernel that maps every track segment to its set of active and neighboring pixels on the anode plane.

For each track the kernel:

  1. Determines the start/end pixel coordinates from physical positions.

  2. Calls get_active_pixels() (Bresenham line) to find pixels directly under the projected track segment.

  3. Calls get_neighboring_pixels() to expand the set by including pixels within detector.MAX_RADIUS of each active pixel.

Parameters:
  • tracks (numpy.ndarray) – Structured array of track segments. Each element must contain the fields x_start, x_end, y_start, y_end, and pixel_plane.

  • active_pixels (numpy.ndarray) – 2-D integer array of shape (n_tracks, max_active_pixels) pre-filled with -1. On return, row i contains the unique pixel IDs that lie directly below the projection of track i.

  • neighboring_pixels (numpy.ndarray) – 2-D integer array of shape (n_tracks, max_neighboring_pixels) pre-filled with -1. On return, row i contains the unique pixel IDs of both the active pixels and their neighbours for track i.

  • neighboring_radius (numpy.ndarray) – 2-D float array of shape (n_tracks, max_neighboring_pixels). On return, entry [i, j] holds the Euclidean distance (in pixel-pitch units) from the nearest active pixel to neighboring_pixels[i, j].

  • n_pixels_list (numpy.ndarray) – 1-D integer array of length n_tracks. On return, element i contains the total number of valid entries in neighboring_pixels[i].

larndsim.pixels_from_track.get_num_active_pixels(x0, y0, x1, y1, plane_id)[source]

Count the number of pixels intercepted by the projection of a track segment onto the anode plane.

Uses an adapted Bresenham line algorithm (without diagonal steps) to traverse the pixel grid from (x0, y0) to (x1, y1) and counts only pixels that fall within the valid detector bounds.

Parameters:
  • x0 (int) – Start pixel index along the x-dimension.

  • y0 (int) – Start pixel index along the y-dimension.

  • x1 (int) – End pixel index along the x-dimension.

  • y1 (int) – End pixel index along the y-dimension.

  • plane_id (int) – Anode plane index used for bounds checking against detector.TPC_BORDERS.

Returns:

Number of valid (in-bounds) pixels intercepted by the line from (x0, y0) to (x1, y1) on the given plane.

Return type:

int

larndsim.pixels_from_track.get_active_pixels(x0, y0, x1, y1, plane_id, tot_pixels)[source]

Fill tot_pixels with the unique IDs of pixels intercepted by the projection of a track segment onto the anode plane.

Uses an adapted Bresenham line algorithm without diagonal movement to convert the line from (x0, y0) to (x1, y1) into a sequence of pixel-grid cells. Only pixels within the valid detector bounds are recorded. Inspired by https://stackoverflow.com/questions/8936183/bresenham-lines-w-o-diagonal-movement/28786538.

Parameters:
  • x0 (int) – Start pixel index along the x-dimension.

  • y0 (int) – Start pixel index along the y-dimension.

  • x1 (int) – End pixel index along the x-dimension.

  • y1 (int) – End pixel index along the y-dimension.

  • plane_id (int) – Anode plane index used for bounds checking against detector.TPC_BORDERS.

  • tot_pixels (numpy.ndarray) – 1-D integer array (pre-allocated, length ≥ expected number of active pixels, initialised to -1) that will be populated in-place with the unique pixel IDs (as returned by pixel2id()) of each intercepted pixel.

larndsim.pixels_from_track.get_neighboring_pixels(active_pixels, neighboring_pixels, neighboring_radius)[source]

Expand a set of active pixels by including all other pixels within detector.MAX_RADIUS pixels, then record the results in-place.

For every pixel in active_pixels the function iterates over the square neighbourhood of half-width detector.MAX_RADIUS and adds each in-bounds, not-yet-seen pixel to neighboring_pixels together with its Euclidean distance to the active pixel. Duplicate entries are suppressed by a linear search over already-added pixels.

This is a CUDA device function and must be called from another kernel or device function.

Parameters:
  • active_pixels (numpy.ndarray) – 1-D integer array of unique pixel IDs (as from pixel2id()) that lie directly below the projected track segment. Entries equal to -1 are treated as empty and skipped.

  • neighboring_pixels (numpy.ndarray) – 1-D integer array (pre-allocated, initialised to -1) that will be populated in-place with the unique pixel IDs of all active and neighbouring pixels.

  • neighboring_radius (numpy.ndarray) – 1-D float array of the same length as neighboring_pixels, populated in-place with the Euclidean distance (in pixel-pitch units) from the nearest active pixel to each entry in neighboring_pixels.

Returns:

Total number of valid pixel entries written into neighboring_pixels (i.e. the number of unique in-bounds pixels found).

Return type:

int