Accessing Sport-Specific Events & IMA Event Data

How to access sport-specific events & IMA event data.

Table of Contents


Introduction

IMA stands for inertial movement analysis and refers to a set of metrics describing “micro movements” made by athletes. For more information, see the following link. This class of data also houses sport-specific events, such as rugby scrums, goalkeeping dives, and baseball throws to name a few.

Validate User Credentials

If enabled on your account, you can also generate an API token string in OpenField Cloud. If you would like this feature enabled on your OpenField account, please speak with your Catapult Sports Customer Success Representative.

For this example, we will extract all Rugby Union events from a game in our Men’s Rugby Union demo account. First we have to get the token corresponding to this account.

All data presented along with account credentials have been anonymized, removing and changing identifiable characteristics that can be traced back to an account, team, or athlete. Typical token strings created in OpenField Cloud will be much longer.


# first, load a few packages
library(catapultR)
library(tidyverse)
library(lubridate)

token <- ofCloudCreateToken(sToken = "8SyAJZonGYUH5adDgINl1re7WkOPXhB0EtbVzcMp",  sRegion = "America")

Getting Athletes and Activities

Now, we can see which athletes and activities are associated with this account. Typically, you will want to identify specific athletes or activities for which you want more information. Once you know when these Activities occurred and the Device IDs that you’re interested in, you can access IMA Event data, Generation 2 Effort data, 10 Hz Sensor Data, or even 100 Hz high frequency data if the necessary modules are enabled on the account.

In order to maintain anonymity, no identifiable data will be shared for the following examples.

Athletes:


athletes <- ofCloudGetAthletes(token)
# glimpse(athletes)
glimpse(athletes)

Rows: 280
Columns: 29
$ id                         <fct> 7pkjvzc2-pf7x-si7l-jldg-axb2lf7vw~
$ first_name                 <chr> "Annnees", "Brian", "Anthony", "B~
$ last_name                  <chr> "Engelhart", "Simion", "Weiss", "~
$ jersey                     <chr> "123", "DM5", "JC", "EO1", "WS5",~
$ nickname                   <chr> "", "", "Mailman", "Sleepy", "", ~
$ height                     <dbl> 178.002063161, 182.702953896, 181~
$ weight                     <dbl> 64.5848746855, 66.0066343451, 74.~
$ date_of_birth              <dbl> 769560828, 785147237, 802150884, ~
$ velocity_max               <dbl> 10.00, 10.00, 9.00, 9.50, 8.20, 8~
$ acceleration_max           <int> 0, 0, 0, 0, 0, 0, 0, 10, 10, 0, 1~
$ heart_rate_max             <int> 0, 0, 200, 196, 199, 0, 200, 193,~
$ player_load_max            <int> 0, 0, 500, 0, 0, 0, 0, 10, 10, 50~
$ image                      <chr> "", "", "", "", "", "", "", "6695~
$ icon                       <chr> "circle", "circle", "circle", "tr~
$ stroke_colour              <chr> "#030303", "#030303", "#030303", ~
$ fill_colour                <chr> "#ff0000", "#ff0000", "#ff0000", ~
$ trail_colour_start         <chr> "", "", "", "", "", "", "", "#000~
$ trail_colour_end           <chr> "", "", "", "", "", "", "", "#000~
$ is_synced                  <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ~
$ is_deleted                 <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ~
$ created_at                 <chr> "2015-06-22 10:04:02", "2015-07-0~
$ modified_at                <chr> "2015-07-31 08:38:44", "2016-09-1~
$ tag_list                   <list> [], [], [], [], [], [], [], [], ~
$ tags                       <list> [], [], [], [], [], [], [], [], ~
$ current_team_id            <chr> "9xvyke5n-hgrc-r7v6-8dtj-31bhkszm~
$ max_player_load_per_minute <int> 12, 12, 15, 15, 15, 12, 12, 15, 1~
$ position                   <chr> "SH", "S", "C", "FB", "S", "FL", ~
$ position_id                <chr> "b93eae54-7071-11e4-afbc-0afe0c90~
$ position_name              <chr> "Scrum-Half", "Second Row", "Cent~


Activities:


# Get data for each activity (Demo Account) ----------------------------------------------
to <- as.integer(as.POSIXct(as.Date("2020-02-02")))
from <- as.integer(as.POSIXct(as.Date("2019-10-02"))) # 20 weeks
activities <- ofCloudGetActivities(token, from = from, to = to)
glimpse(activities)
nrow(activities)

Rows: 180
Columns: 19
$ id             <chr> "pkjv7c2u-pf7x-si7l-jldg-axb2lf7vw9c8", "pdvz~
$ name           <chr> "Rehab", "Training", "Training", "Rehab", "Ma~
$ start_time     <dbl> 1584697281, 1584611296, 1584522199, 158447928~
$ end_time       <dbl> 1584699565, 1584612900, 1584524248, 158448302~
$ modified_at    <chr> "2020-01-31 17:15:48", "2020-01-31 17:15:48",~
$ game_id        <chr> "pkjv7c2u-pf7x-si7l-jldg-axb2lf7vw9c8", "pdvz~
$ owner_id       <chr> "efcb4474-22a6-41fc-95ce-8389d6e8fd36", "efcb~
$ owner          <df[,10]> <data.frame[23 x 10]>
$ periods        <list> [<data.frame[1 x 4]>], [<data.frame[1 x 4~
$ tags           <list> <"Friday", "Compressed", "GPS", "Compressed"~
$ tag_list       <list> [<data.frame[4 x 5]>], [<data.frame[2 x 5]>]~
$ athlete_count  <int> 1, 1, 1, 1, 1, 1, 27, 1, 2, 2, 7, 34, 1, 2, ~
$ period_count   <int> 1, 1, 1, 1, 1, 1, 46, 1, 2, 1, 6, 7, 1, 1, 1,~
$ venue_name     <chr> "Training Pitch 2", "Training Pitch 3", "Trai~
$ venue_width    <int> 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 7~
$ venue_length   <int> 105, 105, 105, 105, 105, 105, 105, 105, 105, ~
$ venue_rotation <int> 169, 169, 169, 169, 169, 169, 169, 169, 169, ~
$ venue_lat      <dbl> 71.7755572, 71.7755572, 71.7755572, 71.775557~
$ venue_lng      <dbl> -19.3345743, -19.3345743, -19.3345743, -19.33~

[1] 180

The column names for the activities dataframe are printed above. We can see that each row contains information for a single activity. Between October 2, 2019 and February 2, 2020, there were 180 activities associated with the account.


We can use the activities data frame above to identify an activity or period from which we would like to extract Events. We also need the athlete_id for each athlete, and the corresponding name of each athlete will also be helpful. For this example, I will just select a random activity. To get the athlete_ids and athlete_names for this activity, we can use the function ofCloudGetAthleteDevices().

Get Device Info for the Activity


# We want athlete name, athlete_id, and device_id
# we can match the name using the device id from the info returned by ofCloudGetAthleteDevices()
device_info <- ofCloudGetAthleteDevicesInActivity(
  token, 
  activity_id = activities$id[27])

glimpse(device_info)

Rows: 32
Columns: 12
$ device_id          <int> 3904, 1083, 8903, 8558, 7337, 9171, 6702,~
$ athlete_id         <chr> "dnc3ystx-mvfe-d2ey-cx14-25i14qtmaglo", "~
$ athlete_name       <chr> "Dao Ibarra", "Dillon Lovato", "Cindy Kea~
$ athlete_first_name <chr> "Dao", "Dillon", "Cindy", "Joshua", "Ange~
$ athlete_last_name  <chr> "Ibarra", "Lovato", "Keasling", "Tree", "~
$ mapping_start_time <dbl> 1581406289, 1581406180, 1578641056, 15829~
$ mapping_end_time   <dbl> 1583481593, 1641898572, 1583416017, 15832~
$ is_current_mapping <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,~
$ jersey             <chr> "CH5", "AC8", "KP2", "DT2", "SM4", "TL3",~
$ team_id            <chr> "iuctbanw-twg7-rqwc-ijzc-icbfwuv5z89p", "~
$ team_name          <chr> "Ravenclaw", "Ravenclaw", "Ravenclaw", "R~
$ player_id          <chr> "", "", "", "", "", "", "", "", "", "", "~

The column names for device_info have been printed above. The device_id column can be used to join athlete names to the event data.

Accessing Events

For a list of IMA event types, use the function ima_events(). While all event types are listed, your account will not be able to access event types for other sports. If you feel that your account does not have the correct sport specific modules to access the correct events, please contact your account manager.

Get the Events for a Single Athlete.

Now that we have the device information (device_id, athlete_id, athlete_name, etc.), we can go ahead and get the events. The code below will get the events for the first athlete. The function ofCloudGetActivityEvents() returns a list of dataframes, one for each event type.


# get ima acceleration, jump, and impact events
events <- ofCloudGetActivityEvents(token, 
                         athlete_id = device_info$athlete_id[10], 
                         activity_id = activities$id[27], 
                         events = c("rugby_union_scrum", 
                                    "rugby_union_contact_involvement", 
                                    "rugby_union_kick")) 
# specify event types from ima_events()

names(events)

[1] "rugby_union_contact_involvement"
[2] "rugby_union_scrum"              

Scrums:


rmarkdown::paged_table(events[["rugby_union_scrum"]])

Contact Involvements:


rmarkdown::paged_table(events[["rugby_union_contact_involvement"]])

Kicks:


events[["rugby_union_kick"]]

NULL

The athlete in the example above did not have any kicks. This is not concerning as most positions on a rugby team do not kick.

Conclusion

You have now accessed some IMA event data for a single athlete. You can extend the logic for multiple athletes and multiple activities if you wish. For other types of data requests, proceed to another section of the Quick Start Tutorial.

Contact: (email) | #ask_catapultR (Slack)