GPU accelerationο
SimBA ships CUDA/CuPy-accelerated implementations of many of its most compute-heavy routines β geometry, image, statistics, circular-statistics, time-series and SHAP operations. On a supported NVIDIA GPU these run the same analyses as their CPU counterparts, but orders of magnitude faster on large datasets.
This page is a single consolidated view of every GPU-accelerated module. Each block is also documented in its topical section (e.g. Geometry, Statistics); the canonical, cross-referenceable entries live there, so the listings here mirror them for a one-stop GPU reference.
Geometry (GPU)ο
- simba.data_processors.cuda.geometry.directionality_to_nonstatic_target(left_ear, right_ear, nose, target, verbose=False)[source]
GPU method to calculate if an animal is directing towards a moving point location given the target location and the left ear, right ear, and nose coordinates of the observer.
EXPECTED RUNTIMES
Observations Frames
Mean (s)
Std (s)
Min (s)
Max (s)
10,000
0.147
0.2064
0.0008
0.4389
100,000
0.0056
0.0005
0.0052
0.0063
1,000,000
0.0438
0.0235
0.0239
0.0768
10,000,000
0.2133
0.0046
0.2083
0.2195
50,000,000
1.5716
0.2608
1.2548
1.8936
NVIDIA GeForce RTX 4070
3 ITERATIONS
See also
Input left ear, right ear, and nose coordinates of the observer is returned by
simba.mixins.feature_extraction_mixin.FeatureExtractionMixin.check_directionality_viable()For non-GPU numba based CPU method, see
simba.mixins.feature_extraction_mixin.FeatureExtractionMixin.jitted_line_crosses_to_nonstatic_targets()If the target is static, consider
simba.mixins.feature_extraction_mixin.FeatureExtractionMixin.jitted_line_crosses_to_static_targets()orsimba.data_processors.cuda.geometry.directionality_to_static_targets()for GPU acceleration.- Parameters
left_ear (np.ndarray) β 2D array of size len(frames) x 2 with the coordinates of the observer animals left ear
right_ear (np.ndarray) β 2D array of size len(frames) x 2 with the coordinates of the observer animals right ear
nose (np.ndarray) β 2D array of size len(frames) x 2 with the coordinates of the observer animals nose
target (np.ndarray) β 1D array of with x,y of target location
- Returns
2D array of size len(frames) x 4. First column represent the side of the observer that the target is in view. 0 = Left side, 1 = Right side, 2 = Not in view. Second and third column represent the x and y location of the observer animals
eye(half-way between the ear and the nose). Fourth column represent if target is view (bool).- Return type
np.ndarray
- Example
>>> left_ear = np.random.randint(0, 500, (100, 2)) >>> right_ear = np.random.randint(0, 500, (100, 2)) >>> nose = np.random.randint(0, 500, (100, 2)) >>> target = np.random.randint(0, 500, (100, 2)) >>> directionality_to_nonstatic_target(left_ear=left_ear, right_ear=right_ear, nose=nose, target=target)
- simba.data_processors.cuda.geometry.directionality_to_static_targets(left_ear, right_ear, nose, target, verbose=False)[source]
GPU helper to calculate if an animal is directing towards a static location (e.g., ROI centroid), given the target location and the left ear, right ear, and nose coordinates of the observer.
Note
Input left ear, right ear, and nose coordinates of the observer is returned by
simba.mixins.feature_extraction_mixin.FeatureExtractionMixin.check_directionality_viable()See also
For numba based CPU method, see
simba.mixins.feature_extraction_mixin.FeatureExtractionMixin.jitted_line_crosses_to_static_targets()If the target is moving, considersimba.mixins.feature_extraction_mixin.FeatureExtractionMixin.jitted_line_crosses_to_nonstatic_targets().
EXPECTED RUNTIMES
FRAMES (MILLIONS)
GPU TIME (S)
GPU TIME (STEV)
10
0.1005
0.02
20
0.1918
0.04
40
0.4382
0.094
80
0.912
0.2904
160
2.8023
1.2692
240
5.7812
3.85148
NVIDIA GeForce RTX 4070
3 ITERATIONS
- Parameters
left_ear (np.ndarray) β 2D array of size len(frames) x 2 with the coordinates of the observer animals left ear
right_ear (np.ndarray) β 2D array of size len(frames) x 2 with the coordinates of the observer animals right ear
nose (np.ndarray) β 2D array of size len(frames) x 2 with the coordinates of the observer animals nose
target (np.ndarray) β 1D array of with x,y of target location
- Returns
2D array of size len(frames) x 4. First column represent the side of the observer that the target is in view. 0 = Left side, 1 = Right side, 2 = Not in view. Second and third column represent the x and y location of the observer animals
eye(half-way between the ear and the nose). Fourth column represent if target is view (bool).- Return type
np.ndarray
- Example
>>> left_ear = np.random.randint(0, 500, (100, 2)) >>> right_ear = np.random.randint(0, 500, (100, 2)) >>> nose = np.random.randint(0, 500, (100, 2)) >>> target = np.random.randint(0, 500, (2)) >>> directionality_to_static_targets(left_ear=left_ear, right_ear=right_ear, nose=nose, target=target)
- simba.data_processors.cuda.geometry.find_midpoints(x, y, percentile=0.5, batch_size=15000000)[source]
Calculate the midpoints between corresponding points in arrays x and y based on a given percentile using GPU acceleration.
For example, calculate the midpoint between the animal ears (to get presumed
nape) or lateral sides (to get presumed center of mass), or nose and left ear (to get left eye) etc.This function computes the midpoints between each pair of points (x[i], y[i]) from the input arrays x and y. The midpoint is calculated by taking a weighted sum of the differences along each axis, where the weight is determined by the specified percentile. The computation is performed in batches to handle large datasets efficiently.
See also
For CPU function see
simba.mixins.feature_extraction_mixin.FeatureExtractionMixin.find_midpoints().
EXPECTED RUNTIMES
OBSERVATIONS (MILLIONS)
TIME (S)
STD (S)
2
0.014
0.004
4
0.022
0.015
8
0.039
0.025
16
0.073
0.057
32
0.161
0.102
64
0.290
0.205
128
0.609
0.477
512
2.100
0.9
- Parameters
x (np.ndarray) β An array of shape (n, 2) representing the x-coordinates of n points.
y (np.ndarray) β An array of shape (n, 2) representing the y-coordinates of n points.
percentile β A float value between 0 and 1 indicating the percentile to use when calculating the midpoints. The default value is 0.5, which corresponds to the middle.
batch_size (Optional[int]) β An integer specifying the batch size for processing the input arrays. Larger batch sizes will use more memory but may be faster. The default value is 15 million (1.5e+7).
- Returns
An array of shape (n, 2) containing the calculated midpoints for each pair of corresponding points in x and y.
- Return type
np.ndarray
- Example
>>> x = np.random.randint(0, 100, (100, 2)).astype(np.int8) >>> y = np.random.randint(0, 100, (100, 2)).astype(np.int8) >>> p = find_midpoints(x=x, y=y)
- simba.data_processors.cuda.geometry.get_convex_hull(pts)[source]
Compute the convex hull for each set of 2D points in parallel using CUDA and the Jarvis March algorithm. This function processes a batch of 2D point sets (frames) and computes the convex hull for each set. The convex hull of a set of points is the smallest convex polygon that contains all the points.
The function uses a variant of the Gift Wrapping algorithm (Jarvis March) to compute the convex hull. It finds the leftmost point, then iteratively determines the next point on the hull by checking the orientation of the remaining points. The results are stored in the results array, where each row corresponds to a frame and contains the indices of the points forming the convex hull. Points not on the hull are marked with -1.
EXPECTED RUNTIMES
FRAMES
TIME (S)
110k
0.009
181k
0.014
327k
0.026
620k
0.049
1.2m
0.095
2.4m
0.18
4.7m
0.351
9m
0.865
17.9m
1.452
35.8m
5.695
71.6m
7.243
NVIDIA GeForce RTX 4070
7 body-parts
Note
Implements the Jarvis March (gift-wrapping) convex-hull algorithm (Jarvis, R. A., 1973, Information Processing Letters 2(1): 18-21).
See also
- Parameters
pts β A 3D numpy array of shape (M, N, 2) where: - M is the number of frames. - N is the number of points (body-parts) in each frame. - The last dimension (2) represents the x and y coordinates of each point.
- Returns
An upated 3D numpy array of shape (M, N, 2) consisting of the points in the hull.
- Return type
np.ndarray
- Example
>>> video_path = r"/mnt/c/troubleshooting/mitra/project_folder/videos/501_MA142_Gi_CNO_0514.mp4" >>> data_path = r"/mnt/c/troubleshooting/mitra/project_folder/csv/outlier_corrected_movement_location/501_MA142_Gi_CNO_0514 - test.csv" >>> df = read_df(file_path=data_path, file_type='csv') >>> frame_data = df.values.reshape(len(df), -1, 2) >>> x = get_convex_hull(frame_data)
- simba.data_processors.cuda.geometry.hausdorff_distance_cuda(verts_a, verts_b, counts_a=None, counts_b=None)[source]
Compute the discrete Hausdorff distance between each pair of polygons (how much one shapeβs outline differs from the otherβs - larger means less similar), batched on the GPU.
Note
Matches shapely to sub-pixel accuracy (float round-off).
EXPECTED RUNTIMES
N PAIRS
INPUT
MEAN (S)
PAIRS/S
10k
tiny
0.0043
2.3m
100k
4mb
0.0159
6.3m
1m
0.3gb
0.1237
8.1m
10m
2.6gb
1.2261
8.2m
NVIDIA GeForce RTX 4070 (12GB)
16-vertex polygon pairs; mean of 3 runs; exact vs shapely; ~88x vs shapely loop
input arrays are the memory constraint (~30-40M in-VRAM ceiling; larger spills to paging)
See also
CPU (shapely) version:
simba.mixins.geometry_mixin.GeometryMixin.hausdorff_distance().- Parameters
verts_a (np.ndarray) β (n_pairs, max_verts, 2) vertices of the first polygon in each pair.
verts_b (np.ndarray) β (n_pairs, max_verts, 2) vertices of the second polygon in each pair.
counts_a (Optional[np.ndarray]) β Only for ragged input - a (n_pairs,) array of the valid vertex count per first polygon when polygons of different vertex counts are packed into
max_vertsby padding. LeaveNone(default) to use allmax_vertsvertices.counts_b (Optional[np.ndarray]) β As
counts_a, for the second polygon. DefaultNone.
- Returns
(n_pairs,) float32 discrete Hausdorff distance per pair.
- Return type
np.ndarray
- Example
>>> d = hausdorff_distance_cuda(verts_a, verts_b) # equal-sized polygons >>> d = hausdorff_distance_cuda(verts_a, verts_b, counts_a=ca, counts_b=cb) # ragged (padded) polygons
- simba.data_processors.cuda.geometry.is_inside_circle(x, y, r)[source]
Determines whether points in array x are inside the circle with center
yand radiusr
EXPECTED RUNTIMES
FRAMES (MILLIONS)
CUDA JIT GPU (S)
2
0.006
4
0.007
8
0.016
16
0.028
32
0.054
64
0.114
128
0.319
256
0.44
512
1.085
1000
2.966
- Parameters
x (np.ndarray) β 2d numeric np.ndarray size (N, 2).
y (np.ndarray) β 2d numeric np.ndarray size (1, 2) representing the center of the circle.
r (float) β The radius of the circle.
- Returns
2d numeric boolean (N, 1) with 1s representing the point being inside the circle and 0 if the point is outside the rectangle.
- Return type
1d np.ndarray vector.
- simba.data_processors.cuda.geometry.is_inside_polygon(x, y)[source]
Determines whether points in array x are inside the polygon defined by the vertices in array y.
This function uses GPU acceleration to perform the point-in-polygon test. The points in x are tested against the polygon defined by the vertices in y. The result is an array where each element indicates whether the corresponding point is inside the polygon.
EXPECTED RUNTIMES
FRAMES (MILLIONS)
CUDA JIT GPU (S)
NUMBA CPU TIME (S)
2
0.002
0.038
4
0.004
0.082
8
0.006
0.170
16
0.009
0.295
32
0.021
0.823
64
0.041
1.395
128
0.101
2.688
256
0.369
4.640
512
0.614
10.940
1000
1.293
19.947
See also
For jitted CPU function see
framewise_inside_polygon_roi()- Parameters
x (np.ndarray) β An array of shape (N, 2) where each row represents a point in 2D space. The points are checked against the polygon.
y (np.ndarray) β An array of shape (M, 2) where each row represents a vertex of the polygon in 2D space.
- Returns
An array of shape (N,) where each element is 1 if the corresponding point in x is inside the polygon defined by y, and 0 otherwise.
- Return type
np.ndarray
- Example
>>> x = np.random.randint(0, 200, (i, 2)).astype(np.int8) >>> y = np.random.randint(0, 200, (4, 2)).astype(np.int8) >>> results = is_inside_polygon(x=x, y=y) >>> print(results) >>> [1 0 1 0 1 1 0 0 1 0]
- simba.data_processors.cuda.geometry.is_inside_rectangle(x, y)[source]
Determines whether points in array x are inside the rectangle defined by the top left and bottom right vertices in array y. π
EXPECTED RUNTIMES
FRAMES (MILLIONS)
CUDA JIT GPU (S)
NUMBA CPU TIME (S)
2
0.005
0.022
4
0.009
0.031
8
0.016
0.097
16
0.028
0.199
32
0.054
0.399
64
0.111
0.769
128
0.33
1.300
256
0.666
2.531
512
1.161
7.273
1000
3.828
13.342
See also
For numba CPU function see
framewise_inside_rectangle_roi()- Parameters
x (np.ndarray) β 2d numeric np.ndarray size (N, 2).
y (np.ndarray) β 2d numeric np.ndarray size (2, 2) (top left[x, y], bottom right[x, y])
- Returns
2d numeric boolean (N, 1) with 1s representing the point being inside the rectangle and 0 if the point is outside the rectangle.
- Return type
np.ndarray
- simba.data_processors.cuda.geometry.minimum_rotated_rectangle_cuda(data)[source]
Compute the minimum rotated rectangle (oriented bounding box, OBB) of each point set in a batch, on the GPU.
EXPECTED RUNTIMES
N SHAPES
MEAN (S)
SD (S)
SHAPES/S
1k
0.0012
0.0001
838k
10k
0.0016
0.0002
6.3m
100k
0.0090
0.0003
11.1m
1m
0.0814
0.0011
12.3m
NVIDIA GeForce RTX 4070
9 body-parts (K=9)
end-to-end (incl. host<->device); mean +/- SD of 3 runs
- Parameters
data (np.ndarray) β 3D array
(n_shapes, n_points, 2)of 2D (x, y) points.n_shapesis the number of shapes (usually video frames) andn_pointsthe number of points per shape (usually body-parts); i.e. a pose dataframe reshaped to(len(df), n_bodyparts, 2). Alln_pointspoints are used for every shape - one rectangle is computed per shape (per frame).- Returns
(n_shapes, 4, 2)int32 array of the four OBB corner (x, y) coordinates per shape, rounded to whole pixels (matching the CPUminimum_rotated_rectangle(..., return_type='array')).- Return type
np.ndarray
- Example
>>> df = read_df(file_path='.../Box1.csv') >>> bp_cols = [x for x in df.columns if not x.endswith('_p')] >>> data = df[bp_cols].values.reshape(len(df), len(bp_cols) // 2, 2) # (n_frames, n_bodyparts, 2) >>> rects = minimum_rotated_rectangle_cuda(data=data) # (n_frames, 4, 2) int32
See also
For the CPU counterpart, see
simba.mixins.geometry_mixin.GeometryMixin.minimum_rotated_rectangle().
- simba.data_processors.cuda.geometry.poly_area(data, pixels_per_mm=1.0, batch_size=5000000)[source]
Compute the area of a polygon using GPU acceleration.
This function calculates the area of polygons defined by sets of points in a 3D array. Each 2D slice along the first dimension represents a polygon, with each row corresponding to a point in the polygon and each column representing the x and y coordinates.
The computation is done in batches to handle large datasets efficiently.
See also
- Parameters
data β A 3D numpy array of shape (N, M, 2), where N is the number of polygons, M is the number of points per polygon, and 2 represents the x and y coordinates.
pixels_per_mm β Optional scaling factor to convert the area from pixels squared to square millimeters. Default is 1.0.
batch_size β Optional batch size for processing the data in chunks to fit in memory. Default is 0.5e+7.
- Returns
A 1D numpy array of shape (N,) containing the computed area of each polygon in square millimeters.
- Return type
np.ndarray
- simba.data_processors.cuda.geometry.shape_distance_cuda(verts_a, verts_b, counts_a=None, counts_b=None, pixels_per_mm=1.0, unit='mm')[source]
Compute the minimum distance between the boundaries of each pair of polygons (0 if the shapes overlap or touch), batched on the GPU.
Note
Matches shapely to sub-pixel accuracy (limited by integer-vertex rounding of the input).
EXPECTED RUNTIMES
N PAIRS
INPUT
MEAN (S)
SD (S)
PAIRS/S
10k
tiny
0.0012
0.0001
8.6m
100k
4mb
0.0060
0.0004
16.7m
1m
0.2gb
0.0520
0.0003
19.2m
10m
1.6gb
0.5440
0.0068
18.4m
50m
8gb
3.2388
0.6321
15.4m
NVIDIA GeForce RTX 4070 (12GB)
6-vertex polygon pairs; mean +/- SD of 3 runs
50m~8GB input is the in-VRAM ceiling (100m spills to paging)
See also
CPU (shapely) version:
simba.mixins.geometry_mixin.GeometryMixin.shape_distance().- Parameters
verts_a (np.ndarray) β (n_pairs, max_verts, 2) vertices of the first polygon in each pair.
verts_b (np.ndarray) β (n_pairs, max_verts, 2) vertices of the second polygon in each pair.
counts_a (Optional[np.ndarray]) β Only for ragged input - a (n_pairs,) array of the valid vertex count per first polygon when polygons of different vertex counts are packed into
max_vertsby padding. LeaveNone(default) to use allmax_vertsvertices.counts_b (Optional[np.ndarray]) β As
counts_a, for the second polygon. DefaultNone.pixels_per_mm (float) β Pixel-to-mm conversion. Default 1.0.
unit (str) β One of βmmβ, βcmβ, βdmβ, βmβ. Default βmmβ.
- Returns
(n_pairs,) float32 distances in
unit(0 where shapes overlap/touch).- Return type
np.ndarray
- Example
>>> d = shape_distance_cuda(verts_a, verts_b, pixels_per_mm=1.0) # equal-sized polygons >>> d = shape_distance_cuda(verts_a, verts_b, counts_a=ca, counts_b=cb) # ragged (padded) polygons
Image (GPU)ο
- simba.data_processors.cuda.image.bg_subtraction_cuda(video_path, avg_frm, save_path=None, bg_clr=(0, 0, 0), fg_clr=None, batch_size=500, threshold=50)[source]
Remove background from videos using GPU acceleration.
Note
To create an avg_frm, use
simba.video_processors.video_processing.create_average_frm(),simba.data_processors.cuda.image.create_average_frm_cupy(), orcreate_average_frm_cuda()See also
For CPU-based alternative, see
simba.video_processors.video_processing.video_bg_subtraction()orvideo_bg_subtraction_mp()For GPU-based alternative, seebg_subtraction_cupy(). Needs work, CPU/multicore appears faster.See also
To create average frame on the CPU, see
simba.video_processors.video_processing.create_average_frm(). CPU/multicore appears faster.EXPECTED RUNTIMES
FRAMES
GPU TIME (S)
GPU TIME (STEV)
450
2.76
0.18
900
5.45
0.208
1800
10.36
0.183
3600
20.527
0.886
7200
42.79
0.327
14400
82.95
3.69
28800
160.38
5.186
NVIDIA GeForce RTX 4070
video, RGB 620x530:
3 ITERATIONS
- Parameters
video_path (Union[str, os.PathLike]) β The path to the video to remove the background from.
avg_frm (np.ndarray) β Average frame of the video. Can be created with e.g.,
simba.video_processors.video_processing.create_average_frm().save_path (Optional[Union[str, os.PathLike]]) β Optional location to store the background removed video. If None, then saved in the same directory as the input video with the _bg_removed suffix.
bg_clr (Optional[Tuple[int, int, int]]) β Tuple representing the background color of the video.
fg_clr (Optional[Tuple[int, int, int]]) β Tuple representing the foreground color of the video (e.g., the animal). If None, then the original pixel colors will be used. Default: 50.
batch_size (Optional[int]) β Number of frames to process concurrently. Use higher values of RAM memory allows. Default: 500.
threshold (Optional[int]) β Value between 0-255 representing the difference threshold between the average frame subtracted from each frame. Higher values and more pixels will be considered background. Default: 50.
- Example
>>> video_path = "/mnt/c/troubleshooting/mitra/project_folder/videos/clipped/592_MA147_Gq_CNO_0515.mp4" >>> avg_frm = create_average_frm(video_path=video_path) >>> bg_subtraction_cuda(video_path=video_path, avg_frm=avg_frm, fg_clr=(255, 255, 255))
- simba.data_processors.cuda.image.bg_subtraction_cupy(video_path, avg_frm, save_path=None, bg_clr=(0, 0, 0), fg_clr=None, batch_size=500, threshold=50, verbose=True, async_frame_read=True)[source]
Remove background from videos using GPU acceleration through CuPY.
See also
For CPU-based alternative, see
simba.video_processors.video_processing.video_bg_subtraction()orvideo_bg_subtraction_mp()For GPU-based alternative, seebg_subtraction_cuda(). Needs work, CPU/multicore appears faster.- Parameters
video_path (Union[str, os.PathLike]) β The path to the video to remove the background from.
avg_frm (np.ndarray) β Average frame of the video. Can be created with e.g.,
simba.video_processors.video_processing.create_average_frm().save_path (Optional[Union[str, os.PathLike]]) β Optional location to store the background removed video. If None, then saved in the same directory as the input video with the _bg_removed suffix.
bg_clr (Optional[Tuple[int, int, int]]) β Tuple representing the background color of the video.
fg_clr (Optional[Tuple[int, int, int]]) β Tuple representing the foreground color of the video (e.g., the animal). If None, then the original pixel colors will be used. Default: 50.
batch_size (Optional[int]) β Number of frames to process concurrently. Use higher values of RAM memory allows. Default: 500.
threshold (Optional[int]) β Value between 0-255 representing the difference threshold between the average frame subtracted from each frame. Higher values and more pixels will be considered background. Default: 50.
- Example
>>> avg_frm = create_average_frm(video_path="/mnt/c/troubleshooting/mitra/project_folder/videos/temp/temp_ex_bg_subtraction/original/844_MA131_gq_CNO_0624.mp4") >>> video_path = "/mnt/c/troubleshooting/mitra/project_folder/videos/temp/temp_ex_bg_subtraction/844_MA131_gq_CNO_0624_7.mp4" >>> bg_subtraction_cupy(video_path=video_path, avg_frm=avg_frm, batch_size=500)
- simba.data_processors.cuda.image.create_average_frm_cuda(video_path, start_frm=None, end_frm=None, start_time=None, end_time=None, save_path=None, batch_size=6000, verbose=False, async_frame_read=False)[source]
Computes the average frame using GPU acceleration from a specified range of frames or time interval in a video file. This average frame typically used for background substraction.
The function reads frames from the video, calculates their average, and optionally saves the result to a specified file. If save_path is provided, the average frame is saved as an image file; otherwise, the average frame is returned as a NumPy array.
See also
For CuPy function see
create_average_frm_cupy(). For CPU function seecreate_average_frm().- Parameters
video_path (Union[str, os.PathLike]) β The path to the video file from which to extract frames.
start_frm (Optional[int]) β The starting frame number (inclusive). Either start_frm/end_frm or start_time/end_time must be provided, but not both.
end_frm (Optional[int]) β The ending frame number (exclusive).
start_time (Optional[str]) β The start time in the format βHH:MM:SSβ from which to begin extracting frames.
end_time (Optional[str]) β The end time in the format βHH:MM:SSβ up to which frames should be extracted.
save_path (Optional[Union[str, os.PathLike]]) β The path where the average frame image will be saved. If None, the average frame is returned as a NumPy array.
batch_size (Optional[int]) β The number of frames to process in each batch. Default is 3000. Increase if your RAM allows it.
verbose (Optional[bool]) β If True, prints progress and informational messages during execution.
- Returns
Returns None if the result is saved to save_path. Otherwise, returns the average frame as a NumPy array.
- Example
>>> create_average_frm_cuda(video_path=r"C:/troubleshooting/RAT_NOR/project_folder/videos/2022-06-20_NOB_DOT_4_downsampled.mp4", verbose=True, start_frm=0, end_frm=9000)
- simba.data_processors.cuda.image.create_average_frm_cupy(video_path, start_frm=None, end_frm=None, start_time=None, end_time=None, save_path=None, batch_size=3000, verbose=False, async_frame_read=False)[source]
Computes the average frame using GPU acceleration from a specified range of frames or time interval in a video file. This average frame is typically used for background subtraction.
The function reads frames from the video, calculates their average, and optionally saves the result to a specified file. If save_path is provided, the average frame is saved as an image file; otherwise, the average frame is returned as a NumPy array.
See also
For CPU function see
create_average_frm(). For CUDA function seecreate_average_frm_cuda()EXPECTED RUNTIMES
OBSERVATIONS (THOUSANDS)
TIME (S)
STDEV (S)
1
2.323333333
0.032145503
2
3.486666667
0.205993527
3
4.71
0.02
4
6.03
0.346987031
5
7.566666667
0.159478316
6
8.943333333
0.210792157
7
10.26666667
0.494098506
NVIDIA GeForce RTX 4070
REPEATS = 3
BATCH SIZE: 500.
RESOLUTION: 600 x 400
ASYNC FRAME READ: TRUE
- Parameters
video_path (Union[str, os.PathLike]) β The path to the video file from which to extract frames.
start_frm (Optional[int]) β The starting frame number (inclusive). Either start_frm/end_frm or start_time/end_time must be provided, but not both. If both start_frm and end_frm are None, processes all frames in the video.
end_frm (Optional[int]) β The ending frame number (exclusive). Either start_frm/end_frm or start_time/end_time must be provided, but not both.
start_time (Optional[str]) β The start time in the format βHH:MM:SSβ from which to begin extracting frames. Either start_frm/end_frm or start_time/end_time must be provided, but not both.
end_time (Optional[str]) β The end time in the format βHH:MM:SSβ up to which frames should be extracted. Either start_frm/end_frm or start_time/end_time must be provided, but not both.
save_path (Optional[Union[str, os.PathLike]]) β The path where the average frame image will be saved. If None, the average frame is returned as a NumPy array.
batch_size (Optional[int]) β The number of frames to process in each batch. Default is 3000. Increase if your RAM allows it.
verbose (Optional[bool]) β If True, prints progress and informational messages during execution. Default: False.
async_frame_read (bool) β If True, uses asynchronous frame reading for improved performance. Default: False.
- Returns
Returns None if the result is saved to save_path. Otherwise, returns the average frame as a NumPy array.
- Example
>>> create_average_frm_cupy(video_path=r"C:/troubleshooting/RAT_NOR/project_folder/videos/2022-06-20_NOB_DOT_4_downsampled.mp4", verbose=True, start_frm=0, end_frm=9000) >>> create_average_frm_cupy(video_path=r"C:/videos/my_video.mp4", start_time="00:00:00", end_time="00:01:00", async_frame_read=True, save_path=r"C:/output/avg_frame.png")
- simba.data_processors.cuda.image.cross_correlation_matrix_cuda(imgs)[source]
Compute the normalized cross-correlation (NCC, in [-1, 1]) between every pair of images in a stack, on the GPU.
Note
Matches the CPU function to ~1e-6, and (unlike the CPU version, which is uint8-only) accepts any numeric dtype. Output is a dense (n_images, n_images) float32 matrix, so memory scales with n^2 (independent of image size); large image counts are bounded by GPU memory.
EXPECTED RUNTIMES
N IMAGES (128x128)
OUTPUT
MEAN (S)
SD (S)
PAIRS/S
100
40kb
0.0060
0.0001
1.7m
500
1mb
0.0500
0.0161
5.0m
1k
4mb
0.1143
0.0021
8.8m
2k
16mb
0.3673
0.0004
10.9m
5k
100mb
2.1043
0.0134
11.9m
10k
0.4gb
8.0947
0.0588
12.4m
20k
1.6gb
31.8439
0.2454
12.6m
NVIDIA GeForce RTX 4070 (12GB)
128x128 greyscale; mean +/- SD of 3 runs
compute-bound O(n^2 * pixels): time grows n^2 (memory allows ~50k but 20k already ~32s)
See also
CPU (numba) version:
simba.mixins.image_mixin.ImageMixin.cross_correlation_matrix().- Parameters
imgs (np.ndarray) β 3D array (n_images, H, W) - greyscale image stack.
- Returns
(n, n) float32 cross-correlation matrix; [i, j] is the NCC between image i and image j.
- Return type
np.ndarray
- Example
>>> m = cross_correlation_matrix_cuda(imgs) # imgs: (n, H, W) greyscale
- simba.data_processors.cuda.image.img_matrix_mse_cuda(imgs)[source]
Compute the pairwise mean-squared-error (MSE) between every pair of images in a stack, on the GPU.
Note
Matches the CPU function, including its cast to int32 (the MSE is truncated to a whole number). The op count is O(n^2 * pixels) so runtime grows with n^2 (compute-bound); the output is a dense (n_images, n_images) matrix so memory also scales with n^2.
EXPECTED RUNTIMES
N IMAGES (128x128)
OUTPUT
MEAN (S)
SD (S)
PAIRS/S
100
40kb
0.0052
0.0001
1.9m
500
1mb
0.0345
0.0018
7.3m
1k
4mb
0.1107
0.0022
9.0m
2k
16mb
0.3489
0.0030
11.5m
5k
100mb
2.0593
0.0073
12.1m
10k
0.4gb
8.0415
0.0936
12.4m
20k
1.6gb
31.6372
0.1203
12.6m
NVIDIA GeForce RTX 4070 (12GB)
128x128 greyscale; mean +/- SD of 3 runs; ~15x vs CPU jit
compute-bound O(n^2 * pixels): time grows n^2 (memory allows more but 20k already ~32s)
See also
CPU (numba) version:
simba.mixins.image_mixin.ImageMixin.img_matrix_mse().- Parameters
imgs (np.ndarray) β 3D array (n_images, H, W) - stack of same-shaped images.
- Returns
(n, n) int32 MSE matrix; [i, j] is the MSE between image i and image j.
- Return type
np.ndarray
- Example
>>> m = img_matrix_mse_cuda(imgs) # imgs: (n, H, W)
- simba.data_processors.cuda.image.img_stack_brightness(x, method='digital', ignore_black=True, verbose=False, batch_size=2500)[source]
Calculate the average brightness of a stack of images using a specified method.
Useful for analyzing light cues or brightness changes over time. For example, compute brightness in images containing a light cue ROI, then perform clustering (e.g., k-means) on brightness values to identify frames when the light cue is on vs off.
EXPECTED RUNTIMES
FRAME COUNT (K)
TIME (SECONDS)
STDEV (SECONDS)
1
0.76485
1.239735707
5
3.9256
10.04421855
7
9.445
11.46390422
RESOLUTON: 1200x600
3 RUNS
RTX 4090
Photometric Method: The brightness is calculated using the formula:
\[\text{brightness} = 0.2126 \cdot R + 0.7152 \cdot G + 0.0722 \cdot B\]Digital Method: The brightness is calculated using the formula:
\[\text{brightness} = 0.299 \cdot R + 0.587 \cdot G + 0.114 \cdot B\]See also
For CPU function see
brightness_intensity().- Parameters
x (np.ndarray) β A 4D array of images with dimensions (N, H, W, C), where N is the number of images, H and W are the height and width, and C is the number of channels (RGB).
method (Optional[Literal['photometric', 'digital']]) β The method to use for calculating brightness. It can be βphotometricβ for the standard luminance calculation or βdigitalβ for an alternative set of coefficients. Default is βdigitalβ.
ignore_black (Optional[bool]) β If True, black pixels (i.e., pixels with brightness value 0) will be ignored in the calculation of the average brightness. Default is True.
- Return np.ndarray
A 1D array of average brightness values for each image in the stack. If ignore_black is True, black pixels are ignored in the averaging process.
- Example
>>> imgs = read_img_batch_from_video_gpu(video_path=r"/mnt/c/troubleshooting/RAT_NOR/project_folder/videos/2022-06-20_NOB_DOT_4_downsampled.mp4", start_frm=0, end_frm=5000) >>> imgs = np.stack(list(imgs.values()), axis=0) >>> x = img_stack_brightness(x=imgs)
- simba.data_processors.cuda.image.img_stack_to_bw(imgs, lower_thresh=100, upper_thresh=100, invert=True, batch_size=1000)[source]
Converts a stack of RGB images to binary (black and white) images based on given threshold values using GPU acceleration.
This function processes a 4D stack of images, converting each RGB image to a binary image using specified lower and upper threshold values. The conversion can be inverted if desired, and the processing is done in batches for efficiency.
EXPECTED RUNTIMES
FRAMES (K)
TIME (S)
1
0.280
2
0.260
4
0.600
8
1.100
See also
simba.mixins.image_mixin.ImageMixin.img_to_bw()simba.mixins.image_mixin.ImageMixin.img_stack_to_bw()- Parameters
imgs (np.ndarray) β A 4D NumPy array representing a stack of RGB images, with shape (N, H, W, C).
lower_thresh (Optional[int]) β The lower threshold value. Pixel values below this threshold are set to 0 (or 1 if invert is True). Default is 100.
upper_thresh (Optional[int]) β The upper threshold value. Pixel values above this threshold are set to 1 (or 0 if invert is True). Default is 100.
invert (Optional[bool]) β If True, the binary conversion is inverted, meaning that values below lower_thresh become 1, and values above upper_thresh become 0. Default is True.
batch_size (Optional[int]) β The number of images to process in a single batch. This helps manage memory usage for large stacks of images. Default is 1000.
- Returns
A 3D NumPy array of shape (N, H, W), where each image has been converted to a binary format with pixel values of either 0 or 1.
- Return type
np.ndarray
- simba.data_processors.cuda.image.img_stack_to_grayscale_cuda(x)[source]
Convert image stack to grayscale using CUDA.
See also
For CPU function single images
img_to_greyscale()andimg_stack_to_greyscale()for stack. For CuPy, seeimg_stack_to_grayscale_cupy().EXPECTED RUNTIMES
FRAMES (k)
GPU (s)
STDEV (s)
1
0.16022
0.125786
2
0.14428
0.003726
3
0.19769
0.005645
4
0.2571
0.006002
5
0.33574
0.017868
6
0.39921
0.026858
7
0.45734
0.0333
8
0.53216
0.015075
9
0.50257
0.023186
10
0.54235
0.090055
11
0.69896
0.00999
12
0.57932
0.0010399
13
0.63791
0.017
14
0.99677
0.1073426
15
1.56103
0.5308574
16
1.08143
0.082
17
1.39189
0.3308389
18
1.23648
0.1386822
19
1.39554
0.161
20
1.962
0.576
NVIDIA GeForce RTX 4070
REPEATS= 3
- Parameters
x (np.ndarray) β 4d array of color images in numpy format.
- Return np.ndarray
3D array of greyscaled images.
- Example
>>> imgs = read_img_batch_from_video_gpu(video_path=r"/mnt/c/troubleshooting/mitra/project_folder/videos/temp_2/592_MA147_Gq_Saline_0516_downsampled.mp4", verbose=False, start_frm=0, end_frm=i) >>> imgs = np.stack(list(imgs.values()), axis=0).astype(np.uint8) >>> grey_images = img_stack_to_grayscale_cuda(x=imgs)
- simba.data_processors.cuda.image.img_stack_to_grayscale_cupy(imgs, batch_size=250)[source]
Converts a stack of color images to grayscale using GPU acceleration with CuPy.
See also
For CPU function single images
img_to_greyscale()andimg_stack_to_greyscale()for stack. For CUDA JIT, seeimg_stack_to_grayscale_cuda().EXPECTED RUNTIMES
FRAMES (THOUSANDS)
GPU (s)
0.5
0.3419
1
0.52333
1.5
0.81614
2
1.0632
2.5
1.32399
3
1.61488
3.5
1.87857
4
2.30137
4.5
2.54736
5
2.90824
5.5
3.09271
- Parameters
imgs (np.ndarray) β A 4D NumPy or CuPy array representing a stack of images with shape (num_images, height, width, channels). The images are expected to have 3 channels (RGB).
batch_size (Optional[int]) β The number of images to process in each batch. Defaults to 250. Adjust this parameter to fit your GPUβs memory capacity.
- Return np.ndarray
m A 3D NumPy or CuPy array of shape (num_images, height, width) containing the grayscale images. If the input array is not 4D, the function returns the input as is.
- Example
>>> imgs = read_img_batch_from_video_gpu(video_path=r"/mnt/c/troubleshooting/RAT_NOR/project_folder/videos/2022-06-20_NOB_IOT_1_cropped.mp4", verbose=False, start_frm=0, end_frm=i) >>> imgs = np.stack(list(imgs.values()), axis=0).astype(np.uint8) >>> gray_imgs = img_stack_to_grayscale_cupy(imgs=imgs)
- simba.data_processors.cuda.image.pose_plotter(data, video_path, save_path, circle_size=None, colors='Set1', batch_size=750, verbose=True)[source]
Creates a video overlaying pose-estimation data on frames from a given video using GPU acceleration.
See also
For a faster, fully on-GPU version (NVDEC decode + NVENC encode), see
simba.data_processors.cuda.pose_plotter_nvenc.PosePlotterNVENC. For CPU based methods, seePathPlotterSingleCore()andPathPlotterMulticore().EXPECTED RUNTIMES
FRAMES (K)
TIME (S)
4
17
6
27
10
36
18
63
26
93
NVIDIA GeForce RTX 4070
7 body-parts
FRAME SIZE (WxH): 726x538
BATCH SIZE: 1000 images
- Parameters
data (Union[str, os.PathLike, np.ndarray]) β Path to a CSV file with pose-estimation data or a 3d numpy array (n_images, n_bodyparts, 2) with pose-estimated locations.
video_path (Union[str, os.PathLike]) β Path to a video file where the
datahas been pose-estimated.save_path (Union[str, os.PathLike]) β Location where to store the output visualization.
circle_size (Optional[int]) β The size of the circles representing the location of the pose-estimated locations. If None, the optimal size will be inferred as a 100th of the max(resultion_w, h).
batch_size (int) β The number of frames to process concurrently on the GPU. Default: 750. Increase of host and device RAM allows it to improve runtime. Decrease if you hit memory errors.
- Example
>>> DATA_PATH = "/mnt/c/troubleshooting/mitra/project_folder/csv/outlier_corrected_movement_location/501_MA142_Gi_CNO_0521.csv" >>> VIDEO_PATH = "/mnt/c/troubleshooting/mitra/project_folder/videos/501_MA142_Gi_CNO_0521.mp4" >>> SAVE_PATH = "/mnt/c/troubleshooting/mitra/project_folder/frames/output/pose_ex/test.mp4" >>> pose_plotter(data=DATA_PATH, video_path=VIDEO_PATH, save_path=SAVE_PATH, circle_size=10, batch_size=1000)
- simba.data_processors.cuda.image.rotate_img_stack_cupy(imgs, rotation_degrees=180, batch_size=500, verbose=True)[source]
Rotates a stack of images by a specified number of degrees using GPU acceleration with CuPy.
Accepts a 3D (single-channel images) or 4D (multichannel images) NumPy array, rotates each image in the stack by the specified degree around the center, and returns the result as a NumPy array.
- Parameters
imgs (np.ndarray) β The input stack of images to be rotated. Expected to be a NumPy array with 3 or 4 dimensions. 3D shape: (num_images, height, width) - 4D shape: (num_images, height, width, channels)
rotation_degrees (Optional[float]) β The angle by which the images should be rotated, in degrees. Must be between 1 and 359 degrees. Defaults to 180 degrees.
batch_size (Optional[int]) β Number of images to process on GPU in each batch. Decrease if data canβt fit on GPU RAM.
- Returns
A NumPy array containing the rotated images with the same shape as the input.
- Return type
np.ndarray
- Example
>>> video_path = r"/mnt/c/troubleshooting/mitra/project_folder/videos/F0_gq_Saline_0626_clipped.mp4" >>> imgs = read_img_batch_from_video_gpu(video_path=video_path) >>> imgs = np.stack(np.array(list(imgs.values())), axis=0) >>> imgs = rotate_img_stack_cupy(imgs=imgs, rotation=50)
- simba.data_processors.cuda.image.rotate_video_cupy(video_path, save_path=None, rotation_degrees=180, batch_size=None, verbose=True)[source]
Rotates a video by a specified angle using GPU acceleration and CuPy for image processing.
- Parameters
video_path (Union[str, os.PathLike]) β Path to the input video file.
save_path (Optional[Union[str, os.PathLike]]) β Path to save the rotated video. If None, saves the video in the same directory as the input with β_rotated_<rotation_degrees>β appended to the filename.
rotation_degrees (nptional[float]) β Degrees to rotate the video. Must be between 1 and 359 degrees. Default is 180.
batch_size (Optional[int]) β The number of frames to process in each batch. Deafults to None meaning all images will be processed in a single batch.
- Returns
None.
- Example
>>> video_path = r"/mnt/c/troubleshooting/mitra/project_folder/videos/F0_gq_Saline_0626_clipped.mp4" >>> rotate_video_cupy(video_path=video_path, rotation_degrees=45)
- simba.data_processors.cuda.image.segment_img_stack_horizontal(imgs, pct, upper=False, lower=False)[source]
Segment a stack of images horizontally based on a given percentage using GPU acceleration. For example, return the top half, bottom half, or center half of each image in the stack.
Note
If both top and bottom are true, the center portion is returned.
- Parameters
imgs (np.ndarray) β A 3D or 4D NumPy array representing a stack of images. The array should have shape (N, H, W) for grayscale images or (N, H, W, C) for color images.
pct (float) β The percentage of the image width to be used for segmentation. This value should be between a small positive value (e.g., 10e-6) and 0.99.
upper (bool) β If True, the top part of the image stack will be segmented.
lower (bool) β If True, the bottom part of the image stack will be segmented.
- Returns
A NumPy array containing the segmented images, with the same number of dimensions as the input.
- Return type
np.ndarray
- simba.data_processors.cuda.image.segment_img_stack_vertical(imgs, pct, left, right)[source]
Segment a stack of images vertically based on a given percentage using GPU acceleration. For example, return the left half, right half, or senter half of each image in the stack.
Note
If both left and right are true, the center portion is returned.
- Parameters
imgs (np.ndarray) β A 3D or 4D NumPy array representing a stack of images. The array should have shape (N, H, W) for grayscale images or (N, H, W, C) for color images.
pct (float) β The percentage of the image width to be used for segmentation. This value should be between a small positive value (e.g., 10e-6) and 0.99.
left (bool) β If True, the left side of the image stack will be segmented.
right (bool) β If True, the right side of the image stack will be segmented.
- Returns
A NumPy array containing the segmented images, with the same number of dimensions as the input.
- Return type
np.ndarray
- simba.data_processors.cuda.image.slice_imgs(video_path, shapes, batch_size=1000, verbose=True, save_dir=None)[source]
Slice frames from a video based on given polygon or circle coordinates, and return or save masked/cropped frame regions using GPU acceleration.
This function supports two types of shapes:
Polygon: array of shape (N, M, 2), where N = number of frames, M = number of polygon vertices.
Circle: array of shape (N, 3), where each row represents [center_x, center_y, radius].
- Parameters
video_path (Union[str, os.PathLike]) β Path to the input video file.
shapes (np.ndarray) β Array of polygon coordinates or circle parameters for each frame. - Polygon: shape = (n_frames, n_vertices, 2) - Circle: shape = (n_frames, 3)
batch_size (int) β Number of frames to process per batch during GPU processing. Default 1000.
verbose (bool) β Whether to print progress and status messages. Default True.
save_dir (Optional[Union[str, os.PathLike]]) β If provided, the masked/cropped video will be saved in this directory. Otherwise, the cropped image stack will be returned.
EXPECTED RUNTIMES
FRAMES N
TIME (S)
500
2.92
1000
2.134
2000
3.881
4000
7.358
8000
15.066
16000
35.156
32000
57.9812
IMG SIZE: 714 x 528
Note
For CPU multicore implementation, see
simba.mixins.image_mixin.ImageMixin.slice_shapes_in_imgs(). For single core process, seesimba.mixins.image_mixin.ImageMixin.slice_shapes_in_img()- Example I
Example 1: Mask video using circular regions derived from body part center positions >>> video_path = β/mnt/c/troubleshooting/RAT_NOR/project_folder/videos/03152021_NOB_IOT_8.mp4β >>> data_path = β/mnt/c/troubleshooting/RAT_NOR/project_folder/csv/outlier_corrected_movement_location/03152021_NOB_IOT_8.csvβ >>> save_dir = β/mnt/d/netholabs/yolo_videos/input/mp4_20250606083508β >>> nose_arr = read_df(file_path=data_path, file_type=βcsvβ, usecols=[βNose_xβ, βNose_yβ]).values.reshape(-1, 2).astype(np.int32) >>> polygons = GeometryMixin().multiframe_bodyparts_to_circle(data=nose_arr, parallel_offset=60) >>> polygon_lst = [] >>> center = GeometryMixin.get_center(polygons) >>> polygons = np.hstack([center, np.full(shape=(len(center), 1), fill_value=60)]) >>> slice_imgs(video_path=video_path, shapes=polygons, batch_size=500, save_dir=save_dir)
- Example II
Example 2: Mask video using minimum rotated rectangles from polygon hulls
>>> video_path = "/mnt/c/troubleshooting/RAT_NOR/project_folder/videos/03152021_NOB_IOT_8.mp4" >>> data_path = "/mnt/c/troubleshooting/RAT_NOR/project_folder/csv/outlier_corrected_movement_location/03152021_NOB_IOT_8.csv" >>> save_dir = '/mnt/d/netholabs/yolo_videos/input/mp4_20250606083508' >>> nose_arr = read_df(file_path=data_path, file_type='csv', usecols=['Nose_x', 'Nose_y', 'Tail_base_x', 'Tail_base_y', 'Lat_left_x', 'Lat_left_y', 'Lat_right_x', 'Lat_right_y']).values.reshape(-1, 4, 2).astype(np.int32) ## READ THE BODY-PART THAT DEFINES THE HULL AND CONVERT TO ARRAY >>> polygons = GeometryMixin().multiframe_bodyparts_to_polygon(data=nose_arr, parallel_offset=60) >>> polygons = GeometryMixin().multiframe_minimum_rotated_rectangle(shapes=polygons) >>> polygon_lst = [] >>> for i in polygons: >>> polygon_lst.append(np.array(i.exterior.coords).astype(np.int32)) >>> polygons = np.stack(polygon_lst, axis=0) >>> sliced_imgs = slice_imgs(video_path=video_path, shapes=polygons, batch_size=500, save_dir=save_dir)
- simba.data_processors.cuda.image.sliding_psnr(data, stride_s, sample_rate)[source]
Computes the Peak Signal-to-Noise Ratio (PSNR) between pairs of images in a stack using a sliding window approach.
This function calculates PSNR for each image in a stack compared to another image in the stack that is separated by a specified stride. The sliding window approach allows for the comparison of image quality over a sequence of images.
Note
PSNR values are measured in decibels (dB).
Higher PSNR values indicate better quality with minimal differences from the reference image.
Lower PSNR values indicate higher distortion or noise.
\[\text{PSNR} = 20 \log_{10} \left( \frac{\text{MAX}}{\sqrt{\text{MSE}}} \right)\]where: - \(\text{MAX}\) is the maximum possible pixel value (255 for 8-bit images) - \(\text{MSE}\) is the Mean Squared Error between the two images
- Parameters
data β A 4D NumPy array of shape (N, H, W, C) representing a stack of images, where N is the number of images, H is the height, W is the width, and C is the number of color channels.
stride_s β The base stride length in terms of the number of images between the images being compared. Determines the separation between images for comparison in the stack.
sample_rate β The sample rate to scale the stride length. This allows for adjusting the stride dynamically based on the sample rate.
- Returns
A 1D NumPy array of PSNR values, where each element represents the PSNR between the image at index r and the image at index l = r - stride, for all valid indices r.
- Return type
np.ndarray
- Example
>>> data = ImageMixin().read_img_batch_from_video(video_path =r"/mnt/c/troubleshooting/mitra/project_folder/videos/clipped/501_MA142_Gi_CNO_0514_clipped.mp4", start_frm=0, end_frm=299) >>> data = np.stack(list(data.values()), axis=0).astype(np.uint8) >>> data = ImageMixin.img_stack_to_greyscale(imgs=data) >>> p = sliding_psnr(data=data, stride_s=1, sample_rate=1)
- simba.data_processors.cuda.image.stack_sliding_mse(x, stride=1, batch_size=1000)[source]
Computes the Mean Squared Error (MSE) between each image in a stack and a reference image, where the reference image is determined by a sliding window approach with a specified stride. The function is optimized for large image stacks by processing them in batches.
See also
For CPU function see
img_stack_mse()andimg_sliding_mse().\[\text{MSE} = \frac{1}{n} \sum_{i=1}^{n} (y_i - \hat{y}_i)^2\]- Parameters
x (np.ndarray) β Input array of images, where the first dimension corresponds to the stack of images. The array should be either 3D (height, width, channels) or 4D (batch, height, width, channels).
stride (Optional[int]) β The stride or step size for the sliding window that determines the reference image. Defaults to 1, meaning the previous image in the stack is used as the reference.
batch_size (Optional[int]) β The number of images to process in a single batch. Larger batch sizes may improve performance but require more GPU memory. Defaults to 1000.
- Returns
A 1D NumPy array containing the MSE for each image in the stack compared to its corresponding reference image. The length of the array is equal to the number of images in the input stack.
- Return type
np.ndarray
- simba.data_processors.cuda.image.structural_similarity_matrix_cuda(imgs, data_range=255.0)[source]
Compute the windowed structural-similarity index (SSIM) between every pair of images in a stack, on the GPU.
Note
Matches skimageβs mean-SSIM exactly (7x7 window). Compute-bound - the op count is O(n^2 * pixels * 49) so runtime grows with n^2 and image size; the output is a dense (n_images, n_images) matrix so memory also scales with n^2.
EXPECTED RUNTIMES
N IMAGES (128x128)
OUTPUT
MEAN (S)
SD (S)
PAIRS/S
50
10kb
0.4511
0.010
5.5k
100
40kb
0.5689
0.012
17.6k
300
0.4mb
2.1454
0.030
42.0k
600
1.4mb
7.4050
0.090
48.6k
1k
4mb
24.496
3.429
40.8k
NVIDIA GeForce RTX 4070 (12GB)
128x128 greyscale; mean +/- SD of 3 runs; exact match to skimage
~6-13x vs CPU skimage (grows with n); compute-bound O(n^2 * pixels * 49)
See also
CPU (skimage) version:
simba.mixins.image_mixin.ImageMixin.structural_similarity_matrix().- Parameters
imgs (np.ndarray) β 3D array (n_images, H, W) - greyscale image stack (H, W >= 7).
data_range (float) β Value range of the images (255 for uint8; pass 1.0 for float images in [0, 1]). Sets C1=(0.01*range)^2, C2=(0.03*range)^2. Default 255.
- Returns
(n, n) float32 SSIM matrix; [i, j] is the mean SSIM between image i and image j.
- Return type
np.ndarray
- Example
>>> m = structural_similarity_matrix_cuda(imgs) # imgs: (n, H, W) greyscale uint8
Background subtraction (GPU)ο
- class simba.data_processors.cuda.bg_subtractor.BackgroundSubtractorCUDA(video_path, avg_frm, save_path=None, bg_clr=(0, 0, 0), fg_clr=None, batch_size=500, threshold=50, use_nvenc=None, codec='h264', queue_size=3, verbose=True)[source]
Bases:
objectRemove background from a video using GPU acceleration.
Uses a fully on-GPU pipeline when PyNvVideoCodec is available: frames are decoded on the NVDEC engine straight to device memory, background-subtracted by a CUDA kernel, and re-encoded on the NVENC engine - no host round-trips and no CPU video encoding. When PyNvVideoCodec is not installed, transparently falls back to an ffmpeg-decode + CUDA-kernel + cv2-encode pipeline whose three stages are overlapped across threads.
See also
Reference CPU implementation:
simba.video_processors.video_processing.video_bg_subtraction(). To create anavg_frm, seesimba.video_processors.video_processing.create_average_frm().Note
The NVENC back-end encodes H.264 (YUV420), so its output pixels are perceptually equivalent but not bit-identical to the CPU (mpeg4) back-end - both are lossy. The computed foreground/background classification is the same for both.
Expected runtimes by back-end (RTX 4070, 1280x1024, 1802 frames)ο BACK-END
TIME (S)
SPEEDUP
nvenc (NVDEC -> CUDA -> NVENC)
2.47
731
20x
cv2 fallback (ffmpeg + CUDA + cv2)
10.87
166
4.6x
original bg_subtraction_cuda
50.08
36
1x
NVENC back-end: FPS by image sizeο IMAGE SIZE
FPS
STDEV (FPS)
320x256
1799.3
105.4
640x512
1691.2
35.8
1280x1024
730.7
1.9
1920x1536
346.7
0.4
NVIDIA GeForce RTX 4070
NVENC h264; 1802 frames; 3 runs
Note
batch_sizedoes not affect the NVENC back-end, which decodes and encodes frame-by-frame - measured FPS at 1280x1024 is flat across batch sizes (1 -> 729, 100 -> 735, 500 -> 736).batch_sizeonly tunes the cv2 fallback.- Parameters
video_path (Union[str, os.PathLike]) β Path to the video to remove the background from.
avg_frm (np.ndarray) β Average frame of the video (BGR), e.g. from
create_average_frm().save_path (Optional[Union[str, os.PathLike]]) β Output path. If None, saved next to the input with a
_bg_removedsuffix.bg_clr (Optional[Tuple[int, int, int]]) β Background fill colour. Default (0, 0, 0).
fg_clr (Optional[Tuple[int, int, int]]) β Foreground colour. If None, original pixel colours are kept.
batch_size (Optional[int]) β Frames processed per batch on the fallback (cv2) back-end. Default 500.
threshold (Optional[int]) β Difference threshold (0-255) above which a pixel is foreground. Default 50.
use_nvenc (Optional[bool]) β Force the back-end. None (default) = auto (NVENC if available, else cv2). True raises if PyNvVideoCodec is missing.
codec (str) β NVENC codec when using the NVENC back-end (βh264β, βhevcβ, or βav1β). Default βh264β.
queue_size (int) β Pipeline queue depth for the cv2 fallback back-end. Default 3.
verbose (bool) β If True, print progress. Default True.
- Example
>>> from simba.video_processors.video_processing import create_average_frm >>> video_path = "/mnt/c/troubleshooting/mitra/project_folder/videos/clipped/592_MA147_Gq_CNO_0515.mp4" >>> avg_frm = create_average_frm(video_path=video_path) >>> subtractor = BackgroundSubtractorCUDA(video_path=video_path, avg_frm=avg_frm, fg_clr=(255, 255, 255)) >>> subtractor.run()
- run()[source]
Run background subtraction and write the output video. Returns the save path.
Pose plotting (GPU)ο
- class simba.data_processors.cuda.pose_plotter_nvenc.PosePlotterNVENC(data=None, video_path=None, save_path=None, config_path=None, sample_time=None, circle_size=None, colors='Set1', codec='h264', qp=15, buffer_size=16, n_workers=None, verbose=True)[source]
Bases:
objectOverlay pose-estimation data on a video, fully on the GPU (NVDEC -> CUDA -> NVENC).
See also
For the CPU-encode GPU version, see
simba.data_processors.cuda.image.pose_plotter(). For CPU methods, seePathPlotterSingleCore()andPathPlotterMulticore().Note
Requires PyNvVideoCodec (NVDEC/NVENC) and torch (for the DLPack decode interop); the constructor raises
SimBAPAckageVersionErrorif either is missing. Encoding is 4:4:4 (full-resolution chroma) so small/colored body-part circles stay crisp - 4:2:0 subsamples chroma and mottles or erases them. Trade-off: a 4:4:4 H.264/HEVC stream needs a 4:4:4-capable player (VLC, ffmpeg/OpenCV, mpv all work; some browsers and QuickTime do not). Output is lossy, so pixels are perceptually equivalent but not bit-identical to the CPU path.Expected runtimes by image sizeο IMAGE SIZE
FPS
STDEV (FPS)
320x256
2034.0
98.1
640x512
1913.7
129.9
1280x1024
747.1
0.9
1920x1536
354.6
0.4
NVIDIA GeForce RTX 4070
NVENC h264; threaded NVDEC decode; 1802 frames; 8 body-parts; 3 runs
Multi-worker scaling (100K frames, 1280x1024, 7 body-parts, RTX PRO 6000 Blackwell)ο Workers
Time (s)
FPS
Speedup
1
100.7
993
1.00x
4
55.8
1794
1.81x
Three input styles are supported:
Single file -
datais a CSV path (or a(n_frames, n_bodyparts, 2)array) andvideo_pathis a single video.save_pathis the output file (or a directory, in which case<video_name>.mp4is written).Directory (batch) -
dataandvideo_pathare both directories; each data file is matched to the video of the same name and rendered.save_pathmust be an existing directory. If one ofdata/video_pathis a directory the other must be too.SimBA project -
config_pathpoints at aproject_config.ini; data defaults to the projectβs outlier-corrected directory and videos toproject_folder/videos(either can be overridden by passingdata/video_pathdirectories).save_pathdefaults toproject_folder/frames/output/pose_nvenc.
- Parameters
data (Union[str, os.PathLike, np.ndarray]) β A CSV path or
(n_frames, n_bodyparts, 2)array (single mode), or a directory of pose files (batch mode). In project mode, an optional directory overriding the project default.video_path (Optional[Union[str, os.PathLike]]) β A single video (single mode) or a directory of videos (batch mode). If either
dataorvideo_pathis a directory, both must be. Optional in project mode.save_path (Optional[Union[str, os.PathLike]]) β Output video file (single mode) or output directory (batch/project mode). Optional in project mode (defaults into the project).
config_path (Optional[Union[str, os.PathLike]]) β Path to a SimBA
project_config.inito drive project-mode batch rendering. Default None.sample_time (Optional[float]) β If not None, render only the first
sample_timeseconds of each video (int(fps * sample_time)frames). Useful for quick previews. Default None (full video). When set, the data/video frame counts need not match exactly.circle_size (Optional[int]) β Radius of the body-part circles. If None, inferred from resolution.
colors (Optional[str]) β Palette name for body-part colors. Default βSet1β.
codec (str) β NVENC codec (βh264β, βhevcβ, or βav1β). Default βh264β.
qp (int) β Constant quantization parameter (0-51) for the NVENC encoder (rc=βconstqpβ, high-quality tuning, 4:4:4 chroma). Lower = higher quality and larger files. Default 15.
buffer_size (int) β Number of frames the threaded NVDEC decoder decodes ahead on its background thread (overlaps decoding with GPU compute/encode). Default 16.
n_workers (Optional[int]) β Number of parallel decode/encode pipelines (one per NVDEC/NVENC engine); the video is split into this many chunks and concatenated. None auto-detects the GPUβs NVDEC count. Must be 1..(NVDEC count) - a larger value raises. Default None.
verbose (bool) β If True, print progress. Default True.
- Example
>>> plotter = PosePlotterNVENC(data=DATA_PATH, video_path=VIDEO_PATH, save_path=SAVE_PATH, circle_size=10) >>> plotter.run()
- Example II - directory batch, first 10s of each
>>> plotter = PosePlotterNVENC(data=DATA_DIR, video_path=VIDEO_DIR, save_path=OUT_DIR, sample_time=10) >>> plotter.run()
- Example III - SimBA project
>>> plotter = PosePlotterNVENC(config_path='project_folder/project_config.ini') >>> plotter.run()
- run()[source]
Render every resolved job (one for a single video, several in directory/project mode) to its output path.
Greyscale conversion (GPU)ο
- class simba.data_processors.cuda.greyscale_nvenc.GreyscaleNVENC(data_path, save_dir, codec='h264', verbose=True)[source]
Bases:
objectConvert a video to greyscale, fully on the GPU (NVDEC -> CUDA -> NVENC). GPU-only.
Measured runtime (RTX 4070, h264, single NVDEC/NVENC stream)ο Resolution
Frames
Source FPS
Time (s)
Encode FPS
800x600
108000
30
64.1
1684
Measured batch runtime (RTX 4070, h264, sequential over a directory)ο N videos
Resolution
Total frames
Time (s)
Overall FPS
Per-video avg (s)
20
800x600
2160000
1488.9
1451
74.4
- Parameters
data_path (Union[str, os.PathLike]) β A single video file, OR a directory of videos to convert.
save_dir (Union[str, os.PathLike]) β Output directory. Each converted video is written to
save_dir/<name>.mp4(created if it does not exist).codec (str) β NVENC codec (βh264β, βhevcβ, or βav1β). Default βh264β.
verbose (bool) β If True, print progress. Default True.
- Example
>>> GreyscaleNVENC(data_path='in.mp4', save_dir='/out').run() # single video >>> GreyscaleNVENC(data_path='project_folder/videos', save_dir='/out').run() # whole directory
CLAHE (GPU)ο
- class simba.data_processors.cuda.clahe_nvenc.ClaheNVENC(data_path, save_dir, clip_limit=2, tile_grid_size=(16, 16), codec='h264', buffer_size=16, n_workers=None, verbose=True)[source]
Bases:
objectColour-preserving CLAHE, fully on the GPU (NVDEC -> CUDA -> NVENC). GPU-only.
CLAHE is applied to the Y (luma) channel in YCrCb space; Cr/Cb are preserved, so the output stays in colour. Matches the parameter defaults of SimBAβs CPU
clahe_enhance_video.See also
CPU reference (greyscale output):
clahe_enhance_video()and its multicore variantclahe_enhance_video_mp(). For GPU greyscale (no CLAHE), seeGreyscaleNVENC.Measured runtime (RTX 4070, h264, threaded decode, n_workers=1)ο Resolution
Frames
Source FPS
Time (s)
Encode FPS
800x600
108000
30
68.2
1584
Note
Validated against
cv2.createCLAHEover the same YCrCb pipeline. For tile grids that divide the frame evenly, the GPU output matches cv2 to ~1 grey level (max ~3, from uint8 YCrCb rounding). When the frame is not divisible by the tile count, this class uses ceil-sized tiles with per-tile normalisation rather than cv2βs reflect-padding, so edge tiles differ by a few levels (e.g. 800x600 @ (16,16): mean ~3, 84% of pixels within 5).- Parameters
data_path (Union[str, os.PathLike]) β A single video file, OR a directory of videos.
save_dir (Union[str, os.PathLike]) β Output directory. Each result is written to
save_dir/<name>.mp4(created if needed).clip_limit (int) β CLAHE contrast-amplification limit. Default 2.
tile_grid_size (Tuple[int, int]) β Number of tiles as (n_tiles_x, n_tiles_y), matching cv2βs tileGridSize. Default (16, 16).
codec (str) β NVENC codec (βh264β, βhevcβ, or βav1β). Default βh264β.
buffer_size (int) β Number of frames the threaded NVDEC decoder reads ahead per worker (overlaps decode with GPU compute/encode). Default 16.
n_workers (Optional[int]) β Number of parallel decode/encode pipelines (one per NVDEC/NVENC engine); each video is split into this many contiguous chunks, encoded concurrently, and concatenated. None auto-detects the GPUβs NVDEC count. Must be 1..(NVDEC count); larger raises. On a single-NVDEC GPU this is 1 (single stream). Default None.
verbose (bool) β If True, print progress. Default True.
- Example
>>> ClaheNVENC(data_path='in.mp4', save_dir='/out').run() >>> ClaheNVENC(data_path='project_folder/videos', save_dir='/out', clip_limit=3).run()
- run()[source]
CLAHE-enhance every input video on the GPU and write each to
save_dir.
Egocentric rotation (GPU)ο
- class simba.data_processors.cuda.egocentric_rotator_nvenc.EgocentricRotatorNVENC(video_path, centers, rotation_vectors, anchor_location, save_path=None, fill_clr=(0, 0, 0), codec='h264', buffer_size=16, n_workers=None, verbose=True)[source]
Bases:
objectEgocentric video rotation, fully on the GPU (NVDEC -> CUDA -> NVENC). GPU-only.
GPU counterpart of
EgocentricVideoRotator, taking the samecentersandrotation_vectors. Each frame is rotated about itscenterand translated so the center lands onanchor_location; combined into one affine and applied as an inverse warp with bilinear interpolation.See also
CPU version:
EgocentricVideoRotator. To producecenters/rotation_vectors:egocentrically_align_pose_numba()oregocentrically_align_pose().Measured runtime (RTX 4070, h264, threaded decode, n_workers=1)ο Resolution
Frames
Source FPS
Time (s)
Encode FPS
800x600
108000
30
65.7
1643
- Parameters
video_path (Union[str, os.PathLike]) β Path to the video to rotate.
centers (np.ndarray) β (n_frames, 2) anchor location per frame (pre-alignment).
rotation_vectors (np.ndarray) β (n_frames, 2, 2) per-frame rotation matrices.
anchor_location (Tuple[int, int]) β (x, y) target location the anchor is moved to.
save_path (Union[str, os.PathLike]) β Output path. If None,
<video>_rotated.mp4next to the source.fill_clr (Tuple[int, int, int]) β RGB fill for out-of-frame pixels. Default (0, 0, 0).
codec (str) β NVENC codec (βh264β, βhevcβ, or βav1β). Default βh264β.
buffer_size (int) β Threaded NVDEC read-ahead per worker. Default 16.
n_workers (Optional[int]) β Parallel decode/encode pipelines (one per NVDEC engine); None auto-detects. Default None.
verbose (bool) β If True, print progress. Default True.
- Example
>>> _, centers, rot = egocentrically_align_pose(data=data, anchor_1_idx=6, anchor_2_idx=2, anchor_location=np.array([250, 250]), direction=0) >>> EgocentricRotatorNVENC(video_path='in.mp4', centers=centers, rotation_vectors=rot, anchor_location=(250, 250)).run()
- run()[source]
Rotate the whole video on the GPU and write it to
save_path. Withn_workers> 1 the video is split into contiguous chunks encoded concurrently, then concatenated.
Geometry overlay (GPU)ο
- class simba.data_processors.cuda.geometry_plotter_nvenc.GeometryPlotterNVENC(video_path, geometries=None, roi_path=None, config_path=None, video_name=None, save_path=None, colors=None, palette=None, shape_opacity=0.5, bg_opacity=1.0, outline_clr=None, thickness=2, circle_size=None, codec='h264', buffer_size=16, n_workers=None, verbose=True)[source]
Bases:
objectOverlay geometries on a video, fully on the GPU (NVDEC -> CUDA -> NVENC). GPU-only.
GPU counterpart of
GeometryPlotter. See the module docstring for the supported-geometry scope (filled Polygon + Point, optional outlines; interiors/intersection- colouring are not yet implemented). ROIs can be loaded directly withfrom_roi().See also
Full-featured CPU version:
GeometryPlotter.Measured runtime (RTX 4070, h264, threaded decode, n_workers=1)ο Resolution
Frames
Geometries
Time (s)
Encode FPS
800x600
108000
2 polygons
77.8
1388
1280x720
108000
3 ROIs (rect/circle/polygon)
110.1
962
Provide the geometries as exactly ONE of:
geometries(a per-frame list),roi_path(a SimBAROI_definitions.h5), orconfig_path(a SimBA project).from_roi()is a thin convenience wrapper around theroi_path/config_pathinputs with outline-only defaults.- Parameters
video_path (Union[str, os.PathLike]) β Path to the video to overlay onto.
geometries (Optional[List[List]]) β List (per geometry/track) of per-frame shapely geometries, as for the CPU
GeometryPlotter. Requirescolorsorpalette.roi_path (Optional[Union[str, os.PathLike]]) β Path to a SimBA
ROI_definitions.h5; its ROIs (with their own colours) are drawn. Alternative togeometries.config_path (Optional[Union[str, os.PathLike]]) β Path to a SimBA
project_config.inito read ROIs from the project. Alternative togeometries/roi_path.video_name (Optional[str]) β When reading ROIs, the video whose ROIs to draw. Defaults to the
video_pathfile name.save_path (Union[str, os.PathLike]) β Output path. If None,
<video>_geometry.mp4next to the source.colors (Optional[List[Union[str, Tuple[int,int,int]]]]) β One colour per geometry (BGR tuple or SimBA colour name). Used with
geometries; provide this orpalette.palette (Optional[str]) β Colour palette name (used with
geometriesifcolorsis None).shape_opacity (float) β Fill opacity 0-1 (0 = no fill, outline only). Default 0.5.
bg_opacity (float) β Background opacity 0-1. Default 1.0.
outline_clr (Optional[Tuple[int,int,int]]) β BGR colour for polygon/circle outlines. None = no outline. Default None.
thickness (Optional[int]) β Outline thickness in pixels (used when
outline_clris set). Default 2.circle_size (Optional[int]) β Radius for Point geometries. Default: auto from frame size.
codec (str) β NVENC codec (βh264β, βhevcβ, βav1β). Default βh264β.
buffer_size (int) β Threaded NVDEC read-ahead per worker. Default 16.
n_workers (Optional[int]) β Parallel decode/encode pipelines; None auto-detects NVDEC count. Default None.
verbose (bool) β Print progress. Default True.
- Example
>>> # per-frame geometries: >>> GeometryPlotterNVENC(video_path='in.mp4', geometries=geos, colors=['Red', 'Green'], save_path='out.mp4').run() >>> # or straight from a SimBA ROI file: >>> GeometryPlotterNVENC(video_path='in.mp4', roi_path='ROI_definitions.h5', save_path='out.mp4', outline_clr=(0, 0, 255)).run()
- classmethod from_roi(video_path, roi_path=None, config_path=None, video_name=None, save_path=None, shape_opacity=0.0, bg_opacity=1.0, outline_clr=(0, 0, 255), thickness=2, codec='h264', buffer_size=16, n_workers=None, verbose=True)[source]
Convenience constructor for SimBA ROIs. Identical to passing
roi_path(orconfig_path) toGeometryPlotterNVENCdirectly, but defaults to the usual outline-only ROI look (shape_opacity=0with a red outline).- Example
>>> GeometryPlotterNVENC.from_roi(video_path='in.mp4', roi_path='ROI_definitions.h5', save_path='out.mp4').run()
- run()[source]
Render the geometry-overlay video on the GPU and write it to
save_path.
Statistics (GPU)ο
- simba.data_processors.cuda.statistics.adjusted_rand_gpu(x, y)[source]
Calculate the Adjusted Rand Index (ARI) between two clusterings.
The Adjusted Rand Index (ARI) is a measure of the similarity between two clusterings. It considers all pairs of samples and counts pairs that are assigned to the same or different clusters in both the true and predicted clusterings.
The ARI is defined as:
\[ARI = \frac{TP + TN}{TP + FP + FN + TN}\]- where:
\(TP\) (True Positive) is the number of pairs of elements that are in the same cluster in both x and y,
\(FP\) (False Positive) is the number of pairs of elements that are in the same cluster in y but not in x,
\(FN\) (False Negative) is the number of pairs of elements that are in the same cluster in x but not in y,
\(TN\) (True Negative) is the number of pairs of elements that are in different clusters in both x and y.
The ARI value ranges from -1 to 1. A value of 1 indicates perfect clustering agreement, 0 indicates random clustering, and negative values indicate disagreement between the clusterings.
Note
Modified from scikit-learn
See also
For CPU call, see
simba.mixins.statistics_mixin.Statistics.adjusted_rand().- Parameters
x (np.ndarray) β 1D array representing the labels of the first model.
y (np.ndarray) β 1D array representing the labels of the second model.
- Returns
A value of 1 indicates perfect clustering agreement, a value of 0 indicates random clustering, and negative values indicate disagreement between the clusterings.
- Return type
- Example
>>> x = np.random.randint(low=0, high=55, size=100000000) >>> y = np.random.randint(low=0, high=55, size=100000000) >>> adjusted_rand_gpu(x=x, y=y)
- simba.data_processors.cuda.statistics.bray_curtis_dissimilarity_cuda(x, w=None)[source]
Compute the pairwise Bray-Curtis dissimilarity matrix between all rows of a 2D array, on the GPU.
Dissimilarity is 0 for identical observations and 1 for completely dissimilar ones.
Note
Output is a dense (n, n) float32 matrix, so memory scales with n^2 (n=50,000 ~ 10 GB, the in-VRAM ceiling on a 12 GB card). Matches the CPU version exactly (float32 output). An optional weight matrix is applied from its upper triangle (mirrored to the lower), matching the CPU convention.
EXPECTED RUNTIMES
N OBS (F=30)
OUTPUT
MEAN (S)
SD (S)
PAIRS/S
1k
4mb
0.0022
0.0001
446.2m
2k
16mb
0.0065
0.0002
618.4m
5k
100mb
0.0381
0.0014
656.8m
10k
400mb
0.1382
0.0052
723.7m
20k
1.6gb
0.5582
0.0208
716.6m
30k
3.6gb
1.3267
0.0921
678.4m
40k
6.4gb
2.3235
0.1108
688.6m
50k
10.0gb
3.9855
0.0328
627.3m
NVIDIA GeForce RTX 4070 (12GB)
F=30 features; mean +/- SD of 3 runs; unweighted
dense (n x n) float32 output -> memory scales n^2 (50k~10GB ceiling); ~11x vs CPU numba at 8k
See also
CPU (numba) version:
simba.mixins.statistics_mixin.Statistics.bray_curtis_dissimilarity().- Parameters
x (np.ndarray) β 2D array (n_observations, n_features) of (likely normalized) feature values.
w (Optional[np.ndarray]) β Optional (n, n) weight matrix. Default None (all pairs weighted equally).
- Returns
(n, n) float32 Bray-Curtis dissimilarity matrix.
- Return type
np.ndarray
- Example
>>> x = np.array([[1, 1, 1, 1, 1], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [1, 1, 1, 1, 1]]).astype(np.float32) >>> bray_curtis_dissimilarity_cuda(x=x)
- simba.data_processors.cuda.statistics.count_values_in_ranges(x, r)[source]
Counts the number of values in each feature within specified ranges for each row in a 2D array using CUDA.
EXPECTED RUNTIMES
FRAMES (MILLION)
TIME (S)
4
0.038
8
0.201
16
0.344
32
0.306
64
0.776
128
1.611
NVIDIA GeForce RTX 4070
(n, 11)
See also
For CPU function see
count_values_in_range().- Parameters
x (np.ndarray) β 2d array with feature values.
r (np.ndarray) β 2d array with lower and upper boundaries.
- Returns
2d array of size len(x) x len(r) with the counts of values in each feature range (inclusive).
- Return type
np.ndarray
- Example
>>> x = np.random.randint(1, 11, (10, 10)).astype(np.int8) >>> r = np.array([[1, 6], [6, 11]]) >>> r_x = count_values_in_ranges(x=x, r=r)
- simba.data_processors.cuda.statistics.cov_matrix_cuda(data)[source]
Compute the covariance matrix of a 2D array (observations x features), on the GPU.
Note
Output is the (m, m) sample covariance matrix (
n - 1denominator). One thread per feature pair, so parallelism scales with m^2 (small m under-uses the GPU); input memory scales with n * m. Computed in float64 - matches the CPU version to ~1e-16.EXPECTED RUNTIMES
N OBS (m=100)
INPUT
MEAN (S)
SD (S)
OBS/S
1k
1mb
0.0010
0.0001
1.0m
10k
8mb
0.0057
0.0001
1.8m
100k
80mb
0.0501
0.0005
2.0m
1m
800mb
0.4967
0.0093
2.0m
5m
4.0gb
2.8186
0.3193
1.8m
10m
8.0gb
5.8539
0.1886
1.7m
NVIDIA GeForce RTX 4070 (12GB)
m=100 features; mean +/- SD of 3 runs; float64
input (n x m) float64 binds memory (~12m obs at m=100 ceiling); ~283x vs CPU at 1m m=100
See also
CPU (numba) version:
simba.mixins.statistics_mixin.Statistics.cov_matrix().- Parameters
data (np.ndarray) β 2D array (n_observations, n_features).
- Returns
(n_features, n_features) float64 covariance matrix.
- Return type
np.ndarray
- Example
>>> data = np.random.randint(0, 2, (200, 40)).astype(np.float32) >>> cov_matrix_cuda(data=data)
- simba.data_processors.cuda.statistics.davis_bouldin(x, y)[source]
Computes the Davis-Bouldin Index using GPU acceleration, a clustering evaluation metric that assesses the quality of clustering based on the ratio of within-cluster and between-cluster distances.
The lower the Davis-Bouldin Index, the better the clusters are separated and compact. The function calculates the average similarity between each cluster and its most similar cluster.
See also
For CPU implementation, use
simba.mixins.statistics_mixin.Statistics.davis_bouldin()EXPECTED RUNTIMES
OBSERVATIONS (MILLIONS)
TIME (S)
STDEV (S)
2
0.03166
0.023
4
0.06161
0.04883
8
0.12143
0.09597
16
0.24169
0.19592
32
0.27942
0.12019
64
0.45187
0.09255
128
0.98631
0.31372
NVIDIA GeForce RTX 4070
REPEATS = 3
centers = [[0, 0], [5, 10], [10, 0], [20, 10]]
x, y = make_blobs(n_samples=OBSERVATIONS, n_features=2, centers=centers, cluster_std=1)
- Parameters
x (np.ndarray) β A 2D array of data points where each row corresponds to aan observation and each column corresponds to a feature.
y (np.ndarray) β A 1D array containing the cluster labels for each sample in x.
- Returns
The Davis-Bouldin Index as a float, where lower values indicate better-defined clusters.
- Return type
- Example
>>> centers = [[0, 0], [5, 10], [10, 0], [20, 10]] # Adjust distances between cluster centers >>> x, y = make_blobs(n_samples=50000, n_features=4, centers=3, cluster_std=0.1) >>> p = davis_bouldin(x, y)
- simba.data_processors.cuda.statistics.dunn_index(x, y)[source]
Computes the Dunn Index for clustering quality using GPU acceleration, which is a ratio of the minimum inter-cluster distance to the maximum intra-cluster distance. The higher the Dunn Index, the better the separation between clusters.
The Dunn Index is given by:
\[D = \frac{\min_{i \neq j} \{ \delta(C_i, C_j) \}}{\max_k \{ \Delta(C_k) \}}\]where \(\delta(C_i, C_j)\) is the distance between clusters \(C_i\) and \(C_j\), and \(\Delta(C_k)\) is the diameter of cluster \(C_k\).
The higher the Dunn Index, the better the clustering, as a higher value indicates that the clusters are well-separated relative to their internal cohesion.
EXPECTED RUNTIMES
OBSERVATIONS (MILLIONS)
TIME (S)
STDEV (S)
2
0.2366
0.0114
4
0.4464
0.0016
8
0.9037
0.0032
16
1.8675
0.0019
32
3.6247
0.006497
64
7.2898
0.007388
128
14.822
0.02672
256
29.316
0.0425
512
58.23599271
0.477388716
NVIDIA GeForce RTX 4070
REPEATS = 3
centers = [[0, 0], [5, 10], [10, 0], [20, 10]]
x, y = make_blobs(n_samples=OBSERVATIONS, n_features=2, centers=centers, cluster_std=1)
- Parameters
x (np.ndarray) β The input data points, where each row corresponds to an observation, and columns are features.
y (np.ndarray) β Cluster labels for the data points. Each label corresponds to a cluster assignment for the respective observation in x.
- Returns
The Dunn Index, a floating point value that measures the quality of clustering.
- Return type
- Example
>>> centers = [[0, 0], [5, 10], [10, 0], [20, 10]] # Adjust distances between cluster centers >>> x, y = make_blobs(n_samples=80_000_000, n_features=10, centers=centers, cluster_std=1, random_state=10) >>> v = dunn_index(x=x, y=y)
- simba.data_processors.cuda.statistics.euclidean_distance_to_static_point(data, point, pixels_per_millimeter=1, centimeter=False, batch_size=65000000)[source]
Computes the Euclidean distance between each point in a given 2D array data and a static point using GPU acceleration.
See also
For CPU-based distance to static point (ROI center), see
simba.mixins.feature_extraction_mixin.FeatureExtractionMixin.framewise_euclidean_distance_roi()For CPU-based framewise Euclidean distance, seesimba.mixins.feature_extraction_mixin.FeatureExtractionMixin.framewise_euclidean_distance()For GPU CuPy solution for distance between two sets of points, seesimba.data_processors.cuda.statistics.get_euclidean_distance_cupy()For GPU numba CUDA solution for distance between two sets of points, seesimba.data_processors.cuda.statistics.get_euclidean_distance_cuda()- Parameters
data β A 2D array of shape (N, 2), where N is the number of points, and each point is represented by its (x, y) coordinates. The array can represent pixel coordinates.
point β A tuple of two integers representing the static point (x, y) in the same space as data.
pixels_per_millimeter β A scaling factor that indicates how many pixels correspond to one millimeter. Defaults to 1 if no scaling is necessary.
centimeter β A flag to indicate whether the output distances should be converted from millimeters to centimeters. If True, the result is divided by 10. Defaults to False (millimeters).
batch_size β The number of points to process in each batch to avoid memory overflow on the GPU. The default batch size is set to 65 million points (6.5e+7). Adjust this parameter based on GPU memory capacity.
- Returns
A 1D array of distances between each point in data and the static point, either in millimeters or centimeters depending on the centimeter flag.
- Return type
np.ndarray
- simba.data_processors.cuda.statistics.get_3pt_angle(x, y, z)[source]
Computes the angle formed by three points in 2D space for each corresponding row in the input arrays using GPU. The points x, y, and z represent the coordinates of three points in space, and the angle is calculated at point y between the line segments xy and yz.
EXPECTED RUNTIMES
FRAMES
TIME (S)
4 million
0.02
8 million
0.04
16 million
0.159
32 million
0.29
64 million
0.335
128 million
0.792
256 million
1.371
See also
For CPU function see
angle3pt()and For CPU function seeangle3pt_serialized().- Parameters
x β A numpy array of shape (n, 2) representing the first point (e.g., nose) coordinates.
y β A numpy array of shape (n, 2) representing the second point (e.g., center) coordinates, where the angle is computed.
z β A numpy array of shape (n, 2) representing the second point (e.g., center) coordinates, where the angle is computed.
- Returns
A numpy array of shape (n, 1) containing the calculated angles (in degrees) for each row.
- Return type
np.ndarray
- Example
>>> video_path = r"/mnt/c/troubleshooting/mitra/project_folder/videos/501_MA142_Gi_CNO_0514.mp4" >>> data_path = r"/mnt/c/troubleshooting/mitra/project_folder/csv/outlier_corrected_movement_location/501_MA142_Gi_CNO_0514 - test.csv" >>> df = read_df(file_path=data_path, file_type='csv') >>> y = df[['Center_x', 'Center_y']].values >>> x = df[['Nose_x', 'Nose_y']].values >>> z = df[['Tail_base_x', 'Tail_base_y']].values >>> angle_x = get_3pt_angle(x=x, y=y, z=z)
- simba.data_processors.cuda.statistics.get_euclidean_distance_cuda(x, y)[source]
Computes the Euclidean distance between two sets of points using CUDA for GPU acceleration.
EXPECTED RUNTIMES
OBSERVATION
TIME (S)
110k
0.007
181k
0.021
327k
0.032
620k
0.02
1.2m
0.082
2.4m
0.046
4.7m
0.106
9.3m
0.209
18.6m
0.238
37.2m
0.926
74.5m
1.136
149m
2.046
See also
For CPU function see
framewise_euclidean_distance(). For CuPY function seeget_euclidean_distance_cupy().- Parameters
x (np.ndarray) β A 2D array of shape (n, m) representing n points in m-dimensional space. Each row corresponds to a point.
y (np.ndarray) β A 2D array of shape (n, m) representing n points in m-dimensional space. Each row corresponds to a point.
- Return np.ndarray
A 1D array of shape (n,) where each element represents the Euclidean distance between the corresponding points in x and y.
- Example
>>> video_path = r"/mnt/c/troubleshooting/mitra/project_folder/videos/501_MA142_Gi_CNO_0514.mp4" >>> data_path = r"/mnt/c/troubleshooting/mitra/project_folder/csv/outlier_corrected_movement_location/501_MA142_Gi_CNO_0514 - test.csv" >>> df = read_df(file_path=data_path, file_type='csv')[['Center_x', 'Center_y']] >>> shifted_df = FeatureExtractionMixin.create_shifted_df(df=df, periods=1) >>> x = shifted_df[['Center_x', 'Center_y']].values >>> y = shifted_df[['Center_x_shifted', 'Center_y_shifted']].values >>> get_euclidean_distance_cuda(x=x, y=y)
- simba.data_processors.cuda.statistics.get_euclidean_distance_cupy(x, y, batch_size=35000000007)[source]
Computes the Euclidean distance between corresponding pairs of points in two 2D arrays using CuPy for GPU acceleration. The computation is performed in batches to handle large datasets efficiently.
See also
For CPU function see
framewise_euclidean_distance(). For CUDA JIT function seeget_euclidean_distance_cuda().- Parameters
x (np.ndarray) β A 2D NumPy array with shape (n, 2), where each row represents a point in a 2D space.
y (np.ndarray) β A 2D NumPy array with shape (n, 2), where each row represents a point in a 2D space. The shape of y must match the shape of x.
batch_size (Optional[int]) β The number of points to process in a single batch. This parameter controls memory usage and can be adjusted based on available GPU memory. The default value is large (3.5e10 + 7) to maximize GPU utilization, but it can be lowered if memory issues arise.
- Returns
A 1D NumPy array of shape (n,) containing the Euclidean distances between corresponding points in x and y.
- Return type
np.ndarray
- Example
>>> x = np.array([[1, 2], [3, 4], [5, 6]]) >>> y = np.array([[7, 8], [9, 10], [11, 12]]) >>> distances = get_euclidean_distance_cupy(x, y)
- simba.data_processors.cuda.statistics.gower_distance_cuda(x, y)[source]
Compute the Gower-like distance between corresponding rows of two numerical matrices, on the GPU.
Each row of
xis compared to the row at the same index inyvia the mean of per-feature absolute differences normalized by that featureβs range (computed across the rows ofx); features with zero range are skipped.Note
Binding memory is the input, not the output:
xandyare each (n, d) float32, so ~2 * n * d * 4 bytes must fit in VRAM (n ~ 4,000,000 at d=300 on a 12 GB card). The output is only an (n,) vector.EXPECTED RUNTIMES
N OBS (d=300)
INPUT
MEAN (S)
SD (S)
ROWS/S
1k
2mb
0.0028
0.0008
359k
10k
24mb
0.0111
0.0006
904k
100k
240mb
0.1074
0.0044
931k
1m
2.4gb
1.5552
0.1293
643k
2m
4.8gb
2.9174
0.4774
686k
NVIDIA GeForce RTX 4070 (12GB)
d=300 features; mean +/- SD of 3 runs; float32
input (x + y) ~ 2 * n * d * 4 bytes must fit in VRAM (~4m rows at d=300 ceiling); large-n is transfer-bound
See also
CPU version:
simba.mixins.statistics_mixin.Statistics.gower_distance().- Parameters
x (np.ndarray) β 2D array (n_observations, n_features).
y (np.ndarray) β 2D array with the same shape as
x.
- Returns
(n_observations,) float32 vector of row-wise Gower distances.
- Return type
np.ndarray
- Example
>>> x = np.random.randint(0, 500, (1000, 6000)).astype(np.float32) >>> y = np.random.randint(0, 500, (1000, 6000)).astype(np.float32) >>> d = gower_distance_cuda(x=x, y=y)
- simba.data_processors.cuda.statistics.hamming_distance_gpu(x, y, w=None)[source]
Computes the weighted Hamming distance between two arrays using GPU acceleration.
EXPECTED RUNTIMES
OBSERVATIONS (COUNT)
GPU TIME (S) (NUMBA CUDA)
CPU TIME (S) (NUMBA NJIT)
10k
0.01209025
0.00057592
100k
0.00364709
0.00553586
1m
0.0223
0.0551
10m
0.152
0.771
100m
0.4393
5.858
250m
1.3283
14.8490987
500m
2.2082
29.562
1tn
4.821
59.8388138
NVIDIA GeForce RTX 4070, 32 CORES
See also
For jitted CPU method, see
simba.mixins.statistics_mixin.Statistics.hamming_distance().- Parameters
x (ndarray) β A 1D or 2D NumPy array representing the reference data. If 2D, shape should be (n_samples, n_features). Supported dtypes are numeric.
y (ndarray) β Array of the same shape as x representing the data to compare.
w (ndarray) β A 1D array of shape (n_samples,) representing sample weights. If None, uniform weights are used.
- Returns
The weighted average Hamming distance between corresponding rows of x and y.
- Return type
- Example
>>> x, y = np.random.randint(0, 2, (10, 1)).astype(np.int8), np.random.randint(0, 2, (10, 1)).astype(np.int8) >>> gpu_hamming = hamming_distance_gpu(x=x, y=y)
- simba.data_processors.cuda.statistics.i_index(x, y, verbose=False)[source]
Calculate the I-Index for evaluating clustering quality.
The I-Index is a metric that measures the compactness and separation of clusters. A higher I-Index indicates better clustering with compact and well-separated clusters.
EXPECTED RUNTIMES
OBSERVATIONS (MILLIONS)
TIME (S)
STD TIME(S)
5
1.501366667
0.096872717
10
3.0527
0.117796944
20
5.9634
0.282048418
40
11.44683333
0.087952051
80
22.74773333
0.110135477
160
49.425
0.420928735
NVIDIA GeForce RTX 4070
7 body-parts
100 clusters / 3 features
The I-Index is calculated as:
\[I = \frac{SST}{k \times SWC}\]where:
\(SST = \sum_{i=1}^{n} \|x_i - \mu\|^2\) is the total sum of squares (sum of squared distances from all points to the global centroid)
\(k\) is the number of clusters
\(SWC = \sum_{c=1}^{k} \sum_{i \in c} \|x_i - \mu_c\|^2\) is the within-cluster sum of squares (sum of squared distances from points to their cluster centroids)
See also
To compute Xie-Beni on the CPU, use
i_index()- Parameters
x (np.ndarray) β The dataset as a 2D NumPy array of shape (n_samples, n_features).
y (np.ndarray) β Cluster labels for each data point as a 1D NumPy array of shape (n_samples,).
- Returns
The I-index score for the dataset.
- Return type
References
- 1
Zhao, Q., Xu, M., & FrΓ€nti, P. (2009). Sum-of-squares based cluster validity index and significance analysis. In Adaptive and Natural Computing Algorithms (ICANNGA 2009), Lecture Notes in Computer Science, vol. 5495. Springer.
- Example
>>> X, y = make_blobs(n_samples=5000, centers=20, n_features=3, random_state=0, cluster_std=0.1) >>> i_index(x=X, y=y)
- simba.data_processors.cuda.statistics.kmeans_cuml(data, k=2, max_iter=300, output_type=None, sample_n=None)[source]
CRAP, SLOWER THAN SCIKIT
- simba.data_processors.cuda.statistics.kullback_leibler_divergence_gpu(x, y, fill_value=1, bucket_method='scott', verbose=False)[source]
Compute Kullback-Leibler divergence between two distributions.
Note
Empty bins (0 observations in bin) in is replaced with passed
fill_value.Its range is from 0 to positive infinity. When the KL divergence is zero, it indicates that the two distributions are identical. As the KL divergence increases, it signifies an increasing difference between the distributions.
See also
For CPU implementation, see
simba.mixins.statistics_mixin.Statistics.kullback_leibler_divergence().- Parameters
x (ndarray) β First 1d array representing feature values.
y (ndarray) β Second 1d array representing feature values.
fill_value (Optional[int]) β Optional pseudo-value to use to fill empty buckets in
yhistogrambucket_method (Literal) β Estimator determining optimal bucket count and bucket width. Default: The maximum of the Sturges and Freedman-Diaconis estimators
- Returns
Kullback-Leibler divergence between
xandy- Return type
- Example
>>> x, y = np.random.normal(loc=150, scale=900, size=10000000), np.random.normal(loc=140, scale=900, size=10000000) >>> kl = kullback_leibler_divergence_gpu(x=x, y=y)
- simba.data_processors.cuda.statistics.mahalanobis_distance_cdist_cuda(data)[source]
Compute the pairwise Mahalanobis distance between all observations (rows) of
data- the distance between each pair, scaled by the feature covariance - on the GPU.Note
Matches the CPU/scipy result to ~1e-6. The output is a dense (n, n) float32 matrix, so memory scales with n^2 (n=20,000 is ~1.6 GB; ~50,000 is the ~10 GB in-VRAM ceiling on a 12 GB card) - bounded by GPU memory, not compute. Requires a non-singular covariance matrix (raises if features are collinear or n < n_features).
EXPECTED RUNTIMES
N OBS (d=200)
OUTPUT
MEAN (S)
SD (S)
PAIRS/S
1k
4mb
0.0460
0.0237
21.8m
2k
16mb
0.0511
0.0146
78.3m
5k
100mb
0.1102
0.0056
226.8m
10k
0.4gb
0.2400
0.0161
416.6m
20k
1.6gb
0.8175
0.0243
489.3m
30k
3.6gb
1.7878
0.0600
503.4m
40k
6.4gb
3.1729
0.1474
504.3m
50k
10gb
5.9614
1.0257
419.4m
NVIDIA GeForce RTX 4070 (12GB)
d=200 features; mean +/- SD of 3 runs
output is dense n x n float32 -> memory scales n^2 (50k~10GB is the in-VRAM ceiling)
See also
CPU (numba) version:
simba.mixins.statistics_mixin.Statistics.mahalanobis_distance_cdist().- Parameters
data (np.ndarray) β 2D array (n_observations, n_features).
- Returns
(n, n) float32 pairwise Mahalanobis distance matrix.
- Return type
np.ndarray
- Example
>>> data = np.random.randint(0, 50, (1000, 200)).astype(np.float32) >>> d = mahalanobis_distance_cdist_cuda(data=data)
- simba.data_processors.cuda.statistics.manhattan_distance_cdist_cuda(data)[source]
Compute the pairwise Manhattan (L1) distance between all observations (rows) of
data- the sum of absolute feature differences between each pair - on the GPU.Note
The output is a dense (n, n) float32 matrix, so memory scales with n^2 (n=50,000 ~ 10 GB, the in-VRAM ceiling on a 12 GB card). Unlike the CPU version - which builds a full (N, N, D) intermediate and raises MemoryError for large inputs (e.g. ~74 GB at n=10,000, d=200) - this only allocates the n x n output, so it handles sizes the CPU cannot.
EXPECTED RUNTIMES
N OBS (d=200)
OUTPUT
MEAN (S)
SD (S)
PAIRS/S
1k
4mb
0.0038
0.0003
264.6m
2k
16mb
0.0124
0.0003
323.6m
5k
100mb
0.0675
0.0016
370.4m
10k
0.4gb
0.2544
0.0018
393.0m
20k
1.6gb
0.9951
0.0097
402.0m
30k
3.6gb
2.3614
0.0786
381.1m
40k
6.4gb
4.1067
0.0470
389.6m
50k
10gb
7.3517
0.1918
340.1m
NVIDIA GeForce RTX 4070 (12GB)
d=200 features; mean +/- SD of 3 runs
output is dense n x n float32 -> memory scales n^2 (50k~10GB in-VRAM ceiling; CPU OOMs ~74GB at n=10k)
See also
CPU (numpy) version:
simba.mixins.statistics_mixin.Statistics.manhattan_distance_cdist().- Parameters
data (np.ndarray) β 2D array (n_observations, n_features).
- Returns
(n, n) float32 pairwise Manhattan (L1) distance matrix.
- Return type
np.ndarray
- Example
>>> data = np.random.randint(0, 50, (10000, 2)).astype(np.float32) >>> d = manhattan_distance_cdist_cuda(data=data)
- simba.data_processors.cuda.statistics.silhouette_score_gpu(x, y, metric='euclidean')[source]
Compute the Silhouette Score for clustering assignments on GPU using a specified distance metric.
- Parameters
x (np.ndarray) β Feature matrix of shape (n_samples, n_features) containing numeric data.
y (np.ndarray) β Cluster labels array of shape (n_samples,) with numeric labels.
metric (Literal["cityblock", "cosine", "euclidean", "l1", "l2", "manhattan", "sqeuclidean"]) β Distance metric to use (default=βeuclideanβ). Must be one of: βcityblockβ, βcosineβ, βeuclideanβ, βl1β, βl2β, βmanhattanβ, or βsqeuclideanβ.
- Returns
Mean silhouette score as a float.
- Return type
- Example
>>> x, y = make_blobs(n_samples=50000, n_features=20, centers=5, cluster_std=10, center_box=(-1, 1)) >>> score_gpu = silhouette_score_gpu(x=x, y=y)
- simba.data_processors.cuda.statistics.sliding_autocorrelation_cuda(data, max_lag, time_window, fps)[source]
Compute, for each sliding window, how quickly the signalβs self-correlation decays with lag (the slope of autocorrelation vs lag), on the GPU.
Note
Matches the CPU function to ~1e-3 (the CPU casts to float32 internally). Frames before the first full window are
-1.EXPECTED RUNTIMES
N FRAMES
MEAN (S)
SD (S)
FRAMES/S
1k
0.0011
0.0002
0.9m
10k
0.0012
0.0003
8.0m
100k
0.0033
0.0003
30.4m
1m
0.0288
0.0031
34.7m
10m
0.2461
0.0085
40.6m
100m
2.2989
0.0337
43.5m
500m
11.8696
0.4545
42.1m
NVIDIA GeForce RTX 4070
max_lag=0.5s / window=1.0s / fps=30
mean +/- SD of 3 runs; float32 storage
See also
CPU (numba) version:
simba.mixins.statistics_mixin.Statistics.sliding_autocorrelation().- Parameters
- Returns
1D float32 array (len == data) of the sliding autocorrelation slope per window; entries before the first full window are -1.
- Return type
np.ndarray
- Example
>>> data = np.array([0,1,2,3,4,5,6,7,8,1,10,11,12,13,14]).astype(np.float32) >>> sliding_autocorrelation_cuda(data=data, max_lag=0.5, time_window=1.0, fps=10)
- simba.data_processors.cuda.statistics.sliding_iqr_cuda(x, window_size, sample_rate)[source]
Compute the sliding interquartile range (IQR) of a 1D feature array, on the GPU.
Note
The window length (
int(window_size * sample_rate), min 1) must be <= 512 (per-thread sort buffer). Frames before the first full window are -1. Matches the CPU quartile convention exactly (integer indices sorted[n//4] and sorted[3n//4], no interpolation). Runtime grows with the window length (per-thread sort).EXPECTED RUNTIMES
N FRAMES (win=15)
MEAN (S)
SD (S)
FRAMES/S
1k
0.0006
0.0001
1.7m
10k
0.0006
0.0001
17.1m
100k
0.0015
0.0002
67.2m
1m
0.0107
0.0004
93.1m
10m
0.0951
0.0019
105.2m
100m
0.8488
0.0398
117.8m
500m
4.3946
0.2497
113.8m
NVIDIA GeForce RTX 4070
window=15 frames (0.5s / 30fps); mean +/- SD of 3 runs; float32
runtime grows with window length (per-thread O(win^2) sort; max 512); ~34-40x vs CPU at 1m
See also
CPU version:
simba.mixins.statistics_mixin.Statistics.sliding_iqr().- Parameters
- Returns
(len(x),) float32 array of sliding IQR values.
- Return type
np.ndarray
- Example
>>> data = np.random.randint(0, 50, (90,)).astype(np.float32) >>> sliding_iqr_cuda(x=data, window_size=0.5, sample_rate=10.0)
- simba.data_processors.cuda.statistics.sliding_kendall_tau_cuda(sample_1, sample_2, time_windows, fps)[source]
Compute Kendallβs Tau rank correlation between two signals over each sliding window (for every window length and frame), on the GPU.
Note
Matches the CPU function. Incomplete windows are 0; zero-denominator windows are -1.
EXPECTED RUNTIMES
N FRAMES
MEAN (S)
SD (S)
FRAMES/S
1k
0.0010
0.0003
1.0m
10k
0.0008
0.0002
11.8m
100k
0.0012
0.0002
81.6m
1m
0.0081
0.0006
123.2m
10m
0.0699
0.0012
143.1m
100m
0.5944
0.0633
168.2m
500m
3.0653
0.3333
163.1m
NVIDIA GeForce RTX 4070
1 window (1.0s) / fps=30
mean +/- SD of 3 runs; float32 storage
See also
CPU (numba) version:
simba.mixins.statistics_mixin.Statistics.sliding_kendall_tau().- Parameters
sample_1 (np.ndarray) β First 1D signal.
sample_2 (np.ndarray) β Second 1D signal (same length as
sample_1).time_windows (np.ndarray) β 1D array of window lengths in seconds.
fps (float) β Frames per second.
- Returns
2D float32 array (len(sample_1), len(time_windows)); 0 for incomplete windows, -1 for zero-denominator windows.
- Return type
np.ndarray
- Example
>>> s1 = np.random.rand(20).astype(np.float32); s2 = np.random.rand(20).astype(np.float32) >>> sliding_kendall_tau_cuda(sample_1=s1, sample_2=s2, time_windows=np.array([0.5]), fps=10)
- simba.data_processors.cuda.statistics.sliding_mad_median_rule_cuda(data, k, time_windows, fps)[source]
Count outliers in sliding time-windows using the MAD-Median rule, on the GPU.
A value is an outlier when its absolute deviation from the window median exceeds
ktimes the windowβs median absolute deviation (MAD).Note
Each window length (
int(fps * time_window)) must be <= 512 (per-thread sort buffer). Frames before the first full window are -1. Output is (n_frames, n_time_windows) int32. Runtime grows with window length (per-thread sort).EXPECTED RUNTIMES
N FRAMES (win=30)
MEAN (S)
SD (S)
FRAMES/S
1k
0.0008
0.0001
1.2m
10k
0.0009
0.0001
11.6m
100k
0.0033
0.0002
30.1m
1m
0.0193
0.0007
51.9m
10m
0.1689
0.0014
59.2m
100m
1.6521
0.0050
60.5m
500m
8.6633
0.0426
57.7m
NVIDIA GeForce RTX 4070
window=30 frames (1.0s / 30fps); 1 time-window; mean +/- SD of 3 runs
two per-window medians (window + MAD); runtime grows with window (max 512); ~46x vs CPU at 1m
See also
CPU version:
simba.mixins.statistics_mixin.Statistics.sliding_mad_median_rule().- Parameters
- Returns
(n_frames, n_time_windows) int32 array of per-window outlier counts.
- Return type
np.ndarray
- Example
>>> data = np.random.randint(0, 50, (50000,)).astype(np.float32) >>> sliding_mad_median_rule_cuda(data=data, k=2, time_windows=np.array([20.0]), fps=1.0)
- simba.data_processors.cuda.statistics.sliding_mean(x, time_window, sample_rate)[source]
Computes the mean of values within a sliding window over a 1D numpy array x using CUDA for acceleration.
EXPECTED RUNTIMES
FRAMES (MILLIONS)
TIME (S)
2
0.005
4
0.025
8
0.015
16
0.028
32
0.059
64
0.182
128
0.237
256
0.507
512
1.022
NVIDIA GeForce RTX 4070
time window = 1s / 10 FPS
- Parameters
x (np.ndarray) β The input 1D numpy array of floats. The array over which the sliding window sum is computed.
time_window (float) β The size of the sliding window in seconds. This window slides over the array x to compute the sum.
sample_rate (int) β The number of samples per second in the array x. This is used to convert the time-based window size into the number of samples.
- Returns
A numpy array containing the sum of values within each position of the sliding window.
- Return type
np.ndarray
- Example
>>> x = np.random.randint(1, 11, (100, )).astype(np.float32) >>> time_window = 1 >>> sample_rate = 10 >>> r_x = sliding_mean(x=x, time_window=time_window, sample_rate=10)
- simba.data_processors.cuda.statistics.sliding_min(x, time_window, sample_rate)[source]
Computes the minimum value within a sliding window over a 1D numpy array x using CUDA for acceleration.
EXPECTED RUNTIMES
FRAMES (MILLIONS)
TIME (S)
2
0.003
4
0.016
8
0.012
16
0.049
32
0.053
64
0.099
128
0.211
256
0.495
512
1.031
NVIDIA GeForce RTX 4070
time window = 1s / 10 FPS
- Parameters
- Returns
A numpy array containing the minimum value for each position of the sliding window.
- Return type
np.ndarray
- Example
>>> x = np.arange(0, 10000000) >>> time_window = 1 >>> sample_rate = 10 >>> sliding_min(x=x, time_window=time_window, sample_rate=sample_rate)
- simba.data_processors.cuda.statistics.sliding_pearsons_r_cuda(sample_1, sample_2, time_windows, fps)[source]
Compute Pearsonβs R between two signals over each sliding window (for every window length and frame), on the GPU.
Note
Matches the CPU function to ~1e-7. Incomplete windows and zero-denominator windows are -1.
EXPECTED RUNTIMES
N FRAMES
MEAN (S)
SD (S)
FRAMES/S
1k
0.0008
0.0001
1.2m
10k
0.0010
0.0003
9.9m
100k
0.0013
0.0002
75.9m
1m
0.0067
0.0006
150.2m
10m
0.0603
0.0020
165.8m
100m
0.5535
0.0094
180.7m
500m
3.1061
0.2952
161.0m
NVIDIA GeForce RTX 4070
1 window (1.0s) / fps=30
mean +/- SD of 3 runs; float32 storage
See also
CPU (numba) version:
simba.mixins.statistics_mixin.Statistics.sliding_pearsons_r().- Parameters
sample_1 (np.ndarray) β First 1D signal.
sample_2 (np.ndarray) β Second 1D signal (same length as
sample_1).time_windows (np.ndarray) β 1D array of window lengths in seconds.
fps (float) β Frames per second (converts window lengths in seconds to frames). May be fractional (e.g. 29.97).
- Returns
2D float32 array (len(sample_1), len(time_windows)) of Pearsonβs R per window; incomplete/zero-denominator windows are -1.
- Return type
np.ndarray
- Example
>>> s1 = np.random.randint(0, 50, (10)).astype(np.float32) >>> s2 = np.random.randint(0, 50, (10)).astype(np.float32) >>> sliding_pearsons_r_cuda(sample_1=s1, sample_2=s2, time_windows=np.array([0.5]), fps=10)
- simba.data_processors.cuda.statistics.sliding_skew_cuda(data, time_windows, sample_rate)[source]
Compute the sliding skewness of a 1D signal over one or more time windows, on the GPU.
Note
Output is (n_frames, n_time_windows) float64; frames before the first full window are 0. Uses population standard deviation (ddof=0). Constant windows (std 0) yield inf/nan, as in the CPU/NumPy version.
EXPECTED RUNTIMES
N FRAMES (win=30)
MEAN (S)
SD (S)
FRAMES/S
1k
0.0007
0.0002
1.4m
10k
0.0006
0.0001
15.8m
100k
0.0011
0.0002
92.5m
1m
0.0083
0.0004
119.8m
10m
0.0713
0.0008
140.3m
100m
0.6797
0.0073
147.1m
500m
3.8338
0.5073
130.4m
NVIDIA GeForce RTX 4070
window=30 frames (1.0s / 30fps); 1 window; mean +/- SD of 3 runs; float64
population std (ddof=0); ~9x vs CPU numba at 1m
See also
CPU (numpy) version:
simba.mixins.statistics_mixin.Statistics.sliding_skew().- Parameters
data (np.ndarray) β 1D signal.
time_windows (np.ndarray) β 1D array of window sizes in seconds.
sample_rate (float) β Samples per second (may be fractional).
- Returns
(n_frames, n_time_windows) float64 array of sliding skewness values.
- Return type
np.ndarray
- Example
>>> data = np.random.randint(0, 100, (10,)).astype(np.float32) >>> sliding_skew_cuda(data=data, time_windows=np.array([1.0, 2.0]), sample_rate=2.0)
- simba.data_processors.cuda.statistics.sliding_spearmans_rank(x, y, time_window, sample_rate, batch_size=16000000, verbose=False)[source]
Computes the Spearmanβs rank correlation coefficient between two 1D arrays x and y over sliding windows of size time_window * sample_rate. The computation is performed in batches to optimize memory usage, leveraging GPU acceleration with CuPy.
See also
For CPU function see
sliding_spearman_rank_correlation().\(\rho = 1 - \frac{6 \sum d_i^2}{n_w(n_w^2 - 1)}\)
Where: - \(\rho\) is the Spearmanβs rank correlation coefficient. - \(d_i\) is the difference between the ranks of corresponding elements in the sliding window. - \(n_w\) is the size of the sliding window.
- Parameters
x (np.ndarray) β The first 1D array containing the values for Feature 1.
y (np.ndarray) β The second 1D array containing the values for Feature 2.
time_window (float) β The size of the sliding window in seconds.
sample_rate (int) β The sampling rate (samples per second) of the data.
batch_size (Optional[int]) β The size of each batch to process at a time for memory efficiency. Defaults to 1.6e7.
- Returns
A 1D numpy array containing the Spearmanβs rank correlation coefficient for each sliding window.
- Return type
np.ndarray
- Example
>>> x = np.array([9, 10, 13, 22, 15, 18, 15, 19, 32, 11]) >>> y = np.array([11, 12, 15, 19, 21, 26, 19, 20, 22, 19]) >>> sliding_spearmans_rank(x, y, time_window=0.5, sample_rate=2)
- simba.data_processors.cuda.statistics.sliding_std(x, time_window, sample_rate)[source]
- Parameters
x (np.ndarray) β The input 1D numpy array of floats. The array over which the sliding window sum is computed.
time_window (float) β The size of the sliding window in seconds. This window slides over the array x to compute the sum.
sample_rate (int) β The number of samples per second in the array x. This is used to convert the time-based window size into the number of samples.
- Returns
A numpy array containing the sum of values within each position of the sliding window.
- Return type
np.ndarray
- Example
>>> x = np.random.randint(1, 11, (100, )).astype(np.float32) >>> time_window = 1 >>> sample_rate = 10 >>> r_x = sliding_sum(x=x, time_window=time_window, sample_rate=10)
- simba.data_processors.cuda.statistics.sliding_sum(x, time_window, sample_rate)[source]
Computes the sum of values within a sliding window over a 1D numpy array x using CUDA for acceleration.
- Parameters
x (np.ndarray) β The input 1D numpy array of floats. The array over which the sliding window sum is computed.
time_window (float) β The size of the sliding window in seconds. This window slides over the array x to compute the sum.
sample_rate (int) β The number of samples per second in the array x. This is used to convert the time-based window size into the number of samples.
- Returns
A numpy array containing the sum of values within each position of the sliding window.
- Return type
np.ndarray
- Example
>>> x = np.random.randint(1, 11, (100, )).astype(np.float32) >>> time_window = 1 >>> sample_rate = 10 >>> r_x = sliding_sum(x=x, time_window=time_window, sample_rate=10)
- simba.data_processors.cuda.statistics.sliding_z_scores_cuda(data, time_windows, fps)[source]
Compute sliding Z-scores of a 1D signal over one or more time windows, on the GPU.
Each valueβs Z-score is measured against the mean/std of the trailing window it belongs to (matching the CPU overwrite semantics: the last window covering a frame determines its value).
Note
Output is (n_frames, n_time_windows) float64. Windows larger than the data length yield 0. Constant windows (std 0) yield inf/nan, as in the CPU/NumPy version.
EXPECTED RUNTIMES
N FRAMES (win=30)
MEAN (S)
SD (S)
FRAMES/S
1k
0.0012
0.0003
0.8m
10k
0.0011
0.0001
9.2m
100k
0.0017
0.0001
60.0m
1m
0.0105
0.0007
95.0m
10m
0.1184
0.0140
84.5m
100m
0.9274
0.0041
107.8m
500m
5.2044
0.5351
96.1m
NVIDIA GeForce RTX 4070
window=30 frames (1.0s / 30fps); 1 window; mean +/- SD of 3 runs; float64
z-score vs the last trailing window covering each frame; ~11x vs CPU at 1m
See also
CPU (numpy) version:
simba.mixins.statistics_mixin.Statistics.sliding_z_scores().- Parameters
data (np.ndarray) β 1D signal.
time_windows (np.ndarray) β 1D array of window sizes in seconds.
fps (float) β Samples per second (may be fractional).
- Returns
(n_frames, n_time_windows) float64 array of sliding Z-scores.
- Return type
np.ndarray
- Example
>>> data = np.random.randint(0, 100, (1000,)).astype(np.float32) >>> sliding_z_scores_cuda(data=data, time_windows=np.array([1.0, 2.5]), fps=10.0)
- simba.data_processors.cuda.statistics.sokal_sneath_gpu(x, y, w=None)[source]
Compute the SokalβSneath similarity coefficient between two binary vectors using CUDA acceleration.
See also
For CPU method, see
simba.mixins.statistics_mixin.Statistics.sokal_sneath()- Parameters
x (ndarray) β First binary vector (1D array of 0s and 1s).
y (ndarray) β Second binary vector of the same shape as x.
w (ndarray) β A 1D array of shape (n_samples,) representing sample weights. If None, uniform weights are used.
- Returns
The SokalβSneath similarity coefficient between x and y.
- Return type
float.
- simba.data_processors.cuda.statistics.xie_beni(x, y)[source]
Computes the Xie-Beni index for clustering evaluation.
The score is calculated as the ratio between the average intra-cluster variance and the squared minimum distance between cluster centroids. This ensures that the index penalizes both loosely packed clusters and clusters that are too close to each other.
A lower Xie-Beni index indicates better clustering quality, signifying well-separated and compact clusters.
See also
To compute Xie-Beni on the CPU, use
xie_beni()Significant GPU savings detected at about 1m features, 25 clusters.- Parameters
x (np.ndarray) β The dataset as a 2D NumPy array of shape (n_samples, n_features).
y (np.ndarray) β Cluster labels for each data point as a 1D NumPy array of shape (n_samples,).
- Returns
The Xie-Beni score for the dataset.
- Return type
- Example
>>> from sklearn.datasets import make_blobs >>> X, y = make_blobs(n_samples=100000, centers=40, n_features=600, random_state=0, cluster_std=0.3) >>> xie_beni(x=X, y=y)
References
- 1
Xie, X. L., & Beni, G. (1991). A validity measure for fuzzy clustering. IEEE Transactions on Pattern Analysis and Machine Intelligence, 13(8), 841β847.
Circular statistics (GPU)ο
- simba.data_processors.cuda.circular_statistics.direction_from_three_bps(x, y, z, batch_size=15000000)[source]
Calculate the direction angle based on the coordinates of three body points using GPU acceleration.
This function computes the mean direction angle (in degrees) for a batch of coordinates provided in the form of NumPy arrays. The calculation is based on the arctangent of the difference in x and y coordinates between pairs of points. The result is a value in the range [0, 360) degrees.
See also
More CPU function, see
simba.mixins.circular_statistics.CircularStatisticsMixin.direction_three_bps()
- Parameters
x (np.ndarray) β A 2D array of shape (N, 2) containing the x-coordinates of the first body part (nose)
y (np.ndarray) β A 2D array of shape (N, 2) containing the coordinates of the second body part (left ear).
z (np.ndarray) β A 2D array of shape (N, 2) containing the coordinates of the second body part (right ear).
batch_size (Optional[int]) β The size of the batch to be processed in each iteration. Default is 15 million.
- Returns
An array of shape (N,) containing the computed direction angles in degrees.
- Return type
np.ndarray
- simba.data_processors.cuda.circular_statistics.direction_from_two_bps(x, y)[source]
Compute the directionality in degrees from two body-parts. E.g.,
napeandnose, orswim_bladderandtailwith GPU acceleration.EXPECTED RUNTIMES
FRAMES (MILLIONS)
CUDA JIT GPU (S)
2
0.0285
4
0.0404
8
0.069
16
0.1352
32
0.2711
64
0.5586
128
0.8525
256
1.6652
512
4.1223
See also
For CPU function see
simba.mixins.circular_statistics.CircularStatisticsMixin.direction_two_bps().
- Parameters
x (np.ndarray) β Size len(frames) x 2 representing x and y coordinates for first body-part.
y (np.ndarray) β Size len(frames) x 2 representing x and y coordinates for second body-part.
- Returns
Frame-wise directionality in degrees.
- Return type
np.ndarray.
- simba.data_processors.cuda.circular_statistics.instantaneous_angular_velocity(x, stride=1)[source]
Calculate the instantaneous angular velocity between angles in a given array.
This function uses CUDA to perform parallel computations on the GPU.
The angular velocity is computed using the difference in angles between the current and previous values (with a specified stride) in the array. The result is returned in degrees per unit time.
EXPECTED RUNTIMES
OBSERVATIONS/FRAMES (MILLIONS)
TIME (S)
2
0.045
4
0.098
8
0.088
16
0.227
32
0.231
64
0.514
128
0.641
256
1.43
512
2.721
1000
5.481
\[\omega = \frac{{\Delta \theta}}{{\Delta t}} = \frac{{180}}{{\pi}} \times \left( \pi - \left| \pi - \left| \theta_r - \theta_l \right| \right| \right)\]where: - \(\theta_r\) is the current angle. - \(\theta_l\) is the angle at the specified stride before the current angle. - \(\Delta t\) is the time difference between the two angles.
See also
For CPU function, see
simba.mixins.circular_statistics.CircularStatisticsMixin.instantaneous_angular_velocity()- Parameters
x (np.ndarray) β Array of angles in degrees, for which the instantaneous angular velocity will be calculated.
stride (Optional[int]) β The stride or lag (in frames) to use when calculating the difference in angles. Defaults to 1.
- Returns
Array of instantaneous angular velocities corresponding to the input angles. Velocities are in degrees per unit time.
- Return type
np.ndarray
- simba.data_processors.cuda.circular_statistics.rotational_direction(data, stride=1)[source]
Computes the rotational direction between consecutive data points in a circular space, where the angles wrap around at 360 degrees. The function uses GPU acceleration via CUDA to process the data in parallel.
The result array contains values:
0 where there is no change between points.
1 where the angle has increased in the positive direction.
2 where the angle has decreased in the negative direction.
See also
simba.mixins.circular_statistics.CircularStatisticsMixin.rotational_direction()for jitted CPU method.
- Parameters
data (np.ndarray) β 1D array of angular data (in degrees) to analyze. The data will be internally converted to radians and wrapped between [0, 360) degrees before processing.
stride (Optional[int]) β The stride or gap between data points for which the rotational direction is calculated. Default is 1.
- Returns
A 1D array of integers of the same length as data, where each element indicates the rotational direction between the current and previous point based on the stride. The first stride elements in the result will be initialized to -1 since they cannot be compared.
- Return type
np.ndarray
- Example
>>> data = np.random.randint(0, 365, (100)) >>> p = rotational_direction(data=data)
- simba.data_processors.cuda.circular_statistics.sliding_angular_diff(x, time_windows, fps)[source]
Calculate the sliding angular differences for a given time window using GPU acceleration.
This function computes the angular differences between each angle in x and the corresponding angle located at a distance determined by the time window and frame rate (fps). The results are returned as a 2D array where each row corresponds to a position in x, and each column corresponds to a different time window.
EXPECTED RUNTIMES
FRAMES
CUDA JIT GPU (S)
NUMBA CPU TIME (S)
2
0.0287
0.009
4
0.0544
0.020
8
0.1148
0.043
16
0.2204
0.086
32
0.5686
0.260
64
1.7362
0.607
128
2.5639
0.897
256
5.6997
2.454
512
29.272
12.416
See also
For CPU function, see
simba.mixins.circular_statistics.CircularStatisticsMixin.sliding_angular_diff()
\[\text{difference} = \pi - |\pi - |a_1 - a_2||\]Where: - \(a_1\) is the angle at position x. - \(a_2\) is the angle at position x - text{stride}.
- Parameters
x (np.ndarray) β 1D array of angles in degrees.
time_windows (np.ndarray) β 1D array of time windows in seconds to determine the stride (distance in frames) between angles.
fps (float) β Frame rate (frames per second) used to convert time windows to strides.
- Returns
2D array of angular differences. Each row corresponds to an angle in x, and each column corresponds to a time window.
- Return type
np.ndarray
- simba.data_processors.cuda.circular_statistics.sliding_bearing(x, stride=1, sample_rate=1)[source]
Compute the bearing between consecutive points in a 2D coordinate array using a sliding window approach using GPU acceleration.
This function calculates the angle (bearing) in degrees between each point and a point a certain number of steps ahead (defined by stride) in the 2D coordinate array x. The bearing is calculated using the arctangent of the difference in coordinates, converted from radians to degrees.
EXPECTED RUNTIMES
FRAMES / OBSERVATIONS (MILLIONS)
CUDA JIT GPU (S)
CUDA JIT GPU (STD)
2
0.0584
0.033
4
0.0981
0.04097442
8
0.0871
0.0274
16
0.2331
0.055
32
0.2213
0.0837
64
0.321
0.1053
128
0.3986
0.1917
256
0.9613
0.2957
512
2.4208
0.68659184
1000
24.83
2.1469
See also
simba.mixins.circular_statistics.CircularStatisticsMixin.sliding_bearing()- Parameters
x (np.ndarray) β A 2D array of shape (n, 2) where each row represents a point with x and y coordinates. The array must be numeric.
stride (Optional[float]) β The time (multiplied by sample_rate) to look ahead when computing the bearing in seconds. Defaults to 1.
sample_rate (Optional[float]) β A multiplier applied to the stride value to determine the actual step size for calculating the bearing. E.g., frames per second. Defaults to 1. If the resulting stride is less than 1, it is automatically set to 1.
:return:A 1D array of shape (n,) containing the calculated bearings in degrees. Values outside the valid range (i.e., where the stride exceeds array bounds) are set to -1. :rtype: np.ndarray
- simba.data_processors.cuda.circular_statistics.sliding_circular_correlation_cuda(sample_1, sample_2, time_windows, fps)[source]
Compute the circular correlation coefficient between two angular signals over each sliding window (for every window length and frame), on the GPU.
Note
Angular inputs are in degrees. The result at each frame is the absolute circular cross-correlation of the window ending at that frame; incomplete windows (before the first full window) and zero-denominator windows are 0.
EXPECTED RUNTIMES
N FRAMES
MEAN (S)
SD (S)
FRAMES/S
1k
0.0010
0.0002
1.0m
10k
0.0009
0.0001
11.5m
100k
0.0020
0.0001
49.3m
1m
0.0179
0.0002
55.8m
10m
0.1698
0.0026
58.9m
100m
1.5195
0.1653
65.8m
500m
7.4178
0.6019
67.4m
NVIDIA GeForce RTX 4070
1 window=1.0s / fps=30; mean +/- SD of 3 runs; float32
angular inputs in degrees; ~112x vs CPU numba at 1m frames
See also
CPU (numba) version:
simba.mixins.circular_statistics.CircularStatisticsMixin.sliding_circular_correlation().- Parameters
sample_1 (np.ndarray) β First 1D angular signal in degrees.
sample_2 (np.ndarray) β Second 1D angular signal in degrees (same length as
sample_1).time_windows (np.ndarray) β 1D array of window lengths in seconds.
fps (float) β Frames per second (converts window lengths in seconds to frames). May be fractional (e.g. 29.97).
- Returns
2D float32 array (len(sample_1), len(time_windows)) of circular correlation per window.
- Return type
np.ndarray
- Example
>>> s1 = np.random.randint(0, 361, (200,)).astype(np.float32) >>> s2 = np.random.randint(0, 361, (200,)).astype(np.float32) >>> sliding_circular_correlation_cuda(sample_1=s1, sample_2=s2, time_windows=np.array([0.5, 1.0]), fps=10.0)
- simba.data_processors.cuda.circular_statistics.sliding_circular_hotspots(x, time_window, sample_rate, bins, batch_size=35000000)[source]
Calculate the proportion of data points falling within specified circular bins over a sliding time window using GPU
This function processes time series data representing angles (in degrees) and calculates the proportion of data points within specified angular bins over a sliding window. The calculations are performed in batches to accommodate large datasets efficiently.
EXPECTED RUNTIMES
FRAMES (MILLIONS)
GPU (s)
GPU (STDEV)
2
0.0219
0
4
0.0387
0.002
8
0.0809
0.015
16
0.1304
0.008
32
0.3135
0.043
64
0.593
0.054
128
1.2028
0.156
256
2.3236
0.101
512
4.9477
0.538
1024
10.266
1.351
NVIDIA GeForce RTX 4070
BATCH_SIZE: 3e+7
REPEATS 5
See also
For CPU function see
sliding_circular_hotspots().- Parameters
x (np.ndarray) β The input time series data in degrees. Should be a 1D numpy array.
time_window (float) β The size of the sliding window in seconds.
sample_rate (float) β The sample rate of the time series data (i.e., hz, fps).
bins (ndarray) β 2D array of shape representing circular bins defining [start_degree, end_degree] inclusive.
batch_size (Optional[int]) β The size of each batch for processing the data. Default is 5e+7 (50m).
- Returns
A 2D numpy array where each row corresponds to a time point in data, and each column represents a circular bin. The values in the array represent the proportion of data points within each bin at each time point. The first column represents the first bin.
- Return type
np.ndarray
- simba.data_processors.cuda.circular_statistics.sliding_circular_mean(x, time_window, sample_rate, batch_size=30000000.0)[source]
Calculate the sliding circular mean over a time window for a series of angles.
This function computes the circular mean of angles in the input array x over a specified sliding window. The circular mean is a measure of the average direction for angles, which is especially useful for angular data where traditional averaging would not be meaningful due to the circular nature of angles (e.g., 359Β° and 1Β° should average to 0Β°).
The calculation is performed using a sliding window approach, where the circular mean is computed for each window of angles. The function leverages GPU acceleration via CuPy for efficiency when processing large datasets.
The circular mean \(\mu\) for a set of angles is calculated using the following formula:
\[\mu = \text{atan2}\left(\frac{1}{N} \sum_{i=1}^{N} \sin(\theta_i), \frac{1}{N} \sum_{i=1}^{N} \cos(\theta_i)\right)\]\(\theta_i\) are the angles in radians within the sliding window
\(N\) is the number of samples in the window
EXPECTED RUNTIMES
FRAMES (MILLIONS)
GPU (s)
GPU (STDEV)
1
0.0755
0.07201
2
0.03908
0.00131
4
0.0726
0.00205
8
0.13196
0.00872
16
0.26056
0.01587
32
0.60962
0.07974
64
1.01012
0.02032
128
2.05793
0.15376
256
4.08802
0.14152
512
14.67234
3.66222
1000
27.43026
3.35774
See also
For CPU function see
sliding_circular_mean().- Parameters
x (np.ndarray) β Input array containing angle values in degrees. The array should be 1-dimensional.
time_window (float) β Time duration for the sliding window, in seconds. This determines the number of samples in each window based on the sample_rate.
sample_rate (int) β The number of samples per second (i.e., FPS). This is used to calculate the window size in terms of array indices.
batch_size (Optional[int]) β The maximum number of elements to process in each batch. This is used to handle large arrays by processing them in chunks to avoid memory overflow. Defaults to 3e+7 (30 million elements).
- Return np.ndarray
A 1D numpy array of the same length as x, containing the circular mean for each sliding window. Values before the window is fully populated will be set to -1.
- Example
>>> x = np.random.randint(0, 361, (i, )).astype(np.int32) >>> results = sliding_circular_mean(x, 1, 10)
- simba.data_processors.cuda.circular_statistics.sliding_circular_range(x, time_window, sample_rate, batch_size=50000000)[source]
Computes the sliding circular range of a time series data array using GPU.
This function calculates the circular range of a time series data array using a sliding window approach. The input data is assumed to be in degrees, and the function handles the circular nature of the data by considering the circular distance between angles.
\[R = \min \left( \text{max}(\Delta \theta) - \text{min}(\Delta \theta), \, 360 - \text{max}(\Delta \theta) + \text{min}(\Delta \theta) \right)\]where:
\(\Delta \theta\) is the difference between angles within the window,
\(360\) accounts for the circular nature of the data (i.e., wrap-around at 360 degrees).
EXPECTED RUNTIMES
FRAMES (MILLIONS)
GPU (s)
GPU (STDEV)
2
0.055
0.199
4
0.115
0.005
8
0.239
0.003
16
0.398
0.023
32
0.768
0.012
64
1.596
0.04
128
3.118
0.131
256
6.84703
0.73121
512
12.36
0.122
1024
25.17
0.075
NVIDIA GeForce RTX 4070
BATCH_SIZE: 3e+7
REPEATS 5
See also
For CPU function see
sliding_circular_range().- Parameters
x (np.ndarray) β The input time series data in degrees. Should be a 1D numpy array.
time_window (float) β The size of the sliding window in seconds.
sample_rate (float) β The sample rate of the time series data (i.e., hz, fps).
batch_size (Optional[int]) β The size of each batch for processing the data. Default is 5e+7 (50m).
- Returns
A numpy array containing the sliding circular range values.
- Return type
np.ndarray
- Example
>>> x = np.random.randint(0, 361, (19, )).astype(np.int32) >>> p = sliding_circular_range(x, 1, 10)
- simba.data_processors.cuda.circular_statistics.sliding_circular_std(x, time_window, sample_rate, batch_size=50000000)[source]
Calculate the sliding circular standard deviation of a time series data on GPU.
This function computes the circular standard deviation over a sliding window for a given time series array. The time series data is assumed to be in degrees, and the function converts it to radians for computation. The sliding window approach is used to handle large datasets efficiently, processing the data in batches.
The circular standard deviation (Ο) is computed using the formula:
\[\sigma = \sqrt{-2 \cdot \log \left|\text{mean}\left(\exp(i \cdot x_{\text{batch}})\right)\right|}\]where \(x_{\text{batch}}\) is the data within the current sliding window, and \(\text{mean}\) and \(\log\) are computed in the circular (complex plane) domain.
EXPECTED RUNTIMES
FRAMES (MILLIONS)
GPU (s)
GPU (STDEV)
2
0.027
0.0009
4
0.048
0.0028
8
0.117
0.0199
16
0.163
0.0052
32
0.362
0.0571
64
0.653
0.0134
128
1.439
0.1888
256
2.836
0.1929
512
6.107
0.232
1024
22.893
5.933
NVIDIA GeForce RTX 4070
BATCH_SIZE: 3e+7
REPEATS 5
See also
For CPU function see
sliding_circular_std().- Parameters
x (np.ndarray) β The input time series data in degrees. Should be a 1D numpy array.
time_window (float) β The size of the sliding window in seconds.
sample_rate (float) β The sample rate of the time series data (i.e., hz, fps).
batch_size (Optional[int]) β The size of each batch for processing the data. Default is 5e+7 (50m).
- Returns
A numpy array containing the sliding circular standard deviation values.
- Return type
np.ndarray
- simba.data_processors.cuda.circular_statistics.sliding_kuipers_two_sample_test_cuda(sample_1, sample_2, time_windows, fps)[source]
Compute Kuiperβs two-sample test statistic between two circular signals over sliding windows, on the GPU.
Note
Each window length (
int(time_window * fps)) must be <= 512 (per-thread sort buffers). Following the CPU version, the statistic for windowsample[i-w:i]is stored at rowi, and rows before the first full window are -1. Output is (n_frames, n_time_windows) float64. Runtime grows with window length (per-thread sort).EXPECTED RUNTIMES
N FRAMES (win=30)
MEAN (S)
SD (S)
FRAMES/S
1k
0.0010
0.0002
1.0m
10k
0.0012
0.0000
8.3m
100k
0.0035
0.0002
28.4m
1m
0.0266
0.0012
37.7m
10m
0.2450
0.0065
40.8m
100m
2.3284
0.0407
42.9m
500m
12.0618
0.6098
41.5m
NVIDIA GeForce RTX 4070
window=30 frames (1.0s / 30fps); 1 time-window; mean +/- SD of 3 runs
two per-window sorts + searchsorted CDFs; runtime grows with window (max 512); ~86x vs CPU at 1m
See also
CPU (numba) version:
simba.mixins.circular_statistics.CircularStatisticsMixin.sliding_kuipers_two_sample_test().- Parameters
sample_1 (np.ndarray) β First 1D circular signal in degrees.
sample_2 (np.ndarray) β Second 1D circular signal in degrees (same length as
sample_1).time_windows (np.ndarray) β 1D array of window sizes in seconds.
fps (float) β Sampling rate of the signal (may be fractional).
- Returns
(n_frames, n_time_windows) float64 array of Kuiperβs V statistics.
- Return type
np.ndarray
- Example
>>> s1 = np.random.randint(0, 360, (5000,)).astype(np.float32) >>> s2 = np.random.randint(0, 360, (5000,)).astype(np.float32) >>> sliding_kuipers_two_sample_test_cuda(sample_1=s1, sample_2=s2, time_windows=np.array([0.5, 1.0]), fps=30.0)
- simba.data_processors.cuda.circular_statistics.sliding_rayleigh_z(x, time_window, sample_rate, batch_size=50000000)[source]
Computes the Rayleigh Z-statistic over a sliding window for a given time series of angles
This function calculates the Rayleigh Z-statistic, which tests the null hypothesis that the population of angles is uniformly distributed around the circle. The calculation is performed over a sliding window across the input time series, and results are computed in batches for memory efficiency.
Data is processed using GPU acceleration via CuPy, which allows for faster computation compared to a CPU-based approach.
Note
Adapted from
pingouin.circular.circ_rayleighandpycircstat.tests.rayleigh.Rayleigh Z-statistic:
The Rayleigh Z-statistic is given by:
\[R = \frac{1}{n} \sqrt{\left(\sum_{i=1}^{n} \cos(\theta_i)\right)^2 + \left(\sum_{i=1}^{n} \sin(\theta_i)\right)^2}\]where: - \(\theta_i\) are the angles in the window. - \(n\) is the number of angles in the window.
EXPECTED RUNTIMES
FRAMES (MILLIONS)
GPU (s)
GPU (STDEV)
2
0.02531
0.00328
4
0.04003
0.00533
8
0.07184
0.01016
16
0.12379
0.01608
32
0.2542
0.03084
64
0.52848
0.05978
128
1.05474
0.16997
256
1.93246
0.07944
512
4.45524
0.07773
1000
8.46498
0.33432
NVIDIA GeForce RTX 4070
BATCH_SIZE: 3e+7
REPEATS 5
See also
For CPU function see
sliding_rayleigh_z().- Parameters
x (np.ndarray) β Input array of angles in degrees. Should be a 1D numpy array.
time_window (float) β The size of the sliding window in time units (e.g., seconds).
sample_rate (float) β The sampling rate of the input time series in samples per time unit (e.g., Hz, fps).
batch_size (Optional[int]) β The number of samples to process in each batch. Default is 5e7 (50m). Reducing this value may save memory at the cost of longer computation time.
- Returns
A tuple containing two numpy arrays: - z_results: Rayleigh Z-statistics for each position in the input array where the window was fully applied. - p_results: Corresponding p-values for the Rayleigh Z-statistics.
- Return type
Tuple[np.ndarray, np.ndarray]
- simba.data_processors.cuda.circular_statistics.sliding_resultant_vector_length(x, time_window, sample_rate, batch_size=30000000.0)[source]
Calculate the sliding resultant vector length over a time window for a series of angles.
This function computes the resultant vector length (R) for each window of angles in the input array x. The resultant vector length is a measure of the concentration of angles, and it ranges from 0 to 1, where 1 indicates all angles point in the same direction, and 0 indicates uniform distribution of angles.
For a given sliding window of angles, the resultant vector length \(R\) is calculated using the following formula:
\[R = \frac{1}{N} \sqrt{\left(\sum_{i=1}^{N} \cos(\theta_i)\right)^2 + \left(\sum_{i=1}^{N} \sin(\theta_i)\right)^2}\]where:
\(\theta_i\) are the angles in radians within the sliding window
\(N\) is the number of samples in the window
The computation is performed in a sliding window manner over the entire array, utilizing GPU acceleration with CuPy for efficiency, especially on large datasets.
EXPECTED RUNTIMES
FRAMES (MILLIONS)
GPU (s)
GPU (STDEV)
2
0.04253
0.002
4
0.06979
0
8
0.14922
0.015
16
0.34029
0.062
32
0.48812
0.012
64
1.0269
0.059
128
2.16228
0.156
256
4.15671
0.027
512
11.4188
2.501
1000
28.76021
2.59123
NVIDIA GeForce RTX 4070
BATCH_SIZE: 3e+7
REPEATS 5
See also
For CPU function see
sliding_resultant_vector_length().- Parameters
x (np.ndarray) β Input array containing angle values in degrees. The array should be 1-dimensional.
time_window (float) β Time duration for the sliding window, in seconds. This determines the number of samples in each window based on the sample_rate.
sample_rate (int) β The number of samples per second (i.e., FPS). This is used to calculate the window size in terms of array indices.
batch_size (Optional[int]) β The maximum number of elements to process in each batch. This is used to handle large arrays by processing them in chunks to avoid memory overflow. Defaults to 3e+7 (30 million elements).
- Return np.ndarray
A 1D numpy array of the same length as x, containing the resultant vector length for each sliding window. Values before the window is fully populated will be set to -1.
- Example
>>> x = np.random.randint(0, 361, (5000, )).astype(np.int32) >>> results = sliding_resultant_vector_length(x, 1, 10)
Time-series statistics (GPU)ο
Feature extraction (GPU)ο
- simba.data_processors.cuda.feature_extraction.cdist_3d_cuda(data)[source]ο
Compute the per-frame pairwise Euclidean distance matrix of a set of coordinates against itself, on the GPU.
For each frame the (m, m) matrix of distances between all m points is computed (a batched
scipy.cdist).Note
Output is a dense (n_frames, m, m) float64 array, so memory scales with n * m^2 (the binding constraint; e.g. m=8 ~ 512 bytes/frame, so ~15,000,000 frames on a 12 GB card). Matches the CPU to floating-point rounding (~1e-13).
EXPECTED RUNTIMES
N FRAMES (m=8)
OUTPUT
MEAN (S)
SD (S)
FRAMES/S
1k
1mb
0.0005
0.0000
2.1m
10k
5mb
0.0021
0.0001
4.7m
100k
51mb
0.0150
0.0002
6.7m
1m
512mb
0.1709
0.0022
5.9m
5m
2.6gb
0.9366
0.0223
5.3m
10m
5.1gb
2.0684
0.2112
4.8m
15m
7.7gb
2.9917
0.1970
5.0m
NVIDIA GeForce RTX 4070 (12GB)
m=8 points; mean +/- SD of 3 runs; float64 output
dense (n x m x m) float64 output binds memory (n x m^2); ~15m frames at m=8 ceiling; ~53x vs CPU at 1m
See also
CPU (numba) version:
simba.mixins.feature_extraction_mixin.FeatureExtractionMixin.cdist_3d().- Parameters
data (np.ndarray) β 3D array (n_frames, n_points, n_features) of coordinates (n_features is typically 2).
- Returns
(n_frames, n_points, n_points) float64 array of per-frame pairwise Euclidean distances.
- Return type
np.ndarray
- Example
>>> data = np.random.randint(0, 500, (10000, 8, 2)).astype(np.float32) >>> cdist_3d_cuda(data=data)
- simba.data_processors.cuda.feature_extraction.cosine_similarity_cuda(data)[source]ο
Compute the pairwise cosine similarity between all rows of a 2D array, on the GPU.
The cosine similarity is the cosine of the angle between two vectors (magnitude ignored); values range from 1 (same direction) through 0 (orthogonal) to -1 (opposite). Zero-vectors yield a similarity of 0.
Note
Output is a dense (n, n) float32 matrix, so memory scales with n^2 (n=50,000 ~ 10 GB, the in-VRAM ceiling on a 12 GB card). Matches the CPU version to ~1e-6 (float32 output).
EXPECTED RUNTIMES
N OBS (F=50)
OUTPUT
MEAN (S)
SD (S)
PAIRS/S
1k
4mb
0.0021
0.0003
470.0m
2k
16mb
0.0057
0.0001
702.6m
5k
100mb
0.0292
0.0005
856.4m
10k
400mb
0.1134
0.0052
882.1m
20k
1.6gb
0.4266
0.0023
937.6m
30k
3.6gb
0.9301
0.0164
967.7m
40k
6.4gb
1.6864
0.0362
948.8m
50k
10.0gb
3.1664
0.1933
789.5m
NVIDIA GeForce RTX 4070 (12GB)
F=50 features; mean +/- SD of 3 runs
dense (n x n) float32 output -> memory scales n^2 (50k~10GB ceiling); ~7-9x vs CPU BLAS matmul
See also
CPU (numpy) version:
simba.mixins.feature_extraction_mixin.FeatureExtractionMixin.cosine_similarity().- Parameters
data (np.ndarray) β 2D array (n_observations, n_features).
- Returns
(n, n) float32 pairwise cosine-similarity matrix.
- Return type
np.ndarray
- Example
>>> data = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]).astype(np.float32) >>> cosine_similarity_cuda(data=data)
Feature extraction supplement (GPU)ο
- simba.data_processors.cuda.feature_extraction_supplement.border_distances_cuda(data, pixels_per_mm, img_resolution, time_window, fps)[source]ο
Compute the windowed-mean distance of a key-point to the left, right, top, and bottom image edges, on the GPU.
Note
Output is (n_frames, 4) int32 in millimeters (LEFT, RIGHT, TOP, BOTTOM). Frames before the first full window (
current_frame - window_size < 0) are -1. Values are truncated to whole millimeters, matching the CPU version. Binding memory is the (n, 2) float64 input, so ~300,000,000 frames is the ceiling on a 12 GB card.EXPECTED RUNTIMES
N FRAMES
MEAN (S)
SD (S)
FRAMES/S
1k
0.0005
0.0001
2.0m
10k
0.0008
0.0004
12.4m
100k
0.0021
0.0001
48.4m
1m
0.0162
0.0003
61.8m
10m
0.1683
0.0018
59.4m
100m
1.3993
0.1364
71.5m
NVIDIA GeForce RTX 4070 (12GB)
window=1.0s / fps=30; mean +/- SD of 3 runs
float64 (n x 2) input + int32 (n x 4) output ~32 B/frame; ~300m ceiling (500m OOMs); ~590x vs CPU at 1m
See also
CPU (numba) version:
simba.mixins.feature_extraction_supplement_mixin.FeatureExtractionSupplemental.border_distances().- Parameters
data (np.ndarray) β 2D array (n_frames, 2) of body-part (x, y) coordinates.
pixels_per_mm (float) β Pixels per millimeter of the recorded video.
img_resolution (np.ndarray) β Video resolution as (width, height).
time_window (float) β Rolling time-window in seconds (e.g. 0.2).
fps (float) β Frames per second of the recorded video. May be fractional (e.g. 29.97).
- Returns
(n_frames, 4) int32 array of millimeter distances from LEFT, RIGHT, TOP, BOTTOM.
- Return type
np.ndarray
- Example
>>> data = np.array([[250, 250], [250, 250], [250, 250], [500, 500], [500, 500], [500, 500]]).astype(np.float32) >>> border_distances_cuda(data=data, img_resolution=np.array([500, 500]), time_window=1.0, fps=2.0, pixels_per_mm=1.0)
- simba.data_processors.cuda.feature_extraction_supplement.img_edge_distances_cuda(data, pixels_per_mm, img_resolution, time_window, fps)[source]ο
Compute the windowed-mean distance of body-parts to the four image corners, on the GPU.
Note
Output is (n_frames, 4) float32 in millimeters (TOP-LEFT, TOP-RIGHT, BOTTOM-RIGHT, BOTTOM-LEFT). Each frame averages the corner distances over every body-part in every frame of the window (window_size * n_bodyparts points). Frames before the first full window are NaN. Both input memory and runtime scale with n_bodyparts.
EXPECTED RUNTIMES
N FRAMES (bp=1)
MEAN (S)
SD (S)
FRAMES/S
1k
0.0006
0.0001
1.7m
10k
0.0008
0.0001
13.2m
100k
0.0026
0.0000
38.5m
1m
0.0202
0.0004
49.5m
10m
0.1999
0.0031
50.0m
100m
2.0137
0.1378
49.7m
NVIDIA GeForce RTX 4070 (12GB)
1 body-part; window=1.0s / fps=30; mean +/- SD of 3 runs
memory + runtime scale with n_bodyparts; ~300m frames ceiling at bp=1 (500m OOMs); ~1920x vs CPU at 1m bp=8
See also
CPU (numba) version:
simba.mixins.feature_extraction_supplement_mixin.FeatureExtractionSupplemental.img_edge_distances().- Parameters
data (np.ndarray) β 3D array (n_frames, n_bodyparts, 2) of body-part (x, y) coordinates.
pixels_per_mm (float) β Pixels per millimeter of the recorded video.
img_resolution (np.ndarray) β Video resolution as (width, height).
time_window (float) β Rolling time-window in seconds (e.g. 0.2).
fps (float) β Frames per second of the recorded video. May be fractional (e.g. 29.97).
- Returns
(n_frames, 4) float32 array of millimeter distances from TOP-LEFT, TOP-RIGHT, BOTTOM-RIGHT, BOTTOM-LEFT.
- Return type
np.ndarray
- Example
>>> data = np.random.randint(0, 748, (5000, 2, 2)).astype(np.float32) >>> img_edge_distances_cuda(data=data, pixels_per_mm=2.13, img_resolution=np.array([748, 540]), time_window=1.0, fps=30.0)
SHAP explanations (GPU)ο
- simba.data_processors.cuda.create_shap_log.create_shap_log(rf_clf, x, y, cnt_present, cnt_absent, x_names=None, clf_name=None, save_dir=None, verbose=True)[source]
Computes SHAP (SHapley Additive exPlanations) values using a GPU for a RandomForestClassifier, based on specified counts of positive and negative samples, and optionally saves the results.
Note
The SHAP library has to be built from git repo rather than pip: pip install git+https://github.com/slundberg/shap.git.
The scikit model cannot be built using max_depth > 31. You can set this in the SimBA config under [create ensemble settings][rf_max_depth], or rf_max_depth in the config CSVβs.
- Parameters
rf_clf (Union[str, os.PathLike, RandomForestClassifier]) β Trained RandomForestClassifier model or path to the saved model. Can be a string, os.PathLike object, or an instance of RandomForestClassifier.
x (Union[pd.DataFrame, np.ndarray]) β Input features used for SHAP value computation. Can be a pandas DataFrame or numpy ndarray.
y (Union[pd.DataFrame, pd.Series, np.ndarray]) β Target labels corresponding to the input features. Can be a pandas DataFrame, pandas Series, or numpy ndarray with 0 and 1 values.
cnt_present (int) β Number of positive samples (label=1) to include in the SHAP value computation.
cnt_absent (int) β Number of negative samples (label=0) to include in the SHAP value computation.
x_names (Optional[List[str]]) β Optional list of feature names corresponding to the columns in x. If x is a DataFrame, this is extracted automatically.
clf_name (Optional[str]) β Optional name for the classifier, used in naming output files. If not provided, it is extracted from the y labels if possible.
save_dir (Optional[Union[str, os.PathLike]]) β Optional directory path where the SHAP values and corresponding raw features are saved as CSV files.
verbose (Optional[bool]) β Optional boolean flag indicating whether to print progress messages. Defaults to True.
- Return Union[None, Tuple[pd.DataFrame, pd.DataFrame, int]]
If save_dir is None, returns a tuple containing: - V: DataFrame with SHAP values, expected value, sum of SHAP values, prediction probability, and target labels. - R: DataFrame containing the raw feature values for the selected samples. - expected_value: The expected value from the SHAP explainer.
If save_dir is provided, the function returns None and saves the output to CSV files in the specified directory.
- Example
>>> x = np.random.random((1000, 501)).astype(np.float32) >>> y = np.random.randint(0, 2, size=(len(x), 1)).astype(np.int32) >>> clf_names = [str(x) for x in range(501)] >>> results = create_shap_log(rf_clf=MODEL_PATH, x=x, y=y, cnt_present=int(i/2), cnt_absent=int(i/2), clf_name='TEST', x_names=clf_names, verbose=False)
Data transformations (GPU)ο
- simba.data_processors.cuda.data.egocentrically_align_pose_cuda(data, anchor_1_idx, anchor_2_idx, anchor_location, direction, batch_size=1000000)[source]
Aligns a set of 2D points egocentrically based on two anchor points and a target direction using GPU acceleration.
Rotates and translates a 3D array of 2D points (e.g., time-series of frame-wise data) such that one anchor point is aligned to a specified location, and the direction between the two anchors is aligned to a target angle.
See also
For numpy function, see
simba.utils.data.egocentrically_align_pose(). For numba alternative, seesimba.utils.data.egocentrically_align_pose_numba(). To align both pose and video, seesimba.data_processors.egocentric_aligner.EgocentricalAligner(). To egocentrically rotate video, seesimba.video_processors.egocentric_video_rotator.EgocentricVideoRotator()EXPECTED RUNTIMES
FRAMES (MILLIONS)
CUDA TIME (S)
CUDA TIME (STEV)
0.25
0.1882001
0.15372434
0.5
0.1221498
0.00574819
1
0.24
0.0307
2
0.38
0.1092
4
0.505
0.01590969
8
1.037
0.0346
16
3.42
1.53194867
7 BODY-PARTS PER FRAME
3 ITERATIONS
batch size 16M
DIDNβT TEST HIGHER N AS I DONβT HAVE THE NON-GPU RAM
- Parameters
data (np.ndarray) β A 3D array of shape (num_frames, num_points, 2) containing 2D points for each frame. Each frame is represented as a 2D array of shape (num_points, 2), where each row corresponds to a pointβs (x, y) coordinates.
anchor_1_idx (int) β The index of the first anchor point in data used as the center of alignment. This body-part will be placed in the center of the image.
anchor_2_idx (int) β The index of the second anchor point in data used to calculate the direction vector. This bosy-part will be located direction degrees from the anchor_1 body-part.
direction (int) β The target direction in degrees to which the vector between the two anchors will be aligned.
anchor_location (np.ndarray) β A 1D array of shape (2,) specifying the target (x, y) location for anchor_1_idx after alignment.
batch_size (int) β Size of data that is processed on each iteration on GPU. default 1m. Increase if GPU allows.
- Returns
A tuple containing the rotated data, and variables required for also rotating the video using the same rules: - aligned_data: A 3D array of shape (num_frames, num_points, 2) with the aligned 2D points. - centers: A 2D array of shape (num_frames, 2) containing the original locations of anchor_1_idx in each frame before alignment. - rotation_vectors: A 3D array of shape (num_frames, 2, 2) containing the rotation matrices applied to each frame.
- Return type
Tuple[np.ndarray, np.ndarray, np.ndarray]
- Example
>>> DATA_PATH = r"/mnt/c/Users/sroni/OneDrive/Desktop/rotate_ex/data/501_MA142_Gi_Saline_0513.csv" >>> VIDEO_PATH = r"/mnt/c/Users/sroni/OneDrive/Desktop/rotate_ex/videos/501_MA142_Gi_Saline_0513.mp4" >>> SAVE_PATH = r"/mnt/c/Users/sroni/OneDrive/Desktop/rotate_ex/videos/501_MA142_Gi_Saline_0513_rotated.mp4" >>> ANCHOR_LOC = np.array([300, 300]) >>> >>> df = read_df(file_path=DATA_PATH, file_type='csv') >>> bp_cols = [x for x in df.columns if not x.endswith('_p')] >>> data = df[bp_cols].values.reshape(len(df), int(len(bp_cols)/2), 2).astype(np.int64) >>> data, centers, rotation_matrices = egocentrically_align_pose_cuda(data=data, anchor_1_idx=6, anchor_2_idx=2, anchor_location=ANCHOR_LOC, direction=180,batch_size=36000000)
GPU utilitiesο
Low-level CUDA device primitives (@cuda.jit(device=True)) that the other GPU
kernels compose, plus the public NVDEC video-decoder factory.
Low-level CUDA/Numba GPU helpers.
This module holds the small @cuda.jit(device=True) primitives (means, medians,
standard deviation, MAD, RMS, ranges, Euclidean distance, matrix multiply/transpose,
RGB-to-grey conversions and NaN-aware reductions) that the other
simba.data_processors.cuda kernels compose, together with the public
get_nvc_decoder() factory for GPU (NVDEC) hardware video decoding.
How to useο
The _cuda_* functions are CUDA device functions: they execute on the GPU and
can only be called from inside another CUDA kernel (a function decorated with
@cuda.jit) or another device function β never directly from host/Python code.
They operate on data already resident in GPU memory (device arrays, or thread-local
scratch arrays), take one element/row per thread, and return plain scalars or arrays
for further use inside the kernel. Call them as ordinary functions within a kernel;
Numba inlines them at compile time (there is no kernel-launch overhead per call).
from numba import cuda
from simba.data_processors.cuda.utils import _cuda_mean, _cuda_std
@cuda.jit
def zscore_rows(data, out): # data: (n_rows, row_len) device array
i = cuda.grid(1)
if i < data.shape[0]:
row = data[i]
m = _cuda_mean(row) # device helpers, called from within the kernel
s = _cuda_std(row, m)
out[i] = (row[0] - m) / s
zscore_rows[blocks, threads](d_data, d_out) # launch on device arrays
Notes:
The reductions backed by a fixed thread-local scratch buffer (
_cuda_mac(),_cuda_mad(),_cuda_rms(),_cuda_abs_energy()) assume inputs of at most 512 elements.Several helpers mutate their argument in place (e.g.
_cuda_bubble_sort(),_cuda_median(),_cuda_subtract_2d()) β pass a copy if you need the input preserved.The host-callable entry points are
get_nvc_decoder()andget_nvc_encoder(), which build NVDEC/NVENC hardware video decoder/encoder objects from ordinary Python code.
- simba.data_processors.cuda.utils._cross_test(x, y, x1, y1, x2, y2)[source]ο
Device: which side of a directed segment a point lies on (2D cross-product sign).
- Parameters
- Returns
True if the point lies to the right of the directed segment (x1,y1)->(x2,y2).
- simba.data_processors.cuda.utils._cuda_2d_transpose(x, y)[source]ο
Device: transpose a 2D array.
- Parameters
x (np.ndarray) β Input 2D array of shape (m, n).
y (np.ndarray) β Output 2D array of shape (n, m) that receives the transpose.
- Returns
The output array
y.
- simba.data_processors.cuda.utils._cuda_abs_energy(x)[source]ο
Device: absolute energy (sum of squared elements) of a 1D array.
- Parameters
x (np.ndarray) β Input 1D array (maximum length 512).
- Returns
Sum of the squared elements of
x.
- simba.data_processors.cuda.utils._cuda_add_2d(x, vals)[source]ο
Device: add a per-column 1D vector to every row of a 2D array (in place).
- Parameters
x (np.ndarray) β Input 2D array, modified in place.
vals (np.ndarray) β 1D array with one value per column of
x.
- Returns
The modified array
x.
- simba.data_processors.cuda.utils._cuda_are_rows_equal(x, y, idx_1, idx_2)[source]ο
Device: check whether a row in one 2D array equals a row in another.
- simba.data_processors.cuda.utils._cuda_bubble_sort(x)[source]ο
Device: in-place bubble sort of a 1D array (ascending).
- Parameters
x (np.ndarray) β Input 1D array, sorted in place.
- Returns
The sorted array
x.
- simba.data_processors.cuda.utils._cuda_cos(x, t)[source]ο
Device: element-wise cosine of
xwritten intot.- Parameters
x (np.ndarray) β Input 1D array of angles in radians.
t (np.ndarray) β Output 1D array (same length as
x) that receives the cosines.
- Returns
The output array
t.
- simba.data_processors.cuda.utils._cuda_diff(x, start, end, diff)[source]ο
Compute first-order differences of a slice of x and store in diff.
- Parameters
- Example
>>> diff = cuda.local.array(shape=512, dtype=float64) # pre-allocated local array >>> cuda_diff(x, 0, 5, diff)
- simba.data_processors.cuda.utils._cuda_digital_pixel_to_grey(r, g, b)[source]ο
Device: Rec.601 digital greyscale value of an RGB pixel.
- simba.data_processors.cuda.utils._cuda_luminance_pixel_to_grey(r, g, b)[source]ο
Device: Rec.709 luminance greyscale value of an RGB pixel.
- simba.data_processors.cuda.utils._cuda_mac(x)[source]ο
Device: mean absolute change (mean of
|x[i] - x[i-1]|) of a 1D array.- Parameters
x (np.ndarray) β Input 1D array (maximum length 512).
- Returns
Mean of the absolute first-order differences of
x.
- simba.data_processors.cuda.utils._cuda_mad(x)[source]ο
Device: median absolute deviation (MAD) of a 1D array.
- Parameters
x (np.ndarray) β Input 1D array (maximum length 512).
- Returns
Median absolute deviation of
x.
- simba.data_processors.cuda.utils._cuda_matrix_multiplication(mA, mB, out)[source]ο
Device: matrix multiplication
mA @ mBaccumulated intoout.- Parameters
mA (np.ndarray) β Left 2D matrix of shape (m, k).
mB (np.ndarray) β Right 2D matrix of shape (k, n).
out (np.ndarray) β Pre-zeroed output 2D matrix of shape (m, n) that receives the product.
- Returns
The output matrix
out.
- simba.data_processors.cuda.utils._cuda_max(x)[source]ο
Device: maximum value of a 1D array.
- Parameters
x (np.ndarray) β Input 1D array.
- Returns
Largest element of
x.
- simba.data_processors.cuda.utils._cuda_mean(x)[source]ο
Device: arithmetic mean of a 1D array.
- Parameters
x (np.ndarray) β Input 1D array.
- Returns
Mean of
x.
- simba.data_processors.cuda.utils._cuda_median(x)[source]ο
Device: median of a 1D array.
- Parameters
x (np.ndarray) β Input 1D array (sorted in place as a side effect).
- Returns
Median value of
x.
- simba.data_processors.cuda.utils._cuda_min(x)[source]ο
Device: minimum value of a 1D array.
- Parameters
x (np.ndarray) β Input 1D array.
- Returns
Smallest element of
x.
- simba.data_processors.cuda.utils._cuda_mse(img_1, img_2)[source]ο
Device: mean squared error between two equally-shaped 2D images.
- Parameters
img_1 (np.ndarray) β First 2D image.
img_2 (np.ndarray) β Second 2D image (same shape as
img_1).
- Returns
Mean squared error between the two images.
- simba.data_processors.cuda.utils._cuda_nanmean(x, N)[source]ο
Compute the mean of x ignoring NaN values.
- Parameters
x (np.ndarray) β Input array of length N.
N (int) β Number of elements in x to consider.
- Returns
Mean of non-NaN elements in x. Returns 0.0 if no valid elements found.
- simba.data_processors.cuda.utils._cuda_nanvariance(x, N)[source]ο
Compute the variance of x ignoring NaN values using the unbiased estimator.
- Parameters
x (np.ndarray) β Input array of length N.
N (int) β Number of elements in x to consider. Note this is
- Returns
Variance of non-NaN elements in x. Returns 0.0 if count <= 1.
- simba.data_processors.cuda.utils._cuda_point_to_segment_dist(px, py, ax, ay, bx, by)[source]ο
Device: shortest Euclidean distance from point (px, py) to the line segment (ax, ay)-(bx, by).
Used e.g. to rasterise polygon/line outlines on the GPU (a pixel is βonβ an outline of thickness
twhen this distance is <=t / 2).- Returns
Distance from the point to the nearest location on the segment.
- simba.data_processors.cuda.utils._cuda_range(x)[source]ο
Device: range (max minus min) of a 1D array.
- Parameters
x (np.ndarray) β Input 1D array.
- Returns
Difference between the maximum and minimum of
x.
- simba.data_processors.cuda.utils._cuda_rms(x)[source]ο
Device: root-mean-square of a 1D array.
- Parameters
x (np.ndarray) β Input 1D array (maximum length 512).
- Returns
Root-mean-square of
x.
- simba.data_processors.cuda.utils._cuda_sin(x, t)[source]ο
Device: element-wise sine of
xwritten intot.- Parameters
x (np.ndarray) β Input 1D array of angles in radians.
t (np.ndarray) β Output 1D array (same length as
x) that receives the sines.
- Returns
The output array
t.
- simba.data_processors.cuda.utils._cuda_standard_deviation(x)[source]ο
Device: population standard deviation of a 1D array (divides by N).
- Parameters
x (np.ndarray) β Input 1D array.
- Returns
Standard deviation of
x.
- simba.data_processors.cuda.utils._cuda_std(x, x_hat)[source]ο
Device: standard deviation of
xabout a precomputed mean.- Parameters
x (np.ndarray) β Input 1D array.
x_hat (float) β Precomputed mean of
x.
- Returns
Standard deviation of
xaboutx_hat.
- simba.data_processors.cuda.utils._cuda_subtract_2d(x, vals)[source]ο
Device: subtract a per-column 1D vector from every row of a 2D array (in place).
- Parameters
x (np.ndarray) β Input 2D array, modified in place.
vals (np.ndarray) β 1D array with one value per column of
x.
- Returns
The modified array
x.
- simba.data_processors.cuda.utils._cuda_sum(x)[source]ο
Device: sum of a 1D array.
- Parameters
x (np.ndarray) β Input 1D array.
- Returns
Sum of all elements of
x.
- simba.data_processors.cuda.utils._cuda_variance(x)[source]ο
Device: sample variance of a 1D array (divides by N-1).
- Parameters
x (np.ndarray) β Input 1D array.
- Returns
Variance of
x.
- simba.data_processors.cuda.utils._deg2rad(x)[source]ο
Device: convert an angle from degrees to radians.
- Parameters
x (float) β Angle in degrees.
- Returns
Angle in radians.
- simba.data_processors.cuda.utils._euclid_dist_2d(x, y)[source]ο
Device: Euclidean distance between two 2D points.
- Parameters
x (np.ndarray) β First point as a length-2 array
(x, y).y (np.ndarray) β Second point as a length-2 array
(x, y).
- Returns
Euclidean distance between the two points.
- simba.data_processors.cuda.utils._is_cuda_available()[source]ο
Check if GPU available to numba. If True, returns the GPUs, the model, physical slots and compute capabilitie(s).
Use this check for code paths that run
numbaCUDA kernels.numba.cuda.is_available()requires both the NVIDIA driver andlibNVVM(numbaβs JIT compiler backend, shipped with the CUDA toolkit), so it returns False on machines where the GPU is otherwise usable - do not use it to gatetorchcode paths.See also
For the
torchequivalent, required by YOLO and SAM, seeis_torch_cuda_available().
- simba.data_processors.cuda.utils._rad2deg(x)[source]ο
Device: convert an angle from radians to degrees.
- Parameters
x (float) β Angle in radians.
- Returns
Angle in degrees.
- simba.data_processors.cuda.utils.get_nvc_decoder(video_path, output_color_type=None, gpu_id=0, use_device_memory=False, threaded=False, buffer_size=16, start_frame=0)[source]ο
Create an NVDEC hardware video decoder for GPU-accelerated frame reading.
With
threaded=Falsea random-accessPyNvVideoCodec.SimpleDecoderis returned (index/seek per frame). Withthreaded=TrueaPyNvVideoCodec.ThreadedDecoderis returned, which decodesbuffer_sizeframes ahead on a background thread and is streamed withget_batch_frames(n); this overlaps decoding on the NVDEC engine with downstream GPU compute/encode, and is the faster choice for sequential full-video passes.- Parameters
video_path (Union[str, os.PathLike]) β Path to the video file to decode.
output_color_type (PyNvVideoCodec.OutputColorType) β Colour format of the decoded frames. Pass a member of the
PyNvVideoCodec.OutputColorTypeenum, typicallynvc.OutputColorType.RGB(interleaved HWC, shape(H, W, 3)) ornvc.OutputColorType.RGBP(planar CHW, shape(3, H, W)). Defaults toNone, which is resolved tonvc.OutputColorType.RGBinside the function - the default isNonerather than the enum itself becausePyNvVideoCodecis an optional dependency (nvcmay beNoneat import), so the enum cannot be referenced in the signature.gpu_id (int) β Index of the GPU to decode on. Default 0.
use_device_memory (bool) β If True, keep decoded frames in GPU device memory; otherwise copy to host.
threaded (bool) β If True, return a background-decoding
ThreadedDecoder(sequential streaming); if False, a random-accessSimpleDecoder. Default False.buffer_size (int) β Number of frames the
ThreadedDecoderdecodes ahead (ignored whenthreaded=False). Default 16.start_frame (int) β Frame index the
ThreadedDecoderstarts decoding from, via seeking (ignored whenthreaded=False). Used to split a video into chunks across multiple NVDEC engines. Default 0.
- Raises
SimBAGPUError β If PyNvVideoCodec is not installed, or if no CUDA GPU is available.
- Returns
A configured
PyNvVideoCodec.SimpleDecoderorPyNvVideoCodec.ThreadedDecoder.- Example
>>> import PyNvVideoCodec as nvc >>> from numba import cuda >>> import torch >>> # Random-access decode (default RGB output), read one frame into a CUDA device array: >>> decoder = get_nvc_decoder(video_path='video.mp4', use_device_memory=True) >>> frame = cuda.as_cuda_array(torch.from_dlpack(decoder[0])) # (H, W, 3) uint8 on GPU >>> # Sequential streaming decode across a background thread, from frame 500: >>> decoder = get_nvc_decoder(video_path='video.mp4', output_color_type=nvc.OutputColorType.RGB, use_device_memory=True, threaded=True, buffer_size=32, start_frame=500) >>> batch = decoder.get_batch_frames(16)
- simba.data_processors.cuda.utils.get_nvc_encoder(width, height, codec='h264', fmt='ARGB', use_cpu_input_buffer=False)[source]ο
Create an NVENC hardware video encoder for GPU-accelerated frame encoding.
The counterpart of
get_nvc_decoder(). The returned encoderβsEncode(frame)takes one frame (a GPU device tensor whenuse_cpu_input_buffer=False) and returns an elementary-stream bitstream chunk (empty until the encoder has buffered enough frames); callEndEncode()at the end to flush the tail. The raw elementary stream is then muxed into a container withffmpeg -c copy.- Parameters
width (int) β Frame width in pixels.
height (int) β Frame height in pixels.
codec (str) β NVENC codec, one of βh264β, βhevcβ, βav1β. Default βh264β.
fmt (str) β Input surface format the encoder expects (e.g. βARGBβ, βNV12β). Default βARGBβ.
use_cpu_input_buffer (bool) β If True, frames are supplied from host memory; if False (default), from GPU device memory.
- Raises
SimBAGPUError β If PyNvVideoCodec is not installed, or if no CUDA GPU is available.
- Returns
A configured
PyNvVideoCodecencoder.