irie 0.0.58__py3-none-any.whl → 0.0.60__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/evaluation/models.py +7 -0
  2. irie/apps/events/views_events.py +2 -2
  3. irie/apps/inventory/migrations/0009_datum_angle_x_datum_angle_y.py +23 -0
  4. irie/apps/inventory/models.py +1 -1
  5. irie/apps/inventory/views.py +10 -4
  6. irie/apps/prediction/forms/csi_upload.py +68 -0
  7. irie/apps/prediction/migrations/0007_remove_sensorassignment_orient_x_and_more.py +25 -0
  8. irie/apps/prediction/runners/__init__.py +6 -4
  9. irie/apps/prediction/runners/opensees/__init__.py +49 -14
  10. irie/apps/prediction/urls.py +6 -4
  11. irie/apps/prediction/views.py +248 -17
  12. irie/apps/static/assets/css/brace.css +1 -1
  13. irie/apps/static/assets/css/brace.css.map +1 -1
  14. irie/apps/static/assets/css/brace.min.css +1 -1
  15. irie/apps/static/assets/js/brace.js +101 -42
  16. irie/apps/templates/includes/footer.html +1 -1
  17. irie/apps/templates/inventory/asset-event-summary.html +7 -0
  18. irie/apps/templates/inventory/asset-on-map.html +22 -22
  19. irie/apps/templates/inventory/asset-on-map.js +115 -113
  20. irie/apps/templates/inventory/create-datum.html +44 -0
  21. irie/apps/templates/inventory/sensor-upload.html +22 -22
  22. irie/apps/templates/layouts/base.html +3 -3
  23. irie/apps/templates/prediction/create-model.html +32 -37
  24. irie/apps/templates/prediction/upload/confirm.html +93 -0
  25. irie/apps/templates/prediction/upload/step.html +119 -0
  26. irie/apps/templates/prediction/veux/navigator.html +54 -38
  27. irie/apps/templates/prediction/veux/navigator.js +222 -154
  28. irie/apps/templates/prediction/xara-profile.html +7 -3
  29. irie/core/settings.py +1 -0
  30. {irie-0.0.58.dist-info → irie-0.0.60.dist-info}/METADATA +7 -6
  31. {irie-0.0.58.dist-info → irie-0.0.60.dist-info}/RECORD +35 -29
  32. /irie/apps/prediction/{forms.py → forms/__init__.py} +0 -0
  33. {irie-0.0.58.dist-info → irie-0.0.60.dist-info}/WHEEL +0 -0
  34. {irie-0.0.58.dist-info → irie-0.0.60.dist-info}/entry_points.txt +0 -0
  35. {irie-0.0.58.dist-info → irie-0.0.60.dist-info}/top_level.txt +0 -0
@@ -16,13 +16,15 @@ import uuid
16
16
  import base64
17
17
  import hashlib
18
18
 
19
+ from django.template.loader import render_to_string
20
+ from django.utils.html import escape
19
21
  from django.template import loader
20
22
  from django.contrib.auth.decorators import login_required
21
23
  from django.core.exceptions import ObjectDoesNotExist
22
24
  from django.core.files.base import ContentFile
23
25
  from django.shortcuts import HttpResponse, get_object_or_404
24
26
 
25
- from irie.apps.inventory.models import Asset
27
+ from irie.apps.inventory.models import Asset, Datum
26
28
  from irie.apps.prediction.predictor import PREDICTOR_TYPES
27
29
  from irie.apps.prediction.models import PredictorModel
28
30
  from .forms import PredictorForm
@@ -76,25 +78,93 @@ def asset_predictors(request, calid):
76
78
  def predictor_render(request, calid, preid):
77
79
 
78
80
  predictor = get_object_or_404(PredictorModel, pk=int(preid))
81
+
82
+ canvas = None
83
+
84
+ sname = request.GET.get("section", None)
85
+
86
+ runner = predictor.runner
87
+
88
+ if sname is None:
89
+ try:
90
+ artist = runner.render()
91
+ if artist is None:
92
+ return HttpResponse(
93
+ json.dumps({"error": "No rendering available"}),
94
+ content_type="application/json",
95
+ status=404
96
+ )
97
+ canvas = artist.canvas
98
+ except Exception as e:
99
+ return HttpResponse(
100
+ json.dumps({"error": str(e)}),
101
+ content_type="application/json",
102
+ status=500
103
+ )
104
+ else:
105
+ try:
106
+ _, mesh = runner.structural_section(sname)
107
+
108
+ artist = veux.create_artist(mesh.model, canvas="gltf")
109
+ artist.draw_surfaces()
110
+ # artist.draw_outlines()
111
+ canvas = artist.canvas
112
+ # canvas = veux._create_canvas(name="gltf")
113
+ import numpy as np
114
+ R = np.array([[1, 0],
115
+ [0, 1],
116
+ [0, 0]])
117
+ exterior = mesh.exterior()
118
+ exterior = np.append(exterior, np.array([[exterior[0][0], exterior[0][1]]]), axis=0)
119
+
120
+ canvas.plot_lines(exterior@R.T)
121
+ if (interior := mesh.interior()) is not None:
122
+ for i in interior:
123
+ i = np.append(i, np.array([[i[0][0], i[0][1]]]), axis=0)
124
+ canvas.plot_lines(i@R.T)
125
+ try:
126
+ canvas.plot_vectors(np.zeros((3,3)),
127
+ np.eye(3)*min(mesh.depth, mesh.width)/3, extrude=True)
128
+ except:
129
+ pass
130
+
131
+ except Exception as e:
132
+ raise e
133
+ return HttpResponse(
134
+ json.dumps({"error": "Section not found"}),
135
+ content_type="application/json",
136
+ status=404
137
+ )
138
+
139
+ if canvas is None:
140
+ return HttpResponse(
141
+ json.dumps({"error": "No rendering available"}),
142
+ content_type="application/json",
143
+ status=404
144
+ )
145
+
146
+ glb = canvas.to_glb()
147
+ return HttpResponse(glb, content_type="application/binary")
148
+
149
+
150
+ @login_required(login_url="/login/")
151
+ def predictor_table(request, calid, preid):
152
+
153
+ predictor = get_object_or_404(PredictorModel, pk=int(preid))
79
154
 
80
155
  sname = request.GET.get("section", None)
81
156
 
82
- runner = PREDICTOR_TYPES[predictor.protocol](predictor)
157
+ runner = predictor.runner
83
158
 
84
159
  try:
85
- _, mesh = runner.structural_section(sname)
86
-
87
- can = veux._create_canvas(name="gltf")
88
- import numpy as np
89
- R = np.array([[1, 0],[0, 1], [0, 0]])
90
- can.plot_lines(mesh.exterior()@R.T)
91
- if (interior := mesh.interior()) is not None:
92
- for i in interior:
93
- can.plot_lines(i@R.T)
94
- glb = can.to_glb()
95
- return HttpResponse(glb, content_type="application/binary")
160
+ properties, _ = runner.structural_section(sname)
161
+
162
+ data = json.dumps(properties)
163
+ return HttpResponse(data,
164
+ content_type="application/json")
96
165
 
97
166
  except Exception as e:
167
+ print(e)
98
168
  return HttpResponse(
99
169
  json.dumps({"error": "Section not found"}),
100
170
  content_type="application/json",
@@ -102,6 +172,44 @@ def predictor_render(request, calid, preid):
102
172
  )
103
173
 
104
174
 
175
+ @login_required(login_url="/login/")
176
+ def predictor_analysis(request, calid, preid):
177
+
178
+ predictor = get_object_or_404(PredictorModel, pk=int(preid))
179
+
180
+ runner = predictor.runner
181
+ sname = request.GET.get("section", None)
182
+
183
+ if sname is not None:
184
+
185
+ try:
186
+ _, mesh = runner.structural_section(sname)
187
+ except Exception as e:
188
+ return HttpResponse(
189
+ json.dumps({"error": "Section not found"}),
190
+ content_type="application/json",
191
+ status=404
192
+ )
193
+
194
+ try:
195
+ content = "<div></div>"
196
+ return HttpResponse(content)
197
+
198
+ except Exception as e:
199
+ return HttpResponse(
200
+ json.dumps({"error": str(e)}),
201
+ content_type="application/json",
202
+ status=500
203
+ )
204
+
205
+
206
+ return HttpResponse(
207
+ json.dumps({"error": str(e)}),
208
+ content_type="application/json",
209
+ status=500
210
+ )
211
+
212
+
105
213
  @login_required(login_url="/login/")
106
214
  def predictor_profile(request, calid, preid):
107
215
 
@@ -124,8 +232,8 @@ def predictor_profile(request, calid, preid):
124
232
 
125
233
  predictor = get_object_or_404(PredictorModel, pk=int(preid))
126
234
 
127
- context["asset"] = asset
128
- context["runner"] = PREDICTOR_TYPES[predictor.protocol](predictor)
235
+ context["asset"] = asset
236
+ context["runner"] = predictor.runner
129
237
  context["predictor"] = predictor
130
238
  context["sensors"] = predictor.sensorassignment_set.all()
131
239
 
@@ -151,7 +259,8 @@ def predictor_profile(request, calid, preid):
151
259
  if "DEBUG" in os.environ and os.environ["DEBUG"]:
152
260
  raise e
153
261
  html_template = loader.get_template("site/page-500.html")
154
- return HttpResponse(html_template.render(context, request))
262
+ return HttpResponse(html_template.render(context, request), status=500)
263
+
155
264
 
156
265
 
157
266
  @login_required(login_url="/login/")
@@ -204,7 +313,6 @@ def asset_map(request, calid):
204
313
  return HttpResponse(r200.render(context, request))
205
314
 
206
315
  except Exception as e:
207
- raise e
208
316
  r500 = loader.get_template("site/page-500.html")
209
317
  return HttpResponse(r500.render({"message": str(e)}, request), status=500)
210
318
 
@@ -220,7 +328,129 @@ def create_mdof(request):
220
328
  html_template = loader.get_template("prediction/" + page_template)
221
329
  return HttpResponse(html_template.render(context, request))
222
330
 
331
+ from formtools.wizard.views import SessionWizardView
332
+ from .forms.csi_upload import DatumCreateForm, DatumSelectForm, PredictorForm, SensorForm, ConfirmForm
333
+
334
+ FORMS = [
335
+ ("select datum", DatumSelectForm),
336
+ ("create datum", DatumCreateForm),
337
+ ("structure", PredictorForm),
338
+ ("sensor", SensorForm),
339
+ ("confirm", ConfirmForm),
340
+ ]
341
+
342
+ TEMPLATES = {
343
+ "select datum": "prediction/upload/step.html",
344
+ "create datum": "prediction/upload/step.html",
345
+ "structure": "prediction/upload/step.html",
346
+ "sensor": "prediction/upload/step.html",
347
+ "confirm": "prediction/upload/step.html",
348
+ }
349
+
350
+ from django.shortcuts import redirect
351
+ from django.core.files.storage import FileSystemStorage
352
+ from django.conf import settings
353
+
354
+ class CsiUpload(SessionWizardView):
355
+ form_list = FORMS
356
+ file_storage = FileSystemStorage(location=settings.MEDIA_ROOT)
357
+
358
+ condition_dict = {
359
+ "create datum": lambda self: (
360
+ self.get_cleaned_data_for_step("select datum") is None \
361
+ or self.get_cleaned_data_for_step("select datum").get("datum") is None
362
+ ),
363
+ }
364
+
365
+ def dispatch(self, request, *args, **kwargs):
366
+ self.asset = get_object_or_404(Asset, calid=kwargs["calid"])
367
+ self.request = request
368
+ return super().dispatch(request, *args, **kwargs)
369
+
370
+ def get_template_names(self):
371
+ return [TEMPLATES[self.steps.current]]
372
+
373
+ def get_form_kwargs(self, step=None):
374
+ kwargs = super().get_form_kwargs(step)
375
+
376
+ if step == "select datum":
377
+ kwargs["asset"] = self.asset
378
+ kwargs["initial"] = {"asset": self.asset.id}
379
+ kwargs["datum_queryset"] = Datum.objects.filter(asset=self.asset)
380
+ elif step == "create datum":
381
+ kwargs["asset"] = self.asset
382
+ kwargs["initial"] = {"asset": self.asset.id}
383
+ elif step == "structure":
384
+ kwargs["asset"] = self.asset
385
+ kwargs["initial"] = {
386
+ "asset": self.asset,
387
+ "active": False,
388
+ "protocol": PredictorModel.Protocol.TYPE1,
389
+ }
390
+ elif step == "sensor":
391
+ datum_data = self.get_cleaned_data_for_step("datum") or {}
392
+ kwargs["initial"] = {
393
+ # "datum": datum_data.get("id"),
394
+ "asset": self.asset.id,
395
+ "node": -1,
396
+ "predictor": self.get_cleaned_data_for_step("structure").get("id")
397
+ }
398
+ return kwargs
399
+
400
+ def get_context_data(self, form, **kwargs):
401
+ context = super().get_context_data(form=form, **kwargs)
402
+ context["asset"] = self.asset
403
+ context["segment"] = "assets"
404
+ context["step"] = self.steps.current
405
+
406
+ if self.steps.current == "confirm":
407
+ predictor = self.get_form("structure").save(commit=False)
408
+ model_file = self.get_cleaned_data_for_step("structure").get("config_file")
409
+
410
+ predictor.protocol = PredictorModel.Protocol.TYPE1
411
+ predictor.config_file = model_file
412
+ artist = predictor.runner.render()
413
+ glb = artist.canvas.to_glb()
414
+ glb64 = base64.b64encode(glb).decode("utf-8")
415
+
416
+ context["rndrdoc"] = escape(render_to_string(
417
+ "inventory/asset-on-map.html",
418
+ context={
419
+ "asset": self.asset,
420
+ "viewer": "three",
421
+ "scale": 1/3.2808, # TODO
422
+ # "offset": json.dumps(list(reversed(list(self.asset.coordinates)))),
423
+ "rotate": "[0, 0, 0]",
424
+ "render_glb": f"data:application/octet-stream;base64,{glb64}",
425
+ "location": json.dumps(list(reversed(list(self.asset.coordinates)))),
426
+ },
427
+ request=self.request
428
+ ))
429
+ return context
430
+
431
+ def done(self, form_list, form_dict, **kwargs):
432
+ # datum comes from select step unless create step ran
433
+ if "select datum" in form_dict:
434
+ datum = form_dict["select datum"].cleaned_data["datum"]
435
+ elif "datum create" in form_dict:
436
+ datum = form_dict["datum create"].save(commit=False)
437
+ datum.save()
438
+ else:
439
+ datum = form_dict["select datum"].cleaned_data["datum"]
440
+
441
+ predictor = form_dict["structure"].save(commit=False)
442
+ sensor = form_dict["sensor"].save(commit=False)
223
443
 
444
+ predictor.asset = self.asset
445
+ predictor.active = True
446
+ predictor.protocol = PredictorModel.Protocol.TYPE1
447
+ predictor.save()
448
+
449
+ sensor.node = -1
450
+ sensor.predictor = predictor
451
+ sensor.save()
452
+ return redirect("asset_predictors", calid=predictor.asset.calid)
453
+
224
454
  @login_required(login_url="/login/")
225
455
  def create_model(request, calid):
226
456
 
@@ -252,6 +482,7 @@ def create_model(request, calid):
252
482
  except Exception as e:
253
483
  return HttpResponse(r400.render({"message": json.dumps({"error": str(e)})}), status=500)
254
484
 
485
+
255
486
  # 3) Render the model
256
487
  outlines = collect_outlines(csi, model.frame_tags)
257
488
  artist = veux.create_artist(model,
@@ -5577,7 +5577,7 @@ textarea.form-control-lg {
5577
5577
  --bs-accordion-body-padding-x: 1.25rem;
5578
5578
  --bs-accordion-body-padding-y: 1rem;
5579
5579
  --bs-accordion-active-color: rgb(27.9, 36.9, 49.5);
5580
- --bs-accordion-active-bg: #9CA3AF;
5580
+ --bs-accordion-active-bg: transparent;
5581
5581
  }
5582
5582
 
5583
5583
  .accordion-button {