"""
Function
--------
bokeh_plot(csv)
Plot Bokeh graph of probabilities for each team in tournament for each stage of tournament.
Parameters
----------
csv : CSV file or data in StringIO format
Example of properly formatted csv data is shown in the cell below.
Bokeh runs its visualization through a server-side Java kernal, which makes debugging/writing code using the library in python
EXTREMELY tedious. This code cannot be re-run twice without restarting the ipynb kernal/reloading the page/running the cell empty
to clear everything, etc., so make sure that your code is right the first time you put it in.
This function takes a StringIO-format dataset. The table MUST have five columns
with the following headers: Team, First Round, Conference Semifinals, Conference Finals, The Finals, Conference.
The table MUST a total of 17 rows, including the header.
Team: name of NBA team.
First Round: float between 0 and 1 representing probability of winning first round.
Conference Semifinals: float between 0 and 1 representing probability of winning Semi's.
Conference Finals: float between 0 and 1 representing probability of winning Conference Finals.
The Finals: float between 0 and 1 representing probability of winning Playoff Finals.
Conference: "East" or "West".
Returns
-------
None
"""
def bokeh_plot(csv):
# Create new notebook session.
NotebookSession(plot=None)
# Define colors for different tourney rounds.
round_color = {
"First Round" : "#0d3362",
"Conference Semifinals" : "#c64737",
"Conference Finals" : "black",
"The Finals" : "#ffd700",
}
# Bifurcated color scheme for representing conferences.
conference_color = {
"East" : "#aeaeb8",
"West" : "#e69584",
}
# Read data into DataFrame.
df = pd.read_csv(StringIO(csv))
# Define graph dimensions
width = 800
height = 800
inner_radius = 90
outer_radius = 300 - 10
minr = 0
maxr = 100
# Define ratio between graph measurements and input values.
a = ((outer_radius - inner_radius) / (maxr-minr))
# Define angles.
big_angle = 2.0 * np.pi / (len(df) + 1)
small_angle = big_angle / 9
# Initialize arrays for strings.
x = np.zeros(len(df))
y = np.zeros(len(df))
# Function to transform measurements from input to graph.
def rad(mic):
return a*mic*100+inner_radius
# Set output and hold.
output_notebook()
hold()
# Map lines.
line(x+1, y+1, alpha=0, width=width, height=height, title="", tools="", x_axis_type=None, y_axis_type=None)
# Draw initial graph, background, etc.
plot = curplot()
plot.x_range = Range1d(start=-420, end=420)
plot.y_range = Range1d(start=-420, end=420)
plot.min_border = 0
plot.background_fill = "#FFFFFF"
plot.border_fill = "#f0e1d2"
plot.outline_line_color = None
# annular wedges
angles = np.pi/2 - big_angle/2 - df.index*big_angle
colors = [conference_color[comp] for comp in df.Conference]
annular_wedge(
x, y, inner_radius, outer_radius, -big_angle+angles, angles, color=colors,
)
# small wedges
annular_wedge(
x, y, inner_radius, rad(df["First Round"]), -big_angle+angles + 7*small_angle, -big_angle+angles+8*small_angle, color=round_color["First Round"],
)
annular_wedge(
x, y, inner_radius, rad(df["Conference Semifinals"]), -big_angle+angles + 5*small_angle, -big_angle+angles+6*small_angle, color=round_color["Conference Semifinals"],
)
annular_wedge(
x, y, inner_radius, rad(df["Conference Finals"]), -big_angle+angles + 3*small_angle, -big_angle+angles+4*small_angle, color=round_color["Conference Finals"],
)
annular_wedge(
x, y, inner_radius, rad(df["The Finals"]), -big_angle+angles + 1*small_angle, -big_angle+angles+2*small_angle, color=round_color["The Finals"],
)
# circular axes and lables
labels = np.arange(0, 110,20)
radii = a * labels + inner_radius
circle(x, y, radius=radii, fill_color=None, line_color="white")
text(x[1:], radii[1:], [str(r) for r in labels[1:]], angle=0, text_font_size="8pt", text_align="center", text_baseline="middle")
# radial axes
annular_wedge(
x, y, inner_radius-10, outer_radius+10, -big_angle+angles, -big_angle+angles, color="black",
)
# team labels
xr = (radii[-1]+10)*np.cos(np.array(-big_angle/2 + angles))
yr = (radii[-1]+10)*np.sin(np.array(-big_angle/2 + angles))
label_angle=np.array(-big_angle/2+angles)
label_angle[label_angle < -np.pi/2] += np.pi # easier to read labels on the left side
text(xr, yr, df.Team, angle=label_angle, text_font_size="9pt", text_align="center", text_baseline="middle")
# OK, these hand drawn legends are pretty clunky, will be improved in future release
circle([-40, -40], [-370, -390], color=conference_color.values(), radius=5)
text([-30, -30], [-370, -390], text=[x for x in conference_color.keys()], angle=0, text_font_size="7pt", text_align="left", text_baseline="middle")
rect([-40, -40, -40,-40], [18, 0, -18,-36], width=30, height=13, color=round_color.values())
text([-15, -15, -15,-15], [18, 0, -18,-36], text=round_color.keys(), angle=0, text_font_size="7pt", text_align="left", text_baseline="middle")
xgrid().grid_line_color = None
ygrid().grid_line_color = None
show()