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.

Files changed (145) hide show
  1. irie/__main__.py +24 -0
  2. irie/apps/__init__.py +5 -0
  3. irie/apps/authentication/__init__.py +1 -0
  4. irie/apps/authentication/admin.py +1 -0
  5. irie/apps/authentication/config.py +6 -0
  6. irie/apps/authentication/forms.py +41 -0
  7. irie/apps/authentication/migrations/__init__.py +1 -0
  8. irie/apps/authentication/models.py +1 -0
  9. irie/apps/authentication/tests.py +1 -0
  10. irie/apps/authentication/urls.py +9 -0
  11. irie/apps/authentication/views.py +53 -0
  12. irie/apps/config.py +8 -0
  13. irie/apps/context_processors.py +5 -0
  14. irie/apps/documents/__init__.py +0 -0
  15. irie/apps/documents/apps.py +7 -0
  16. irie/apps/documents/documents.py +61 -0
  17. irie/apps/documents/migrations/__init__.py +0 -0
  18. irie/apps/documents/tests.py +3 -0
  19. irie/apps/documents/urls.py +12 -0
  20. irie/apps/documents/views.py +27 -0
  21. irie/apps/evaluation/__init__.py +0 -0
  22. irie/apps/evaluation/admin.py +43 -0
  23. irie/apps/evaluation/apps.py +18 -0
  24. irie/apps/evaluation/daemon.py +107 -0
  25. irie/apps/evaluation/identification.py +196 -0
  26. irie/apps/evaluation/migrations/0001_initial.py +25 -0
  27. irie/apps/evaluation/migrations/0002_remove_evaluation_cesmd.py +17 -0
  28. irie/apps/evaluation/migrations/0003_evaluation_asset.py +20 -0
  29. irie/apps/evaluation/migrations/__init__.py +0 -0
  30. irie/apps/evaluation/models.py +72 -0
  31. irie/apps/evaluation/urls.py +16 -0
  32. irie/apps/evaluation/views.py +68 -0
  33. irie/apps/events/__init__.py +0 -0
  34. irie/apps/events/admin.py +9 -0
  35. irie/apps/events/apps.py +12 -0
  36. irie/apps/events/migrations/0001_initial.py +27 -0
  37. irie/apps/events/migrations/0002_alter_event_id.py +18 -0
  38. irie/apps/events/migrations/0003_event_cesmd.py +19 -0
  39. irie/apps/events/migrations/0004_event_record_identifier.py +19 -0
  40. irie/apps/events/migrations/0005_event_asset.py +21 -0
  41. irie/apps/events/migrations/0006_alter_event_event_file.py +18 -0
  42. irie/apps/events/migrations/__init__.py +0 -0
  43. irie/apps/events/models.py +70 -0
  44. irie/apps/events/tests.py +1 -0
  45. irie/apps/events/tests_events.py +240 -0
  46. irie/apps/events/urls.py +29 -0
  47. irie/apps/events/views.py +55 -0
  48. irie/apps/events/views_events.py +215 -0
  49. irie/apps/inventory/CESMD.py +81 -0
  50. irie/apps/inventory/__init__.py +5 -0
  51. irie/apps/inventory/admin.py +10 -0
  52. irie/apps/inventory/apps.py +12 -0
  53. irie/apps/inventory/archive/arcGIS.py +1175 -0
  54. irie/apps/inventory/calid.py +65 -0
  55. irie/apps/inventory/fields.py +5 -0
  56. irie/apps/inventory/forms.py +12 -0
  57. irie/apps/inventory/migrations/0001_initial.py +31 -0
  58. irie/apps/inventory/migrations/0002_assetevaluationmodel_cesmd.py +19 -0
  59. irie/apps/inventory/migrations/0003_auto_20230520_2030.py +23 -0
  60. irie/apps/inventory/migrations/0004_asset.py +27 -0
  61. irie/apps/inventory/migrations/0005_auto_20230731_1802.py +23 -0
  62. irie/apps/inventory/migrations/0006_auto_20230731_1816.py +28 -0
  63. irie/apps/inventory/migrations/0007_auto_20230731_1827.py +24 -0
  64. irie/apps/inventory/migrations/0008_asset_is_complete.py +19 -0
  65. irie/apps/inventory/migrations/0009_auto_20230731_1842.py +29 -0
  66. irie/apps/inventory/migrations/0010_auto_20230801_0025.py +23 -0
  67. irie/apps/inventory/migrations/0011_alter_asset_cgs_data.py +18 -0
  68. irie/apps/inventory/migrations/0012_corridor.py +22 -0
  69. irie/apps/inventory/migrations/0013_alter_asset_cesmd.py +18 -0
  70. irie/apps/inventory/migrations/0014_alter_asset_cesmd.py +18 -0
  71. irie/apps/inventory/migrations/__init__.py +0 -0
  72. irie/apps/inventory/models.py +70 -0
  73. irie/apps/inventory/tables.py +584 -0
  74. irie/apps/inventory/traffic.py +175052 -0
  75. irie/apps/inventory/urls.py +25 -0
  76. irie/apps/inventory/views.py +515 -0
  77. irie/apps/management/__init__.py +0 -0
  78. irie/apps/management/commands/__init__.py +0 -0
  79. irie/apps/networks/__init__.py +0 -0
  80. irie/apps/networks/apps.py +5 -0
  81. irie/apps/networks/forms.py +64 -0
  82. irie/apps/networks/migrations/0001_initial.py +26 -0
  83. irie/apps/networks/migrations/__init__.py +0 -0
  84. irie/apps/networks/models.py +14 -0
  85. irie/apps/networks/networks.py +782 -0
  86. irie/apps/networks/tests.py +1 -0
  87. irie/apps/networks/urls.py +18 -0
  88. irie/apps/networks/views.py +89 -0
  89. irie/apps/prediction/__init__.py +0 -0
  90. irie/apps/prediction/admin.py +9 -0
  91. irie/apps/prediction/apps.py +12 -0
  92. irie/apps/prediction/forms.py +20 -0
  93. irie/apps/prediction/metrics.py +61 -0
  94. irie/apps/prediction/migrations/0001_initial.py +32 -0
  95. irie/apps/prediction/migrations/0002_auto_20230731_1801.py +27 -0
  96. irie/apps/prediction/migrations/0003_rename_assetevaluationmodel_evaluation.py +18 -0
  97. irie/apps/prediction/migrations/0004_delete_evaluation.py +16 -0
  98. irie/apps/prediction/migrations/0005_predictormodel_protocol.py +18 -0
  99. irie/apps/prediction/migrations/0006_alter_predictormodel_protocol.py +18 -0
  100. irie/apps/prediction/migrations/0007_predictormodel_active.py +19 -0
  101. irie/apps/prediction/migrations/0008_predictormodel_description.py +18 -0
  102. irie/apps/prediction/migrations/0009_predictormodel_entry_point.py +19 -0
  103. irie/apps/prediction/migrations/0010_alter_predictormodel_entry_point.py +18 -0
  104. irie/apps/prediction/migrations/0011_remove_predictormodel_entry_point.py +17 -0
  105. irie/apps/prediction/migrations/0012_predictormodel_entry_point.py +18 -0
  106. irie/apps/prediction/migrations/0013_predictormodel_metrics.py +18 -0
  107. irie/apps/prediction/migrations/0014_auto_20240930_0004.py +28 -0
  108. irie/apps/prediction/migrations/0015_alter_predictormodel_render_file.py +18 -0
  109. irie/apps/prediction/migrations/__init__.py +0 -0
  110. irie/apps/prediction/models.py +37 -0
  111. irie/apps/prediction/predictor.py +286 -0
  112. irie/apps/prediction/runners/__init__.py +450 -0
  113. irie/apps/prediction/runners/metrics.py +168 -0
  114. irie/apps/prediction/runners/opensees/__init__.py +0 -0
  115. irie/apps/prediction/runners/opensees/schemas/__init__.py +39 -0
  116. irie/apps/prediction/runners/utilities.py +277 -0
  117. irie/apps/prediction/runners/xmlutils.py +232 -0
  118. irie/apps/prediction/runners/zipped.py +27 -0
  119. irie/apps/prediction/templatetags/__init__.py +0 -0
  120. irie/apps/prediction/templatetags/predictor.py +20 -0
  121. irie/apps/prediction/urls.py +19 -0
  122. irie/apps/prediction/views.py +184 -0
  123. irie/apps/prediction/views_api.py +216 -0
  124. irie/apps/site/__init__.py +0 -0
  125. irie/apps/site/admin.py +1 -0
  126. irie/apps/site/config.py +6 -0
  127. irie/apps/site/migrations/__init__.py +1 -0
  128. irie/apps/site/models.py +2 -0
  129. irie/apps/site/templatetags/__init__.py +0 -0
  130. irie/apps/site/templatetags/indexing.py +7 -0
  131. irie/apps/site/tests.py +1 -0
  132. irie/apps/site/urls.py +8 -0
  133. irie/apps/site/view_sdof.py +40 -0
  134. irie/apps/site/view_utils.py +13 -0
  135. irie/apps/site/views.py +88 -0
  136. irie/core/__init__.py +5 -0
  137. irie/core/asgi.py +12 -0
  138. irie/core/settings.py +223 -0
  139. irie/core/urls.py +39 -0
  140. irie/core/wsgi.py +12 -0
  141. irie-0.0.0.dist-info/METADATA +48 -0
  142. irie-0.0.0.dist-info/RECORD +145 -0
  143. irie-0.0.0.dist-info/WHEEL +5 -0
  144. irie-0.0.0.dist-info/entry_points.txt +2 -0
  145. irie-0.0.0.dist-info/top_level.txt +1 -0
irie/__main__.py ADDED
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env python
2
+ #===----------------------------------------------------------------------===#
3
+ #
4
+ # STAIRLab -- STructural Artificial Intelligence Laboratory
5
+ #
6
+ #===----------------------------------------------------------------------===#
7
+
8
+ import os
9
+ import sys
10
+
11
+ def main():
12
+ os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'core.settings')
13
+ try:
14
+ from django.core.management import execute_from_command_line
15
+ except ImportError as exc:
16
+ raise ImportError(
17
+ "Couldn't import Django. Are you sure it's installed and "
18
+ "available on your PYTHONPATH environment variable? Did you "
19
+ "forget to activate a virtual environment?"
20
+ ) from exc
21
+ execute_from_command_line(sys.argv)
22
+
23
+ if __name__ == '__main__':
24
+ main()
irie/apps/__init__.py ADDED
@@ -0,0 +1,5 @@
1
+ #===----------------------------------------------------------------------===#
2
+ #
3
+ # STAIRLab -- STructural Artificial Intelligence Laboratory
4
+ #
5
+ #===----------------------------------------------------------------------===#
@@ -0,0 +1 @@
1
+
@@ -0,0 +1 @@
1
+ from django.contrib import admin
@@ -0,0 +1,6 @@
1
+ from django.apps import AppConfig
2
+
3
+
4
+ class AuthConfig(AppConfig):
5
+ name = "apps.auth"
6
+ label = "apps_auth"
@@ -0,0 +1,41 @@
1
+ from django import forms
2
+ from django.contrib.auth.forms import UserCreationForm
3
+ from django.contrib.auth.models import User
4
+
5
+
6
+ class LoginForm(forms.Form):
7
+ username = forms.CharField(
8
+ widget=forms.TextInput(
9
+ attrs={"placeholder": "Username", "class": "form-control"}
10
+ )
11
+ )
12
+ password = forms.CharField(
13
+ widget=forms.PasswordInput(
14
+ attrs={"placeholder": "Password", "class": "form-control"}
15
+ )
16
+ )
17
+
18
+
19
+ class SignUpForm(UserCreationForm):
20
+ username = forms.CharField(
21
+ widget=forms.TextInput(
22
+ attrs={"placeholder": "Username", "class": "form-control"}
23
+ )
24
+ )
25
+ email = forms.EmailField(
26
+ widget=forms.EmailInput(attrs={"placeholder": "Email", "class": "form-control"})
27
+ )
28
+ password1 = forms.CharField(
29
+ widget=forms.PasswordInput(
30
+ attrs={"placeholder": "Password", "class": "form-control"}
31
+ )
32
+ )
33
+ password2 = forms.CharField(
34
+ widget=forms.PasswordInput(
35
+ attrs={"placeholder": "Password check", "class": "form-control"}
36
+ )
37
+ )
38
+
39
+ class Meta:
40
+ model = User
41
+ fields = ("username", "email", "password1", "password2")
@@ -0,0 +1 @@
1
+ from django.db import models
@@ -0,0 +1 @@
1
+ from django.test import TestCase
@@ -0,0 +1,9 @@
1
+ from django.urls import path
2
+ from .views import login_view, register_user
3
+ from django.contrib.auth.views import LogoutView
4
+
5
+ urlpatterns = [
6
+ path("login/", login_view, name="login"),
7
+ path("register/", register_user, name="register"),
8
+ path("logout/", LogoutView.as_view(), name="logout"),
9
+ ]
@@ -0,0 +1,53 @@
1
+ from django.shortcuts import render, redirect
2
+ from django.contrib.auth import authenticate, login
3
+ from .forms import LoginForm, SignUpForm
4
+
5
+
6
+ def login_view(request):
7
+ form = LoginForm(request.POST or None)
8
+
9
+ msg = None
10
+
11
+ if request.method == "POST":
12
+ if form.is_valid():
13
+ username = form.cleaned_data.get("username")
14
+ password = form.cleaned_data.get("password")
15
+ user = authenticate(username=username, password=password)
16
+ if user is not None:
17
+ login(request, user)
18
+ return redirect("/")
19
+ else:
20
+ msg = "Invalid credentials"
21
+ else:
22
+ msg = "Error validating the form"
23
+
24
+ return render(request, "accounts/login.html", {"form": form, "msg": msg})
25
+
26
+
27
+ def register_user(request):
28
+ msg = None
29
+ success = False
30
+
31
+ if request.method == "POST":
32
+ form = SignUpForm(request.POST)
33
+ if form.is_valid():
34
+ form.save()
35
+ username = form.cleaned_data.get("username")
36
+ raw_password = form.cleaned_data.get("password1")
37
+ user = authenticate(username=username, password=raw_password)
38
+
39
+ msg = "User created successfully."
40
+ success = True
41
+
42
+ # return redirect("/login/")
43
+
44
+ else:
45
+ msg = "Form is not valid"
46
+ else:
47
+ form = SignUpForm()
48
+
49
+ return render(
50
+ request,
51
+ "accounts/register.html",
52
+ {"form": form, "msg": msg, "success": success},
53
+ )
irie/apps/config.py ADDED
@@ -0,0 +1,8 @@
1
+ from django.apps import AppConfig
2
+
3
+
4
+ class AppsConfig(AppConfig):
5
+ default_auto_field = "django.db.models.BigAutoField"
6
+ name = "apps"
7
+ label = "apps"
8
+
@@ -0,0 +1,5 @@
1
+ from django.conf import settings
2
+
3
+
4
+ def cfg_assets_root(request):
5
+ return {"ASSETS_ROOT": settings.ASSETS_ROOT}
File without changes
@@ -0,0 +1,7 @@
1
+ from django.apps import AppConfig
2
+
3
+
4
+ class DocumentsConfig(AppConfig):
5
+ default_auto_field = "django.db.models.BigAutoField"
6
+ name = 'apps.documents'
7
+ label = 'documents'
@@ -0,0 +1,61 @@
1
+ TECHNOLOGY, MODELING, RESEARCH = range(3)
2
+
3
+ DOCUMENTS = [
4
+ # {
5
+ # "path": "2023-05-30 2nd Annual Report/BRACE2_2023_Annual_Report_Revised_After_Caltrans_Review.pdf",
6
+ # "title": "2nd Annual Report",
7
+ # "date": "2023-09-07",
8
+ # "scope": [TECHNOLOGY, MODELING, RESEARCH],
9
+ # "draft": False,
10
+ # "flags": ["new"]
11
+ # },
12
+ # {
13
+ # "path": "2023-05-30 2nd Annual Report/BRACE2_2023_Annual_Report.pdf",
14
+ # "title": "2nd Annual Report",
15
+ # "date": "2023-05-30",
16
+ # "scope": [TECHNOLOGY, MODELING, RESEARCH],
17
+ # "draft": True
18
+ # },
19
+ # {
20
+ # "path": "2021-10-27 ANNUAL Progress Report/BRACE2-Annual-Report-10-27-2021.pdf",
21
+ # "title": "1st Annual Report",
22
+ # "scope": [TECHNOLOGY, MODELING, RESEARCH],
23
+ # "date": "2021-10-27"
24
+ # },
25
+ # {
26
+ # "path": "2022-01-18 Progress Report 4/Update_BRACE2_1_18_2022.pdf",
27
+ # "title": "Progress Report 4",
28
+ # "scope": [MODELING, RESEARCH],
29
+ # "date": "2022-01-18"
30
+ # },
31
+ # {
32
+ # "path": "2022-04-21 Progress Report 5/BRACE2_Progress_Report_V_Part_I-4-21-2022.pdf",
33
+ # "title": "Progress Report 5",
34
+ # "scope": [MODELING, RESEARCH],
35
+ # "date": "2022-04-21"
36
+ # },
37
+ # {
38
+ # "path": "2022-06-01 NCE/BRACE2_Project_Extension_Workplan-6-1-2022.pdf",
39
+ # "title": "NCE/Project Extension Workplan",
40
+ # "scope": [MODELING, RESEARCH],
41
+ # "date": "2022-06-01"
42
+ # },
43
+ # {
44
+ # "path": "2022-08-11 Progress Report 6/BRACE2_Progress_Report_VI.pdf",
45
+ # "title": "Progress Report 6",
46
+ # "scope": [MODELING, RESEARCH],
47
+ # "date": "2022-08-11"
48
+ # },
49
+ # {
50
+ # "path": "2022-12-06 Memo Platform Guide/BRACE2_Memo_Platform_Guide_Final.pdf",
51
+ # "title": "Memo - Platform Guide",
52
+ # "scope": [MODELING],
53
+ # "date": "2022-12-06"
54
+ # },
55
+ # {
56
+ # "path": "2023-01-30 Platform Comment Responses/BRACE2_Memo_Platform_Comments_2-Jan-30-2023.pdf",
57
+ # "title": "Memo - Platform Comment Responses",
58
+ # "date": "2023-01-30"
59
+ # }
60
+ ]
61
+
File without changes
@@ -0,0 +1,3 @@
1
+ from django.test import TestCase
2
+
3
+ # Create your tests here.
@@ -0,0 +1,12 @@
1
+ from django.urls import path
2
+ from django.conf.urls.static import static
3
+ from core import settings
4
+ from django.contrib.staticfiles.urls import staticfiles_urlpatterns
5
+
6
+ from . import views
7
+
8
+ urlpatterns = [
9
+ path("documents/", views.document_list, name="documents"),
10
+ path("documents.html", views.document_list),
11
+ ] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
12
+
@@ -0,0 +1,27 @@
1
+ from django.shortcuts import render
2
+
3
+ from django import template
4
+ from django.contrib.auth.decorators import login_required
5
+ from django.http import HttpResponse, HttpResponseRedirect
6
+ from django.template import loader
7
+
8
+ from .documents import DOCUMENTS
9
+
10
+ @login_required(login_url="/login/")
11
+ def document_list(request):
12
+
13
+ context = {}
14
+ load_template = "documents.html"
15
+ context["documents"] = sorted(DOCUMENTS, key=lambda i: i["date"], reverse=True)
16
+ context["segment"] = load_template
17
+
18
+ try:
19
+ html_template = loader.get_template("documents/" + load_template)
20
+ return HttpResponse(html_template.render(context, request))
21
+
22
+ except Exception as e:
23
+ if "DEBUG" in os.environ and os.environ["DEBUG"]:
24
+ raise e
25
+ html_template = loader.get_template("home/page-500.html")
26
+ return HttpResponse(html_template.render(context, request))
27
+
File without changes
@@ -0,0 +1,43 @@
1
+ #===----------------------------------------------------------------------===#
2
+ #
3
+ # STAIRLab -- STructural Artificial Intelligence Laboratory
4
+ #
5
+ #===----------------------------------------------------------------------===#
6
+ #
7
+ # Summer 2023, BRACE2 Team
8
+ # Berkeley, CA
9
+ #
10
+ #----------------------------------------------------------------------------#
11
+ import json
12
+ import logging
13
+
14
+ from django.db.models import JSONField
15
+ from django.contrib import admin
16
+ from django.forms import widgets
17
+
18
+ from .models import Evaluation
19
+
20
+ logger = logging.getLogger(__name__)
21
+
22
+
23
+ class PrettyJSONWidget(widgets.Textarea):
24
+
25
+ def format_value(self, value):
26
+ try:
27
+ value = json.dumps(json.loads(value), indent=2, sort_keys=True)
28
+ # these lines will try to adjust size of TextArea to fit to content
29
+ row_lengths = [len(r) for r in value.split('\n')]
30
+ self.attrs['rows'] = min(max(len(row_lengths) + 2, 10), 30)
31
+ self.attrs['cols'] = min(max(max(row_lengths) + 2, 40), 120)
32
+ return value
33
+ except Exception as e:
34
+ logger.warning("Error while formatting JSON: {}".format(e))
35
+ return super(PrettyJSONWidget, self).format_value(value)
36
+
37
+
38
+ class JsonAdmin(admin.ModelAdmin):
39
+ formfield_overrides = {
40
+ JSONField: {'widget': PrettyJSONWidget}
41
+ }
42
+
43
+ admin.site.register(Evaluation, JsonAdmin)
@@ -0,0 +1,18 @@
1
+ #===----------------------------------------------------------------------===#
2
+ #
3
+ # STAIRLab -- STructural Artificial Intelligence Laboratory
4
+ #
5
+ #===----------------------------------------------------------------------===#
6
+ #
7
+ # Summer 2023, BRACE2 Team
8
+ # Berkeley, CA
9
+ #
10
+ #----------------------------------------------------------------------------#
11
+ from django.apps import AppConfig
12
+
13
+
14
+ class PredictionConfig(AppConfig):
15
+ default_auto_field = 'django.db.models.BigAutoField'
16
+ name = 'apps.evaluation'
17
+ label = 'apps_evaluation'
18
+
@@ -0,0 +1,107 @@
1
+ #===----------------------------------------------------------------------===#
2
+ #
3
+ # STAIRLab -- STructural Artificial Intelligence Laboratory
4
+ #
5
+ #===----------------------------------------------------------------------===#
6
+ #
7
+ # Summer 2023, BRACE2 Team
8
+ # Berkeley, CA
9
+ #
10
+ #----------------------------------------------------------------------------#
11
+ import sys
12
+ import multiprocessing.dummy
13
+ from collections import defaultdict
14
+ from typing import List, Iterator, Tuple, Dict, Collection
15
+
16
+ from apps.prediction.predictor import RunID
17
+ from apps.prediction.metrics import HealthMetric, METRIC_CLASSES
18
+
19
+ class LiveEvaluation:
20
+ # TODO: Merge into models.Evaluation?
21
+ def __init__(self, event, predictors, evaluation):
22
+ self.predictors = predictors
23
+
24
+ self.metrics: Dict[str, Dict[str, HealthMetric]] = defaultdict(dict)
25
+ self.active_metrics: List[str] = list(METRIC_CLASSES.keys())
26
+
27
+ self._evaluation = evaluation
28
+
29
+ self.evaluation_data = defaultdict(lambda: {
30
+ "predictors": [],
31
+ "summary": {},
32
+ "details": {}
33
+ })
34
+
35
+ def update(self):
36
+ self._evaluation.evaluation_data = dict(self.evaluation_data)
37
+ self.save(["evaluation_data"])
38
+
39
+ def save(self, fields=None):
40
+ if fields is None:
41
+ self._evaluation.save()
42
+ else:
43
+ self._evaluation.save(update_fields=fields)
44
+
45
+ def runPredictor(self, args: Tuple[str, Tuple[RunID, List[HealthMetric]]]):
46
+ predictor_name, (run_id, metrics) = args
47
+ self.predictors[predictor_name].runPrediction(run_id)
48
+ return predictor_name, run_id
49
+
50
+ # met_tag, predictor_name
51
+ def addMetric(self, mname: str, pid: str, confidence_score:int=0)->HealthMetric:
52
+ """
53
+ mname: metric id
54
+ pid: predictor id
55
+ """
56
+ #self.metrics[metric.metric_tag][metric.predictor] = metric
57
+ self.evaluation_data[mname]["predictors"].append(pid)
58
+ self.update()
59
+ return mname
60
+
61
+ def setMetricData(self, mname: str, pid: str, data: dict):
62
+ # self.metrics[mname][pid].data = data
63
+ # try:
64
+ # self.evaluation_data[mname]["details"][pid] = data["details"]
65
+ # except KeyError:
66
+ # self.evaluation_data[mname]["details"][pid] = data
67
+ # self.metrics[mname][pid].buildDetails()
68
+ # try:
69
+ # None
70
+ # except KeyError:
71
+ # self.evaluation_data[mname]["summary"][pid] = \
72
+ # self.metrics[mname][pid].getSummary()
73
+
74
+ self.evaluation_data[mname]["details"][pid] = data.get("details", data)
75
+ self.evaluation_data[mname]["summary"][pid] = data.get("summary", data)
76
+ if len(self.evaluation_data[mname]["summary"]) == 1:
77
+ self.evaluation_data[mname]["summary"][pid]["is_primary"] = True
78
+
79
+ self.update()
80
+
81
+ def assignMetricPredictors(self, event)->Dict[str, Tuple[RunID,List[HealthMetric]]]:
82
+ queued_predictions : Dict[str, Tuple[RunID,List[HealthMetric]]] = {}
83
+
84
+ for mname in self.active_metrics:
85
+ for predictor, score in self.scorePredictors(mname, self.predictors.values(), event):
86
+ print(predictor, score)
87
+
88
+
89
+ if predictor.name not in queued_predictions and predictor.active:
90
+ rid = predictor.newPrediction(event)
91
+ queued_predictions[predictor.name] = (rid, [])
92
+
93
+ predictor.activateMetric(mname, queued_predictions[predictor.name][0])
94
+ queued_predictions[predictor.name][1].append(
95
+ #self.addMetric(METRIC_CLASSES[metric](predictor.name), score)
96
+ self.addMetric(mname, predictor.name, score)
97
+ )
98
+
99
+ return queued_predictions
100
+
101
+
102
+ def scorePredictors(self, metric, predictors: Collection["Predictor"], event)->Iterator[Tuple["Predictor", int]]:
103
+ for predictor in predictors:
104
+ if predictor.active and metric in predictor.getMetricList():
105
+ print(">>> ", predictor.name, metric, file=sys.stderr)
106
+ yield (predictor, 0)
107
+
@@ -0,0 +1,196 @@
1
+ #===----------------------------------------------------------------------===#
2
+ #
3
+ # STAIRLab -- STructural Artificial Intelligence Laboratory
4
+ #
5
+ #===----------------------------------------------------------------------===#
6
+ #
7
+ # Summer 2023, BRACE2 Team
8
+ # Berkeley, CA
9
+ #
10
+ #----------------------------------------------------------------------------#
11
+ """
12
+ 0. dd = {event_id: {idx01: mode01, idx02: mode02}} // with mode0? = {node: [*ndf]}
13
+ // or mode0? = [*ndf] ?
14
+ // mode = {"period", "idx", "shape"}
15
+ 1. aa = {event_id: mode}
16
+ 2. for event in aa:
17
+ bb[event] = 0.0
18
+ for other_event in aa:
19
+ if other_event != event :
20
+ if assoc(dd[event], dd[other_event])[event] == event:
21
+ bb[event] += 1/(len(aa)-1)
22
+
23
+ """
24
+ import os
25
+ import json
26
+ from collections import defaultdict
27
+
28
+ import numpy as np
29
+ from apps.events.models import Event
30
+ from apps.site.view_utils import raise404
31
+ from apps.inventory.models import Asset
32
+
33
+ def mkdd(asset, pid, key):
34
+ evaluations = list(reversed(sorted(Evaluation.objects.filter(asset=asset),
35
+ key=lambda x: x.event.motion_data["event_date"])))
36
+ return {
37
+ i_eval: {
38
+ idx: mode for idx,mode in \
39
+ enumerate(evaluation.evaluation_data["SPECTRAL_SHIFT_IDENTIFICATION"]["summary"][pid])
40
+ if key in mode and mode.get("emac", 1.0) > 0.5 and mode.get("mpc", 1.0) > 0.5
41
+
42
+ } for i_eval,evaluation in enumerate(evaluations)
43
+ }
44
+
45
+ def _ssid_stats(asset, pid, key):
46
+ filtered_modes = mkdd(asset, pid, key)
47
+ values = [mode[key] for mode in event.values() for event in filtered_modes.values()]
48
+
49
+ mean = np.mean(values)
50
+ std = np.std(values)
51
+
52
+ result = {}
53
+ for i_eval, event_results in filtered_modes.items():
54
+ idx = np.argmin(np.abs(mean - np.array([mode[key] for mode in event_results])))
55
+ result[i_eval] = event_results[idx]
56
+ result[i_eval]["idx"] = idx
57
+ return result
58
+
59
+ # return {
60
+ # i_eval: event_results[np.argmin(np.abs(mean - np.array([mode[key] for mode in event_results])))]
61
+ # if event_results and len(event_results) > 0 else {}
62
+ # for i_eval, event_results in filtered_modes.items()
63
+ # }
64
+
65
+
66
+ def ff(asset, pid, key):
67
+ # evaluation_data
68
+ dd = mkdd(asset, pid, key)
69
+
70
+ aa = _ssid_stats(asset, pid, key)
71
+
72
+ for event in aa:
73
+ aa[event]["bb"] = 0.0
74
+ for other_event in aa:
75
+ if other_event != event :
76
+ if assoc(dd[event], dd[other_event])[event] == event:
77
+ aa[event]["bb"] += 1/(len(aa)-1)
78
+
79
+ HELP = """
80
+ modeID [options] <baseline> <unknown>
81
+
82
+ OeventPTIONS:
83
+ -c<compare-mode> compare mode, currently only 'max' supported
84
+
85
+ EXAMPLES:
86
+
87
+ Default compare:
88
+ modeID baseline.yaml unknown.yaml
89
+
90
+ To use `max` compare mode:
91
+ modeID -cmax baseline.yaml unknown.yaml
92
+ or
93
+ modeID -c max baseline.yaml unknown.yaml
94
+
95
+ """
96
+
97
+ import yaml
98
+ import numpy as np
99
+ import sys
100
+
101
+ TOL = 1e-14
102
+
103
+ def _clean_modes(modes, tol=1e-14):
104
+ "Zero-out small values"
105
+ mode_array = np.array([
106
+ [val for node in mode.values() for val in node]
107
+ for mode in modes.values()
108
+ ])
109
+ mode_array[abs(mode_array) < tol] = 0.0
110
+ return mode_array
111
+
112
+
113
+ def associate_modes(baseline, unidentified_dict, compare = None, verbose=True):
114
+ identified_keys = set()
115
+ identified = {}
116
+ _old_labels = list(unidentified_dict.keys())
117
+
118
+ if compare is None:
119
+ _compare = lambda errors, labels: np.argmin(errors)
120
+
121
+ elif compare == "max":
122
+ _compare = lambda errors, labels: np.argmax(errors[~np.isin(np.arange(len(errors)), labels)])
123
+
124
+ unidentified = _clean_modes(unidentified_dict, tol=TOL)
125
+
126
+ for key, mode in baseline.items():
127
+ #
128
+ baseline_data = np.array([*mode.values()]).flatten()
129
+ baseline_data[abs(baseline_data) < TOL] = 0.0
130
+ scale_index = np.argmax(np.absolute(baseline_data))
131
+ baseline_scale = baseline_data[scale_index]
132
+
133
+ errors = np.sum(abs(baseline_data - unidentified*baseline_scale/unidentified[:,scale_index][:,None]), axis=1)
134
+
135
+ # Get index of mode from <unidentified> that is closest to `mode`
136
+ index = _compare(errors, identified_keys)
137
+ old_label = _old_labels[index]
138
+
139
+ if verbose:
140
+ print(f"{old_label} -> {key}", file=sys.stderr)
141
+
142
+ if old_label in identified_keys and verbose:
143
+ print(f"WARNING: duplicate identification of key {old_label}", file=sys.stderr)
144
+
145
+ identified_keys.add(_old_labels[index])
146
+ identified[key] = unidentified[index]
147
+
148
+ return identified
149
+
150
+
151
+ if __name__ == "__main__":
152
+ # Parse command line
153
+ index = 1
154
+ compare_mode = None
155
+ if "-c" in sys.argv[1]:
156
+ index += 1
157
+ if len(sys.argv[1]) > 2:
158
+ compare_mode = sys.argv[1][2:]
159
+ else:
160
+ compare_mode = sys.argv[index]
161
+ index += 1
162
+
163
+ baseline_file, unidentified_file = sys.argv[index:]
164
+
165
+
166
+ # Open Files
167
+ with open(unidentified_file, "r") as f:
168
+ unidentified = yaml.load(f, Loader=yaml.Loader)
169
+
170
+ with open(baseline_file, "r") as f:
171
+ baseline = yaml.load(f, Loader=yaml.Loader)
172
+
173
+ for nodes in unidentified.values():
174
+ node_names = list(nodes.keys())
175
+ break
176
+
177
+ # print(yaml.dump(
178
+ # {
179
+ # key: {
180
+ # node_name: [float(v) for v in node_vals]
181
+ # for node_name, node_vals in
182
+ # zip(node_names, mode.reshape((-1, len(node_names))).T)
183
+ # } for key, mode in
184
+ # associate_modes(baseline, unidentified, compare=compare).items()
185
+ # }
186
+ # ))
187
+
188
+ # for k,mode in associate_modes(baseline, unidentified, compare=compare).items():
189
+ # print(f"{k}:\n\t")
190
+ # print("\n\t".join((f"{node_name}: [{','.join(str(v) for v in node_vals)}]"
191
+ # for node_name, node_vals in
192
+ # zip(node_names, mode.reshape((-1, len(node_names))).T)
193
+ # )))
194
+
195
+ associate_modes(baseline, unidentified, compare=compare_mode)
196
+