geo-activity-playground 1.8.3__py3-none-any.whl → 1.9.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -183,14 +183,18 @@ def enrichment_distance(
183
183
  if "speed" not in time_series.columns:
184
184
  time_series["speed"] = (
185
185
  time_series["distance_km"].diff()
186
- / (time_series["time"].diff().dt.total_seconds() + 1e-3)
186
+ / time_series["time"].diff().dt.total_seconds()
187
187
  * 3600
188
188
  )
189
+ # Division by zero causes infinity. We replace these with NaN and interpolate the values instead.
190
+ time_series["speed"] = time_series["speed"].replace([np.inf, -np.inf], np.nan)
191
+ time_series.interpolate(inplace=True)
192
+
189
193
  changed = True
190
194
 
191
195
  potential_jumps = (time_series["speed"] > 40) & (time_series["speed"].diff() > 10)
192
196
  if np.any(potential_jumps):
193
- time_series.replace(time_series.loc[~potential_jumps])
197
+ time_series.replace(time_series.loc[~potential_jumps], inplace=True)
194
198
  changed = True
195
199
 
196
200
  if "segment_id" not in time_series.columns:
@@ -240,6 +240,8 @@ def _process_activity(
240
240
  zip(activity_tiles["tile_x"], activity_tiles["tile_y"]),
241
241
  ):
242
242
  if activity.kind.consider_for_achievements:
243
+ if time is not None and time.tz is None:
244
+ time = time.tz_localize("UTC")
243
245
  if tile not in tile_state["tile_visits"][zoom]:
244
246
  new_tile_history_soa["activity_id"].append(activity_id)
245
247
  new_tile_history_soa["time"].append(time)
@@ -202,9 +202,32 @@ def read_gpx_activity(path: pathlib.Path, open) -> pd.DataFrame:
202
202
  time = dateutil.parser.parse(str(point.time))
203
203
  else:
204
204
  time = None
205
- points.append((time, point.latitude, point.longitude, point.elevation))
206
-
207
- df = pd.DataFrame(points, columns=["time", "latitude", "longitude", "elevation"])
205
+ row = {
206
+ "time": time,
207
+ "latitude": point.latitude,
208
+ "longitude": point.longitude,
209
+ "elevation": point.elevation,
210
+ }
211
+ if point.extensions:
212
+ for ext in point.extensions:
213
+ if (
214
+ ext.tag
215
+ == "{http://www.garmin.com/xmlschemas/TrackPointExtension/v1}TrackPointExtension"
216
+ ):
217
+ for datum in ext:
218
+ if (
219
+ datum.tag
220
+ == "{http://www.garmin.com/xmlschemas/TrackPointExtension/v1}hr"
221
+ ):
222
+ row["heartrate"] = int(datum.text)
223
+ if (
224
+ datum.tag
225
+ == "{http://www.garmin.com/xmlschemas/TrackPointExtension/v1}cad"
226
+ ):
227
+ row["cadence"] = int(datum.text)
228
+
229
+ points.append(row)
230
+ df = pd.DataFrame(points)
208
231
  # Some files don't have elevation information. In these cases we remove the column.
209
232
  if not df["elevation"].any():
210
233
  del df["elevation"]
@@ -117,6 +117,9 @@ def try_import_strava(
117
117
  for strava_activity in tqdm(
118
118
  client.get_activities(after=get_after), desc="Downloading Strava activities"
119
119
  ):
120
+ logger.info(
121
+ f"Examining Strava activity with ID {strava_activity.id} and name '{strava_activity.name}' …"
122
+ )
120
123
  if (
121
124
  strava_end
122
125
  and strava_activity.start_date is not None
@@ -195,6 +198,7 @@ def try_import_strava(
195
198
  activity.moving_time = detailed_activity.moving_time
196
199
 
197
200
  update_and_commit(activity, time_series, config)
201
+ logger.info(f"Added activity '{activity.name}' from Strava.")
198
202
  compute_tile_visits_new(repository, tile_visit_accessor)
199
203
  compute_tile_evolution(tile_visit_accessor.tile_state, config)
200
204
  tile_visit_accessor.save()
@@ -8,6 +8,7 @@ from flask import flash
8
8
  from flask import redirect
9
9
  from flask import render_template
10
10
  from flask import request
11
+ from flask import Response
11
12
  from flask import url_for
12
13
 
13
14
  from ...core.activities import ActivityRepository
@@ -59,8 +60,9 @@ def make_upload_blueprint(
59
60
  if file.filename == "":
60
61
  flash("No selected file", "warning")
61
62
  return redirect("/upload")
62
- if file:
63
+ for file in request.files.getlist("file"):
63
64
  filename = file.filename
65
+ assert filename is not None
64
66
  target_path = pathlib.Path(request.form["directory"]) / filename
65
67
  assert target_path.suffix in [
66
68
  ".csv",
@@ -79,18 +81,18 @@ def make_upload_blueprint(
79
81
  )
80
82
  return redirect(url_for(".index"))
81
83
  file.save(target_path)
82
- scan_for_activities(
83
- repository,
84
- tile_visit_accessor,
85
- config,
86
- skip_strava=True,
87
- )
88
- latest_activity = DB.session.scalar(
89
- sqlalchemy.select(Activity).order_by(Activity.id.desc()).limit(1)
90
- )
91
- assert latest_activity is not None
92
- flash(f"Activity was saved with ID {latest_activity.id}.", "success")
93
- return redirect(f"/activity/{latest_activity.id}")
84
+ scan_for_activities(
85
+ repository,
86
+ tile_visit_accessor,
87
+ config,
88
+ skip_strava=True,
89
+ )
90
+ latest_activity = DB.session.scalar(
91
+ sqlalchemy.select(Activity).order_by(Activity.id.desc()).limit(1)
92
+ )
93
+ assert latest_activity is not None
94
+ flash(f"Activity was saved with ID {latest_activity.id}.", "success")
95
+ return redirect(f"/activity/{latest_activity.id}")
94
96
 
95
97
  @blueprint.route("/refresh")
96
98
  @needs_authentication(authenticator)
@@ -6,7 +6,7 @@
6
6
  <form method="post" enctype="multipart/form-data" action="{{ url_for('.receive') }}">
7
7
  <div class="mb-3">
8
8
  <label for="file1" class="form-label">Activity file</label>
9
- <input type="file" name="file" id="file1" class="form-control">
9
+ <input type="file" name="file" id="file1" class="form-control" multiple>
10
10
  </div>
11
11
  <div class="mb-3">
12
12
  <label for="directory" class="form-label">Target directory</label>
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: geo-activity-playground
3
- Version: 1.8.3
3
+ Version: 1.9.0
4
4
  Summary: Analysis of geo data activities like rides, runs or hikes.
5
5
  License: MIT
6
6
  Author: Martin Ueding
@@ -22,7 +22,7 @@ geo_activity_playground/core/config.py,sha256=mmdMQ5iCLNGnAlriT1ETEVS-gM6Aq_9sg2
22
22
  geo_activity_playground/core/coordinates.py,sha256=rW_OmMRpTUyIsQwrT6mgT9Y6uPGuwqTo5XDDMS7mGuo,1140
23
23
  geo_activity_playground/core/copernicus_dem.py,sha256=t6Bc9fsyGyx1awdePXvlN-Zc-tiT2eGSJ80SV5B1Z9A,2944
24
24
  geo_activity_playground/core/datamodel.py,sha256=yuq3XCynetp1OlMr3fpSlXBArElgzdfejbqnJJX-xC4,16728
25
- geo_activity_playground/core/enrichment.py,sha256=b27E_KK30xjq8MuGFZyIpKzz8fO2LwLVaGGTP0mb5N0,8618
25
+ geo_activity_playground/core/enrichment.py,sha256=QMJla3r27Ejwa1fiS1Fc81m4oP8wiVHkdT1M0z830zE,8863
26
26
  geo_activity_playground/core/export.py,sha256=ayOmhWL72263oP9NLIZRYCg_Db0GLUFhgNIL_MCrV-E,4435
27
27
  geo_activity_playground/core/heart_rate.py,sha256=-S3WAhS7AOywrw_Lk5jfuo_fu6zvZQ1VtjwEKSycWpU,1542
28
28
  geo_activity_playground/core/meta_search.py,sha256=Sevl4AtBwJZMW3VJ6ihRqwjC0M9fhJqX3MN6tw_hIFQ,6627
@@ -48,14 +48,14 @@ geo_activity_playground/core/tiles.py,sha256=LBn2V6WAvMxZeXSIQ8ruZL71iyvOXoFZMz7
48
48
  geo_activity_playground/core/time_conversion.py,sha256=f5CByqyWSthCplrbXZThSFbt3eY-t1g-2H5lkfBlgc0,1556
49
49
  geo_activity_playground/explorer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
50
50
  geo_activity_playground/explorer/grid_file.py,sha256=YNL_c4O1-kxaajATJwj4ZLywCL5Hpj9qy2h-F7rk8Yg,3260
51
- geo_activity_playground/explorer/tile_visits.py,sha256=BEv6mUNO8Q71HbRPJDXe4OrzQW0CTMKh6DE9hNU9ukw,17188
51
+ geo_activity_playground/explorer/tile_visits.py,sha256=DzAmZmyLSeGe8mIg6-Kx1gXtCf5Bj8YjfNFD_imJyjE,17296
52
52
  geo_activity_playground/explorer/video.py,sha256=7j6Qv3HG6On7Tn7xh7Olwrx_fbQnfzS7CeRg3TEApHg,4397
53
53
  geo_activity_playground/heatmap_video.py,sha256=I8i1uVvbbPUXVtvLAROaLy58nQoUPnuMCZkERWNkQjg,3318
54
54
  geo_activity_playground/importers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
55
- geo_activity_playground/importers/activity_parsers.py,sha256=NAK_Fv_zy75WuNa1bgYgzjc7Dnsj1oVah6DW0faLCG4,11403
55
+ geo_activity_playground/importers/activity_parsers.py,sha256=Ums6SQ_fggE2alwwDbZZakxbeLQz0_9Iq4limDTW31k,12431
56
56
  geo_activity_playground/importers/csv_parser.py,sha256=O1pP5GLhWhnWcy2Lsrr9g17Zspuibpt-GtZ3ZS5eZF4,2143
57
57
  geo_activity_playground/importers/directory.py,sha256=sHcLIi0DOPEATt4wiE_vp00h89fO940wUQyJZUzzpnw,3978
58
- geo_activity_playground/importers/strava_api.py,sha256=IUmsN3Zor-CXXtdDVXJHsqBFnDNx-W0YoQ8d9ECcFT8,9377
58
+ geo_activity_playground/importers/strava_api.py,sha256=1sRb_CD4tbsW-MwP6QPg7zpATlb6XpniS4rtH72iwkw,9606
59
59
  geo_activity_playground/importers/strava_checkout.py,sha256=joJI_uic9fYtu7E5Odh6GUq_LyiLqQ72Ucy_Mbjr-X0,9289
60
60
  geo_activity_playground/importers/test_csv_parser.py,sha256=nOTVTdlzIY0TDcbWp7xNyNaIO6Mkeu55hVziVl22QE4,1092
61
61
  geo_activity_playground/importers/test_directory.py,sha256=_fn_-y98ZyElbG0BRxAmGFdtGobUShPU86SdEOpuv-A,691
@@ -83,7 +83,7 @@ geo_activity_playground/webui/blueprints/square_planner_blueprint.py,sha256=xVax
83
83
  geo_activity_playground/webui/blueprints/summary_blueprint.py,sha256=7aJYvo8EERGnItL9PFCMLM6T26xiQa3VP2RUvWglgy4,6734
84
84
  geo_activity_playground/webui/blueprints/tile_blueprint.py,sha256=YzZf9OrNdjhc1_j4MtO1DMcw1uCv29ueNsYd-mWqgbg,837
85
85
  geo_activity_playground/webui/blueprints/time_zone_fixer_blueprint.py,sha256=PEHsk3kRHx2EvQ-6VPD4xeOmXGjh64GMAagFkQ0wbeg,2301
86
- geo_activity_playground/webui/blueprints/upload_blueprint.py,sha256=mwoLeanW8oN6u7msE_Lx0grxDOYev4beqPbkPZRemkM,4763
86
+ geo_activity_playground/webui/blueprints/upload_blueprint.py,sha256=VLyMic2ptBRcMyunGXl-6Auxs1jglIO5fYgRGPhH25s,4816
87
87
  geo_activity_playground/webui/columns.py,sha256=FP0YfX-WFQk1JEXhrywv3NUEVq-x7Hv0or35X3Ltf9c,1525
88
88
  geo_activity_playground/webui/flasher.py,sha256=Covc1D9cO_jjokRWnvyiXCc2tfp3aZ8XkNqFdA1AXtk,500
89
89
  geo_activity_playground/webui/plot_util.py,sha256=5Uesjj-xcMskQX2z9viDZYHSxLGrH2a5dHA1ogsJW9U,261
@@ -173,10 +173,10 @@ geo_activity_playground/webui/templates/square_planner/index.html.j2,sha256=-OnY
173
173
  geo_activity_playground/webui/templates/summary/index.html.j2,sha256=VuSed6GU-FzjPC1aCYuEuK5B8Rw2D8NcseNLTFIGxkA,1441
174
174
  geo_activity_playground/webui/templates/summary/vega-chart.html.j2,sha256=mw8HtigeSnShTFZNG56UGUqHLJe70kvFR3o0TT71dBI,94
175
175
  geo_activity_playground/webui/templates/time_zone_fixer/index.html.j2,sha256=s9r6BJMXmd7kLSyjkvH4xLi6e01S5bpGRcMgMMJyCAE,1760
176
- geo_activity_playground/webui/templates/upload/index.html.j2,sha256=I1Ix8tDS3YBdi-HdaNfjkzYXVVCjfUTe5PFTnap1ydc,775
176
+ geo_activity_playground/webui/templates/upload/index.html.j2,sha256=5W2gpm4eSvidOyJOCSZZbvTZaTkSWNrOWux3-oIm0zI,784
177
177
  geo_activity_playground/webui/templates/upload/reload.html.j2,sha256=YZWX5eDeNyqKJdQAywDBcU8DZBm22rRBbZqFjrFrCvQ,556
178
- geo_activity_playground-1.8.3.dist-info/LICENSE,sha256=4RpAwKO8bPkfXH2lnpeUW0eLkNWglyG4lbrLDU_MOwY,1070
179
- geo_activity_playground-1.8.3.dist-info/METADATA,sha256=OhfYXMd4NPi3vQcxAmHZKoRiNMwZtLwABe4_EC4sExA,1937
180
- geo_activity_playground-1.8.3.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
181
- geo_activity_playground-1.8.3.dist-info/entry_points.txt,sha256=pbNlLI6IIZIp7nPYCfAtiSiz2oxJSCl7DODD6SPkLKk,81
182
- geo_activity_playground-1.8.3.dist-info/RECORD,,
178
+ geo_activity_playground-1.9.0.dist-info/LICENSE,sha256=4RpAwKO8bPkfXH2lnpeUW0eLkNWglyG4lbrLDU_MOwY,1070
179
+ geo_activity_playground-1.9.0.dist-info/METADATA,sha256=DO-gcjADFWzzSvxGFzgs9qfh2xs-EB39Rb_s2LYpXBg,1937
180
+ geo_activity_playground-1.9.0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
181
+ geo_activity_playground-1.9.0.dist-info/entry_points.txt,sha256=pbNlLI6IIZIp7nPYCfAtiSiz2oxJSCl7DODD6SPkLKk,81
182
+ geo_activity_playground-1.9.0.dist-info/RECORD,,