geo-activity-playground 0.39.0__py3-none-any.whl → 0.39.1__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.
@@ -91,6 +91,9 @@ class ActivityRepository:
91
91
  df["hours"] = [
92
92
  elapsed_time.total_seconds() / 3600 for elapsed_time in df["elapsed_time"]
93
93
  ]
94
+ df["hours_moving"] = [
95
+ moving_time.total_seconds() / 3600 for moving_time in df["moving_time"]
96
+ ]
94
97
  df.index = df["id"]
95
98
  return df
96
99
 
@@ -234,7 +234,7 @@ def get_or_make_kind(name: str, config: Config) -> Kind:
234
234
  else:
235
235
  kind = Kind(
236
236
  name=name,
237
- consider_for_achievements=config.kinds_without_achievements.get(name, True),
237
+ consider_for_achievements=name in config.kinds_without_achievements,
238
238
  )
239
239
  DB.session.add(kind)
240
240
  return kind
@@ -0,0 +1,101 @@
1
+ import dataclasses
2
+ from typing import Optional
3
+
4
+ import altair as alt
5
+ import pandas as pd
6
+
7
+
8
+ @dataclasses.dataclass
9
+ class ParametricPlotSpec:
10
+ mark: str
11
+ x: str
12
+ y: str
13
+ color: Optional[str]
14
+ shape: Optional[str]
15
+ size: Optional[str]
16
+ row: Optional[str]
17
+ column: Optional[str]
18
+
19
+
20
+ MARKS = {"point": "Point", "circle": "Circle", "area": "Area", "bar": "Bar"}
21
+ CONTINUOUS_VARIABLES = {
22
+ "distance_km": "Distance / km",
23
+ "sum(distance_km)": "Total distance / km",
24
+ "mean(distance_km)": "Average distance / km",
25
+ "start": "Date",
26
+ "hours": "Elapsed time / h",
27
+ "hours_moving": "Moving time / h",
28
+ "start_latitude": "Start latitude / °",
29
+ "start_longitude": "Start longitude / °",
30
+ "end_latitude": "End latitude / °",
31
+ "end_longitude": "End longitude / °",
32
+ "start_elevation": "Start elevation / m",
33
+ "end_elevation": "End elevation / m",
34
+ "elevation_gain": "Elevation gain / m",
35
+ "sum(elevation_gain)": "Total elevation gain / m",
36
+ "mean(elevation_gain)": "Average elevation gain / m",
37
+ "calories": "Energy / kcal",
38
+ "steps": "Steps",
39
+ "num_new_tiles_14": "New tiles 14",
40
+ "num_new_tiles_14": "New tiles 17",
41
+ "average_speed_moving_kmh": "Average moving speed / km/h",
42
+ "average_speed_elapsed_kmh": "Average elapsed speed / km/h",
43
+ }
44
+ DISCRETE_VARIABLES = {
45
+ "": "",
46
+ "year(start)": "Year",
47
+ "yearquarter(start)": "Year, Quarter",
48
+ "yearquartermonth(start)": "Year, Quarter, Month",
49
+ "yearmonth(start)": "Year, Month",
50
+ "quarter(start)": "Quarter",
51
+ "quartermonth(start)": "Quarter, Month",
52
+ "month(start)": "Month",
53
+ "date(start)": "Day of month",
54
+ "weekday(start)": "Day of week",
55
+ "iso_year": "ISO Year",
56
+ "week": "ISO Week",
57
+ "equipment": "Equipment",
58
+ "kind": "Activity kind",
59
+ "consider_for_achievements": "Consider for achievements",
60
+ }
61
+ ALL_VARIABLES = {**DISCRETE_VARIABLES, **CONTINUOUS_VARIABLES}
62
+
63
+
64
+ def make_parametric_plot(df: pd.DataFrame, spec: ParametricPlotSpec) -> str:
65
+ chart = alt.Chart(df)
66
+
67
+ match spec.mark:
68
+ case "point":
69
+ chart = chart.mark_point()
70
+ case "circle":
71
+ chart = chart.mark_circle()
72
+ case "area":
73
+ chart = chart.mark_area()
74
+ case "bar":
75
+ chart = chart.mark_bar()
76
+
77
+ encodings = [
78
+ alt.X(spec.x, title=ALL_VARIABLES[spec.x]),
79
+ alt.Y(spec.y, title=ALL_VARIABLES[spec.y]),
80
+ ]
81
+ tooltips = [
82
+ alt.Tooltip(spec.x, title=ALL_VARIABLES[spec.x]),
83
+ alt.Tooltip(spec.y, title=ALL_VARIABLES[spec.y]),
84
+ ]
85
+ if spec.color:
86
+ encodings.append(alt.Color(spec.color, title=ALL_VARIABLES[spec.color]))
87
+ tooltips.append(alt.Tooltip(spec.color, title=ALL_VARIABLES[spec.color]))
88
+ if spec.shape:
89
+ encodings.append(alt.Shape(spec.shape, title=ALL_VARIABLES[spec.shape]))
90
+ tooltips.append(alt.Tooltip(spec.shape, title=ALL_VARIABLES[spec.shape]))
91
+ if spec.size:
92
+ encodings.append(alt.Size(spec.size, title=ALL_VARIABLES[spec.size]))
93
+ tooltips.append(alt.Tooltip(spec.size, title=ALL_VARIABLES[spec.size]))
94
+ if spec.row:
95
+ encodings.append(alt.Row(spec.row, title=ALL_VARIABLES[spec.row]))
96
+ tooltips.append(alt.Tooltip(spec.row, title=ALL_VARIABLES[spec.row]))
97
+ if spec.column:
98
+ encodings.append(alt.Column(spec.column, title=ALL_VARIABLES[spec.column]))
99
+ tooltips.append(alt.Tooltip(spec.column, title=ALL_VARIABLES[spec.column]))
100
+
101
+ return chart.encode(*encodings).interactive().to_json(format="vega")
@@ -32,6 +32,7 @@ from .blueprints.entry_views import register_entry_views
32
32
  from .blueprints.equipment_blueprint import make_equipment_blueprint
33
33
  from .blueprints.explorer_blueprint import make_explorer_blueprint
34
34
  from .blueprints.heatmap_blueprint import make_heatmap_blueprint
35
+ from .blueprints.plot_builder_blueprint import make_plot_builder_blueprint
35
36
  from .blueprints.search_blueprint import make_search_blueprint
36
37
  from .blueprints.settings_blueprint import make_settings_blueprint
37
38
  from .blueprints.square_planner_blueprint import make_square_planner_blueprint
@@ -137,6 +138,7 @@ def web_ui_main(
137
138
  "/heatmap": make_heatmap_blueprint(
138
139
  repository, tile_visit_accessor, config_accessor(), search_query_history
139
140
  ),
141
+ "/plot-builder": make_plot_builder_blueprint(repository),
140
142
  "/settings": make_settings_blueprint(config_accessor, authenticator, flasher),
141
143
  "/square-planner": make_square_planner_blueprint(tile_visit_accessor),
142
144
  "/search": make_search_blueprint(
@@ -0,0 +1,43 @@
1
+ from flask import Blueprint
2
+ from flask import render_template
3
+ from flask import request
4
+ from flask import Response
5
+
6
+ from ...core.activities import ActivityRepository
7
+ from ...core.parametric_plot import ALL_VARIABLES
8
+ from ...core.parametric_plot import CONTINUOUS_VARIABLES
9
+ from ...core.parametric_plot import DISCRETE_VARIABLES
10
+ from ...core.parametric_plot import make_parametric_plot
11
+ from ...core.parametric_plot import MARKS
12
+ from ...core.parametric_plot import ParametricPlotSpec
13
+
14
+
15
+ def make_plot_builder_blueprint(repository: ActivityRepository) -> Blueprint:
16
+ blueprint = Blueprint("plot_builder", __name__, template_folder="templates")
17
+
18
+ @blueprint.route("/")
19
+ def index() -> Response:
20
+ context = {}
21
+ if request.args:
22
+ spec = ParametricPlotSpec(
23
+ mark=request.args["mark"],
24
+ x=request.args["x"],
25
+ y=request.args["y"],
26
+ color=request.args.get("color", None),
27
+ shape=request.args.get("shape", None),
28
+ size=request.args.get("size", None),
29
+ row=request.args.get("row", None),
30
+ column=request.args.get("column", None),
31
+ )
32
+ plot = make_parametric_plot(repository.meta, spec)
33
+ context["plot"] = plot
34
+ return render_template(
35
+ "plot_builder/index.html.j2",
36
+ marks=MARKS,
37
+ continuous=ALL_VARIABLES,
38
+ discrete=DISCRETE_VARIABLES,
39
+ **context,
40
+ **request.args
41
+ )
42
+
43
+ return blueprint
@@ -0,0 +1,44 @@
1
+ {% extends "page.html.j2" %}
2
+ {% from "search_form.html.j2" import search_form %}
3
+
4
+ {% block container %}
5
+
6
+ <h1 class="row mb-3">Plot Builder</h1>
7
+
8
+
9
+ <div class="row">
10
+ <div class="col-md-4">
11
+ {% macro select_field(label, name, choices, active) %}
12
+ <div class="mb-3">
13
+ <label for="{{ name }}">{{ label }}</label>
14
+ <select name="{{ name }}" class="form-select">
15
+ {% for choice_value, choice_label in choices.items() %}
16
+ <option id="{{ name }}" value="{{ choice_value }}" {% if active==choice_value %} selected {% endif %}>
17
+ {{ choice_label }}
18
+ </option>
19
+ {% endfor %}
20
+ </select>
21
+ </div>
22
+ {% endmacro %}
23
+
24
+ <form>
25
+ {{ select_field("Mark", "mark", marks, mark)}}
26
+
27
+ {{ select_field("X", "x", continuous, x)}}
28
+ {{ select_field("Y", "y", continuous, y)}}
29
+ {{ select_field("Color", "color", continuous, color)}}
30
+ {{ select_field("Size", "size", continuous, size)}}
31
+ {{ select_field("Shape", "shape", discrete, shape)}}
32
+ {{ select_field("Row", "row", discrete, row)}}
33
+ {{ select_field("Column", "column", discrete, column)}}
34
+
35
+ <button type="submit" class="btn btn-primary">Submit</button>
36
+ </form>
37
+ </div>
38
+ <div class="col-md-8">
39
+ {% if plot %}
40
+ {{ vega_direct("plot", plot) }}
41
+ {% endif %}
42
+ </div>
43
+ </div>
44
+ {% endblock %}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: geo-activity-playground
3
- Version: 0.39.0
3
+ Version: 0.39.1
4
4
  Summary: Analysis of geo data activities like rides, runs or hikes.
5
5
  License: MIT
6
6
  Author: Martin Ueding
@@ -8,13 +8,14 @@ geo_activity_playground/alembic/versions/ab83b9d23127_add_upstream_id.py,sha256=
8
8
  geo_activity_playground/alembic/versions/b03491c593f6_add_crop_indices.py,sha256=1pt7aes0PWJXZ98HxqeDK-ehaU9KLApjCmZYoqCa8V0,975
9
9
  geo_activity_playground/alembic/versions/e02e27876deb_add_square_planner_bookmark_name.py,sha256=Y0OMxp5z_-CQ83rww6GEBFRawXu0J0pLrLArgSjJ7wQ,866
10
10
  geo_activity_playground/alembic/versions/script.py.mako,sha256=3qBrHBf7F7ChKDUIdiNItiSXrDpgQdM7sR0YKzpaC50,689
11
- geo_activity_playground/core/activities.py,sha256=7Z8xiT0juLdo1nQ3fPqWKtSp6MjRkSzd-_FYrzb-Tpg,5360
11
+ geo_activity_playground/core/activities.py,sha256=R3RDvOkHyWL2Wr-Bgqjgr5wDjVqaJ3WSECL2fbMyiu8,5485
12
12
  geo_activity_playground/core/config.py,sha256=eGWWbNfHa6H64AHCnFYTsAJ7-pWi-PhyxL4hjZ4u03U,5256
13
13
  geo_activity_playground/core/coordinates.py,sha256=tDfr9mlXhK6E_MMIJ0vYWVCoH0Lq8uyuaqUgaa8i0jg,966
14
- geo_activity_playground/core/datamodel.py,sha256=cbVNvvHLYHYBg-Gaabm3bewfro8uQ4Sqdq_0mujcos0,8693
14
+ geo_activity_playground/core/datamodel.py,sha256=EeMcwZ2xbqQRwo6R7lOJwbc9iIXnpgg2E4eBdsAbk24,8685
15
15
  geo_activity_playground/core/enrichment.py,sha256=LWAKF6mAKtiZcIF8ptAgpt8fYTYZAnSuXGHuX5TTO6o,7220
16
16
  geo_activity_playground/core/heart_rate.py,sha256=-S3WAhS7AOywrw_Lk5jfuo_fu6zvZQ1VtjwEKSycWpU,1542
17
17
  geo_activity_playground/core/meta_search.py,sha256=naErjAC7ZCFhOF6d492kbegZxCdzbpGcJvjQLJTE4xE,5016
18
+ geo_activity_playground/core/parametric_plot.py,sha256=JdG2HvQHn5mMY1pfcebdgajzpp0CD7KvaHyeaJodDsE,3538
18
19
  geo_activity_playground/core/paths.py,sha256=aUXGuNn9hBvGPQWPoUJeImHN0PB0fS1tja1tm2eq8mA,2595
19
20
  geo_activity_playground/core/privacy_zones.py,sha256=4TumHsVUN1uW6RG3ArqTXDykPVipF98DCxVBe7YNdO8,512
20
21
  geo_activity_playground/core/raster_map.py,sha256=Cq8dNLdxVQg3Agzn2bmXVu0-8kZf56QrSe-LKNn3jaU,7994
@@ -39,7 +40,7 @@ geo_activity_playground/importers/strava_checkout.py,sha256=EixNFXXnxkopqUs0qe6i
39
40
  geo_activity_playground/importers/test_csv_parser.py,sha256=nOTVTdlzIY0TDcbWp7xNyNaIO6Mkeu55hVziVl22QE4,1092
40
41
  geo_activity_playground/importers/test_directory.py,sha256=_fn_-y98ZyElbG0BRxAmGFdtGobUShPU86SdEOpuv-A,691
41
42
  geo_activity_playground/importers/test_strava_api.py,sha256=7b8bl5Rh2BctCmvTPEhCadxtUOq3mfzuadD6F5XxRio,398
42
- geo_activity_playground/webui/app.py,sha256=K-xZsNjorxPhVl9_z-W1MX0_s3gTjZ8XU7P56SFhwDk,6872
43
+ geo_activity_playground/webui/app.py,sha256=h1AULky6kMxxmi54h3aTaE8rtJjOeRoCXIYI4gFNicU,7013
43
44
  geo_activity_playground/webui/authenticator.py,sha256=jtQqvpVHa_eLTAulmvvJgDRoCWOEege49G9zn3MfYk8,1394
44
45
  geo_activity_playground/webui/blueprints/activity_blueprint.py,sha256=ERYcUqvaG-hQqOr6uKEIZzGk1WelNKDHwvecsfu2c3c,24328
45
46
  geo_activity_playground/webui/blueprints/auth_blueprint.py,sha256=_VZeP3VN626BoOOZUkNVnuw9v-cEOrkHz5lhFPmxqMY,784
@@ -50,6 +51,7 @@ geo_activity_playground/webui/blueprints/entry_views.py,sha256=-CRrE5b9QYyrmQhLY
50
51
  geo_activity_playground/webui/blueprints/equipment_blueprint.py,sha256=juQ5L2BlrECb00LBbiY2yc0b8W_B9Y3fPwtbiaRfgpo,5634
51
52
  geo_activity_playground/webui/blueprints/explorer_blueprint.py,sha256=ZNDRwtmYvWGyqDe3fszGp0DR5qzRRxRss32ZGPRuXsY,12469
52
53
  geo_activity_playground/webui/blueprints/heatmap_blueprint.py,sha256=iHI5YJYhX7ZOlzTgzl2efIRDzt3UMYCx7X4-LVd0MWk,8702
54
+ geo_activity_playground/webui/blueprints/plot_builder_blueprint.py,sha256=EWLsNNIAl7eK73WVIi5Tneqjg0QVUZXoM1lScldr4ck,1544
53
55
  geo_activity_playground/webui/blueprints/search_blueprint.py,sha256=Sv_KL1Cdai26y51qVfI-5jZLhtElREsEar1dbR_VAC4,2275
54
56
  geo_activity_playground/webui/blueprints/settings_blueprint.py,sha256=UUv63BDQFnBPq8fLDdlWHd5mxL5qIgcGUuqQRFemyEA,16108
55
57
  geo_activity_playground/webui/blueprints/square_planner_blueprint.py,sha256=xVaxJxmt8Dysl3UL9f2y__LVLtTH2Np1Ust4OSXKRAk,4746
@@ -109,6 +111,7 @@ geo_activity_playground/webui/templates/explorer/index.html.j2,sha256=3t9ikAF6oM
109
111
  geo_activity_playground/webui/templates/heatmap/index.html.j2,sha256=kTVvEt-GmSNebDlVMa6zwyIuP0mJcZQFuqj-IY8JV5U,1359
110
112
  geo_activity_playground/webui/templates/home.html.j2,sha256=vQp9uMn7BLY7pexWJVpQVWN8ZbbtWZvkW_hYSkYQeZs,2212
111
113
  geo_activity_playground/webui/templates/page.html.j2,sha256=TSNEZNLFzJ76G_22dDIXoTozfdWjmKk03qZl6exsdCQ,11043
114
+ geo_activity_playground/webui/templates/plot_builder/index.html.j2,sha256=JQvXHVnPqA6Vlp2HfOt8_LhzvJ_eH5xTxe8-51sMkQk,1493
112
115
  geo_activity_playground/webui/templates/search/index.html.j2,sha256=_kxTgsdbT8o-4ryW0pvyWE7a-rOs7xzGUpdSPp8Q1is,1320
113
116
  geo_activity_playground/webui/templates/search_form.html.j2,sha256=TG9xIql0HnhsXtbHZxl3GLBt6cGYjA8jPeBq11syQ3A,6512
114
117
  geo_activity_playground/webui/templates/settings/admin-password.html.j2,sha256=VYwddpObD1RpeTH5Dm4y7VtmT7kwURDCIjxyzJeq08c,495
@@ -126,8 +129,8 @@ geo_activity_playground/webui/templates/square_planner/index.html.j2,sha256=-OnY
126
129
  geo_activity_playground/webui/templates/summary/index.html.j2,sha256=bM89LdumssVvmuI0EeI8mnzMYxSzNjWY_XWfzn-f6nI,5377
127
130
  geo_activity_playground/webui/templates/upload/index.html.j2,sha256=I1Ix8tDS3YBdi-HdaNfjkzYXVVCjfUTe5PFTnap1ydc,775
128
131
  geo_activity_playground/webui/templates/upload/reload.html.j2,sha256=YZWX5eDeNyqKJdQAywDBcU8DZBm22rRBbZqFjrFrCvQ,556
129
- geo_activity_playground-0.39.0.dist-info/LICENSE,sha256=4RpAwKO8bPkfXH2lnpeUW0eLkNWglyG4lbrLDU_MOwY,1070
130
- geo_activity_playground-0.39.0.dist-info/METADATA,sha256=jughq9g1K5BCZKW7diQ6A8p9Lmp1CJk3vlQhDUcYmc0,1758
131
- geo_activity_playground-0.39.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
132
- geo_activity_playground-0.39.0.dist-info/entry_points.txt,sha256=pbNlLI6IIZIp7nPYCfAtiSiz2oxJSCl7DODD6SPkLKk,81
133
- geo_activity_playground-0.39.0.dist-info/RECORD,,
132
+ geo_activity_playground-0.39.1.dist-info/LICENSE,sha256=4RpAwKO8bPkfXH2lnpeUW0eLkNWglyG4lbrLDU_MOwY,1070
133
+ geo_activity_playground-0.39.1.dist-info/METADATA,sha256=ez-3_BF1sUiuV-TSZ7pO0yIjHw6u0BBxJtVQ8aITGn4,1758
134
+ geo_activity_playground-0.39.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
135
+ geo_activity_playground-0.39.1.dist-info/entry_points.txt,sha256=pbNlLI6IIZIp7nPYCfAtiSiz2oxJSCl7DODD6SPkLKk,81
136
+ geo_activity_playground-0.39.1.dist-info/RECORD,,