irie 0.0.36__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.
- irie/apps/inventory/forms.py +8 -2
- irie/apps/inventory/migrations/0005_alter_sensor_group.py +19 -0
- irie/apps/inventory/migrations/0006_datum_asset_datum_locate_x_datum_locate_y_and_more.py +56 -0
- irie/apps/inventory/migrations/0007_sensor_name.py +19 -0
- irie/apps/inventory/migrations/0008_alter_sensor_dx_alter_sensor_dy_alter_sensor_dz_and_more.py +43 -0
- irie/apps/inventory/models.py +16 -9
- irie/apps/inventory/views.py +12 -5
- irie/apps/templates/inventory/asset-event-summary.html +17 -7
- irie/apps/templates/inventory/asset-profile.html +3 -3
- irie/apps/templates/inventory/asset-sensors.html +31 -12
- irie/apps/templates/inventory/sensor-upload.html +353 -20
- irie/apps/templates/layouts/base-fullscreen.html +3 -4
- irie/apps/templates/site/index.html +2 -2
- {irie-0.0.36.dist-info → irie-0.0.37.dist-info}/METADATA +1 -1
- {irie-0.0.36.dist-info → irie-0.0.37.dist-info}/RECORD +18 -14
- {irie-0.0.36.dist-info → irie-0.0.37.dist-info}/WHEEL +1 -1
- {irie-0.0.36.dist-info → irie-0.0.37.dist-info}/entry_points.txt +0 -0
- {irie-0.0.36.dist-info → irie-0.0.37.dist-info}/top_level.txt +0 -0
irie/apps/inventory/forms.py
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
#===----------------------------------------------------------------------===#
|
|
6
6
|
from django import forms
|
|
7
7
|
from django.forms import formset_factory
|
|
8
|
-
from irie.apps.inventory.models import Asset, SensorGroup, Sensor
|
|
8
|
+
from irie.apps.inventory.models import Asset, SensorGroup, Sensor, Datum
|
|
9
9
|
|
|
10
10
|
class AssetForm(forms.ModelForm):
|
|
11
11
|
class Meta:
|
|
@@ -16,12 +16,18 @@ class SensorGroupForm(forms.ModelForm):
|
|
|
16
16
|
class Meta:
|
|
17
17
|
model = SensorGroup
|
|
18
18
|
fields = ['name', 'datum']
|
|
19
|
+
|
|
20
|
+
def __init__(self, *args, asset=None, **kwargs):
|
|
21
|
+
super().__init__(*args, **kwargs)
|
|
22
|
+
if asset:
|
|
23
|
+
self.fields['datum'].queryset = Datum.objects.filter(asset=asset)
|
|
19
24
|
|
|
20
25
|
class SensorForm(forms.ModelForm):
|
|
21
26
|
class Meta:
|
|
22
27
|
model = Sensor
|
|
23
|
-
fields = ['x', 'y', 'z', 'dx', 'dy', 'dz']
|
|
28
|
+
fields = ['name', 'x', 'y', 'z', 'dx', 'dy', 'dz']
|
|
24
29
|
labels = {
|
|
30
|
+
'name': 'Name',
|
|
25
31
|
'x': 'x',
|
|
26
32
|
'y': 'y',
|
|
27
33
|
'z': 'z',
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Generated by Django 5.1.2 on 2025-02-25 04:49
|
|
2
|
+
|
|
3
|
+
import django.db.models.deletion
|
|
4
|
+
from django.db import migrations, models
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Migration(migrations.Migration):
|
|
8
|
+
|
|
9
|
+
dependencies = [
|
|
10
|
+
('irie_apps_inventory', '0004_datum_sensorgroup_sensor'),
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
operations = [
|
|
14
|
+
migrations.AlterField(
|
|
15
|
+
model_name='sensor',
|
|
16
|
+
name='group',
|
|
17
|
+
field=models.ForeignKey(on_delete=django.db.models.deletion.RESTRICT, related_name='sensors', to='irie_apps_inventory.sensorgroup'),
|
|
18
|
+
),
|
|
19
|
+
]
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Generated by Django 5.1.2 on 2025-02-25 05:07
|
|
2
|
+
|
|
3
|
+
import django.db.models.deletion
|
|
4
|
+
from django.db import migrations, models
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Migration(migrations.Migration):
|
|
8
|
+
|
|
9
|
+
dependencies = [
|
|
10
|
+
('irie_apps_inventory', '0005_alter_sensor_group'),
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
operations = [
|
|
14
|
+
migrations.AddField(
|
|
15
|
+
model_name='datum',
|
|
16
|
+
name='asset',
|
|
17
|
+
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.RESTRICT, to='irie_apps_inventory.asset'),
|
|
18
|
+
preserve_default=False,
|
|
19
|
+
),
|
|
20
|
+
migrations.AddField(
|
|
21
|
+
model_name='datum',
|
|
22
|
+
name='locate_x',
|
|
23
|
+
field=models.CharField(default=0, max_length=240),
|
|
24
|
+
preserve_default=False,
|
|
25
|
+
),
|
|
26
|
+
migrations.AddField(
|
|
27
|
+
model_name='datum',
|
|
28
|
+
name='locate_y',
|
|
29
|
+
field=models.CharField(default=0, max_length=240),
|
|
30
|
+
preserve_default=False,
|
|
31
|
+
),
|
|
32
|
+
migrations.AddField(
|
|
33
|
+
model_name='datum',
|
|
34
|
+
name='locate_z',
|
|
35
|
+
field=models.CharField(default=0, max_length=240),
|
|
36
|
+
preserve_default=False,
|
|
37
|
+
),
|
|
38
|
+
migrations.AddField(
|
|
39
|
+
model_name='datum',
|
|
40
|
+
name='orient_x',
|
|
41
|
+
field=models.CharField(default=0, max_length=240),
|
|
42
|
+
preserve_default=False,
|
|
43
|
+
),
|
|
44
|
+
migrations.AddField(
|
|
45
|
+
model_name='datum',
|
|
46
|
+
name='orient_y',
|
|
47
|
+
field=models.CharField(default=0, max_length=240),
|
|
48
|
+
preserve_default=False,
|
|
49
|
+
),
|
|
50
|
+
migrations.AddField(
|
|
51
|
+
model_name='datum',
|
|
52
|
+
name='orient_z',
|
|
53
|
+
field=models.CharField(default=0, max_length=240),
|
|
54
|
+
preserve_default=False,
|
|
55
|
+
),
|
|
56
|
+
]
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Generated by Django 5.1.2 on 2025-02-26 03:21
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
|
|
8
|
+
dependencies = [
|
|
9
|
+
('irie_apps_inventory', '0006_datum_asset_datum_locate_x_datum_locate_y_and_more'),
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
operations = [
|
|
13
|
+
migrations.AddField(
|
|
14
|
+
model_name='sensor',
|
|
15
|
+
name='name',
|
|
16
|
+
field=models.CharField(default=1, max_length=100),
|
|
17
|
+
preserve_default=False,
|
|
18
|
+
),
|
|
19
|
+
]
|
irie/apps/inventory/migrations/0008_alter_sensor_dx_alter_sensor_dy_alter_sensor_dz_and_more.py
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Generated by Django 5.1.2 on 2025-02-26 07:05
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
|
|
8
|
+
dependencies = [
|
|
9
|
+
('irie_apps_inventory', '0007_sensor_name'),
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
operations = [
|
|
13
|
+
migrations.AlterField(
|
|
14
|
+
model_name='sensor',
|
|
15
|
+
name='dx',
|
|
16
|
+
field=models.DecimalField(decimal_places=2, max_digits=10),
|
|
17
|
+
),
|
|
18
|
+
migrations.AlterField(
|
|
19
|
+
model_name='sensor',
|
|
20
|
+
name='dy',
|
|
21
|
+
field=models.DecimalField(decimal_places=2, max_digits=10),
|
|
22
|
+
),
|
|
23
|
+
migrations.AlterField(
|
|
24
|
+
model_name='sensor',
|
|
25
|
+
name='dz',
|
|
26
|
+
field=models.DecimalField(decimal_places=2, max_digits=10),
|
|
27
|
+
),
|
|
28
|
+
migrations.AlterField(
|
|
29
|
+
model_name='sensor',
|
|
30
|
+
name='x',
|
|
31
|
+
field=models.DecimalField(decimal_places=2, max_digits=10),
|
|
32
|
+
),
|
|
33
|
+
migrations.AlterField(
|
|
34
|
+
model_name='sensor',
|
|
35
|
+
name='y',
|
|
36
|
+
field=models.DecimalField(decimal_places=2, max_digits=10),
|
|
37
|
+
),
|
|
38
|
+
migrations.AlterField(
|
|
39
|
+
model_name='sensor',
|
|
40
|
+
name='z',
|
|
41
|
+
field=models.DecimalField(decimal_places=2, max_digits=10),
|
|
42
|
+
),
|
|
43
|
+
]
|
irie/apps/inventory/models.py
CHANGED
|
@@ -104,12 +104,18 @@ class Vulnerability: # (models.Model):
|
|
|
104
104
|
|
|
105
105
|
class Datum(models.Model):
|
|
106
106
|
name = models.CharField(max_length=100)
|
|
107
|
+
orient_x = models.CharField(max_length=240) # eg, longitudinal axis of the deck from west to east
|
|
108
|
+
locate_x = models.CharField(max_length=240) # eg, east abutment-to-deck interface
|
|
109
|
+
orient_y = models.CharField(max_length=240) # eg, transverse axis of the deck from north to south
|
|
110
|
+
locate_y = models.CharField(max_length=240) # eg, center of deck
|
|
111
|
+
orient_z = models.CharField(max_length=240) # eg, vertical upwards
|
|
112
|
+
locate_z = models.CharField(max_length=240) # eg, deck surface
|
|
113
|
+
asset = models.ForeignKey(Asset, on_delete=models.RESTRICT)
|
|
114
|
+
|
|
107
115
|
def __str__(self):
|
|
108
116
|
return f"{self.name}"
|
|
109
117
|
|
|
110
118
|
class SensorGroup(models.Model):
|
|
111
|
-
"""
|
|
112
|
-
"""
|
|
113
119
|
name = models.CharField(max_length=100)
|
|
114
120
|
# sensors; access with .sensor_set.all()
|
|
115
121
|
asset = models.ForeignKey(Asset, on_delete=models.RESTRICT)
|
|
@@ -123,15 +129,16 @@ class Sensor(models.Model):
|
|
|
123
129
|
# class Status:
|
|
124
130
|
# active: bool
|
|
125
131
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
132
|
+
name = models.CharField(max_length=100)
|
|
133
|
+
x = models.DecimalField(decimal_places=2, max_digits=10)
|
|
134
|
+
y = models.DecimalField(decimal_places=2, max_digits=10)
|
|
135
|
+
z = models.DecimalField(decimal_places=2, max_digits=10)
|
|
129
136
|
|
|
130
|
-
dx = models.
|
|
131
|
-
dy = models.
|
|
132
|
-
dz = models.
|
|
137
|
+
dx = models.DecimalField(decimal_places=2, max_digits=10)
|
|
138
|
+
dy = models.DecimalField(decimal_places=2, max_digits=10)
|
|
139
|
+
dz = models.DecimalField(decimal_places=2, max_digits=10)
|
|
133
140
|
|
|
134
141
|
group = models.ForeignKey(SensorGroup, related_name="sensors", on_delete=models.RESTRICT)
|
|
135
142
|
|
|
136
143
|
def __str__(self):
|
|
137
|
-
return f"
|
|
144
|
+
return f"{self.name} ({self.group.name})"
|
irie/apps/inventory/views.py
CHANGED
|
@@ -22,7 +22,7 @@ from django.forms import formset_factory
|
|
|
22
22
|
|
|
23
23
|
from irie.apps.events.models import EventRecord
|
|
24
24
|
from irie.apps.site.view_utils import raise404
|
|
25
|
-
from irie.apps.inventory.models import Asset, SensorGroup, Sensor
|
|
25
|
+
from irie.apps.inventory.models import Asset, SensorGroup, Sensor, Datum
|
|
26
26
|
from irie.apps.inventory.forms import SensorGroupForm, SensorForm, SensorFormSet
|
|
27
27
|
from .filters import AssetFilter
|
|
28
28
|
# Predictors
|
|
@@ -318,7 +318,10 @@ def _make_tables(asset):
|
|
|
318
318
|
} for group in asset.nbi_data.values()
|
|
319
319
|
]
|
|
320
320
|
tables.extend(nbi_data)
|
|
321
|
-
|
|
321
|
+
try:
|
|
322
|
+
tables = [tables[2], *tables[:2], *tables[3:]]
|
|
323
|
+
except:
|
|
324
|
+
pass
|
|
322
325
|
condition = {}
|
|
323
326
|
for table in tables:
|
|
324
327
|
keys = set()
|
|
@@ -355,10 +358,13 @@ def asset_sensors(request, calid):
|
|
|
355
358
|
@login_required(login_url="/login/")
|
|
356
359
|
def sensor_upload(request, calid):
|
|
357
360
|
asset = get_object_or_404(Asset, calid=calid) # Fetch the asset using calid
|
|
361
|
+
datums = Datum.objects.filter(asset=asset).values(
|
|
362
|
+
'id', 'orient_x', 'locate_x', 'orient_y', 'locate_y', 'orient_z', 'locate_z'
|
|
363
|
+
)
|
|
358
364
|
SensorFormSet = formset_factory(SensorForm, extra=1, can_delete=False)
|
|
359
365
|
|
|
360
366
|
if request.method == "POST":
|
|
361
|
-
group_form = SensorGroupForm(request.POST)
|
|
367
|
+
group_form = SensorGroupForm(request.POST, asset=asset)
|
|
362
368
|
formset = SensorFormSet(request.POST)
|
|
363
369
|
|
|
364
370
|
if group_form.is_valid() and formset.is_valid():
|
|
@@ -375,13 +381,14 @@ def sensor_upload(request, calid):
|
|
|
375
381
|
return redirect('asset_sensors', calid=calid) # Redirect after successful submission
|
|
376
382
|
|
|
377
383
|
else:
|
|
378
|
-
group_form = SensorGroupForm()
|
|
384
|
+
group_form = SensorGroupForm(asset=asset)
|
|
379
385
|
formset = SensorFormSet()
|
|
380
386
|
|
|
381
387
|
return render(request, "inventory/sensor-upload.html", {
|
|
382
388
|
"group_form": group_form,
|
|
383
389
|
"formset": formset,
|
|
384
|
-
"asset": asset
|
|
390
|
+
"asset": asset,
|
|
391
|
+
"datums": list(datums)
|
|
385
392
|
})
|
|
386
393
|
|
|
387
394
|
|
|
@@ -6,6 +6,10 @@
|
|
|
6
6
|
{% endblock %}
|
|
7
7
|
|
|
8
8
|
{% block stylesheets %}
|
|
9
|
+
{% if asset.rendering %}
|
|
10
|
+
<!-- <meta name="viewport" content="width=device-width, initial-scale=1.0"> -->
|
|
11
|
+
<script type="module" src="https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js"></script>
|
|
12
|
+
{% endif %}
|
|
9
13
|
<style>
|
|
10
14
|
.ct-series-a .ct-point, .ct-series-a .ct-line, .ct-series-a .ct-bar, .ct-series-a .ct-slice-donut{
|
|
11
15
|
stroke: #506690;
|
|
@@ -60,15 +64,21 @@
|
|
|
60
64
|
<div class="tab-content" id="pills-tabContent">
|
|
61
65
|
<div class="tab-pane fade show active"
|
|
62
66
|
id="pills-rendering" role="tabpanel">
|
|
63
|
-
{% if asset.
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
{% if asset.rendering %}
|
|
68
|
+
<model-viewer
|
|
69
|
+
id="viewer"
|
|
70
|
+
src="{{ asset.rendering }}"
|
|
71
|
+
alt="3D Model"
|
|
72
|
+
auto-rotate
|
|
73
|
+
camera-controls
|
|
74
|
+
interaction-prompt="none"
|
|
75
|
+
camera-orbit="0deg 75deg 2m"
|
|
76
|
+
field-of-view="30deg"
|
|
77
|
+
style="width: 100%; height: 400px;">
|
|
78
|
+
</model-viewer>
|
|
69
79
|
{% endif %}
|
|
70
80
|
</div>
|
|
71
|
-
<div class="tab-pane fade show {% if not asset.
|
|
81
|
+
<div class="tab-pane fade show {% if not asset.rendering %}active{% endif %}"
|
|
72
82
|
id="pills-sensors" role="tabpanel">
|
|
73
83
|
<img src="{{ ASSETS_ROOT }}/inventory/ll{{ asset.cesmd|slice:"2:" }}.svg">
|
|
74
84
|
</div>
|
|
@@ -129,7 +129,7 @@
|
|
|
129
129
|
<div class="btn-toolbar mb-2 mb-md-0">
|
|
130
130
|
<a role="button"
|
|
131
131
|
href="/inventory/{{ asset.calid }}/predictors/"
|
|
132
|
-
class="btn btn-sm btn-outline-primary d-inline-flex align-items-center">
|
|
132
|
+
class="btn btn-sm btn-outline-primary d-inline-flex align-items-center mx-1">
|
|
133
133
|
<svg class="icon icon-xs me-2" fill="none"
|
|
134
134
|
stroke="currentColor" viewBox="0 0 24 24"
|
|
135
135
|
xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6"></path></svg>
|
|
@@ -137,7 +137,7 @@
|
|
|
137
137
|
</a>
|
|
138
138
|
<a role="button"
|
|
139
139
|
href="{% url 'asset_sensors' calid=asset.calid %}"
|
|
140
|
-
class="btn btn-sm btn-outline-primary d-inline-flex align-items-center">
|
|
140
|
+
class="btn btn-sm btn-outline-primary d-inline-flex align-items-center mx-1">
|
|
141
141
|
<svg class="icon icon-xs me-2" fill="none"
|
|
142
142
|
stroke="currentColor" viewBox="0 0 24 24"
|
|
143
143
|
xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6"></path></svg>
|
|
@@ -145,7 +145,7 @@
|
|
|
145
145
|
</a>
|
|
146
146
|
</div>
|
|
147
147
|
</div>
|
|
148
|
-
{% if
|
|
148
|
+
{% if asset.nbi_data.NBI_BRIDGE %}
|
|
149
149
|
<div class="col-10">
|
|
150
150
|
<p>
|
|
151
151
|
{% if asset.id|divisibleby:3 %}
|
|
@@ -22,20 +22,39 @@ Chrystal Chern, Spring 2025
|
|
|
22
22
|
href="{% url 'sensor_upload' calid=asset.calid %}" class="me-1">Add SensorGroup</a>
|
|
23
23
|
</div>
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
<div class="col-10">
|
|
25
|
+
<div class="col-lg-10">
|
|
27
26
|
{% for group in groups %}
|
|
28
|
-
<div class="card">
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
</
|
|
27
|
+
<div class="card shadow-lg mb-4">
|
|
28
|
+
<div class="card-header bg-dark text-white fw-bold d-flex justify-content-between align-items-center">
|
|
29
|
+
<span>{{ group.name }}</span>
|
|
30
|
+
<span class="badge bg-gray text-white px-2 py-1 fs-6">Datum: {{ group.datum.name }}</span>
|
|
31
|
+
</div>
|
|
32
32
|
<div class="card-body">
|
|
33
|
-
<table>
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
<
|
|
37
|
-
|
|
38
|
-
|
|
33
|
+
<table class="table table-striped table-hover table-bordered">
|
|
34
|
+
<thead class="table-dark">
|
|
35
|
+
<tr>
|
|
36
|
+
<th>Sensor</th>
|
|
37
|
+
<th>x</th>
|
|
38
|
+
<th>y</th>
|
|
39
|
+
<th>z</th>
|
|
40
|
+
<th>dx</th>
|
|
41
|
+
<th>dy</th>
|
|
42
|
+
<th>dz</th>
|
|
43
|
+
</tr>
|
|
44
|
+
</thead>
|
|
45
|
+
<tbody>
|
|
46
|
+
{% for sensor in group.sensors.all %}
|
|
47
|
+
<tr>
|
|
48
|
+
<td class="fw-bold">{{ sensor.name }}</td>
|
|
49
|
+
<td>{{ sensor.x }}</td>
|
|
50
|
+
<td>{{ sensor.y }}</td>
|
|
51
|
+
<td>{{ sensor.z }}</td>
|
|
52
|
+
<td>{{ sensor.dx }}</td>
|
|
53
|
+
<td>{{ sensor.dy }}</td>
|
|
54
|
+
<td>{{ sensor.dz }}</td>
|
|
55
|
+
</tr>
|
|
56
|
+
{% endfor %}
|
|
57
|
+
</tbody>
|
|
39
58
|
</table>
|
|
40
59
|
</div>
|
|
41
60
|
</div>
|
|
@@ -9,18 +9,57 @@ Chrystal Chern, Spring 2025
|
|
|
9
9
|
|
|
10
10
|
-->
|
|
11
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
|
+
|
|
12
35
|
{% block title %} Add Sensor Group to {{ asset.calid }} {% endblock %}
|
|
13
36
|
|
|
14
37
|
{% block content %}
|
|
15
|
-
|
|
16
38
|
<h1>Add Sensor Group to <code>{{ asset.calid }}</code></h1>
|
|
17
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" >
|
|
18
53
|
<form method="post">
|
|
19
54
|
{% csrf_token %}
|
|
20
55
|
|
|
21
|
-
<fieldset>
|
|
56
|
+
<fieldset class="mb-4">
|
|
22
57
|
<legend>Sensor Group</legend>
|
|
23
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>
|
|
24
63
|
</fieldset>
|
|
25
64
|
|
|
26
65
|
<fieldset>
|
|
@@ -28,30 +67,39 @@ Chrystal Chern, Spring 2025
|
|
|
28
67
|
{{ formset.management_form }}
|
|
29
68
|
<div id="formset-container" class="container">
|
|
30
69
|
{% for form in formset %}
|
|
31
|
-
<div class="sensor-form">
|
|
32
|
-
<div class="row
|
|
70
|
+
<div class="sensor-form mb-4">
|
|
71
|
+
<div class="row mb-3">
|
|
33
72
|
<div class="input-group">
|
|
34
|
-
<span class="input-group-text col-md-2">{{ form.
|
|
35
|
-
<input id="{{form.
|
|
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>
|
|
36
75
|
</div>
|
|
76
|
+
</div>
|
|
77
|
+
<div class="row"><div class="col-md-12 d-flex align-items-center mb-3">
|
|
37
78
|
<div class="input-group">
|
|
38
|
-
<span class="input-group-text col-md-
|
|
39
|
-
<input id="{{form.
|
|
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>
|
|
40
81
|
</div>
|
|
41
82
|
<div class="input-group">
|
|
42
|
-
<span class="input-group-text col-md-
|
|
43
|
-
<input id="{{form.
|
|
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>
|
|
44
89
|
</div>
|
|
45
90
|
</div></div>
|
|
46
|
-
<div class="row"><div class="col-md-
|
|
47
|
-
<div class="
|
|
48
|
-
|
|
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>
|
|
49
95
|
</div>
|
|
50
|
-
<div class="
|
|
51
|
-
|
|
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>
|
|
52
99
|
</div>
|
|
53
|
-
<div class="
|
|
54
|
-
|
|
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>
|
|
55
103
|
</div>
|
|
56
104
|
</div></div>
|
|
57
105
|
|
|
@@ -60,14 +108,91 @@ Chrystal Chern, Spring 2025
|
|
|
60
108
|
{% endfor %}
|
|
61
109
|
</div>
|
|
62
110
|
|
|
63
|
-
<button id="add-form" class="btn btn-sm button btn-outline-
|
|
111
|
+
<button id="add-form" class="btn btn-sm button btn-outline-primary mb-3">Add Sensor</button>
|
|
64
112
|
</fieldset>
|
|
113
|
+
|
|
114
|
+
<button type="button" id="plot-btn" class="btn btn-info btn-sm mb-3">Plot</button>
|
|
65
115
|
|
|
66
|
-
<button type="submit" class="btn btn-sm button btn-success
|
|
116
|
+
<button type="submit" class="btn btn-sm button btn-success mb-3">Submit</button>
|
|
67
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> -->
|
|
68
192
|
{%endblock content %}
|
|
69
|
-
{% block javascripts %}
|
|
70
193
|
|
|
194
|
+
|
|
195
|
+
{% block javascripts %}
|
|
71
196
|
<script>
|
|
72
197
|
document.addEventListener("DOMContentLoaded", () => {
|
|
73
198
|
const formsetContainer = document.getElementById("formset-container");
|
|
@@ -116,4 +241,212 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
116
241
|
updateRemoveButtons();
|
|
117
242
|
});
|
|
118
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>
|
|
119
452
|
{% endblock javascripts %}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
2
|
<html lang="en">
|
|
3
3
|
<head>
|
|
4
|
-
|
|
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/
|
|
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/
|
|
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>
|
|
@@ -62,18 +62,22 @@ irie/apps/inventory/apps.py,sha256=bZ6qYIwPMG4_4IeLfg9N4WuZAEgEVj84oOswV-7_MAI,4
|
|
|
62
62
|
irie/apps/inventory/calid.py,sha256=3L8MbPIGOE3kzDnqeyY055pRBiF2O2l0cmpuDbTsdTg,3014
|
|
63
63
|
irie/apps/inventory/fields.py,sha256=J3nTImPsuCeiOWBizSL4tnuKs36sPfXALNTKEZY-wVg,79
|
|
64
64
|
irie/apps/inventory/filters.py,sha256=8ge94J5OlGhLRIo6EtBYVe2c9QxW7YCBLxJzfoFHzSg,2185
|
|
65
|
-
irie/apps/inventory/forms.py,sha256=
|
|
66
|
-
irie/apps/inventory/models.py,sha256=
|
|
65
|
+
irie/apps/inventory/forms.py,sha256=y8tcIGInXDg7KCf1OWd1jtc4umJsm8rf8-4O8nDhNd4,1244
|
|
66
|
+
irie/apps/inventory/models.py,sha256=sYDGpFK41Ga7JXvD5kV6hLc4zr77XFqu7t9IHHO86dQ,5424
|
|
67
67
|
irie/apps/inventory/sitemaps.py,sha256=Nha1MTsIH_ad7JyoxwonPytp7MNuEhDNszkEUOmlN0o,826
|
|
68
68
|
irie/apps/inventory/tables.py,sha256=vZdPOcbN1ibuWXqLwbBUoQw9iavwa1GJ5fd83k8bu7Y,27874
|
|
69
69
|
irie/apps/inventory/traffic.py,sha256=B3PHqn2Pm4AEdUZ_tuA16fuFruo2rm5waMBwLQyF-9g,4490337
|
|
70
70
|
irie/apps/inventory/urls.py,sha256=bH63Y2jk-DzDDTiFdCDb5YLXFvq3sRyJrMAz0z_niKs,1476
|
|
71
|
-
irie/apps/inventory/views.py,sha256=
|
|
71
|
+
irie/apps/inventory/views.py,sha256=riKKJjTWBJScn_VAvh2krvbZgNHZv0lDdY5GJQ1A3Zk,19396
|
|
72
72
|
irie/apps/inventory/archive/arcGIS.py,sha256=vcfsy1be4edOXD1Z3rkUnq9QmCTol7dypdF816Q3B_w,34893
|
|
73
73
|
irie/apps/inventory/migrations/0001_initial.py,sha256=PwTHv4Q3gqWFha--8Zp9kUOh-cYalB14jXj7RVJUVnw,1786
|
|
74
74
|
irie/apps/inventory/migrations/0002_alter_asset_bridge_sensors_and_more.py,sha256=rPzWHkjg-ZCorVA_gv6MVb5F6LTLHcwlPwhBR1PxVr0,842
|
|
75
75
|
irie/apps/inventory/migrations/0003_asset_notes.py,sha256=N3p8PdRlwlED7z5gPAVVcDVsAjSLx-e0D4bx5eEwGlQ,436
|
|
76
76
|
irie/apps/inventory/migrations/0004_datum_sensorgroup_sensor.py,sha256=Jk_GdHN33ymWM6As1K95WC5JPdMg4bLNdWunVw6vEm4,1712
|
|
77
|
+
irie/apps/inventory/migrations/0005_alter_sensor_group.py,sha256=fW_qIR78n0UkxKmCFpQIPhOtXUgXeBax9drZTzIiwJ0,530
|
|
78
|
+
irie/apps/inventory/migrations/0006_datum_asset_datum_locate_x_datum_locate_y_and_more.py,sha256=yCjupVpwQ1qof3grjCo7wL3wIRJWWnMatlPPR1wrMXA,1738
|
|
79
|
+
irie/apps/inventory/migrations/0007_sensor_name.py,sha256=b98wYN1XApHniMkTvrgvTjtxiSlzt966QMMftMzpNZA,474
|
|
80
|
+
irie/apps/inventory/migrations/0008_alter_sensor_dx_alter_sensor_dy_alter_sensor_dz_and_more.py,sha256=y99Ro9cTl9UphgVeILO7YIEVQ1wi0k2RhXqYnBg_ZzY,1255
|
|
77
81
|
irie/apps/inventory/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
78
82
|
irie/apps/inventory/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
79
83
|
irie/apps/inventory/templatetags/get.py,sha256=ZVjFYv1uhjhcOQ8I5ukz7DuR6TXnbYuijPWKkgxacOM,134
|
|
@@ -391,17 +395,17 @@ irie/apps/templates/includes/scripts.html,sha256=1Up6xJJSTpdLTJp0tDAa3JubevvSlic
|
|
|
391
395
|
irie/apps/templates/includes/settings-box.html,sha256=_YubYOyAJ8IldTgVlXP2wLLXpKpInp8hJ88FN6i6rmw,2488
|
|
392
396
|
irie/apps/templates/includes/sidebar.html,sha256=m2TahYwFnysqcLkK4ANYZhUf8xGVId_tiJFBKrQD4Cw,12386
|
|
393
397
|
irie/apps/templates/inventory/asset-evals.html,sha256=KzbdJJ7ildMpfO4IQDuXqGBcPzUTlYpJ_Y3Wg4payVc,2700
|
|
394
|
-
irie/apps/templates/inventory/asset-event-summary.html,sha256=
|
|
395
|
-
irie/apps/templates/inventory/asset-profile.html,sha256=
|
|
396
|
-
irie/apps/templates/inventory/asset-sensors.html,sha256=
|
|
398
|
+
irie/apps/templates/inventory/asset-event-summary.html,sha256=5G7uZVf7kVL0wBaAfsEtTEEA5HRuBCzx8NrgDFheWI4,51357
|
|
399
|
+
irie/apps/templates/inventory/asset-profile.html,sha256=K7D1D-ApjyEV05AyYxGnGs6B0sNq11jKusdPDwubmFA,14135
|
|
400
|
+
irie/apps/templates/inventory/asset-sensors.html,sha256=Ugfdc79WqrHDvzAPi2o8HkjYz5nD7w5S5wZSknQNjxA,2184
|
|
397
401
|
irie/apps/templates/inventory/asset-table.html,sha256=Ak_N_QDUgWzyffBBidJ8H0wLR3zX3wNHQm6MnZYbruQ,12589
|
|
398
402
|
irie/apps/templates/inventory/bridge-dashboard.html,sha256=67zrDlih3LOi9xFVwPVZZkgRT3DO-lE_qRL7q8Uz9GY,45472
|
|
399
403
|
irie/apps/templates/inventory/bridge.html,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
400
404
|
irie/apps/templates/inventory/dashboard.html,sha256=_qhFiPP6xN-UzZj5NuM5e9NxsgDHJkQ89oXN1cBwhj0,7505
|
|
401
405
|
irie/apps/templates/inventory/preamble.tex,sha256=TmRhIWg2-Pxj_e2OBctANRZPwU8RWMT3EZJFSa3R8HY,3547
|
|
402
406
|
irie/apps/templates/inventory/report.tex,sha256=A1XKpwknlBrAZjFzzxVIDwypjXteqzoCQiuo1tQANfw,45228
|
|
403
|
-
irie/apps/templates/inventory/sensor-upload.html,sha256=
|
|
404
|
-
irie/apps/templates/layouts/base-fullscreen.html,sha256=
|
|
407
|
+
irie/apps/templates/inventory/sensor-upload.html,sha256=w-stoKgcEoonoV-_7IFJUrQ6w2Ww5DTErWNzbO5R_-g,18285
|
|
408
|
+
irie/apps/templates/layouts/base-fullscreen.html,sha256=q1nKewLnQ8inBxsUcHlq2Iv_s_qrw6k6bumX7mLR1mI,2579
|
|
405
409
|
irie/apps/templates/layouts/base.html,sha256=phiHZX_CjuOhmkJgqyMAGTPdwm0qqrJCKZZwKLGTtQY,2387
|
|
406
410
|
irie/apps/templates/layouts/json-form.html,sha256=cT6Pd2168Z3p8RODS7SulUC79LnuzSs0EVLVxkGOXAo,1333
|
|
407
411
|
irie/apps/templates/networks/corridor_table.html,sha256=SW6WMmxGsw2li1BXqvCRj1CFJ3IPUulfk-KHJBIMFx0,876
|
|
@@ -419,7 +423,7 @@ irie/apps/templates/prediction/hazus/history.js,sha256=blHRXzlEfMBCezPE-2dZCpt2r
|
|
|
419
423
|
irie/apps/templates/site/about.html,sha256=5hS5taj3XF-F8z-uIn53ZFXVHVS4apLRMg39OyvMvRs,610
|
|
420
424
|
irie/apps/templates/site/asset_map.html,sha256=rnTjeYMc8NESIo6Uuq8fgZ_xcKNuKdt4zcqoUTDI8Xg,387
|
|
421
425
|
irie/apps/templates/site/components-forms.html,sha256=FKOiR-3e9iw-xOHeaP2RB3O2gP10R-Mt8wdXfb1rDBQ,13865
|
|
422
|
-
irie/apps/templates/site/index.html,sha256=
|
|
426
|
+
irie/apps/templates/site/index.html,sha256=Sat1nNPmc1lR4qxpiMnYyPBHI3h1K7PN8GDg901Eiew,16980
|
|
423
427
|
irie/apps/templates/site/json-form.html,sha256=ZrRWy5xnGBOqG51b6mdVGI0Io5X1z47DTFB9wW6ZQYA,1785
|
|
424
428
|
irie/apps/templates/site/page-403.html,sha256=caU6t3fsCJiAIuZvRQekK2UemdZSNxc3l80ceSz0mp0,1289
|
|
425
429
|
irie/apps/templates/site/page-404-sidebar.html,sha256=krMA-iYHaJNfXSwY7H_epZycWLiIb_bBbuWTmqC4ca4,1581
|
|
@@ -465,8 +469,8 @@ irie/init/management/commands/init_corridors.py,sha256=EzLk0HUiFxlco-2u0rypewOc9
|
|
|
465
469
|
irie/init/management/commands/init_predictors.py,sha256=jdD7rd8l2qxuUuR5GOYuHXp-ZQkAK477TefksBMdlOw,2362
|
|
466
470
|
irie/rest/__main__.py,sha256=6Nf_-Rr9zGmMyp_wqCFDO7ls9QPnPd9UyUgN17rIGYw,3680
|
|
467
471
|
irie/usgs/__main__.py,sha256=HiSvPn5IW5IqRiCk1qRRq5dCy3-7iISw7v1P_w2rLrk,5049
|
|
468
|
-
irie-0.0.
|
|
469
|
-
irie-0.0.
|
|
470
|
-
irie-0.0.
|
|
471
|
-
irie-0.0.
|
|
472
|
-
irie-0.0.
|
|
472
|
+
irie-0.0.37.dist-info/METADATA,sha256=XvXazQgq6UwvY3TfdB8ymOG1UUkrkwoBNbK92HmwUOg,3207
|
|
473
|
+
irie-0.0.37.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
|
|
474
|
+
irie-0.0.37.dist-info/entry_points.txt,sha256=A_3h9wPBGfxGQ78_MGa-nO6Z0foxOYeAnIE47jxEztg,44
|
|
475
|
+
irie-0.0.37.dist-info/top_level.txt,sha256=zVCxi5E2nkISZPzKq8VEhWe_dGuPcefLYV1tYqQdwlY,5
|
|
476
|
+
irie-0.0.37.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|