Ejemplo n.º 1
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
Ejemplo n.º 2
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"]),
        )
Ejemplo n.º 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"]),
        )
Ejemplo n.º 4
0
    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']))
Ejemplo n.º 5
0
    def transform_frame(self, frame: Frame) -> Frame:
        flip = self.__needs_flip(
            ball_owning_team=frame.ball_owning_team,
            attacking_direction=frame.period.attacking_direction)

        return Frame(
            # doesn't change
            timestamp=frame.timestamp,
            frame_id=frame.frame_id,
            ball_owning_team=frame.ball_owning_team,
            ball_state=frame.ball_state,
            period=frame.period,

            # changes
            ball_position=self.transform_point(frame.ball_position, flip),
            home_team_player_positions={
                jersey_no: self.transform_point(point, flip)
                for jersey_no, point in
                frame.home_team_player_positions.items()
            },
            away_team_player_positions={
                jersey_no: self.transform_point(point, flip)
                for jersey_no, point in
                frame.away_team_player_positions.items()
            })
Ejemplo n.º 6
0
    def __change_frame_dimensions(self, frame: Frame):

        return Frame(
            # doesn't change
            timestamp=frame.timestamp,
            frame_id=frame.frame_id,
            ball_owning_team=frame.ball_owning_team,
            ball_state=frame.ball_state,
            period=frame.period,
            # changes
            ball_coordinates=self.change_point_dimensions(
                frame.ball_coordinates
            ),
            players_data={
                key: PlayerData(
                    coordinates=self.change_point_dimensions(
                        player_data.coordinates
                    ),
                    distance=player_data.distance,
                    speed=player_data.speed,
                    other_data=player_data.other_data,
                )
                for key, player_data in frame.players_data.items()
            },
            other_data=frame.other_data,
        )
Ejemplo n.º 7
0
 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
Ejemplo n.º 8
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
Ejemplo n.º 9
0
    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,
        )
Ejemplo n.º 10
0
    def _frame_from_framedata(cls, teams, period, frame_data):

        frame_id = frame_data["frameIdx"]
        frame_timestamp = frame_data["gameClock"]

        if frame_data["ball"]["xyz"]:
            ball_x, ball_y, ball_z = frame_data["ball"]["xyz"]
            ball_coordinates = Point3D(
                float(ball_x), float(ball_y), float(ball_z)
            )
        else:
            ball_coordinates = None

        ball_state = BallState.ALIVE if frame_data["live"] else BallState.DEAD
        ball_owning_team = (
            teams[0] if frame_data["lastTouch"] == "home" else teams[1]
        )

        players_data = {}
        for team, team_str in zip(teams, ["homePlayers", "awayPlayers"]):
            for player_data in frame_data[team_str]:

                jersey_no = player_data["number"]
                x, y, _ = player_data["xyz"]
                player = team.get_player_by_jersey_number(jersey_no)

                if not player:
                    player = Player(
                        player_id=player_data["playerId"],
                        team=team,
                        jersey_no=int(jersey_no),
                    )
                    team.players.append(player)

                players_data[player] = PlayerData(
                    coordinates=Point(float(x), float(y))
                )

        return Frame(
            frame_id=frame_id,
            timestamp=frame_timestamp,
            ball_coordinates=ball_coordinates,
            ball_state=ball_state,
            ball_owning_team=ball_owning_team,
            players_data=players_data,
            period=period,
            other_data={},
        )
Ejemplo n.º 11
0
    def transform_frame(self, frame: Frame) -> Frame:
        flip = self.__needs_flip(
            ball_owning_team=frame.ball_owning_team,
            attacking_direction=frame.period.attacking_direction,
        )

        return Frame(
            # doesn't change
            timestamp=frame.timestamp,
            frame_id=frame.frame_id,
            ball_owning_team=frame.ball_owning_team,
            ball_state=frame.ball_state,
            period=frame.period,
            # changes
            ball_coordinates=self.transform_point(frame.ball_coordinates,
                                                  flip),
            players_coordinates={
                key: self.transform_point(point, flip)
                for key, point in frame.players_coordinates.items()
            },
        )
Ejemplo n.º 12
0
    def __flip_frame(self, frame: Frame):

        players_data = {}
        for player, data in frame.players_data.items():
            players_data[player] = PlayerData(
                coordinates=self.flip_point(data.coordinates),
                distance=data.distance,
                speed=data.speed,
                other_data=data.other_data,
            )

        return Frame(
            # doesn't change
            timestamp=frame.timestamp,
            frame_id=frame.frame_id,
            ball_owning_team=frame.ball_owning_team,
            ball_state=frame.ball_state,
            period=frame.period,
            # changes
            ball_coordinates=self.flip_point(frame.ball_coordinates),
            players_data=players_data,
            other_data=frame.other_data,
        )
Ejemplo n.º 13
0
    def deserialize(self,
                    inputs: Dict[str, Readable],
                    options: Dict = None) -> TrackingDataset:
        """
        Deserialize Metrica tracking data into a `TrackingDataset`.

        Parameters
        ----------
        inputs : dict
            input `raw_data_home` should point to a `Readable` object containing
            the 'csv' formatted raw data for the home team. input `raw_data_away` should point
            to a `Readable` object containing the 'csv' formatted raw data for the away team.
        options : dict
            Options for deserialization of the Metrica file. Possible options are
            `sample_rate` (float between 0 and 1) to specify the amount of
            frames that should be loaded, `limit` to specify the max number of
            frames that will be returned.
        Returns
        -------
        dataset : TrackingDataset
        Raises
        ------
        ValueError when both input files don't seem to belong to each other

        See Also
        --------

        Examples
        --------
        >>> serializer = MetricaTrackingSerializer()
        >>> with open("Sample_Game_1_RawTrackingData_Away_Team.csv", "rb") as raw_home, \
        >>>      open("Sample_Game_1_RawTrackingData_Home_Team.csv", "rb") as raw_away:
        >>>
        >>>     dataset = serializer.deserialize(
        >>>         inputs={
        >>>             'raw_data_home': raw_home,
        >>>             'raw_data_away': raw_away
        >>>         },
        >>>         options={
        >>>             'sample_rate': 1/12
        >>>         }
        >>>     )
        """
        self.__validate_inputs(inputs)
        if not options:
            options = {}

        sample_rate = float(options.get('sample_rate', 1.0))
        limit = int(options.get('limit', 0))

        # consider reading this from data
        frame_rate = 25

        with performance_logging("prepare", logger=logger):
            home_iterator = self.__create_iterator(inputs['raw_data_home'],
                                                   sample_rate, frame_rate)
            away_iterator = self.__create_iterator(inputs['raw_data_away'],
                                                   sample_rate, frame_rate)

            partial_frames = zip(home_iterator, away_iterator)

        with performance_logging("loading", logger=logger):
            frames = []
            periods = []

            partial_frame_type = self.__PartialFrame
            home_partial_frame: partial_frame_type
            away_partial_frame: partial_frame_type
            for n, (home_partial_frame,
                    away_partial_frame) in enumerate(partial_frames):
                self.__validate_partials(home_partial_frame,
                                         away_partial_frame)

                period: Period = home_partial_frame.period
                frame_id: int = home_partial_frame.frame_id

                frame = Frame(frame_id=frame_id,
                              timestamp=frame_id / frame_rate -
                              period.start_timestamp,
                              ball_position=home_partial_frame.ball_position,
                              home_team_player_positions=home_partial_frame.
                              player_positions,
                              away_team_player_positions=away_partial_frame.
                              player_positions,
                              period=period,
                              ball_state=None,
                              ball_owning_team=None)

                frames.append(frame)

                if not periods or period.id != periods[-1].id:
                    periods.append(period)

                if not period.attacking_direction_set:
                    period.set_attacking_direction(
                        attacking_direction=attacking_direction_from_frame(
                            frame))

                n += 1
                if limit and n >= limit:
                    break

        orientation = (
            Orientation.FIXED_HOME_AWAY if periods[0].attacking_direction
            == AttackingDirection.HOME_AWAY else Orientation.FIXED_AWAY_HOME)

        return TrackingDataset(
            flags=~(DatasetFlag.BALL_STATE | DatasetFlag.BALL_OWNING_TEAM),
            frame_rate=frame_rate,
            orientation=orientation,
            pitch_dimensions=PitchDimensions(x_dim=Dimension(0, 1),
                                             y_dim=Dimension(0, 1)),
            periods=periods,
            records=frames)
Ejemplo n.º 14
0
    def _frame_from_line(cls, teams, period, line, frame_rate):
        line = str(line)
        frame_id, players, ball = line.strip().split(":")[:3]

        players_data = {}

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

            if team_id == 1:
                team = teams[0]
            elif team_id == 0:
                team = teams[1]
            else:
                # it's probably -1, but make sure it doesn't crash
                continue

            player = team.get_player_by_jersey_number(jersey_no)

            if not player:
                player = Player(
                    player_id=f"{team.ground}_{jersey_no}",
                    team=team,
                    jersey_no=int(jersey_no),
                )
                team.players.append(player)

            players_data[player] = PlayerData(
                coordinates=Point(float(x), float(y)), speed=float(speed)
            )

        (
            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 = teams[0]
        elif ball_owning_team == "A":
            ball_owning_team = teams[1]
        else:
            raise DeserializationError(
                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 DeserializationError(f"Unknown ball state: {ball_state}")

        return Frame(
            frame_id=frame_id,
            timestamp=frame_id / frame_rate - period.start_timestamp,
            ball_coordinates=Point3D(
                float(ball_x), float(ball_y), float(ball_z)
            ),
            ball_state=ball_state,
            ball_owning_team=ball_owning_team,
            players_data=players_data,
            period=period,
            other_data={},
        )
Ejemplo n.º 15
0
    def _get_frame_data(
        cls,
        teams,
        teamdict,
        players,
        player_id_to_team_dict,
        periods,
        player_dict,
        anon_players,
        ball_id,
        referee_dict,
        frame,
    ):
        frame_period = frame["period"]

        frame_id = frame["frame"]
        frame_time = cls._timestamp_from_timestring(frame["time"])

        ball_coordinates = None
        players_data = {}

        # ball_carrier = frame["possession"].get("trackable_object")
        ball_owning_team = frame["possession"].get("group")

        if ball_owning_team == "home team":
            ball_owning_team = teams[0]
        elif ball_owning_team == "away team":
            ball_owning_team = teams[1]
        else:
            ball_owning_team = None

        for frame_record in frame["data"]:
            # containing x, y, trackable_object, track_id, group_name
            x = frame_record.get("x")
            y = frame_record.get("y")

            trackable_object = frame_record.get("trackable_object", None)

            track_id = frame_record.get("track_id", None)
            group_name = frame_record.get("group_name", None)

            if trackable_object == ball_id:
                group_name = "ball"
                z = frame_record.get("z")
                if z is not None:
                    z = float(z)
                ball_coordinates = Point3D(x=float(x), y=float(y), z=z)
                continue

            elif trackable_object in referee_dict.keys():
                group_name = "referee"
                continue  # Skip Referee Coords

            if group_name is None:
                group_name = teamdict.get(
                    player_id_to_team_dict.get(trackable_object))

                if group_name == "home_team":
                    player = players["HOME"][trackable_object]
                elif group_name == "away_team":
                    player = players["AWAY"][trackable_object]

            if trackable_object is None:
                player_id = str(track_id)
                if group_name == "home team":
                    if f"anon_{player_id}" not in anon_players["HOME"].keys():
                        player = cls.__create_anon_player(teams, frame_record)
                        anon_players["HOME"][f"anon_home_{player_id}"] = player
                    else:
                        player = anon_players["HOME"][f"anon_home_{player_id}"]

                elif group_name == "away team":
                    if f"anon_{player_id}" not in anon_players["AWAY"].keys():
                        player = cls.__create_anon_player(teams, frame_record)
                        anon_players["AWAY"][f"anon_away_{player_id}"] = player
                    else:
                        player = anon_players["AWAY"][f"anon_away_{player_id}"]

            players_data[player] = PlayerData(coordinates=Point(x, y))

        return Frame(
            frame_id=frame_id,
            timestamp=frame_time,
            ball_coordinates=ball_coordinates,
            players_data=players_data,
            period=periods[frame_period],
            ball_state=None,
            ball_owning_team=ball_owning_team,
            other_data={},
        )
Ejemplo n.º 16
0
    def _frame_from_line(cls, teams, period, line, frame_rate):
        line = str(line)
        frame_id, players, ball = line.strip().split(":")[:3]

        players_coordinates = {}

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

            if team_id == 1:
                team = teams[0]
            elif team_id == 0:
                team = teams[1]
            else:
                raise Exception(f"Unknown team {team_id}")

            player = team.get_player_by_jersey_number(jersey_no)

            if not player:
                player = Player(
                    player_id=f"{team.ground}_{jersey_no}",
                    team=team,
                    jersey_no=int(jersey_no),
                )
                team.players.append(player)

            players_coordinates[player] = 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 = teams[0]
        elif ball_owning_team == "A":
            ball_owning_team = teams[1]
        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_coordinates=Point(float(ball_x), float(ball_y)),
            ball_state=ball_state,
            ball_owning_team=ball_owning_team,
            players_coordinates=players_coordinates,
            period=period,
        )