irie 0.0.16__py3-none-any.whl → 0.0.18__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 (35) hide show
  1. irie/apps/events/views_events.py +4 -6
  2. irie/apps/inventory/filters.py +37 -5
  3. irie/apps/inventory/models.py +14 -1
  4. irie/apps/inventory/sitemaps.py +19 -0
  5. irie/apps/inventory/views.py +2 -7
  6. irie/apps/prediction/forms.py +4 -1
  7. irie/apps/prediction/predictor.py +5 -274
  8. irie/apps/prediction/runners/__init__.py +17 -15
  9. irie/apps/prediction/runners/hazus.py +271 -182
  10. irie/apps/prediction/runners/opensees/__init__.py +88 -11
  11. irie/apps/prediction/runners/ssid.py +168 -9
  12. irie/apps/prediction/urls.py +3 -4
  13. irie/apps/prediction/views.py +8 -85
  14. irie/apps/sitemaps.py +14 -0
  15. irie/apps/static/assets/content_images/brace/mdof.svg +1 -0
  16. irie/apps/static/assets/content_images/brace/opensees.jpg +0 -0
  17. irie/apps/static/assets/content_images/brace/sdof.svg +327 -0
  18. irie/apps/static/assets/content_images/brace/sees.png +0 -0
  19. irie/apps/templates/accounts/login.html +50 -55
  20. irie/apps/templates/inventory/asset-profile.html +0 -15
  21. irie/apps/templates/inventory/asset-table.html +38 -15
  22. irie/apps/templates/prediction/asset-predictors.html +38 -5
  23. irie/apps/templates/prediction/new-runner.html +1 -1
  24. irie/apps/templates/prediction/predictor-profile.html +11 -0
  25. irie/apps/templates/site/index.html +5 -7
  26. irie/init/__main__.py +8 -5
  27. irie/init/data/cgs-stations.json +2967 -0
  28. irie/init/getCGSData.py +9 -4
  29. irie/init/management/commands/init_assets.py +1 -1
  30. irie/init/management/commands/init_cesmd.py +25 -0
  31. {irie-0.0.16.dist-info → irie-0.0.18.dist-info}/METADATA +1 -1
  32. {irie-0.0.16.dist-info → irie-0.0.18.dist-info}/RECORD +35 -27
  33. {irie-0.0.16.dist-info → irie-0.0.18.dist-info}/WHEEL +0 -0
  34. {irie-0.0.16.dist-info → irie-0.0.18.dist-info}/entry_points.txt +0 -0
  35. {irie-0.0.16.dist-info → irie-0.0.18.dist-info}/top_level.txt +0 -0
@@ -55,8 +55,7 @@ def save_event(request, event, success_status):
55
55
 
56
56
 
57
57
  if len(errors) > 0:
58
- return HttpResponse(json.dumps(
59
- {
58
+ return HttpResponse(json.dumps({
60
59
  "errors": errors
61
60
  }), status=status.HTTP_400_BAD_REQUEST)
62
61
 
@@ -69,10 +68,10 @@ def save_event(request, event, success_status):
69
68
  ).serialize(serialize_data=False, summarize=True)
70
69
  )
71
70
  except:
72
- return HttpResponse(json.dumps(
73
- {
71
+ return HttpResponse(json.dumps({
74
72
  "errors": ["Failed to parse ground motion file."]
75
- }), status=status.HTTP_400_BAD_REQUEST)
73
+ }), status=status.HTTP_400_BAD_REQUEST)
74
+
76
75
  elif "motion_data" in request.data:
77
76
  motion_data = json.loads(request.data.get("motion_data"))
78
77
 
@@ -85,7 +84,6 @@ def save_event(request, event, success_status):
85
84
  # RECORD ID
86
85
  rec_id = motion_data.get("record_identifier", "")
87
86
 
88
-
89
87
  if EventRecord.objects.filter(record_identifier=rec_id).first():
90
88
  print("\n\nSKIPPING\n\n")
91
89
  return HttpResponse(json.dumps({"data": ""}), status=success_status)
@@ -14,16 +14,48 @@ class AssetFilter(django_filters.FilterSet):
14
14
  method='filter_cesmd_exists'
15
15
  )
16
16
 
17
- is_complete = django_filters.BooleanFilter(
18
- field_name='is_complete',
19
- label='Is Complete',
20
- widget=CheckboxInput()
21
- )
17
+ # is_complete = django_filters.BooleanFilter(
18
+ # field_name='is_complete',
19
+ # label='Is Complete',
20
+ # widget=CheckboxInput()
21
+ # )
22
22
  district = django_filters.CharFilter(
23
23
  label='District',
24
24
  method='filter_district'
25
25
  )
26
26
 
27
+ max_year = django_filters.NumberFilter(
28
+ label='Max Year',
29
+ method='filter_year',
30
+ # widget=django_filters.widgets.DateInput(attrs={'type': 'date'})
31
+ )
32
+ # max_year = django_filters.DateFilter(
33
+ # label='Max Year',
34
+ # field_name='nbi_data__NBI_BRIDGE__Year Built',
35
+ # lookup_expr='lte'
36
+ # )
37
+ def filter_year(self, queryset, name, value):
38
+ ids = {
39
+ asset.id for asset in queryset if (
40
+ asset.nbi_data and int(asset.nbi_data["NBI_BRIDGE"]["Year Built"] or 0) <= int(value) #.year
41
+ )
42
+ }
43
+ return queryset.filter(id__in=ids)
44
+ if value:
45
+ return queryset.filter(
46
+ nbi_data__NBI_BRIDGE__Year_Built__lte=int(value) #.year
47
+ )
48
+ return
49
+
50
+ if value:
51
+ filtered_ids = [
52
+ asset.id for asset in queryset if (
53
+ asset.nbi_data and asset.nbi_data["NBI_BRIDGE"]["Year Built"] <= value.year
54
+ )
55
+ ]
56
+ return queryset.filter(id__in=filtered_ids)
57
+
58
+
27
59
  def filter_cesmd_exists(self, queryset, name, value):
28
60
  if value: # Checkbox is checked
29
61
  return queryset.exclude(cesmd__isnull=True).exclude(cesmd__exact='')
@@ -10,6 +10,7 @@
10
10
  #----------------------------------------------------------------------------#
11
11
  from django.db import models
12
12
  from django.core.validators import int_list_validator
13
+ from django.urls import reverse
13
14
 
14
15
  class Corridor(models.Model):
15
16
  id = models.BigAutoField(primary_key=True)
@@ -41,6 +42,18 @@ class Asset(models.Model):
41
42
 
42
43
  def __str__(self):
43
44
  return f"{self.calid} - {self.name}"
45
+
46
+ def get_absolute_url(self):
47
+ return reverse("asset_profile", args=[self.calid])
48
+
49
+ @property
50
+ def last_event(self):
51
+ from irie.apps.events.models import EventRecord
52
+ # TODO: use event_date
53
+ try:
54
+ return EventRecord.objects.filter(asset=self).latest("upload_date")
55
+ except EventRecord.DoesNotExist:
56
+ return None
44
57
 
45
58
  @property
46
59
  def predictors(self): # ->Dict[str, Predictor]:
@@ -54,7 +67,7 @@ class Asset(models.Model):
54
67
  @property
55
68
  def event_count(self):
56
69
  from irie.apps.events.models import EventRecord
57
- return len(EventRecord.objects.filter(asset=self))
70
+ return EventRecord.objects.filter(asset=self).count()
58
71
 
59
72
  @property
60
73
  def rendering(self):
@@ -0,0 +1,19 @@
1
+
2
+ from django.contrib.sitemaps import Sitemap
3
+ from django.urls import reverse
4
+ from .models import Asset # Replace with your model
5
+
6
+ class InventorySitemap(Sitemap):
7
+ changefreq = "weekly" # Change frequency of the content
8
+ priority = 0.5 # Priority of the URLs in the sitemap
9
+
10
+ def items(self):
11
+ # Return a queryset of objects for the sitemap
12
+ return Asset.objects.exclude(cesmd__isnull=True)
13
+
14
+ def lastmod(self, obj):
15
+ # Return the last modification date of an object
16
+ if event := obj.last_event:
17
+ return event.upload_date
18
+ return None
19
+
@@ -140,7 +140,6 @@ def dashboard(request):
140
140
  return HttpResponse(html_template.render(context, request))
141
141
 
142
142
 
143
-
144
143
  @login_required(login_url="/login/")
145
144
  def asset_event_report(request):
146
145
  from irie.apps.evaluation.models import Evaluation
@@ -173,7 +172,7 @@ def asset_event_report(request):
173
172
 
174
173
 
175
174
 
176
- @login_required(login_url="/login/")
175
+ # @login_required(login_url="/login/")
177
176
  def asset_profile(request, calid):
178
177
 
179
178
  context = {}
@@ -209,10 +208,6 @@ def asset_profile(request, calid):
209
208
  except:
210
209
  pass
211
210
 
212
- try:
213
- context["mountains"] = make_mountains(asset)
214
- except:
215
- pass
216
211
 
217
212
  context["tables"] = _make_tables(asset)
218
213
 
@@ -298,7 +293,7 @@ def _make_tables(asset):
298
293
 
299
294
 
300
295
 
301
- @login_required(login_url="/login/")
296
+ # @login_required(login_url="/login/")
302
297
  def asset_table(request):
303
298
  """
304
299
  Returns a table of all assets in the database, paginated
@@ -10,7 +10,10 @@ class PredictorForm(forms.ModelForm):
10
10
  class Meta:
11
11
  model = PredictorModel
12
12
  fields = '__all__'
13
- exclude = ['render_file', 'asset', 'metrics', 'active',
13
+ exclude = ['render_file',
14
+ 'asset',
15
+ 'metrics',
16
+ 'active',
14
17
  'entry_point',
15
18
  'config',
16
19
  'protocol']
@@ -10,285 +10,16 @@
10
10
  #
11
11
  #----------------------------------------------------------------------------#
12
12
  from __future__ import annotations
13
- import sys
14
- import json
15
- import subprocess
16
- from pathlib import Path
17
13
  from typing import Dict
18
14
 
19
- from .runners import (
20
- Runner, RunID,
21
- classproperty
22
- )
15
+ from .runners import Runner, RunID
23
16
  from .runners.opensees import OpenSeesRunner
24
-
25
- class Event: pass
26
-
27
-
28
- class PredictorType1(Runner):
29
- @property
30
- def platform(self):
31
- return self.conf.get("platform", "")
32
-
33
- @classmethod
34
- def create(cls, asset, request):
35
- from .models import PredictorModel
36
- predictor = PredictorModel()
37
- data = json.loads(request.data.get("json"))
38
- predictor.entry_point = [
39
- sys.executable, "-m", "opensees"
40
- ]
41
- data["metrics"] = []
42
-
43
- predictor.name = data.pop("name")
44
- predictor.config = data
45
- predictor.asset = asset
46
- predictor.protocol = "IRIE_PREDICTOR_T1"
47
- predictor.active = False
48
- return predictor
49
-
50
-
51
- @classproperty
52
- def schema(cls):
53
- from .runners.opensees import schemas
54
- return {
55
- "title": "Structural Model",
56
- "options": {"disable_collaps": True},
57
- "schema": "http://json-schema.org/draft-04/schema#",
58
- "type": "object",
59
- "properties": {
60
- "platform": {
61
- "type": "string",
62
- "title": "Platform",
63
- "enum": ["OpenSees","CSiBridge"]
64
- },
65
- "model": schemas.load("hwd_conf.schema.json"),
66
- "analysis": schemas.load("hwd_analysis.schema.json"),
67
- }
68
- }
69
-
70
- def newPrediction(self, event: Event) -> RunID:
71
- self.event = event
72
- event_file = Path(event.event_file.path).resolve()
73
- command = [*self.entry_point, "new", event_file]
74
- run_id = subprocess.check_output(command).decode().strip()
75
- return RunID(int(run_id))
76
-
77
- def runPrediction(self, run_id: RunID):
78
- command = [*self.entry_point, "run", str(run_id)]
79
-
80
- if "scale" in self.event.upload_data:
81
- command.extend(["--scale", str(float(self.event.upload_data["scale"]))])
82
- print(":: Running ", command, file=sys.stderr)
83
- subprocess.check_output(command)
84
-
85
- print(f":: Model {self.name} returned", file=sys.stderr)
86
- return
87
-
88
- def getMetricData(self, run, metric):
89
- try:
90
- return json.loads(subprocess.check_output([*self.entry_point, "get", str(run), metric]).decode())
91
- except json.decoder.JSONDecodeError:
92
- return {}
93
-
94
-
95
- class PredictorType2(Runner):
96
- platform = "mdof"
97
-
98
- schema = {
99
- "title": "System ID",
100
- "name": "P2",
101
- "type": "object",
102
- "required": [
103
- "name",
104
- "decimation",
105
- "method",
106
- "channels"
107
- ],
108
- "properties": {
109
- "name": {
110
- "type": "string",
111
- "title": "Name",
112
- "description": "Predictor name",
113
- "minLength": 2,
114
- # "default": "S1"
115
- },
116
- "method": {
117
- "type": "string",
118
- "title": "Method",
119
- "enum": ["Fourier Spectrum","Response Spectrum","SRIM","OKID"]
120
- },
121
- "decimation": {
122
- "type": "integer",
123
- "title": "Decimation",
124
- "default": 1,
125
- "minimum": 1,
126
- "maximum": 8
127
- },
128
- "order": {
129
- "type": "integer",
130
- "title": "Model Order",
131
- "default": 8,
132
- "minimum": 2,
133
- "maximum": 64,
134
- "options": {"dependencies": {"method": ["SRIM","OKID"]}}
135
- },
136
- "horizon": {
137
- "type": "integer",
138
- "title": "Prediction Horizon",
139
- "default": 100,
140
- "minimum": 50,
141
- "maximum": 500,
142
- "options": {"dependencies": {"method": ["SRIM"]}}
143
- },
144
- "period_band": {
145
- "type": "string",
146
- "title": "Period Band",
147
- "default": "[0.1,2.3]",
148
- "options": {"dependencies": {"method": ["Fourier Spectrum"]}},
149
- "description": "[0.1,2.3] if interested in periods between 0.1 seconds and 2.3 seconds"
150
- },
151
- "damping": {
152
- "type": "float",
153
- "title": "Damping",
154
- "default": 0.02,
155
- "options": {"dependencies": {"method": ["Response Spectrum"]}},
156
- "description": "assumed damping ratio"
157
- },
158
- "channels": {
159
- "type": "array",
160
- "format": "table",
161
- "title": "Channels",
162
- "uniqueItems": True,
163
- "items": {
164
- "title": "Acceleration",
165
- "type": "object",
166
- "properties": {
167
- "type": {
168
- "type": "string",
169
- "enum": ["output","input"],
170
- "default": "output"
171
- },
172
- "id": {"type": "integer", "description": "Number identifying signal channel"}
173
- }
174
- },
175
- "default": [{"type": "output", "id": 1}]
176
- }
177
- }
178
- }
179
-
180
- @classmethod
181
- def create(cls, asset, request):
182
- from .models import PredictorModel
183
- predictor = PredictorModel()
184
- data = json.loads(request.data.get("json"))
185
- method = {
186
- "Fourier Spectrum": "fourier",
187
- "Response Spectrum": "response",
188
- "FDD": "fdd",
189
- "OKID": "okid-era",
190
- "SRIM": "srim"
191
- }[data.pop("method")]
192
- predictor.entry_point = [
193
- sys.executable, "-m", "mdof", method
194
- ]
195
- data["outputs"] = [i["id"] for i in data["channels"] if i["type"] == "output"]
196
- data["inputs"] = [i["id"] for i in data["channels"] if i["type"] == "input"]
197
- data["threads"] = 4
198
- data["metrics"] = ["SPECTRAL_SHIFT_IDENTIFICATION"]
199
- del data["channels"]
200
-
201
- predictor.name = data.pop("name")
202
- predictor.config = data
203
- predictor.asset = asset
204
- predictor.protocol = "IRIE_PREDICTOR_T2"
205
- predictor.active = True
206
- return predictor
207
-
208
-
209
- def newPrediction(self, event):
210
- self.event = event
211
- return RunID(1)
212
-
213
- def runPrediction(self, run_id: RunID) -> bool:
214
- event_file = Path(self.event.event_file.path).resolve()
215
- command = [*self.entry_point,
216
- "--config",
217
- json.dumps(self.conf),
218
- event_file]
219
-
220
- if False:
221
- command = [*self.entry_point,
222
- event_file,
223
- *map(str, self.conf.get("argv", []))]
224
- try:
225
- self.metric_details = json.loads(
226
- subprocess.check_output(command).decode()
227
- )
228
- return True
229
- except Exception as e:
230
- self.metric_data = {"error": str(e)}
231
- return False
232
-
233
- def getMetricData(self, run, metric):
234
- if not hasattr(self, "metric_details"):
235
- raise Exception(f"Error {self.name}({id(self)}), {run}")
236
- return self.metric_details
237
-
238
-
239
- class PredictorType4(Runner):
240
- platform = "csi"
241
-
242
- @classmethod
243
- def create(cls, asset, request, config):
244
- from .models import PredictorModel
245
- predictor = PredictorModel()
246
-
247
- predictor.entry_point = [
248
- sys.executable, "-m", "opensees"
249
- ]
250
-
251
- predictor.name = config.pop("name")
252
- predictor.config = config
253
- predictor.asset = asset
254
- predictor.protocol = "IRIE_PREDICTOR_T4"
255
- predictor.active = True
256
- return predictor
257
-
258
-
259
- def newPrediction(self, event):
260
- self.event = event
261
- return RunID(1)
262
-
263
- def runPrediction(self, run_id: RunID) -> bool:
264
- event_file = Path(self.event.event_file.path).resolve()
265
- command = [*self.entry_point,
266
- "--config", json.dumps(self.conf),
267
- event_file]
268
- if False:
269
- command = [*self.entry_point,
270
- event_file,
271
- *map(str, self.conf.get("argv", []))]
272
-
273
- try:
274
- self.metric_details = json.loads(
275
- subprocess.check_output(command).decode()
276
- )
277
- return True
278
- except Exception as e:
279
- self.metric_details = {"error": str(e)}
280
- return False
281
-
282
- def getMetricData(self, run, metric):
283
- if not hasattr(self, "metric_details"):
284
- raise Exception(f"Error {self.name}({id(self)}), {run}")
285
- return self.metric_details
286
-
17
+ from .runners.ssid import SystemIdRunner
287
18
 
288
19
  PREDICTOR_TYPES : Dict[str, Runner] = {
289
- "IRIE_PREDICTOR_V1" : PredictorType1,
290
- "IRIE_PREDICTOR_T2" : PredictorType2,
291
- "" : PredictorType2,
20
+ # "IRIE_PREDICTOR_V1" : PredictorType1,
21
+ "IRIE_PREDICTOR_T2" : SystemIdRunner,
22
+ "" : SystemIdRunner,
292
23
  # "IRIE_PREDICTOR_T3" : PredictorType3,
293
24
  "IRIE_PREDICTOR_T4" : OpenSeesRunner,
294
25
  }
@@ -11,28 +11,30 @@ class classproperty(property):
11
11
 
12
12
 
13
13
  class Runner:
14
- def __init__(self, conf: dict):
14
+ def __init__(self, pred: dict):
15
15
 
16
- if isinstance(conf, dict):
16
+ if isinstance(pred, dict):
17
17
  # Create from dict when posted from API; this
18
18
  # is used to create a new PredictorModel
19
- self.name: str = conf["name"]
20
- self.description = conf.get("description", "")
21
- self.conf = conf["config"]
22
- self.metrics = conf["metrics"]
23
- self.entry_point = conf["entry_point"]
24
- self.active = conf.get("active", True)
19
+ self.name: str = pred["name"]
20
+ self.description = pred.get("description", "")
21
+ self.conf = pred["config"]
22
+ self.metrics = pred["metrics"]
23
+ self.entry_point = pred["entry_point"]
24
+ self.active = pred.get("active", True)
25
25
  else:
26
26
  # Create from PredictorModel when loaded from database.
27
27
  # This is done when running analysis
28
- self.name: str = conf.name
28
+ self.id = pred.id
29
+ self.asset = pred.asset
30
+ self.name: str = pred.name
29
31
  self.description = "" # conf.description
30
- self.conf = conf.config
31
- self.entry_point = conf.entry_point
32
- self.metrics = conf.metrics
33
- self.active = conf.active
34
- if conf.config_file:
35
- self.model_file = Path(conf.config_file.path).resolve()
32
+ self.conf = pred.config
33
+ self.entry_point = pred.entry_point
34
+ self.metrics = pred.metrics
35
+ self.active = pred.active
36
+ if pred.config_file:
37
+ self.model_file = Path(pred.config_file.path).resolve()
36
38
  self.out_dir = Path(__file__).parents[0]/"Predictions"
37
39
  self.runs = {}
38
40