socr / tests /spadl /test_wyscout.py
scfive's picture
Upload 203 files
d6ea71e verified
import os
import pandas as pd
from socceraction.data.wyscout import PublicWyscoutLoader
from socceraction.spadl import SPADLSchema
from socceraction.spadl import config as spadl
from socceraction.spadl import wyscout as wy
class TestSpadlConvertor:
def setup_method(self) -> None:
data_dir = os.path.join(
os.path.dirname(__file__), os.pardir, "datasets", "wyscout_public", "raw"
)
self.WSL = PublicWyscoutLoader(root=data_dir, download=False)
self.events = self.WSL.events(2058007)
def test_convert_to_actions(self) -> None:
df_actions = wy.convert_to_actions(self.events, 5629)
assert len(df_actions) > 0
SPADLSchema.validate(df_actions)
assert (df_actions.game_id == 2058007).all()
assert ((df_actions.team_id == 5629) | (df_actions.team_id == 12913)).all()
def test_insert_interception_passes(self) -> None:
event = pd.DataFrame(
[
{
"type_id": 8,
"subtype_name": "Head pass",
"tags": [{"id": 102}, {"id": 1401}, {"id": 1801}], # own goal
"player_id": 38093,
"positions": [{"y": 56, "x": 5}, {"y": 100, "x": 100}],
"game_id": 2499737,
"type_name": "Pass",
"team_id": 1610,
"period_id": 2,
"milliseconds": 2184.793924,
"subtype_id": 82,
"event_id": 180427412,
}
]
)
actions = wy.convert_to_actions(event, 1610)
assert len(actions) == 2
assert actions.at[0, "type_id"] == spadl.actiontypes.index("interception")
assert actions.at[1, "type_id"] == spadl.actiontypes.index("bad_touch")
assert actions.at[0, "result_id"] == spadl.results.index("success")
assert actions.at[1, "result_id"] == spadl.results.index("owngoal")
def test_convert_own_goal(self) -> None:
events_morira = self.WSL.events(2057961)
own_goal_event = events_morira[events_morira.event_id == 258696133]
own_goal_actions = wy.convert_to_actions(own_goal_event, 16216)
assert len(own_goal_actions) == 2 # interception + clearance
assert own_goal_actions.iloc[0]["type_id"] == spadl.actiontypes.index("interception")
assert own_goal_actions.iloc[0]["result_id"] == spadl.results.index("success")
assert own_goal_actions.iloc[1]["type_id"] == spadl.actiontypes.index("bad_touch")
assert own_goal_actions.iloc[1]["result_id"] == spadl.results.index("owngoal")
assert own_goal_actions.iloc[1]["bodypart_id"] == spadl.bodyparts.index("foot")
def test_convert_own_goal_touches(self) -> None:
"""Tests conversion of own goals following a bad touch.
Own goals resulting from bad touch events in the Wyscout event
streams should be included in the SPADL representation.
"""
# An own goal from the game between Leicester and Stoke on 24 Feb 2018.
# Stoke's goalkeeper Jack Butland allows a low cross to bounce off his
# gloves and into the net:
event = pd.DataFrame(
[
{
"type_id": 8,
"subtype_name": "Cross",
"tags": [{"id": 402}, {"id": 801}, {"id": 1802}],
"player_id": 8013,
"positions": [{"y": 89, "x": 97}, {"y": 0, "x": 0}],
"game_id": 2499994,
"type_name": "Pass",
"team_id": 1631,
"period_id": 2,
"milliseconds": 1496.7290489999993,
"subtype_id": 80,
"event_id": 230320305,
},
{
"type_id": 7,
"subtype_name": "Touch",
"tags": [{"id": 102}],
"player_id": 8094,
"positions": [{"y": 50, "x": 1}, {"y": 100, "x": 100}],
"game_id": 2499994,
"type_name": "Others on the ball",
"team_id": 1639,
"period_id": 2,
"milliseconds": 1497.6330749999993,
"subtype_id": 72,
"event_id": 230320132,
},
{
"type_id": 9,
"subtype_name": "Reflexes",
"tags": [{"id": 101}, {"id": 1802}],
"player_id": 8094,
"positions": [{"y": 100, "x": 100}, {"y": 50, "x": 1}],
"game_id": 2499994,
"type_name": "Save attempt",
"team_id": 1639,
"period_id": 2,
"milliseconds": 1499.980547,
"subtype_id": 90,
"event_id": 230320135,
},
]
)
actions = wy.convert_to_actions(event, 1639)
# FIXME: It adds a dribble between the bad touch of the goalkeeper and
# his attempt to save the ball before crossing the line. Not sure
# whether that is ideal.
assert len(actions) == 4
assert actions.at[1, "type_id"] == spadl.actiontypes.index("bad_touch")
assert actions.at[1, "result_id"] == spadl.results.index("owngoal")
def test_convert_simulations_precede_by_take_on(self) -> None:
events = pd.DataFrame(
[
{
"type_id": 1,
"subtype_name": "Ground attacking duel",
"tags": [{"id": 503}, {"id": 701}, {"id": 1802}],
"player_id": 8327,
"positions": [{"y": 48, "x": 82}, {"y": 47, "x": 83}],
"game_id": 2576263,
"type_name": "Duel",
"team_id": 3158,
"period_id": 2,
"milliseconds": 706.309475 * 1000,
"subtype_id": 11,
"event_id": 240828365,
},
{
"type_id": 2,
"subtype_name": "Simulation",
"tags": [{"id": 1702}],
"player_id": 8327,
"positions": [{"y": 47, "x": 83}, {"y": 0, "x": 0}],
"game_id": 2576263,
"type_name": "Foul",
"team_id": 3158,
"period_id": 2,
"milliseconds": 709.1020480000002 * 1000,
"subtype_id": 25,
"event_id": 240828368,
},
]
)
actions = wy.convert_to_actions(events, 3158)
assert len(actions) == 1
assert actions.at[0, "type_id"] == spadl.actiontypes.index("take_on")
assert actions.at[0, "result_id"] == spadl.results.index("fail")
def test_convert_simulations(self) -> None:
events = pd.DataFrame(
[
{
"type_id": 8,
"subtype_name": "Cross",
"tags": [{"id": 402}, {"id": 801}, {"id": 1801}],
"player_id": 20472,
"positions": [{"y": 76, "x": 92}, {"y": 92, "x": 98}],
"game_id": 2575974,
"type_name": "Pass",
"team_id": 3173,
"period_id": 1,
"milliseconds": 1010.5460250000001 * 1000,
"subtype_id": 80,
"event_id": 182640540,
},
{
"type_id": 1,
"subtype_name": "Ground loose ball duel",
"tags": [{"id": 701}, {"id": 1802}],
"player_id": 116171,
"positions": [{"y": 92, "x": 98}, {"y": 43, "x": 87}],
"game_id": 2575974,
"type_name": "Duel",
"team_id": 3173,
"period_id": 1,
"milliseconds": 1012.8018770000001 * 1000,
"subtype_id": 13,
"event_id": 182640541,
},
{
"type_id": 2,
"subtype_name": "Simulation",
"tags": [{"id": 1702}],
"player_id": 116171,
"positions": [{"y": 43, "x": 87}, {"y": 100, "x": 100}],
"game_id": 2575974,
"type_name": "Foul",
"team_id": 3173,
"period_id": 1,
"milliseconds": 1014.7540220000001 * 1000,
"subtype_id": 25,
"event_id": 182640542,
},
]
)
actions = wy.convert_to_actions(events, 3157)
assert len(actions) == 3
assert actions.at[2, "type_id"] == spadl.actiontypes.index("take_on")
assert actions.at[2, "result_id"] == spadl.results.index("fail")