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:
- Returns:
Unique integer identifier for the pixel.
- Return type:
- 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().
- 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 fieldsx_start,x_end,y_start,y_end, andpixel_plane.n_max_pixels (
numpy.ndarray) – Single-element integer array used to accumulate the maximum pixel count viacuda.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:
Determines the start/end pixel coordinates from physical positions.
Calls
get_active_pixels()(Bresenham line) to find pixels directly under the projected track segment.Calls
get_neighboring_pixels()to expand the set by including pixels withindetector.MAX_RADIUSof each active pixel.
- Parameters:
tracks (
numpy.ndarray) – Structured array of track segments. Each element must contain the fieldsx_start,x_end,y_start,y_end, andpixel_plane.active_pixels (
numpy.ndarray) – 2-D integer array of shape(n_tracks, max_active_pixels)pre-filled with-1. On return, rowicontains the unique pixel IDs that lie directly below the projection of tracki.neighboring_pixels (
numpy.ndarray) – 2-D integer array of shape(n_tracks, max_neighboring_pixels)pre-filled with-1. On return, rowicontains the unique pixel IDs of both the active pixels and their neighbours for tracki.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 toneighboring_pixels[i, j].n_pixels_list (
numpy.ndarray) – 1-D integer array of lengthn_tracks. On return, elementicontains the total number of valid entries inneighboring_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:
- Returns:
Number of valid (in-bounds) pixels intercepted by the line from
(x0, y0)to(x1, y1)on the given plane.- Return type:
- larndsim.pixels_from_track.get_active_pixels(x0, y0, x1, y1, plane_id, tot_pixels)[source]¶
Fill
tot_pixelswith 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 bypixel2id()) 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_RADIUSpixels, then record the results in-place.For every pixel in
active_pixelsthe function iterates over the square neighbourhood of half-widthdetector.MAX_RADIUSand adds each in-bounds, not-yet-seen pixel toneighboring_pixelstogether 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 frompixel2id()) that lie directly below the projected track segment. Entries equal to-1are 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 asneighboring_pixels, populated in-place with the Euclidean distance (in pixel-pitch units) from the nearest active pixel to each entry inneighboring_pixels.
- Returns:
Total number of valid pixel entries written into
neighboring_pixels(i.e. the number of unique in-bounds pixels found).- Return type: