<jupyter_start><jupyter_text>Make your own heatmap based on Strava activitiesThis notebook shows you how to create your own heatmap based on your Strava activities.You need to create a Strava API application in order to use their API. Follow the instructions on this page to create your app: After setting up the app, note down the following information (you will need it to run this notebook):- Client id- Client secret**Note:** Strava imposes some request limits (30'000/day, and 600/every 15min).<jupyter_code>!pip install stravaio folium
import os
import logging
import json
import urllib
import requests
import folium
from stravaio import StravaIO
# Paste your client id and client secret here.
STRAVA_CLIENT_ID = "ENTER-YOUR-CLIENT-ID"
STRAVA_CLIENT_SECRET = "ENTER-YOUR-CLIENT-SECRET"<jupyter_output><empty_output><jupyter_text>Authorization with StravaThe cell below creates the proper authorization link using the Stravaio Python library, which is used later to retrieve activities.It is important to run this cell, just pasting the access_token from your Strava settings will not work, because Stravaio needs to be authorized.- Run the cell below and click the link that is printed, when prompted click "Authorize" on the website that opens- After you click "Authorize" you see something like, "This site can't be reached"- Stay on that page and look at the URL- The URL will show the authorization code (the bit after "code=" in the URL) and scope you accepted- Copy the code and paste it below and continue the notebook executionMore detailed info can be found here:- -<jupyter_code>params_oauth = {
    "client_id": STRAVA_CLIENT_ID,
    "response_type": "code",
    "redirect_uri": f"http://localhost:8000/authorization_successful",
    "scope": "read,profile:read_all,activity:read",
    "state": 'https://github.com/sladkovm/strava-http', # Sladkovm is the author of the Stravaio library
    "approval_prompt": "force"
}
values_url = urllib.parse.urlencode(params_oauth)
base_url = 'https://www.strava.com/oauth/authorize'
authorize_url = base_url + '?' + values_url
print(authorize_url)
# Paste the code from the URL here. Afterwards there are no manual steps anymore.
AUTHORIZATION_CODE = "ENTER-YOUR-AUTHORIZATION-CODE"<jupyter_output><empty_output><jupyter_text>The following cell retrieves an access token using the authorization code. That access token can then be used to retrieve Strava data.<jupyter_code>payload = {
    "client_id": STRAVA_CLIENT_ID,
    "client_secret": STRAVA_CLIENT_SECRET,
    "grant_type": "authorization_code",
    "code": AUTHORIZATION_CODE,
}

response = requests.request(
    "POST", "https://www.strava.com/api/v3/oauth/token", data=payload
)

response = json.loads(response.text)
TOKEN = response["access_token"]
!pip install stravaio folium
client = StravaIO(access_token=TOKEN)
athlete = client.get_logged_in_athlete()
activities = client.get_logged_in_athlete_activities(after=20170101)
m = folium.Map(
    tiles="cartodbpositron",
    location=[59.925, 10.728123],
    zoom_start=11.5,
    control_scale=True
)
folium.TileLayer("cartodbpositron").add_to(m)
folium.TileLayer("cartodbdark_matter").add_to(m)
folium.LayerControl().add_to(m)
def downsample(l, n):
    """Returns every nth element from list l. Returns the
    original list if n is set to 1.
    Used to reduce the number of GPS points per activity,
    to improve performance of the website.
    """
    
    return l[0::n]

def map_activities(activities, folium_map, opacity=0.5, weight=1):
    if len(activities) == 0:
        logging.info("No activities found, returning empty folium map.")
        return folium_map

    counter = 0
    for a in activities:
        if a.type == "Workout":
            continue
        streams = client.get_activity_streams(a.id, athlete.id)
        try:
            points = list(zip(streams.lat, streams.lng))
            points = downsample(l=points, n=2)
            if a.type == "Run":
                folium.PolyLine(
                    locations=points, color="#ff9933", opacity=opacity, weight=weight
                ).add_to(folium_map)
            elif a.type == "Ride":
                folium.PolyLine(
                    locations=points, color="#0066ff", opacity=opacity, weight=weight
                ).add_to(folium_map)
            elif a.type == "NordicSki":
                folium.PolyLine(
                    locations=points, color="#00ffff", opacity=opacity, weight=weight
                ).add_to(folium_map)
            elif a.type == "AlpineSki":
                folium.PolyLine(
                    locations=points, color="#00ccff", opacity=opacity, weight=weight
                ).add_to(folium_map)
            elif a.type == "Canoeing":
                folium.PolyLine(
                    locations=points, color="#00ff55", opacity=opacity, weight=weight
                ).add_to(folium_map)
            elif a.type == "IceSkate":
                folium.PolyLine(
                    locations=points, color="#f6ff00", opacity=opacity, weight=weight
                ).add_to(folium_map)
            else:
                folium.PolyLine(
                    locations=points, color="#cc00ff", opacity=opacity, weight=weight
                ).add_to(folium_map)
            logging.critical("Mapped activity with id: {}".format(a.id))
        except Exception:
            logging.error("Could not map activity with id: {}".format(a.id))
            
    return folium_map
m = map_activities(
    activities=activities,
    folium_map=m,
    opacity=0.5,
    weight=2
)
m<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.09586835986406725, 'fraction_numerical': 0.012698980504382043, 'mean_word_length': 3.18562874251497, 'pattern_counts': {'":': 17, '<': 13, '<?xml version=': 0, '>': 13, 'https://': 3, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '3', 'dir': 'jupyter-structured-clean-dedup', 'id': '3751', 'license': 'MIT', 'n_tokens_mistral': 1722, 'n_tokens_neox': 1664, 'n_words': 491, 'path': 'examples/make_your_own.ipynb', 'repo_name': 'rafaelschlatter/strava-heatmap', 'size': '5591'}