kinemotion 0.26.0__tar.gz → 0.27.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of kinemotion might be problematic. Click here for more details.

Files changed (215) hide show
  1. {kinemotion-0.26.0 → kinemotion-0.27.0}/CHANGELOG.md +16 -0
  2. {kinemotion-0.26.0 → kinemotion-0.27.0}/PKG-INFO +1 -1
  3. {kinemotion-0.26.0 → kinemotion-0.27.0}/pyproject.toml +1 -1
  4. {kinemotion-0.26.0 → kinemotion-0.27.0}/src/kinemotion/api.py +17 -9
  5. {kinemotion-0.26.0 → kinemotion-0.27.0}/src/kinemotion/core/video_io.py +6 -0
  6. {kinemotion-0.26.0 → kinemotion-0.27.0}/src/kinemotion/dropjump/analysis.py +92 -34
  7. kinemotion-0.27.0/tests/test_video_io.py +114 -0
  8. {kinemotion-0.26.0 → kinemotion-0.27.0}/uv.lock +1 -1
  9. {kinemotion-0.26.0 → kinemotion-0.27.0}/.dockerignore +0 -0
  10. {kinemotion-0.26.0 → kinemotion-0.27.0}/.gitattributes +0 -0
  11. {kinemotion-0.26.0 → kinemotion-0.27.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  12. {kinemotion-0.26.0 → kinemotion-0.27.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  13. {kinemotion-0.26.0 → kinemotion-0.27.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  14. {kinemotion-0.26.0 → kinemotion-0.27.0}/.github/pull_request_template.md +0 -0
  15. {kinemotion-0.26.0 → kinemotion-0.27.0}/.github/workflows/docs.yml +0 -0
  16. {kinemotion-0.26.0 → kinemotion-0.27.0}/.github/workflows/release.yml +0 -0
  17. {kinemotion-0.26.0 → kinemotion-0.27.0}/.github/workflows/test.yml +0 -0
  18. {kinemotion-0.26.0 → kinemotion-0.27.0}/.gitignore +0 -0
  19. {kinemotion-0.26.0 → kinemotion-0.27.0}/.pre-commit-config.yaml +0 -0
  20. {kinemotion-0.26.0 → kinemotion-0.27.0}/.readthedocs.yml +0 -0
  21. {kinemotion-0.26.0 → kinemotion-0.27.0}/.tool-versions +0 -0
  22. {kinemotion-0.26.0 → kinemotion-0.27.0}/CLAUDE.md +0 -0
  23. {kinemotion-0.26.0 → kinemotion-0.27.0}/CODE_OF_CONDUCT.md +0 -0
  24. {kinemotion-0.26.0 → kinemotion-0.27.0}/CONTRIBUTING.md +0 -0
  25. {kinemotion-0.26.0 → kinemotion-0.27.0}/Dockerfile +0 -0
  26. {kinemotion-0.26.0 → kinemotion-0.27.0}/GEMINI.md +0 -0
  27. {kinemotion-0.26.0 → kinemotion-0.27.0}/LICENSE +0 -0
  28. {kinemotion-0.26.0 → kinemotion-0.27.0}/README.md +0 -0
  29. {kinemotion-0.26.0 → kinemotion-0.27.0}/SECURITY.md +0 -0
  30. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/README.md +0 -0
  31. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/api/cmj.md +0 -0
  32. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/api/core.md +0 -0
  33. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/api/dropjump.md +0 -0
  34. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/api/overview.md +0 -0
  35. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/development/errors-findings.md +0 -0
  36. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/development/testing.md +0 -0
  37. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/development/type-hints.md +0 -0
  38. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/development/validation-plan.md +0 -0
  39. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/development/validation-roadmap.md +0 -0
  40. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/development/wallball-norep-detection.md +0 -0
  41. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/guides/bulk-processing.md +0 -0
  42. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/guides/camera-setup.md +0 -0
  43. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/guides/cmj-guide.md +0 -0
  44. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/index.md +0 -0
  45. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/reference/json-output-format.md +0 -0
  46. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/reference/json-structure-comparison.md +0 -0
  47. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/reference/parameters.md +0 -0
  48. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/reference/pose-systems.md +0 -0
  49. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/paper-downloader/HOW-TO-FIND-DOIS.md +0 -0
  50. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/paper-downloader/README.md +0 -0
  51. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/paper-downloader/dois.txt +0 -0
  52. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/paper-downloader/download.py +0 -0
  53. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/paper-downloader/pyproject.toml +0 -0
  54. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/paper-downloader/uv.lock +0 -0
  55. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/sports-biomechanics-pose-estimation.md +0 -0
  56. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/MANUAL-DOWNLOAD-GUIDE.md +0 -0
  57. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/README.md +0 -0
  58. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/convert_pdfs.py +0 -0
  59. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/markdown/athlete-monitoring/2001_Foster_Session-RPE-Training-Monitoring.md +0 -0
  60. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/markdown/athlete-monitoring/2015_Buchheit_GPS-Accelerometers-Stride-Stiffness.md +0 -0
  61. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/markdown/athlete-monitoring/2018_Flatt_HRV-Recovery-Swimmers.md +0 -0
  62. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/markdown/athlete-monitoring/2018_Saw_Training-Camps-Monitoring.md +0 -0
  63. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/markdown/athlete-monitoring/2018_Ward_Putting-i-in-Team.md +0 -0
  64. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/markdown/injury-prevention/2011_Petersen_Nordic-Hamstring-Prevention.md +0 -0
  65. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/markdown/injury-prevention/2011_Wilk_Shoulder-GIRD-Baseball-Pitchers.md +0 -0
  66. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/markdown/injury-prevention/2012_Hewit_Multidirectional-Leg-Asymmetry.md +0 -0
  67. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/markdown/injury-prevention/2015_Ford_Hip-Neuromuscular-Exercise-Valgus.md +0 -0
  68. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/markdown/injury-prevention/2015_Mosler_Hip-Groin-Pain-Factors.md +0 -0
  69. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/markdown/injury-prevention/2015_Sconce_Nordic-Hamstring-Validity.md +0 -0
  70. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/markdown/injury-prevention/2016_Mendez-Villanueva_Hamstring-MRI-Regional.md +0 -0
  71. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/markdown/injury-prevention/2016_Read_Youth-Soccer-Injury-Risk.md +0 -0
  72. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/markdown/injury-prevention/2017_Mason-Mackay_Ankle-Dorsiflexion-Landing.md +0 -0
  73. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/markdown/injury-prevention/2017_Mendiguchia_Hamstring-Treatment-Algorithm.md +0 -0
  74. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/markdown/injury-prevention/2018_Balsalobre-Fernandez_Ankle-Dorsiflexion-App.md +0 -0
  75. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/markdown/injury-prevention/2018_Bramah_Pathological-Gait-Running-Injuries.md +0 -0
  76. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/markdown/injury-prevention/2020_Fidai_Fatigue-Knee-Valgus-Youth.md +0 -0
  77. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/markdown/jump-performance/2011_Harper_10-to-5-Jump-Test.md +0 -0
  78. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/markdown/jump-performance/2012_Samozino_Optimal-Force-Velocity-Profile.md +0 -0
  79. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/markdown/jump-performance/2014_Samozino_FV-Imbalance.md +0 -0
  80. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/markdown/jump-performance/2016_Jimenez-Reyes_Force-Velocity-Training.md +0 -0
  81. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/markdown/jump-performance/2016_Morin-Samozino_Power-Force-Velocity-Profiles.md +0 -0
  82. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/markdown/jump-performance/2018_Garcia-Ramos_Two-Point-Method-Optimization.md +0 -0
  83. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/markdown/jump-performance/2022_Wells_Golf-Clubhead-CMJ.md +0 -0
  84. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/markdown/running-biomechanics/2005_Morin_Running-Stiffness-Measurement.md +0 -0
  85. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/markdown/running-biomechanics/2015_Balsalobre-Fernandez_Strength-Training-Running-Economy.md +0 -0
  86. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/markdown/running-biomechanics/2016_Balsalobre-Fernandez_iPhone-Running-Mechanics.md +0 -0
  87. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/markdown/running-biomechanics/2016_Moore_Economical-Running-Technique.md +0 -0
  88. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/markdown/running-biomechanics/2020_Filter_Curve-Sprint-Test-Soccer.md +0 -0
  89. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/markdown/running-biomechanics/2020_Harper_Horizontal-Deceleration-Radar.md +0 -0
  90. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/markdown/running-biomechanics/2021_vanOeveren_Running-Biomechanics-Synthesis.md +0 -0
  91. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/markdown/running-biomechanics/2024_Bramah_Sprint-Mechanics-Assessment-Score.md +0 -0
  92. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/markdown/smartphone-technology/2015_Balsalobre-Fernandez_iPhone-Vertical-Jump.md +0 -0
  93. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/markdown/smartphone-technology/2022_Bishop_MyJumpLab-Validation.md +0 -0
  94. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/markdown/velocity-based-training/2011_Jidovtseff_Load-Velocity-1RM-Prediction.md +0 -0
  95. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/markdown/velocity-based-training/2016_Conceicao_Movement-Velocity-Lower-Limb.md +0 -0
  96. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/markdown/velocity-based-training/2016_Pareja-Blanco_Velocity-Loss-Training.md +0 -0
  97. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/markdown/velocity-based-training/2017_Balsalobre-Fernandez_Barbell-Velocity-1RM.md +0 -0
  98. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/markdown/velocity-based-training/2020_Balsalobre-Fernandez_Barbell-Trajectory-Snatch.md +0 -0
  99. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/markdown/velocity-based-training/2023_Balsalobre-Fernandez_AI-Barbell-Velocity.md +0 -0
  100. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/online-references-for-papers.md +0 -0
  101. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/pdfs/athlete-monitoring/2001_Foster_Session-RPE-Training-Monitoring.pdf +0 -0
  102. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/pdfs/athlete-monitoring/2015_Buchheit_GPS-Accelerometers-Stride-Stiffness.pdf +0 -0
  103. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/pdfs/athlete-monitoring/2018_Flatt_HRV-Recovery-Swimmers.pdf +0 -0
  104. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/pdfs/athlete-monitoring/2018_Saw_Training-Camps-Monitoring.pdf +0 -0
  105. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/pdfs/athlete-monitoring/2018_Ward_Putting-i-in-Team.pdf +0 -0
  106. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/pdfs/injury-prevention/2011_Petersen_Nordic-Hamstring-Prevention.pdf +0 -0
  107. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/pdfs/injury-prevention/2011_Wilk_Shoulder-GIRD-Baseball-Pitchers.pdf +0 -0
  108. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/pdfs/injury-prevention/2012_Hewit_Multidirectional-Leg-Asymmetry.pdf +0 -0
  109. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/pdfs/injury-prevention/2015_Ford_Hip-Neuromuscular-Exercise-Valgus.pdf +0 -0
  110. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/pdfs/injury-prevention/2015_Mosler_Hip-Groin-Pain-Factors.pdf +0 -0
  111. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/pdfs/injury-prevention/2015_Sconce_Nordic-Hamstring-Validity.pdf +0 -0
  112. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/pdfs/injury-prevention/2016_Mendez-Villanueva_Hamstring-MRI-Regional.pdf +0 -0
  113. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/pdfs/injury-prevention/2016_Read_Youth-Soccer-Injury-Risk.pdf +0 -0
  114. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/pdfs/injury-prevention/2017_Mason-Mackay_Ankle-Dorsiflexion-Landing.pdf +0 -0
  115. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/pdfs/injury-prevention/2017_Mendiguchia_Hamstring-Treatment-Algorithm.pdf +0 -0
  116. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/pdfs/injury-prevention/2018_Balsalobre-Fernandez_Ankle-Dorsiflexion-App.pdf +0 -0
  117. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/pdfs/injury-prevention/2018_Bramah_Pathological-Gait-Running-Injuries.pdf +0 -0
  118. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/pdfs/injury-prevention/2020_Fidai_Fatigue-Knee-Valgus-Youth.pdf +0 -0
  119. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/pdfs/jump-performance/2011_Harper_10-to-5-Jump-Test.pdf +0 -0
  120. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/pdfs/jump-performance/2012_Samozino_Optimal-Force-Velocity-Profile.pdf +0 -0
  121. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/pdfs/jump-performance/2014_Samozino_FV-Imbalance.pdf +0 -0
  122. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/pdfs/jump-performance/2016_Jimenez-Reyes_Force-Velocity-Training.pdf +0 -0
  123. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/pdfs/jump-performance/2016_Morin-Samozino_Power-Force-Velocity-Profiles.pdf +0 -0
  124. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/pdfs/jump-performance/2018_Garcia-Ramos_Two-Point-Method-Optimization.pdf +0 -0
  125. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/pdfs/jump-performance/2022_Wells_Golf-Clubhead-CMJ.pdf +0 -0
  126. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/pdfs/running-biomechanics/2005_Morin_Running-Stiffness-Measurement.pdf +0 -0
  127. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/pdfs/running-biomechanics/2015_Balsalobre-Fernandez_Strength-Training-Running-Economy.pdf +0 -0
  128. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/pdfs/running-biomechanics/2016_Balsalobre-Fernandez_iPhone-Running-Mechanics.pdf +0 -0
  129. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/pdfs/running-biomechanics/2016_Moore_Economical-Running-Technique.pdf +0 -0
  130. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/pdfs/running-biomechanics/2020_Filter_Curve-Sprint-Test-Soccer.pdf +0 -0
  131. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/pdfs/running-biomechanics/2020_Harper_Horizontal-Deceleration-Radar.pdf +0 -0
  132. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/pdfs/running-biomechanics/2021_vanOeveren_Running-Biomechanics-Synthesis.pdf +0 -0
  133. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/pdfs/running-biomechanics/2024_Bramah_Sprint-Mechanics-Assessment-Score.pdf +0 -0
  134. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/pdfs/smartphone-technology/2015_Balsalobre-Fernandez_iPhone-Vertical-Jump.pdf +0 -0
  135. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/pdfs/smartphone-technology/2022_Bishop_MyJumpLab-Validation.pdf +0 -0
  136. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/pdfs/velocity-based-training/2011_Jidovtseff_Load-Velocity-1RM-Prediction.pdf +0 -0
  137. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/pdfs/velocity-based-training/2016_Conceicao_Movement-Velocity-Lower-Limb.pdf +0 -0
  138. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/pdfs/velocity-based-training/2016_Pareja-Blanco_Velocity-Loss-Training.pdf +0 -0
  139. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/pdfs/velocity-based-training/2017_Balsalobre-Fernandez_Barbell-Velocity-1RM.pdf +0 -0
  140. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/pdfs/velocity-based-training/2020_Balsalobre-Fernandez_Barbell-Trajectory-Snatch.pdf +0 -0
  141. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/research/thirdparty/pdfs/velocity-based-training/2023_Balsalobre-Fernandez_AI-Barbell-Velocity.pdf +0 -0
  142. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/technical/framerate.md +0 -0
  143. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/technical/implementation-details.md +0 -0
  144. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/technical/imu-metadata.md +0 -0
  145. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/technical/real-time-analysis.md +0 -0
  146. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/technical/triple-extension.md +0 -0
  147. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/translations/es/camera-setup.md +0 -0
  148. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/validation/determinism-test.md +0 -0
  149. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/validation/known-height-validation.md +0 -0
  150. {kinemotion-0.26.0 → kinemotion-0.27.0}/docs/validation-status.md +0 -0
  151. {kinemotion-0.26.0 → kinemotion-0.27.0}/examples/bulk/README.md +0 -0
  152. {kinemotion-0.26.0 → kinemotion-0.27.0}/examples/bulk/bulk_processing.py +0 -0
  153. {kinemotion-0.26.0 → kinemotion-0.27.0}/examples/bulk/simple_example.py +0 -0
  154. {kinemotion-0.26.0 → kinemotion-0.27.0}/examples/programmatic_usage.py +0 -0
  155. {kinemotion-0.26.0 → kinemotion-0.27.0}/mkdocs.yml +0 -0
  156. {kinemotion-0.26.0 → kinemotion-0.27.0}/presentation/.gitignore +0 -0
  157. {kinemotion-0.26.0 → kinemotion-0.27.0}/presentation/README.md +0 -0
  158. {kinemotion-0.26.0 → kinemotion-0.27.0}/presentation/demos/.gitignore +0 -0
  159. {kinemotion-0.26.0 → kinemotion-0.27.0}/presentation/demos/README.md +0 -0
  160. {kinemotion-0.26.0 → kinemotion-0.27.0}/presentation/demos/api_demo.ipynb +0 -0
  161. {kinemotion-0.26.0 → kinemotion-0.27.0}/presentation/demos/batch_processing_demo.py +0 -0
  162. {kinemotion-0.26.0 → kinemotion-0.27.0}/presentation/demos/sample_data/.gitkeep +0 -0
  163. {kinemotion-0.26.0 → kinemotion-0.27.0}/presentation/presentation_guide.md +0 -0
  164. {kinemotion-0.26.0 → kinemotion-0.27.0}/presentation/revealjs/.gitignore +0 -0
  165. {kinemotion-0.26.0 → kinemotion-0.27.0}/presentation/revealjs/Makefile +0 -0
  166. {kinemotion-0.26.0 → kinemotion-0.27.0}/presentation/revealjs/README.md +0 -0
  167. {kinemotion-0.26.0 → kinemotion-0.27.0}/presentation/revealjs/slides.md +0 -0
  168. {kinemotion-0.26.0 → kinemotion-0.27.0}/presentation/speaker_script.md +0 -0
  169. {kinemotion-0.26.0 → kinemotion-0.27.0}/requirements-docs.txt +0 -0
  170. {kinemotion-0.26.0 → kinemotion-0.27.0}/samples/cmjs/README.md +0 -0
  171. {kinemotion-0.26.0 → kinemotion-0.27.0}/scripts/README.md +0 -0
  172. {kinemotion-0.26.0 → kinemotion-0.27.0}/scripts/analyze_determinism_variance.py +0 -0
  173. {kinemotion-0.26.0 → kinemotion-0.27.0}/scripts/generate_test_data.py +0 -0
  174. {kinemotion-0.26.0 → kinemotion-0.27.0}/scripts/plot_validation_results.py +0 -0
  175. {kinemotion-0.26.0 → kinemotion-0.27.0}/scripts/test_determinism.sh +0 -0
  176. {kinemotion-0.26.0 → kinemotion-0.27.0}/scripts/validate_known_heights.py +0 -0
  177. {kinemotion-0.26.0 → kinemotion-0.27.0}/sonar-project.properties +0 -0
  178. {kinemotion-0.26.0 → kinemotion-0.27.0}/src/kinemotion/__init__.py +0 -0
  179. {kinemotion-0.26.0 → kinemotion-0.27.0}/src/kinemotion/cli.py +0 -0
  180. {kinemotion-0.26.0 → kinemotion-0.27.0}/src/kinemotion/cmj/__init__.py +0 -0
  181. {kinemotion-0.26.0 → kinemotion-0.27.0}/src/kinemotion/cmj/analysis.py +0 -0
  182. {kinemotion-0.26.0 → kinemotion-0.27.0}/src/kinemotion/cmj/cli.py +0 -0
  183. {kinemotion-0.26.0 → kinemotion-0.27.0}/src/kinemotion/cmj/debug_overlay.py +0 -0
  184. {kinemotion-0.26.0 → kinemotion-0.27.0}/src/kinemotion/cmj/joint_angles.py +0 -0
  185. {kinemotion-0.26.0 → kinemotion-0.27.0}/src/kinemotion/cmj/kinematics.py +0 -0
  186. {kinemotion-0.26.0 → kinemotion-0.27.0}/src/kinemotion/core/__init__.py +0 -0
  187. {kinemotion-0.26.0 → kinemotion-0.27.0}/src/kinemotion/core/auto_tuning.py +0 -0
  188. {kinemotion-0.26.0 → kinemotion-0.27.0}/src/kinemotion/core/cli_utils.py +0 -0
  189. {kinemotion-0.26.0 → kinemotion-0.27.0}/src/kinemotion/core/debug_overlay_utils.py +0 -0
  190. {kinemotion-0.26.0 → kinemotion-0.27.0}/src/kinemotion/core/filtering.py +0 -0
  191. {kinemotion-0.26.0 → kinemotion-0.27.0}/src/kinemotion/core/metadata.py +0 -0
  192. {kinemotion-0.26.0 → kinemotion-0.27.0}/src/kinemotion/core/pose.py +0 -0
  193. {kinemotion-0.26.0 → kinemotion-0.27.0}/src/kinemotion/core/quality.py +0 -0
  194. {kinemotion-0.26.0 → kinemotion-0.27.0}/src/kinemotion/core/smoothing.py +0 -0
  195. {kinemotion-0.26.0 → kinemotion-0.27.0}/src/kinemotion/dropjump/__init__.py +0 -0
  196. {kinemotion-0.26.0 → kinemotion-0.27.0}/src/kinemotion/dropjump/cli.py +0 -0
  197. {kinemotion-0.26.0 → kinemotion-0.27.0}/src/kinemotion/dropjump/debug_overlay.py +0 -0
  198. {kinemotion-0.26.0 → kinemotion-0.27.0}/src/kinemotion/dropjump/kinematics.py +0 -0
  199. {kinemotion-0.26.0 → kinemotion-0.27.0}/src/kinemotion/py.typed +0 -0
  200. {kinemotion-0.26.0 → kinemotion-0.27.0}/tests/__init__.py +0 -0
  201. {kinemotion-0.26.0 → kinemotion-0.27.0}/tests/core/test_quality.py +0 -0
  202. {kinemotion-0.26.0 → kinemotion-0.27.0}/tests/test_adaptive_threshold.py +0 -0
  203. {kinemotion-0.26.0 → kinemotion-0.27.0}/tests/test_api.py +0 -0
  204. {kinemotion-0.26.0 → kinemotion-0.27.0}/tests/test_aspect_ratio.py +0 -0
  205. {kinemotion-0.26.0 → kinemotion-0.27.0}/tests/test_cli_cmj.py +0 -0
  206. {kinemotion-0.26.0 → kinemotion-0.27.0}/tests/test_cli_dropjump.py +0 -0
  207. {kinemotion-0.26.0 → kinemotion-0.27.0}/tests/test_cli_imports.py +0 -0
  208. {kinemotion-0.26.0 → kinemotion-0.27.0}/tests/test_cmj_analysis.py +0 -0
  209. {kinemotion-0.26.0 → kinemotion-0.27.0}/tests/test_cmj_kinematics.py +0 -0
  210. {kinemotion-0.26.0 → kinemotion-0.27.0}/tests/test_com_estimation.py +0 -0
  211. {kinemotion-0.26.0 → kinemotion-0.27.0}/tests/test_contact_detection.py +0 -0
  212. {kinemotion-0.26.0 → kinemotion-0.27.0}/tests/test_filtering.py +0 -0
  213. {kinemotion-0.26.0 → kinemotion-0.27.0}/tests/test_joint_angles.py +0 -0
  214. {kinemotion-0.26.0 → kinemotion-0.27.0}/tests/test_kinematics.py +0 -0
  215. {kinemotion-0.26.0 → kinemotion-0.27.0}/tests/test_polyorder.py +0 -0
@@ -7,6 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  <!-- version list -->
9
9
 
10
+ ## v0.27.0 (2025-11-14)
11
+
12
+ ### Features
13
+
14
+ - Extract video codec from metadata
15
+ ([`52c7ff2`](https://github.com/feniix/kinemotion/commit/52c7ff2ee3f6620a5271f670ab60e6bca8bc38fb))
16
+
17
+
18
+ ## v0.26.1 (2025-11-14)
19
+
20
+ ### Bug Fixes
21
+
22
+ - Reduce cognitive complexity in ground contact detection and API
23
+ ([`57f0424`](https://github.com/feniix/kinemotion/commit/57f0424043e4f15540851157220133e7361213a1))
24
+
25
+
10
26
  ## v0.26.0 (2025-11-14)
11
27
 
12
28
  ### Features
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kinemotion
3
- Version: 0.26.0
3
+ Version: 0.27.0
4
4
  Summary: Video-based kinematic analysis for athletic performance
5
5
  Project-URL: Homepage, https://github.com/feniix/kinemotion
6
6
  Project-URL: Repository, https://github.com/feniix/kinemotion
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "kinemotion"
3
- version = "0.26.0"
3
+ version = "0.27.0"
4
4
  description = "Video-based kinematic analysis for athletic performance"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10,<3.13"
@@ -244,6 +244,20 @@ def _apply_smoothing(
244
244
  )
245
245
 
246
246
 
247
+ def _calculate_foot_visibility(frame_landmarks: dict) -> float:
248
+ """Calculate average visibility of foot landmarks.
249
+
250
+ Args:
251
+ frame_landmarks: Dictionary of landmarks for a frame
252
+
253
+ Returns:
254
+ Average visibility value (0-1)
255
+ """
256
+ foot_keys = ["left_ankle", "right_ankle", "left_heel", "right_heel"]
257
+ foot_vis = [frame_landmarks[key][2] for key in foot_keys if key in frame_landmarks]
258
+ return float(np.mean(foot_vis)) if foot_vis else 0.0
259
+
260
+
247
261
  def _extract_vertical_positions(
248
262
  smoothed_landmarks: list,
249
263
  ) -> tuple[np.ndarray, np.ndarray]:
@@ -262,13 +276,7 @@ def _extract_vertical_positions(
262
276
  if frame_landmarks:
263
277
  _, foot_y = compute_average_foot_position(frame_landmarks)
264
278
  position_list.append(foot_y)
265
-
266
- # Average visibility of foot landmarks
267
- foot_vis = []
268
- for key in ["left_ankle", "right_ankle", "left_heel", "right_heel"]:
269
- if key in frame_landmarks:
270
- foot_vis.append(frame_landmarks[key][2])
271
- visibilities_list.append(float(np.mean(foot_vis)) if foot_vis else 0.0)
279
+ visibilities_list.append(_calculate_foot_visibility(frame_landmarks))
272
280
  else:
273
281
  position_list.append(position_list[-1] if position_list else 0.5)
274
282
  visibilities_list.append(0.0)
@@ -524,7 +532,7 @@ def process_dropjump_video(
524
532
  height=video.height,
525
533
  duration_s=video.frame_count / video.fps,
526
534
  frame_count=video.frame_count,
527
- codec=None,
535
+ codec=video.codec,
528
536
  )
529
537
 
530
538
  processing_info = ProcessingInfo(
@@ -965,7 +973,7 @@ def process_cmj_video(
965
973
  height=video.height,
966
974
  duration_s=video.frame_count / video.fps,
967
975
  frame_count=video.frame_count,
968
- codec=None, # TODO: Extract from video metadata if available
976
+ codec=video.codec,
969
977
  )
970
978
 
971
979
  processing_info = ProcessingInfo(
@@ -50,6 +50,9 @@ class VideoProcessor:
50
50
  # OpenCV ignores rotation metadata, so we need to extract and apply it manually
51
51
  self.rotation = 0 # Will be set by _extract_video_metadata()
52
52
 
53
+ # Extract codec information from video metadata
54
+ self.codec: str | None = None # Will be set by _extract_video_metadata()
55
+
53
56
  # Calculate display dimensions considering SAR (Sample Aspect Ratio)
54
57
  # Mobile videos often have non-square pixels encoded in SAR metadata
55
58
  # OpenCV doesn't directly expose SAR, but we need to handle display correctly
@@ -141,6 +144,9 @@ class VideoProcessor:
141
144
 
142
145
  stream = data["streams"][0]
143
146
 
147
+ # Extract codec name (e.g., "h264", "hevc", "vp9")
148
+ self.codec = stream.get("codec_name")
149
+
144
150
  # Extract and parse SAR (Sample Aspect Ratio)
145
151
  sar_str = stream.get("sample_aspect_ratio", "1:1")
146
152
  self._parse_sample_aspect_ratio(sar_str)
@@ -235,6 +235,86 @@ def detect_drop_start(
235
235
  )
236
236
 
237
237
 
238
+ def _filter_stationary_with_visibility(
239
+ is_stationary: np.ndarray,
240
+ visibilities: np.ndarray | None,
241
+ visibility_threshold: float,
242
+ ) -> np.ndarray:
243
+ """Apply visibility filter to stationary flags.
244
+
245
+ Args:
246
+ is_stationary: Boolean array indicating stationary frames
247
+ visibilities: Optional visibility scores for each frame
248
+ visibility_threshold: Minimum visibility to trust landmark
249
+
250
+ Returns:
251
+ Filtered is_stationary array
252
+ """
253
+ if visibilities is not None:
254
+ is_visible = visibilities > visibility_threshold
255
+ return is_stationary & is_visible
256
+ return is_stationary
257
+
258
+
259
+ def _find_contact_frames(
260
+ is_stationary: np.ndarray,
261
+ min_contact_frames: int,
262
+ ) -> set[int]:
263
+ """Find frames with sustained contact using minimum duration filter.
264
+
265
+ Args:
266
+ is_stationary: Boolean array indicating stationary frames
267
+ min_contact_frames: Minimum consecutive frames to confirm contact
268
+
269
+ Returns:
270
+ Set of frame indices that meet minimum contact duration
271
+ """
272
+ contact_frames: set[int] = set()
273
+ current_run = []
274
+
275
+ for i, stationary in enumerate(is_stationary):
276
+ if stationary:
277
+ current_run.append(i)
278
+ else:
279
+ if len(current_run) >= min_contact_frames:
280
+ contact_frames.update(current_run)
281
+ current_run = []
282
+
283
+ # Handle last run
284
+ if len(current_run) >= min_contact_frames:
285
+ contact_frames.update(current_run)
286
+
287
+ return contact_frames
288
+
289
+
290
+ def _assign_contact_states(
291
+ n_frames: int,
292
+ contact_frames: set[int],
293
+ visibilities: np.ndarray | None,
294
+ visibility_threshold: float,
295
+ ) -> list[ContactState]:
296
+ """Assign contact states based on contact frames and visibility.
297
+
298
+ Args:
299
+ n_frames: Total number of frames
300
+ contact_frames: Set of frames with confirmed contact
301
+ visibilities: Optional visibility scores for each frame
302
+ visibility_threshold: Minimum visibility to trust landmark
303
+
304
+ Returns:
305
+ List of ContactState for each frame
306
+ """
307
+ states = []
308
+ for i in range(n_frames):
309
+ if visibilities is not None and visibilities[i] < visibility_threshold:
310
+ states.append(ContactState.UNKNOWN)
311
+ elif i in contact_frames:
312
+ states.append(ContactState.ON_GROUND)
313
+ else:
314
+ states.append(ContactState.IN_AIR)
315
+ return states
316
+
317
+
238
318
  def detect_ground_contact(
239
319
  foot_positions: np.ndarray,
240
320
  velocity_threshold: float = 0.02,
@@ -247,7 +327,7 @@ def detect_ground_contact(
247
327
  """
248
328
  Detect when feet are in contact with ground based on vertical motion.
249
329
 
250
- Uses derivative-based velocity calculation via Savitzky-Golay filter for smooth,
330
+ Uses derivative-based velocity calculation via Savitzky-Goyal filter for smooth,
251
331
  accurate velocity estimates. This is consistent with the velocity calculation used
252
332
  throughout the pipeline for sub-frame interpolation and curvature analysis.
253
333
 
@@ -264,52 +344,30 @@ def detect_ground_contact(
264
344
  List of ContactState for each frame
265
345
  """
266
346
  n_frames = len(foot_positions)
267
- states = [ContactState.UNKNOWN] * n_frames
268
347
 
269
348
  if n_frames < 2:
270
- return states
349
+ return [ContactState.UNKNOWN] * n_frames
271
350
 
272
351
  # Compute vertical velocity using derivative-based method
273
- # This provides smoother, more accurate velocity estimates than frame-to-frame differences
274
- # and is consistent with the velocity calculation used for sub-frame interpolation
275
352
  velocities = compute_velocity_from_derivative(
276
353
  foot_positions, window_length=window_length, polyorder=polyorder
277
354
  )
278
355
 
279
- # Detect potential contact frames based on low velocity
356
+ # Detect stationary frames based on velocity threshold
280
357
  is_stationary = np.abs(velocities) < velocity_threshold
281
358
 
282
359
  # Apply visibility filter
283
- if visibilities is not None:
284
- is_visible = visibilities > visibility_threshold
285
- is_stationary = is_stationary & is_visible
286
-
287
- # Apply minimum contact duration filter
288
- contact_frames = []
289
- current_run = []
290
-
291
- for i, stationary in enumerate(is_stationary):
292
- if stationary:
293
- current_run.append(i)
294
- else:
295
- if len(current_run) >= min_contact_frames:
296
- contact_frames.extend(current_run)
297
- current_run = []
298
-
299
- # Don't forget the last run
300
- if len(current_run) >= min_contact_frames:
301
- contact_frames.extend(current_run)
360
+ is_stationary = _filter_stationary_with_visibility(
361
+ is_stationary, visibilities, visibility_threshold
362
+ )
302
363
 
303
- # Set states
304
- for i in range(n_frames):
305
- if visibilities is not None and visibilities[i] < visibility_threshold:
306
- states[i] = ContactState.UNKNOWN
307
- elif i in contact_frames:
308
- states[i] = ContactState.ON_GROUND
309
- else:
310
- states[i] = ContactState.IN_AIR
364
+ # Find frames with sustained contact
365
+ contact_frames = _find_contact_frames(is_stationary, min_contact_frames)
311
366
 
312
- return states
367
+ # Assign states
368
+ return _assign_contact_states(
369
+ n_frames, contact_frames, visibilities, visibility_threshold
370
+ )
313
371
 
314
372
 
315
373
  def find_contact_phases(
@@ -0,0 +1,114 @@
1
+ """Tests for video I/O functionality including codec extraction."""
2
+
3
+ import tempfile
4
+ from unittest.mock import patch
5
+
6
+ import cv2
7
+ import numpy as np
8
+ import pytest
9
+
10
+ from kinemotion.core.video_io import VideoProcessor
11
+
12
+
13
+ @pytest.fixture
14
+ def test_video_path() -> str:
15
+ """Create a test video file with codec metadata."""
16
+ temp_file = tempfile.NamedTemporaryFile(suffix=".mp4", delete=False)
17
+ temp_path = temp_file.name
18
+ temp_file.close()
19
+
20
+ # Create a simple test video with mp4v codec
21
+ fourcc = cv2.VideoWriter_fourcc(*"mp4v")
22
+ writer = cv2.VideoWriter(temp_path, fourcc, 30.0, (640, 480))
23
+
24
+ # Write 10 frames
25
+ for _ in range(10):
26
+ frame = np.zeros((480, 640, 3), dtype=np.uint8)
27
+ cv2.circle(frame, (320, 240), 50, (255, 255, 255), -1)
28
+ writer.write(frame)
29
+
30
+ writer.release()
31
+ return temp_path
32
+
33
+
34
+ def test_codec_extraction_from_video(test_video_path: str) -> None:
35
+ """Test that codec is extracted from video metadata."""
36
+ video = VideoProcessor(test_video_path)
37
+ try:
38
+ # Codec should be extracted (or None if ffprobe unavailable)
39
+ # We just verify it's either a string or None
40
+ assert video.codec is None or isinstance(video.codec, str)
41
+ finally:
42
+ video.close()
43
+
44
+
45
+ def test_codec_extraction_with_ffprobe_available(test_video_path: str) -> None:
46
+ """Test codec extraction when ffprobe is available."""
47
+ video = VideoProcessor(test_video_path)
48
+ try:
49
+ # If ffprobe is available, codec should be a string like "h264", "hevc", "mpeg4", etc.
50
+ # If ffprobe is not available, it will be None
51
+ if video.codec is not None:
52
+ assert isinstance(video.codec, str)
53
+ # Common codec names
54
+ assert (
55
+ video.codec
56
+ in [
57
+ "h264",
58
+ "hevc",
59
+ "mpeg4",
60
+ "vp8",
61
+ "vp9",
62
+ "av1",
63
+ "mpeg2video",
64
+ "rawvideo",
65
+ "mpeg1video",
66
+ ]
67
+ or len(video.codec) > 0
68
+ )
69
+ finally:
70
+ video.close()
71
+
72
+
73
+ def test_codec_none_on_ffprobe_failure(test_video_path: str) -> None:
74
+ """Test that codec remains None if ffprobe fails or is unavailable."""
75
+ with patch("kinemotion.core.video_io.subprocess.run") as mock_run:
76
+ # Simulate ffprobe not being available (FileNotFoundError)
77
+ mock_run.side_effect = FileNotFoundError("ffprobe not found")
78
+
79
+ video = VideoProcessor(test_video_path)
80
+ try:
81
+ # Codec should remain None when ffprobe is unavailable
82
+ assert video.codec is None
83
+ finally:
84
+ video.close()
85
+
86
+
87
+ def test_video_processor_basic_properties(test_video_path: str) -> None:
88
+ """Test that VideoProcessor initializes all properties including codec."""
89
+ video = VideoProcessor(test_video_path)
90
+ try:
91
+ # Verify all properties are set
92
+ assert video.fps > 0
93
+ assert video.frame_count > 0
94
+ assert video.width > 0
95
+ assert video.height > 0
96
+ assert video.rotation in [0, 90, -90, 180, -180]
97
+ # codec can be None or str
98
+ assert video.codec is None or isinstance(video.codec, str)
99
+ finally:
100
+ video.close()
101
+
102
+
103
+ def test_codec_persists_across_frame_reading(test_video_path: str) -> None:
104
+ """Test that codec property persists after reading frames."""
105
+ video = VideoProcessor(test_video_path)
106
+ try:
107
+ codec_before = video.codec
108
+ # Read a frame
109
+ frame = video.read_frame()
110
+ assert frame is not None
111
+ # Codec should remain unchanged
112
+ assert video.codec == codec_before
113
+ finally:
114
+ video.close()
@@ -700,7 +700,7 @@ wheels = [
700
700
 
701
701
  [[package]]
702
702
  name = "kinemotion"
703
- version = "0.26.0"
703
+ version = "0.27.0"
704
704
  source = { editable = "." }
705
705
  dependencies = [
706
706
  { name = "click" },
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes