opensportslib 0.3.0__tar.gz → 0.3.0.dev1__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.
Files changed (182) hide show
  1. {opensportslib-0.3.0/opensportslib.egg-info → opensportslib-0.3.0.dev1}/PKG-INFO +21 -5
  2. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/README.md +19 -4
  3. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/apis/classification.py +12 -1
  4. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/apis/localization.py +103 -5
  5. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/apis/vqa.py +59 -25
  6. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/configs/default.yaml +1 -1
  7. opensportslib-0.3.0.dev1/opensportslib/configs/localization/h5_header_distance.yaml +93 -0
  8. opensportslib-0.3.0.dev1/opensportslib/configs/localization/h5_header_distance_angle.yaml +93 -0
  9. opensportslib-0.3.0.dev1/opensportslib/configs/localization/h5_header_distance_speed.yaml +93 -0
  10. opensportslib-0.3.0.dev1/opensportslib/configs/localization/h5_header_distance_speed_angle.yaml +93 -0
  11. opensportslib-0.3.0.dev1/opensportslib/configs/localization/h5_header_rule.yaml +99 -0
  12. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/configs/vqa/default.yaml +1 -1
  13. opensportslib-0.3.0.dev1/opensportslib/configs/vqa/qwen3_vl_native.yaml +81 -0
  14. opensportslib-0.3.0.dev1/opensportslib/configs/vqa/qwen_lora.yaml +69 -0
  15. opensportslib-0.3.0.dev1/opensportslib/configs/vqa/qwen_sngar_frames.yaml +133 -0
  16. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/core/config/accessors.py +96 -0
  17. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/core/trainer/classification_trainer.py +12 -2
  18. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/core/trainer/localization_trainer.py +10 -1
  19. opensportslib-0.3.0.dev1/opensportslib/core/trainer/vqa_trainer.py +1726 -0
  20. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/core/utils/load_annotations.py +9 -1
  21. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/datasets/classification_dataset.py +160 -0
  22. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/datasets/localization_dataset.py +8 -0
  23. opensportslib-0.3.0.dev1/opensportslib/datasets/utils/h5_tracking.py +338 -0
  24. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/datasets/vqa_dataset.py +145 -17
  25. opensportslib-0.3.0.dev1/opensportslib/models/base/qwen_vl_native.py +620 -0
  26. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/models/base/qwen_xvars.py +108 -11
  27. opensportslib-0.3.0.dev1/opensportslib/models/base/rule_based.py +579 -0
  28. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/models/base/xvars_videochatgpt.py +57 -15
  29. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/models/builder.py +16 -3
  30. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/tools/__init__.py +3 -0
  31. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1/opensportslib.egg-info}/PKG-INFO +21 -5
  32. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib.egg-info/SOURCES.txt +19 -1
  33. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib.egg-info/requires.txt +1 -0
  34. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/pyproject.toml +2 -2
  35. opensportslib-0.3.0.dev1/scripts/run_h5_header_rule_inference.py +65 -0
  36. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/tests/conftest.py +1 -1
  37. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/tests/test_config_architecture.py +14 -0
  38. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/tests/test_config_utils_smoke.py +37 -1
  39. opensportslib-0.3.0.dev1/tests/test_h5_header_rule_spotter.py +540 -0
  40. opensportslib-0.3.0.dev1/tests/test_h5_tracking_dataset.py +196 -0
  41. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/tests/test_task_model_api_contract.py +77 -0
  42. opensportslib-0.3.0.dev1/tests/test_vqa_api.py +595 -0
  43. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/tests/test_vqa_qwen_xvars.py +79 -1
  44. opensportslib-0.3.0.dev1/tests/test_vqa_training_lora.py +1229 -0
  45. opensportslib-0.3.0.dev1/tools/convert/build_sn_vqa_2026_vqa.py +7 -0
  46. opensportslib-0.3.0.dev1/tools/convert/build_soccernet_gar_vqa.py +7 -0
  47. opensportslib-0.3.0.dev1/tools/training/vqa.py +79 -0
  48. opensportslib-0.3.0.dev1/tools/upload/upload_model_hf.py +223 -0
  49. opensportslib-0.3.0/opensportslib/core/trainer/vqa_trainer.py +0 -797
  50. opensportslib-0.3.0/tests/test_vqa_api.py +0 -240
  51. opensportslib-0.3.0/tests/test_vqa_training_lora.py +0 -563
  52. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/LICENSE +0 -0
  53. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/LICENSE-COMMERCIAL +0 -0
  54. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/MANIFEST.in +0 -0
  55. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/examples/quickstart/basic_classification.py +0 -0
  56. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/examples/quickstart/basic_localization.py +0 -0
  57. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/examples/quickstart/basic_vqa.py +0 -0
  58. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/__init__.py +0 -0
  59. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/apis/__init__.py +0 -0
  60. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/apis/base_task_model.py +0 -0
  61. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/cli.py +0 -0
  62. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/configs/classification/default.yaml +0 -0
  63. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/configs/classification/sngar_frames.yaml +0 -0
  64. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/configs/classification/sngar_tracking.yaml +0 -0
  65. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/configs/classification/video.yaml +0 -0
  66. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/configs/localization/calf_resnetpca512.yaml +0 -0
  67. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/configs/localization/default.yaml +0 -0
  68. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/configs/localization/netvladpp_resnetpca512.yaml +0 -0
  69. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/configs/localization/video_dali.yaml +0 -0
  70. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/configs/localization/video_ocv.yaml +0 -0
  71. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/configs/vqa/qwen.yaml +0 -0
  72. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/configs/vqa/xvars.yaml +0 -0
  73. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/core/__init__.py +0 -0
  74. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/core/config/__init__.py +0 -0
  75. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/core/config/conflicts.py +0 -0
  76. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/core/config/loader.py +0 -0
  77. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/core/config/migrate.py +0 -0
  78. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/core/config/migrations/__init__.py +0 -0
  79. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/core/config/migrations/legacy_to_canonical.py +0 -0
  80. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/core/config/runtime_adapter.py +0 -0
  81. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/core/config/schema.py +0 -0
  82. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/core/config/schemas/__init__.py +0 -0
  83. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/core/config/schemas/schema_canonical.py +0 -0
  84. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/core/config/schemas/schema_legacy.py +0 -0
  85. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/core/config/validate.py +0 -0
  86. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/core/loss/__init__.py +0 -0
  87. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/core/loss/builder.py +0 -0
  88. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/core/loss/calf.py +0 -0
  89. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/core/loss/ce.py +0 -0
  90. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/core/loss/combine.py +0 -0
  91. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/core/loss/nll.py +0 -0
  92. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/core/optimizer/__init__.py +0 -0
  93. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/core/optimizer/builder.py +0 -0
  94. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/core/sampler/weighted_sampler.py +0 -0
  95. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/core/scheduler/__init__.py +0 -0
  96. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/core/scheduler/builder.py +0 -0
  97. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/core/trainer/__init__.py +0 -0
  98. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/core/utils/checkpoint.py +0 -0
  99. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/core/utils/config.py +0 -0
  100. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/core/utils/config_normalize.py +0 -0
  101. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/core/utils/data.py +0 -0
  102. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/core/utils/ddp.py +0 -0
  103. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/core/utils/default_args.py +0 -0
  104. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/core/utils/hf_runtime.py +0 -0
  105. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/core/utils/lightning.py +0 -0
  106. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/core/utils/seed.py +0 -0
  107. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/core/utils/video_processing.py +0 -0
  108. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/core/utils/wandb.py +0 -0
  109. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/datasets/__init__.py +0 -0
  110. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/datasets/builder.py +0 -0
  111. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/datasets/utils/__init__.py +0 -0
  112. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/datasets/utils/tracking.py +0 -0
  113. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/legacy_config/classification.yaml +0 -0
  114. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/legacy_config/localization-e2e-ocv.yaml +0 -0
  115. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/legacy_config/localization-json_calf_resnetpca512.yaml +0 -0
  116. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/legacy_config/localization-json_netvlad++_resnetpca512.yaml +0 -0
  117. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/legacy_config/localization.yaml +0 -0
  118. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/legacy_config/sngar-frames.yaml +0 -0
  119. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/legacy_config/sngar-tracking.yaml +0 -0
  120. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/metrics/classification_metric.py +0 -0
  121. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/metrics/localization_metric.py +0 -0
  122. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/metrics/vqa_metric.py +0 -0
  123. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/models/__init__.py +0 -0
  124. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/models/backbones/builder.py +0 -0
  125. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/models/base/contextaware.py +0 -0
  126. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/models/base/e2e.py +0 -0
  127. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/models/base/learnablepooling.py +0 -0
  128. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/models/base/tracking.py +0 -0
  129. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/models/base/vars.py +0 -0
  130. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/models/base/video.py +0 -0
  131. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/models/base/video_chatgpt_compat.py +0 -0
  132. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/models/base/video_mae.py +0 -0
  133. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/models/heads/builder.py +0 -0
  134. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/models/neck/builder.py +0 -0
  135. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/models/utils/common.py +0 -0
  136. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/models/utils/impl/__init__.py +0 -0
  137. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/models/utils/impl/asformer.py +0 -0
  138. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/models/utils/impl/calf.py +0 -0
  139. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/models/utils/impl/gsm.py +0 -0
  140. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/models/utils/impl/gtad.py +0 -0
  141. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/models/utils/impl/tsm.py +0 -0
  142. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/models/utils/litebase.py +0 -0
  143. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/models/utils/modules.py +0 -0
  144. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/models/utils/shift.py +0 -0
  145. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/models/utils/utils.py +0 -0
  146. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/models/utils/vqa_prediction_priors.py +0 -0
  147. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/models/utils/vqa_prompting.py +0 -0
  148. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/models/utils/xvars_clip_index.py +0 -0
  149. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/setup/setup.py +0 -0
  150. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/tools/_common.py +0 -0
  151. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/tools/hf_transfer.py +0 -0
  152. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/tools/osl_json_to_parquet.py +0 -0
  153. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib/tools/parquet_to_osl_json.py +0 -0
  154. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib.egg-info/dependency_links.txt +0 -0
  155. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib.egg-info/entry_points.txt +0 -0
  156. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/opensportslib.egg-info/top_level.txt +0 -0
  157. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/setup.cfg +0 -0
  158. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/tests/test_classification_dataset_paths.py +0 -0
  159. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/tests/test_classification_trainer_dataloader.py +0 -0
  160. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/tests/test_config_split_override_sync.py +0 -0
  161. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/tests/test_conversion_tools.py +0 -0
  162. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/tests/test_extract_xvars_features.py +0 -0
  163. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/tests/test_hf_transfer_tools.py +0 -0
  164. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/tests/test_localization_dali_filenames.py +0 -0
  165. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/tests/test_package_smoke.py +0 -0
  166. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/tests/test_pretrained_config_merge_policy.py +0 -0
  167. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/tests/test_public_apis_smoke.py +0 -0
  168. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/tests/test_setup_cli.py +0 -0
  169. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/tests/test_subset_train_infer_integration.py +0 -0
  170. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/tests/test_vqa_metrics_semantic.py +0 -0
  171. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/tests/test_vqa_xvars_videochatgpt.py +0 -0
  172. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/tools/convert/build_soccernet_gar.py +0 -0
  173. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/tools/convert/build_soccernet_gar_action_spotting.py +0 -0
  174. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/tools/convert/build_xvars_indexes.py +0 -0
  175. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/tools/convert/extract_xvars_clip_features.py +0 -0
  176. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/tools/convert/osl_json_to_parquet_webdataset.py +0 -0
  177. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/tools/convert/parquet_webdataset_to_osl_json.py +0 -0
  178. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/tools/download/download_hf_repo.py +0 -0
  179. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/tools/download/download_osl_hf.py +0 -0
  180. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/tools/download/upload_osl_hf.py +0 -0
  181. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/tools/training/classification.py +0 -0
  182. {opensportslib-0.3.0 → opensportslib-0.3.0.dev1}/tools/training/localization.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: opensportslib
3
- Version: 0.3.0
3
+ Version: 0.3.0.dev1
4
4
  Summary: OpenSportsLib is the professional library, designed for advanced video understanding in sports. It provides state-of-the-art tools for action recognition, spotting, retrieval, and captioning, making it ideal for researchers, analysts, and developers working with sports video data.
5
5
  Author: Jeet Vora
6
6
  Requires-Python: >=3.12
@@ -26,6 +26,7 @@ Requires-Dist: tabulate
26
26
  Requires-Dist: pytorch-lightning
27
27
  Requires-Dist: pandas
28
28
  Requires-Dist: pyarrow
29
+ Requires-Dist: h5py==3.16.0
29
30
  Requires-Dist: huggingface_hub
30
31
  Requires-Dist: easydict
31
32
  Provides-Extra: test
@@ -316,10 +317,25 @@ single_prediction = my_model.infer(
316
317
  ```
317
318
 
318
319
  Use `opensportslib/configs/vqa/xvars.yaml` with `opensportslib setup --vqa_xvars`
319
- for the X-VARS-compatible backend, or `opensportslib/configs/vqa/qwen.yaml` with
320
- `opensportslib setup --vqa_qwen` for the Qwen-compatible backend. The Qwen
321
- backend currently supports `Qwen/Qwen2.5-7B-Instruct` and
322
- `Qwen/Qwen3.5-9B-Base`.
320
+ for the X-VARS backend. OpenSportsLib supports three VQA options:
321
+
322
+ - `opensportslib/configs/vqa/xvars.yaml`
323
+ Original X-VARS / Video-ChatGPT path.
324
+ - CLIP features + Qwen
325
+ Use `opensportslib/configs/vqa/qwen.yaml` for inference and
326
+ `opensportslib/configs/vqa/qwen_lora.yaml` for LoRA training.
327
+ - `opensportslib/configs/vqa/qwen3_vl_native.yaml`
328
+ Full end-to-end native QwenVL path. This is the single canonical QwenVL
329
+ config; change `MODEL.components.llm_decoder.params.repo_id` to switch model
330
+ IDs.
331
+
332
+ Use `opensportslib setup --vqa_qwen` for both the CLIP+Qwen and native QwenVL
333
+ paths. The CLIP+Qwen configs support `Qwen/Qwen2.5-7B-Instruct` and
334
+ `Qwen/Qwen3.5-9B-Base`. The native QwenVL config defaults to
335
+ `Qwen/Qwen3-VL-8B-Instruct` and supports:
336
+
337
+ - `Qwen/Qwen3-VL-8B-Instruct`
338
+ - `Qwen/Qwen2.5-VL-7B-Instruct`
323
339
 
324
340
  For X-VARS, `feature_source: indexed_or_raw_clip` prefers indexed CLIP features
325
341
  when available and falls back to extracting CLIP features from raw video during
@@ -281,10 +281,25 @@ single_prediction = my_model.infer(
281
281
  ```
282
282
 
283
283
  Use `opensportslib/configs/vqa/xvars.yaml` with `opensportslib setup --vqa_xvars`
284
- for the X-VARS-compatible backend, or `opensportslib/configs/vqa/qwen.yaml` with
285
- `opensportslib setup --vqa_qwen` for the Qwen-compatible backend. The Qwen
286
- backend currently supports `Qwen/Qwen2.5-7B-Instruct` and
287
- `Qwen/Qwen3.5-9B-Base`.
284
+ for the X-VARS backend. OpenSportsLib supports three VQA options:
285
+
286
+ - `opensportslib/configs/vqa/xvars.yaml`
287
+ Original X-VARS / Video-ChatGPT path.
288
+ - CLIP features + Qwen
289
+ Use `opensportslib/configs/vqa/qwen.yaml` for inference and
290
+ `opensportslib/configs/vqa/qwen_lora.yaml` for LoRA training.
291
+ - `opensportslib/configs/vqa/qwen3_vl_native.yaml`
292
+ Full end-to-end native QwenVL path. This is the single canonical QwenVL
293
+ config; change `MODEL.components.llm_decoder.params.repo_id` to switch model
294
+ IDs.
295
+
296
+ Use `opensportslib setup --vqa_qwen` for both the CLIP+Qwen and native QwenVL
297
+ paths. The CLIP+Qwen configs support `Qwen/Qwen2.5-7B-Instruct` and
298
+ `Qwen/Qwen3.5-9B-Base`. The native QwenVL config defaults to
299
+ `Qwen/Qwen3-VL-8B-Instruct` and supports:
300
+
301
+ - `Qwen/Qwen3-VL-8B-Instruct`
302
+ - `Qwen/Qwen2.5-VL-7B-Instruct`
288
303
 
289
304
  For X-VARS, `feature_source: indexed_or_raw_clip` prefers indexed CLIP features
290
305
  when available and falls back to extracting CLIP features from raw video during
@@ -17,6 +17,17 @@ from opensportslib.core.config.accessors import (
17
17
  )
18
18
  from opensportslib.core.utils.config import expand
19
19
 
20
+
21
+ def _is_tracking_graph_modality(modality):
22
+ return str(modality).lower() in {
23
+ "tracking",
24
+ "tracking_parquet",
25
+ "tracking_h5",
26
+ "player_centroids_h5",
27
+ "player_joints_h5",
28
+ }
29
+
30
+
20
31
  class ClassificationModel(BaseTaskModel):
21
32
  """Top-level task wrapper for classification."""
22
33
 
@@ -100,7 +111,7 @@ class ClassificationModel(BaseTaskModel):
100
111
  trainer.model = model
101
112
 
102
113
  modality = get_data_modality(config)
103
- use_tracking_collate = modality in {"tracking", "tracking_parquet"}
114
+ use_tracking_collate = _is_tracking_graph_modality(modality)
104
115
  logging.info(
105
116
  "Worker setup | mode=%s | modality=%s | tracking_collate=%s",
106
117
  mode,
@@ -1,6 +1,7 @@
1
1
  import logging
2
2
  import os
3
3
  import time
4
+ from types import SimpleNamespace
4
5
 
5
6
  from opensportslib.apis.base_task_model import BaseTaskModel
6
7
  from opensportslib.core.config.accessors import (
@@ -14,6 +15,8 @@ from opensportslib.core.config.accessors import (
14
15
  get_split_annotation_path,
15
16
  get_split_cfg,
16
17
  set_split_annotation_path,
18
+ set_loader_backend,
19
+ get_model_family,
17
20
  )
18
21
  from opensportslib.core.utils.config import expand
19
22
 
@@ -21,6 +24,17 @@ from opensportslib.core.utils.config import expand
21
24
  class LocalizationModel(BaseTaskModel):
22
25
  """Top-level task wrapper for localization / spotting."""
23
26
 
27
+ _HF_BACKEND_SPLIT_TYPES = {
28
+ "dali": {
29
+ "VideoGameWithOpencv": "VideoGameWithDali",
30
+ "VideoGameWithOpencvVideo": "VideoGameWithDaliVideo",
31
+ },
32
+ "opencv": {
33
+ "VideoGameWithDali": "VideoGameWithOpencv",
34
+ "VideoGameWithDaliVideo": "VideoGameWithOpencvVideo",
35
+ },
36
+ }
37
+
24
38
  # def __init__(self, config=None, weights=None):
25
39
  # super().__init__(config=config, weights=None)
26
40
  # if weights is not None:
@@ -61,6 +75,82 @@ class LocalizationModel(BaseTaskModel):
61
75
  device,
62
76
  )
63
77
 
78
+ @staticmethod
79
+ def _device_type(device) -> str:
80
+ device_type = getattr(device, "type", device)
81
+ return str(device_type).split(":", 1)[0].lower()
82
+
83
+ @staticmethod
84
+ def _is_hf_repo_weights(weights: str | None) -> bool:
85
+ if not weights:
86
+ return False
87
+ from opensportslib.core.utils.config import is_local_path
88
+
89
+ return not is_local_path(weights)
90
+
91
+ @staticmethod
92
+ def _iter_split_items(splits):
93
+ if splits is None:
94
+ return []
95
+ if isinstance(splits, dict):
96
+ return list(splits.items())
97
+ return list(vars(splits).items())
98
+
99
+ @staticmethod
100
+ def _ensure_namespace(parent, attr: str):
101
+ current = getattr(parent, attr, None)
102
+ if current is None:
103
+ current = SimpleNamespace()
104
+ setattr(parent, attr, current)
105
+ return current
106
+
107
+ def _normalize_opencv_dataloader(self, split_name: str, split_cfg) -> None:
108
+ dataloader = getattr(split_cfg, "dataloader", None)
109
+ if dataloader is None:
110
+ dataloader = SimpleNamespace()
111
+ setattr(split_cfg, "dataloader", dataloader)
112
+
113
+ if getattr(dataloader, "batch_size", None) is None:
114
+ dataloader.batch_size = 1
115
+ if getattr(dataloader, "shuffle", None) is None:
116
+ dataloader.shuffle = split_name == "train"
117
+ if getattr(dataloader, "num_workers", None) is None:
118
+ dataloader.num_workers = 0
119
+ if getattr(dataloader, "pin_memory", None) is None:
120
+ dataloader.pin_memory = False
121
+
122
+ def _adapt_hf_backend_for_device(self, weights: str | None) -> None:
123
+ if not self._is_hf_repo_weights(weights):
124
+ return
125
+
126
+ from opensportslib.core.utils.config import select_device
127
+
128
+ device = select_device(self.config.SYSTEM)
129
+ backend = "dali" if self._device_type(device) == "cuda" else "opencv"
130
+ current_backend = get_loader_backend(self.config)
131
+ set_loader_backend(self.config, backend)
132
+
133
+ common = getattr(getattr(self.config, "DATA", None), "common", None)
134
+ if common is None:
135
+ return
136
+ splits = self._ensure_namespace(common, "splits")
137
+ remap = self._HF_BACKEND_SPLIT_TYPES[backend]
138
+
139
+ for split_name, split_cfg in self._iter_split_items(splits):
140
+ split_type = getattr(split_cfg, "type", None)
141
+ if split_type in remap:
142
+ setattr(split_cfg, "type", remap[split_type])
143
+ if backend == "opencv":
144
+ self._normalize_opencv_dataloader(split_name, split_cfg)
145
+
146
+ if current_backend != backend:
147
+ logging.info(
148
+ "HF localization runtime backend override: %s -> %s for weights=%s",
149
+ current_backend,
150
+ backend,
151
+ weights,
152
+ )
153
+
64
154
  def load_weights(
65
155
  self,
66
156
  weights: str | None = None,
@@ -79,6 +169,7 @@ class LocalizationModel(BaseTaskModel):
79
169
  if weights is None:
80
170
  raise ValueError("`weights` must be provided to load_weights().")
81
171
 
172
+ self._adapt_hf_backend_for_device(weights)
82
173
  device = select_device(self.config.SYSTEM)
83
174
  self._gate_multi_gpu_by_device(device)
84
175
  if self.model is None:
@@ -170,6 +261,11 @@ class LocalizationModel(BaseTaskModel):
170
261
 
171
262
  del kwargs
172
263
 
264
+ if str(get_model_family(self.config)).lower() == "rulebased":
265
+ raise NotImplementedError(
266
+ "RuleBased localization models are inference-only; call infer() instead of train()."
267
+ )
268
+
173
269
  train_set = self._resolve_split_path("train", train_set)
174
270
  valid_set = self._resolve_split_path("valid", valid_set)
175
271
  self._set_split_path("train", train_set)
@@ -177,8 +273,10 @@ class LocalizationModel(BaseTaskModel):
177
273
  # E2E validation mAP uses the `valid_data_frames` split; keep it in sync
178
274
  # with explicit valid annotation overrides.
179
275
  self._set_split_path("valid_data_frames", valid_set)
180
-
276
+
181
277
  self.config = resolve_config_omega(self.config, weights=weights)
278
+ effective_weights = weights if weights is not None else self.last_loaded_weights
279
+ self._adapt_hf_backend_for_device(effective_weights)
182
280
  check_config(self.config, split="train")
183
281
  init_wandb(
184
282
  self.config_path,
@@ -190,8 +288,6 @@ class LocalizationModel(BaseTaskModel):
190
288
  logging.info("Configuration:")
191
289
  logging.info(self.config)
192
290
 
193
- effective_weights = weights if weights is not None else self.last_loaded_weights
194
-
195
291
  def set_seed(seed):
196
292
  random.seed(seed)
197
293
  np.random.seed(seed)
@@ -292,6 +388,8 @@ class LocalizationModel(BaseTaskModel):
292
388
  self._set_split_path("test", test_set)
293
389
 
294
390
  self.config = resolve_config_omega(self.config, weights=weights)
391
+ effective_weights = weights if weights is not None else self.last_loaded_weights
392
+ self._adapt_hf_backend_for_device(effective_weights)
295
393
  check_config(self.config, split="test")
296
394
  self.config.infer_split = whether_infer_split(get_split_cfg(self.config, "test"))
297
395
 
@@ -307,8 +405,6 @@ class LocalizationModel(BaseTaskModel):
307
405
 
308
406
  start = time.time()
309
407
 
310
- effective_weights = weights if weights is not None else self.last_loaded_weights
311
-
312
408
  if effective_weights is not None:
313
409
  if self.model is None or self.last_loaded_weights != effective_weights:
314
410
  self.load_weights(weights=effective_weights)
@@ -362,6 +458,8 @@ class LocalizationModel(BaseTaskModel):
362
458
  test_set = self._resolve_split_path("test", test_set)
363
459
  self._set_split_path("test", test_set)
364
460
  self.config = resolve_config_omega(self.config, weights=weights)
461
+ effective_weights = weights if weights is not None else self.last_loaded_weights
462
+ self._adapt_hf_backend_for_device(effective_weights)
365
463
  check_config(self.config, split="test")
366
464
  self.config.infer_split = whether_infer_split(get_split_cfg(self.config, "test"))
367
465
 
@@ -51,6 +51,7 @@ class VQAModel(BaseTaskModel):
51
51
  return_queue=None,
52
52
  train_set=None,
53
53
  valid_set=None,
54
+ resume_from_checkpoint=None,
54
55
  use_wandb=False,
55
56
  ):
56
57
  import torch
@@ -97,14 +98,10 @@ class VQAModel(BaseTaskModel):
97
98
  train_data = build_dataset(config, train_set, None, split="train")
98
99
  valid_data = build_dataset(config, valid_set, None, split="valid")
99
100
  trainer = Trainer_VQA(config)
100
- ckpt = trainer.train(
101
- None,
102
- train_data,
103
- valid_data,
104
- rank=rank,
105
- world_size=world_size,
106
- use_wandb=use_wandb,
107
- )
101
+ train_kwargs = {"rank": rank, "world_size": world_size, "use_wandb": use_wandb}
102
+ if resume_from_checkpoint is not None:
103
+ train_kwargs["resume_from_checkpoint"] = resume_from_checkpoint
104
+ ckpt = trainer.train(None, train_data, valid_data, **train_kwargs)
108
105
  if rank == 0 and return_queue is not None:
109
106
  return_queue.put(ckpt)
110
107
  finally:
@@ -139,37 +136,73 @@ class VQAModel(BaseTaskModel):
139
136
  train_set: str | None = None,
140
137
  valid_set: str | None = None,
141
138
  weights: str | None = None,
139
+ resume_from_checkpoint: str | None = None,
140
+ use_ddp: bool | None = None,
142
141
  use_wandb: bool = True,
143
142
  **kwargs,
144
143
  ) -> str | None:
145
144
  del kwargs
145
+
146
+ self.config = resolve_config_omega(self.config, weights=weights)
147
+ execution = get_train_execution(self.config)
148
+ backend = str(execution.get("training_backend", "placeholder")).lower()
149
+ vqa_backend = get_vqa_backend(self.config)
150
+ if vqa_backend == "qwen_xvars_infer" and backend != "qwen_xvars_lora":
151
+ raise ValueError(
152
+ "The 'qwen_xvars_infer' backend requires TRAIN.execution.training_backend='qwen_xvars_lora' for train()."
153
+ )
154
+ if vqa_backend == "qwen_vl_native_infer" and backend != "qwen_vl_native_lora":
155
+ raise ValueError(
156
+ "The 'qwen_vl_native_infer' backend requires TRAIN.execution.training_backend='qwen_vl_native_lora' for train()."
157
+ )
146
158
  import torch
147
159
  import torch.multiprocessing as mp
148
160
 
149
- self.config = resolve_config_omega(self.config, weights=weights)
150
- if get_vqa_backend(self.config) == "qwen_xvars_infer":
151
- raise ValueError("The 'qwen_xvars_infer' backend is inference-only and does not support train().")
152
161
  train_set = self._resolve_split_path("train", train_set)
153
162
  valid_set = self._resolve_split_path("valid", valid_set)
154
- execution = get_train_execution(self.config)
155
- backend = str(execution.get("training_backend", "placeholder")).lower()
156
- if backend == "xvars_videochatgpt_lora":
157
- world_size = torch.cuda.device_count() or get_system_gpu_count(self.config)
163
+ if backend in {"xvars_videochatgpt_lora", "qwen_xvars_lora", "qwen_vl_native_lora"}:
158
164
  requested_gpus = get_system_gpu_count(self.config)
159
- use_ddp = world_size > 1 and int(requested_gpus) > 1
165
+ available_gpus = int(torch.cuda.device_count() or 0)
166
+ if requested_gpus > 0:
167
+ world_size = min(available_gpus, int(requested_gpus)) if available_gpus > 0 else int(requested_gpus)
168
+ else:
169
+ world_size = available_gpus
170
+ effective_world_size = max(int(world_size), 1)
171
+ if use_ddp is None:
172
+ launch_ddp = effective_world_size > 1
173
+ else:
174
+ launch_ddp = bool(use_ddp) and effective_world_size > 1
175
+ if requested_gpus > 0 and available_gpus > 0 and requested_gpus != available_gpus:
176
+ logging.info(
177
+ "VQA train GPU selection | requested=%s | available=%s | launching=%s",
178
+ requested_gpus,
179
+ available_gpus,
180
+ effective_world_size if launch_ddp else 1,
181
+ )
160
182
  logging.info(
161
- "VQA train launch | mode=%s | world_size=%s",
162
- "ddp" if use_ddp else "single",
163
- world_size if use_ddp else 1,
183
+ "VQA train launch | mode=%s | requested_gpus=%s | available_gpus=%s | world_size=%s",
184
+ "ddp" if launch_ddp else "single",
185
+ requested_gpus,
186
+ available_gpus,
187
+ effective_world_size if launch_ddp else 1,
164
188
  )
165
189
 
166
190
  ctx = mp.get_context("spawn")
167
191
  queue = ctx.SimpleQueue()
168
- if use_ddp:
192
+ if launch_ddp:
169
193
  mp.spawn(
170
194
  VQAModel._worker_ddp,
171
- args=(world_size, self.config_path, self.config, queue, train_set, valid_set, use_wandb),
172
- nprocs=world_size,
195
+ args=(
196
+ effective_world_size,
197
+ self.config_path,
198
+ self.config,
199
+ queue,
200
+ train_set,
201
+ valid_set,
202
+ resume_from_checkpoint,
203
+ use_wandb,
204
+ ),
205
+ nprocs=effective_world_size,
173
206
  )
174
207
  else:
175
208
  VQAModel._worker_ddp(
@@ -180,6 +213,7 @@ class VQAModel(BaseTaskModel):
180
213
  return_queue=queue,
181
214
  train_set=train_set,
182
215
  valid_set=valid_set,
216
+ resume_from_checkpoint=resume_from_checkpoint,
183
217
  use_wandb=use_wandb,
184
218
  )
185
219
  ckpt = queue.get()
@@ -189,7 +223,7 @@ class VQAModel(BaseTaskModel):
189
223
 
190
224
  raise ValueError(
191
225
  f"Unsupported VQA training backend '{backend}'. "
192
- "Only 'xvars_videochatgpt_lora' is supported."
226
+ "Only 'xvars_videochatgpt_lora' and 'qwen_xvars_lora' are supported."
193
227
  )
194
228
 
195
229
  def infer(
@@ -216,8 +250,6 @@ class VQAModel(BaseTaskModel):
216
250
  self.config = resolve_config_omega(self.config, weights=weights)
217
251
  backend = get_vqa_backend(self.config)
218
252
  effective_weights = weights if weights is not None else self.last_loaded_weights
219
- if backend == "qwen_xvars_infer" and effective_weights is not None:
220
- raise ValueError("The 'qwen_xvars_infer' backend does not support adapter weights for infer().")
221
253
  _set_model_checkpoint_path(self.config, effective_weights)
222
254
  self.trainer = Trainer_VQA(self.config)
223
255
  if effective_weights is not None:
@@ -237,6 +269,8 @@ class VQAModel(BaseTaskModel):
237
269
  "question": str(question).strip(),
238
270
  "references": [],
239
271
  "video_path": resolved_video_path,
272
+ "frame_paths": [],
273
+ "video_frames": [],
240
274
  "video_spatio_temporal_features": None,
241
275
  "prior_prediction_text": "",
242
276
  "labels": {},
@@ -2,7 +2,7 @@ SYSTEM:
2
2
  paths:
3
3
  log_dir: ./logs
4
4
  save_dir: ./checkpoints
5
- device: cuda
5
+ device: auto
6
6
  gpu:
7
7
  id: 0
8
8
  reproducibility:
@@ -0,0 +1,93 @@
1
+ TASK: localization
2
+ VERSION: 2
3
+
4
+ SYSTEM:
5
+ paths:
6
+ work_dir: ./outputs/header_spotting_distance
7
+ device: cpu
8
+ gpu:
9
+ count: 0
10
+
11
+ DATA:
12
+ common:
13
+ dataset_name: h5_headers
14
+ data_root: ./data
15
+ classes:
16
+ - header
17
+ splits:
18
+ test:
19
+ type: H5OSLJsonSpotting
20
+ annotation_path: ./data/h5.json
21
+ source_path: ./data
22
+ dataloader:
23
+ batch_size: 1
24
+ shuffle: false
25
+ num_workers: 0
26
+ pin_memory: false
27
+ inputs:
28
+ tracking:
29
+ modality: player_joints_h5
30
+ representation: raw
31
+ source:
32
+ format: h5
33
+ sampling: {}
34
+ transform: {}
35
+ augmentations: {}
36
+ params: {}
37
+
38
+ MODEL:
39
+ metadata:
40
+ family: RuleBased
41
+ runner:
42
+ type: runner_h5_header_rule
43
+ components:
44
+ rule:
45
+ kind: algorithm
46
+ source:
47
+ provider: opensportslib
48
+ registry: rule_based
49
+ name: h5_header_distance
50
+ params:
51
+ label: header
52
+ head_name: action
53
+ distance_threshold_m: 0.5
54
+ min_confidence: 0.5
55
+ confidence_mode: linear_inverse_distance
56
+ confidence_power: 1.0
57
+ nms_window_ms: 1000
58
+ nms_scope: sample
59
+ ball_tolerance_ms: 60
60
+ chunk_size: 100000
61
+ head_joints: [nose, neck, l_eye, r_eye, l_ear, r_ear]
62
+ required_input_type: player_joints_h5
63
+ ball_path_field: ball_path
64
+ timestamp_field: timestamp_utc
65
+ output_task: action_spotting
66
+ include_diagnostics: true
67
+ position_ms_origin: joint_h5_start
68
+ metadata_start_field: start_utc
69
+ metadata_end_field: end_utc
70
+ ball_coordinate_fields: [x, y, z]
71
+ joint_coordinate_suffixes: [x, y, z]
72
+ identity_fields: [player_id, jersey_number, team_id, is_home]
73
+ invalid_coordinate_values: [-200.0]
74
+ sideline_filter_enabled: true
75
+ pitch_half_width_m: 50.0
76
+ sideline_exclusion_m: 1.0
77
+ sideline_reference: ball_y
78
+ trajectory_filter_enabled: false
79
+ trajectory_change_mode: either_angle_or_speed
80
+ trajectory_pre_window_ms: 200
81
+ trajectory_post_window_ms: 200
82
+ trajectory_min_angle_deg: 25.0
83
+ trajectory_min_speed_delta_ratio: 0.25
84
+ trajectory_min_vector_norm_m: 0.05
85
+ trajectory_use_xy_only: false
86
+ confidence_output_key: confidence_score
87
+ topology: []
88
+
89
+ TRAIN:
90
+ trainer:
91
+ type: trainer_rule_based
92
+ execution:
93
+ enabled: false
@@ -0,0 +1,93 @@
1
+ TASK: localization
2
+ VERSION: 2
3
+
4
+ SYSTEM:
5
+ paths:
6
+ work_dir: ./outputs/header_spotting_distance_angle
7
+ device: cpu
8
+ gpu:
9
+ count: 0
10
+
11
+ DATA:
12
+ common:
13
+ dataset_name: h5_headers
14
+ data_root: ./data
15
+ classes:
16
+ - header
17
+ splits:
18
+ test:
19
+ type: H5OSLJsonSpotting
20
+ annotation_path: ./data/h5.json
21
+ source_path: ./data
22
+ dataloader:
23
+ batch_size: 1
24
+ shuffle: false
25
+ num_workers: 0
26
+ pin_memory: false
27
+ inputs:
28
+ tracking:
29
+ modality: player_joints_h5
30
+ representation: raw
31
+ source:
32
+ format: h5
33
+ sampling: {}
34
+ transform: {}
35
+ augmentations: {}
36
+ params: {}
37
+
38
+ MODEL:
39
+ metadata:
40
+ family: RuleBased
41
+ runner:
42
+ type: runner_h5_header_rule
43
+ components:
44
+ rule:
45
+ kind: algorithm
46
+ source:
47
+ provider: opensportslib
48
+ registry: rule_based
49
+ name: h5_header_distance_angle
50
+ params:
51
+ label: header
52
+ head_name: action
53
+ distance_threshold_m: 0.5
54
+ min_confidence: 0.5
55
+ confidence_mode: linear_inverse_distance
56
+ confidence_power: 1.0
57
+ nms_window_ms: 1000
58
+ nms_scope: sample
59
+ ball_tolerance_ms: 60
60
+ chunk_size: 100000
61
+ head_joints: [nose, neck, l_eye, r_eye, l_ear, r_ear]
62
+ required_input_type: player_joints_h5
63
+ ball_path_field: ball_path
64
+ timestamp_field: timestamp_utc
65
+ output_task: action_spotting
66
+ include_diagnostics: true
67
+ position_ms_origin: joint_h5_start
68
+ metadata_start_field: start_utc
69
+ metadata_end_field: end_utc
70
+ ball_coordinate_fields: [x, y, z]
71
+ joint_coordinate_suffixes: [x, y, z]
72
+ identity_fields: [player_id, jersey_number, team_id, is_home]
73
+ invalid_coordinate_values: [-200.0]
74
+ sideline_filter_enabled: true
75
+ pitch_half_width_m: 50.0
76
+ sideline_exclusion_m: 1.0
77
+ sideline_reference: ball_y
78
+ trajectory_filter_enabled: true
79
+ trajectory_change_mode: angle
80
+ trajectory_pre_window_ms: 200
81
+ trajectory_post_window_ms: 200
82
+ trajectory_min_angle_deg: 25.0
83
+ trajectory_min_speed_delta_ratio: 0.25
84
+ trajectory_min_vector_norm_m: 0.05
85
+ trajectory_use_xy_only: false
86
+ confidence_output_key: confidence_score
87
+ topology: []
88
+
89
+ TRAIN:
90
+ trainer:
91
+ type: trainer_rule_based
92
+ execution:
93
+ enabled: false