The objective is to synchronize the events provided by Wyscout, Opta, StatsBomb, and Impect with SkillCorner data.
There are two main usages of this repository:
- with_tracking: full synchronization between event data and SkillCorner tracking data.
- with_dynamic_events: processing and alignment of provider events with SkillCorner dynamic events only (without tracking XY for all players), for cases where full tracking is not available or not necessary.
Below we first describe the generic synchronization process (with tracking), then how to use the dedicated entry points for each mode.
This step combines tracking and event timestamps to find the offset that best aligns the two datasets. By using player-ball distance, we statistically determine and refine the offset frame.
This step refines the event frame using tracking data to pinpoint the exact moment of a pass or shot. It identifies a window where the distance between the player involved and the ball is less than 3 meters. Within this window, the frame with the highest ball acceleration is considered the exact event moment. If the acceleration data is unreliable, the frame identified using the general offset is retained.
As each event is associated with a player, we have the possibility to compare the distance between the player involved in the event and the ball using our tracking data. A threshold of 3.5 meters is used within a window of ±5 frames around the event's frame. So if the distance player and ball is within 3.5 meters at least once during this window, then is_matched=True; otherwise, is_matched=False. This comparison helps create the is_matched binary flag, indicating whether the tracking data and events can be trusted at this frame.
In with_tracking mode, the synchronization process generates three main outputs:
- report_by_event: A CSV file where each row corresponds to an event. Columns include:
- {provider}_event_id
- {provider}_event_type
- period
- frame
- player_id
- {provider}_player_id
- player_name
- player_role
- player_number
- starting
- team_id
- {provider}_team_id
- team_type
- team_name
- is_matched
- is_player_detected
- has_{provider}_player_id_attached
- frame_tracking_data_available
- is_matched_applicable
- report_by_event_type: A CSV file grouping events by type with performance metrics related to
is_matched. Columns include:- {provider}_event_type
- nb_events
- is_matched
- %_is_matched
- is_matched_is_player_detected
- is_not_matched
- is_not_matched_is_player_detected
- is_not_matched_has_{provider}_player_id_attached
- is_not_matched_frame_tracking_data_available
- is_matched_applicable
- freeze_frame_format: A list of dictionaries containing enriched tracking data. Example of an element:
{ "frame": 35261, "timestamp": "00:53:28.10", "period": 2, "ball_data": { "x": -25.15, "y": -24.01, "z": 0.17, "is_detected": true }, "player_data": [ { "x": -46.05, "y": -2.62, "player_id": 11898, "is_detected": false, "speed_norm": 1.47, "vx": -1.45, "vy": -0.25, "acc_norm": 0.15 }, ... { "x": -19.12, "y": -13.14, "player_id": 17965, "is_detected": true, "speed_norm": 4.65, "vx": -4.2, "vy": 2.0, "acc_norm": 3.08 } ], "{provider}_event_id": "2315178015", "{provider}_event_type": "Pass", "player_id": 34847, "{provider}_player_id": "426384", "team_id": 672, "{provider}_team_id": "596", "is_matched": true, "is_player_detected": true, "projected_{provider}_event_x": -21.6, "projected_{provider}_event_y": -22.27 }
To use the project, follow these steps:
- Ensure you have Python >= 3.8 installed.
- Install the required dependencies:
pip install -r requirements.txt
To use the synchronization tool with tracking, follow these steps:
- Ensure you are in the root of the folder
- Run the event-synchronization:
python -m tools.run_impect
--match_data_path /path/to/skc_match_data.json \
--tracking_data_path /path/to/skc_tracking_data.json \
--impect_events_path /path/to/impect_events.json \
--impect_match_data_path /path/to/impect_match_data.json \
--save_outputs_dir /path/to/output_directory \python -m tools.run_opta \
--match_data_path /path/to/skc_match_data.json \
--tracking_data_path /path/to/skc_tracking_data.json \
--opta_events_path /path/to/opta_events.json (or .xml) \
--opta_match_data_path /path/to/opta_match_data.json (or .xml) \
--save_outputs_dir /path/to/output_directory \python -m tools.run_statsbomb \
--match_data_path /path/to/skc_match_data.json \
--tracking_data_path /path/to/skc_tracking_data.json \
--statsbomb_events_path /path/to/statsbomb_events.json \
--statsbomb_match_data_path /path/to/statsbomb_lineup.json \
--statsbomb_home_team_id statsbomb_home_team_id \
--save_outputs_dir /path/to/output_directory \python -m tools.run_wyscout \
--match_data_path /path/to/skc_match_data.json \
--tracking_data_path /path/to/skc_tracking_data.json \
--wyscout_events_path /path/to/wyscout_events.json \
--save_outputs_dir /path/to/output_directory \Note:
You also have access to some notebook examples in: tools/notebook_example (Don't forget to install skillcorner to use SkillcornerClient).
This mode corresponds to the logic in event_synchronization/with_dynamic_events/. It does require only SkillCorner dynamic events and provider events (StatsBomb, Impect, Wyscout). Sync with Opta is not yet available with dynamic events.
Typical usage patterns:
-
Via python scripts:
Fill the
load_datafunction to add path of skc and provider files- run
python -m tools.run_statsbomb - run
python -m tools.run_impect - run
python -m tools.run_wyscout
- run
-
Via notebooks:
- Fill the notebook cells with the appropriate code to load and process the data in
/with_dynamic_events/notebooks/. - Run the cells sequentially to perform synchronization and analysis.
- Fill the notebook cells with the appropriate code to load and process the data in
Distributed under the SkillCorner License.