From 1c2d4b95309e36c6795a5c33ed0e638e947bdec6 Mon Sep 17 00:00:00 2001 From: pavi Date: Tue, 18 Jul 2023 18:21:17 -0700 Subject: [PATCH 1/7] functions to get mapping and hand movement decompositions. --- aopy/postproc/base.py | 1 + aopy/postproc/centerout.py | 172 +++++++++++++++++++++++++++++++++++++ 2 files changed, 173 insertions(+) create mode 100644 aopy/postproc/centerout.py diff --git a/aopy/postproc/base.py b/aopy/postproc/base.py index 78700604..3c04a420 100644 --- a/aopy/postproc/base.py +++ b/aopy/postproc/base.py @@ -586,3 +586,4 @@ def get_source_files(preproc_dir, subject, te_id, date): exp_data, exp_metadata = load_preproc_exp_data(preproc_dir, subject, te_id, date) return exp_metadata['source_files'], exp_metadata['source_dir'] + diff --git a/aopy/postproc/centerout.py b/aopy/postproc/centerout.py new file mode 100644 index 00000000..d9f568b0 --- /dev/null +++ b/aopy/postproc/centerout.py @@ -0,0 +1,172 @@ +import numpy as np +from scipy.spatial.transform import Rotation as R + +rotations = dict( + yzx = np.array( # names come from rows (optitrack), but screen coords come from columns: + [[0, 1, 0, 0], # x goes into second column (y-coordinate, coming out of screen) + [0, 0, 1, 0], # y goes into third column (z-coordinate, up) + [1, 0, 0, 0], # z goes into first column (x-coordinate, right) + [0, 0, 0, 1]] + ), + zyx = np.array( + [[0, 0, 1, 0], + [0, 1, 0, 0], + [1, 0, 0, 0], + [0, 0, 0, 1]] + ), + xzy = np.array( + [[1, 0, 0, 0], + [0, 0, 1, 0], + [0, 1, 0, 0], + [0, 0, 0, 1]] + ), + xyz = np.identity(4), +) + +exp_rotations = dict( + none = np.identity(4), + about_x_90 = np.array( + [[1, 0, 0, 0], + [0, 0, 1, 0], + [0, 1, 0, 0], + [0, 0, 0, 1]] + ), + about_x_minus_90 = np.array( + [[1, 0, 0, 0], + [0, 0, -1, 0], + [0, 1, 0, 0], + [0, 0, 0, 1]] + ), + oop_xy_45 = np.array( + [[ 0.707, 0.5 , 0.5 , 0.], + [ 0. , 0.707, -0.707, 0.], + [-0.707, 0.5 , 0.5 , 0.], + [ 0., 0. , 0., 1.]] + ), + oop_xy_minus_45 = np.array( + [[ 0.707, 0.5 , -0.5 , 0.], + [ 0. , 0.707, 0.707, 0.], + [ 0.707, -0.5 , 0.5 , 0.], + [ 0., 0. , 0., 1.]] + ), + oop_xy_20 = np.array( + [[ 0.94 , 0.117, 0.321, 0.], + [-0. , 0.94 , -0.342, 0.], + [-0.342, 0.321, 0.883, 0.], + [ 0., 0. , 0., 1.]] + ), + oop_xy_minus_20 = np.array( + [[ 0.94 , 0.117, -0.321, 0.], + [-0. , 0.94 , 0.342, 0.], + [ 0.342, -0.321, 0.883, 0.], + [ 0., 0. , 0., 1.]] + )) + +def _get_mapping(exp_metadata): + ''' + Returns transformed coordinates based on rotation, offset, and scale traits + Args: + exp_metadata: exp_metadata from load_preproc_exp_data(preproc_dir, subject, te_id, date) + + Returns: + mapping (3 x 3 numpy array): mapping of hand to cursor data used + ''' + offset = exp_metadata['offset'] + offset_arr = np.array( + [[1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [offset[0], offset[1], offset[2], 1]] + ) + scale = exp_metadata['scale'] + scale_arr = np.array( + [[scale, 0, 0, 0], + [0, scale, 0, 0], + [0, 0, scale, 0], + [0, 0, 0, 1]] + ) + rotation = exp_metadata['rotation'] # optitrack -> screen space +# print(rotation) + exp_rotation = exp_metadata['exp_rotation'] # out of plane perturbations applied in screen space - x - right, y - towards monkey, z - up + perturbation = exp_metadata['pertubation_rotation'] # in plane perturbations applied in screen space about y axis so rotation is inplane + new_plane = np.linalg.multi_dot((offset_arr, scale_arr, rotations[rotation], exp_rotations[exp_rotation])) # multi dot product of 4 x 4 matrices + pertubation_rot = R.from_euler('y', perturbation, degrees=True) + mapping = np.matmul(pertubation_rot.as_matrix(), new_plane[0:3]) + return mapping + +def _transform_coords(hand_data, exp_metadata): + ''' + Transforms hand data into mapping used in center out experiment + Args: + hand_traj (2D numpy array): 3D array of hand trajectory data (n_timepoints x 3) + exp_metadata: exp_metadata from load_preproc_exp_data(preproc_dir, subject, te_id, date) + + Returns: + + ''' + offset = exp_metadata['offset'] + offset_arr = np.array( + [[1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [offset[0], offset[1], offset[2], 1]] + ) + scale = exp_metadata['scale'] + scale_arr = np.array( + [[scale, 0, 0, 0], + [0, scale, 0, 0], + [0, 0, scale, 0], + [0, 0, 0, 1]] + ) + rotation = exp_metadata['rotation'] # optitrack -> screen space +# print(rotation) + exp_rotation = exp_metadata['exp_rotation'] # out of plane perturbations applied in screen space - x - right, y - towards monkey, z - up + perturbation = exp_metadata['pertubation_rotation'] # in plane perturbations applied in screen space about y axis so rotation is inplane + old = np.concatenate((np.reshape(hand_data, -1), [1])) +# print( coords.shape, old.shape, offset_arr.shape, scale_arr.shape, rotations[rotation].shape, exp_rotations[exp_rotation].shape ) + new = np.linalg.multi_dot((old, offset_arr, scale_arr, rotations[rotation], exp_rotations[exp_rotation])) + pertubation_rot = R.from_euler('y', perturbation, degrees=True) + hand_transformed = np.matmul(pertubation_rot.as_matrix(), new[0:3]) +# print(coords, new_coords) + return hand_transformed + +def get_taskspace_and_nullspace(mapping, task='2DCenterOut'): + ''' + Decomposes hand movement into components of movement in the plane of the screen and out of the plane of the screen + Args: + mapping (3 x 3 numpy array): Mapping matrix used in experiment. See :func:`get_mapping` for more details + + Returns: + t_a (3 x 3 numpy array): Matrix that projects hand movement into the task potent cursor space + n_a (3 x 3 numpy array): Matrix that projects hand movement into the null space + ''' + if task == '2DCenterOut': + a = mapping[[0,2], :] # rows are cursor and columns are hand + elif task == '1DTracking': + a = mapping[2,:] + + a_plus = a.T @ np.linalg.pinv(a @ a.T) + t_a = a_plus @ a + n_a = np.eye(3) - t_a + + return t_a, n_a + +def decompose_hand_movements(hand_data, mapping): + ''' + Decomposes hand movement into components of movement in the plane of the screen and out of the plane of the screen + Args: + hand_data (2D numpy array): 3D array of hand trajectory data (n_timepoints x 3) + mapping (3 x 3 numpy array): Mapping matrix used in experiment. See :func:`get_mapping` for more details . Rows must be cursor and columns must be hand. + + Returns: + + ''' + t_a, n_a = get_taskspace_and_nullspace(mapping) + hand_data = np.array(hand_data) + hT = np.dot(t_a, hand_data.T) # 3x2400 + hN = np.dot(n_a, hand_data.T) + + hT_norm = np.mean(np.linalg.norm(hT, axis=0)) + hN_norm = np.mean(np.linalg.norm(hN, axis=0)) + + return hT_norm, hN_norm \ No newline at end of file From 6384af768ad1da082354a5a5ec3c9c869d7fad11 Mon Sep 17 00:00:00 2001 From: pavi Date: Fri, 21 Jul 2023 15:54:48 -0700 Subject: [PATCH 2/7] functions to get mapping and hand movement decompositions. --- aopy/postproc/centerout.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/aopy/postproc/centerout.py b/aopy/postproc/centerout.py index d9f568b0..b3e1fde3 100644 --- a/aopy/postproc/centerout.py +++ b/aopy/postproc/centerout.py @@ -141,7 +141,7 @@ def get_taskspace_and_nullspace(mapping, task='2DCenterOut'): n_a (3 x 3 numpy array): Matrix that projects hand movement into the null space ''' if task == '2DCenterOut': - a = mapping[[0,2], :] # rows are cursor and columns are hand + a = mapping[[0,2], :] # rows are cursor and columns are hand. taking only hy and hz components of optitrack that correspond to up/down and right/left elif task == '1DTracking': a = mapping[2,:] @@ -155,7 +155,7 @@ def decompose_hand_movements(hand_data, mapping): ''' Decomposes hand movement into components of movement in the plane of the screen and out of the plane of the screen Args: - hand_data (2D numpy array): 3D array of hand trajectory data (n_timepoints x 3) + hand_data (2D numpy array): 3D array of hand trajectory per trial (n_timepoints x 3) in optitrack space. X - forward/back, Y - up/down, Z - right/left mapping (3 x 3 numpy array): Mapping matrix used in experiment. See :func:`get_mapping` for more details . Rows must be cursor and columns must be hand. Returns: @@ -163,10 +163,11 @@ def decompose_hand_movements(hand_data, mapping): ''' t_a, n_a = get_taskspace_and_nullspace(mapping) hand_data = np.array(hand_data) + hT = np.dot(t_a, hand_data.T) # 3x2400 hN = np.dot(n_a, hand_data.T) - hT_norm = np.mean(np.linalg.norm(hT, axis=0)) - hN_norm = np.mean(np.linalg.norm(hN, axis=0)) + hT_norm = np.mean(np.linalg.norm(hT, axis=0)) # gives the magnitude of movement in task space + hN_norm = np.mean(np.linalg.norm(hN, axis=0)) # gives the magnitude of movement in null space - return hT_norm, hN_norm \ No newline at end of file + return hT_norm, hN_norm From 002d2edce7020389cab49df612273eb963632f81 Mon Sep 17 00:00:00 2001 From: Katherine Date: Thu, 31 Aug 2023 17:23:33 -0700 Subject: [PATCH 3/7] update mapping & movement decomposition functions --- aopy/postproc/centerout.py | 65 ++++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 31 deletions(-) diff --git a/aopy/postproc/centerout.py b/aopy/postproc/centerout.py index b3e1fde3..f5462ce3 100644 --- a/aopy/postproc/centerout.py +++ b/aopy/postproc/centerout.py @@ -63,37 +63,40 @@ )) def _get_mapping(exp_metadata): + ''' + Returns a mapping A that transforms centered hand coordinates to cursor coordinates through c=A*h + + Hand coordinates ordered [hx hy hz] where hx: forward/backward, hy: up/down, hz: right/left + Cursor coordinates ordered [cx cz cy] where cx: right/left, cz: in/out of screen, cy: up/down (same order as exp_data['task']['cursor']) + + Hand coordinates are centered about the hand space origin (i.e. offset already applied) ''' - Returns transformed coordinates based on rotation, offset, and scale traits - Args: - exp_metadata: exp_metadata from load_preproc_exp_data(preproc_dir, subject, te_id, date) - - Returns: - mapping (3 x 3 numpy array): mapping of hand to cursor data used - ''' - offset = exp_metadata['offset'] - offset_arr = np.array( - [[1, 0, 0, 0], - [0, 1, 0, 0], - [0, 0, 1, 0], - [offset[0], offset[1], offset[2], 1]] - ) scale = exp_metadata['scale'] scale_arr = np.array( - [[scale, 0, 0, 0], - [0, scale, 0, 0], - [0, 0, scale, 0], + [[scale, 0, 0, 0], + [0, scale, 0, 0], + [0, 0, scale, 0], [0, 0, 0, 1]] ) - rotation = exp_metadata['rotation'] # optitrack -> screen space -# print(rotation) - exp_rotation = exp_metadata['exp_rotation'] # out of plane perturbations applied in screen space - x - right, y - towards monkey, z - up - perturbation = exp_metadata['pertubation_rotation'] # in plane perturbations applied in screen space about y axis so rotation is inplane - new_plane = np.linalg.multi_dot((offset_arr, scale_arr, rotations[rotation], exp_rotations[exp_rotation])) # multi dot product of 4 x 4 matrices - pertubation_rot = R.from_euler('y', perturbation, degrees=True) - mapping = np.matmul(pertubation_rot.as_matrix(), new_plane[0:3]) + rotation = exp_metadata['rotation'] # optitrack (x: forward/backward, y: up/down, z: right/left) --> screen space (x: right/left, y: forward/backward, z: up/down) + exp_rotation = exp_metadata['exp_rotation'] # out of plane perturbations applied in screen space + + if 'incremental_rotation' not in [feature.decode("utf-8") for feature in exp_metadata['features']]: + perturbation = exp_metadata['pertubation_rotation'] # in plane perturbations applied in screen space, about bmi3d y-axis (in/out of screen) + perturbation_rotation = R.from_euler('y', perturbation, degrees=True).as_matrix() + mapping = np.linalg.multi_dot((scale_arr[:3,:3], rotations[rotation][:3,:3], exp_rotations[exp_rotation][:3,:3], perturbation_rotation)).T # mapping from *centered* hand coords --> cursor coords + else: + mapping = [] + start = exp_metadata['init_rotation_y'] + stop = exp_metadata['final_rotation_y'] + step = exp_metadata['delta_rotation_y'] + for perturbation in np.arange(start, stop+step, step): + perturbation_rotation = R.from_euler('y', perturbation, degrees=True).as_matrix() + mapping.append(np.linalg.multi_dot((scale_arr[:3,:3], rotations[rotation][:3,:3], exp_rotations[exp_rotation][:3,:3], perturbation_rotation)).T) # mapping from *centered* hand coords --> cursor coords + return mapping + def _transform_coords(hand_data, exp_metadata): ''' Transforms hand data into mapping used in center out experiment @@ -141,9 +144,9 @@ def get_taskspace_and_nullspace(mapping, task='2DCenterOut'): n_a (3 x 3 numpy array): Matrix that projects hand movement into the null space ''' if task == '2DCenterOut': - a = mapping[[0,2], :] # rows are cursor and columns are hand. taking only hy and hz components of optitrack that correspond to up/down and right/left + a = mapping[[0,2], :] # rows are cursor and columns are hand. taking only hand components that correspond to cursor up/down and right/left elif task == '1DTracking': - a = mapping[2,:] + a = mapping[2,:].reshape(1,3) # rows are cursor and columns are hand. taking only hand components that correspond to cursor up/down a_plus = a.T @ np.linalg.pinv(a @ a.T) t_a = a_plus @ a @@ -151,23 +154,23 @@ def get_taskspace_and_nullspace(mapping, task='2DCenterOut'): return t_a, n_a -def decompose_hand_movements(hand_data, mapping): +def decompose_hand_movements(hand_data, mapping, task='2DCenterOut'): ''' Decomposes hand movement into components of movement in the plane of the screen and out of the plane of the screen Args: hand_data (2D numpy array): 3D array of hand trajectory per trial (n_timepoints x 3) in optitrack space. X - forward/back, Y - up/down, Z - right/left - mapping (3 x 3 numpy array): Mapping matrix used in experiment. See :func:`get_mapping` for more details . Rows must be cursor and columns must be hand. + mapping (3 x 3 numpy array): Mapping matrix used in experiment. See :func:`_get_mapping` for more details . Rows must be cursor and columns must be hand. Returns: ''' - t_a, n_a = get_taskspace_and_nullspace(mapping) + t_a, n_a = get_taskspace_and_nullspace(mapping, task) hand_data = np.array(hand_data) - hT = np.dot(t_a, hand_data.T) # 3x2400 + hT = np.dot(t_a, hand_data.T) # 3 x n_timepoints hN = np.dot(n_a, hand_data.T) hT_norm = np.mean(np.linalg.norm(hT, axis=0)) # gives the magnitude of movement in task space hN_norm = np.mean(np.linalg.norm(hN, axis=0)) # gives the magnitude of movement in null space - return hT_norm, hN_norm + return hT_norm, hN_norm From a72174bdcd1ed908467fd000a6568b25f5d73657 Mon Sep 17 00:00:00 2001 From: pavi Date: Thu, 7 Sep 2023 17:46:36 -0700 Subject: [PATCH 4/7] functions to get mapping and hand movement decompositions. --- aopy/postproc/centerout.py | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/aopy/postproc/centerout.py b/aopy/postproc/centerout.py index f5462ce3..7edde365 100644 --- a/aopy/postproc/centerout.py +++ b/aopy/postproc/centerout.py @@ -63,19 +63,26 @@ )) def _get_mapping(exp_metadata): - ''' + ''' Returns a mapping A that transforms centered hand coordinates to cursor coordinates through c=A*h - + Hand coordinates ordered [hx hy hz] where hx: forward/backward, hy: up/down, hz: right/left Cursor coordinates ordered [cx cz cy] where cx: right/left, cz: in/out of screen, cy: up/down (same order as exp_data['task']['cursor']) - + Hand coordinates are centered about the hand space origin (i.e. offset already applied) ''' + offset = exp_metadata['offset'] + offset_arr = np.array( + [[1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [offset[0], offset[1], offset[2], 1]] + ) scale = exp_metadata['scale'] scale_arr = np.array( - [[scale, 0, 0, 0], - [0, scale, 0, 0], - [0, 0, scale, 0], + [[scale, 0, 0, 0], + [0, scale, 0, 0], + [0, 0, scale, 0], [0, 0, 0, 1]] ) rotation = exp_metadata['rotation'] # optitrack (x: forward/backward, y: up/down, z: right/left) --> screen space (x: right/left, y: forward/backward, z: up/down) @@ -144,9 +151,9 @@ def get_taskspace_and_nullspace(mapping, task='2DCenterOut'): n_a (3 x 3 numpy array): Matrix that projects hand movement into the null space ''' if task == '2DCenterOut': - a = mapping[[0,2], :] # rows are cursor and columns are hand. taking only hand components that correspond to cursor up/down and right/left + a = mapping[[0,2], :] # rows are cursor and columns are hand. taking only hy and hz components of optitrack that correspond to up/down and right/left elif task == '1DTracking': - a = mapping[2,:].reshape(1,3) # rows are cursor and columns are hand. taking only hand components that correspond to cursor up/down + a = mapping[2,:] a_plus = a.T @ np.linalg.pinv(a @ a.T) t_a = a_plus @ a @@ -173,4 +180,4 @@ def decompose_hand_movements(hand_data, mapping, task='2DCenterOut'): hT_norm = np.mean(np.linalg.norm(hT, axis=0)) # gives the magnitude of movement in task space hN_norm = np.mean(np.linalg.norm(hN, axis=0)) # gives the magnitude of movement in null space - return hT_norm, hN_norm + return hT_norm, hN_norm From 73b475a76245f30ead4438c8f17c0f1dbf6feaae Mon Sep 17 00:00:00 2001 From: pavi Date: Tue, 7 May 2024 16:32:36 -0700 Subject: [PATCH 5/7] Added functions for transforming hand and cursor to intuitive coords for plotting --- aopy/postproc/centerout.py | 54 ++++++++++++++++++++- docs/source/_images/MC_coord_defintion.png | Bin 0 -> 66441 bytes 2 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 docs/source/_images/MC_coord_defintion.png diff --git a/aopy/postproc/centerout.py b/aopy/postproc/centerout.py index 7edde365..4c3093a3 100644 --- a/aopy/postproc/centerout.py +++ b/aopy/postproc/centerout.py @@ -108,10 +108,11 @@ def _transform_coords(hand_data, exp_metadata): ''' Transforms hand data into mapping used in center out experiment Args: - hand_traj (2D numpy array): 3D array of hand trajectory data (n_timepoints x 3) + hand_traj (3D numpy array): 3D array of hand trajectory data (n_timepoints x 3) : hand data when output from get_kinematics is in BMI3D coordinates. exp_metadata: exp_metadata from load_preproc_exp_data(preproc_dir, subject, te_id, date) Returns: + transformed_hand_traj (3D numpy array) ''' offset = exp_metadata['offset'] @@ -181,3 +182,54 @@ def decompose_hand_movements(hand_data, mapping, task='2DCenterOut'): hN_norm = np.mean(np.linalg.norm(hN, axis=0)) # gives the magnitude of movement in null space return hT_norm, hN_norm + + +def transform_optitrack2hand_coordinates(o_coords): + """ + Transforms coordinates from the Optitrack coordinates (O) to the intuitive hand coordinates for plotting (H). + + Parameters: + o_coords (numpy array): The original coordinates as a numpy array [Ox, Oy, Oz]. + + :: image:: _images/MC_coord_definition.png + + Returns: + numpy array: The transformed coordinates [Hx, Hy, Hz]. + """ + # Transformation matrix + T = np.array([ + [0, 1, 0], + [0, 0, 1], + [1, 0, 0] + ]) + + # Perform the matrix multiplication + h_coords = T.dot(o_coords) + + return h_coords + + +def transform_bmi3dscreen2cursor_coordinates(b_coords): + """ + Transforms coordinates from the BMI3d screen coordinates (B) to the intuitive cursor coordinates for plotting (H). + Note: Get kinematics functions output hand kinematics in optitrack coordinates & cursor kinematics in bmi3d coordinates + + :: image:: _images/MC_coord_definition.png + + Parameters: + b_coords (numpy array): The original coordinates as a numpy array [Bx, By, Bz]. + + Returns: + numpy array: The transformed coordinates [Cx, Cy, Cz]. + """ + # Transformation matrix + T = np.array([ + [1, 0, 0], + [0, 0, 1], + [0, 1, 0] + ]) + + # Perform the matrix multiplication + c_coords = T.dot(b_coords) + + return c_coords diff --git a/docs/source/_images/MC_coord_defintion.png b/docs/source/_images/MC_coord_defintion.png new file mode 100644 index 0000000000000000000000000000000000000000..aaf6343dad34f975cc030dc9b63a0c6dd2a77f41 GIT binary patch literal 66441 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 Date: Tue, 7 May 2024 16:39:09 -0700 Subject: [PATCH 6/7] test function for centerout.py --- aopy/postproc/centerout.py | 4 ++-- tests/test_postproc.py | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/aopy/postproc/centerout.py b/aopy/postproc/centerout.py index 4c3093a3..9377b949 100644 --- a/aopy/postproc/centerout.py +++ b/aopy/postproc/centerout.py @@ -188,11 +188,11 @@ def transform_optitrack2hand_coordinates(o_coords): """ Transforms coordinates from the Optitrack coordinates (O) to the intuitive hand coordinates for plotting (H). + :: image:: _images/MC_coord_definition.png + Parameters: o_coords (numpy array): The original coordinates as a numpy array [Ox, Oy, Oz]. - :: image:: _images/MC_coord_definition.png - Returns: numpy array: The transformed coordinates [Hx, Hy, Hz]. """ diff --git a/tests/test_postproc.py b/tests/test_postproc.py index 3537c459..66c9e7ed 100644 --- a/tests/test_postproc.py +++ b/tests/test_postproc.py @@ -248,5 +248,10 @@ def test_get_calibrated_eye_data(self): calibrated = get_calibrated_eye_data(eye_data, coefficients) np.testing.assert_array_equal(eye_data, calibrated) +class TestCenterout(unittest.TestCase): + + def test_get_mapping(self): + + if __name__ == "__main__": unittest.main() From 768630e0b0ddd44e7de51d464e3d0b31dae4d18f Mon Sep 17 00:00:00 2001 From: pavi Date: Tue, 18 Jun 2024 14:22:06 -0700 Subject: [PATCH 7/7] added test_functions for coordinate transformations --- aopy/postproc/centerout.py | 28 ++++++++++-------- .../_images/cursor_data_coordinates.png | Bin 0 -> 15504 bytes docs/source/_images/hand_data_coordinates.png | Bin 0 -> 20277 bytes tests/test_postproc.py | 21 ++++++++++++- 4 files changed, 35 insertions(+), 14 deletions(-) create mode 100644 docs/source/_images/cursor_data_coordinates.png create mode 100644 docs/source/_images/hand_data_coordinates.png diff --git a/aopy/postproc/centerout.py b/aopy/postproc/centerout.py index 9377b949..2f14a003 100644 --- a/aopy/postproc/centerout.py +++ b/aopy/postproc/centerout.py @@ -71,6 +71,7 @@ def _get_mapping(exp_metadata): Hand coordinates are centered about the hand space origin (i.e. offset already applied) ''' + offset = exp_metadata['offset'] offset_arr = np.array( [[1, 0, 0, 0], @@ -105,7 +106,7 @@ def _get_mapping(exp_metadata): def _transform_coords(hand_data, exp_metadata): - ''' + ''' Transforms hand data into mapping used in center out experiment Args: hand_traj (3D numpy array): 3D array of hand trajectory data (n_timepoints x 3) : hand data when output from get_kinematics is in BMI3D coordinates. @@ -114,7 +115,7 @@ def _transform_coords(hand_data, exp_metadata): Returns: transformed_hand_traj (3D numpy array) - ''' + ''' offset = exp_metadata['offset'] offset_arr = np.array( [[1, 0, 0, 0], @@ -188,23 +189,24 @@ def transform_optitrack2hand_coordinates(o_coords): """ Transforms coordinates from the Optitrack coordinates (O) to the intuitive hand coordinates for plotting (H). - :: image:: _images/MC_coord_definition.png - Parameters: - o_coords (numpy array): The original coordinates as a numpy array [Ox, Oy, Oz]. + o_coords (numpy array): Optitrack data in Optitrack coordinates [Ox, Oy, Oz] as a numpy array (n_timepoints x 3). Returns: numpy array: The transformed coordinates [Hx, Hy, Hz]. + + .. image:: _images/hand_data_coordinates.png + """ # Transformation matrix T = np.array([ - [0, 1, 0], [0, 0, 1], + [0, 1, 0], [1, 0, 0] ]) # Perform the matrix multiplication - h_coords = T.dot(o_coords) + h_coords = o_coords.dot(T) return h_coords @@ -213,14 +215,14 @@ def transform_bmi3dscreen2cursor_coordinates(b_coords): """ Transforms coordinates from the BMI3d screen coordinates (B) to the intuitive cursor coordinates for plotting (H). Note: Get kinematics functions output hand kinematics in optitrack coordinates & cursor kinematics in bmi3d coordinates - - :: image:: _images/MC_coord_definition.png - Parameters: - b_coords (numpy array): The original coordinates as a numpy array [Bx, By, Bz]. + b_coords (numpy array): cursor data in BMI3d screen coordinates [Bx, By, Bz] as a numpy array (n_timepoints x 3). Returns: numpy array: The transformed coordinates [Cx, Cy, Cz]. + + .. image:: _images/cursor_data_coordinates.png + """ # Transformation matrix T = np.array([ @@ -230,6 +232,6 @@ def transform_bmi3dscreen2cursor_coordinates(b_coords): ]) # Perform the matrix multiplication - c_coords = T.dot(b_coords) + c_coords = b_coords.dot(T) - return c_coords + return c_coords \ No newline at end of file diff --git a/docs/source/_images/cursor_data_coordinates.png b/docs/source/_images/cursor_data_coordinates.png new file mode 100644 index 0000000000000000000000000000000000000000..44b9eff86583506a5119823caa1bd6986d1c9496 GIT binary patch literal 15504 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 literal 0 HcmV?d00001 diff --git a/docs/source/_images/hand_data_coordinates.png b/docs/source/_images/hand_data_coordinates.png new file mode 100644 index 0000000000000000000000000000000000000000..464eb5728c5bc272c42bee960830cf6c5d77546a GIT binary patch literal 20277 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 literal 0 HcmV?d00001 diff --git a/tests/test_postproc.py b/tests/test_postproc.py index 66c9e7ed..1f669efc 100644 --- a/tests/test_postproc.py +++ b/tests/test_postproc.py @@ -1,4 +1,5 @@ from aopy.postproc import * +from aopy.postproc.centerout import * import aopy import numpy as np import warnings @@ -250,7 +251,25 @@ def test_get_calibrated_eye_data(self): class TestCenterout(unittest.TestCase): - def test_get_mapping(self): + def test_transform_optitrack2hand_coordinates(self): + o_coords = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) + expected_h_coords = np.array([[3, 2, 1], [6, 5, 4], [9, 8, 7]]) + np.testing.assert_array_equal(transform_optitrack2hand_coordinates(o_coords), expected_h_coords) + + def test_transform_optitrack2hand_coordinates_single_point(self): + o_coords = np.array([[0, 1, 2]]) + expected_h_coords = np.array([[2, 1, 0]]) + np.testing.assert_array_equal(transform_optitrack2hand_coordinates(o_coords), expected_h_coords) + + def test_transform_bmi3dscreen2cursor_coordinates(self): + b_coords = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) + expected_c_coords = np.array([[1, 3, 2], [4, 6, 5], [7, 9, 8]]) + np.testing.assert_array_equal(transform_bmi3dscreen2cursor_coordinates(b_coords), expected_c_coords) + + def test_transform_bmi3dscreen2cursor_coordinates_single_point(self): + b_coords = np.array([[1, 0, 2]]) + expected_c_coords = np.array([[1, 2, 0]]) + np.testing.assert_array_equal(transform_bmi3dscreen2cursor_coordinates(b_coords), expected_c_coords) if __name__ == "__main__":