feat(vector): add 3D support for coordinate transforms and vector ops#948
Open
khan-u wants to merge 2 commits intoneuroinformatics-unit:mainfrom
Open
feat(vector): add 3D support for coordinate transforms and vector ops#948khan-u wants to merge 2 commits intoneuroinformatics-unit:mainfrom
khan-u wants to merge 2 commits intoneuroinformatics-unit:mainfrom
Conversation
|
khan-u
added a commit
to khan-u/movement
that referenced
this pull request
Apr 4, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Description
Adds 3D Support for Coordinate Transforms & Vector Operations
What is this PR
Why is this PR needed?
The
movementlibrary currently only supports 2D coordinate transforms and vector operations invector.py. To enable 3D motion analysis, the vector utilities need to handle 3D Cartesian, cylindrical, and spherical coordinate systems.What does this PR do?
Extends existing functions and adds new functions in
movement/utils/vector.py:compute_norm["x", "y", "z"]and 3D cylindrical["rho", "phi", "z"]convert_to_unitcart2polpol2cartcart2sph["rho", "azimuth", "elevation"]sph2cart_raise_error_for_invalid_spatial_dim_lengthImplementation details:
cart2pol/pol2cartbefore accessing coords (raisesValueErrorwith clear message)drop=Trueon.sel()calls to avoid retaining scalar coordinatescoords="minimal"inxr.concatforcart2sph/sph2cartto handle coordinate alignment_raise_error_for_invalid_spatial_dim_lengthfor consistent error messagesReferences
How has this PR been tested?
Added 7 new test methods and 2 new fixtures in
tests/test_unit/test_vector.py:New fixtures:
cart_pol_dataset_3d- 3D Cartesian + cylindrical test data (5 points including null vector edge case)cart_sph_dataset- 3D Cartesian + spherical test data (5 points including poles and axis-aligned vectors)New tests:
test_cart2pol_3dtest_pol2cart_3dtest_compute_norm_3dsqrt(x²+y²+z²)for Cartesian,rhofor cylindricaltest_convert_to_unit_3dtest_cart2sphtest_sph2carttest_cart2sph_sph2cart_roundtripExisting 2D tests continue to pass, ensuring no regression.
Is this a breaking change?
No. All existing 2D functionality is preserved. The changes extend the existing functions to accept 3D data while maintaining full backward compatibility with 2D data.
Does this PR require an update to the documentation?
No. API reference is auto-generated from docstrings. The following docstrings have been added/updated:
cart2polandpol2cart: Updated to document both 2D and 3D modes, including:["x", "y"]or["x", "y", "z"])["rho", "phi"]or["rho", "phi", "z"])zpasses through unchanged in 3D modecompute_normandconvert_to_unit: Accept both 2D and 3D implicitly via existingspace/space_poldimension handling (no docstring changes needed)cart2sphandsph2cart(new):rho,azimuth,elevation)See AlsoNext Steps
A subsequent PR (once #875 is merged) can then extend
collective.pyto support 3D polarization by utilizing the new vector utilities.Current state of
collective.py:return_angle: boolandin_degrees: boolparametersmean_angle(2D only, usescompute_signed_angle_2d)zcoordinate (line 55-56: "polarization is computed in the x/y plane")Planned changes:
Update imports - Add
cart2polandcart2sph:Replace
return_angle/in_degreeswithreturn_direction:False(default): return only polarization"unit_vector": also return mean heading/orientation as unit vector"angle_radians": also return angle(s) in radians"angle_degrees": also return angle(s) in degreesUse
cart2pol/cart2sphfor angle conversion (replacescompute_signed_angle_2d):Example API after changes:
Checklist: