Skip to content
Prev Previous commit
Next Next commit
Add all player and ball features
  • Loading branch information
Mihir Thalanki authored and Mihir Thalanki committed Sep 3, 2024
commit e182fee23dc4ba3b2477a2d93dc648477905ac9b
44 changes: 39 additions & 5 deletions unravel/utils/features/node_feature_set.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def add_x(self, normed: bool = False):
if normed:
self.node_feature_functions.append(('normalize_x', normalize_coords, ['x', 'max_x']))
else:
self.node_feature_functions.append(('coord_x', coord, ['x']))
self.node_feature_functions.append(('coord_x', lambda x: x, ['x']))

return self

Expand All @@ -38,7 +38,7 @@ def add_y(self, normed: bool = False):
if normed:
self.node_feature_functions.append(('normalize_y', normalize_coords, ['y', 'max_y']))
else:
self.node_feature_functions.append(('coord_y', coord, ['y']))
self.node_feature_functions.append(('coord_y', lambda y: y, ['y']))

return self

Expand All @@ -65,10 +65,10 @@ def add_speed(self, normed: bool = True):
if normed:
self.node_feature_functions.append(('normalized_speed', normalize_speed, ['speed', 'max_speed'])) #Have to round this
else:
self.node_feature_functions.append(('speed', coord, ['speed']))
self.node_feature_functions.append(('speed', lambda s: s, ['speed']))
return self

def add_goal_metric(self, normed: bool = True):
def add_goal_distance(self, normed: bool = True):
if normed:
self.node_feature_functions.append(('normalized_goal_distance',
lambda position, goal_mouth_position, max_dist_to_goal: normalize_distance(
Expand All @@ -77,9 +77,43 @@ def add_goal_metric(self, normed: bool = True):
, ['position', 'goal_mouth_position', 'max_dist_to_goal']))
else:
self.node_feature_functions.append(('goal_distance', lambda position, goal_mouth_position: np.linalg.norm(position - goal_mouth_position), ['position', 'goal_mouth_position']))
return self

def add_goal_angle(self, normed: bool = True):
if normed:
self.node_feature_functions.append(('normed_goal_angle', normalize_angles, ['goal_angle']))
else:
self.node_feature_functions.append(('goal_angle', lambda a: a, ['goal_angle']))


return self

def add_ball_distance(self, normed: bool = True):
if normed:
self.node_feature_functions.append(('normalized_ball_distance',
lambda position, ball_position, max_dist_to_player: normalize_distance(
np.linalg.norm(position - ball_position),
max_dist_to_player)
, ['position', 'ball_position', 'max_dist_to_player']))
else:
self.node_feature_functions.append(('ball_distance', lambda position, ball_position: np.linalg.norm(position - ball_position), ['position', 'ball_position']))
return self

def add_ball_angle(self, normed: bool = True):
if normed:
self.node_feature_functions.append(('normed_ball_angle', normalize_angles, ['ball_angle']))
else:
self.node_feature_functions.append(('ball_angle', lambda a: a, ['ball_angle']))

return self

def add_team(self):
self.node_feature_functions.append(('team', lambda t: t, ['team']))
return self

def add_potential_reciever(self):
self.node_feature_functions.append(('potential_reciever', lambda potential_receiver, non_potential_receiver_node_value : 1.0 if potential_receiver else non_potential_receiver_node_value, ['potential_receiver', 'non_potential_receiver_node_value']))
return self

def get_features(self):
return self.node_feature_functions

31 changes: 20 additions & 11 deletions unravel/utils/features/node_features.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ def player_features(p, team, potential_receiver=None):
goal_angle = math.atan2(
p.y1 - goal_mouth_position[0], p.x1 - goal_mouth_position[1]
)
#print(p)
player_node_features = []
all_params = {'x': p.x1,
'max_x': pitch_dimensions.x_dim.max,
Expand All @@ -58,7 +57,14 @@ def player_features(p, team, potential_receiver=None):
'max_speed': max_player_speed,
'position': p.position,
'goal_mouth_position': goal_mouth_position,
'max_dist_to_goal': max_dist_to_goal
'max_dist_to_goal': max_dist_to_goal,
'goal_angle': goal_angle,
'ball_position': ball.position,
'max_dist_to_player': max_dist_to_player,
'ball_angle': ball_angle,
'team': team,
'potential_receiver': potential_receiver,
'non_potential_receiver_node_value': non_potential_receiver_node_value
}
computed_values = {}
for func_name, func, reqd_params in function_list:
Expand All @@ -70,15 +76,14 @@ def player_features(p, team, potential_receiver=None):
player_node_features.append(value)
else: #else, print out the missing parameters. Maybe you should check if there is a default value. Then it is okay if the parameter is not present
missing_params = [param for param in reqd_params if param not in all_params]
print(f"Warning: Missing parameters {missing_params} for function '{func_name}'")
computed_values[func_name] = None
player_node_features.append(None)
#print(f"Warning: Missing parameters {missing_params} for function '{func_name}'")
computed_values[func_name] = 0
player_node_features.append(0)
except Exception as e:
print(f"Error while executing function '{func_name}': {e}")
computed_values[func_name] = None
player_node_features.append(None)

print(computed_values)
return player_node_features

def ball_features(ball):
Expand All @@ -88,11 +93,15 @@ def ball_features(ball):
ball_node_features = []
all_params = {'x': ball.x1,
'max_x': pitch_dimensions.x_dim.max,
'y': ball.x2,
'y': ball.y1,
'max_y': pitch_dimensions.y_dim.max,
'velocity': ball.velocity,
'speed': ball.speed,
'max_speed': max_ball_speed,
'position': ball.position,
'goal_mouth_position': goal_mouth_position,
'max_dist_to_goal': max_dist_to_goal,
'goal_angle': goal_angle,
}
computed_values = {}
for func_name, func, reqd_params in function_list:
Expand All @@ -104,14 +113,14 @@ def ball_features(ball):
ball_node_features.append(value)
else: #else, print out the missing parameters. Maybe you should check if there is a default value. Then it is okay if the parameter is not present
missing_params = [param for param in reqd_params if param not in all_params]
print(f"Warning: Missing parameters {missing_params} for function '{func_name}'")
computed_values[func_name] = None
ball_node_features.append(None)
#print(f"Warning: Missing parameters {missing_params} for function '{func_name}'")
computed_values[func_name] = 0
ball_node_features.append(0)
except Exception as e:
print(f"Error while executing function '{func_name}': {e}")
computed_values[func_name] = None
ball_node_features.append(None)

#print(computed_values)
return np.asarray([ball_node_features])

# loop over attacking players, grab ball_carrier, potential receiver and intended receiver
Expand Down