irie 0.0.35__py3-none-any.whl → 0.0.37__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 (28) hide show
  1. irie/apps/context_processors.py +8 -0
  2. irie/apps/inventory/admin.py +4 -1
  3. irie/apps/inventory/forms.py +30 -1
  4. irie/apps/inventory/migrations/0004_datum_sensorgroup_sensor.py +43 -0
  5. irie/apps/inventory/migrations/0005_alter_sensor_group.py +19 -0
  6. irie/apps/inventory/migrations/0006_datum_asset_datum_locate_x_datum_locate_y_and_more.py +56 -0
  7. irie/apps/inventory/migrations/0007_sensor_name.py +19 -0
  8. irie/apps/inventory/migrations/0008_alter_sensor_dx_alter_sensor_dy_alter_sensor_dz_and_more.py +43 -0
  9. irie/apps/inventory/models.py +47 -17
  10. irie/apps/inventory/urls.py +4 -2
  11. irie/apps/inventory/views.py +55 -2
  12. irie/apps/templates/includes/sidebar.html +29 -10
  13. irie/apps/templates/inventory/asset-event-summary.html +17 -7
  14. irie/apps/templates/inventory/asset-profile.html +10 -2
  15. irie/apps/templates/inventory/asset-sensors.html +69 -0
  16. irie/apps/templates/inventory/sensor-upload.html +452 -0
  17. irie/apps/templates/layouts/base-fullscreen.html +3 -4
  18. irie/apps/templates/site/index.html +2 -2
  19. irie/core/settings.py +1 -0
  20. irie/init/data/nbi_definitions.json +1 -0
  21. irie/init/getNBIData.py +12 -0
  22. irie/init/management/commands/init_assets.py +11 -7
  23. irie/init/management/commands/init_cesmd.py +11 -8
  24. {irie-0.0.35.dist-info → irie-0.0.37.dist-info}/METADATA +1 -1
  25. {irie-0.0.35.dist-info → irie-0.0.37.dist-info}/RECORD +28 -20
  26. {irie-0.0.35.dist-info → irie-0.0.37.dist-info}/WHEEL +1 -1
  27. {irie-0.0.35.dist-info → irie-0.0.37.dist-info}/entry_points.txt +0 -0
  28. {irie-0.0.35.dist-info → irie-0.0.37.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,452 @@
1
+ <!--
2
+ ===----------------------------------------------------------------------===#
3
+
4
+ STAIRLab -- STructural Artificial Intelligence Laboratory
5
+
6
+ ===----------------------------------------------------------------------===#
7
+
8
+ Chrystal Chern, Spring 2025
9
+
10
+ -->
11
+ {% extends "layouts/base.html" %}
12
+
13
+ {% block stylesheets %}
14
+ <style>
15
+ input[type="number"] {
16
+ -moz-appearance: textfield; /* Firefox */
17
+ appearance: textfield; /* Standard */
18
+ }
19
+ input[type="number"]::-webkit-inner-spin-button,
20
+ input[type="number"]::-webkit-outer-spin-button {
21
+ -webkit-appearance: none;
22
+ margin: 0;
23
+ }
24
+ </style>
25
+ <script type="importmap">
26
+ {
27
+ "imports": {
28
+ "three": "https://cdn.jsdelivr.net/npm/three@0.172.0/build/three.module.js",
29
+ "three/addons/": "https://cdn.jsdelivr.net/npm/three@0.172.0/examples/jsm/"
30
+ }
31
+ }
32
+ </script>
33
+ {% endblock stylesheets %}
34
+
35
+ {% block title %} Add Sensor Group to {{ asset.calid }} {% endblock %}
36
+
37
+ {% block content %}
38
+ <h1>Add Sensor Group to <code>{{ asset.calid }}</code></h1>
39
+
40
+ <div class="py-4 align-right">
41
+ <a role="button" class="button btn btn-outline-primary"
42
+ href="{% url 'asset_profile' calid=asset.calid %}" class="me-1">Back to Structure</a>
43
+ <a role="button" class="button btn btn-outline-primary"
44
+ href="{% url 'asset_sensors' calid=asset.calid %}" class="me-1">Back to Sensors</a>
45
+ </div>
46
+
47
+
48
+ <div class="container">
49
+ <div class="row align-right">
50
+
51
+ <!-- Left Side: Sensor Form -->
52
+ <div class="col-md-6" >
53
+ <form method="post">
54
+ {% csrf_token %}
55
+
56
+ <fieldset class="mb-4">
57
+ <legend>Sensor Group</legend>
58
+ {{ group_form.as_p }}
59
+ <div id="datum-info" class="mb-4 p-2 border rounded bg-light" style="display: none;">
60
+ <strong>Datum Location (x;y;z):</strong> <span id="datum-location">_, _, _</span> <br>
61
+ <strong>Datum Orientation (dx;dy;dz):</strong> <span id="datum-orientation">_, _, _</span>
62
+ </div>
63
+ </fieldset>
64
+
65
+ <fieldset>
66
+ <legend>Sensors</legend>
67
+ {{ formset.management_form }}
68
+ <div id="formset-container" class="container">
69
+ {% for form in formset %}
70
+ <div class="sensor-form mb-4">
71
+ <div class="row mb-3">
72
+ <div class="input-group">
73
+ <span class="input-group-text col-md-2 text-dark border-dark">{{ form.name.label }}</span>
74
+ <input id="{{form.name.html_name}}" type="text" name="{{form.name.html_name}}" class="form-control col-md-4 text-dark border-dark" required></input>
75
+ </div>
76
+ </div>
77
+ <div class="row"><div class="col-md-12 d-flex align-items-center mb-3">
78
+ <div class="input-group">
79
+ <span class="input-group-text col-md-4 text-gray">{{ form.x.label }}</span>
80
+ <input id="{{form.x.html_name}}" type="number" step="any" name="{{form.x.html_name}}" class="form-control col-md-8 text-gray" required></input>
81
+ </div>
82
+ <div class="input-group">
83
+ <span class="input-group-text col-md-4 text-gray">{{ form.y.label }}</span>
84
+ <input id="{{form.y.html_name}}" type="number" step="any" name="{{form.y.html_name}}" class="form-control col-md-8 text-gray" required></input>
85
+ </div>
86
+ <div class="input-group">
87
+ <span class="input-group-text col-md-4 text-gray">{{ form.z.label }}</span>
88
+ <input id="{{form.z.html_name}}" type="number" step="any" name="{{form.z.html_name}}" class="form-control col-md-8 text-gray" required></input>
89
+ </div>
90
+ </div></div>
91
+ <div class="row"><div class="col-md-12 d-flex align-items-center mb-3">
92
+ <div class="input-group">
93
+ <span class="input-group-text col-md-5 text-gray">{{ form.dx.label }}</span>
94
+ <input id="{{form.dx.html_name}}" type="number" step="any" name="{{form.dx.html_name}}" class="form-control col-md-8 text-gray" required></input>
95
+ </div>
96
+ <div class="input-group">
97
+ <span class="input-group-text col-md-5 text-gray">{{ form.dy.label }}</span>
98
+ <input id="{{form.dy.html_name}}" type="number" step="any" name="{{form.dy.html_name}}" class="form-control col-md-8 text-gray" required></input>
99
+ </div>
100
+ <div class="input-group">
101
+ <span class="input-group-text col-md-5 text-gray">{{ form.dz.label }}</span>
102
+ <input id="{{form.dz.html_name}}" type="number" step="any" name="{{form.dz.html_name}}" class="form-control col-md-8 text-gray" required></input>
103
+ </div>
104
+ </div></div>
105
+
106
+ <button class="remove-form btn btn-danger btn-sm ml-2">Remove</button>
107
+ </div>
108
+ {% endfor %}
109
+ </div>
110
+
111
+ <button id="add-form" class="btn btn-sm button btn-outline-primary mb-3">Add Sensor</button>
112
+ </fieldset>
113
+
114
+ <button type="button" id="plot-btn" class="btn btn-info btn-sm mb-3">Plot</button>
115
+
116
+ <button type="submit" class="btn btn-sm button btn-success mb-3">Submit</button>
117
+ </form>
118
+ </div>
119
+ <!-- Right Side: Asset Geometry -->
120
+ <div class="col-md-6">
121
+ <h4>Geometry</h4>
122
+ {%if false %}
123
+ {% if asset.cesmd %}
124
+ <div id="sensors" class="card bg-white-100 border-1 rounded-0 shadow mb-3">
125
+ <div class="card-body text-center p-2">
126
+ <img src="{{ ASSETS_ROOT }}/inventory/ll{{ asset.cesmd|slice:"2:" }}.svg" class="img-fluid">
127
+ </div>
128
+ <div class="card-footer text-center">
129
+ <span class="small">
130
+ Source: <a rel="nofollow noreferrer" href="https://www.strongmotioncenter.org/cgi-bin/CESMD/stationhtml.pl?stationID={{asset.cesmd}}&network=CGS">CGS</a>
131
+ </span>
132
+ </div>
133
+ </div>
134
+ {% endif %}
135
+
136
+ <div id="rendering" class="card bg-white-100 border-1 rounded-0 shadow">
137
+ <div class="card-body text-center">
138
+ <model-viewer
139
+ id="irie-viewer"
140
+ alt="3D Model"
141
+ {% if asset.rendering %}
142
+ src="{{ asset.rendering }}"
143
+ {% else %}
144
+ src="{{ ASSETS_ROOT }}/inventory/empty.glb"
145
+ {% endif %}
146
+ camera-controls
147
+ interaction-prompt="none"
148
+ camera-orbit="0deg 75deg 2m"
149
+ field-of-view="30deg"
150
+ style="width: 100%; height: 300px; background-color: #f0f0f0;">
151
+ </model-viewer>
152
+ </div>
153
+ <div class="card-footer text-center">
154
+ Powered by <a href="https://veux.io/">veux</a>
155
+ </div>
156
+ </div>
157
+ {% else %}
158
+ {% if asset.cesmd %}
159
+ <div id="sensors" class="card bg-white-100 border-1 rounded-0 shadow mb-3">
160
+ <div class="card-body text-center p-2">
161
+ <img src="{{ ASSETS_ROOT }}/inventory/ll{{ asset.cesmd|slice:"2:" }}.svg" class="img-fluid">
162
+ </div>
163
+ <div class="card-footer text-center">
164
+ <span class="small">
165
+ Source: <a rel="nofollow noreferrer" href="https://www.strongmotioncenter.org/cgi-bin/CESMD/stationhtml.pl?stationID={{asset.cesmd}}&network=CGS">CGS</a>
166
+ </span>
167
+ </div>
168
+ </div>
169
+ {% endif %}
170
+
171
+ <div id="rendering" class="card bg-white-100 border-1 rounded-0 shadow">
172
+ <div class="card-body text-center" style="background-color: #f0f0f0;">
173
+ <!-- Our Three.js container -->
174
+ <div id="threejs-container"
175
+ style="width: 100%; height: 300px; background-color: #f0f0f0; margin: 0 auto;">
176
+ </div>
177
+ </div>
178
+ <div class="card-footer text-center">
179
+ Powered by <a href="https://veux.io/">veux</a>
180
+ </div>
181
+ </div>
182
+ {% endif %}
183
+ </div>
184
+
185
+ </div>
186
+ </div>
187
+ <!--
188
+ <div id="plot-container" style="display: none;">
189
+ <h3>3D Sensor Plot</h3>
190
+ <div id="sensor-plot"></div>
191
+ </div> -->
192
+ {%endblock content %}
193
+
194
+
195
+ {% block javascripts %}
196
+ <script>
197
+ document.addEventListener("DOMContentLoaded", () => {
198
+ const formsetContainer = document.getElementById("formset-container");
199
+ const addButton = document.getElementById("add-form");
200
+ const totalForms = document.getElementById("id_form-TOTAL_FORMS");
201
+
202
+ function updateRemoveButtons() {
203
+ let forms = document.querySelectorAll(".sensor-form");
204
+
205
+ forms.forEach((form, index) => {
206
+ let removeButton = form.querySelector(".remove-form");
207
+ if (forms.length > 1)
208
+ removeButton.style.display = "inline-block";
209
+ else
210
+ removeButton.style.display = "none";
211
+ });
212
+ }
213
+
214
+ addButton.addEventListener("click", (e) => {
215
+ e.preventDefault();
216
+ let formNum = parseInt(totalForms.value);
217
+ let newForm = document.querySelector(".sensor-form").cloneNode(true);
218
+
219
+ // Update form attributes
220
+ newForm.innerHTML = newForm.innerHTML.replace(/form-(\d+)-/g, `form-${formNum}-`);
221
+ formsetContainer.appendChild(newForm);
222
+
223
+ // Increment the management form count
224
+ totalForms.value = formNum + 1;
225
+
226
+ updateRemoveButtons();
227
+ });
228
+
229
+ formsetContainer.addEventListener("click", (e) => {
230
+ if (e.target.classList.contains("remove-form")) {
231
+ e.preventDefault();
232
+ if (document.querySelectorAll(".sensor-form").length > 1) {
233
+ e.target.closest(".sensor-form").remove();
234
+ totalForms.value = document.querySelectorAll(".sensor-form").length;
235
+ updateRemoveButtons();
236
+ }
237
+ }
238
+ });
239
+
240
+ // Ensure the correct remove button state on load
241
+ updateRemoveButtons();
242
+ });
243
+ </script>
244
+ <script>
245
+ document.addEventListener("DOMContentLoaded", function () {
246
+ const datumSelect = document.getElementById("id_datum");
247
+ const datumInfoDiv = document.getElementById("datum-info");
248
+ const locationSpan = document.getElementById("datum-location");
249
+ const orientationSpan = document.getElementById("datum-orientation");
250
+
251
+ // Store datum data from Django
252
+ const datums = {{ datums|safe }};
253
+
254
+ datumSelect.addEventListener("change", function () {
255
+ const selectedDatumId = this.value;
256
+ const selectedDatum = datums.find(d => d.id == selectedDatumId);
257
+
258
+ if (selectedDatum) {
259
+ locationSpan.textContent = `${selectedDatum.locate_x}; ${selectedDatum.locate_y}; ${selectedDatum.locate_z}`;
260
+ orientationSpan.textContent = `${selectedDatum.orient_x}; ${selectedDatum.orient_y}; ${selectedDatum.orient_z}`;
261
+ datumInfoDiv.style.display = "block"; // Show info box
262
+ } else {
263
+ datumInfoDiv.style.display = "none"; // Hide if no datum selected
264
+ }
265
+ });
266
+ });
267
+ </script>
268
+ <script type="module">
269
+
270
+ import * as THREE from 'three';
271
+ import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
272
+ import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
273
+
274
+ function createArrow(origin, direction, length, color, headLength, headWidth, shaftRadius) {
275
+ const dir = direction.clone().normalize();
276
+
277
+ const shaftLength = length - headLength;
278
+
279
+ const arrowGroup = new THREE.Group();
280
+
281
+ const shaftGeometry = new THREE.CylinderGeometry(shaftRadius, shaftRadius, shaftLength, 16);
282
+ const shaftMaterial = new THREE.MeshStandardMaterial({ color: color });
283
+ const shaftMesh = new THREE.Mesh(shaftGeometry, shaftMaterial);
284
+
285
+ // CylinderGeometry is oriented along the Y-axis.
286
+ // Rotate it so it aligns with the group's local +Y (arrow "up").
287
+ // Then rotate the entire group to match `dir`.
288
+ shaftMesh.position.y = shaftLength / 2; // move it so its base starts at y=0
289
+ arrowGroup.add(shaftMesh);
290
+
291
+ const headGeometry = new THREE.ConeGeometry(shaftRadius * 2, headLength, 16);
292
+ const headMaterial = new THREE.MeshStandardMaterial({ color: color });
293
+ const headMesh = new THREE.Mesh(headGeometry, headMaterial);
294
+
295
+ headMesh.position.y = shaftLength + headLength / 2;
296
+ arrowGroup.add(headMesh);
297
+
298
+ arrowGroup.position.copy(origin);
299
+
300
+ // 5) Rotate the entire group so that +Y in local space points along `dir`
301
+ const up = new THREE.Vector3(0, 1, 0);
302
+ const quaternion = new THREE.Quaternion().setFromUnitVectors(up, dir);
303
+ arrowGroup.quaternion.copy(quaternion);
304
+
305
+ return arrowGroup;
306
+ }
307
+
308
+ document.addEventListener('DOMContentLoaded', () => {
309
+ const container = document.getElementById('threejs-container');
310
+ // Fallback or real path
311
+ const modelPath = `{{ asset.rendering|default_if_none:"" }}`;
312
+
313
+ // 1) SETUP SCENE
314
+ const scene = new THREE.Scene();
315
+ scene.background = new THREE.Color(0xf0f0f0);
316
+
317
+ // 2) SETUP RENDERER
318
+ const renderer = new THREE.WebGLRenderer({ antialias: true });
319
+ renderer.setPixelRatio(window.devicePixelRatio);
320
+ renderer.setSize(container.clientWidth, container.clientHeight);
321
+ // renderer.outputEncoding = THREE.sRGBEncoding;
322
+ container.appendChild(renderer.domElement);
323
+
324
+ // 3) SETUP CAMERA
325
+ const camera = new THREE.PerspectiveCamera(
326
+ 30, // fov
327
+ container.clientWidth / container.clientHeight, // aspect
328
+ 0.1, // near
329
+ 1000 // far
330
+ );
331
+ // Position: "0deg 75deg 2m" => we can interpret as an angle from horizontal
332
+ // Place the camera a bit above and away from the origin.
333
+ camera.position.set(0, 2, 2);
334
+ camera.lookAt(0, 0, 0);
335
+
336
+ // 4) ORBIT CONTROLS
337
+ const controls = new OrbitControls(camera, renderer.domElement);
338
+ controls.enableDamping = true;
339
+ controls.dampingFactor = 0.05;
340
+ controls.target.set(0, 0, 0);
341
+
342
+ // 5) LIGHTING (basic environment)
343
+ const ambientLight = new THREE.HemisphereLight(0xffffff, 0x444444, 1.2);
344
+ scene.add(ambientLight);
345
+
346
+ const globalLight = new THREE.AmbientLight(0xffffff, 0.4);
347
+ scene.add(globalLight);
348
+
349
+ const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
350
+ directionalLight.position.set(5, 10, 7.5);
351
+ scene.add(directionalLight);
352
+
353
+ // 6) LOAD THE GLB MODEL (if asset.rendering is not empty)
354
+ if (modelPath) {
355
+ const loader = new GLTFLoader();
356
+ loader.load(modelPath, (gltf) => {
357
+ const model = gltf.scene;
358
+ scene.add(model);
359
+
360
+ // Compute bounding box
361
+ const box = new THREE.Box3().setFromObject(model);
362
+ const size = box.getSize(new THREE.Vector3()).length();
363
+ const center = box.getCenter(new THREE.Vector3());
364
+
365
+ // Adjust camera clipping
366
+ camera.near = size / 100;
367
+ camera.far = size * 100;
368
+ camera.updateProjectionMatrix();
369
+
370
+ // Move camera so the model is nicely framed
371
+ camera.position.copy(center);
372
+ // Move the camera out some distance (play with the multiplier)
373
+ camera.position.x += size;
374
+ camera.position.y += size;
375
+ camera.position.z += size;
376
+ camera.lookAt(center);
377
+
378
+
379
+ controls.target.copy(center);
380
+ controls.update();
381
+ },
382
+ undefined,
383
+ (error) => {
384
+ console.error('Error loading GLB:', error);
385
+ });
386
+ } else {
387
+ const axesHelper = new THREE.AxesHelper(1);
388
+ scene.add(axesHelper);
389
+ }
390
+
391
+ // 7) HANDLE WINDOW RESIZE
392
+ window.addEventListener('resize', onWindowResize, false);
393
+ function onWindowResize() {
394
+ camera.aspect = container.clientWidth / container.clientHeight;
395
+ camera.updateProjectionMatrix();
396
+ renderer.setSize(container.clientWidth, container.clientHeight);
397
+ }
398
+
399
+ // 8) ANIMATE LOOP
400
+ function animate() {
401
+ requestAnimationFrame(animate);
402
+ controls.update();
403
+ renderer.render(scene, camera);
404
+ }
405
+ animate();
406
+
407
+ const arrowObjects = [];
408
+
409
+ //
410
+ // Plot Button
411
+ //
412
+ const plotButton = document.getElementById('plot-btn');
413
+ plotButton.addEventListener('click', function () {
414
+ arrowObjects.forEach(arrow => {
415
+ scene.remove(arrow);
416
+ });
417
+ arrowObjects.length = 0;
418
+
419
+ // Grab sensor forms
420
+ const sensorForms = document.querySelectorAll('.sensor-form');
421
+ sensorForms.forEach((form) => {
422
+ const x = parseFloat(form.querySelector("input[name*='x']").value) || 0;
423
+ const y = parseFloat(form.querySelector("input[name*='y']").value) || 0;
424
+ const z = parseFloat(form.querySelector("input[name*='z']").value) || 0;
425
+ const dx = parseFloat(form.querySelector("input[name*='dx']").value) || 0;
426
+ const dy = parseFloat(form.querySelector("input[name*='dy']").value) || 0;
427
+ const dz = parseFloat(form.querySelector("input[name*='dz']").value) || 0;
428
+
429
+ // Create a direction vector from dx,dy,dz
430
+ const direction = new THREE.Vector3(dx, dy, dz);
431
+ const length = direction.length() || 0.1; // arrow length
432
+ direction.normalize();
433
+
434
+ const origin = new THREE.Vector3(x, y, z);
435
+ const color = 0xff0000;
436
+ const arrow = createArrow(
437
+ origin,
438
+ direction,
439
+ length,
440
+ color,
441
+ 0.3*length, // head length
442
+ 0.2*length, // head width
443
+ 0.1*length // shaft radius
444
+ );
445
+
446
+ scene.add(arrow);
447
+ arrowObjects.push(arrow);
448
+ });
449
+ });
450
+ });
451
+ </script>
452
+ {% endblock javascripts %}
@@ -1,13 +1,14 @@
1
1
  <!DOCTYPE html>
2
2
  <html lang="en">
3
3
  <head>
4
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
4
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5
5
  <title>{% block title %}{% endblock %} | BRACE2</title>
6
6
 
7
7
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
8
8
  <meta name="title" content="BRACE2 - Sign up page">
9
9
  <meta name="author" content="PEER">
10
10
  <meta name="description" content="BRACE2 is a platform for structural health monitoring.">
11
+ <link rel="canonical" href="https://structures.live{{ request.path }}">
11
12
 
12
13
  <!-- Open Graph / Facebook -->
13
14
  <meta property="og:type" content="website">
@@ -44,12 +45,10 @@
44
45
 
45
46
  </head>
46
47
  <body>
47
-
48
48
  {% block content %}{% endblock content %}
49
49
 
50
50
  {% include 'includes/scripts.html' %}
51
51
 
52
- {% block javascripts %}{% endblock javascripts %}
53
-
52
+ {% block javascripts %}{% endblock javascripts %}
54
53
  </body>
55
54
  </html>
@@ -219,7 +219,7 @@ td.left-text{vertical-align:middle}
219
219
  <div class="col-lg-5 order-lg-2 mb-5 mb-lg-0">
220
220
  <h2 class="h1">Digital Twins</h2>
221
221
  <p class="mb-4">The <em>IRiE</em> engine is used to realize high-fidelity digital twins that are backed by
222
- state-of-the-art analysis platforms like <a href="https://pypi.org/project/opensees">OpenSees</a> for nonlinear finite element analysis and <em><a href="https://chrystalchern.github.io/mdof">mdof</a></em> for system identification.</p>
222
+ state-of-the-art analysis platforms like <a href="https://pypi.org/project/sees">OpenSees</a> for nonlinear finite element analysis and <em><a href="https://chrystalchern.github.io/mdof">mdof</a></em> for system identification.</p>
223
223
  </div>
224
224
  <div class="col-lg-4 order-lg-1 card shadow"><img src="{{ ASSETS_ROOT }}/img/twin.png"
225
225
  alt="Digital twins"></div>
@@ -258,7 +258,7 @@ td.left-text{vertical-align:middle}
258
258
  <a href="https://stairlab.berkeley.edu/software/opensees/">
259
259
  <img class="first-column-layout"
260
260
  src="{{ ASSETS_ROOT }}/content_images/brace/opensees.jpg" alt="opensees"></a></td>
261
- <td class=full-center-text><a href="https://pypi.org/project/opensees" >sees</a></td>
261
+ <td class=full-center-text><a href="https://pypi.org/project/sees" >sees</a></td>
262
262
  <td class=left-text>Direct and idiomatic bindings to <a href="https://github.com/claudioperez/OpenSeesRT" >
263
263
  <samp>OpenSeesRT</samp></a> kernel for finite element analysis.</td>
264
264
  </tr>
irie/core/settings.py CHANGED
@@ -100,6 +100,7 @@ TEMPLATES = [
100
100
  "django.contrib.auth.context_processors.auth",
101
101
  "django.contrib.messages.context_processors.messages",
102
102
  "apps.context_processors.cfg_assets_root",
103
+ "irie.apps.context_processors.irie_apps",
103
104
  ],
104
105
  },
105
106
  },
@@ -0,0 +1 @@
1
+ {"1": "State Name", "2": "Highway Agency District", "3": "County Name", "4": "Place Code", "5A": "Record Type", "5B": "Route Signing Prefix Code", "5C": "Designated Level of Service Code", "5D": "Route Number", "5E": "Directional Suffix Code", "6A": "Features Intersected", "7": "Facility Carried By Structure", "8": "Structure Number", "9": "Location", "10": "Inventory Route - Minimum Vertical Clearance", "11": "Mile Point", "12": "Base Highway Network", "13A": "LRS Inventory Route", "13B": "Subroute Number", "16": "Latitude", "17": "Longitude", "19": "Bypass or Detour Length", "20": "Toll Status", "21": "Maintenance Responsibility", "22": "Owner Agency", "26": "Functional Class Of Inventory Route", "27": "Year Built", "28A": "Lanes On the Structure", "28B": "Lanes Under the Structure", "29": "Average Daily Traffic", "30": "Year of Average Daily Traffic", "31": "Design Load Descriptor", "32": "Approach Roadway Width", "33": "Bridge Median Code", "34": "Skew Angle", "35": "Structure Flared", "36A": "Bridge Railings", "36B": "Transitions", "36C": "Approach Guardrail", "36D": "Bridge Guardrail Ends", "37": "Historical Significance Code", "38": "Navigation Control Code", "39": "Navigation Vertical Clearance", "40": "Navigation Horizontal Clearance", "41": "Structure Operational Status Code", "42A": "Type of Service on Bridge Code", "42B": "Type Of Service Under Bridge Code", "43A": "Main Span Material", "43B": "Main Span Design", "44A": "Approach Spans Material", "44B": "Approach Spans Design", "45": "Number of Spans in Main Unit", "46": "Number of Approach Spans", "47": "Inventory Route Total Horizontal Clearance", "48": "Length of Maximum Span", "49": "Structure Length", "50A": "Left Curb/Sidewalk Width", "50B": "Right Curb/Sidewalk Width", "51": "Bridge Roadway Width Curb to Curb", "52": "Deck Width - Out to Out", "53": "Minimum Vertical Clearance Over Bridge Roadway", "54A": "Minimum Vertical Underclearance Reference Feature", "54B": "Minimum Vertical Underclearance", "55A": "Minimum Lateral Underclearance Reference Feature", "55B": "Minimum Lateral Underclearance on Right", "56": "Minimum Lateral Underclearance on Left", "58": "Deck Condition Rating", "59": "Superstructure Condition Rating", "60": "Substructure Condition Rating", "61": "Channel and Channel Protection Condition Rating", "62": "Culverts Condition Rating", "63": "Operating Rating Method Code", "64": "Operating Rating", "65": "Inventory Rating Method Code", "66": "Inventory Rating", "67": "Structural Evaluation Appraisal", "68": "Deck Geometry Appraisal", "69": "Underclearance Appraisal Vertical and Horizontal", "70": "Bridge Posting Code", "71": "Waterway Adequacy Appraisal", "72": "Approach Alignment Appraisal", "75A": "Type of Work Proposed", "75B": "Work Done By", "76": "Length of Structure Improvement", "90": "Inspection Date", "91": "Designated Inspection Frequency", "92A": "Fracture Critical Details", "92B": "Underwater Inspection", "92C": "Other Special Inspection", "93A": "Fracture Critical Detail Date", "93B": "Underwater Inspection Date", "93C": "Other Special Inspection Date", "94": "Bridge Improvement Cost", "95": "Roadway Improvement Cost", "96": "Total Project Cost", "97": "Year of Improvement Cost Estimate", "98A": "Neighboring State Name", "98B": "Neighboring State Percent Responsibility", "99": "Border Bridge Structure Number", "100": "STRAHNET Highway Designation", "101": "Parallel Structure Designation Code", "102": "Direction of Traffic Code", "103": "Temporary Structure Designation Code", "104": "Inventory Route NHS Code", "105": "Federal Lands Highways Code", "106": "Year Reconstructed", "107": "Deck Structure Type Code", "108A": "Wearing Surface Type Code", "108B": "Membrane Type Code", "108C": "Deck Protection Code", "109": "Average Daily Truck Traffic (Percent ADT)", "110": "Designated National Truck Network Code", "111": "Pier Abutment Protection Code", "112": "NBIS Minimum Bridge Length", "113": "Scour Critical Bridge Value", "114": "Future Average Daily Traffic", "115": "Year of Future Average Daily Traffic", "116": "Minimum Vertical Clearance - Lift Bridge", "Computed": "Average Daily Truck Traffic (Volume)", "CAT29": "Deck Area", "CAT10": "Bridge Condition", "CAT23": "Condition Code", "null": "City (InfoBridge Place Code-Name)"}
irie/init/getNBIData.py CHANGED
@@ -12,6 +12,18 @@
12
12
  #
13
13
  # Claudio M. Perez
14
14
  #
15
+ # TODO:
16
+ #
17
+ # - Add option for "SELECTED_TAB": "NBETab",
18
+ #
19
+ # - Perhaps add something like:
20
+ # --filter-calid calids.txt
21
+ # This will be useful for testing, eg, (chrystal's first version)
22
+ # python getNBIData.py yearly.json --filter-calid <(echo "33 0214L")
23
+ #
24
+ # or
25
+ # python getNBIData.py | python getNBIData.py /dev/stdin <(echo "33 0214L")
26
+ #
15
27
  import sys
16
28
  import json
17
29
  import requests
@@ -98,10 +98,14 @@ def load_assets(NBI_DATA):
98
98
 
99
99
  # 1. Collect routes of interest
100
100
  ROUTES = set()
101
- for bridge in BRIDGES.values():
102
- if "calid" not in bridge:
101
+ for calid in CESMD: #BRIDGES.values():
102
+ # if "calid" not in bridge:
103
+ try:
104
+ calid = Asset.objects.get(calid=calid).calid
105
+ except:
103
106
  continue
104
- calid = bridge["calid"].split(" ")[0].replace("-", " ")
107
+
108
+ calid = calid.split(" ")[0].replace("-", " ")
105
109
  nbi = get_nbi(calid, missing_ok=True)
106
110
  if nbi is not None:
107
111
  ROUTES.add(get_route(nbi))
@@ -112,7 +116,7 @@ def load_assets(NBI_DATA):
112
116
  for item in NBI_DATA:
113
117
  calid = item.replace(" ", "-")
114
118
  nbi = get_nbi(item)
115
- config = find_bridge(BRIDGES, calid)
119
+ config = None # find_bridge(BRIDGES, calid)
116
120
  try:
117
121
  if skip(nbi, ROUTES) or item == "33 0726L":
118
122
  continue
@@ -143,9 +147,9 @@ def load_assets(NBI_DATA):
143
147
 
144
148
  count += 1
145
149
 
146
- if config:
147
- asset.bridge_sensors = json.dumps(config["accelerometers"]["bridge_channels"])
148
- asset.ground_sensors = json.dumps(config["accelerometers"]["ground_channels"])
150
+ # if config:
151
+ # asset.bridge_sensors = json.dumps(config["accelerometers"]["bridge_channels"])
152
+ # asset.ground_sensors = json.dumps(config["accelerometers"]["ground_channels"])
149
153
 
150
154
  asset.save()
151
155
 
@@ -13,18 +13,21 @@ with open(DATA/"cgs_data.json") as f:
13
13
 
14
14
  class Command(BaseCommand):
15
15
  def handle(self, *args, **kwargs):
16
- with open(DATA/"cgs-stations.json") as f:
17
- stations = json.load(f)
16
+ # with open(DATA/"cgs-stations.json") as f:
17
+ # stations = json.load(f)
18
18
 
19
19
  count = 0
20
20
  try:
21
- for asset in Asset.objects.all():
22
- if asset.calid not in CESMD:
23
- continue
21
+ for calid, (cesmd, route, name) in CESMD.items():
22
+ try:
23
+ asset = Asset.objects.get(calid=calid)
24
+ except Asset.DoesNotExist:
25
+ asset = Asset()
26
+ asset.is_complete = False
24
27
 
25
- cesmd = CESMD[asset.calid][0]
26
- asset.cesmd = CESMD[asset.calid][0]
27
- asset.name = CESMD[asset.calid][2]
28
+ asset.name = name
29
+ asset.cesmd = cesmd
30
+ asset.calid = calid
28
31
  asset.cgs_data = CGS_DATA.get(cesmd, {})
29
32
  asset.save()
30
33
  print(asset)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: irie
3
- Version: 0.0.35
3
+ Version: 0.0.37
4
4
  Summary: An infrastructure resilience engine
5
5
  Author-email: "Claudio M. Perez" <50180406+claudioperez@users.noreply.github.com>
6
6
  Project-URL: Repository, https://github.com/STAIRLab