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.
- geo_activity_playground/core/activities.py +3 -0
- geo_activity_playground/core/datamodel.py +1 -1
- geo_activity_playground/core/parametric_plot.py +101 -0
- geo_activity_playground/webui/app.py +2 -0
- geo_activity_playground/webui/blueprints/plot_builder_blueprint.py +43 -0
- geo_activity_playground/webui/templates/plot_builder/index.html.j2 +44 -0
- {geo_activity_playground-0.39.0.dist-info → geo_activity_playground-0.39.1.dist-info}/METADATA +1 -1
- {geo_activity_playground-0.39.0.dist-info → geo_activity_playground-0.39.1.dist-info}/RECORD +11 -8
- {geo_activity_playground-0.39.0.dist-info → geo_activity_playground-0.39.1.dist-info}/LICENSE +0 -0
- {geo_activity_playground-0.39.0.dist-info → geo_activity_playground-0.39.1.dist-info}/WHEEL +0 -0
- {geo_activity_playground-0.39.0.dist-info → geo_activity_playground-0.39.1.dist-info}/entry_points.txt +0 -0
@@ -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
|
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 %}
|
{geo_activity_playground-0.39.0.dist-info → geo_activity_playground-0.39.1.dist-info}/RECORD
RENAMED
@@ -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=
|
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=
|
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=
|
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.
|
130
|
-
geo_activity_playground-0.39.
|
131
|
-
geo_activity_playground-0.39.
|
132
|
-
geo_activity_playground-0.39.
|
133
|
-
geo_activity_playground-0.39.
|
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,,
|
{geo_activity_playground-0.39.0.dist-info → geo_activity_playground-0.39.1.dist-info}/LICENSE
RENAMED
File without changes
|
File without changes
|
File without changes
|