-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathapp.py
160 lines (123 loc) · 5.03 KB
/
app.py
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
import os
from datetime import datetime
import pandas as pd
from flask import Flask, render_template, request
from flask_sqlalchemy import SQLAlchemy
from flask_wtf import FlaskForm
from sqlalchemy import Integer, String, Float, DateTime
from sqlalchemy.orm import DeclarativeBase
from sqlalchemy.orm import Mapped, mapped_column
from wtforms import SelectMultipleField, SubmitField
from maps import load_and_build_map, build_map
from plots import create_bokeh_network, create_plotly_distograms, create_plotly_heatmap
class Base(DeclarativeBase):
pass
db = SQLAlchemy(model_class=Base)
class PersonForm(FlaskForm):
prefix = "person"
options = SelectMultipleField("Select person(s)")
peoplesubmit = SubmitField("Update Map")
class Person(db.Model):
person_id: Mapped[int] = mapped_column(Integer, primary_key=True)
person: Mapped[str] = mapped_column(String, unique=True, nullable=False)
cluster: Mapped[int] = mapped_column(Integer, nullable=True)
convex_hull_area: Mapped[float] = mapped_column(Float, nullable=True)
location_density: Mapped[float] = mapped_column(Float, nullable=True)
location_count: Mapped[int] = mapped_column(Integer)
def to_dict(self):
return {field.name: getattr(self, field.name) for field in self.__table__.c}
class Tag(db.Model):
tag_id: Mapped[int] = mapped_column(Integer, primary_key=True)
name: Mapped[str] = mapped_column(String, nullable=False)
placed_by: Mapped[str] = mapped_column(String, nullable=True)
found_by: Mapped[str] = mapped_column(String, nullable=True)
placed_by_id: Mapped[int] = mapped_column(Integer, nullable=True)
found_by_id: Mapped[int] = mapped_column(Integer, nullable=True)
placed_at_datetime: Mapped[datetime] = mapped_column(DateTime, nullable=True)
found_at_datetime: Mapped[datetime] = mapped_column(DateTime, nullable=True)
drive_distance_mi: Mapped[float] = mapped_column(Float, nullable=True)
crow_distance_mi: Mapped[float] = mapped_column(Float, nullable=True)
def to_dict(self):
return {field.name: getattr(self, field.name) for field in self.__table__.c}
SECRET_KEY = os.urandom(32)
app = Flask(__name__)
app.config["SECRET_KEY"] = SECRET_KEY
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite://"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db.init_app(app)
with app.app_context():
db.create_all()
db.session.commit()
m, map_df, person_df, gdf = load_and_build_map("data/biketag.tsv")
for person, row in person_df.iterrows():
p = Person(
person_id=row.person_id,
person=person,
cluster=row.cluster_label,
convex_hull_area=round(row.convex_hull_area, 2),
location_density=round(row.location_density, 4),
location_count=row.location_count,
)
db.session.add(p)
db.session.commit()
for tag, row in gdf.iterrows():
t = Tag(
tag_id=row.tag_id,
name=row["name"],
placed_by=row.placed_by,
found_by=row.found_by,
placed_by_id=row.placed_by_id,
found_by_id=row.found_by_id,
placed_at_datetime=datetime.fromisoformat(row.placed_at_datetime),
found_at_datetime=datetime.fromisoformat(row.found_at_datetime),
drive_distance_mi=row.drive_distance_mi,
crow_distance_mi=row.crow_dist_mi,
)
db.session.add(t)
db.session.commit()
@app.route("/", methods=["GET", "POST"])
def index():
m, map_df, person_df, gdf = load_and_build_map("data/biketag.tsv")
clusters = len(person_df.cluster.unique())
people = Person.query
if request.method == "POST":
if request.form.get("row"):
selected_indices = [int(x) for x in request.form.getlist("row")]
selected_person_df = person_df.loc[
person_df.person_id.isin(selected_indices)
]
selected_map_df = map_df.loc[map_df.person_id.isin(selected_indices)]
m = build_map(selected_map_df, selected_person_df, gdf, clusters)
else:
m = build_map(map_df, person_df, gdf, clusters)
# set the iframe width and height
m.get_root().width = "1000"
m.get_root().height = "600px"
iframe = m.get_root()._repr_html_()
return render_template(
"map_table.html",
title="Bike Tag Map!",
iframe=iframe,
peopletable=people,
)
@app.route("/plots", methods=["GET"])
def show_plots():
tags = Tag.query
tag_df = pd.DataFrame([tag.to_dict() for tag in tags]).set_index("tag_id")
# draw_network
network_script, network_div = create_bokeh_network(person_df, tag_df)
# time to find hist
# distance hist
distograms = create_plotly_distograms(tag_df)
# frequency by month-year
datemap = create_plotly_heatmap(tag_df)
return render_template(
"plots.html",
title="Bike Tag Plots",
script=network_script,
div=network_div,
distograms=distograms,
datemap=datemap,
)
if __name__ == "__main__":
app.run(debug=True)