opensportslib 0.3.1.dev14__tar.gz → 0.3.1.dev16__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.
- {opensportslib-0.3.1.dev14/opensportslib.egg-info → opensportslib-0.3.1.dev16}/PKG-INFO +13 -9
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/README.md +10 -8
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/adaptation/spotta.py +4 -38
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/configs/localization/e2e_spotta.yaml +1 -10
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/core/config/loader.py +18 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/core/utils/video_processing.py +2 -3
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/datasets/localization_dataset.py +44 -6
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/remote_registry.py +29 -11
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/setup/setup.py +61 -25
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16/opensportslib.egg-info}/PKG-INFO +13 -9
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib.egg-info/SOURCES.txt +56 -31
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib.egg-info/requires.txt +2 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/pyproject.toml +7 -2
- opensportslib-0.3.1.dev16/scripts/redact_test_stream.py +49 -0
- opensportslib-0.3.1.dev16/scripts/summarize_test_report.py +147 -0
- opensportslib-0.3.1.dev16/tests/__init__.py +1 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/tests/conftest.py +110 -3
- opensportslib-0.3.1.dev16/tests/helpers/__init__.py +1 -0
- opensportslib-0.3.1.dev16/tests/helpers/configs.py +16 -0
- opensportslib-0.3.1.dev16/tests/helpers/pipeline_stubs.py +71 -0
- opensportslib-0.3.1.dev16/tests/integration/classification/test_pipeline.py +31 -0
- opensportslib-0.3.1.dev16/tests/integration/localization/test_pipeline.py +26 -0
- opensportslib-0.3.1.dev16/tests/integration/vqa/test_pipeline.py +46 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/tests/release/_release_common.py +46 -15
- opensportslib-0.3.1.dev16/tests/release/test_00_environment.py +28 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/tests/release/test_classification_release.py +153 -35
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/tests/release/test_localization_release.py +18 -16
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/tests/release/test_vqa_release.py +23 -17
- opensportslib-0.3.1.dev16/tests/smoke/test_cli.py +31 -0
- opensportslib-0.3.1.dev16/tests/smoke/test_environment.py +45 -0
- opensportslib-0.3.1.dev14/tests/test_remote_model_registry.py → opensportslib-0.3.1.dev16/tests/unit/api/test_remote_registry.py +26 -3
- opensportslib-0.3.1.dev16/tests/unit/api/test_remote_sessions.py +56 -0
- opensportslib-0.3.1.dev16/tests/unit/api/test_server_jobs.py +63 -0
- opensportslib-0.3.1.dev14/tests/test_server_model_registry.py → opensportslib-0.3.1.dev16/tests/unit/api/test_server_registry.py +20 -2
- opensportslib-0.3.1.dev16/tests/unit/api/test_server_startup_scripts.py +50 -0
- opensportslib-0.3.1.dev14/tests/test_task_model_api_contract.py → opensportslib-0.3.1.dev16/tests/unit/api/test_task_model_contract.py +50 -12
- opensportslib-0.3.1.dev14/tests/test_vqa_api.py → opensportslib-0.3.1.dev16/tests/unit/api/test_vqa.py +27 -133
- opensportslib-0.3.1.dev14/tests/test_config_architecture.py → opensportslib-0.3.1.dev16/tests/unit/config/test_architecture.py +27 -1
- opensportslib-0.3.1.dev14/tests/test_editable_config.py → opensportslib-0.3.1.dev16/tests/unit/config/test_editable.py +1 -1
- opensportslib-0.3.1.dev14/tests/test_pretrained_config_merge_policy.py → opensportslib-0.3.1.dev16/tests/unit/config/test_pretrained_merge.py +1 -1
- opensportslib-0.3.1.dev16/tests/unit/contracts/test_architecture.py +73 -0
- opensportslib-0.3.1.dev16/tests/unit/contracts/test_dependencies.py +71 -0
- opensportslib-0.3.1.dev16/tests/unit/contracts/test_package.py +64 -0
- {opensportslib-0.3.1.dev14/tests → opensportslib-0.3.1.dev16/tests/unit/contracts}/test_release_versions.py +1 -1
- opensportslib-0.3.1.dev16/tests/unit/contracts/test_runner_contract.py +37 -0
- opensportslib-0.3.1.dev16/tests/unit/core/test_training_components.py +63 -0
- opensportslib-0.3.1.dev16/tests/unit/core/test_video_processing.py +66 -0
- {opensportslib-0.3.1.dev14/tests → opensportslib-0.3.1.dev16/tests/unit/data}/test_localization_intervals.py +20 -0
- opensportslib-0.3.1.dev16/tests/unit/data/test_osl_formats.py +56 -0
- opensportslib-0.3.1.dev16/tests/unit/models/test_classification_metrics.py +21 -0
- opensportslib-0.3.1.dev16/tests/unit/models/test_localization_metrics.py +25 -0
- opensportslib-0.3.1.dev16/tests/unit/models/test_temporal_shift.py +29 -0
- opensportslib-0.3.1.dev16/tests/unit/tools/test_report_summary.py +50 -0
- opensportslib-0.3.1.dev14/tests/test_setup_cli.py → opensportslib-0.3.1.dev16/tests/unit/tools/test_setup.py +76 -2
- opensportslib-0.3.1.dev14/tests/test_subset_train_infer_integration.py +0 -292
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/LICENSE +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/LICENSE-COMMERCIAL +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/MANIFEST.in +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/examples/quickstart/basic_classification.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/examples/quickstart/basic_localization.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/examples/quickstart/basic_vqa.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/__init__.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/adaptation/__init__.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/apis/__init__.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/apis/base_task_model.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/apis/classification.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/apis/config.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/apis/configuration.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/apis/localization.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/apis/vqa.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/cli.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/configs/classification/default.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/configs/classification/sngar_frames.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/configs/classification/sngar_tracking.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/configs/classification/video.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/configs/default.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/configs/localization/calf_resnetpca512.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/configs/localization/default.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/configs/localization/h5_header_distance.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/configs/localization/h5_header_skeleton.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/configs/localization/netvladpp_resnetpca512.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/configs/localization/tracking_action_spotting.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/configs/localization/video_dali.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/configs/localization/video_ocv.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/configs/vqa/default.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/configs/vqa/qwen.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/configs/vqa/qwen3_vl_native.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/configs/vqa/qwen_lora.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/configs/vqa/qwen_sngar_frames.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/configs/vqa/xvars.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/core/__init__.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/core/config/__init__.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/core/config/accessors.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/core/config/conflicts.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/core/config/editable.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/core/config/migrate.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/core/config/migrations/__init__.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/core/config/migrations/legacy_to_canonical.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/core/config/rule_variants.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/core/config/runtime_adapter.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/core/config/schema.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/core/config/schemas/__init__.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/core/config/schemas/schema_canonical.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/core/config/schemas/schema_legacy.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/core/config/validate.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/core/loss/__init__.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/core/loss/builder.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/core/loss/calf.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/core/loss/ce.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/core/loss/combine.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/core/loss/nll.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/core/optimizer/__init__.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/core/optimizer/builder.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/core/sampler/weighted_sampler.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/core/scheduler/__init__.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/core/scheduler/builder.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/core/trainer/__init__.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/core/trainer/classification_trainer.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/core/trainer/localization_trainer.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/core/trainer/vqa_trainer.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/core/utils/checkpoint.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/core/utils/config.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/core/utils/config_normalize.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/core/utils/data.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/core/utils/ddp.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/core/utils/default_args.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/core/utils/direct_video.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/core/utils/hf_runtime.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/core/utils/lightning.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/core/utils/load_annotations.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/core/utils/seed.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/core/utils/wandb.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/datasets/__init__.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/datasets/builder.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/datasets/classification_dataset.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/datasets/utils/__init__.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/datasets/utils/h5_tracking.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/datasets/utils/tracking.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/datasets/vqa_dataset.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/legacy_config/classification.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/legacy_config/localization-e2e-ocv.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/legacy_config/localization-json_calf_resnetpca512.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/legacy_config/localization-json_netvlad++_resnetpca512.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/legacy_config/localization.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/legacy_config/sngar-frames.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/legacy_config/sngar-tracking.yaml +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/metrics/classification_metric.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/metrics/localization_metric.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/metrics/vqa_metric.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/models/__init__.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/models/backbones/builder.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/models/base/contextaware.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/models/base/e2e.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/models/base/learnablepooling.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/models/base/qwen_vl_native.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/models/base/qwen_xvars.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/models/base/rule_based.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/models/base/tracking.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/models/base/vars.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/models/base/video.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/models/base/video_chatgpt_compat.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/models/base/video_mae.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/models/base/xvars_videochatgpt.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/models/builder.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/models/heads/builder.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/models/neck/builder.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/models/utils/common.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/models/utils/impl/__init__.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/models/utils/impl/asformer.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/models/utils/impl/calf.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/models/utils/impl/gsm.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/models/utils/impl/gtad.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/models/utils/impl/tsm.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/models/utils/litebase.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/models/utils/modules.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/models/utils/shift.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/models/utils/utils.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/models/utils/vqa_prediction_priors.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/models/utils/vqa_prompting.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/models/utils/xvars_clip_index.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/tools/__init__.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/tools/_common.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/tools/hf_transfer.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/tools/osl_json_to_parquet.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/tools/parquet_to_osl_json.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib.egg-info/dependency_links.txt +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib.egg-info/entry_points.txt +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib.egg-info/top_level.txt +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/scripts/release_versions.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/scripts/run_h5_header_rule_inference.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/setup.cfg +0 -0
- /opensportslib-0.3.1.dev14/tests/test_spotta_e2e.py → /opensportslib-0.3.1.dev16/tests/integration/localization/test_spotta.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/tests/release/__init__.py +0 -0
- /opensportslib-0.3.1.dev14/tests/test_config_utils_smoke.py → /opensportslib-0.3.1.dev16/tests/smoke/test_config_utils.py +0 -0
- /opensportslib-0.3.1.dev14/tests/test_package_smoke.py → /opensportslib-0.3.1.dev16/tests/smoke/test_package.py +0 -0
- /opensportslib-0.3.1.dev14/tests/test_public_apis_smoke.py → /opensportslib-0.3.1.dev16/tests/smoke/test_public_apis.py +0 -0
- /opensportslib-0.3.1.dev14/tests/test_optional_hf_config.py → /opensportslib-0.3.1.dev16/tests/unit/config/test_optional_hf.py +0 -0
- /opensportslib-0.3.1.dev14/tests/test_config_split_override_sync.py → /opensportslib-0.3.1.dev16/tests/unit/config/test_split_overrides.py +0 -0
- /opensportslib-0.3.1.dev14/tests/test_classification_trainer_dataloader.py → /opensportslib-0.3.1.dev16/tests/unit/core/test_classification_trainer.py +0 -0
- /opensportslib-0.3.1.dev14/tests/test_localization_hf_backend_override.py → /opensportslib-0.3.1.dev16/tests/unit/core/test_localization_hf_backend.py +0 -0
- /opensportslib-0.3.1.dev14/tests/test_classification_dataset_paths.py → /opensportslib-0.3.1.dev16/tests/unit/data/test_classification_paths.py +0 -0
- /opensportslib-0.3.1.dev14/tests/test_h5_tracking_dataset.py → /opensportslib-0.3.1.dev16/tests/unit/data/test_h5_tracking.py +0 -0
- /opensportslib-0.3.1.dev14/tests/test_localization_dali_filenames.py → /opensportslib-0.3.1.dev16/tests/unit/data/test_localization_dali.py +0 -0
- /opensportslib-0.3.1.dev14/tests/test_h5_header_rule_spotter.py → /opensportslib-0.3.1.dev16/tests/unit/models/test_header_rule_spotter.py +0 -0
- /opensportslib-0.3.1.dev14/tests/test_h5_header_skeleton_spotter.py → /opensportslib-0.3.1.dev16/tests/unit/models/test_header_skeleton_spotter.py +0 -0
- /opensportslib-0.3.1.dev14/tests/test_vqa_metrics_semantic.py → /opensportslib-0.3.1.dev16/tests/unit/models/test_vqa_metrics.py +0 -0
- {opensportslib-0.3.1.dev14/tests → opensportslib-0.3.1.dev16/tests/unit/models}/test_vqa_qwen_xvars.py +0 -0
- {opensportslib-0.3.1.dev14/tests → opensportslib-0.3.1.dev16/tests/unit/models}/test_vqa_training_lora.py +0 -0
- {opensportslib-0.3.1.dev14/tests → opensportslib-0.3.1.dev16/tests/unit/models}/test_vqa_xvars_videochatgpt.py +0 -0
- /opensportslib-0.3.1.dev14/tests/test_conversion_tools.py → /opensportslib-0.3.1.dev16/tests/unit/tools/test_conversion.py +0 -0
- {opensportslib-0.3.1.dev14/tests → opensportslib-0.3.1.dev16/tests/unit/tools}/test_extract_xvars_features.py +0 -0
- /opensportslib-0.3.1.dev14/tests/test_hf_transfer_tools.py → /opensportslib-0.3.1.dev16/tests/unit/tools/test_hf_transfer.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/tools/convert/build_sn_vqa_2026_vqa.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/tools/convert/build_sngar_spotting.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/tools/convert/build_soccernet_gar.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/tools/convert/build_soccernet_gar_action_spotting.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/tools/convert/build_soccernet_gar_vqa.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/tools/convert/build_xvars_indexes.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/tools/convert/extract_xvars_clip_features.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/tools/convert/osl_json_to_parquet_webdataset.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/tools/convert/parquet_webdataset_to_osl_json.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/tools/convert/sngar_dataset_card.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/tools/convert/sngar_events.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/tools/convert/verify_sngar_spotting.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/tools/download/download_hf_repo.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/tools/download/download_osl_hf.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/tools/download/push_sngar_spotting.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/tools/download/upload_osl_hf.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/tools/training/classification.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/tools/training/localization.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/tools/training/vqa.py +0 -0
- {opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/tools/upload/upload_model_hf.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: opensportslib
|
|
3
|
-
Version: 0.3.1.
|
|
3
|
+
Version: 0.3.1.dev16
|
|
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
|
|
@@ -32,6 +32,8 @@ Requires-Dist: easydict
|
|
|
32
32
|
Provides-Extra: test
|
|
33
33
|
Requires-Dist: pytest; extra == "test"
|
|
34
34
|
Requires-Dist: pytest-cov; extra == "test"
|
|
35
|
+
Requires-Dist: pytest-json-report; extra == "test"
|
|
36
|
+
Requires-Dist: pytest-timeout; extra == "test"
|
|
35
37
|
Dynamic: license-file
|
|
36
38
|
|
|
37
39
|
# OpenSportsLib
|
|
@@ -45,9 +47,9 @@ See the [complete inference server guide](docs/server/inference-server.md) for
|
|
|
45
47
|
installation, registry administration, curl requests, single-video inference,
|
|
46
48
|
full-test-set and per-sample remote inference, job polling, and sessions.
|
|
47
49
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
50
|
+
Hugging Face registration is authorized by repository access. Set `HF_TOKEN`
|
|
51
|
+
on the worker or pass `hf_token` per request. The optional `OSL_API_KEY`
|
|
52
|
+
protects local-model and general administrative operations.
|
|
51
53
|
|
|
52
54
|
## Configuration From Hugging Face
|
|
53
55
|
|
|
@@ -138,7 +140,7 @@ OpenSportsLib is designed for **researchers, ML engineers, and sports analytics
|
|
|
138
140
|
|
|
139
141
|
> Requires **Python 3.12+**.
|
|
140
142
|
> Supports CUDA 12.6 / 12.8 / 13.0 (with CPU fallback).
|
|
141
|
-
> PyTorch Geometric
|
|
143
|
+
> PyTorch Geometric uses a dedicated PyTorch 2.12.1 compatibility profile.
|
|
142
144
|
|
|
143
145
|
### Create conda env
|
|
144
146
|
|
|
@@ -170,7 +172,8 @@ pip install -e .
|
|
|
170
172
|
# Install PyTorch (CPU/GPU auto-detected)
|
|
171
173
|
opensportslib setup
|
|
172
174
|
|
|
173
|
-
# Optional: install PyTorch Geometric support
|
|
175
|
+
# Optional: install PyTorch Geometric support. This replaces the installed
|
|
176
|
+
# Torch stack with the PyG-compatible PyTorch 2.12.1 profile.
|
|
174
177
|
opensportslib setup --pyg
|
|
175
178
|
|
|
176
179
|
# Optional: install for DALI support
|
|
@@ -554,7 +557,8 @@ pip install -e .
|
|
|
554
557
|
# Install PyTorch (CPU/GPU auto-detected)
|
|
555
558
|
opensportslib setup
|
|
556
559
|
|
|
557
|
-
# Optional: install PyTorch Geometric support
|
|
560
|
+
# Optional: install PyTorch Geometric support. This replaces the installed
|
|
561
|
+
# Torch stack with the PyG-compatible PyTorch 2.12.1 profile.
|
|
558
562
|
opensportslib setup --pyg
|
|
559
563
|
|
|
560
564
|
# Optional: install for DALI support
|
|
@@ -635,8 +639,8 @@ this repository, activate a fresh Python 3.12 or newer environment and install t
|
|
|
635
639
|
|
|
636
640
|
```bash
|
|
637
641
|
pip install -e ./server
|
|
638
|
-
|
|
639
|
-
|
|
642
|
+
server/scripts/serverctl setup
|
|
643
|
+
server/scripts/serverctl start
|
|
640
644
|
```
|
|
641
645
|
|
|
642
646
|
The server installs the OpenSportsLib release from PyPI pinned to the root project
|
|
@@ -9,9 +9,9 @@ See the [complete inference server guide](docs/server/inference-server.md) for
|
|
|
9
9
|
installation, registry administration, curl requests, single-video inference,
|
|
10
10
|
full-test-set and per-sample remote inference, job polling, and sessions.
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
Hugging Face registration is authorized by repository access. Set `HF_TOKEN`
|
|
13
|
+
on the worker or pass `hf_token` per request. The optional `OSL_API_KEY`
|
|
14
|
+
protects local-model and general administrative operations.
|
|
15
15
|
|
|
16
16
|
## Configuration From Hugging Face
|
|
17
17
|
|
|
@@ -102,7 +102,7 @@ OpenSportsLib is designed for **researchers, ML engineers, and sports analytics
|
|
|
102
102
|
|
|
103
103
|
> Requires **Python 3.12+**.
|
|
104
104
|
> Supports CUDA 12.6 / 12.8 / 13.0 (with CPU fallback).
|
|
105
|
-
> PyTorch Geometric
|
|
105
|
+
> PyTorch Geometric uses a dedicated PyTorch 2.12.1 compatibility profile.
|
|
106
106
|
|
|
107
107
|
### Create conda env
|
|
108
108
|
|
|
@@ -134,7 +134,8 @@ pip install -e .
|
|
|
134
134
|
# Install PyTorch (CPU/GPU auto-detected)
|
|
135
135
|
opensportslib setup
|
|
136
136
|
|
|
137
|
-
# Optional: install PyTorch Geometric support
|
|
137
|
+
# Optional: install PyTorch Geometric support. This replaces the installed
|
|
138
|
+
# Torch stack with the PyG-compatible PyTorch 2.12.1 profile.
|
|
138
139
|
opensportslib setup --pyg
|
|
139
140
|
|
|
140
141
|
# Optional: install for DALI support
|
|
@@ -518,7 +519,8 @@ pip install -e .
|
|
|
518
519
|
# Install PyTorch (CPU/GPU auto-detected)
|
|
519
520
|
opensportslib setup
|
|
520
521
|
|
|
521
|
-
# Optional: install PyTorch Geometric support
|
|
522
|
+
# Optional: install PyTorch Geometric support. This replaces the installed
|
|
523
|
+
# Torch stack with the PyG-compatible PyTorch 2.12.1 profile.
|
|
522
524
|
opensportslib setup --pyg
|
|
523
525
|
|
|
524
526
|
# Optional: install for DALI support
|
|
@@ -599,8 +601,8 @@ this repository, activate a fresh Python 3.12 or newer environment and install t
|
|
|
599
601
|
|
|
600
602
|
```bash
|
|
601
603
|
pip install -e ./server
|
|
602
|
-
|
|
603
|
-
|
|
604
|
+
server/scripts/serverctl setup
|
|
605
|
+
server/scripts/serverctl start
|
|
604
606
|
```
|
|
605
607
|
|
|
606
608
|
The server installs the OpenSportsLib release from PyPI pinned to the root project
|
|
@@ -59,7 +59,6 @@ class SpoTTAConfig:
|
|
|
59
59
|
drift_scale: float = 10.0
|
|
60
60
|
drift_threshold: float = 1.0
|
|
61
61
|
drift_gamma: float = 0.2
|
|
62
|
-
augmentation: bool = True
|
|
63
62
|
|
|
64
63
|
@classmethod
|
|
65
64
|
def from_mapping(cls, value: Any) -> "SpoTTAConfig":
|
|
@@ -70,7 +69,6 @@ class SpoTTAConfig:
|
|
|
70
69
|
memory = _mapping(root.get("memory"))
|
|
71
70
|
optimizer = _mapping(root.get("optimizer"))
|
|
72
71
|
teacher = _mapping(root.get("teacher"))
|
|
73
|
-
augmentation = _mapping(root.get("augmentation"))
|
|
74
72
|
|
|
75
73
|
_require_supported_value(
|
|
76
74
|
root,
|
|
@@ -78,34 +76,6 @@ class SpoTTAConfig:
|
|
|
78
76
|
"adapt_then_predict",
|
|
79
77
|
"adaptation",
|
|
80
78
|
)
|
|
81
|
-
_require_supported_value(tether, "mode", "bayesian", "robust_bn.tether")
|
|
82
|
-
_require_supported_value(
|
|
83
|
-
gate,
|
|
84
|
-
"uncertainty",
|
|
85
|
-
"one_minus_max_probability",
|
|
86
|
-
"confidence_gate",
|
|
87
|
-
)
|
|
88
|
-
_require_supported_value(
|
|
89
|
-
gate,
|
|
90
|
-
"aggregation",
|
|
91
|
-
"min_over_predicted_action_frames",
|
|
92
|
-
"confidence_gate",
|
|
93
|
-
)
|
|
94
|
-
_require_supported_value(optimizer, "type", "Adam", "optimizer")
|
|
95
|
-
_require_supported_value(
|
|
96
|
-
optimizer,
|
|
97
|
-
"trainable_parameters",
|
|
98
|
-
"batch_norm_affine_only",
|
|
99
|
-
"optimizer",
|
|
100
|
-
)
|
|
101
|
-
_require_supported_value(teacher, "type", "ema", "teacher")
|
|
102
|
-
_require_supported_value(
|
|
103
|
-
teacher, "adaptive_from_bn_drift", True, "teacher"
|
|
104
|
-
)
|
|
105
|
-
_require_supported_value(
|
|
106
|
-
augmentation, "mode", "framewise_rotta_strong", "augmentation"
|
|
107
|
-
)
|
|
108
|
-
|
|
109
79
|
config = cls(
|
|
110
80
|
alpha=float(robust_bn.get("alpha", cls.alpha)),
|
|
111
81
|
tether_cap=float(tether.get("cap", cls.tether_cap)),
|
|
@@ -133,7 +103,6 @@ class SpoTTAConfig:
|
|
|
133
103
|
teacher.get("drift_threshold", cls.drift_threshold)
|
|
134
104
|
),
|
|
135
105
|
drift_gamma=float(teacher.get("drift_gamma", cls.drift_gamma)),
|
|
136
|
-
augmentation=bool(augmentation.get("enabled", cls.augmentation)),
|
|
137
106
|
)
|
|
138
107
|
config.validate()
|
|
139
108
|
return config
|
|
@@ -577,13 +546,10 @@ class SpoTTA:
|
|
|
577
546
|
with torch.no_grad():
|
|
578
547
|
teacher_logits = _logits(self.teacher(clips))
|
|
579
548
|
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
).reshape(batch, time, channels, height, width)
|
|
585
|
-
else:
|
|
586
|
-
augmented = clips
|
|
549
|
+
batch, time, channels, height, width = clips.shape
|
|
550
|
+
augmented = self.augmentation(
|
|
551
|
+
clips.reshape(batch * time, channels, height, width)
|
|
552
|
+
).reshape(batch, time, channels, height, width)
|
|
587
553
|
|
|
588
554
|
self.student.train()
|
|
589
555
|
student_logits = _logits(self.student(augmented))
|
|
@@ -39,6 +39,7 @@ DATA:
|
|
|
39
39
|
resize:
|
|
40
40
|
height: 224
|
|
41
41
|
width: 398
|
|
42
|
+
preserve_aspect_ratio: true
|
|
42
43
|
params:
|
|
43
44
|
crop_dim: 224
|
|
44
45
|
dilate_len: 0
|
|
@@ -69,13 +70,10 @@ MODEL:
|
|
|
69
70
|
robust_bn:
|
|
70
71
|
alpha: 0.05
|
|
71
72
|
tether:
|
|
72
|
-
mode: bayesian
|
|
73
73
|
cap: 0.5
|
|
74
74
|
confidence_gate:
|
|
75
75
|
action_class_index: 1
|
|
76
76
|
min_action_frames: 1
|
|
77
|
-
uncertainty: one_minus_max_probability
|
|
78
|
-
aggregation: min_over_predicted_action_frames
|
|
79
77
|
threshold: 0.3
|
|
80
78
|
memory:
|
|
81
79
|
capacity: 8
|
|
@@ -83,21 +81,14 @@ MODEL:
|
|
|
83
81
|
lambda_t: 1.0
|
|
84
82
|
lambda_u: 1.0
|
|
85
83
|
optimizer:
|
|
86
|
-
type: Adam
|
|
87
84
|
learning_rate: 0.001
|
|
88
85
|
beta: 0.9
|
|
89
|
-
trainable_parameters: batch_norm_affine_only
|
|
90
86
|
teacher:
|
|
91
|
-
type: ema
|
|
92
87
|
base_nu: 0.001
|
|
93
|
-
adaptive_from_bn_drift: true
|
|
94
88
|
max_nu: 0.02
|
|
95
89
|
drift_scale: 10.0
|
|
96
90
|
drift_threshold: 1.0
|
|
97
91
|
drift_gamma: 0.2
|
|
98
|
-
augmentation:
|
|
99
|
-
enabled: true
|
|
100
|
-
mode: framewise_rotta_strong
|
|
101
92
|
|
|
102
93
|
TRAIN:
|
|
103
94
|
execution:
|
|
@@ -206,9 +206,27 @@ def _preferred_loader_backend(payload: dict[str, Any]) -> str | None:
|
|
|
206
206
|
if _declares_opencv_split_types(payload):
|
|
207
207
|
return "opencv"
|
|
208
208
|
|
|
209
|
+
# DALI cannot run on CPU, regardless of an explicit preference in a
|
|
210
|
+
# configuration. This safety fallback also remaps DALI split types below.
|
|
209
211
|
mode = str(system.get("device", "auto")).lower()
|
|
210
212
|
if mode == "cpu":
|
|
211
213
|
return "opencv"
|
|
214
|
+
|
|
215
|
+
data = payload.get("DATA", {})
|
|
216
|
+
common = data.get("common", {}) if isinstance(data, dict) else {}
|
|
217
|
+
runtime = common.get("runtime", {}) if isinstance(common, dict) else {}
|
|
218
|
+
configured_backend = (
|
|
219
|
+
str(runtime.get("loader_backend", "auto")).lower()
|
|
220
|
+
if isinstance(runtime, dict)
|
|
221
|
+
else "auto"
|
|
222
|
+
)
|
|
223
|
+
# An explicit backend is part of the configuration contract. Runtime
|
|
224
|
+
# detection is only a default for configs which leave that choice as auto.
|
|
225
|
+
if configured_backend == "opencv":
|
|
226
|
+
return "opencv"
|
|
227
|
+
if configured_backend == "dali":
|
|
228
|
+
return "dali" if _dali_available() else "opencv"
|
|
229
|
+
|
|
212
230
|
if mode == "cuda":
|
|
213
231
|
return "dali" if _dali_available() else "opencv"
|
|
214
232
|
if mode == "auto":
|
{opensportslib-0.3.1.dev14 → opensportslib-0.3.1.dev16}/opensportslib/core/utils/video_processing.py
RENAMED
|
@@ -145,9 +145,8 @@ def distribute_elements(batch_size, len_devices):
|
|
|
145
145
|
"""
|
|
146
146
|
quotient, remainder = divmod(batch_size, len_devices)
|
|
147
147
|
distribution = [quotient] * len_devices
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
distribution[i] += 1
|
|
148
|
+
for i in range(remainder):
|
|
149
|
+
distribution[i] += 1
|
|
151
150
|
|
|
152
151
|
return distribution
|
|
153
152
|
|
|
@@ -161,6 +161,7 @@ class LocalizationDataset(Dataset):
|
|
|
161
161
|
imagenet_std=normalization.get("std"),
|
|
162
162
|
target_height=resize.get("height"),
|
|
163
163
|
target_width=resize.get("width"),
|
|
164
|
+
preserve_aspect_ratio=resize.get("preserve_aspect_ratio", False),
|
|
164
165
|
)
|
|
165
166
|
annotation_path = annotations_path or getattr(
|
|
166
167
|
split_cfg, "annotation_path", getattr(split_cfg, "path", None)
|
|
@@ -346,6 +347,7 @@ class LocalizationDataset(Dataset):
|
|
|
346
347
|
IMAGENET_STD=self.data_cfg.imagenet_std,
|
|
347
348
|
TARGET_HEIGHT=self.data_cfg.target_height,
|
|
348
349
|
TARGET_WIDTH=self.data_cfg.target_width,
|
|
350
|
+
preserve_aspect_ratio=self.data_cfg.preserve_aspect_ratio,
|
|
349
351
|
)
|
|
350
352
|
elif dataset_type == "VideoGameWithOpencvVideo":
|
|
351
353
|
dataset = ActionSpotVideoDataset(
|
|
@@ -362,6 +364,7 @@ class LocalizationDataset(Dataset):
|
|
|
362
364
|
IMAGENET_STD=self.data_cfg.imagenet_std,
|
|
363
365
|
TARGET_HEIGHT=self.data_cfg.target_height,
|
|
364
366
|
TARGET_WIDTH=self.data_cfg.target_width,
|
|
367
|
+
preserve_aspect_ratio=self.data_cfg.preserve_aspect_ratio,
|
|
365
368
|
)
|
|
366
369
|
elif dataset_type == "VideoGameWithDali":
|
|
367
370
|
if not DALI_AVAILABLE:
|
|
@@ -543,6 +546,7 @@ class FrameReader:
|
|
|
543
546
|
sample_fps=2,
|
|
544
547
|
TARGET_HEIGHT=224,
|
|
545
548
|
TARGET_WIDTH=398,
|
|
549
|
+
preserve_aspect_ratio=False,
|
|
546
550
|
):
|
|
547
551
|
self._is_flow = modality == "flow"
|
|
548
552
|
self._crop_transform = crop_transform
|
|
@@ -551,6 +555,37 @@ class FrameReader:
|
|
|
551
555
|
self._sample_fps = sample_fps
|
|
552
556
|
self.TARGET_HEIGHT = TARGET_HEIGHT
|
|
553
557
|
self.TARGET_WIDTH = TARGET_WIDTH
|
|
558
|
+
self.preserve_aspect_ratio = preserve_aspect_ratio
|
|
559
|
+
|
|
560
|
+
def _resize_frame_ocv(self, frame):
|
|
561
|
+
"""Resize an OpenCV frame using the configured spatial policy.
|
|
562
|
+
|
|
563
|
+
With aspect preservation enabled, ``TARGET_HEIGHT`` fixes the output
|
|
564
|
+
height and the width is derived from the source aspect ratio. If no
|
|
565
|
+
target height is configured, ``TARGET_WIDTH`` fixes the output width.
|
|
566
|
+
"""
|
|
567
|
+
import cv2
|
|
568
|
+
|
|
569
|
+
height, width = frame.shape[:2]
|
|
570
|
+
if self.preserve_aspect_ratio:
|
|
571
|
+
if self.TARGET_HEIGHT is not None and self.TARGET_HEIGHT > 0:
|
|
572
|
+
scale = self.TARGET_HEIGHT / height
|
|
573
|
+
elif self.TARGET_WIDTH is not None and self.TARGET_WIDTH > 0:
|
|
574
|
+
scale = self.TARGET_WIDTH / width
|
|
575
|
+
else:
|
|
576
|
+
return frame
|
|
577
|
+
|
|
578
|
+
output_height = max(1, round(height * scale))
|
|
579
|
+
output_width = max(1, round(width * scale))
|
|
580
|
+
else:
|
|
581
|
+
output_height = self.TARGET_HEIGHT
|
|
582
|
+
output_width = self.TARGET_WIDTH
|
|
583
|
+
|
|
584
|
+
if output_height is None or output_width is None:
|
|
585
|
+
return frame
|
|
586
|
+
if (height, width) == (output_height, output_width):
|
|
587
|
+
return frame
|
|
588
|
+
return cv2.resize(frame, (output_width, output_height))
|
|
554
589
|
|
|
555
590
|
def adapt_frame_ocv(self, frame):
|
|
556
591
|
"""Apply some modifications to the frame to have the expected shape and format.
|
|
@@ -675,8 +710,7 @@ class FrameReader:
|
|
|
675
710
|
ret, frame = vc.read()
|
|
676
711
|
if ret:
|
|
677
712
|
if i % stride_extract == 0:
|
|
678
|
-
|
|
679
|
-
frame = cv2.resize(frame, (ow, oh))
|
|
713
|
+
frame = self._resize_frame_ocv(frame)
|
|
680
714
|
img = self.adapt_frame_ocv(frame)
|
|
681
715
|
if self._crop_transform:
|
|
682
716
|
if self._same_transform:
|
|
@@ -781,6 +815,7 @@ class ActionSpotDataset(Dataset):
|
|
|
781
815
|
IMAGENET_STD=[0.229, 0.224, 0.225],
|
|
782
816
|
TARGET_HEIGHT=224,
|
|
783
817
|
TARGET_WIDTH=398,
|
|
818
|
+
preserve_aspect_ratio=False,
|
|
784
819
|
):
|
|
785
820
|
import random
|
|
786
821
|
from opensportslib.core.utils.load_annotations import annotationstoe2eformat
|
|
@@ -850,7 +885,8 @@ class ActionSpotDataset(Dataset):
|
|
|
850
885
|
same_transform,
|
|
851
886
|
extract_fps,
|
|
852
887
|
self.TARGET_HEIGHT,
|
|
853
|
-
self.TARGET_WIDTH
|
|
888
|
+
self.TARGET_WIDTH,
|
|
889
|
+
preserve_aspect_ratio,
|
|
854
890
|
)
|
|
855
891
|
|
|
856
892
|
def load_frame_gpu(self, batch, device):
|
|
@@ -973,7 +1009,7 @@ class ActionSpotDataset(Dataset):
|
|
|
973
1009
|
return self._dataset_len
|
|
974
1010
|
|
|
975
1011
|
def print_info(self):
|
|
976
|
-
from core.utils.config import _print_info_helper
|
|
1012
|
+
from opensportslib.core.utils.config import _print_info_helper
|
|
977
1013
|
_print_info_helper(self._src_file, self._labels)
|
|
978
1014
|
|
|
979
1015
|
|
|
@@ -1097,6 +1133,7 @@ class ActionSpotVideoDataset(Dataset, DatasetVideoSharedMethods):
|
|
|
1097
1133
|
IMAGENET_STD=[0.229, 0.224, 0.225],
|
|
1098
1134
|
TARGET_HEIGHT=224,
|
|
1099
1135
|
TARGET_WIDTH=398,
|
|
1136
|
+
preserve_aspect_ratio=False,
|
|
1100
1137
|
):
|
|
1101
1138
|
from opensportslib.core.utils.load_annotations import annotationstoe2eformat, construct_labels
|
|
1102
1139
|
from opensportslib.core.utils.video_processing import _get_img_transforms
|
|
@@ -1138,7 +1175,8 @@ class ActionSpotVideoDataset(Dataset, DatasetVideoSharedMethods):
|
|
|
1138
1175
|
False,
|
|
1139
1176
|
extract_fps,
|
|
1140
1177
|
self.TARGET_HEIGHT,
|
|
1141
|
-
self.TARGET_WIDTH
|
|
1178
|
+
self.TARGET_WIDTH,
|
|
1179
|
+
preserve_aspect_ratio,
|
|
1142
1180
|
)
|
|
1143
1181
|
|
|
1144
1182
|
self._flip = flip
|
|
@@ -1960,7 +1998,7 @@ if DALI_AVAILABLE:
|
|
|
1960
1998
|
return labels
|
|
1961
1999
|
|
|
1962
2000
|
def print_info(self):
|
|
1963
|
-
from core.utils.config import _print_info_helper
|
|
2001
|
+
from opensportslib.core.utils.config import _print_info_helper
|
|
1964
2002
|
_print_info_helper(self._src_file, self._labels)
|
|
1965
2003
|
|
|
1966
2004
|
|
|
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
4
|
import time
|
|
5
|
+
import warnings
|
|
5
6
|
from pathlib import Path
|
|
6
7
|
from typing import Any
|
|
7
8
|
from urllib import error, parse, request
|
|
@@ -17,13 +18,23 @@ class RemoteRegistryError(RuntimeError):
|
|
|
17
18
|
class RemoteModelRegistry:
|
|
18
19
|
"""Administrative client for an OpenSportsLib server model registry."""
|
|
19
20
|
|
|
20
|
-
def __init__(
|
|
21
|
+
def __init__(
|
|
22
|
+
self,
|
|
23
|
+
remote: str,
|
|
24
|
+
api_key: str | None = None,
|
|
25
|
+
timeout: float = 30.0,
|
|
26
|
+
*,
|
|
27
|
+
admin_token: str | None = None,
|
|
28
|
+
):
|
|
21
29
|
if not remote:
|
|
22
30
|
raise ValueError("remote is required.")
|
|
23
|
-
if not
|
|
24
|
-
|
|
31
|
+
if admin_token is not None:
|
|
32
|
+
warnings.warn("admin_token is deprecated; use api_key.", DeprecationWarning, stacklevel=2)
|
|
33
|
+
if api_key is not None and api_key != admin_token:
|
|
34
|
+
raise ValueError("api_key and admin_token must match when both are provided.")
|
|
35
|
+
api_key = admin_token
|
|
25
36
|
self.remote = remote.rstrip("/")
|
|
26
|
-
self.
|
|
37
|
+
self.api_key = api_key
|
|
27
38
|
self.timeout = float(timeout)
|
|
28
39
|
if self.timeout <= 0:
|
|
29
40
|
raise ValueError("timeout must be positive.")
|
|
@@ -36,6 +47,7 @@ class RemoteModelRegistry:
|
|
|
36
47
|
weights_path: str | Path | None = None,
|
|
37
48
|
config_path: str | Path | None = None,
|
|
38
49
|
model_id: str | None = None,
|
|
50
|
+
hf_token: str | None = None,
|
|
39
51
|
) -> dict[str, Any]:
|
|
40
52
|
"""Register exactly one Hugging Face or server-local model source."""
|
|
41
53
|
if (huggingface_model_id is None) == (weights_path is None):
|
|
@@ -45,9 +57,12 @@ class RemoteModelRegistry:
|
|
|
45
57
|
raise ValueError("config_path applies only to local models.")
|
|
46
58
|
if model_id is not None and model_id != huggingface_model_id:
|
|
47
59
|
raise ValueError("A Hugging Face model uses its repository ID as model_id.")
|
|
60
|
+
source = {"type": "huggingface", "model_id": huggingface_model_id}
|
|
61
|
+
if hf_token is not None:
|
|
62
|
+
source["hf_token"] = hf_token
|
|
48
63
|
payload = {
|
|
49
64
|
"task_type": task_type,
|
|
50
|
-
"source":
|
|
65
|
+
"source": source,
|
|
51
66
|
}
|
|
52
67
|
else:
|
|
53
68
|
payload = {
|
|
@@ -59,7 +74,7 @@ class RemoteModelRegistry:
|
|
|
59
74
|
"config_path": str(config_path) if config_path is not None else None,
|
|
60
75
|
},
|
|
61
76
|
}
|
|
62
|
-
return self._request("POST", "/models", payload, authenticated=
|
|
77
|
+
return self._request("POST", "/models", payload, authenticated=weights_path is not None)
|
|
63
78
|
|
|
64
79
|
def list_models(self) -> list[dict[str, Any]]:
|
|
65
80
|
return self._request("GET", "/models")["models"]
|
|
@@ -69,7 +84,7 @@ class RemoteModelRegistry:
|
|
|
69
84
|
return self._request("GET", f"/models/status?{query}")
|
|
70
85
|
|
|
71
86
|
def get_operation(self, operation_id: str) -> dict[str, Any]:
|
|
72
|
-
return self._request("GET", f"/model-operations/{parse.quote(operation_id, safe='')}"
|
|
87
|
+
return self._request("GET", f"/model-operations/{parse.quote(operation_id, safe='')}")
|
|
73
88
|
|
|
74
89
|
def wait_for_operation(
|
|
75
90
|
self,
|
|
@@ -93,9 +108,9 @@ class RemoteModelRegistry:
|
|
|
93
108
|
task = parse.quote(task_type, safe="")
|
|
94
109
|
return self._request("PUT", f"/models/defaults/{task}", {"model_id": model_id}, authenticated=True)
|
|
95
110
|
|
|
96
|
-
def unregister_model(self, model_id: str) -> dict[str, Any]:
|
|
111
|
+
def unregister_model(self, model_id: str, hf_token: str | None = None) -> dict[str, Any]:
|
|
97
112
|
encoded = parse.quote(model_id, safe="")
|
|
98
|
-
return self._request("DELETE", f"/models/{encoded}", authenticated=True)
|
|
113
|
+
return self._request("DELETE", f"/models/{encoded}", authenticated=True, hf_token=hf_token)
|
|
99
114
|
|
|
100
115
|
def reconcile_runtime(
|
|
101
116
|
self,
|
|
@@ -117,11 +132,14 @@ class RemoteModelRegistry:
|
|
|
117
132
|
endpoint: str,
|
|
118
133
|
payload: dict[str, Any] | None = None,
|
|
119
134
|
authenticated: bool = False,
|
|
135
|
+
hf_token: str | None = None,
|
|
120
136
|
) -> dict[str, Any]:
|
|
121
137
|
body = json.dumps(payload).encode() if payload is not None else None
|
|
122
138
|
headers = {"Content-Type": "application/json"}
|
|
123
|
-
if authenticated:
|
|
124
|
-
headers["Authorization"] = f"Bearer {self.
|
|
139
|
+
if authenticated and self.api_key:
|
|
140
|
+
headers["Authorization"] = f"Bearer {self.api_key}"
|
|
141
|
+
if hf_token:
|
|
142
|
+
headers["X-HF-Token"] = hf_token
|
|
125
143
|
outgoing = request.Request(self.remote + endpoint, data=body, method=method, headers=headers)
|
|
126
144
|
try:
|
|
127
145
|
with request.urlopen(outgoing, timeout=self.timeout) as response:
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import platform
|
|
2
2
|
import subprocess
|
|
3
3
|
import sys
|
|
4
|
+
import tempfile
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
CUDA_WHEEL_VERSIONS = {
|
|
@@ -14,6 +15,20 @@ LEGACY_GPU_CUDA_WHEEL = "cu126"
|
|
|
14
15
|
LEGACY_GPU_CUDA_WHEEL_MAX_COMPUTE_CAPABILITY = (9, 0)
|
|
15
16
|
CUDA13_REQUIRED_MIN_COMPUTE_CAPABILITY = (10, 0)
|
|
16
17
|
|
|
18
|
+
# PyG extension wheels are published for a narrower PyTorch matrix than the
|
|
19
|
+
# base PyTorch packages. Keep this profile explicit: selecting ``--pyg`` is
|
|
20
|
+
# allowed to replace an otherwise newer PyTorch installation.
|
|
21
|
+
PYG_TORCH_VERSION = "2.12.1"
|
|
22
|
+
PYG_TORCH_PACKAGES = (
|
|
23
|
+
f"torch=={PYG_TORCH_VERSION}",
|
|
24
|
+
"torchvision==0.27.1",
|
|
25
|
+
)
|
|
26
|
+
PYG_EXTENSION_PACKAGES = (
|
|
27
|
+
"pyg-lib",
|
|
28
|
+
"torch-scatter",
|
|
29
|
+
"torch-sparse",
|
|
30
|
+
)
|
|
31
|
+
|
|
17
32
|
XVARS_DEPENDENCY_PINS = {
|
|
18
33
|
"transformers": "4.38.2",
|
|
19
34
|
"peft": "0.9.0",
|
|
@@ -154,10 +169,17 @@ def install_xvars_dependencies(DEPENDENCY_PINS):
|
|
|
154
169
|
subprocess.check_call([python, "-m", "pip", "install", *pinned_packages])
|
|
155
170
|
print("Dependencies installed successfully.")
|
|
156
171
|
|
|
157
|
-
def install_torch():
|
|
172
|
+
def install_torch(*, pyg_compatible=False):
|
|
173
|
+
"""Install the default Torch stack or the pinned PyG-compatible stack."""
|
|
158
174
|
python = sys.executable
|
|
159
175
|
subprocess.call([python, "-m", "pip", "uninstall", "-y", "torch", "torchvision", "torchaudio"])
|
|
160
|
-
packages = select_torch_packages(GPU_COMPUTE_CAPABILITIES)
|
|
176
|
+
packages = PYG_TORCH_PACKAGES if pyg_compatible else select_torch_packages(GPU_COMPUTE_CAPABILITIES)
|
|
177
|
+
|
|
178
|
+
if pyg_compatible:
|
|
179
|
+
print(
|
|
180
|
+
"\nInstalling the PyTorch Geometric compatibility profile: "
|
|
181
|
+
f"PyTorch {PYG_TORCH_VERSION}. This replaces the installed Torch stack.\n"
|
|
182
|
+
)
|
|
161
183
|
|
|
162
184
|
subprocess.check_call([
|
|
163
185
|
python, "-m", "pip", "install",
|
|
@@ -168,6 +190,30 @@ def install_torch():
|
|
|
168
190
|
print(f"\nSuccess with {CUDA_TAG}: {', '.join(packages)}")
|
|
169
191
|
return CUDA_TAG
|
|
170
192
|
|
|
193
|
+
|
|
194
|
+
def pyg_wheel_url(torch_version=None, cuda_tag=None):
|
|
195
|
+
torch_version = torch_version or PYG_TORCH_VERSION
|
|
196
|
+
cuda_tag = CUDA_TAG if cuda_tag is None else cuda_tag
|
|
197
|
+
suffix = "cpu" if cuda_tag == "cpu" else cuda_tag
|
|
198
|
+
return f"https://data.pyg.org/whl/torch-{torch_version}+{suffix}.html"
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def validate_pyg_wheels():
|
|
202
|
+
"""Ensure every required PyG wheel exists before replacing Torch.
|
|
203
|
+
|
|
204
|
+
``--only-binary`` is intentional: pip otherwise falls back to a source
|
|
205
|
+
build, which is both slow and incompatible with its isolated build
|
|
206
|
+
environment unless Torch is installed there as well.
|
|
207
|
+
"""
|
|
208
|
+
python = sys.executable
|
|
209
|
+
url = pyg_wheel_url()
|
|
210
|
+
print("\nChecking PyTorch Geometric wheels before replacing the Torch stack...\n")
|
|
211
|
+
with tempfile.TemporaryDirectory(prefix="opensportslib-pyg-wheel-check-") as download_dir:
|
|
212
|
+
subprocess.check_call([
|
|
213
|
+
python, "-m", "pip", "download", "--no-deps", "--only-binary=:all:",
|
|
214
|
+
"--dest", download_dir, *PYG_EXTENSION_PACKAGES, "-f", url,
|
|
215
|
+
])
|
|
216
|
+
|
|
171
217
|
def install_dali():
|
|
172
218
|
|
|
173
219
|
python = sys.executable
|
|
@@ -202,36 +248,24 @@ def install_dali():
|
|
|
202
248
|
|
|
203
249
|
def install_pyg():
|
|
204
250
|
import torch
|
|
205
|
-
from packaging import version
|
|
206
251
|
|
|
207
252
|
python = sys.executable
|
|
208
|
-
torch_version =
|
|
209
|
-
|
|
253
|
+
torch_version = torch.__version__.split("+")[0]
|
|
254
|
+
if torch_version != PYG_TORCH_VERSION:
|
|
255
|
+
raise RuntimeError(
|
|
256
|
+
"PyTorch Geometric extensions require the OpenSportsLib PyG compatibility "
|
|
257
|
+
f"profile (PyTorch {PYG_TORCH_VERSION}); found PyTorch {torch_version}. "
|
|
258
|
+
"Run 'opensportslib setup --pyg' so the matching Torch stack is installed."
|
|
259
|
+
)
|
|
210
260
|
print("\nInstalling Py-Geometric ecosystem...\n")
|
|
211
|
-
|
|
212
|
-
url = f"https://data.pyg.org/whl/torch-{torch_version}+cpu.html"
|
|
213
|
-
else:
|
|
214
|
-
url = f"https://data.pyg.org/whl/torch-{torch_version}+{cuda_tag}.html"
|
|
261
|
+
url = pyg_wheel_url(torch_version)
|
|
215
262
|
|
|
216
263
|
subprocess.check_call([
|
|
217
|
-
python, "-m", "pip", "install",
|
|
218
|
-
"torch-geometric", "-f", url
|
|
219
|
-
])
|
|
220
|
-
subprocess.check_call([
|
|
221
|
-
python, "-m", "pip", "install",
|
|
222
|
-
"torch-scatter", "-f", url
|
|
264
|
+
python, "-m", "pip", "install", "torch-geometric",
|
|
223
265
|
])
|
|
224
266
|
subprocess.check_call([
|
|
225
267
|
python, "-m", "pip", "install",
|
|
226
|
-
"
|
|
227
|
-
])
|
|
228
|
-
subprocess.check_call([
|
|
229
|
-
python, "-m", "pip", "install",
|
|
230
|
-
"torch-cluster", "-f", url
|
|
231
|
-
])
|
|
232
|
-
subprocess.check_call([
|
|
233
|
-
python, "-m", "pip", "install",
|
|
234
|
-
"torch-spline-conv", "-f", url
|
|
268
|
+
*PYG_EXTENSION_PACKAGES, "--only-binary=:all:", "-f", url
|
|
235
269
|
])
|
|
236
270
|
|
|
237
271
|
def install_extras(dali=False, pyg=False):
|
|
@@ -256,7 +290,9 @@ def verify():
|
|
|
256
290
|
print("Running on CPU")
|
|
257
291
|
|
|
258
292
|
def setup(dali=False, pyg=False, vqa_xvars=False, vqa_qwen=False):
|
|
259
|
-
|
|
293
|
+
if pyg:
|
|
294
|
+
validate_pyg_wheels()
|
|
295
|
+
install_torch(pyg_compatible=pyg)
|
|
260
296
|
install_extras(dali=dali, pyg=pyg)
|
|
261
297
|
if vqa_xvars:
|
|
262
298
|
install_xvars_dependencies(XVARS_DEPENDENCY_PINS)
|