File: activities.md

package info (click to toggle)
stravalib 2.4-2
  • links: PTS, VCS
  • area: contrib
  • in suites: forky, sid
  • size: 5,340 kB
  • sloc: python: 4,462; makefile: 5
file content (308 lines) | stat: -rw-r--r-- 8,729 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
(activities)=
# Get Strava activity data

This page overviews working with your Strava activity data using the stravalib Python library.

## Retrieve an activity

To access data for a given activity, use the `client.get_activity` method and provide the `activity_id`.

The `client.get_activity` method returns a {py:class}`stravalib.model.DetailedActivity` object.

:::{note}
All of the commands below require you first to authenticate using a client object containing a token.

`from stravalib.client import Client`

:::

```{code-block} pycon
# This command assumes that you have already authenticated the client object.
>>> activity = client.get_activity(1234)
>>> type(activity)

<class 'stravalib.model.DetailedActivity'>
```

The `DetailedActivity` object has many properties such as type, distance, and elapsed time.

```{code-block} pycon
# Get the activity type
>>> activity = client.get_activity(207650614)
>>> print(f"type = {activity.type}")

# Output
root='Hike'
```

```pycon
# Get activity distance
>>> print(f"The distance is: {a.distance}")
The distance is: 1234
```

## Stravalib offers unit conversion helpers

stravalib uses the [python Pint library](https://pypi.org/project/Pint/) to facilitate working
with the values in the API that have associated units (e.g. distance, speed). You can use the pint library
directly or through the `stravalib.unithelper` module for shortcuts

You can convert the distance value to another unit if you import stravalib's
`stravalib.unit_helper` module.

```python
from stravalib import unit_helper

unit_helper.feet(activity.distance)

# Output: <Quantity(8073.49081, 'foot')>

unit_helper.miles(activity.distance)
# <Quantity(1.52907023, 'mile')>

unit_helper.kilometers(activity.distance)
# <Quantity(2.4608, 'kilometer')>
```

Similarly, you can access elapsed time and
convert it to a `timedelta` object.

```python
activity.elapsed_time

# Output: 2273

activity.elapsed_time.timedelta
# Output: <bound method Duration.timedelta of 2273>
```

### DetailedActivity iterator objects

Some items returned by stravalib will be returned as a
{py:class}`BatchedResultsIterator` object. A `BatchedResultsIterator` object contains a list of
items associated with an activity - for example, a list of comments or kudos.

If an attribute contains a discrete value, you can access the item's value as an attribute like this:

```{code-block} pycon
>>> activity.comment_count
3
```

However if it's a `BatchedResultsIterator`, you will see this:

```{code-block} pycon
>>> activity.comments
<BatchedResultsIterator entity=Comment>
```

You can access each comment or item within a `BatchedResultsIterator` object using a Python loop or a list comprehension:

```{code-block} pycon
>>> for comment in activity.comments:
>>>     print(f"Comment by: {comment.athlete.firstname},  {comment.text}")

Comment by: YourFriendsNameHere: Not the pool!
```

## Get Strava activity streams

{py:func}`stravalib.client.Client.get_activity_streams` returns a dictionary containing time-series
data associated with your activity.

You can specify the stream variables that you want to be returned by providing a list of accepted types to the `types`
parameter. The type options for streaming data can be found here: {py:class}`stravalib.strava_model.StreamType`.


The data returned from this request is a dictionary object that looks something like this:

```python
streams

"""
# Output dict:
{'latlng': Stream(...),
 'distance': Stream(...),
 'altitude': Stream(...)}
"""
```

The Python dictionary's key represent the stream type:

```python
if "altitude" in streams.keys():
    print(streams["altitude"].data)
```



:::{tip}
The resolution of the streaming data refers to the number of data points returned for your activity. Low resolution means fewer points. Low-resolution data returns a smaller dataset; this data will be faster to download. Alternatively, high-resolution data will return a larger dataset and is slower to download. However, the output spatial data will look more "smooth" as more points are associated with the activity path.
:::

:::{warning}
Collecting streaming data is API (and memory) intensive!
:::

### Full-resolution data

When accessing streaming data, if you don't set a resolution value it will default to `None`.
In this case, Strava will return the full-resolution representation of your data.

:::{warning}
The `resolution` parameter for Strava data streams is undocumented and could (and has) changed
at any time.
:::

### Low-resolution data request

```python
# Request desired stream types
types = ["latlng", "altitude"]
streams = client.get_activity_streams(
    activity_id=123456,
    types=types,
    resolution="low",
    series_type="distance",
)
print(type(streams))

# Output
# dict


print(len(streams_low["latlng"].data))
# Output: This will return the lowest resolution data
# 100
```

### Medium resolution data request

```python
# Request desired stream types
types = ["latlng", "altitude"]
streams = client.get_activity_streams(
    activity_id=123456,
    types=types,
    resolution="medium",
    series_type="distance",
)

print(len(streams_med["latlng"].data))
# Output: notice there are more data points compared to a low resolution request
# 983
```

### High resolution data request

```python
# Request desired stream types
types = ["latlng", "altitude"]
streams = client.get_activity_streams(
    activity_id=123456,
    types=types,
    resolution="high",
    series_type="distance",
)

print(len(streams_high["latlng"].data))
# Output: notice there are more data points compared to both low and medium resolution. This is the max resolution possible.
# 1729
```

:::{note}
If your activity is short, the number of data points returned for medium vs. low-resolution data may not be significantly different.
:::

### Access activity zones

Additionally, you can retrieve activity zones using: {py:func}`stravalib.client.Client.get_activity_zones`; activity laps can be retrieved with {py:func}`stravalib.client.Client.get_activity_laps`.

### Access photos for an activity

To get photos for an associated activity, you can use`client.get_activity_photos(activity_id, max_resolution)`. Here, max_resolution is the maximum resolution of photos that you want to
collect in pixels.

```python
photos = client.get_activity_photos(id_w_photos, 2000)
photos

# Expected Output:
# <BatchedResultsIterator entity=ActivityPhoto>
```

The photos endpoint returns a `BatchedResultsIterator` object that you can loop through to access photo metadata and URLs for downloading the photos.

```python
for i, photo in enumerate(photos):
    print("photo")
```

You can access photo attributes like this:

```python
photo.default
True

photo.sizes
{"2000": [2048, 1261]}

photo.urls

{"2000": "https://dgtzuqphqg23d.cloudfront.net/url-is-here.jpg"}
```

## Get a list of Strava activities

You can access multiple activities using the {py:func}`stravalib.client.Client.get_activities` method. This method will return a `BatchedResultsIterator` that you can loop through.

:::{note}
The activities `batchedResultsIterator` object stores data that allows stravalib to access activity data when you iterate through the object. This approach limits the API requests made up front to Strava.
:::

Below, you request activities that were recorded after Jan 1, 2024.

```python
activities = client.get_activities(after="2024-01-01", limit=5)
print(activities)
# Expected output:
# <BatchedResultsIterator entity=SummaryActivity>
```

Using the limit parameter will limit the number of activities
Stravalib will retrieve. Above, you retrieve the first 5 activities.

```python
for i, activity in enumerate(activities):
    print(i)
"""
0
1
2
3
4

print(f"I found {i+1} activities for you.")
I found 5 activities for you.
"""
```

:::{tip}
To get activities starting with the oldest first, specify a value for the `after=` parameter when calling `client.get_activities`. Use the `before=` parameter to get the last 5 activities.
:::

## Get club member activities

You can also use stravalib to access activities associated with a club. To do this, use {py:func}`stravalib.client.Client.get_club_activities`.

<!-- (TODO)
## Create and update activities

I think this should be a new page on updating and creating activities.
=============== ================================================
method           doc
=============== ================================================
create_activity  {py:func}`stravalib.client.Client.create_activity`
upload_activity {py:func}`stravalib.client.Client.upload_activity`
update_activity {py:func}`stravalib.client.Client.update_activity`
=============== ================================================ -->