Video Analysis XML Export#
databallpy can export event data to XML files compatible with video analysis tools such as SportsCode and Longomatch. This lets you automatically tag match footage from your existing data, turning every pass, shot, or custom event into a labelled video clip — without manual tagging.
There are two workflows:
Export from
EventData— filter and export events that already live in yourgame.event_dataDataFrame.Custom events — define your own events (e.g. from your own detection logic) and export them via
events_to_xml().
Both produce the same XML format; the right choice depends on whether you want to use events that databallpy has already parsed or events you have computed yourself.
import os
from databallpy import get_saved_game
game = get_saved_game("not_synced_game", os.path.join(os.getcwd(), "../saved_games"))
Workflow 1: Export from EventData#
game.event_data is a specialised DataFrame that exposes a to_video_analysis_xml() method. Calling it with no arguments exports every event in the dataset:
xml_str = game.event_data.to_video_analysis_xml()
print(xml_str[:800])
<?xml version="1.0" encoding="utf-8"?>
<file>
<SORT_INFO>
<sort_type>sort order</sort_type>
</SORT_INFO>
<ALL_INSTANCES>
<instance>
<ID>p1</ID>
<start>0.00</start>
<end>3.00</end>
<code>1H</code>
<label>
<group>Period</group>
<text>1</text>
</label>
</instance>
<instance>
<ID>0</ID>
<start>-4320.75</start>
<end>-4314.75</end>
<code>team set up</code>
<label>
<group>Team</group>
<text>T-3f505904</text>
</label>
<label>
<group>Original Event</group>
<text>team set up</text>
</label>
</instance>
<instance>
<ID>1</ID>
<start>-4167.35</start>
<end>-4161.35</end>
<code>team set up</code>
<label>
<group>Team</group>
<text>T-4266dd74</text>
</label>
<label>
<group>Original Event</group
print(f"Generated XML with {xml_str.count('<instance>')} instance(s)")
Generated XML with 155 instance(s)
The XML contains one <instance> per event plus a period-start marker per half. Each instance carries a <code> (the event type used for colour grouping in the video tool) and one <label> per piece of metadata — player name, team, outcome, etc.
Filtering and clip windows#
In practice you usually want a subset. The method accepts several keyword-only filters:
xml_shots = game.event_data.to_video_analysis_xml(
databallpy_events=["shot"], # only shots
before_seconds=5.0, # clip starts 5 s before the event
after_seconds=3.0, # clip ends 3 s after
tag_period_starts=False, # omit period markers
)
print(f"Generated XML with {xml_shots.count('<instance>')} shot instance(s)")
Generated XML with 2 shot instance(s)
You can layer multiple filters at once:
home_passes_xml = game.event_data.to_video_analysis_xml(
team_id=game.home_team_id, # home team only
databallpy_events=["pass"], # passes only
is_successful=True, # successful passes only
before_seconds=3.0,
after_seconds=5.0,
)
print(f"Generated XML with {home_passes_xml.count('<instance>')} instance(s)")
Generated XML with 49 instance(s)
Writing to a file#
Pass a file path to output instead of "string" to write directly to disk:
path = game.event_data.to_video_analysis_xml(
databallpy_events=["shot"],
output="shots.xml",
)
Workflow 2: Custom Events#
When the events you want to tag do not come directly from the parsed event data — for example, pressing sequences detected from tracking data, or events from your own model — use events_to_xml() with manually constructed Event dicts.
Two TypedDicts define the structure:
Type |
Fields |
|---|---|
|
|
|
|
Times are in seconds relative to the start of the relevant half — the same convention used by SportsCode and Longomatch.
from databallpy import events_to_xml, Event, LabelDict
# Imagine these pressing events were detected from tracking data
pressing_events: dict[str, Event] = {
"0": Event(
id="0",
code="Press",
start_t=312.0, # seconds from half-start
end_t=320.0,
labels=[
LabelDict(group="Team", name="Home"),
LabelDict(group="Outcome", name="Ball won"),
],
),
"1": Event(
id="1",
code="Press",
start_t=874.5,
end_t=882.0,
labels=[
LabelDict(group="Team", name="Away"),
LabelDict(group="Outcome", name="Unsuccessful"),
],
),
}
xml_str = events_to_xml(pressing_events)
print(xml_str)
<?xml version="1.0" encoding="utf-8"?>
<file>
<SORT_INFO>
<sort_type>sort order</sort_type>
</SORT_INFO>
<ALL_INSTANCES>
<instance>
<ID>0</ID>
<start>312.00</start>
<end>320.00</end>
<code>Press</code>
<label>
<group>Team</group>
<text>Home</text>
</label>
<label>
<group>Outcome</group>
<text>Ball won</text>
</label>
</instance>
<instance>
<ID>1</ID>
<start>874.50</start>
<end>882.00</end>
<code>Press</code>
<label>
<group>Team</group>
<text>Away</text>
</label>
<label>
<group>Outcome</group>
<text>Unsuccessful</text>
</label>
</instance>
</ALL_INSTANCES>
<ROWS>
<row>
<code>Press</code>
<R>96077</R>
<G>70587</G>
<B>61568</B>
<sort_order>0</sort_order>
</row>
</ROWS>
</file>
Tip
You can mix both workflows: use to_video_analysis_xml() for the bulk of your events and add hand-crafted entries on top by combining the resulting dicts before calling events_to_xml().
Summary#
Task |
Method |
|---|---|
Export parsed events from a game |
|
Filter by team, player, minute, event type, outcome |
keyword arguments on |
Write directly to a file |
|
Export fully custom events |
|
For the full parameter reference see the Event Data API documentation page.