Skip to content

Commit 32161bb

Browse files
committed
#5 Work in progress:
- Finish expert_data_table method - Add expert_ascent_rate_graph method [ci skip]
1 parent 2a7e600 commit 32161bb

File tree

1 file changed

+62
-11
lines changed

1 file changed

+62
-11
lines changed

ezgpx/gpx/gpx.py

+62-11
Original file line numberDiff line numberDiff line change
@@ -1254,13 +1254,13 @@ def expert_elevation_profile_plot(
12541254

12551255
# Plot
12561256
if color in ["ele", "speed", "pace", "vertical_drop", "ascent_rate", "ascent_speed"]:
1257-
axes.scatter(self.dataframe["distance_from_start"].values,
1257+
axes.scatter(self.dataframe["distance_from_start"].values / 1000,
12581258
self.dataframe["ele"].values,
12591259
s=size,
12601260
c=self.dataframe[color],
12611261
cmap=cmap) # .values to avoid -> Multi-dimensional indexing (e.g. `obj[:, None]`) is no longer supported. Convert to a numpy array before indexing instead.
12621262
else:
1263-
axes.scatter(self.dataframe["distance_from_start"].values,
1263+
axes.scatter(self.dataframe["distance_from_start"].values / 1000,
12641264
self.dataframe["ele"].values,
12651265
s=size,
12661266
color=color) # .values to avoid -> Multi-dimensional indexing (e.g. `obj[:, None]`)
@@ -1269,6 +1269,10 @@ def expert_elevation_profile_plot(
12691269
if grid:
12701270
axes.grid()
12711271

1272+
# Axis labels
1273+
axes.set_xlabel("Distance [km]")
1274+
axes.set_ylabel("Elevation [m]")
1275+
12721276
def expert_data_table(
12731277
self,
12741278
axes: Axes,
@@ -1289,12 +1293,12 @@ def expert_data_table(
12891293
cell_text = [
12901294
[f"{self.distance()/1000:.2f} km"],
12911295
[f"{self.ascent():.2f} m"],
1292-
[""],
1293-
[""],
1294-
[""],
1295-
[""],
1296-
[""],
1297-
[""]
1296+
[f"{self.descent():.2f} m"],
1297+
[f"{self.total_elapsed_time()}"],
1298+
[f"{self.avg_speed():.2f} km/h"],
1299+
[f"{self.avg_moving_speed():.2f} km/h"],
1300+
[f"{self.max_speed():.2f} km/h"],
1301+
[f"{self.moving_time()}"]
12981302
]
12991303

13001304
axes.table(cellText=cell_text,
@@ -1304,6 +1308,39 @@ def expert_data_table(
13041308
bbox=bbox)
13051309
axes.axis("off")
13061310

1311+
def expert_ascent_rate_graph(
1312+
self,
1313+
axes: Axes):
1314+
ascent_rates = [None, 1, 5, 10, 20]
1315+
nb_ascent_rates = [0 for i in ascent_rates]
1316+
nb_points = 0
1317+
1318+
# Move to a Gpx method?
1319+
for track in self.gpx.tracks:
1320+
for track_segment in track.trkseg:
1321+
nb_points += len(track_segment.trkpt)
1322+
for track_point in track_segment.trkpt:
1323+
i = len(ascent_rates)-1
1324+
while i > 0 and track_point.ascent_rate < ascent_rates[i]:
1325+
i -= 1
1326+
nb_ascent_rates[i] += 1
1327+
1328+
percent_ascent_rate = [(nb * 100) / nb_points for nb in nb_ascent_rates]
1329+
1330+
y_pos = range(1, len(ascent_rates)+1)
1331+
y_labels = [f"{x} %" if x is not None else "" for x in ascent_rates]
1332+
rects = axes.barh(y=y_pos,
1333+
width=percent_ascent_rate,
1334+
color=["green", "yellow", "orange", "red", "black"])
1335+
large_percentiles = [f"{p:.1f} %" if p > 40 else '' for p in percent_ascent_rate]
1336+
small_percentiles = [f"{p:.1f} %" if p <= 40 else '' for p in percent_ascent_rate]
1337+
axes.bar_label(rects, small_percentiles,
1338+
padding=5, color='black', fontweight='bold')
1339+
axes.bar_label(rects, large_percentiles,
1340+
padding=-40, color='white', fontweight='bold')
1341+
axes.set_yticks(y_pos, labels=y_labels)
1342+
axes.set_title("Ascent rate")
1343+
13071344
def expert_plot(
13081345
self,
13091346
figsize: Tuple[int, int] = (14,8),
@@ -1327,12 +1364,14 @@ def expert_plot(
13271364
elevation_profile_color: str = "#101010",
13281365
elevation_profile_cmap: Optional[mpl.colors.Colormap] = None,
13291366
elevation_profile_colorbar: bool = False,
1367+
ascent_rate_graph_position: Optional[Tuple[int, int]] = (0,1), # None
13301368
shared_color: str = "#101010",
13311369
shared_cmap: Optional[mpl.colors.Colormap] = None,
13321370
shared_colorbar: bool = False,
13331371
data_table_position: Optional[Tuple[int, int]] = (1,1), # None
13341372
title: Optional[str] = None,
13351373
title_fontsize: int = 20,
1374+
watermark: bool = False,
13361375
file_path: Optional[str] = None):
13371376
# Create dataframe containing data from the GPX file
13381377
self.dataframe = self.to_dataframe(projection=True,
@@ -1396,7 +1435,7 @@ def expert_plot(
13961435
cmap=elevation_profile_cmap,
13971436
colorbar=elevation_profile_colorbar)
13981437
else:
1399-
logging.error(f"Invalid map position: no subplot {elevation_profile_position} in a {subplot} array of plots")
1438+
logging.error(f"Invalid elevation profile position: no subplot {elevation_profile_position} in a {subplot} array of plots")
14001439
return
14011440

14021441
# Handle data table plot
@@ -1409,12 +1448,24 @@ def expert_plot(
14091448
self.expert_data_table(axs[data_table_position[0], data_table_position[1]],
14101449
bbox=bbox)
14111450
else:
1412-
logging.error(f"Invalid map position: no subplot {elevation_profile_position} in a {subplot} array of plots")
1451+
logging.error(f"Invalid data table position: no subplot {data_table_position} in a {subplot} array of plots")
1452+
return
1453+
1454+
# Handle ascent rate bar graph
1455+
if ascent_rate_graph_position is not None:
1456+
if (True): # Check if ascent_rate_graph_position is correct
1457+
# Plot bar graph on subplot
1458+
self.expert_ascent_rate_graph(axs[ascent_rate_graph_position[0], ascent_rate_graph_position[1]])
1459+
else:
1460+
logging.error(f"Invalid ascent rate graph position: no subplot {ascent_rate_graph_position} in a {subplot} array of plots")
14131461
return
14141462

14151463
# Add title
14161464
if title is not None:
1417-
fig.suptitle(title, fontsize=title_fontsize)
1465+
if watermark:
1466+
fig.suptitle(title + "\n[made with ezGPX]", fontsize=title_fontsize)
1467+
else:
1468+
fig.suptitle(title, fontsize=title_fontsize)
14181469

14191470
# MAKE FUNCTION ??
14201471
# Save or display plot

0 commit comments

Comments
 (0)