wsba-hockey 1.0.6__py3-none-any.whl → 1.1.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- wsba_hockey/api/api/index.py +129 -0
- wsba_hockey/api/api/main.py +4 -0
- wsba_hockey/api/api/tools/__init__.py +0 -0
- wsba_hockey/api/api/tools/agg.py +374 -0
- wsba_hockey/api/api/tools/archive/old_scraping.py +1104 -0
- wsba_hockey/api/api/tools/plotting.py +144 -0
- wsba_hockey/api/api/tools/scraping.py +1000 -0
- wsba_hockey/api/api/tools/utils/__init__.py +1 -0
- wsba_hockey/api/api/tools/utils/config.py +14 -0
- wsba_hockey/api/api/tools/utils/save_pages.py +133 -0
- wsba_hockey/api/api/tools/utils/shared.py +450 -0
- wsba_hockey/api/api/tools/xg_model.py +455 -0
- wsba_hockey/api/api/wsba_main.py +1213 -0
- wsba_hockey/data_pipelines.py +71 -8
- wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/game_stats/app.py +6 -5
- wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/goalie/app.py +101 -0
- wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/goalie/plot.py +71 -0
- wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/goalie/rink_plot.py +245 -0
- wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/heatmaps/app.py +1 -1
- wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/heatmaps/plot.py +2 -0
- wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/heatmaps/rink_plot.py +1 -1
- wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/matchups/app.py +3 -3
- wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/matchups/plot.py +2 -0
- wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/matchups/rink_plot.py +1 -1
- wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/pbp/app.py +44 -28
- wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/pbp/plot.py +12 -3
- wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/pbp/rink_plot.py +1 -1
- wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/skater/app.py +1 -1
- wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/skater/plot.py +5 -4
- wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/skater/rink_plot.py +1 -1
- wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/team_heatmaps/app.py +103 -0
- wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/team_heatmaps/plot.py +95 -0
- wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/team_heatmaps/rink_plot.py +245 -0
- wsba_hockey/flask/app.py +77 -0
- wsba_hockey/tools/plotting.py +3 -3
- wsba_hockey/tools/scraping.py +7 -3
- wsba_hockey/tools/xg_model.py +3 -3
- wsba_hockey/workspace.py +28 -12
- wsba_hockey/wsba_main.py +10 -17
- {wsba_hockey-1.0.6.dist-info → wsba_hockey-1.1.1.dist-info}/METADATA +1 -1
- {wsba_hockey-1.0.6.dist-info → wsba_hockey-1.1.1.dist-info}/RECORD +44 -24
- {wsba_hockey-1.0.6.dist-info → wsba_hockey-1.1.1.dist-info}/WHEEL +0 -0
- {wsba_hockey-1.0.6.dist-info → wsba_hockey-1.1.1.dist-info}/licenses/LICENSE +0 -0
- {wsba_hockey-1.0.6.dist-info → wsba_hockey-1.1.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,144 @@
|
|
1
|
+
import os
|
2
|
+
import matplotlib.pyplot as plt
|
3
|
+
import numpy as np
|
4
|
+
import pandas as pd
|
5
|
+
from hockey_rink import NHLRink
|
6
|
+
from hockey_rink import CircularImage
|
7
|
+
from scipy.interpolate import griddata
|
8
|
+
from scipy.ndimage import gaussian_filter
|
9
|
+
from tools.xg_model import *
|
10
|
+
|
11
|
+
### PLOTTING FUNCTIONS ###
|
12
|
+
# Provided in this file are basic plotting functions for the WSBA Hockey Python package. #
|
13
|
+
|
14
|
+
## GLOBAL VARIABLES ##
|
15
|
+
|
16
|
+
event_markers = {
|
17
|
+
'faceoff':'X',
|
18
|
+
'hit':'P',
|
19
|
+
'blocked-shot':'v',
|
20
|
+
'missed-shot':'o',
|
21
|
+
'shot-on-goal':'D',
|
22
|
+
'goal':'*',
|
23
|
+
'giveaway':'1',
|
24
|
+
'takeaway':'2',
|
25
|
+
}
|
26
|
+
|
27
|
+
dir = os.path.dirname(os.path.realpath(__file__))
|
28
|
+
info_path = os.path.join(dir,'teaminfo\\nhl_teaminfo.csv')
|
29
|
+
img_path = os.path.join(dir,'utils\\wsba.png')
|
30
|
+
|
31
|
+
def wsba_rink(display_range='offense',rotation = 0):
|
32
|
+
rink = NHLRink(center_logo={
|
33
|
+
"feature_class": CircularImage,
|
34
|
+
"image_path": img_path,
|
35
|
+
"length": 25, "width": 25,
|
36
|
+
"x": 0, "y": 0,
|
37
|
+
"radius": 14,
|
38
|
+
"zorder": 11,
|
39
|
+
}
|
40
|
+
)
|
41
|
+
rink.draw(
|
42
|
+
display_range=display_range,
|
43
|
+
rotation=rotation,
|
44
|
+
despine=True
|
45
|
+
)
|
46
|
+
|
47
|
+
def prep_plot_data(pbp,events,strengths,marker_dict=event_markers):
|
48
|
+
try: pbp['xG']
|
49
|
+
except:
|
50
|
+
pbp = wsba_xG(pbp)
|
51
|
+
pbp['xG'] = np.where(pbp['xG'].isna(),0,pbp['xG'])
|
52
|
+
|
53
|
+
pbp['WSBA'] = pbp['event_player_1_name']+pbp['season'].astype(str)+pbp['event_team_abbr']
|
54
|
+
|
55
|
+
pbp['x_plot'] = np.where(pbp['x']<0,-pbp['y_adj'],pbp['y_adj'])
|
56
|
+
pbp['y_plot'] = abs(pbp['x_adj'])
|
57
|
+
|
58
|
+
pbp['home_on_ice'] = pbp['home_on_1'].astype(str) + ";" + pbp['home_on_2'].astype(str) + ";" + pbp['home_on_3'].astype(str) + ";" + pbp['home_on_4'].astype(str) + ";" + pbp['home_on_5'].astype(str) + ";" + pbp['home_on_6'].astype(str)
|
59
|
+
pbp['away_on_ice'] = pbp['away_on_1'].astype(str) + ";" + pbp['away_on_2'].astype(str) + ";" + pbp['away_on_3'].astype(str) + ";" + pbp['away_on_4'].astype(str) + ";" + pbp['away_on_5'].astype(str) + ";" + pbp['away_on_6'].astype(str)
|
60
|
+
|
61
|
+
pbp['onice_for'] = np.where(pbp['home_team_abbr']==pbp['event_team_abbr'],pbp['home_on_ice'],pbp['away_on_ice'])
|
62
|
+
pbp['onice_against'] = np.where(pbp['away_team_abbr']==pbp['event_team_abbr'],pbp['home_on_ice'],pbp['away_on_ice'])
|
63
|
+
|
64
|
+
pbp['size'] = np.where(pbp['xG']<=0,40,pbp['xG']*400)
|
65
|
+
pbp['marker'] = pbp['event_type'].replace(marker_dict)
|
66
|
+
|
67
|
+
pbp = pbp.loc[(pbp['event_type'].isin(events))]
|
68
|
+
|
69
|
+
if strengths != 'all':
|
70
|
+
pbp = pbp.loc[(pbp['strength_state'].isin(strengths))]
|
71
|
+
|
72
|
+
return pbp
|
73
|
+
|
74
|
+
def league_shots(pbp,events,strengths):
|
75
|
+
pbp = prep_plot_data(pbp,events,strengths)
|
76
|
+
|
77
|
+
print(pbp[['event_player_1_name','xG','x_plot','y_plot']].head(10))
|
78
|
+
|
79
|
+
[x,y] = np.round(np.meshgrid(np.linspace(-42.5,42.5,85),np.linspace(0,100,100)))
|
80
|
+
xgoals = griddata((pbp[f'x_plot'],pbp[f'y_plot']),pbp['xG'],(x,y),method='cubic',fill_value=0)
|
81
|
+
xgoals_smooth = gaussian_filter(xgoals,sigma = 3)
|
82
|
+
|
83
|
+
return xgoals_smooth
|
84
|
+
|
85
|
+
def plot_skater_shots(pbp, player, season, team, strengths, title = None, marker_dict=event_markers, onice='for', legend=False):
|
86
|
+
shots = ['missed-shot','shot-on-goal','goal']
|
87
|
+
pbp = prep_plot_data(pbp,shots,strengths,marker_dict)
|
88
|
+
pbp = pbp.loc[(pbp['season'].astype(str)==season)&((pbp['away_team_abbr']==team)|(pbp['home_team_abbr']==team))]
|
89
|
+
|
90
|
+
team_data = pd.read_csv(info_path)
|
91
|
+
team_color = list(team_data.loc[team_data['WSBA']==f'{team}{season}','Primary Color'])[0]
|
92
|
+
team_color_2nd = list(team_data.loc[team_data['WSBA']==f'{team}{season}','Secondary Color'])[0]
|
93
|
+
|
94
|
+
if onice in ['for','against']:
|
95
|
+
skater = pbp.loc[(pbp[f'onice_{onice}'].str.contains(player.upper()))]
|
96
|
+
skater['color'] = np.where(skater['event_player_1_name']==player.upper(),team_color,team_color_2nd)
|
97
|
+
|
98
|
+
else:
|
99
|
+
skater = pbp.loc[pbp['event_player_1_name']==player.upper()]
|
100
|
+
skater['color'] = team_color
|
101
|
+
|
102
|
+
fig, ax = plt.subplots()
|
103
|
+
wsba_rink(rotation=90)
|
104
|
+
|
105
|
+
for event in shots:
|
106
|
+
plays = skater.loc[skater['event_type']==event]
|
107
|
+
ax.scatter(plays['x_plot'],plays['y_plot'],plays['size'],plays['color'],marker=event_markers[event],label=event,zorder=5)
|
108
|
+
|
109
|
+
ax.set_title(title) if title else ''
|
110
|
+
ax.legend().set_visible(legend)
|
111
|
+
ax.legend().set_zorder(1000)
|
112
|
+
|
113
|
+
return fig
|
114
|
+
|
115
|
+
def plot_game_events(pbp,game_id,events,strengths,marker_dict=event_markers,team_colors={'away':'secondary','home':'primary'},legend=False):
|
116
|
+
pbp = prep_plot_data(pbp,events,strengths,marker_dict)
|
117
|
+
pbp = pbp.loc[pbp['game_id'].astype(str)==str(game_id)]
|
118
|
+
|
119
|
+
away_abbr = list(pbp['away_team_abbr'])[0]
|
120
|
+
home_abbr = list(pbp['home_team_abbr'])[0]
|
121
|
+
date = list(pbp['game_date'])[0]
|
122
|
+
season = list(pbp['season'])[0]
|
123
|
+
|
124
|
+
team_data = pd.read_csv(info_path)
|
125
|
+
team_info ={
|
126
|
+
'away_color':'#000000' if list(team_data.loc[team_data['WSBA']==f'{away_abbr}{season}','Secondary Color'])[0]=='#FFFFFF' else list(team_data.loc[team_data['WSBA']==f'{away_abbr}{season}',f'{team_colors['away'].capitalize()} Color'])[0],
|
127
|
+
'home_color': list(team_data.loc[team_data['WSBA']==f'{home_abbr}{season}',f'{team_colors['home'].capitalize()} Color'])[0],
|
128
|
+
'away_logo': f'tools/logos/png/{away_abbr}{season}.png',
|
129
|
+
'home_logo': f'tools/logos/png/{home_abbr}{season}.png',
|
130
|
+
}
|
131
|
+
|
132
|
+
pbp['color'] = np.where(pbp['event_team_abbr']==away_abbr,team_info['away_color'],team_info['home_color'])
|
133
|
+
|
134
|
+
fig, ax = plt.subplots()
|
135
|
+
wsba_rink(display_range='full')
|
136
|
+
|
137
|
+
for event in events:
|
138
|
+
plays = pbp.loc[pbp['event_type']==event]
|
139
|
+
ax.scatter(plays['x_adj'],plays['y_adj'],plays['size'],plays['color'],marker=event_markers[event],edgecolors='white',label=event,zorder=5)
|
140
|
+
|
141
|
+
ax.set_title(f'{away_abbr} @ {home_abbr} - {date}')
|
142
|
+
ax.legend(bbox_to_anchor =(0.5,-0.35), loc='lower center',ncol=1).set_visible(legend)
|
143
|
+
|
144
|
+
return fig
|