graphomotor.features.velocity
Feature extraction module for velocity-based metrics in spiral drawing data.
1"""Feature extraction module for velocity-based metrics in spiral drawing data.""" 2 3import numpy as np 4from scipy import stats 5 6from graphomotor.core import models 7 8 9def _calculate_statistics(values: np.ndarray, name: str) -> dict[str, float]: 10 """Helper function to calculate statistics for a given array. 11 12 Args: 13 values: 1-D Numpy array of numerical values. 14 name: Name prefix for the statistics (e.g., "linear_velocity"). 15 16 Returns: 17 Dictionary containing calculated metrics (sum, median, variation, skewness, 18 kurtosis) with keys prefixed by the provided name. 19 """ 20 return { 21 f"{name}_sum": np.sum(np.abs(values)), 22 f"{name}_median": np.median(np.abs(values)), 23 f"{name}_coefficient_of_variation": stats.variation(values), 24 f"{name}_skewness": stats.skew(values), 25 f"{name}_kurtosis": stats.kurtosis(values), 26 } 27 28 29def calculate_velocity_metrics(spiral: models.Spiral) -> dict[str, float]: 30 """Calculate velocity-based metrics from spiral drawing data. 31 32 This function computes three types of velocity metrics by calculating the difference 33 between consecutive points in the spiral drawing data. The three types of velocity 34 are: 35 36 1. **Linear velocity**: The magnitude of change of Euclidean distance in pixels 37 per second. This is calculated as the square root of the sum of squares of 38 the differences in x and y coordinates divided by the difference in time. 39 2. **Radial velocity**: The magnitude of change of distance from center (radius) in 40 pixels per second. Radius is calculated as the square root of the sum of 41 squares of x and y coordinates. 42 3. **Angular velocity**: The magnitude of change of angle in radians per second. 43 Angle is calculated using the arctangent of y coordinates divided by x 44 coordinates, and then unwrapped to maintain continuity across the -π to π 45 boundary. 46 47 For each velocity type, the following metrics are calculated: 48 49 - **Sum**: Sum of absolute velocity values 50 - **Median**: Median of absolute velocity values 51 - **Coefficient of variation**: Standard deviation divided by the mean 52 - **Skewness**: Asymmetry of the velocity distribution 53 - **Kurtosis**: Tailedness of the velocity distribution 54 55 Args: 56 spiral: Spiral object containing drawing data. 57 58 Returns: 59 Dictionary containing calculated velocity metrics. 60 """ 61 x = spiral.data["x"].values 62 y = spiral.data["y"].values 63 time = spiral.data["seconds"].values 64 radius = np.sqrt(x**2 + y**2) 65 theta = np.unwrap(np.arctan2(y, x)) 66 67 dx = np.diff(x) 68 dy = np.diff(y) 69 dt = np.diff(time) 70 dr = np.diff(radius) 71 dtheta = np.diff(theta) 72 73 linear_velocity = np.sqrt(dx**2 + dy**2) / dt 74 radial_velocity = dr / dt 75 angular_velocity = dtheta / dt 76 77 return { 78 **_calculate_statistics(linear_velocity, "linear_velocity"), 79 **_calculate_statistics(radial_velocity, "radial_velocity"), 80 **_calculate_statistics(angular_velocity, "angular_velocity"), 81 }
30def calculate_velocity_metrics(spiral: models.Spiral) -> dict[str, float]: 31 """Calculate velocity-based metrics from spiral drawing data. 32 33 This function computes three types of velocity metrics by calculating the difference 34 between consecutive points in the spiral drawing data. The three types of velocity 35 are: 36 37 1. **Linear velocity**: The magnitude of change of Euclidean distance in pixels 38 per second. This is calculated as the square root of the sum of squares of 39 the differences in x and y coordinates divided by the difference in time. 40 2. **Radial velocity**: The magnitude of change of distance from center (radius) in 41 pixels per second. Radius is calculated as the square root of the sum of 42 squares of x and y coordinates. 43 3. **Angular velocity**: The magnitude of change of angle in radians per second. 44 Angle is calculated using the arctangent of y coordinates divided by x 45 coordinates, and then unwrapped to maintain continuity across the -π to π 46 boundary. 47 48 For each velocity type, the following metrics are calculated: 49 50 - **Sum**: Sum of absolute velocity values 51 - **Median**: Median of absolute velocity values 52 - **Coefficient of variation**: Standard deviation divided by the mean 53 - **Skewness**: Asymmetry of the velocity distribution 54 - **Kurtosis**: Tailedness of the velocity distribution 55 56 Args: 57 spiral: Spiral object containing drawing data. 58 59 Returns: 60 Dictionary containing calculated velocity metrics. 61 """ 62 x = spiral.data["x"].values 63 y = spiral.data["y"].values 64 time = spiral.data["seconds"].values 65 radius = np.sqrt(x**2 + y**2) 66 theta = np.unwrap(np.arctan2(y, x)) 67 68 dx = np.diff(x) 69 dy = np.diff(y) 70 dt = np.diff(time) 71 dr = np.diff(radius) 72 dtheta = np.diff(theta) 73 74 linear_velocity = np.sqrt(dx**2 + dy**2) / dt 75 radial_velocity = dr / dt 76 angular_velocity = dtheta / dt 77 78 return { 79 **_calculate_statistics(linear_velocity, "linear_velocity"), 80 **_calculate_statistics(radial_velocity, "radial_velocity"), 81 **_calculate_statistics(angular_velocity, "angular_velocity"), 82 }
Calculate velocity-based metrics from spiral drawing data.
This function computes three types of velocity metrics by calculating the difference between consecutive points in the spiral drawing data. The three types of velocity are:
- Linear velocity: The magnitude of change of Euclidean distance in pixels per second. This is calculated as the square root of the sum of squares of the differences in x and y coordinates divided by the difference in time.
- Radial velocity: The magnitude of change of distance from center (radius) in pixels per second. Radius is calculated as the square root of the sum of squares of x and y coordinates.
- Angular velocity: The magnitude of change of angle in radians per second. Angle is calculated using the arctangent of y coordinates divided by x coordinates, and then unwrapped to maintain continuity across the -π to π boundary.
For each velocity type, the following metrics are calculated:
- Sum: Sum of absolute velocity values
- Median: Median of absolute velocity values
- Coefficient of variation: Standard deviation divided by the mean
- Skewness: Asymmetry of the velocity distribution
- Kurtosis: Tailedness of the velocity distribution
Arguments:
- spiral: Spiral object containing drawing data.
Returns:
Dictionary containing calculated velocity metrics.