irie 0.0.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.
Potentially problematic release.
This version of irie might be problematic. Click here for more details.
- irie/__main__.py +24 -0
- irie/apps/__init__.py +5 -0
- irie/apps/authentication/__init__.py +1 -0
- irie/apps/authentication/admin.py +1 -0
- irie/apps/authentication/config.py +6 -0
- irie/apps/authentication/forms.py +41 -0
- irie/apps/authentication/migrations/__init__.py +1 -0
- irie/apps/authentication/models.py +1 -0
- irie/apps/authentication/tests.py +1 -0
- irie/apps/authentication/urls.py +9 -0
- irie/apps/authentication/views.py +53 -0
- irie/apps/config.py +8 -0
- irie/apps/context_processors.py +5 -0
- irie/apps/documents/__init__.py +0 -0
- irie/apps/documents/apps.py +7 -0
- irie/apps/documents/documents.py +61 -0
- irie/apps/documents/migrations/__init__.py +0 -0
- irie/apps/documents/tests.py +3 -0
- irie/apps/documents/urls.py +12 -0
- irie/apps/documents/views.py +27 -0
- irie/apps/evaluation/__init__.py +0 -0
- irie/apps/evaluation/admin.py +43 -0
- irie/apps/evaluation/apps.py +18 -0
- irie/apps/evaluation/daemon.py +107 -0
- irie/apps/evaluation/identification.py +196 -0
- irie/apps/evaluation/migrations/0001_initial.py +25 -0
- irie/apps/evaluation/migrations/0002_remove_evaluation_cesmd.py +17 -0
- irie/apps/evaluation/migrations/0003_evaluation_asset.py +20 -0
- irie/apps/evaluation/migrations/__init__.py +0 -0
- irie/apps/evaluation/models.py +72 -0
- irie/apps/evaluation/urls.py +16 -0
- irie/apps/evaluation/views.py +68 -0
- irie/apps/events/__init__.py +0 -0
- irie/apps/events/admin.py +9 -0
- irie/apps/events/apps.py +12 -0
- irie/apps/events/migrations/0001_initial.py +27 -0
- irie/apps/events/migrations/0002_alter_event_id.py +18 -0
- irie/apps/events/migrations/0003_event_cesmd.py +19 -0
- irie/apps/events/migrations/0004_event_record_identifier.py +19 -0
- irie/apps/events/migrations/0005_event_asset.py +21 -0
- irie/apps/events/migrations/0006_alter_event_event_file.py +18 -0
- irie/apps/events/migrations/__init__.py +0 -0
- irie/apps/events/models.py +70 -0
- irie/apps/events/tests.py +1 -0
- irie/apps/events/tests_events.py +240 -0
- irie/apps/events/urls.py +29 -0
- irie/apps/events/views.py +55 -0
- irie/apps/events/views_events.py +215 -0
- irie/apps/inventory/CESMD.py +81 -0
- irie/apps/inventory/__init__.py +5 -0
- irie/apps/inventory/admin.py +10 -0
- irie/apps/inventory/apps.py +12 -0
- irie/apps/inventory/archive/arcGIS.py +1175 -0
- irie/apps/inventory/calid.py +65 -0
- irie/apps/inventory/fields.py +5 -0
- irie/apps/inventory/forms.py +12 -0
- irie/apps/inventory/migrations/0001_initial.py +31 -0
- irie/apps/inventory/migrations/0002_assetevaluationmodel_cesmd.py +19 -0
- irie/apps/inventory/migrations/0003_auto_20230520_2030.py +23 -0
- irie/apps/inventory/migrations/0004_asset.py +27 -0
- irie/apps/inventory/migrations/0005_auto_20230731_1802.py +23 -0
- irie/apps/inventory/migrations/0006_auto_20230731_1816.py +28 -0
- irie/apps/inventory/migrations/0007_auto_20230731_1827.py +24 -0
- irie/apps/inventory/migrations/0008_asset_is_complete.py +19 -0
- irie/apps/inventory/migrations/0009_auto_20230731_1842.py +29 -0
- irie/apps/inventory/migrations/0010_auto_20230801_0025.py +23 -0
- irie/apps/inventory/migrations/0011_alter_asset_cgs_data.py +18 -0
- irie/apps/inventory/migrations/0012_corridor.py +22 -0
- irie/apps/inventory/migrations/0013_alter_asset_cesmd.py +18 -0
- irie/apps/inventory/migrations/0014_alter_asset_cesmd.py +18 -0
- irie/apps/inventory/migrations/__init__.py +0 -0
- irie/apps/inventory/models.py +70 -0
- irie/apps/inventory/tables.py +584 -0
- irie/apps/inventory/traffic.py +175052 -0
- irie/apps/inventory/urls.py +25 -0
- irie/apps/inventory/views.py +515 -0
- irie/apps/management/__init__.py +0 -0
- irie/apps/management/commands/__init__.py +0 -0
- irie/apps/networks/__init__.py +0 -0
- irie/apps/networks/apps.py +5 -0
- irie/apps/networks/forms.py +64 -0
- irie/apps/networks/migrations/0001_initial.py +26 -0
- irie/apps/networks/migrations/__init__.py +0 -0
- irie/apps/networks/models.py +14 -0
- irie/apps/networks/networks.py +782 -0
- irie/apps/networks/tests.py +1 -0
- irie/apps/networks/urls.py +18 -0
- irie/apps/networks/views.py +89 -0
- irie/apps/prediction/__init__.py +0 -0
- irie/apps/prediction/admin.py +9 -0
- irie/apps/prediction/apps.py +12 -0
- irie/apps/prediction/forms.py +20 -0
- irie/apps/prediction/metrics.py +61 -0
- irie/apps/prediction/migrations/0001_initial.py +32 -0
- irie/apps/prediction/migrations/0002_auto_20230731_1801.py +27 -0
- irie/apps/prediction/migrations/0003_rename_assetevaluationmodel_evaluation.py +18 -0
- irie/apps/prediction/migrations/0004_delete_evaluation.py +16 -0
- irie/apps/prediction/migrations/0005_predictormodel_protocol.py +18 -0
- irie/apps/prediction/migrations/0006_alter_predictormodel_protocol.py +18 -0
- irie/apps/prediction/migrations/0007_predictormodel_active.py +19 -0
- irie/apps/prediction/migrations/0008_predictormodel_description.py +18 -0
- irie/apps/prediction/migrations/0009_predictormodel_entry_point.py +19 -0
- irie/apps/prediction/migrations/0010_alter_predictormodel_entry_point.py +18 -0
- irie/apps/prediction/migrations/0011_remove_predictormodel_entry_point.py +17 -0
- irie/apps/prediction/migrations/0012_predictormodel_entry_point.py +18 -0
- irie/apps/prediction/migrations/0013_predictormodel_metrics.py +18 -0
- irie/apps/prediction/migrations/0014_auto_20240930_0004.py +28 -0
- irie/apps/prediction/migrations/0015_alter_predictormodel_render_file.py +18 -0
- irie/apps/prediction/migrations/__init__.py +0 -0
- irie/apps/prediction/models.py +37 -0
- irie/apps/prediction/predictor.py +286 -0
- irie/apps/prediction/runners/__init__.py +450 -0
- irie/apps/prediction/runners/metrics.py +168 -0
- irie/apps/prediction/runners/opensees/__init__.py +0 -0
- irie/apps/prediction/runners/opensees/schemas/__init__.py +39 -0
- irie/apps/prediction/runners/utilities.py +277 -0
- irie/apps/prediction/runners/xmlutils.py +232 -0
- irie/apps/prediction/runners/zipped.py +27 -0
- irie/apps/prediction/templatetags/__init__.py +0 -0
- irie/apps/prediction/templatetags/predictor.py +20 -0
- irie/apps/prediction/urls.py +19 -0
- irie/apps/prediction/views.py +184 -0
- irie/apps/prediction/views_api.py +216 -0
- irie/apps/site/__init__.py +0 -0
- irie/apps/site/admin.py +1 -0
- irie/apps/site/config.py +6 -0
- irie/apps/site/migrations/__init__.py +1 -0
- irie/apps/site/models.py +2 -0
- irie/apps/site/templatetags/__init__.py +0 -0
- irie/apps/site/templatetags/indexing.py +7 -0
- irie/apps/site/tests.py +1 -0
- irie/apps/site/urls.py +8 -0
- irie/apps/site/view_sdof.py +40 -0
- irie/apps/site/view_utils.py +13 -0
- irie/apps/site/views.py +88 -0
- irie/core/__init__.py +5 -0
- irie/core/asgi.py +12 -0
- irie/core/settings.py +223 -0
- irie/core/urls.py +39 -0
- irie/core/wsgi.py +12 -0
- irie-0.0.0.dist-info/METADATA +48 -0
- irie-0.0.0.dist-info/RECORD +145 -0
- irie-0.0.0.dist-info/WHEEL +5 -0
- irie-0.0.0.dist-info/entry_points.txt +2 -0
- irie-0.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#===----------------------------------------------------------------------===#
|
|
2
|
+
#
|
|
3
|
+
# STAIRLab -- STructural Artificial Intelligence Laboratory
|
|
4
|
+
#
|
|
5
|
+
#===----------------------------------------------------------------------===#
|
|
6
|
+
#
|
|
7
|
+
# Summer 2023, BRACE2 Team
|
|
8
|
+
# Berkeley, CA
|
|
9
|
+
#
|
|
10
|
+
#----------------------------------------------------------------------------#
|
|
11
|
+
from django.urls import path, re_path
|
|
12
|
+
from apps.inventory import views
|
|
13
|
+
|
|
14
|
+
urlpatterns = [
|
|
15
|
+
path("dashboard/", views.dashboard, name="dashboard"),
|
|
16
|
+
path("dashboard.html", views.dashboard),
|
|
17
|
+
path("dashboard/demo", views.dashboard),
|
|
18
|
+
|
|
19
|
+
path("asset-table.html", views.asset_table),
|
|
20
|
+
path("asset-table/", views.asset_table, name="asset_table"),
|
|
21
|
+
re_path(
|
|
22
|
+
r"^evaluations/(?P<event>[0-9 A-Z-]*)/(?P<cesmd>[0-9 A-Z-]*)/.*", views.asset_event_summary, name="asset_event_summary"
|
|
23
|
+
),
|
|
24
|
+
re_path(r"^inventory/(?P<calid>[0-9 A-Z-]*)/", views.asset_profile, name="asset_profile"),
|
|
25
|
+
]
|
|
@@ -0,0 +1,515 @@
|
|
|
1
|
+
#===----------------------------------------------------------------------===#
|
|
2
|
+
#
|
|
3
|
+
# STAIRLab -- STructural Artificial Intelligence Laboratory
|
|
4
|
+
#
|
|
5
|
+
#===----------------------------------------------------------------------===#
|
|
6
|
+
#
|
|
7
|
+
# Summer 2023, BRACE2 Team
|
|
8
|
+
# Berkeley, CA
|
|
9
|
+
#
|
|
10
|
+
#----------------------------------------------------------------------------#
|
|
11
|
+
import os
|
|
12
|
+
import re
|
|
13
|
+
from django.core.paginator import Paginator
|
|
14
|
+
from django.template import loader, TemplateDoesNotExist
|
|
15
|
+
from django.http import HttpResponse
|
|
16
|
+
from django.contrib.auth.decorators import login_required
|
|
17
|
+
from django.core.exceptions import ObjectDoesNotExist
|
|
18
|
+
|
|
19
|
+
from apps.events.models import Event
|
|
20
|
+
from apps.site.view_utils import raise404
|
|
21
|
+
from apps.inventory.models import Asset
|
|
22
|
+
from apps.inventory.forms import AssetForm
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@login_required(login_url="/login/")
|
|
26
|
+
def fetch_rendering(request):
|
|
27
|
+
asset_id = request.GET.get('asset')
|
|
28
|
+
asset = Asset.objects.get(id=asset_id)
|
|
29
|
+
|
|
30
|
+
if asset.cesmd == "CE58658":
|
|
31
|
+
template = loader.get_template(f"bridges/InteractiveTwin-{asset.cesmd}.html")
|
|
32
|
+
return HttpResponse(template.render({}, request))
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
from apps.prediction.models import PredictorModel
|
|
36
|
+
for p in PredictorModel.objects.filter(asset=asset):
|
|
37
|
+
if p.protocol == "BRACE2_CLI_PREDICTOR_T4":
|
|
38
|
+
return HttpResponse("html")
|
|
39
|
+
|
|
40
|
+
return HttpResponse("No rendering available for this asset.")
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _make_freq_plot(evaluation):
|
|
45
|
+
import numpy as np
|
|
46
|
+
from mdof.macro import FrequencyContent
|
|
47
|
+
|
|
48
|
+
plot = FrequencyContent(scale=True, period=True, xlabel="Period (s)", ylabel="Normalized Amplitude")
|
|
49
|
+
|
|
50
|
+
for name, mdata in evaluation["summary"].items():
|
|
51
|
+
periods = []
|
|
52
|
+
amplitudes = []
|
|
53
|
+
for i in mdata.get("data", []):
|
|
54
|
+
if "period" in i:
|
|
55
|
+
periods.append(i["period"])
|
|
56
|
+
if "amplitude" in i:
|
|
57
|
+
amplitudes.append(i["amplitude"])
|
|
58
|
+
|
|
59
|
+
if len(amplitudes) and (len(amplitudes) == len(periods)):
|
|
60
|
+
plot.add(np.array(periods), np.array(amplitudes), label=name)
|
|
61
|
+
else:
|
|
62
|
+
plot.add(np.array(periods), label=name)
|
|
63
|
+
|
|
64
|
+
fig = plot.get_figure()
|
|
65
|
+
return fig.to_json()
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
@login_required(login_url="/login/")
|
|
69
|
+
def asset_event_summary(request, cesmd, event):
|
|
70
|
+
from apps.evaluation.models import Evaluation
|
|
71
|
+
|
|
72
|
+
context = {}
|
|
73
|
+
context["segment"] = "events"
|
|
74
|
+
html_template = loader.get_template("inventory/asset-event-summary.html")
|
|
75
|
+
|
|
76
|
+
try:
|
|
77
|
+
|
|
78
|
+
segments = request.path.split("/")
|
|
79
|
+
_, _, is_nce = segments[-3:]
|
|
80
|
+
|
|
81
|
+
try:
|
|
82
|
+
evaluation = Evaluation.objects.filter(event_id=int(event))[0]
|
|
83
|
+
evaluation_data = evaluation.evaluation_data
|
|
84
|
+
|
|
85
|
+
except Exception as e:
|
|
86
|
+
# TODO: Handle case where evaluation cant be found
|
|
87
|
+
evaluation_data = {}
|
|
88
|
+
evaluation = None
|
|
89
|
+
|
|
90
|
+
for metric in evaluation_data.values():
|
|
91
|
+
metric["completion"] = (
|
|
92
|
+
100 * len(metric["summary"])/len(metric["predictors"])
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
if "SPECTRAL_SHIFT_IDENTIFICATION" in evaluation_data:
|
|
96
|
+
context["freq_plot_json"] = \
|
|
97
|
+
_make_freq_plot(evaluation_data["SPECTRAL_SHIFT_IDENTIFICATION"])
|
|
98
|
+
|
|
99
|
+
context["all_evaluations"] = evaluation_data
|
|
100
|
+
|
|
101
|
+
context["evaluation_details"] = {
|
|
102
|
+
metric.replace("_", " ").title(): {
|
|
103
|
+
key: [list(map(lambda i: f"{i:.3}" if isinstance(i,float) else str(i), row)) for row in table]
|
|
104
|
+
for key, table in predictors["details"].items()
|
|
105
|
+
}
|
|
106
|
+
for metric, predictors in sorted(evaluation_data.items(), key=lambda i: i[0])
|
|
107
|
+
}
|
|
108
|
+
context["asset"] = evaluation and evaluation.event.asset or None
|
|
109
|
+
context["nce_version"] = is_nce
|
|
110
|
+
context["event_data"] = Event.objects.get(pk=int(event)).motion_data
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
resp = html_template.render(context, request)
|
|
114
|
+
|
|
115
|
+
return HttpResponse(resp)
|
|
116
|
+
|
|
117
|
+
except Exception as e:
|
|
118
|
+
if "DEBUG" in os.environ and os.environ["DEBUG"]:
|
|
119
|
+
raise e
|
|
120
|
+
html_template = loader.get_template("site/page-500.html")
|
|
121
|
+
return HttpResponse(html_template.render(context, request))
|
|
122
|
+
|
|
123
|
+
@login_required(login_url="/login/")
|
|
124
|
+
def dashboard(request):
|
|
125
|
+
from apps.inventory.models import Asset
|
|
126
|
+
from apps.evaluation.models import Evaluation
|
|
127
|
+
|
|
128
|
+
context = {}
|
|
129
|
+
context["segment"] = "dashboard"
|
|
130
|
+
try:
|
|
131
|
+
if "demo" in request.path:
|
|
132
|
+
context["demo_version"] = True
|
|
133
|
+
|
|
134
|
+
context["recent_evaluations"] = [
|
|
135
|
+
(evaluation, Event.objects.get(pk=evaluation.event_id))
|
|
136
|
+
for evaluation in reversed(list(Evaluation.objects.all())[-6:])
|
|
137
|
+
]
|
|
138
|
+
assets = [
|
|
139
|
+
Asset.objects.get(cesmd=event[1].cesmd) for event in context["recent_evaluations"]
|
|
140
|
+
]
|
|
141
|
+
context["asset_map"] = AssetMap(assets,
|
|
142
|
+
layer_assets=False,
|
|
143
|
+
traffic=False).get_html()
|
|
144
|
+
context["calid"] = {b.cesmd: b.calid for b in assets}
|
|
145
|
+
|
|
146
|
+
html_template = loader.get_template("inventory/dashboard.html")
|
|
147
|
+
return HttpResponse(html_template.render(context, request))
|
|
148
|
+
|
|
149
|
+
except Exception as e:
|
|
150
|
+
if "DEBUG" in os.environ and os.environ["DEBUG"]:
|
|
151
|
+
raise e
|
|
152
|
+
html_template = loader.get_template("site/page-500.html")
|
|
153
|
+
return HttpResponse(html_template.render(context, request))
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def _ssid_stats(events, key):
|
|
158
|
+
"""
|
|
159
|
+
mode_results is a list (station level) of lists (event level) of dictionaries (mode level).
|
|
160
|
+
mode_results = [
|
|
161
|
+
[
|
|
162
|
+
{
|
|
163
|
+
"period": ...,
|
|
164
|
+
"frequency": ...,
|
|
165
|
+
"damping": ...,
|
|
166
|
+
"emac": ...,
|
|
167
|
+
"mpc": ...,
|
|
168
|
+
},
|
|
169
|
+
...
|
|
170
|
+
],
|
|
171
|
+
...
|
|
172
|
+
]
|
|
173
|
+
|
|
174
|
+
[
|
|
175
|
+
# "Event"
|
|
176
|
+
{"S1": {"period": [0.1]},
|
|
177
|
+
"R1": {"period": [1.2]}}
|
|
178
|
+
]
|
|
179
|
+
"""
|
|
180
|
+
mode_results = [_find_ssid(event.id) for event in events]
|
|
181
|
+
import numpy as np
|
|
182
|
+
|
|
183
|
+
filtered_results = [
|
|
184
|
+
{
|
|
185
|
+
method: [
|
|
186
|
+
result for result in event_results[method]
|
|
187
|
+
if key in result and result.get("emac", 1.0) > 0.5 and result.get("mpc", 1.0) > 0.5
|
|
188
|
+
] for method in event_results
|
|
189
|
+
} for event_results in mode_results
|
|
190
|
+
]
|
|
191
|
+
|
|
192
|
+
from collections import defaultdict
|
|
193
|
+
values = defaultdict(list)
|
|
194
|
+
for event in filtered_results:
|
|
195
|
+
for method in event:
|
|
196
|
+
for result in event[method]:
|
|
197
|
+
values[method].append(result[key])
|
|
198
|
+
|
|
199
|
+
mean = {method: np.mean(values[method]) for method in values}
|
|
200
|
+
std = {method: np.std(values[method]) for method in values}
|
|
201
|
+
|
|
202
|
+
def _first(method_results):
|
|
203
|
+
if method_results and len(method_results) > 0:
|
|
204
|
+
results = np.array([result[key] for result in method_results])
|
|
205
|
+
try:
|
|
206
|
+
idx = np.argmax([result["amplitude"] for result in method_results])
|
|
207
|
+
return results[idx]
|
|
208
|
+
except KeyError:
|
|
209
|
+
return np.max(results)
|
|
210
|
+
else:
|
|
211
|
+
return {}
|
|
212
|
+
|
|
213
|
+
return [
|
|
214
|
+
{method: {
|
|
215
|
+
# "distance": (closest_item[key]-mean)/std),
|
|
216
|
+
"nearest_mean": event_results[method][np.argmin(np.abs(mean[method] \
|
|
217
|
+
- [result[key] for result in event_results[method]]))] \
|
|
218
|
+
if event_results[method] and len(event_results[method]) > 0 else {} ,
|
|
219
|
+
"maximum": _first(event_results[method])
|
|
220
|
+
}
|
|
221
|
+
for method in event_results
|
|
222
|
+
}
|
|
223
|
+
for event_results in filtered_results
|
|
224
|
+
]
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
def _find_ssid(event_id=None, evaluation=None):
|
|
228
|
+
"""
|
|
229
|
+
Given an event ID, finds the results of the first configured
|
|
230
|
+
system ID run. This generally looks like a list of dicts,
|
|
231
|
+
each with fields "frequency", "damping", etc.
|
|
232
|
+
"""
|
|
233
|
+
from apps.evaluation.models import Evaluation
|
|
234
|
+
|
|
235
|
+
if evaluation is None:
|
|
236
|
+
evaluation = Evaluation.objects.filter(event_id=int(event_id))
|
|
237
|
+
|
|
238
|
+
elif not isinstance(evaluation, list):
|
|
239
|
+
evaluation = [evaluation]
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
if len(evaluation) != 1:
|
|
243
|
+
return []
|
|
244
|
+
|
|
245
|
+
else:
|
|
246
|
+
evaluation_data = evaluation[0].evaluation_data
|
|
247
|
+
|
|
248
|
+
if "SPECTRAL_SHIFT_IDENTIFICATION" in evaluation_data:
|
|
249
|
+
return {
|
|
250
|
+
key: val.get("data", val.get("error", []))
|
|
251
|
+
for key,val in evaluation_data["SPECTRAL_SHIFT_IDENTIFICATION"]["summary"].items()
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
else:
|
|
255
|
+
return []
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
@login_required(login_url="/login/")
|
|
259
|
+
def asset_profile(request, calid):
|
|
260
|
+
|
|
261
|
+
context = {}
|
|
262
|
+
html_template = loader.get_template("inventory/asset-profile.html")
|
|
263
|
+
context["segment"] = "assets"
|
|
264
|
+
|
|
265
|
+
context["nce_version"] = True
|
|
266
|
+
|
|
267
|
+
try:
|
|
268
|
+
asset = Asset.objects.get(calid=calid)
|
|
269
|
+
|
|
270
|
+
except ObjectDoesNotExist:
|
|
271
|
+
return raise404(request, context)
|
|
272
|
+
|
|
273
|
+
context["asset"] = asset
|
|
274
|
+
|
|
275
|
+
context["tables"] = _make_tables(asset)
|
|
276
|
+
|
|
277
|
+
if asset.cesmd:
|
|
278
|
+
cesmd = asset.cesmd
|
|
279
|
+
|
|
280
|
+
events = list(reversed(sorted(Event.objects.filter(cesmd=cesmd),
|
|
281
|
+
key=lambda x: x.motion_data["event_date"])))
|
|
282
|
+
|
|
283
|
+
evals = [
|
|
284
|
+
{"event": event,
|
|
285
|
+
"pga": event.pga, #abs(event.motion_data["peak_accel"])/980.,
|
|
286
|
+
"evaluation": ssid,
|
|
287
|
+
}
|
|
288
|
+
for i, (event, ssid) in enumerate(zip(events, _ssid_stats(events, "period")))
|
|
289
|
+
]
|
|
290
|
+
context["evaluations"] = Paginator(evals, 5).get_page(1)
|
|
291
|
+
|
|
292
|
+
try:
|
|
293
|
+
return HttpResponse(html_template.render(context, request))
|
|
294
|
+
|
|
295
|
+
# except TemplateDoesNotExist:
|
|
296
|
+
# context["rendering"] = None
|
|
297
|
+
# return HttpResponse(html_template.render(context, request))
|
|
298
|
+
|
|
299
|
+
except Exception as e:
|
|
300
|
+
if "DEBUG" in os.environ and os.environ["DEBUG"]:
|
|
301
|
+
raise e
|
|
302
|
+
html_template = loader.get_template("site/page-500.html")
|
|
303
|
+
return HttpResponse(html_template.render(context, request))
|
|
304
|
+
|
|
305
|
+
def _make_tables(asset):
|
|
306
|
+
if asset.cesmd:
|
|
307
|
+
tables = [
|
|
308
|
+
{k: v for k,v in group.items()
|
|
309
|
+
if k not in {
|
|
310
|
+
"Remarks",
|
|
311
|
+
"Instrumentation",
|
|
312
|
+
"Remarks/Notes",
|
|
313
|
+
"Construction Date"
|
|
314
|
+
}
|
|
315
|
+
} for group in asset.cgs_data[1:]
|
|
316
|
+
]
|
|
317
|
+
else:
|
|
318
|
+
tables = []
|
|
319
|
+
|
|
320
|
+
# Filter out un-interesting information
|
|
321
|
+
nbi_data = [
|
|
322
|
+
{k: v for k,v in group.items()
|
|
323
|
+
if k not in {
|
|
324
|
+
"Owner Agency",
|
|
325
|
+
"Year Reconstructed",
|
|
326
|
+
"Bridge Posting Code",
|
|
327
|
+
"Latitude",
|
|
328
|
+
"Longitude",
|
|
329
|
+
"NBIS Minimum Bridge Length",
|
|
330
|
+
"Record Type",
|
|
331
|
+
"State Name",
|
|
332
|
+
"U.S. Congressional District",
|
|
333
|
+
"Inventory Route NHS Code"
|
|
334
|
+
}
|
|
335
|
+
} for group in asset.nbi_data.values()
|
|
336
|
+
]
|
|
337
|
+
tables.extend(nbi_data)
|
|
338
|
+
tables = [tables[2], *tables[:2], *tables[3:]]
|
|
339
|
+
condition = {}
|
|
340
|
+
for table in tables:
|
|
341
|
+
keys = set()
|
|
342
|
+
for k in table:
|
|
343
|
+
key = k.lower()
|
|
344
|
+
if "condition" in key \
|
|
345
|
+
or "rating" in key \
|
|
346
|
+
or (re.search("^ *[0-9] - [A-Z]", table[k]) is not None and "code" not in key):
|
|
347
|
+
condition[k] = table[k]
|
|
348
|
+
keys.add(k)
|
|
349
|
+
|
|
350
|
+
for k in keys:
|
|
351
|
+
del table[k]
|
|
352
|
+
|
|
353
|
+
tables.insert(3,condition)
|
|
354
|
+
|
|
355
|
+
# for some tables, all values are empty. Filter these out
|
|
356
|
+
tables = [
|
|
357
|
+
table for table in tables if sum(map(lambda i: len(i),table.values()))
|
|
358
|
+
]
|
|
359
|
+
return tables
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
@login_required(login_url="/login/")
|
|
364
|
+
def asset_table(request):
|
|
365
|
+
"""
|
|
366
|
+
Returns a table of all assets in the database, paginated
|
|
367
|
+
"""
|
|
368
|
+
|
|
369
|
+
context = {}
|
|
370
|
+
context["segment"] = "assets"
|
|
371
|
+
html_template = loader.get_template("inventory/asset-table.html")
|
|
372
|
+
|
|
373
|
+
page = request.GET.get("page", 1)
|
|
374
|
+
try:
|
|
375
|
+
page = int(page)
|
|
376
|
+
except:
|
|
377
|
+
page = 1
|
|
378
|
+
|
|
379
|
+
assets = Asset.objects.all() #exclude(cesmd__isnull=True),
|
|
380
|
+
context["bridges"] = Paginator(assets, 10).get_page(page)
|
|
381
|
+
context["asset_map"] = AssetMap(assets=assets,
|
|
382
|
+
cesmd=True,
|
|
383
|
+
layer_assets=True).get_html()
|
|
384
|
+
|
|
385
|
+
try:
|
|
386
|
+
return HttpResponse(html_template.render(context, request))
|
|
387
|
+
|
|
388
|
+
except Exception as e:
|
|
389
|
+
if "DEBUG" in os.environ and os.environ["DEBUG"]:
|
|
390
|
+
raise e
|
|
391
|
+
html_template = loader.get_template("site/page-500.html")
|
|
392
|
+
return HttpResponse(html_template.render(context, request))
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
|
|
396
|
+
import folium
|
|
397
|
+
from folium import branca
|
|
398
|
+
|
|
399
|
+
class AssetMap:
|
|
400
|
+
def __init__(self,
|
|
401
|
+
assets,
|
|
402
|
+
layer_assets=True,
|
|
403
|
+
traffic=False,
|
|
404
|
+
cesmd=True):
|
|
405
|
+
self._layer_assets = layer_assets
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
self._assets = assets
|
|
409
|
+
|
|
410
|
+
self._figure = figure = folium.Figure()
|
|
411
|
+
self._map = m = folium.Map(
|
|
412
|
+
location=[37.7735, -122.0993], zoom_start=6, tiles=None
|
|
413
|
+
)
|
|
414
|
+
|
|
415
|
+
folium.raster_layers.TileLayer(
|
|
416
|
+
tiles='cartodbpositron',
|
|
417
|
+
name='Instrumented Bridges'
|
|
418
|
+
).add_to(m)
|
|
419
|
+
m.add_to(figure)
|
|
420
|
+
|
|
421
|
+
if cesmd:
|
|
422
|
+
self.add_CESMD()
|
|
423
|
+
|
|
424
|
+
if traffic:
|
|
425
|
+
self.add_traffic()
|
|
426
|
+
|
|
427
|
+
if self._layer_assets:
|
|
428
|
+
|
|
429
|
+
self._asset_layers = {
|
|
430
|
+
"partial": folium.FeatureGroup(name="Partial Digital Twins"),
|
|
431
|
+
"complete": folium.FeatureGroup(name="Full Digital Twins")
|
|
432
|
+
}
|
|
433
|
+
list(map(lambda i: i.add_to(self._map), self._asset_layers.values()))
|
|
434
|
+
self.add_twins(list(self._asset_layers.values()))
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
def get_html(self, **kwargs):
|
|
438
|
+
folium.LayerControl(collapsed=False).add_to(self._map)
|
|
439
|
+
self._figure.render()
|
|
440
|
+
return self._map._repr_html_()
|
|
441
|
+
|
|
442
|
+
def add_twins(self, features):
|
|
443
|
+
|
|
444
|
+
for b in self._assets:
|
|
445
|
+
lat, lon = b.coordinates
|
|
446
|
+
popup = folium.Popup(
|
|
447
|
+
folium.Html(
|
|
448
|
+
'<a style="display: inline;" target="_blank" href="/inventory/{calid}/">{label}</a>'.format(
|
|
449
|
+
calid=b.calid,
|
|
450
|
+
label=b.calid
|
|
451
|
+
),
|
|
452
|
+
script=True
|
|
453
|
+
),
|
|
454
|
+
min_width= 50,
|
|
455
|
+
max_width=100
|
|
456
|
+
)
|
|
457
|
+
if b.is_complete:
|
|
458
|
+
folium.Marker(
|
|
459
|
+
location=[lat, lon],
|
|
460
|
+
popup=popup,
|
|
461
|
+
icon=folium.Icon(icon="cloud", color="blue" if not b.is_complete else "beige"),
|
|
462
|
+
z_index_offset=1000
|
|
463
|
+
).add_to(features[int(b.is_complete)])
|
|
464
|
+
else:
|
|
465
|
+
folium.CircleMarker(
|
|
466
|
+
location=[lat, lon],
|
|
467
|
+
popup=popup,
|
|
468
|
+
color="blue",
|
|
469
|
+
fill=True,
|
|
470
|
+
opacity=1,
|
|
471
|
+
fill_opacity=1,
|
|
472
|
+
radius=3,
|
|
473
|
+
z_index_offset=800
|
|
474
|
+
).add_to(features[int(b.is_complete)])
|
|
475
|
+
return self
|
|
476
|
+
|
|
477
|
+
def add_CESMD(self):
|
|
478
|
+
cesmdbridges = folium.FeatureGroup(name="Registered Bridges")
|
|
479
|
+
cesmdbridges.add_to(self._map)
|
|
480
|
+
|
|
481
|
+
for b in self._assets:
|
|
482
|
+
if not b.cesmd:
|
|
483
|
+
continue
|
|
484
|
+
lat, lon = b.coordinates
|
|
485
|
+
|
|
486
|
+
folium.Marker(
|
|
487
|
+
location=[lat, lon],
|
|
488
|
+
popup=b.cesmd,
|
|
489
|
+
icon=folium.Icon(icon="glyphicon-road", color="lightgray"),
|
|
490
|
+
).add_to(cesmdbridges)
|
|
491
|
+
|
|
492
|
+
|
|
493
|
+
def add_traffic(self):
|
|
494
|
+
# from apps.inventory.traffic import TRAFFIC_LOW, TRAFFIC_MID, TRAFFIC_HIGH, TRAFFIC_ALL
|
|
495
|
+
from apps.inventory.traffic import TRAFFIC_ALL
|
|
496
|
+
traffic = folium.FeatureGroup(name="Traffic")
|
|
497
|
+
traffic.add_to(self._map)
|
|
498
|
+
|
|
499
|
+
cm = branca.colormap.LinearColormap(colors=['green', 'yellow', 'orange', 'red'], vmin=10000, vmax=100000)
|
|
500
|
+
for loc in TRAFFIC_ALL:
|
|
501
|
+
folium.CircleMarker([loc["coords"][1],loc["coords"][0]],
|
|
502
|
+
radius=5,
|
|
503
|
+
popup=None,
|
|
504
|
+
color=cm.rgb_hex_str(loc["properties"]["AHEAD_AADT"]),
|
|
505
|
+
fill=True,
|
|
506
|
+
opacity=0.5,
|
|
507
|
+
weight=0,
|
|
508
|
+
).add_to(traffic)
|
|
509
|
+
|
|
510
|
+
cm = branca.colormap.LinearColormap(colors=['green', 'yellow', 'orange', 'red'],
|
|
511
|
+
vmin=10000, vmax=100000,
|
|
512
|
+
caption='Average Annual Daily Traffic Crossings')
|
|
513
|
+
cm.add_to(self._map)
|
|
514
|
+
|
|
515
|
+
return self
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
#===----------------------------------------------------------------------===#
|
|
2
|
+
#
|
|
3
|
+
# STAIRLab -- STructural Artificial Intelligence Laboratory
|
|
4
|
+
#
|
|
5
|
+
#===----------------------------------------------------------------------===#
|
|
6
|
+
from django import forms
|
|
7
|
+
from .models import UserNetworkPreferences
|
|
8
|
+
from crispy_forms.helper import FormHelper
|
|
9
|
+
from crispy_forms.layout import Submit
|
|
10
|
+
|
|
11
|
+
class UserPreferencesForm(forms.ModelForm):
|
|
12
|
+
class Meta:
|
|
13
|
+
model = UserNetworkPreferences
|
|
14
|
+
fields = ['latitude', 'longitude']
|
|
15
|
+
|
|
16
|
+
class WeightInput(forms.NumberInput):
|
|
17
|
+
# template_name = 'styled_inputs.html'
|
|
18
|
+
|
|
19
|
+
def __init__(self, label, attrs=None):
|
|
20
|
+
default_attrs = {
|
|
21
|
+
'label': label,
|
|
22
|
+
'class': 'form-row form-inline',
|
|
23
|
+
'style': 'width: 100px; flex: 1; color: black;'
|
|
24
|
+
}
|
|
25
|
+
if attrs:
|
|
26
|
+
default_attrs.update(attrs)
|
|
27
|
+
super().__init__(attrs=default_attrs)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class CorridorsForm(forms.Form):
|
|
31
|
+
method = forms.TypedChoiceField(
|
|
32
|
+
label='Method',
|
|
33
|
+
choices=[(0, 'A'), (1, 'B'), (2, 'B-alt')],
|
|
34
|
+
coerce=int,
|
|
35
|
+
initial=0
|
|
36
|
+
)
|
|
37
|
+
hos_weight = forms.IntegerField(label="Hospital", initial=1, widget=WeightInput("Hospital"))
|
|
38
|
+
fire_weight = forms.IntegerField(label="Fire station", initial=0, widget=WeightInput("Fire station"))
|
|
39
|
+
police_weight = forms.IntegerField(label="Police station", initial=0, widget=WeightInput("Police station"))
|
|
40
|
+
maintenance_weight = forms.IntegerField(label="Maintenance", initial=0, widget=WeightInput("Maintenance"))
|
|
41
|
+
airport_weight = forms.IntegerField(label="Airport", initial=0, widget=WeightInput("Airport"))
|
|
42
|
+
seaport_weight = forms.IntegerField(label="Seaport", initial=0, widget=WeightInput("Seaport"))
|
|
43
|
+
ferry_weight = forms.IntegerField(label="Ferry terminal", initial=0, widget=WeightInput("Ferry terminal"))
|
|
44
|
+
consider_population = forms.TypedChoiceField(
|
|
45
|
+
label='Consider population',
|
|
46
|
+
choices=[(0, 'No'), (1, 'Yes')],
|
|
47
|
+
coerce=int,
|
|
48
|
+
initial=0
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
corridor_input = forms.IntegerField(widget=forms.HiddenInput(),
|
|
52
|
+
required=False,
|
|
53
|
+
min_value=1,max_value=162)
|
|
54
|
+
|
|
55
|
+
def __init__(self, *args, **kwargs):
|
|
56
|
+
super(CorridorsForm, self).__init__(*args, **kwargs)
|
|
57
|
+
self.helper = FormHelper()
|
|
58
|
+
self.helper.form_class = 'form-inline' # makes the form inline
|
|
59
|
+
self.helper.label_class = 'form-row sr-only' # hides labels if desired
|
|
60
|
+
self.helper.field_class = 'form-row mr-2' # margin for spacing between fields
|
|
61
|
+
self.helper.form_method = 'get'
|
|
62
|
+
# self.helper.form_style = # 'inline'
|
|
63
|
+
self.helper.add_input(Submit('update', 'Rank', css_class='btn btn-primary'))
|
|
64
|
+
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Generated by Django 5.1 on 2024-11-03 00:27
|
|
2
|
+
|
|
3
|
+
import django.db.models.deletion
|
|
4
|
+
from django.conf import settings
|
|
5
|
+
from django.db import migrations, models
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Migration(migrations.Migration):
|
|
9
|
+
|
|
10
|
+
initial = True
|
|
11
|
+
|
|
12
|
+
dependencies = [
|
|
13
|
+
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
operations = [
|
|
17
|
+
migrations.CreateModel(
|
|
18
|
+
name='UserNetworkPreferences',
|
|
19
|
+
fields=[
|
|
20
|
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
21
|
+
('latitude', models.FloatField(default=37.806)),
|
|
22
|
+
('longitude', models.FloatField(default=-122.365)),
|
|
23
|
+
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
|
24
|
+
],
|
|
25
|
+
),
|
|
26
|
+
]
|
|
File without changes
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#===----------------------------------------------------------------------===#
|
|
2
|
+
#
|
|
3
|
+
# STAIRLab -- STructural Artificial Intelligence Laboratory
|
|
4
|
+
#
|
|
5
|
+
#===----------------------------------------------------------------------===#
|
|
6
|
+
from django.db import models
|
|
7
|
+
from django.contrib.auth.models import User
|
|
8
|
+
|
|
9
|
+
class UserNetworkPreferences(models.Model):
|
|
10
|
+
user = models.OneToOneField(User, on_delete=models.CASCADE)
|
|
11
|
+
latitude = models.FloatField(default=37.806)
|
|
12
|
+
longitude = models.FloatField(default=-122.365)
|
|
13
|
+
|
|
14
|
+
|