-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathapp.py
More file actions
123 lines (89 loc) · 5.08 KB
/
Copy pathapp.py
File metadata and controls
123 lines (89 loc) · 5.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
from typing import Tuple
from viktor import ViktorController
from viktor.parametrization import ViktorParametrization, NumberField
from viktor.views import GeometryAndDataView
from viktor.views import GeometryAndDataResult
from viktor.views import DataItem
from viktor.views import DataGroup
from viktor.views import GeometryResult
from viktor.views import DataResult
from viktor.views import DataView
from viktor.views import GeometryView
from viktor.external.generic import GenericAnalysis
from viktor.external.dynamo import DynamoFile
from viktor.external.dynamo import get_dynamo_result
from viktor.external.dynamo import convert_geometry_to_glb
from viktor.core import File
from pathlib import Path
class Parametrization(ViktorParametrization):
# Input fields
number_of_houses = NumberField("Number of houses", max=8.0, min=1.0, variant='slider', step=1.0, default=3.0)
number_of_floors = NumberField("Number of floors", max=5.0, min=1.0, variant='slider', step=1.0, default=2.0)
depth = NumberField("Depth [m]", max=10.0, min=5.0, variant='slider', step=1.0, default=8.0)
width = NumberField("Width [m]", max=6.0, min=4.0, variant='slider', step=1.0, default=5.0)
height_floor = NumberField("Height floor", max=3.0, min=2.0, variant='slider', step=0.1, default=2.5, suffix='m')
height_roof = NumberField("Height roof", max=3.0, min=2.0, variant='slider', step=0.1, default=2.5, suffix='m')
class Controller(ViktorController):
viktor_enforce_field_constraints = True # Resolves upgrade instruction https://docs.viktor.ai/sdk/upgrades#U83
label = 'Residential Block'
parametrization = Parametrization
@staticmethod
def update_model(params) -> Tuple[File, DynamoFile]:
"""This method updates the nodes of the dynamo file with the parameters
from the parametrization class."""
# First the path to the dynamo file is specified and loaded
file_path = Path(__file__).parent / "dynamo_model_sample_app.dyn"
_file = File.from_path(file_path)
dyn_file = DynamoFile(_file)
# Update dynamo file with parameters from user input
dyn_file.update("Number of houses", params.number_of_houses)
dyn_file.update("Number of floors", params.number_of_floors)
dyn_file.update("Depth", params.depth)
dyn_file.update("Width", params.width)
dyn_file.update("Height floor", params.height_floor)
dyn_file.update("Height roof", params.height_roof)
# generate updated file
input_file = dyn_file.generate()
return input_file, dyn_file
@GeometryAndDataView("Building 3D", duration_guess=5)
def geometry_and_data_view(self, params, **kwargs):
"""The endpoint that initiates the logic to visualize the geometry and data executed
and retrieved from a Dynamo script."""
# Step 1: Update model
input_file, dynamo_file = self.update_model(params)
# Step 2: Running analyses
files = [
('input.dyn', input_file),
]
generic_analysis = GenericAnalysis(files=files, executable_key="dynamo",
output_filenames=["output.xml", "geometry.json"])
generic_analysis.execute(timeout=60)
# Step 3: Processing geometry
geometry_file = generic_analysis.get_output_file('geometry.json', as_file=True)
glb_file = convert_geometry_to_glb(geometry_file)
# Step 4: Process numerical output
output_file = generic_analysis.get_output_file('output.xml', as_file=True)
data_group = self.convert_dynamo_file_to_data_items(dynamo_file, output_file)
return GeometryAndDataResult(geometry=glb_file, data=data_group)
@staticmethod
def convert_dynamo_file_to_data_items(input_file: DynamoFile, output_file: File) -> DataGroup:
"""Extracts the output of the Dynamo results by using the input and output files."""
# Collect ids for the computational output from the dynamo file (numerical output)
output_id_floor_area = input_file.get_node_id("(OUTPUT) Floor area per house")
output_id_total_cost = input_file.get_node_id("(OUTPUT) Total cost")
output_id_mki = input_file.get_node_id("(OUTPUT) MKI")
output_id_co2 = input_file.get_node_id("(OUTPUT) CO2")
# Collect the numerical results from the output file using the collected ids
with output_file.open_binary() as f:
floor_area = get_dynamo_result(f, id_=output_id_floor_area)
total_cost = get_dynamo_result(f, id_=output_id_total_cost)
mki = get_dynamo_result(f, id_=output_id_mki)
co2 = get_dynamo_result(f, id_=output_id_co2)
# Add values to a structured data group
data_group = DataGroup(
DataItem(label="Floor area", value=round(float(floor_area), 2), suffix="m²"),
DataItem(label="Total cost", value=round(float(total_cost), 2), suffix="€"),
DataItem(label="MKI", value=round(float(mki), 2)),
DataItem(label="CO₂ emission", value=round(float(co2), 2), suffix="ton CO₂"),
)
return data_group