Skip to content

Instantly share code, notes, and snippets.

@barrysmyth
Last active November 12, 2023 20:47
Show Gist options
  • Save barrysmyth/c4bb6f7819fe61634b63ff82be720839 to your computer and use it in GitHub Desktop.
Save barrysmyth/c4bb6f7819fe61634b63ff82be720839 to your computer and use it in GitHub Desktop.
def plot_training_week_summary_bars(headline, header, chart, footer, week, fontsize=15):
""" Plot a summary of the training week.
Args:
headline - axis for the chart headline/title.
header - axis for the chart header info (weekly mins, RE, % easy).
chart - axis for the main chart (horizontal bar).
footer - axis for the weekly kms and mean pace.
week - a dataframe with data for the week to be summarised.
fontsize - fontsize to be used for all text annotations.
"""
# ------------------------------------------------------------------------ #
# The start/end of the current training week.
# Calculate the number of week before the race.
num_weeks_before_race = week['days_before_race'].iloc[0]//7
# The date of the first day of the week.
first_session_day_num = int(week.index[0])
first_session_date = week.iloc[0]['date']
week_start_date = (first_session_date-timedelta(days=first_session_day_num))
week_end_date = week_start_date + timedelta(days=6)
# ------------------------------------------------------------------------ #
# Get the session data needed ...
# Sum across the week's sessions.
w = week.select_dtypes(include='number').sum()
# Total kms and mins for the week.
total_kms = w['distance']/1000
total_mins = w['moving_time']/60
# Mean pace for the week.
mean_pace = convert_to_pace(total_mins/total_kms)
# The number of activities and total relative effort
num_activities = len(week)
total_suffer_score = w['suffer_score']
# The % of easy (Z1/Z2) running.
pct_easy = (
100*(week[['z1_moving_time', 'z2_moving_time']]
.sum(axis=1)
.sum()/w['moving_time'])
)
# The kms in each HR zone.
kms_in_zone = w.filter(regex='z\d_distance')/1000
mins_in_zone = w.filter(regex='z\d_moving_time')/60
# ------------------------------------------------------------------------ #
# Creating the weekly chart
# Remove the axis decorations.
headline.set_axis_off()
header.set_axis_off()
footer.set_axis_off()
# The colours for the 6 HR zones.
use_cmap = mpl.colormaps['coolwarm']
use_colours = use_cmap(np.linspace(.25, 1, 6))
# Plot the bar chart.
chart.barh(range(len(mins_in_zone)), mins_in_zone, color=use_colours)
chart.set_xlim(0, 450)
chart.set_yticks(range(len(kms_in_zone)))
chart.set_yticklabels(['Z1', 'Z2', 'Z3', 'Z4', 'Z5', 'Z6'], fontsize=fontsize)
# Remove the spines/ticks for the right/top/bottom axes.
chart.spines[['right', 'top', 'bottom']].set_visible(False)
chart.xaxis.set_tick_params(bottom=False, labelbottom=False)
# Add the labels for each bar.
for z, m in enumerate(mins_in_zone):
if int(m)>0: chart.text(m, z, ' {:.0f} mins'.format(m), fontsize=fontsize, ha='left', va='center', color='grey')
# -------------------------------------------------------------------------#
# Add the headline, header, and footer annotations
headline.text(
0, np.mean(footer.get_ylim()),
'Wk {}. {} - {} (x{:.0f})'.format(num_weeks_before_race, week_start_date.strftime('%b %d'), week_end_date.strftime('%b %d'), num_activities),
fontsize=fontsize, fontweight='bold',
ha='left', va='center'
)
header.text(
0, np.mean(header.get_ylim()),
'{:.0f} mins, {:.0f} RE, {:.0f}% Easy'.format(total_mins, total_suffer_score, pct_easy),
fontsize=fontsize, color='grey',
ha='left', va='center'
)
footer.text(
0, np.mean(footer.get_ylim()),
'{:.2f} kms @ {} mins/km'.format(total_kms, mean_pace),
fontsize=fontsize, ha='left', va='center', color='grey'
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment