Skip to content

Commit

Permalink
Merge branch 'master' into fix-transform-orientation
Browse files Browse the repository at this point in the history
  • Loading branch information
probberechts authored Jan 30, 2024
2 parents be7885e + bb2dbad commit e2cb448
Show file tree
Hide file tree
Showing 8 changed files with 371 additions and 160 deletions.
9 changes: 7 additions & 2 deletions kloppy/infra/serializers/event/metrica/json_deserializer.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from typing import Dict, List, NamedTuple, IO, Optional
import logging
import json
from dataclasses import replace
from typing import Dict, List, NamedTuple, IO, Optional

from kloppy.domain import (
BallState,
Expand Down Expand Up @@ -384,6 +385,10 @@ def deserialize(self, inputs: MetricaJsonEventDataInputs) -> EventDataset:
events.append(transformer.transform_event(event))

return EventDataset(
metadata=metadata,
metadata=replace(
metadata,
pitch_dimensions=transformer.get_to_coordinate_system().pitch_dimensions,
coordinate_system=transformer.get_to_coordinate_system(),
),
records=events,
)
11 changes: 8 additions & 3 deletions kloppy/infra/serializers/event/opta/deserializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,11 @@


def _parse_f24_datetime(dt_str: str) -> float:
def zero_pad_milliseconds(timestamp):
parts = timestamp.split(".")
return ".".join(parts[:-1] + ["{:03d}".format(int(parts[-1]))])

dt_str = zero_pad_milliseconds(dt_str)
return (
datetime.strptime(dt_str, "%Y-%m-%dT%H:%M:%S.%f")
.replace(tzinfo=pytz.utc)
Expand Down Expand Up @@ -705,10 +710,10 @@ def deserialize(self, inputs: OptaInputs) -> EventDataset:
away_score = None
for team_elm in team_elms:
if team_elm.attrib["Side"] == "Home":
home_score = team_elm.attrib["Score"]
home_score = int(team_elm.attrib["Score"])
home_team = _team_from_xml_elm(team_elm, f7_root)
elif team_elm.attrib["Side"] == "Away":
away_score = team_elm.attrib["Score"]
away_score = int(team_elm.attrib["Score"])
away_team = _team_from_xml_elm(team_elm, f7_root)
else:
raise DeserializationError(
Expand Down Expand Up @@ -952,7 +957,7 @@ def deserialize(self, inputs: OptaInputs) -> EventDataset:
score=score,
frame_rate=None,
orientation=Orientation.ACTION_EXECUTING_TEAM,
flags=DatasetFlag.BALL_OWNING_TEAM,
flags=DatasetFlag.BALL_OWNING_TEAM | DatasetFlag.BALL_STATE,
provider=Provider.OPTA,
coordinate_system=transformer.get_to_coordinate_system(),
)
Expand Down
2 changes: 1 addition & 1 deletion kloppy/infra/serializers/event/wyscout/deserializer_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -712,7 +712,7 @@ def deserialize(self, inputs: WyscoutInputs) -> EventDataset:
pitch_dimensions=transformer.get_to_coordinate_system().pitch_dimensions,
score=None,
frame_rate=None,
orientation=Orientation.BALL_OWNING_TEAM,
orientation=Orientation.ACTION_EXECUTING_TEAM,
flags=None,
provider=Provider.WYSCOUT,
coordinate_system=transformer.get_to_coordinate_system(),
Expand Down
2 changes: 1 addition & 1 deletion kloppy/infra/serializers/event/wyscout/deserializer_v3.py
Original file line number Diff line number Diff line change
Expand Up @@ -684,7 +684,7 @@ def deserialize(self, inputs: WyscoutInputs) -> EventDataset:
pitch_dimensions=transformer.get_to_coordinate_system().pitch_dimensions,
score=None,
frame_rate=None,
orientation=Orientation.BALL_OWNING_TEAM,
orientation=Orientation.ACTION_EXECUTING_TEAM,
flags=None,
provider=Provider.WYSCOUT,
coordinate_system=transformer.get_to_coordinate_system(),
Expand Down
38 changes: 28 additions & 10 deletions kloppy/infra/serializers/tracking/skillcorner.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from collections import Counter
import numpy as np
import json
from pathlib import Path

from kloppy.domain import (
attacking_direction_from_frame,
Expand Down Expand Up @@ -137,7 +138,7 @@ def _get_frame_data(

return Frame(
frame_id=frame_id,
timestamp=frame_time,
timestamp=frame_time - periods[frame_period].start_timestamp,
ball_coordinates=ball_coordinates,
players_data=players_data,
period=periods[frame_period],
Expand All @@ -148,8 +149,16 @@ def _get_frame_data(

@classmethod
def _timestamp_from_timestring(cls, timestring):
m, s = timestring.split(":")
return 60 * float(m) + float(s)
parts = timestring.split(":")

if len(parts) == 2:
m, s = parts
return 60 * float(m) + float(s)
elif len(parts) == 3:
h, m, s = parts
return 3600 * float(h) + 60 * float(m) + float(s)
else:
raise ValueError("Invalid timestring format")

@classmethod
def _get_skillcorner_attacking_directions(cls, frames, periods):
Expand Down Expand Up @@ -181,7 +190,17 @@ def _get_skillcorner_attacking_directions(cls, frames, periods):
return attacking_directions

def __load_json(self, file):
return json.load(file)
if Path(file.name).suffix == ".jsonl":
data = []
for line in file:
obj = json.loads(line)
# for each line rename timestamp to time to make it compatible with existing loader
if "timestamp" in obj:
obj["time"] = obj.pop("timestamp")
data.append(obj)
return data
else:
return json.load(file)

@classmethod
def __get_periods(cls, tracking):
Expand Down Expand Up @@ -260,7 +279,7 @@ def deserialize(self, inputs: SkillCornerInputs) -> TrackingDataset:
metadata["away_team"].get("id"): "away_team",
}

player_id_to_team_dict = {
player_to_team_dict = {
player["trackable_object"]: player["team_id"]
for player in metadata["players"]
}
Expand Down Expand Up @@ -301,8 +320,7 @@ def deserialize(self, inputs: SkillCornerInputs) -> TrackingDataset:
)
teams = [home_team, away_team]

for player_id in player_dict.keys():
player = player_dict.get(player_id)
for player_track_obj_id, player in player_dict.items():
team_id = player["team_id"]

if team_id == home_team_id:
Expand All @@ -312,8 +330,8 @@ def deserialize(self, inputs: SkillCornerInputs) -> TrackingDataset:
team_string = "AWAY"
team = away_team

players[team_string][player_id] = Player(
player_id=f"{team.ground}_{player['number']}",
players[team_string][player_track_obj_id] = Player(
player_id=f"{player['id']}",
team=team,
jersey_no=player["number"],
name=f"{player['first_name']} {player['last_name']}",
Expand Down Expand Up @@ -358,7 +376,7 @@ def _iter():
teams,
teamdict,
players,
player_id_to_team_dict,
player_to_team_dict,
periods,
player_dict,
anon_players,
Expand Down
Loading

0 comments on commit e2cb448

Please sign in to comment.