How to Upload Gpx Route to Strava
Office 4/half dozen - Calculate and visualize gradients of a Strava route GPX files with Python
Last week you've seen how easy it is to calculate the elevation deviation and distance of a Strava route. Information technology was a pace in the right direction, as you'll need both elevation and distance data today. One matter cyclists love talking most is gradients. These represent the gradient of the surface yous're riding on.
Every bit information technology turns out, you lot can estimate them effortlessly with bones Python and math skills. We have a lot to cover today, and so let'south dive direct in.
Don't feel like reading? Watch my video instead:
You tin download the source code on GitHub.
How to Read a Strava Route Dataset
Nosotros won't bother with GPX files today, as we already accept road data points, elevation, and distance extracted to a CSV file. To kickoff, import the usual suspects and tweak Matplotlib's default styling:
import numpy as np import pandas as pd import matplotlib.pyplot every bit plt plt.rcParams['figure.figsize'] = (16, 6) plt.rcParams['axes.spines.top'] = False plt.rcParams['axes.spines.right'] = False
From hither, load the route dataset:
route_df = pd.read_csv('../data/route_df_elevation_distance.csv') route_df.caput()
Read the last calendar week's article if you lot don't accept the route dataset in this format. To recap, in that location are 835 information points in total on this 36,4-kilometer route, so there are on average 43,half dozen meters between information points.
We can use the height divergence and distance information to approximate boilerplate gradients on each of 835 private segments.
How to Calculate Gradient from a Strava Route
A gradient is nothing only a slope of the surface you're riding on. Our data is quite limited, as we only accept 835 information points spread over 36 kilometers. We'll practice our best, but everything yous'll see from this point is but an estimation.
We can gauge the average slope between 2 information points by dividing the elevation difference betwixt them with the distance covered and multiplying the results by 100.
Let'southward test the logic with hardcoded values from the second data point (1.86 meters of summit gained over 87.59 meters):
(1.86 / 87.59) * 100 >>> ii.1235300833428474
The average grade from the road start to the second data bespeak was 2.1%. This means that, provided the aforementioned gradient continues, you would gain 2.i meters of elevation after 100 meters of distance.
It's simply an boilerplate, then continue that in mind. The first xv meters of the segment could have a 10% slope, and the remaining 72 meters could exist completely flat. On the other hand, the entire 87-meter segment could accept a perfectly distributed two.1% grade. The signal is - we can't know for sure, and the above logic is the best we tin do.
Let'southward employ it to the entire dataset. We'll skip the first row, every bit there's nothing to compare information technology with. Gradients are unremarkably rounded upward to single decimal points, but that's a convention, not a requirement. Experience complimentary to include more.
gradients = [np.nan] for ind, row in route_df.iterrows(): if ind == 0: keep course = (row['elevation_diff'] / row['distance']) * 100 gradients.append(np.circular(form, 1)) gradients[:10]
Calculations washed - allow'southward at present visualize the boilerplate slope for each of the 835 data points:
plt.title('Terrain gradient on the route', size=20) plt.xlabel('Data point', size=14) plt.ylabel('Slope (%)', size=xiv) plt.plot(np.arange(len(gradients)), gradients, lw=two, color='#101010');
There appears to be something incorrect with the route file. A unmarried information point has over 1200% gradient, which is incommunicable. In theory, that would mean yous proceeds 1200 meters of elevation after 100 meters of distance.
We'll mitigate this issue by adding a condition - if the estimated average gradient is greater than thirty%, we'll append NaN
to the listing. At that place are no gradients to a higher place 30% on this route, and such gradients are extremely rare overall.
gradients = [np.nan] for ind, row in route_df.iterrows(): if ind == 0: keep grade = (row['elevation_diff'] / row['distance']) * 100 if grade > 30: gradients.append(np.nan) else: gradients.append(np.round(form, one))
Permit's encounter how it looks like:
plt.title('Terrain gradient on the road', size=20) plt.xlabel('Data betoken', size=14) plt.ylabel('Slope (%)', size=14) plt.plot(np.arange(len(gradients)), gradients, lw=2, color='#101010');
It'due south a step in the right direction, but we now have a couple of missing data points. The thing is - there'due south a stupidly unproblematic ready.
How to Interpolate Incorrect Gradients From a Strava Road
First things first, we'll assign the calculated gradients to a new dataset column:
route_df['gradient'] = gradients route_df.head()
Permit's run across where the missing values are:
route_df[route_df['gradient'].isna()]
We can ignore the starting time one, as information technology's missing for a whole dissimilar reason. Nosotros'll have to handle the other 2. To get the idea of the approach, let'southward isolate the second one with the surrounding couple of rows:
route_df[401:406]
We'll impute the missing values with interpolation. It will supervene upon the missing value with the average of the data point before and after information technology. For example, the missing slope before the missing value was 0, and after it was -v.9. The interpolated slope will be -2,95, as (0 + (-5.9)) / two = -2.95
:
route_df[401:406].interpolate()
Use the snippet below to apply interpolation to the unabridged dataset and fill the missing value at the start row with a nix:
route_df['gradient'] = route_df['gradient'].interpolate().fillna(0) route_df.head()
Finally, we'll visualize the gradient to meet if the line is connected this time:
plt.championship('Terrain gradient on the route', size=twenty) plt.xlabel('Information point', size=14) plt.ylabel('Gradient (%)', size=14) plt.plot(np.arange(len(route_df)), route_df['gradient'], lw=2, colour='#101010');
Everything looks practiced now, which ways nosotros're ready to further clarify the gradient. We'll go out that for the upcoming article, merely for now delight save the dataset to a CSV file:
route_df.to_csv('../data/route_df_gradient.csv', index=Faux)
That'due south all I wanted to comprehend today. Let's wrap things upwards next.
Conclusion
And there you lot accept information technology - how to calculate and visualize gradients of a Strava route GPX file. You accept to acknowledge - information technology's easier than information technology sounds. Everything boils to uncomplicated school math anyone can follow. The following article volition complicate things slightly, every bit we'll shift our focus to gradient profiles. Put simply, we want to know the distance cycled beyond different gradient ranges, but don't worry about it just all the same.
Hither are the links to the entire series - I'll add together the URLs as I release the articles:
- Commodity one: Load and analyze GPX files from Strava
- Article two: Visualize GPX files from Strava with Folium — circle markers and polygon lines
- Article 3: Calculate elevation difference and altitude between points, visualize elevation profile of the route
- Article four: Summate route gradients based on tiptop difference and distance between points
- Commodity v: Calculate and visualize gradient profiles — altitude cycled in gradient ranges
- Article vi: Create a web application that analyzes and visualizes a user-uploaded GPX file from Strava
Source: https://betterdatascience.com/data-science-for-cycling-calculate-route-gradients-from-strava-gpx/
0 Response to "How to Upload Gpx Route to Strava"
Post a Comment