{"cells":[{"metadata":{"_uuid":"dfbce5c91045f19281e03318493edf43fa421a20"},"cell_type":"markdown","source":"# Visualizing all 37 Concussion Plays - Video Links + Velocity Data\n[My final report can be found in this kernel. If you haven't please read it first](https://www.kaggle.com/robikscube/evolving-the-punt-play-nfl-data-formal-report)  \n\nIn this notebook I provide some of the code I used to conduct my analysis of the 37 NFL punt plays that resulted in concussions. These functions can also be used for plotting other plays. I'm using data provided by the NFL and Next Gen Stats - which include each players position on the field during the plays. Hopefully you find them helpful.\n\nSome things to note:\n- I lower all the columns names of the dataframes- this may cause functions to not work unless you do the same.\n- The hash marks on an NFL field are closer together than college football field. If you are using these functions to plot college football data you will have to modify.\n- I do a good bit of preprocessing to merge data.\n- I'm using an external data source for the injury plays just so I have all the NGS data in one place. However you should be albe to load other NGS datasets and this code should work on other plays just the same.\n- I wasn't entirely happy with my color selection for the plots, if you have better suggestions please let me know in the comments!"},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport matplotlib.pylab as plt\nfrom scipy import stats\nimport datetime as dt\nfrom IPython.core.display import display, HTML\n\nimport matplotlib.pyplot as plt\nimport matplotlib.patches as patches\nimport numpy as np\nimport cmath\n\nplt.style.use('ggplot')\npd.set_option('display.max_columns', 50)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"dadcc887a96cdc38ddf109e13131711af6ddee55"},"cell_type":"markdown","source":"## Read in the data"},{"metadata":{"trusted":true,"_uuid":"61def699a1b051bdaf71172e19abc56a45b5cd25"},"cell_type":"code","source":"# Read in non-NGS data sources\nppd = pd.read_csv('../input/NFL-Punt-Analytics-Competition/player_punt_data.csv')\ngd = pd.read_csv('../input/NFL-Punt-Analytics-Competition/game_data.csv')\npprd = pd.read_csv('../input/NFL-Punt-Analytics-Competition/play_player_role_data.csv')\nvr = pd.read_csv('../input/NFL-Punt-Analytics-Competition/video_review.csv')\nvfi = pd.read_csv('../input/NFL-Punt-Analytics-Competition/video_footage-injury.csv')\npi = pd.read_csv('../input/NFL-Punt-Analytics-Competition/play_information.csv')\nvfi = vfi.rename(columns={'season' : 'season_year'})\n\ngsisid_numbers = ppd.groupby('GSISID')['Number'].apply(lambda x: \"%s\" % ', '.join(x))\ngsisid_numbers = pd.DataFrame(gsisid_numbers).reset_index()\nvr_with_number = pd.merge(vr, gsisid_numbers, how='left', on='GSISID', suffixes=('','_injured'))\nvr_with_number['Primary_Partner_GSISID'] = vr_with_number['Primary_Partner_GSISID'].fillna(0).replace('Unclear',0).astype('int64')\nvr_with_number = pd.merge(vr_with_number,\n                          gsisid_numbers,\n                          how='left',\n                          left_on='Primary_Partner_GSISID',\n                          right_on='GSISID',\n                          suffixes=('','_primary_partner'))\nvr = vr_with_number\nall_dfs = [ppd, gd, pprd, vr, vfi, pi]\n# Change column names so they are all lowercase \n# never have to guess about which letters are uppercase\nfor mydf in all_dfs:\n    mydf.columns = [col.lower() for col in mydf.columns]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"c9c8582910c361bfe03033d21789df1e6cfc78b5"},"cell_type":"code","source":"\"\"\"\nCreate Dataframe with Generalized Punting Roles\ninclude which team they are on (punting/returning)\n\"\"\"\nrole_info_dict = {'GL': ['Gunner', 'Punting_Team'],\n                  'GLi': ['Gunner', 'Punting_Team'],\n                  'GLo': ['Gunner', 'Punting_Team'],\n                  'GR': ['Gunner', 'Punting_Team'],\n                  'GRi': ['Gunner', 'Punting_Team'],\n                  'GRo': ['Gunner', 'Punting_Team'],\n                  'P': ['Punter', 'Punting_Team'],\n                  'PC': ['Punter_Protector', 'Punting_Team'],\n                  'PPR': ['Punter_Protector', 'Punting_Team'],\n                  'PPRi': ['Punter_Protector', 'Punting_Team'],\n                  'PPRo': ['Punter_Protector', 'Punting_Team'],\n                  'PDL1': ['Defensive_Lineman', 'Returning_Team'],\n                  'PDL2': ['Defensive_Lineman', 'Returning_Team'],\n                  'PDL3': ['Defensive_Lineman', 'Returning_Team'],\n                  'PDR1': ['Defensive_Lineman', 'Returning_Team'],\n                  'PDR2': ['Defensive_Lineman', 'Returning_Team'],\n                  'PDR3': ['Defensive_Lineman', 'Returning_Team'],\n                  'PDL5': ['Defensive_Lineman', 'Returning_Team'],\n                  'PDL6': ['Defensive_Lineman', 'Returning_Team'],\n                  'PFB': ['PuntFullBack', 'Returning_Team'],\n                  'PLG': ['Punting_Lineman', 'Punting_Team'],\n                  'PLL': ['Defensive_Backer', 'Returning_Team'],\n                  'PLL1': ['Defensive_Backer', 'Returning_Team'],\n                  'PLL3': ['Defensive_Backer', 'Returning_Team'],\n                  'PLS': ['Punting_Longsnapper', 'Punting_Team'],\n                  'PLT': ['Punting_Lineman', 'Punting_Team'],\n                  'PLW': ['Punting_Wing', 'Punting_Team'],\n                  'PRW': ['Punting_Wing', 'Punting_Team'],\n                  'PR': ['Punt_Returner', 'Returning_Team'],\n                  'PRG': ['Punting_Lineman', 'Punting_Team'],\n                  'PRT': ['Punting_Lineman', 'Punting_Team'],\n                  'VLo': ['Jammer', 'Returning_Team'],\n                  'VR': ['Jammer', 'Returning_Team'],\n                  'VL': ['Jammer', 'Returning_Team'],\n                  'VRo': ['Jammer', 'Returning_Team'],\n                  'VRi': ['Jammer', 'Returning_Team'],\n                  'VLi': ['Jammer', 'Returning_Team'],\n                  'PPL': ['Punter_Protector', 'Punting_Team'],\n                  'PPLo': ['Punter_Protector', 'Punting_Team'],\n                  'PPLi': ['Punter_Protector', 'Punting_Team'],\n                  'PLR': ['Defensive_Backer', 'Returning_Team'],\n                  'PRRo': ['Defensive_Backer', 'Returning_Team'],\n                  'PDL4': ['Defensive_Lineman', 'Returning_Team'],\n                  'PDR4': ['Defensive_Lineman', 'Returning_Team'],\n                  'PLM': ['Defensive_Backer', 'Returning_Team'],\n                  'PLM1': ['Defensive_Backer', 'Returning_Team'],\n                  'PLR1': ['Defensive_Backer', 'Returning_Team'],\n                  'PLR2': ['Defensive_Backer', 'Returning_Team'],\n                  'PLR3': ['Defensive_Backer', 'Returning_Team'],\n                  'PLL2': ['Defensive_Backer', 'Returning_Team'],\n                  'PDM': ['Defensive_Lineman', 'Returning_Team'],\n                  'PDR5': ['Defensive_Lineman', 'Returning_Team'],\n                  'PDR6': ['Defensive_Lineman', 'Returning_Team'],\n                  }\nrole_info = pd.DataFrame.from_dict(role_info_dict, orient='index',\n                                   columns=['generalized_role', 'punting_returning_team']) \\\n    .reset_index() \\\n    .rename(columns={'index': 'role'})","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"8b63ff05942a9a36ce9d4bf0d39266ef8e999a61"},"cell_type":"code","source":"# More Data Prep\ninjury_play_ngs = pd.read_parquet(\n    '../input/nfl-punt-data-preprocessing-ngs-injury-plays/NGS-injury-plays.parquet')\ngsisid_numbers = ppd.groupby('gsisid')['number'].apply(\n    lambda x: \"%s\" % ', '.join(x))\ngsisid_numbers = pd.DataFrame(gsisid_numbers).reset_index()\n# Add Player Number and Direction\nvr_with_number = pd.merge(\n    vr, gsisid_numbers, how='left', suffixes=('', '_injured'))\nvr_with_number['primary_partner_gsisid'] = vr_with_number['primary_partner_gsisid'].replace(\n    'Unclear', np.nan).fillna(0).astype('int')\nvr_with_number = pd.merge(vr_with_number, gsisid_numbers, how='left',\n                          left_on='primary_partner_gsisid', right_on='gsisid', suffixes=('', '_primary_partner'))\nvr = vr_with_number\n\nvr_merged = pd.merge(vr, pprd)\nvr_merged = pd.merge(vr_merged, role_info)\n\n\nvr_merged = pd.merge(vr_merged, pprd, left_on=['season_year', 'gamekey', 'playid', 'primary_partner_gsisid'],\n                     right_on=['season_year', 'gamekey', 'playid', 'gsisid'], how='left',\n                     suffixes=('', '_primary_partner'))\nvr_merged = pd.merge(vr_merged, role_info, left_on='role_primary_partner',\n                     right_on='role', how='left', suffixes=('', '_primary_partner'))\n\nvr_merged = vr_merged.fillna('None')\nvr_merged['count'] = 1\n\nvr_merged['generalized_role'] = vr_merged['generalized_role'].str.replace(\n    '_', ' ')\nvr_merged['generalized_role_primary_partner'] = vr_merged['generalized_role_primary_partner'].str.replace(\n    '_', ' ')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"2006fff42dd9bbc32f639a96bc54e99e745a86df"},"cell_type":"markdown","source":"## Function for creating football field in matplotlib"},{"metadata":{"trusted":true,"_uuid":"ae1c47d7af6317379d9ba38eadee97ed24d4ed4c"},"cell_type":"code","source":"def create_football_field(linenumbers=True,\n                          endzones=True,\n                          highlight_line=False,\n                          highlight_line_number=50,\n                          highlighted_name='Line of Scrimmage',\n                          fifty_is_los=False,\n                          figsize=(12, 6.33)):\n    \"\"\"\n    Function that plots the football field for viewing plays.\n    Allows for showing or hiding endzones.\n    \"\"\"\n    rect = patches.Rectangle((0, 0), 120, 53.3, linewidth=0.1,\n                             edgecolor='r', facecolor='darkgreen', zorder=0)\n\n    fig, ax = plt.subplots(1, figsize=figsize)\n    ax.add_patch(rect)\n\n    plt.plot([10, 10, 10, 20, 20, 30, 30, 40, 40, 50, 50, 60, 60, 70, 70, 80,\n              80, 90, 90, 100, 100, 110, 110, 120, 0, 0, 120, 120],\n             [0, 0, 53.3, 53.3, 0, 0, 53.3, 53.3, 0, 0, 53.3, 53.3, 0, 0, 53.3,\n              53.3, 0, 0, 53.3, 53.3, 0, 0, 53.3, 53.3, 53.3, 0, 0, 53.3],\n             color='white')\n    if fifty_is_los:\n        plt.plot([60, 60], [0, 53.3], color='gold')\n        plt.text(62, 50, '<- Player Yardline at Snap', color='gold')\n    # Endzones\n    if endzones:\n        ez1 = patches.Rectangle((0, 0), 10, 53.3,\n                                linewidth=0.1,\n                                edgecolor='r',\n                                facecolor='blue',\n                                alpha=0.2,\n                                zorder=0)\n        ez2 = patches.Rectangle((110, 0), 120, 53.3,\n                                linewidth=0.1,\n                                edgecolor='r',\n                                facecolor='blue',\n                                alpha=0.2,\n                                zorder=0)\n        ax.add_patch(ez1)\n        ax.add_patch(ez2)\n    plt.xlim(0, 120)\n    plt.ylim(-5, 58.3)\n    plt.axis('off')\n    if linenumbers:\n        for x in range(20, 110, 10):\n            numb = x\n            if x > 50:\n                numb = 120 - x\n            plt.text(x, 5, str(numb - 10),\n                     horizontalalignment='center',\n                     fontsize=20,  # fontname='Arial',\n                     color='white')\n            plt.text(x - 0.95, 53.3 - 5, str(numb - 10),\n                     horizontalalignment='center',\n                     fontsize=20,  # fontname='Arial',\n                     color='white', rotation=180)\n    if endzones:\n        hash_range = range(11, 110)\n    else:\n        hash_range = range(1, 120)\n\n    for x in hash_range:\n        ax.plot([x, x], [0.4, 0.7], color='white')\n        ax.plot([x, x], [53.0, 52.5], color='white')\n        ax.plot([x, x], [22.91, 23.57], color='white')\n        ax.plot([x, x], [29.73, 30.39], color='white')\n\n    if highlight_line:\n        hl = highlight_line_number + 10\n        plt.plot([hl, hl], [0, 53.3], color='yellow')\n        plt.text(hl + 2, 50, '<- {}'.format(highlighted_name),\n                 color='yellow')\n\n    return fig, ax","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"61910d8ab27015878fc3ba5566bc1e5b15b242c7"},"cell_type":"markdown","source":"## Function for creating compass and trimming play to just action moments"},{"metadata":{"trusted":true,"_uuid":"05f0b911c171f5870c8640f77c507cdc20ae2478"},"cell_type":"code","source":"\"\"\"\nThis cell block contains functions for interacting with the NGS data.\nPlotting compass of player angle and velocity along with the playing field\n\"\"\"\n\n\ndef compass(angles, radii, arrowprops=None, ax=None):\n    \"\"\"\n    Compass draws a graph that displays the vectors with\n    components `u` and `v` as arrows from the origin.\n\n    Examples\n    --------\n    >>> import numpy as np\n    >>> u = [+0, +0.5, -0.50, -0.90]\n    >>> v = [+1, +0.5, -0.45, +0.85]\n    >>> compass(u, v)\n    \"\"\"\n\n    #angles, radii = cart2pol(u, v)\n    if ax is None:\n        fig, ax = plt.subplots(subplot_kw=dict(polar=True))\n\n    kw = dict(arrowstyle=\"->\", color='k')\n    if arrowprops:\n        kw.update(arrowprops)\n    [ax.annotate(\"\", xy=(angle, radius), xytext=(0, 0),\n                 arrowprops=kw) for\n     angle, radius in zip(angles, radii)]\n\n    ax.set_ylim(0, np.max(radii))\n\n    return ax\n\n\ndef trim_play_action(df):\n    \"\"\"\n    Trims a play to only the duration of action\n    \"\"\"\n    if len(df.loc[df['event'] == 'ball_snap']['time'].values) == 0:\n        print('........No Snap for this play')\n        ball_snap_time = df['time'].min()\n    else:\n        ball_snap_time = df.loc[df['event'] ==\n                                'ball_snap']['time'].values.min()\n\n    try:\n        end_time = df.loc[(df['event'] == 'out_of_bounds') |\n                          (df['event'] == 'downed') |\n                          (df['event'] == 'tackle') |\n                          (df['event'] == 'punt_downed') |\n                          (df['event'] == 'fair_catch') |\n                          (df['event'] == 'touchback') |\n                          (df['event'] == 'touchdown')]['time'].values.max()\n    except ValueError:\n        end_time = df['time'].values.max()\n    df = df.loc[(df['time'] >= ball_snap_time) & (df['time'] <= end_time)]\n    return df\n","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"94b9c5eee5b58ed601c7c34b03816791e066d922"},"cell_type":"markdown","source":"## Function to put it all together"},{"metadata":{"trusted":true,"_uuid":"5970fd606a901f6d3dcafd095321e9bcc40b54cb"},"cell_type":"code","source":"def plot_injury_play(season_year, gamekey, playid,\n                     plot_velocity=False, ax3=None, display_url=False,\n                     figsize_velocity=(5, 4),\n                     **kwargs):\n    \"\"\"\n    Plot the injury play with velocity and details\n    \"\"\"\n    vr_thisplay = vr.loc[(vr['season_year'] == season_year) &\n                         (vr['playid'] == playid) &\n                         (vr['gamekey'] == gamekey)]\n\n    play = injury_play_ngs.loc[(injury_play_ngs['season_year'] == season_year) &\n                               (injury_play_ngs['playid'] == playid) &\n                               (injury_play_ngs['gamekey'] == gamekey)].copy()\n\n    # Calculate velocity in meters per second\n    play['dis_meters'] = play['dis'] / 1.0936  # Add distance in meters\n    # Speed\n    play['dis_meters'] / 0.01\n    play['v_mps'] = play['dis_meters'] / 0.1\n\n    # Filter to only duration of play\n    play = trim_play_action(play)\n\n    # play = pd.read_csv('../working/playlevel/during_play/{}-{}-{}.csv'.format(season_year, gamekey, playid))\n    play['dir_theta'] = play['dir'] * np.pi / 180\n\n    # Video footage link\n    url_link = vfi.loc[(vfi['season_year'] == season_year) &\n                       (vfi['playid'] == playid) &\n                       (vfi['gamekey'] == gamekey)]['preview link (5000k)'].values[0]\n\n    playdescription = vfi.loc[(vfi['season_year'] == season_year) &\n                              (vfi['playid'] == playid) &\n                              (vfi['gamekey'] == gamekey)]['playdescription'].values[0]\n\n    print('==========================================================')\n    print('======= Running for Season {} PlayID {} GameKey {} ==='.format(season_year, playid, gamekey))\n    print('==========================================================')\n    print(\"=== PLAY DESCRIPTION: ===\")\n    print(playdescription)\n    \n    if display_url:\n        print(\"=== INJURY INFO: ===\")\n\n        print('Injured player number {} was injured while {} with primary impact {}'\n              .format(vr_thisplay['number'].values[0],\n                      vr_thisplay['player_activity_derived'].values[0],\n                      vr_thisplay['primary_impact_type'].values[0]))\n        \n        if vr_thisplay['gsisid_primary_partner'].values[0][0] != np.nan:\n            print('Injuring player number was injured the other player while {} with primary impact {}'\n                  .format(vr_thisplay['primary_partner_activity_derived'].values[0],\n                          vr_thisplay['primary_impact_type'].values[0]))\n        display(HTML(\"\"\"<a href=\"{}\">LINK TO VIDEO FOOTAGE FOR SEASON: {} PLAYID: {} GAMEKEY: {}</a>\"\"\" \\\n                     .format(url_link, season_year, playid, gamekey)))\n\n    # Determine time of injury\n    injured = play.loc[play['injured_player']]\n    primarypartner = play.loc[play['primary_partner_player']]\n    injury_time = None\n    if len(primarypartner) != 0:\n        inj_and_pp = pd.merge(injured[['time', 'x', 'y']], primarypartner[[\n                              'time', 'x', 'y']], on='time', suffixes=('_inj', '_pp'))\n        inj_and_pp['dis_from_eachother'] = np.sqrt(np.square(inj_and_pp['x_inj'] -\n                                                             inj_and_pp['x_pp']) +\n                                                   np.square(inj_and_pp['y_inj'] -\n                                                             inj_and_pp['y_pp']))\n        injury_time = inj_and_pp.sort_values('dis_from_eachother')[\n            'time'].values[0]\n    # PLOT\n    fig, ax3 = create_football_field(**kwargs)\n\n    # Plot path of injured player\n    d = play.loc[play['injured_player']]\n    injured_player_role = play.loc[play['injured_player']]['role'].values[0]\n    d.plot('x', 'y', kind='scatter', ax=ax3,  zorder=5, color='blue', alpha=0.3,\n           xlim=(0, 120), ylim=(0, 53.3),\n           label='Injured Player Path - Role: {}'.format(injured_player_role))  # Plot injured player path\n    play.loc[(play['punting_returning_team'] == 'Returning_Team') &\n             (play['event'] == 'ball_snap')].plot('x', 'y', alpha=1, kind='scatter',\n                                                  color='purple', ax=ax3, zorder=5, style='+',\n                                                  label='Returning Team Player')\n    play.loc[(play['punting_returning_team'] == 'Punting_Team') &\n             (play['event'] == 'ball_snap')].plot('x', 'y', alpha=1, kind='scatter',\n                                                  color='orange', ax=ax3, zorder=4, style='+',\n                                                  label='Punting Team Player')\n    start_pos = d.loc[d['time'] == d['time'].min()]\n    inj_star_pos = ax3.scatter(start_pos['x'], start_pos['y'], color='red',\n                               zorder=5, label='Injured Player Starting Position')\n    end_pos = d.loc[d['time'] == d['time'].max()]\n    ax3.scatter(end_pos['x'], end_pos['y'], color='black',\n                zorder=5, label='Injured Player Ending Position')\n    if injury_time:\n        inj_pos = d.loc[d['time'] == injury_time]\n    pp_player_role = None\n    if len(primarypartner) != 0:\n        pp_player_role = play.loc[play['primary_partner_player']\n                                  ]['role'].values[0]\n        play.loc[play['primary_partner_player']].plot('x', 'y', kind='scatter',\n                                                      xlim=(0, 120), ylim=(0, 53.3),\n                                                      ax=ax3, color='yellow', alpha=0.3, zorder=3,\n                                                      label='Primary Partner Path - Role {}'.format(pp_player_role))\n        ax3.scatter(inj_pos['x'],\n                    inj_pos['y'],\n                    color='red',\n                    zorder=5,\n                    s=50,\n                    marker='+',\n                    label='Aproximate Location of Injury')\n    play_info_string = 'Season {} - Gamekey {} - Playid {}'.format(\n        season_year, gamekey, playid)\n    injured_player_string = 'Injured Player Number: {} - action {}' \\\n        .format(vr_thisplay['number'].values[0],\n                vr_thisplay['player_activity_derived'].values[0])\n    primary_partner_string = 'Primary Partner Player Number: {} - action {}' \\\n        .format(vr_thisplay['number_primary_partner'].values[0],\n                vr_thisplay['primary_partner_activity_derived'].values[0])\n    # Plot punt return path if not one of the players.\n    if (injured_player_role != 'PR') and (pp_player_role != 'PR'):\n        punt_returner = play.loc[play['role'] == 'PR']\n        punt_returner.plot('x', 'y', kind='scatter', ax=ax3,  zorder=3, color='white', alpha=0.3,\n                           label='Punt Returner Path')\n\n    plt.suptitle(play_info_string, fontsize=15)\n    plt.legend(loc='center left', bbox_to_anchor=(1, 0.5))\n\n    if plot_velocity:\n        # Plot injured player compass\n\n        fig3, (ax1, ax2) = plt.subplots(\n            1, 2, subplot_kw=dict(polar=True), figsize=figsize_velocity)\n\n        d = play.loc[play['injured_player']]\n        role = d.role.values[0]\n\n        ax1 = compass(d['dir_theta'], d['v_mps'],\n                      arrowprops={'alpha': 0.3}, ax=ax1)\n        ax1.set_theta_zero_location(\"N\")\n        ax1.set_theta_direction(-1)\n        ax1.set_title('Injured Player: {}'.format(role))\n        # Color point of time when inujury happened\n        if len(primarypartner) != 0:\n            theta_at_inj = d.loc[d['time'] ==\n                                 injury_time]['dir_theta'].values[0]\n            dis_at_inj = d.loc[d['time'] == injury_time]['v_mps'].values[0]\n            impact_arrow = ax1.annotate(\"\",\n                                        xy=(theta_at_inj, dis_at_inj), xytext=(\n                                            0, 0),\n                                        arrowprops={'color': 'orange'},\n                                        label='Aproximate Point of Impact')  # use cir mean\n            # plt.legend(loc='center left', bbox_to_anchor=(1, 0.5))\n        # plt.suptitle('Velocity and Direction (Injured Player): {}'.format(role), x=0.52, y=1.01, fontsize=15)\n\n        if len(primarypartner) != 0:\n            # Plot primary partner compass\n            d = play.loc[play['primary_partner_player']]\n            role = d.role.values[0]\n            ax2 = compass(d['dir_theta'], d['v_mps'],\n                          arrowprops={'alpha': 0.3}, ax=ax2)\n            ax2.set_theta_zero_location(\"N\")\n            ax2.set_theta_direction(-1)\n            ax2.set_title('Primary Partner: {}'.format(role))\n            # Color point of time when inujury happened\n            theta_at_inj = d.loc[d['time'] ==\n                                 injury_time]['dir_theta'].values[0]\n            dis_at_inj = d.loc[d['time'] == injury_time]['v_mps'].values[0]\n            ax2.annotate(\"\", xy=(theta_at_inj, dis_at_inj), xytext=(\n                0, 0), arrowprops={'color': 'orange'})  # use cir mean\n            # plt.suptitle('Velocity and Direction (Primary Partner): {}'.format(role), x=0.52, y=1.01, fontsize=15)\n            plt.show()\n    return ax3","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"caa5e849596c7d87c180e5445869ad4d3c2ac286"},"cell_type":"markdown","source":"# Loop through each injury play and plot, with information and link to video footage."},{"metadata":{"trusted":true,"_uuid":"b99c9ae6aea4dc197622ab2d0ae7e99fded456a5","scrolled":false},"cell_type":"code","source":"for row in vr.iterrows():\n    \"\"\"\n    Loop through each play in the video review dataframe and call the\n    plot injury plat to show information about the play.\n    \"\"\"\n    season_year = row[1]['season_year']\n    gamekey = row[1]['gamekey']\n    playid = row[1]['playid']\n    \n    plot_injury_play(season_year=season_year, \n                     gamekey=gamekey,\n                     playid=playid,\n                     figsize=(10, 5),\n                     plot_velocity=True,\n                     figsize_velocity=(15, 5),\n                     display_url=True)\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"eb5f61b8ee83dbeabdc0d68895e3f9ed6dbd6ce0"},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.6","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}