コード例 #1
0
    def _frame_from_row(row: dict, metadata: EPTSMetadata) -> Frame:
        timestamp = row["timestamp"]
        if metadata.periods and row["period_id"]:
            # might want to search for it instead
            period = metadata.periods[row["period_id"] - 1]
        else:
            period = None

        players_coordinates = {}
        for team in metadata.teams:
            for player in team.players:
                if f"player_{player.player_id}_x" in row:
                    players_coordinates[player] = Point(
                        x=row[f"player_{player.player_id}_x"],
                        y=row[f"player_{player.player_id}_y"],
                    )

        return Frame(
            frame_id=row["frame_id"],
            timestamp=timestamp,
            ball_owning_team=None,
            ball_state=None,
            period=period,
            players_coordinates=players_coordinates,
            ball_coordinates=Point(x=row["ball_x"], y=row["ball_y"]),
        )
コード例 #2
0
ファイル: test_helpers.py プロジェクト: PySport/kloppy
    def test_transform_to_coordinate_system(self):
        base_dir = os.path.dirname(__file__)

        dataset = tracab.load(
            meta_data=f"{base_dir}/files/tracab_meta.xml",
            raw_data=f"{base_dir}/files/tracab_raw.dat",
            only_alive=False,
            coordinates="tracab",
        )

        player_home_19 = dataset.metadata.teams[0].get_player_by_jersey_number(
            19)
        assert dataset.records[0].players_data[
            player_home_19].coordinates == Point(x=-1234.0, y=-294.0)

        transformed_dataset = dataset.transform(
            to_coordinate_system=Provider.METRICA)
        transformerd_coordinate_system = MetricaCoordinateSystem(
            normalized=True,
            length=dataset.metadata.coordinate_system.length,
            width=dataset.metadata.coordinate_system.width,
        )

        assert transformed_dataset.records[0].players_data[
            player_home_19].coordinates == Point(x=0.3766,
                                                 y=0.5489999999999999)
        assert (transformed_dataset.metadata.orientation ==
                dataset.metadata.orientation)
        assert (transformed_dataset.metadata.coordinate_system ==
                transformerd_coordinate_system)
        assert (transformed_dataset.metadata.pitch_dimensions ==
                transformerd_coordinate_system.pitch_dimensions)
コード例 #3
0
    def _frame_from_row(row: dict, meta_data: EPTSMetaData) -> Frame:
        timestamp = row["timestamp"]
        if meta_data.periods and row["period_id"]:
            # might want to search for it instead
            period = meta_data.periods[row["period_id"] - 1]
        else:
            period = None

        home_team_player_positions = {}
        away_team_player_positions = {}
        for player in meta_data.players:
            if player.team == Team.HOME:
                if f"player_home_{player.jersey_no}_x" in row:
                    home_team_player_positions[player.jersey_no] = Point(
                        x=row[f"player_home_{player.jersey_no}_x"],
                        y=row[f"player_home_{player.jersey_no}_y"],
                    )
            elif player.team == Team.AWAY:
                if f"player_away_{player.jersey_no}_x" in row:
                    away_team_player_positions[player.jersey_no] = Point(
                        x=row[f"player_away_{player.jersey_no}_x"],
                        y=row[f"player_away_{player.jersey_no}_y"],
                    )

        return Frame(
            frame_id=row["frame_id"],
            timestamp=timestamp,
            ball_owning_team=None,
            ball_state=None,
            period=period,
            home_team_player_positions=home_team_player_positions,
            away_team_player_positions=away_team_player_positions,
            ball_position=Point(x=row["ball_x"], y=row["ball_y"]),
        )
コード例 #4
0
ファイル: serializer.py プロジェクト: ivd-git/kloppy
    def _frame_from_row(row: dict, meta_data: EPTSMetaData) -> Frame:
        timestamp = row['timestamp']
        if meta_data.periods:
            # might want to search for it instead
            period = meta_data.periods[row['period_id'] - 1]
        else:
            period = None

        home_team_player_positions = {}
        away_team_player_positions = {}
        for player in meta_data.players:
            if player.team == Team.HOME:
                home_team_player_positions[player.jersey_no] = Point(
                    x=row[f'player_home_{player.jersey_no}_x'],
                    y=row[f'player_home_{player.jersey_no}_y'])
            elif player.team == Team.AWAY:
                home_team_player_positions[player.jersey_no] = Point(
                    x=row[f'player_away_{player.jersey_no}_x'],
                    y=row[f'player_away_{player.jersey_no}_y'])

        return Frame(frame_id=row['frame_id'],
                     timestamp=timestamp,
                     ball_owning_team=None,
                     ball_state=None,
                     period=period,
                     home_team_player_positions=home_team_player_positions,
                     away_team_player_positions=away_team_player_positions,
                     ball_position=Point(x=row['ball_x'], y=row['ball_y']))
コード例 #5
0
    def _get_tracking_dataset(self):
        home_team = Team(team_id="home", name="home", ground=Ground.HOME)
        away_team = Team(team_id="away", name="away", ground=Ground.AWAY)
        teams = [home_team, away_team]

        periods = [
            Period(
                id=1,
                start_timestamp=0.0,
                end_timestamp=10.0,
                attacking_direction=AttackingDirection.HOME_AWAY,
            ),
            Period(
                id=2,
                start_timestamp=15.0,
                end_timestamp=25.0,
                attacking_direction=AttackingDirection.AWAY_HOME,
            ),
        ]
        metadata = Metadata(
            flags=~(DatasetFlag.BALL_OWNING_TEAM | DatasetFlag.BALL_STATE),
            pitch_dimensions=PitchDimensions(x_dim=Dimension(0, 100),
                                             y_dim=Dimension(-50, 50)),
            orientation=Orientation.HOME_TEAM,
            frame_rate=25,
            periods=periods,
            teams=teams,
            score=None,
            provider=None,
        )

        tracking_data = TrackingDataset(
            metadata=metadata,
            records=[
                Frame(
                    frame_id=1,
                    timestamp=0.1,
                    ball_owning_team=None,
                    ball_state=None,
                    period=periods[0],
                    players_coordinates={},
                    ball_coordinates=Point(x=100, y=-50),
                ),
                Frame(
                    frame_id=2,
                    timestamp=0.2,
                    ball_owning_team=None,
                    ball_state=None,
                    period=periods[0],
                    players_coordinates={
                        Player(team=home_team, player_id="home_1", jersey_no=1):
                        Point(x=15, y=35)
                    },
                    ball_coordinates=Point(x=0, y=50),
                ),
            ],
        )
        return tracking_data
コード例 #6
0
    def test_correct_deserialization(self):
        base_dir = os.path.dirname(__file__)

        serializer = MetricaTrackingSerializer()

        with open(
            f"{base_dir}/files/metrica_home.csv", "rb"
        ) as raw_data_home, open(
            f"{base_dir}/files/metrica_away.csv", "rb"
        ) as raw_data_away:
            dataset = serializer.deserialize(
                inputs={
                    "raw_data_home": raw_data_home,
                    "raw_data_away": raw_data_away,
                }
            )
        assert dataset.metadata.provider == Provider.METRICA
        assert dataset.dataset_type == DatasetType.TRACKING
        assert len(dataset.records) == 6
        assert len(dataset.metadata.periods) == 2
        assert dataset.metadata.orientation == Orientation.FIXED_HOME_AWAY
        assert dataset.metadata.periods[0] == Period(
            id=1,
            start_timestamp=0.04,
            end_timestamp=0.12,
            attacking_direction=AttackingDirection.HOME_AWAY,
        )
        assert dataset.metadata.periods[1] == Period(
            id=2,
            start_timestamp=5800.16,
            end_timestamp=5800.24,
            attacking_direction=AttackingDirection.AWAY_HOME,
        )

        # make sure data is loaded correctly (including flip y-axis)
        home_player = dataset.metadata.teams[0].players[0]
        assert dataset.records[0].players_coordinates[home_player] == Point(
            x=0.00082, y=1 - 0.48238
        )

        away_player = dataset.metadata.teams[1].players[0]
        assert dataset.records[0].players_coordinates[away_player] == Point(
            x=0.90509, y=1 - 0.47462
        )

        assert dataset.records[0].ball_coordinates == Point(
            x=0.45472, y=1 - 0.38709
        )

        # make sure player data is only in the frame when the player is at the pitch
        assert "home_14" not in [
            player.player_id
            for player in dataset.records[0].players_coordinates.keys()
        ]
        assert "home_14" in [
            player.player_id
            for player in dataset.records[3].players_coordinates.keys()
        ]
コード例 #7
0
    def __create_iterator(self, data: Readable, sample_rate: float,
                          frame_rate: int) -> Iterator:
        """
        Notes:
            1. the y-axis is flipped because Metrica use (y, -y) instead of (-y, y)
        """

        team = None
        frame_idx = 0
        frame_sample = 1 / sample_rate
        player_jersey_numbers = []
        period = None

        for i, line in enumerate(data):
            line = line.strip().decode("ascii")
            columns = line.split(",")
            if i == 0:
                team = columns[3]
            elif i == 1:
                player_jersey_numbers = columns[3:-2:2]
            elif i == 2:
                # consider doing some validation on the columns
                pass
            else:
                period_id = int(columns[0])
                frame_id = int(columns[1])

                if period is None or period.id != period_id:
                    period = Period(
                        id=period_id,
                        start_timestamp=frame_id / frame_rate,
                        end_timestamp=frame_id / frame_rate,
                    )
                else:
                    # consider not update this every frame for performance reasons
                    period.end_timestamp = frame_id / frame_rate

                if frame_idx % frame_sample == 0:
                    yield self.__PartialFrame(
                        team=team,
                        period=period,
                        frame_id=frame_id,
                        player_positions={
                            player_no: Point(
                                x=float(columns[3 + i * 2]),
                                y=1 - float(columns[3 + i * 2 + 1]),
                            )
                            for i, player_no in enumerate(
                                player_jersey_numbers)
                            if columns[3 + i * 2] != "NaN"
                        },
                        ball_position=Point(x=float(columns[-2]),
                                            y=1 - float(columns[-1]))
                        if columns[-2] != "NaN" else None,
                    )
                frame_idx += 1
コード例 #8
0
    def test_transform(self):
        tracking_data = self._get_dataset()

        # orientation change AND dimension scale
        transformed_data_set = transform(tracking_data,
                                         to_orientation="AWAY_TEAM",
                                         to_pitch_dimensions=[[0, 1], [0, 1]])

        assert transformed_data_set.frames[0].ball_position == Point(x=0, y=1)
        assert transformed_data_set.frames[1].ball_position == Point(x=1, y=0)
コード例 #9
0
    def test_correct_deserialization(self, meta_data: str, raw_data: str,
                                     additional_meta_data: str):
        dataset = secondspectrum.load(
            meta_data=meta_data,
            raw_data=raw_data,
            additional_meta_data=additional_meta_data,
            only_alive=False,
            coordinates="secondspectrum",
        )

        # Check provider, type, shape, etc
        assert dataset.metadata.provider == Provider.SECONDSPECTRUM
        assert dataset.dataset_type == DatasetType.TRACKING
        assert len(dataset.records) == 376
        assert len(dataset.metadata.periods) == 2
        assert dataset.metadata.orientation == Orientation.FIXED_AWAY_HOME

        # Check the Periods
        assert dataset.metadata.periods[0].id == 1
        assert dataset.metadata.periods[0].start_timestamp == 0
        assert dataset.metadata.periods[0].end_timestamp == 2982240
        assert (dataset.metadata.periods[0].attacking_direction ==
                AttackingDirection.AWAY_HOME)

        assert dataset.metadata.periods[1].id == 2
        assert dataset.metadata.periods[1].start_timestamp == 3907360
        assert dataset.metadata.periods[1].end_timestamp == 6927840
        assert (dataset.metadata.periods[1].attacking_direction ==
                AttackingDirection.HOME_AWAY)

        # Check some timestamps
        assert dataset.records[0].timestamp == 0  # First frame
        assert dataset.records[20].timestamp == 320.0  # Later frame

        # Check some players
        home_player = dataset.metadata.teams[0].players[2]
        assert home_player.player_id == "8xwx2"
        assert dataset.records[0].players_coordinates[home_player] == Point(
            x=-8.943903672572427, y=-28.171654132650364)

        away_player = dataset.metadata.teams[1].players[3]
        assert away_player.player_id == "2q0uv"
        assert dataset.records[0].players_coordinates[away_player] == Point(
            x=-45.11871334915762, y=-20.06459030559596)

        # Check the ball
        assert dataset.records[1].ball_coordinates == Point3D(
            x=-23.147073918432426, y=13.69367399756424, z=0.0)

        # Check pitch dimensions
        pitch_dimensions = dataset.metadata.pitch_dimensions
        assert pitch_dimensions.x_dim.min == -52.425
        assert pitch_dimensions.x_dim.max == 52.425
        assert pitch_dimensions.y_dim.min == -33.985
        assert pitch_dimensions.y_dim.max == 33.985
コード例 #10
0
ファイル: tracab.py プロジェクト: MKlaasman/kloppy
    def _frame_from_line(cls, period, line, frame_rate):
        line = str(line)
        frame_id, players, ball = line.strip().split(":")[:3]

        home_team_player_positions = {}
        away_team_player_positions = {}

        for player in players.split(";")[:-1]:
            team_id, target_id, jersey_no, x, y, speed = player.split(",")
            team_id = int(team_id)

            if team_id == 1:
                home_team_player_positions[jersey_no] = Point(
                    float(x), float(y))
            elif team_id == 0:
                away_team_player_positions[jersey_no] = Point(
                    float(x), float(y))

        (
            ball_x,
            ball_y,
            ball_z,
            ball_speed,
            ball_owning_team,
            ball_state,
        ) = ball.rstrip(";").split(",")[:6]

        frame_id = int(frame_id)

        if ball_owning_team == "H":
            ball_owning_team = Team.HOME
        elif ball_owning_team == "A":
            ball_owning_team = Team.AWAY
        else:
            raise Exception(f"Unknown ball owning team: {ball_owning_team}")

        if ball_state == "Alive":
            ball_state = BallState.ALIVE
        elif ball_state == "Dead":
            ball_state = BallState.DEAD
        else:
            raise Exception(f"Unknown ball state: {ball_state}")

        return Frame(
            frame_id=frame_id,
            timestamp=frame_id / frame_rate - period.start_timestamp,
            ball_position=Point(float(ball_x), float(ball_y)),
            ball_state=ball_state,
            ball_owning_team=ball_owning_team,
            home_team_player_positions=home_team_player_positions,
            away_team_player_positions=away_team_player_positions,
            period=period,
        )
コード例 #11
0
ファイル: test_tracab.py プロジェクト: MKlaasman/kloppy
    def test_correct_deserialization(self):
        base_dir = os.path.dirname(__file__)

        serializer = TRACABSerializer()

        with open(f"{base_dir}/files/tracab_meta.xml",
                  "rb") as meta_data, open(f"{base_dir}/files/tracab_raw.dat",
                                           "rb") as raw_data:

            dataset = serializer.deserialize(
                inputs={
                    "meta_data": meta_data,
                    "raw_data": raw_data
                },
                options={"only_alive": False},
            )

        assert len(dataset.records) == 6
        assert len(dataset.periods) == 2
        assert dataset.orientation == Orientation.FIXED_HOME_AWAY
        assert dataset.periods[0] == Period(
            id=1,
            start_timestamp=4.0,
            end_timestamp=4.08,
            attacking_direction=AttackingDirection.HOME_AWAY,
        )

        assert dataset.periods[1] == Period(
            id=2,
            start_timestamp=8.0,
            end_timestamp=8.08,
            attacking_direction=AttackingDirection.AWAY_HOME,
        )

        assert dataset.records[0].home_team_player_positions["19"] == Point(
            x=-1234.0, y=-294.0)
        assert dataset.records[0].away_team_player_positions["19"] == Point(
            x=8889, y=-666)
        assert dataset.records[0].ball_position == Point(x=-27, y=25)
        assert dataset.records[0].ball_state == BallState.ALIVE
        assert dataset.records[0].ball_owning_team == Team.HOME

        assert dataset.records[1].ball_owning_team == Team.AWAY

        assert dataset.records[2].ball_state == BallState.DEAD

        # make sure player data is only in the frame when the player is at the pitch
        assert "1337" not in dataset.records[0].away_team_player_positions
        assert "1337" in dataset.records[3].away_team_player_positions
コード例 #12
0
 def test_correct_normalized_deserialization(self, f7_data: str,
                                             f24_data: str):
     dataset = opta.load(
         f24_data=f24_data,
         f7_data=f7_data,
     )
     assert dataset.events[0].coordinates == Point(0.501, 0.506)
コード例 #13
0
    def test_correct_deserialization(self):
        base_dir = os.path.dirname(__file__)

        serializer = EPTSSerializer()

        with open(f"{base_dir}/files/epts_meta.xml",
                  "rb") as metadata, open(f"{base_dir}/files/epts_raw.txt",
                                          "rb") as raw_data:

            dataset = serializer.deserialize(inputs={
                "metadata": metadata,
                "raw_data": raw_data
            })

        first_player = next(iter(dataset.records[0].players_coordinates))

        assert len(dataset.records) == 2
        assert len(dataset.metadata.periods) == 1
        assert dataset.metadata.orientation is None

        assert dataset.records[0].players_coordinates[first_player] == Point(
            x=-769, y=-2013)

        assert dataset.records[0].ball_coordinates == Point3D(x=-2656,
                                                              y=367,
                                                              z=100)
コード例 #14
0
ファイル: dataset.py プロジェクト: PySport/kloppy
    def __change_point_coordinate_system(self, point: Union[Point, Point3D]):

        if not point:
            return None

        x = self._from_coordinate_system.pitch_dimensions.x_dim.to_base(
            point.x
        )
        y = self._from_coordinate_system.pitch_dimensions.y_dim.to_base(
            point.y
        )

        if (
            self._from_coordinate_system.vertical_orientation
            != self._to_coordinate_system.vertical_orientation
        ):
            y = 1 - y

        if not self._to_coordinate_system.normalized:
            x = self._to_coordinate_system.pitch_dimensions.x_dim.from_base(x)
            y = self._to_coordinate_system.pitch_dimensions.y_dim.from_base(y)

        if isinstance(point, Point3D):
            return Point3D(x=x, y=y, z=point.z)
        else:
            return Point(x=x, y=y)
コード例 #15
0
ファイル: deserializer.py プロジェクト: PySport/kloppy
def _parse_coordinates(event_attributes: Dict) -> Point:
    if "X-Position" not in event_attributes:
        return None
    return Point(
        x=float(event_attributes["X-Position"]),
        y=float(event_attributes["Y-Position"]),
    )
コード例 #16
0
def _parse_shot(raw_event: Dict, next_event: Dict) -> Dict:
    result = None
    qualifiers = _generic_qualifiers(raw_event)
    if _has_tag(raw_event, 101):
        result = ShotResult.GOAL
    elif _has_tag(raw_event, 2101):
        result = ShotResult.BLOCKED
    elif any((_has_tag(raw_event, tag) for tag in wyscout_tags.SHOT_POST)):
        result = ShotResult.POST
    elif any(
        (_has_tag(raw_event, tag) for tag in wyscout_tags.SHOT_OFF_TARGET)
    ):
        result = ShotResult.OFF_TARGET
    elif any((_has_tag(raw_event, tag) for tag in wyscout_tags.SHOT_ON_GOAL)):
        result = ShotResult.SAVED

    if next_event["eventName"] == wyscout_events.SAVE.EVENT:
        if next_event["subEventName"] == wyscout_events.SAVE.REFLEXES:
            qualifiers.append(
                GoalkeeperActionQualifier(GoalkeeperAction.REFLEX)
            )
        if next_event["subEventName"] == wyscout_events.SAVE.SAVE_ATTEMPT:
            qualifiers.append(
                GoalkeeperActionQualifier(GoalkeeperAction.SAVE_ATTEMPT)
            )

    return {
        "result": result,
        "result_coordinates": Point(
            x=float(raw_event["positions"][1]["x"]),
            y=float(raw_event["positions"][1]["y"]),
        ),
        "qualifiers": qualifiers,
    }
コード例 #17
0
def _parse_pass(raw_event: Dict, next_event: Dict) -> Dict:
    pass_result = None

    if _has_tag(raw_event, wyscout_tags.ACCURATE):
        pass_result = PassResult.COMPLETE
    elif _has_tag(raw_event, wyscout_tags.NOT_ACCURATE):
        pass_result = PassResult.INCOMPLETE

    if next_event:
        if next_event["eventName"] == wyscout_events.OFFSIDE.EVENT:
            pass_result = PassResult.OFFSIDE
        if next_event["eventName"] == wyscout_events.INTERRUPTION.EVENT:
            if (
                next_event["subEventName"]
                == wyscout_events.INTERRUPTION.BALL_OUT
            ):
                pass_result = PassResult.OUT

    return {
        "result": pass_result,
        "qualifiers": _pass_qualifiers(raw_event),
        "receive_timestamp": None,
        "receiver_player": None,
        "receiver_coordinates": Point(
            x=float(raw_event["positions"][1]["x"]),
            y=float(raw_event["positions"][1]["y"]),
        ),
    }
コード例 #18
0
ファイル: deserializer.py プロジェクト: PySport/kloppy
def _parse_coordinates(coordinates: Dict[str, float]) -> Point:
    # location is cell based
    # +-------+-------+
    # | -1,-1 |  1,-1 |
    # +-------+-------+
    # | -1,1  |  1,1  |
    # +-------+-------+
    return Point(x=coordinates["x"], y=coordinates["y"])
コード例 #19
0
ファイル: test_helpers.py プロジェクト: MKlaasman/kloppy
 def _get_tracking_dataset(self):
     periods = [
         Period(
             id=1,
             start_timestamp=0.0,
             end_timestamp=10.0,
             attacking_direction=AttackingDirection.HOME_AWAY,
         ),
         Period(
             id=2,
             start_timestamp=15.0,
             end_timestamp=25.0,
             attacking_direction=AttackingDirection.AWAY_HOME,
         ),
     ]
     tracking_data = TrackingDataset(
         flags=~(DatasetFlag.BALL_OWNING_TEAM | DatasetFlag.BALL_STATE),
         pitch_dimensions=PitchDimensions(x_dim=Dimension(0, 100),
                                          y_dim=Dimension(-50, 50)),
         orientation=Orientation.HOME_TEAM,
         frame_rate=25,
         records=[
             Frame(
                 frame_id=1,
                 timestamp=0.1,
                 ball_owning_team=None,
                 ball_state=None,
                 period=periods[0],
                 away_team_player_positions={},
                 home_team_player_positions={},
                 ball_position=Point(x=100, y=-50),
             ),
             Frame(
                 frame_id=2,
                 timestamp=0.2,
                 ball_owning_team=None,
                 ball_state=None,
                 period=periods[0],
                 away_team_player_positions={"1": Point(x=10, y=20)},
                 home_team_player_positions={"1": Point(x=15, y=35)},
                 ball_position=Point(x=0, y=50),
             ),
         ],
         periods=periods,
     )
     return tracking_data
コード例 #20
0
    def test_correct_normalized_deserialization(self, lineup_data: str,
                                                event_data: str):
        """
        This test uses data from the StatsBomb open data project.
        """
        dataset = statsbomb.load(lineup_data=lineup_data,
                                 event_data=event_data)

        assert dataset.events[10].coordinates == Point(0.2875, 0.25625)
コード例 #21
0
def _parse_shot(qualifiers: Dict[int, str], type_id: int,
                position: Point) -> Dict:
    if type_id == EVENT_TYPE_SHOT_GOAL:
        if 28 in qualifiers:
            position = Point(x=100 - position.x, y=100 - position.y)
        result = ShotResult.GOAL
    else:
        result = None

    return dict(position=position, result=result)
コード例 #22
0
def _parse_shot(qualifiers: Dict[int, str], type_id: int,
                coordinates: Point) -> Dict:
    if type_id == EVENT_TYPE_SHOT_GOAL:
        if 28 in qualifiers:
            coordinates = Point(x=100 - coordinates.x, y=100 - coordinates.y)
        result = ShotResult.GOAL
    else:
        result = None

    return dict(coordinates=coordinates, result=result)
コード例 #23
0
ファイル: test_skillcorner.py プロジェクト: PySport/kloppy
    def test_correct_normalized_deserialization(
        self, meta_data: str, raw_data: str
    ):
        base_dir = os.path.dirname(__file__)
        dataset = skillcorner.load(meta_data=meta_data, raw_data=raw_data)

        home_player = dataset.metadata.teams[0].players[2]
        assert dataset.records[0].players_data[
            home_player
        ].coordinates == Point(x=0.8225688718076191, y=0.6405503322430882)
コード例 #24
0
def _parse_coordinates(event_start_or_end: dict) -> Point:
    x = event_start_or_end["x"]
    y = event_start_or_end["y"]
    if x is None:
        return None

    return Point(
        x=x,
        y=y,
    )
コード例 #25
0
ファイル: test_metrica_csv.py プロジェクト: PySport/kloppy
    def test_correct_deserialization(self, home_data: str, away_data: str):
        dataset = metrica.load_tracking_csv(home_data=home_data,
                                            away_data=away_data)
        assert dataset.metadata.provider == Provider.METRICA
        assert dataset.dataset_type == DatasetType.TRACKING
        assert len(dataset.records) == 6
        assert len(dataset.metadata.periods) == 2
        assert dataset.metadata.orientation == Orientation.FIXED_HOME_AWAY
        assert dataset.metadata.periods[0] == Period(
            id=1,
            start_timestamp=0.04,
            end_timestamp=0.12,
            attacking_direction=AttackingDirection.HOME_AWAY,
        )
        assert dataset.metadata.periods[1] == Period(
            id=2,
            start_timestamp=5800.16,
            end_timestamp=5800.24,
            attacking_direction=AttackingDirection.AWAY_HOME,
        )

        # make sure data is loaded correctly (including flip y-axis)
        home_player = dataset.metadata.teams[0].players[0]
        assert dataset.records[0].players_data[
            home_player].coordinates == Point(x=0.00082, y=1 - 0.48238)

        away_player = dataset.metadata.teams[1].players[0]
        assert dataset.records[0].players_data[
            away_player].coordinates == Point(x=0.90509, y=1 - 0.47462)

        assert dataset.records[0].ball_coordinates == Point(x=0.45472,
                                                            y=1 - 0.38709)

        # make sure player data is only in the frame when the player is at the pitch
        assert "home_14" not in [
            player.player_id
            for player in dataset.records[0].players_data.keys()
        ]
        assert "home_14" in [
            player.player_id
            for player in dataset.records[3].players_data.keys()
        ]
コード例 #26
0
    def _frame_from_row(row: dict, metadata: EPTSMetadata,
                        transformer: DatasetTransformer) -> Frame:
        timestamp = row["timestamp"]
        if metadata.periods and row["period_id"]:
            # might want to search for it instead
            period = metadata.periods[row["period_id"] - 1]
        else:
            period = None

        other_sensors = []
        for sensor in metadata.sensors:
            if sensor.sensor_id not in ["position", "distance", "speed"]:
                other_sensors.append(sensor)

        players_data = {}
        for team in metadata.teams:
            for player in team.players:

                other_data = {}
                for sensor in other_sensors:
                    other_data.update({
                        sensor.sensor_id:
                        row[f"player_{player.player_id}_{sensor.channels[0].channel_id}"]
                    })

                players_data[player] = PlayerData(
                    coordinates=Point(
                        x=row[f"player_{player.player_id}_x"],
                        y=row[f"player_{player.player_id}_y"],
                    ) if f"player_{player.player_id}_x" in row else None,
                    speed=row[f"player_{player.player_id}_s"]
                    if f"player_{player.player_id}_s" in row else None,
                    distance=row[f"player_{player.player_id}_d"]
                    if f"player_{player.player_id}_d" in row else None,
                    other_data=other_data,
                )

        frame = Frame(
            frame_id=row["frame_id"],
            timestamp=timestamp,
            ball_owning_team=None,
            ball_state=None,
            period=period,
            players_data=players_data,
            other_data={},
            ball_coordinates=Point3D(x=row["ball_x"],
                                     y=row["ball_y"],
                                     z=row.get("ball_z")),
        )

        if transformer:
            frame = transformer.transform_frame(frame)

        return frame
コード例 #27
0
def _parse_pass(raw_qualifiers: Dict[int, str], outcome: int) -> Dict:
    if outcome:
        receiver_coordinates = Point(x=float(raw_qualifiers[140]),
                                     y=float(raw_qualifiers[141]))
        result = PassResult.COMPLETE
    else:
        result = PassResult.INCOMPLETE
        # receiver_coordinates = None
        receiver_coordinates = Point(x=float(raw_qualifiers[140]),
                                     y=float(raw_qualifiers[141]))

    qualifiers = _get_event_qualifiers(raw_qualifiers)

    return dict(
        result=result,
        receiver_coordinates=receiver_coordinates,
        receiver_player=None,
        receive_timestamp=None,
        qualifiers=qualifiers,
    )
コード例 #28
0
ファイル: test_metrica.py プロジェクト: MKlaasman/kloppy
    def test_correct_deserialization(self):
        base_dir = os.path.dirname(__file__)

        serializer = MetricaTrackingSerializer()

        with open(f"{base_dir}/files/metrica_home.csv",
                  "rb") as raw_data_home, open(
                      f"{base_dir}/files/metrica_away.csv",
                      "rb") as raw_data_away:
            dataset = serializer.deserialize(inputs={
                "raw_data_home": raw_data_home,
                "raw_data_away": raw_data_away,
            })

        assert len(dataset.records) == 6
        assert len(dataset.periods) == 2
        assert dataset.orientation == Orientation.FIXED_HOME_AWAY
        assert dataset.periods[0] == Period(
            id=1,
            start_timestamp=0.04,
            end_timestamp=0.12,
            attacking_direction=AttackingDirection.HOME_AWAY,
        )
        assert dataset.periods[1] == Period(
            id=2,
            start_timestamp=5800.16,
            end_timestamp=5800.24,
            attacking_direction=AttackingDirection.AWAY_HOME,
        )

        # make sure data is loaded correctly (including flip y-axis)
        assert dataset.records[0].home_team_player_positions["11"] == Point(
            x=0.00082, y=1 - 0.48238)
        assert dataset.records[0].away_team_player_positions["25"] == Point(
            x=0.90509, y=1 - 0.47462)
        assert dataset.records[0].ball_position == Point(x=0.45472,
                                                         y=1 - 0.38709)

        # make sure player data is only in the frame when the player is at the pitch
        assert "14" not in dataset.records[0].home_team_player_positions
        assert "14" in dataset.records[3].home_team_player_positions
コード例 #29
0
ファイル: serializer.py プロジェクト: dmallory42/kloppy
def _parse_position(position: List[float], fidelity_version: int) -> Point:
    # location is cell based
    # [1, 120] x [1, 80]
    # +-----+------+
    # | 1,1 | 2, 1 |
    # +-----+------+
    # | 1,2 | 2,2  |
    # +-----+------+
    cell_side = 0.1 if fidelity_version == 2 else 1.0
    cell_relative_center = cell_side / 2
    return Point(x=position[0] - cell_relative_center,
                 y=position[1] - cell_relative_center)
コード例 #30
0
ファイル: __init__.py プロジェクト: aeroaks/kloppy
    def transform_point(self, point: Point, flip: bool) -> Point:
        # 1. always apply changes from coordinate system
        # 2. flip coordinates depending on orientation
        x_base = self._from_pitch_dimensions.x_dim.to_base(point.x)
        y_base = self._from_pitch_dimensions.y_dim.to_base(point.y)

        if flip:
            x_base = 1 - x_base
            y_base = 1 - y_base

        return Point(x=self._to_pitch_dimensions.x_dim.from_base(x_base),
                     y=self._to_pitch_dimensions.y_dim.from_base(y_base))