-
Notifications
You must be signed in to change notification settings - Fork 73
feat: compute_kinetic_energy for per-individual KE decomposition (#228) #623
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: compute_kinetic_energy for per-individual KE decomposition (#228) #623
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #623 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 32 33 +1
Lines 1860 1889 +29
=========================================
+ Hits 1860 1889 +29 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
niksirbi
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @vtushar06!
I've left some high-level comments for you to consider. After you've dealt with these we can do another round of review to deal with the details.
This will take some more work and time, but it's an exciting feature I'm looking forward to seeing released.
8861543 to
69e2da2
Compare
|
|
Hi @niksirbi, Please have a look at the latest changes when you get a chance. Happy to refine further if needed. Thanks! |
|
Hii @niksirbi, |
|
Thanks for the reminder @vtushar06 and for keeping the momentum going. PR #634 has to wait till the 2nd half of August I'm afraid. The whole of the core maintainer team will be pre-occupied with teaching till then. |
|
Thanks @niksirbi! Appreciate the update. I’ll be ready for any further feedback whenever you get a chance. |
niksirbi
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for your patience @vtushar06.
I finally had a chance to go through it properly and also discussed it with @sfmig. Our conversations led us to a few overall points, which I’ll summarise here. These differ somewhat from what was outlined in the original issue #228 — but that’s often the case. Having a concrete implementation to look at helped us think more clearly about the problem, so thank you for providing that.
In addition to these main points, I’ve also left some inline comments on specific parts of the code, with concrete suggestions for implementation.
- Correction to translational kinetic energy. There’s an error in how translational kinetic energy is computed. At the moment you use
K_trans = 0.5 * compute_norm(v_cm) ** 2but this expression also needs to be multiplied by the individual’s total mass (weights.sum). See below for the correct math. The error stems from a mistake in the formula I had originally supplied in issue #228 — apologies for that. I realised the error while running tests: I was getting a non-zero "rotational" kinetic energy onvalid_poses_dataset(without any modifications), which shouldn’t be happening. With this correction, the tests can also be simplified (see my inline comments). - Renaming the "rotational" component. Sofía and I agreed that “rotational” isn’t quite the right term here. Since the animals aren’t rigid bodies, inter-keypoint distances aren’t fixed, and motions such as scaling and shearing also contribute to the non-translational kinetic energy. I suggest renaming this component from rotational to internal, meaning any motion relative to the individual’s centre of mass.
- Default behaviour of
compute_kinetic_energy. Since many users may not need the decomposition, it might make sense forcompute_kinetic_energyto return the total kinetic energy by default. We could add a boolean argumentdecompose=Falseso that, if set toTrue, the function returns both translational and internal components.
Finally, because the maths here tripped me up at first (and could do the same for users), I recommend adding the explicit formulas in a "Notes" section of the docstring. I’ve drafted a version you can adapt, which I’ve included below. Note that I use T to denote kinetic energy in the formulas, as is common in Physics.
Click to show source code
Notes
-----
Considering a given individual at time point :math:`t` as a system of
keypoint particles, its total kinetic energy :math:`T_{total}` is given by:
.. math:: T_{total} = \sum_{i} \frac{1}{2} m_i \| \mathbf{v}_i(t) \|^2
where :math:`m_i` is the mass of the :math:`i`-th keypoint and
:math:`\mathbf{v}_i(t)` is its velocity at time :math:`t`.
From Samuel König's second theorem, we can decompose :math:`T_{total}`
into:
- Translational kinetic energy: the kinetic energy of the individual's
total mass :math:`M` moving with the centre of mass velocity;
- Internal kinetic energy: the kinetic energy of the keypoints moving
relative to the individual's centre of mass.
We compute translational kinetic energy :math:`T_{trans}` as follows:
.. math:: T_{trans} = \frac{1}{2} M \| \mathbf{v}_{cm}(t) \|^2
where :math:`M = \sum_{i} m_i` is the total mass of the individual
and :math:`\mathbf{v}_{cm}(t) = \frac{1}{M} \sum_{i} m_i \mathbf{v}_i(t)`
is the velocity of the centre of mass at time :math:`t`
(computed as the weighted mean of keypoint velocities).
Internal kinetic energy :math:`T_{int}` is derived as the difference
between the total and translational components:
.. math:: T_{int} = T_{total} - T_{trans}
|
Hi @niksirbi, I have updated my pr as per yours guidance and requirement, can you please have a look on this. |
niksirbi
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @vtushar06!
Only some minor changes remain to be made, so I'l already approve this PR.
Basically you need to edit the movement/kinematics/__init__.py file and make the suggested changes in the docstring examples (see my inline comments).
Other than these, it's good to go.
d4fd6c7 to
b3a4f32
Compare
|
|
It all looks good now 🎉 I've rebased to the |
04c5948
|
That's fantastic news 🎉🎉! Thank you so much, @niksirbi. I really appreciate you taking the time to guide me through this. Your detailed feedback and patience were incredibly helpful, and the feature is much better because of it. I learned a ton in the process. I'm so excited to see this included in the next release! Looking forward to finding another issue to contribute to soon. 🎉 |





Description
What is this PR
Why is this PR needed?
This PR introduces a new utility function,
compute_kinetic_energy, for decomposing kinetic energy into translational and rotational components for each individual. This is based on the enhancement request raised in Issue #228 by @niksirbi. It improves the analytical capabilities of themovementlibrary and sets the foundation for further physics-based behavioral analysis.What does this PR do?
• Adds the function compute_kinetic_energy() to movement/kinematics/kinetic_energy.py
• Supports optional keypoint selection and custom mass dictionaries
• Handles both "xy" and "space" dimension naming conventions in the velocity input
• Returns an xarray with dimensions (time, individuals, energy) and coordinates ["translational", "rotational"]
• Adds a test case test_kinetic_energy_basic() to validate functionality
• Ensures full compatibility with pre-commit hooks and project linting standards (ruff, mypy)
References
Fixes: #228
How has this PR been tested?
✅ Added a dedicated unit test in tests/test_unit/test_kinematics/test_kinetic_energy.py
✅ Used simulated velocity input to verify correctness of translational and rotational KE outputs
✅ Ran all tests with pytest, all passed
✅ Passed all pre-commit checks including docstring rules, formatting, type checks, and linting
Is this a breaking change?
N/A
If this PR breaks any existing functionality, please explain how and why.
Does this PR require an update to the documentation?
Function includes a detailed docstring explaining usage, input format, and output structure.
Checklist: