The unravelsports package aims to aid researchers, analysts and enthusiasts by providing intermediary steps in the complex process of turning raw sports data into meaningful information and actionable insights.
Feature to allow users to decide node and edge features
Feature to export settings and graph configurations to a JSON to ensure reproducability
Summary of Changes
Dynamic selection of node features
The goal of this enhancement is to provide users with the flexibility to configure which features should be included in the nodes of theGraphConverter
Originally, theGraphConverter’s node features were static and pre-defined like this:
ball_node_features = [
normalize_coords(ball.x1, pitch_dimensions.x_dim.max), #normalize x coordinate
normalize_coords(ball.y1, pitch_dimensions.y_dim.max), #normalize y coordinate
.
.
.
]
player_node_features = [
(
0.0
if np.isnan(p.x1)
else normalize_coords(p.x1, pitch_dimensions.x_dim.max) #normalize x coordinate
),
(
0.0
if np.isnan(p.x1)
else normalize_coords(p.y1, pitch_dimensions.y_dim.max) #normalize y coordinate
),
.
.
.
]
With this update, users can dynamically select features when instantiating theGraphConverter(). In the future, we also would like to implement aadd_my_custom_feature()functionality
converter = GraphConverter()
.node_features
.add_x(normed=True) #normalize x coordinate
.add_y(normed=True) #normalize y coordinate
.add_my_custom_feature()
To facilitate this functionality, we introduced aNodeFeatureSetclass. This class enables users to dynamically add node features to the feature set and customize how it is calculated. The feature set is then populated with a feature function which includes the name, the function and the parameters required in the function. The code is present inunravel/utils/features/node_feature_set.py
The function defined above in theNodeFeatureSetallows the user to add the x-coordinate of the ball and player to node features. Ifnormed=True, it normalized the x-coordinate. This dynamic configuration allows users to define the specific functions employed to calculate node features at the time of instantiating the GraphConverter. Similarly all the node feature calculations were captured using:
Function name | Function logic
-- | --
add_x | if normed, stores normalize_coords()function (from utils.py) and passes x and max_x
Else, stores a lambda identity function lambda x: x to relay x |
add_y | Similar to add_x with y and max_y
add_velocity | Using unit_vector(), it calculates the velocity in x and y directions. If both the directions are included, it calculates the angle of velocity which can be normalized using normalize_angles()
add_speed | If normed, stores normalize_speed() function and passes speed and max_speed, else stores the identity function
add_goal_distance | .
add_goal_angle | .
add_ball_distance | .
add_ball_angle | .
add_team | .
add_potential_reciever | .
Export settings feature
Introduced a functionexport_settings()inGraphConverterclass which stores the version of unravel, node and edge features used along with graph settings into a json filesettings.jsonin the root
def export_settings(self) -> None:
file_path = 'settings.json'
data = {
"__version__": "0.1.2",
"node_features": [func_name for func_name,_,_ in self.node_features.get_features()],
"edge_features": [func_name for func_name,_,_ in self.edge_features.get_features()],
"graph_settings": self.settings.to_dict()
}
with open(file_path, 'w') as json_file:
json.dump(data, json_file, indent=4)
return
Also created a functionto_dict()ingraph_settings.pyto serialize the object into a JSON subscriptable format. The following is a sample JSON file that was exported:
I conducted a sanity check by utilizing the dynamic feature selection introduced in the recent update to reproduce the output of the previous static configuration.
Stored the variableXthat is returned fromnode_featuresfrom the original and updated version into a txt file and ran a script to verify if the text files are identical.
Stored the variableethat is returned fromedge_featuresfrom the original and updated versions and the script verifies that they are identical.
This means that this update has ensured correctness of output
Overview
The following changes have been made:
Summary of Changes
Dynamic selection of node features
The goal of this enhancement is to provide users with the flexibility to configure which features should be included in the nodes of the
GraphConverter
Originally, the
GraphConverter
’s node features were static and pre-defined like this:With this update, users can dynamically select features when instantiating the
GraphConverter()
. In the future, we also would like to implement aadd_my_custom_feature()
functionalityTo facilitate this functionality, we introduced a
NodeFeatureSet
class. This class enables users to dynamically add node features to the feature set and customize how it is calculated. The feature set is then populated with a feature function which includes the name, the function and the parameters required in the function. The code is present inunravel/utils/features/node_feature_set.py
The function defined above in the
Function name | Function logic -- | -- add_x | if normed, stores normalize_coords()function (from utils.py) and passes x and max_x Else, stores a lambda identity function lambda x: x to relay x | add_y | Similar to add_x with y and max_y add_velocity | Using unit_vector(), it calculates the velocity in x and y directions. If both the directions are included, it calculates the angle of velocity which can be normalized using normalize_angles() add_speed | If normed, stores normalize_speed() function and passes speed and max_speed, else stores the identity function add_goal_distance | . add_goal_angle | . add_ball_distance | . add_ball_angle | . add_team | . add_potential_reciever | .NodeFeatureSet
allows the user to add the x-coordinate of the ball and player to node features. Ifnormed=True
, it normalized the x-coordinate. This dynamic configuration allows users to define the specific functions employed to calculate node features at the time of instantiating theGraphConverter
. Similarly all the node feature calculations were captured using:Export settings feature
Introduced a function
export_settings()
inGraphConverter
class which stores the version of unravel, node and edge features used along with graph settings into a json filesettings.json
in the rootAlso created a function
to_dict()
ingraph_settings.py
to serialize the object into a JSON subscriptable format. The following is a sample JSON file that was exported:Verifying correctness
I conducted a sanity check by utilizing the dynamic feature selection introduced in the recent update to reproduce the output of the previous static configuration.
X
that is returned fromnode_features
from the original and updated version into a txt file and ran a script to verify if the text files are identical.e
that is returned fromedge_features
from the original and updated versions and the script verifies that they are identical.This means that this update has ensured correctness of output