diff --git a/kloppy/infra/serializers/tracking/tracab/tracab_dat.py b/kloppy/infra/serializers/tracking/tracab/tracab_dat.py
index dcd3f07e..a878c9e3 100644
--- a/kloppy/infra/serializers/tracking/tracab/tracab_dat.py
+++ b/kloppy/infra/serializers/tracking/tracab/tracab_dat.py
@@ -72,6 +72,7 @@ def _frame_from_line(cls, teams, period, line, frame_rate):
)
player = team.get_player_by_jersey_number(jersey_no)
+
if not player:
player = Player(
player_id=f"{team.ground}_{jersey_no}",
@@ -162,8 +163,12 @@ def deserialize(self, inputs: TRACABInputs) -> TrackingDataset:
meta_data = objectify.fromstring(inputs.meta_data.read())
match = meta_data.match
frame_rate = int(match.attrib["iFrameRateFps"])
- pitch_size_width = float(match.attrib["fPitchXSizeMeters"])
- pitch_size_height = float(match.attrib["fPitchYSizeMeters"])
+ pitch_size_width = float(
+ match.attrib["fPitchXSizeMeters"].replace(",", ".")
+ )
+ pitch_size_height = float(
+ match.attrib["fPitchYSizeMeters"].replace(",", ".")
+ )
periods = []
for period in match.iterchildren(tag="period"):
@@ -182,7 +187,9 @@ def deserialize(self, inputs: TRACABInputs) -> TrackingDataset:
)
)
- if meta_data.get("HomeTeam") and meta_data.get("AwayTeam"):
+ if hasattr(meta_data, "HomeTeam") and hasattr(
+ meta_data, "AwayTeam"
+ ):
home_team = self.create_team(
meta_data["HomeTeam"], Ground.HOME, start_frame_id
)
diff --git a/kloppy/tests/files/tracab_meta_2.xml b/kloppy/tests/files/tracab_meta_2.xml
new file mode 100644
index 00000000..13f2368c
--- /dev/null
+++ b/kloppy/tests/files/tracab_meta_2.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
diff --git a/kloppy/tests/files/tracab_meta_3.xml b/kloppy/tests/files/tracab_meta_3.xml
new file mode 100644
index 00000000..4316a7b4
--- /dev/null
+++ b/kloppy/tests/files/tracab_meta_3.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
diff --git a/kloppy/tests/test_tracab.py b/kloppy/tests/test_tracab.py
index abbf817c..3298e2ce 100644
--- a/kloppy/tests/test_tracab.py
+++ b/kloppy/tests/test_tracab.py
@@ -39,6 +39,16 @@ def xml_meta_data(base_dir: Path) -> Path:
return base_dir / "files" / "tracab_meta.xml"
+@pytest.fixture(scope="session")
+def xml_meta2_data(base_dir: Path) -> Path:
+ return base_dir / "files" / "tracab_meta_2.xml"
+
+
+@pytest.fixture(scope="session")
+def xml_meta3_data(base_dir: Path) -> Path:
+ return base_dir / "files" / "tracab_meta_3.xml"
+
+
@pytest.fixture(scope="session")
def dat_raw_data(base_dir: Path) -> Path:
return base_dir / "files" / "tracab_raw.dat"
@@ -223,3 +233,125 @@ def test_correct_normalized_deserialization(
assert dataset.records[0].players_data[
player_home_1
].coordinates == Point(x=1.0019047619047619, y=0.49602941176470583)
+
+
+class TestTracabMeta2:
+ def test_correct_deserialization(
+ self, xml_meta2_data: Path, dat_raw_data: Path
+ ):
+ dataset = tracab.load(
+ meta_data=xml_meta2_data,
+ raw_data=dat_raw_data,
+ coordinates="tracab",
+ only_alive=False,
+ )
+
+ # Check metadata
+ assert dataset.metadata.provider == Provider.TRACAB
+ assert dataset.dataset_type == DatasetType.TRACKING
+ assert len(dataset.records) == 7
+ assert len(dataset.metadata.periods) == 2
+ assert dataset.metadata.orientation == Orientation.AWAY_HOME
+ assert dataset.metadata.periods[0].id == 1
+ assert dataset.metadata.periods[0].start_timestamp == timedelta(
+ seconds=73940, microseconds=320000
+ )
+ assert dataset.metadata.periods[0].end_timestamp == timedelta(
+ seconds=76656, microseconds=320000
+ )
+ assert dataset.metadata.periods[1].id == 2
+ assert dataset.metadata.periods[1].start_timestamp == timedelta(
+ seconds=77684, microseconds=560000
+ )
+ assert dataset.metadata.periods[1].end_timestamp == timedelta(
+ seconds=80717, microseconds=320000
+ )
+
+ # No need to check frames, since we do that in TestTracabDATTracking
+ # The only difference in this test is the meta data file structure
+
+ # make sure player data is only in the frame when the player is at the pitch
+ assert "home_20" in [
+ player.player_id
+ for player in dataset.records[0].players_data.keys()
+ ]
+ assert "home_20" not in [
+ player.player_id
+ for player in dataset.records[6].players_data.keys()
+ ]
+
+ def test_correct_normalized_deserialization(
+ self, xml_meta2_data: Path, dat_raw_data: Path
+ ):
+ dataset = tracab.load(
+ meta_data=xml_meta2_data, raw_data=dat_raw_data, only_alive=False
+ )
+
+ player_home_1 = dataset.metadata.teams[0].get_player_by_jersey_number(
+ 1
+ )
+
+ assert dataset.records[0].players_data[
+ player_home_1
+ ].coordinates == Point(x=1.0019047619047619, y=0.49602941176470583)
+
+
+class TestTracabMeta3:
+ def test_correct_deserialization(
+ self, xml_meta3_data: Path, dat_raw_data: Path
+ ):
+ dataset = tracab.load(
+ meta_data=xml_meta3_data,
+ raw_data=dat_raw_data,
+ coordinates="tracab",
+ only_alive=False,
+ )
+
+ # Check metadata
+ assert dataset.metadata.provider == Provider.TRACAB
+ assert dataset.dataset_type == DatasetType.TRACKING
+ assert len(dataset.records) == 7
+ assert len(dataset.metadata.periods) == 2
+ assert dataset.metadata.orientation == Orientation.AWAY_HOME
+ assert dataset.metadata.periods[0].id == 1
+ assert dataset.metadata.periods[0].start_timestamp == timedelta(
+ seconds=73940, microseconds=320000
+ )
+ assert dataset.metadata.periods[0].end_timestamp == timedelta(
+ seconds=76656, microseconds=320000
+ )
+ assert dataset.metadata.periods[1].id == 2
+ assert dataset.metadata.periods[1].start_timestamp == timedelta(
+ seconds=77684, microseconds=560000
+ )
+ assert dataset.metadata.periods[1].end_timestamp == timedelta(
+ seconds=80717, microseconds=320000
+ )
+
+ # No need to check frames, since we do that in TestTracabDATTracking
+ # The only difference in this test is the meta data file structure
+
+ # make sure player data is only in the frame when the player is at the pitch
+ assert "home_20" in [
+ player.player_id
+ for player in dataset.records[0].players_data.keys()
+ ]
+ assert "home_20" not in [
+ player.player_id
+ for player in dataset.records[6].players_data.keys()
+ ]
+
+ def test_correct_normalized_deserialization(
+ self, xml_meta3_data: Path, dat_raw_data: Path
+ ):
+ dataset = tracab.load(
+ meta_data=xml_meta3_data, raw_data=dat_raw_data, only_alive=False
+ )
+
+ player_home_1 = dataset.metadata.teams[0].get_player_by_jersey_number(
+ 1
+ )
+
+ assert dataset.records[0].players_data[
+ player_home_1
+ ].coordinates == Point(x=1.0019047619047619, y=0.49602941176470583)