Skip to content

Commit

Permalink
Merge pull request #246 from probberechts/feat/wyscout-shot-result-co…
Browse files Browse the repository at this point in the history
…ordinates

Estimate Wyscout v2 shot result coordinates
  • Loading branch information
koenvo authored Dec 26, 2023
2 parents 789f34b + 713d45b commit a288d08
Showing 1 changed file with 77 additions and 7 deletions.
84 changes: 77 additions & 7 deletions kloppy/infra/serializers/event/wyscout/deserializer_v2.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import json
import logging
from typing import Dict, List, Tuple, NamedTuple, IO
from typing import Dict, List, Tuple, NamedTuple, IO, Optional

from kloppy.domain import (
BodyPart,
Expand Down Expand Up @@ -80,6 +80,81 @@ def _generic_qualifiers(raw_event: Dict) -> List[Qualifier]:
return qualifiers


def _create_shot_result_coordinates(raw_event: Dict) -> Optional[Point]:
"""Estimate the shot end location from the Wyscout tags.
Wyscout does not provide end-coordinates of shots. Instead shots on goal
are tagged with a zone. This function maps each of these zones to
a coordinate. The zones and corresponding y-coordinate are depicted below.
ohl | ohc | ohr
--------------------------------
||=================||
-------------------------------
|| ghl | ghc | ghr ||
--------------------------------
ocl || gcl | gc | gcr || ocr
--------------------------------
oll || gll | glc | glr || olr
40 45 50 55 60 (y-coordinate of zone)
44.62 55.38 (y-coordiante of post)
"""
if (
_has_tag(raw_event, wyscout_tags.GOAL_LOW_CENTER)
or _has_tag(raw_event, wyscout_tags.GOAL_CENTER)
or _has_tag(raw_event, wyscout_tags.GOAL_HIGH_CENTER)
):
return Point(100.0, 50.0)
if (
_has_tag(raw_event, wyscout_tags.GOAL_LOW_RIGHT)
or _has_tag(raw_event, wyscout_tags.GOAL_CENTER_RIGHT)
or _has_tag(raw_event, wyscout_tags.GOAL_HIGH_RIGHT)
):
return Point(100.0, 55.0)
if (
_has_tag(raw_event, wyscout_tags.GOAL_LOW_LEFT)
or _has_tag(raw_event, wyscout_tags.GOAL_CENTER_LEFT)
or _has_tag(raw_event, wyscout_tags.GOAL_HIGH_LEFT)
):
return Point(100.0, 45.0)
if _has_tag(raw_event, wyscout_tags.OUT_HIGH_CENTER) or _has_tag(
raw_event, wyscout_tags.POST_HIGH_CENTER
):
return Point(100.0, 50.0)
if (
_has_tag(raw_event, wyscout_tags.OUT_LOW_RIGHT)
or _has_tag(raw_event, wyscout_tags.OUT_CENTER_RIGHT)
or _has_tag(raw_event, wyscout_tags.OUT_HIGH_RIGHT)
):
return Point(100.0, 60.0)
if (
_has_tag(raw_event, wyscout_tags.OUT_LOW_LEFT)
or _has_tag(raw_event, wyscout_tags.OUT_CENTER_LEFT)
or _has_tag(raw_event, wyscout_tags.OUT_HIGH_LEFT)
):
return Point(100.0, 40.0)
if (
_has_tag(raw_event, wyscout_tags.POST_LOW_LEFT)
or _has_tag(raw_event, wyscout_tags.POST_CENTER_LEFT)
or _has_tag(raw_event, wyscout_tags.POST_HIGH_LEFT)
):
return Point(100.0, 55.38)
if (
_has_tag(raw_event, wyscout_tags.POST_LOW_RIGHT)
or _has_tag(raw_event, wyscout_tags.POST_CENTER_RIGHT)
or _has_tag(raw_event, wyscout_tags.POST_HIGH_RIGHT)
):
return Point(100.0, 44.62)
if _has_tag(raw_event, wyscout_tags.BLOCKED):
return Point(
x=float(raw_event["positions"][0]["x"]),
y=float(raw_event["positions"][0]["y"]),
)
return None


def _parse_shot(raw_event: Dict, next_event: Dict) -> Dict:
result = None
qualifiers = _generic_qualifiers(raw_event)
Expand All @@ -106,12 +181,7 @@ def _parse_shot(raw_event: Dict, next_event: Dict) -> Dict:

return {
"result": result,
"result_coordinates": Point(
x=float(raw_event["positions"][1]["x"]),
y=float(raw_event["positions"][1]["y"]),
)
if len(raw_event["positions"]) > 1
else None,
"result_coordinates": _create_shot_result_coordinates(raw_event),
"qualifiers": qualifiers,
}

Expand Down

0 comments on commit a288d08

Please sign in to comment.