honeybee-radiance-postprocess 0.4.555__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.
- honeybee_radiance_postprocess/__init__.py +1 -0
- honeybee_radiance_postprocess/__main__.py +4 -0
- honeybee_radiance_postprocess/annual.py +73 -0
- honeybee_radiance_postprocess/annualdaylight.py +289 -0
- honeybee_radiance_postprocess/annualirradiance.py +35 -0
- honeybee_radiance_postprocess/breeam/__init__.py +1 -0
- honeybee_radiance_postprocess/breeam/breeam.py +552 -0
- honeybee_radiance_postprocess/cli/__init__.py +33 -0
- honeybee_radiance_postprocess/cli/abnt.py +392 -0
- honeybee_radiance_postprocess/cli/breeam.py +96 -0
- honeybee_radiance_postprocess/cli/datacollection.py +133 -0
- honeybee_radiance_postprocess/cli/grid.py +295 -0
- honeybee_radiance_postprocess/cli/leed.py +143 -0
- honeybee_radiance_postprocess/cli/merge.py +161 -0
- honeybee_radiance_postprocess/cli/mtxop.py +161 -0
- honeybee_radiance_postprocess/cli/postprocess.py +1092 -0
- honeybee_radiance_postprocess/cli/schedule.py +103 -0
- honeybee_radiance_postprocess/cli/translate.py +216 -0
- honeybee_radiance_postprocess/cli/two_phase.py +252 -0
- honeybee_radiance_postprocess/cli/util.py +121 -0
- honeybee_radiance_postprocess/cli/viewfactor.py +157 -0
- honeybee_radiance_postprocess/cli/well.py +110 -0
- honeybee_radiance_postprocess/data_type.py +102 -0
- honeybee_radiance_postprocess/dynamic.py +273 -0
- honeybee_radiance_postprocess/electriclight.py +24 -0
- honeybee_radiance_postprocess/en17037.py +304 -0
- honeybee_radiance_postprocess/helper.py +266 -0
- honeybee_radiance_postprocess/ies/__init__.py +1 -0
- honeybee_radiance_postprocess/ies/lm.py +224 -0
- honeybee_radiance_postprocess/ies/lm_schedule.py +248 -0
- honeybee_radiance_postprocess/leed/__init__.py +1 -0
- honeybee_radiance_postprocess/leed/leed.py +801 -0
- honeybee_radiance_postprocess/leed/leed_schedule.py +256 -0
- honeybee_radiance_postprocess/metrics.py +439 -0
- honeybee_radiance_postprocess/reader.py +80 -0
- honeybee_radiance_postprocess/results/__init__.py +4 -0
- honeybee_radiance_postprocess/results/annual_daylight.py +752 -0
- honeybee_radiance_postprocess/results/annual_irradiance.py +196 -0
- honeybee_radiance_postprocess/results/results.py +1416 -0
- honeybee_radiance_postprocess/type_hints.py +38 -0
- honeybee_radiance_postprocess/util.py +211 -0
- honeybee_radiance_postprocess/vis_metadata.py +49 -0
- honeybee_radiance_postprocess/well/__init__.py +1 -0
- honeybee_radiance_postprocess/well/well.py +509 -0
- honeybee_radiance_postprocess-0.4.555.dist-info/METADATA +79 -0
- honeybee_radiance_postprocess-0.4.555.dist-info/RECORD +50 -0
- honeybee_radiance_postprocess-0.4.555.dist-info/WHEEL +5 -0
- honeybee_radiance_postprocess-0.4.555.dist-info/entry_points.txt +2 -0
- honeybee_radiance_postprocess-0.4.555.dist-info/licenses/LICENSE +661 -0
- honeybee_radiance_postprocess-0.4.555.dist-info/top_level.txt +1 -0
@@ -0,0 +1,552 @@
|
|
1
|
+
"""Functions for BREEAM post-processing."""
|
2
|
+
from typing import Union
|
3
|
+
from pathlib import Path
|
4
|
+
import json
|
5
|
+
try:
|
6
|
+
import cupy as np
|
7
|
+
is_gpu = True
|
8
|
+
except ImportError:
|
9
|
+
is_gpu = False
|
10
|
+
import numpy as np
|
11
|
+
|
12
|
+
from honeybee.model import Model
|
13
|
+
from honeybee_radiance.writer import _filter_by_pattern
|
14
|
+
|
15
|
+
from ..results.annual_daylight import AnnualDaylight
|
16
|
+
|
17
|
+
|
18
|
+
program_type_metrics = {
|
19
|
+
'BREEAM::Education_buildings::Preschools': [
|
20
|
+
{
|
21
|
+
'type': 'Education buildings',
|
22
|
+
'credits': 2,
|
23
|
+
'area': 80,
|
24
|
+
'average_daylight_illuminance': {
|
25
|
+
'illuminance': 300,
|
26
|
+
'hours': 2000
|
27
|
+
},
|
28
|
+
'minimum_daylight_illuminance': {
|
29
|
+
'illuminance': 90,
|
30
|
+
'hours': 2000
|
31
|
+
}
|
32
|
+
}
|
33
|
+
],
|
34
|
+
'BREEAM::Education_buildings::Higher_education': [
|
35
|
+
{
|
36
|
+
'type': 'Education buildings',
|
37
|
+
'credits': 2,
|
38
|
+
'area': 80,
|
39
|
+
'average_daylight_illuminance': {
|
40
|
+
'illuminance': 300,
|
41
|
+
'hours': 2000
|
42
|
+
},
|
43
|
+
'minimum_daylight_illuminance': {
|
44
|
+
'illuminance': 90,
|
45
|
+
'hours': 2000
|
46
|
+
}
|
47
|
+
},
|
48
|
+
{
|
49
|
+
'type': 'Education buildings',
|
50
|
+
'credits': 1,
|
51
|
+
'area': 60,
|
52
|
+
'average_daylight_illuminance': {
|
53
|
+
'illuminance': 300,
|
54
|
+
'hours': 2000
|
55
|
+
},
|
56
|
+
'minimum_daylight_illuminance': {
|
57
|
+
'illuminance': 90,
|
58
|
+
'hours': 2000
|
59
|
+
}
|
60
|
+
}
|
61
|
+
],
|
62
|
+
'BREEAM::Healthcare_buildings::Staff_and_public_areas': [
|
63
|
+
{
|
64
|
+
'type': 'Healthcare buildings',
|
65
|
+
'credits': 2,
|
66
|
+
'area': 80,
|
67
|
+
'average_daylight_illuminance': {
|
68
|
+
'illuminance': 300,
|
69
|
+
'hours': 2650
|
70
|
+
},
|
71
|
+
'minimum_daylight_illuminance': {
|
72
|
+
'illuminance': 90,
|
73
|
+
'hours': 2650
|
74
|
+
}
|
75
|
+
},
|
76
|
+
{
|
77
|
+
'type': 'Healthcare buildings',
|
78
|
+
'credits': 1,
|
79
|
+
'area': 80,
|
80
|
+
'average_daylight_illuminance': {
|
81
|
+
'illuminance': 300,
|
82
|
+
'hours': 2000
|
83
|
+
},
|
84
|
+
'minimum_daylight_illuminance': {
|
85
|
+
'illuminance': 90,
|
86
|
+
'hours': 2000
|
87
|
+
}
|
88
|
+
}
|
89
|
+
],
|
90
|
+
'BREEAM::Healthcare_buildings::Patients_areas_and_consulting_rooms': [
|
91
|
+
{
|
92
|
+
'type': 'Healthcare buildings',
|
93
|
+
'credits': 2,
|
94
|
+
'area': 80,
|
95
|
+
'average_daylight_illuminance': {
|
96
|
+
'illuminance': 300,
|
97
|
+
'hours': 2650
|
98
|
+
},
|
99
|
+
'minimum_daylight_illuminance': {
|
100
|
+
'illuminance': 90,
|
101
|
+
'hours': 2650
|
102
|
+
}
|
103
|
+
},
|
104
|
+
{
|
105
|
+
'type': 'Healthcare buildings',
|
106
|
+
'credits': 1,
|
107
|
+
'area': 80,
|
108
|
+
'average_daylight_illuminance': {
|
109
|
+
'illuminance': 300,
|
110
|
+
'hours': 2000
|
111
|
+
},
|
112
|
+
'minimum_daylight_illuminance': {
|
113
|
+
'illuminance': 90,
|
114
|
+
'hours': 2000
|
115
|
+
}
|
116
|
+
}
|
117
|
+
],
|
118
|
+
'BREEAM::Multi_residential_buildings::Kitchen': [
|
119
|
+
{
|
120
|
+
'type': 'Multi-residential buildings',
|
121
|
+
'credits': 2,
|
122
|
+
'area': 100,
|
123
|
+
'average_daylight_illuminance': {
|
124
|
+
'illuminance': 100,
|
125
|
+
'hours': 3450
|
126
|
+
},
|
127
|
+
'minimum_daylight_illuminance': {
|
128
|
+
'illuminance': 30,
|
129
|
+
'hours': 3450
|
130
|
+
}
|
131
|
+
}
|
132
|
+
],
|
133
|
+
'BREEAM::Multi_residential_buildings::Living_rooms_dining_rooms_studies': [
|
134
|
+
{
|
135
|
+
'type': 'Multi-residential buildings',
|
136
|
+
'credits': 2,
|
137
|
+
'area': 100,
|
138
|
+
'average_daylight_illuminance': {
|
139
|
+
'illuminance': 100,
|
140
|
+
'hours': 3450
|
141
|
+
},
|
142
|
+
'minimum_daylight_illuminance': {
|
143
|
+
'illuminance': 30,
|
144
|
+
'hours': 3450
|
145
|
+
}
|
146
|
+
}
|
147
|
+
],
|
148
|
+
'BREEAM::Multi_residential_buildings::Non_residential_or_communal_spaces': [
|
149
|
+
{
|
150
|
+
'type': 'Multi-residential buildings',
|
151
|
+
'credits': 2,
|
152
|
+
'area': 80,
|
153
|
+
'average_daylight_illuminance': {
|
154
|
+
'illuminance': 200,
|
155
|
+
'hours': 2650
|
156
|
+
},
|
157
|
+
'minimum_daylight_illuminance': {
|
158
|
+
'illuminance': 60,
|
159
|
+
'hours': 2650
|
160
|
+
}
|
161
|
+
}
|
162
|
+
],
|
163
|
+
'BREEAM::Retail_buildings::Sales_areas': [
|
164
|
+
{
|
165
|
+
'type': 'Retail buildings',
|
166
|
+
'credits': 1,
|
167
|
+
'area': 35,
|
168
|
+
'average_daylight_illuminance': {
|
169
|
+
'illuminance': 200,
|
170
|
+
'hours': 2650
|
171
|
+
},
|
172
|
+
'minimum_daylight_illuminance': {
|
173
|
+
'illuminance': 200,
|
174
|
+
'hours': 2650
|
175
|
+
}
|
176
|
+
}
|
177
|
+
],
|
178
|
+
'BREEAM::Retail_buildings::Other_occupied_areas': [
|
179
|
+
{
|
180
|
+
'type': 'Retail buildings',
|
181
|
+
'credits': 1,
|
182
|
+
'area': 80,
|
183
|
+
'average_daylight_illuminance': {
|
184
|
+
'illuminance': 200,
|
185
|
+
'hours': 2650
|
186
|
+
},
|
187
|
+
'minimum_daylight_illuminance': {
|
188
|
+
'illuminance': 60,
|
189
|
+
'hours': 2650
|
190
|
+
}
|
191
|
+
}
|
192
|
+
],
|
193
|
+
'BREEAM::Prison_buildings::Cells_and_custody_cells': [
|
194
|
+
{
|
195
|
+
'type': 'Prison buildings',
|
196
|
+
'credits': 2,
|
197
|
+
'area': 80,
|
198
|
+
'average_daylight_illuminance': {
|
199
|
+
'illuminance': 100,
|
200
|
+
'hours': 3150
|
201
|
+
},
|
202
|
+
'minimum_daylight_illuminance': None
|
203
|
+
}
|
204
|
+
],
|
205
|
+
'BREEAM::Prison_buildings::Internal_association_or_atrium': [
|
206
|
+
{
|
207
|
+
'type': 'Prison buildings',
|
208
|
+
'credits': 2,
|
209
|
+
'area': 80,
|
210
|
+
'average_daylight_illuminance': {
|
211
|
+
'illuminance': 300,
|
212
|
+
'hours': 2650
|
213
|
+
},
|
214
|
+
'minimum_daylight_illuminance': {
|
215
|
+
'illuminance': 210,
|
216
|
+
'hours': 2650
|
217
|
+
}
|
218
|
+
}
|
219
|
+
],
|
220
|
+
'BREEAM::Prison_buildings::Patient_care_spaces': [
|
221
|
+
{
|
222
|
+
'type': 'Prison buildings',
|
223
|
+
'credits': 2,
|
224
|
+
'area': 80,
|
225
|
+
'average_daylight_illuminance': {
|
226
|
+
'illuminance': 300,
|
227
|
+
'hours': 2650
|
228
|
+
},
|
229
|
+
'minimum_daylight_illuminance': {
|
230
|
+
'illuminance': 210,
|
231
|
+
'hours': 2650
|
232
|
+
}
|
233
|
+
}
|
234
|
+
],
|
235
|
+
'BREEAM::Prison_buildings::Teaching_lecture_and_seminar_spaces': [
|
236
|
+
{
|
237
|
+
'type': 'Prison buildings',
|
238
|
+
'credits': 2,
|
239
|
+
'area': 80,
|
240
|
+
'average_daylight_illuminance': {
|
241
|
+
'illuminance': 300,
|
242
|
+
'hours': 2000
|
243
|
+
},
|
244
|
+
'minimum_daylight_illuminance': {
|
245
|
+
'illuminance': 90,
|
246
|
+
'hours': 2000
|
247
|
+
}
|
248
|
+
}
|
249
|
+
],
|
250
|
+
'BREEAM::Office_buildings::Occupied_spaces': [
|
251
|
+
{
|
252
|
+
'type': 'Office buildings',
|
253
|
+
'credits': 2,
|
254
|
+
'area': 80,
|
255
|
+
'average_daylight_illuminance': {
|
256
|
+
'illuminance': 300,
|
257
|
+
'hours': 2000
|
258
|
+
},
|
259
|
+
'minimum_daylight_illuminance': {
|
260
|
+
'illuminance': 90,
|
261
|
+
'hours': 2000
|
262
|
+
}
|
263
|
+
}
|
264
|
+
],
|
265
|
+
'BREEAM::Crèche_buildings::Occupied_spaces': [
|
266
|
+
{
|
267
|
+
'type': 'Crèche buildings',
|
268
|
+
'credits': 2,
|
269
|
+
'area': 80,
|
270
|
+
'average_daylight_illuminance': {
|
271
|
+
'illuminance': 300,
|
272
|
+
'hours': 2000
|
273
|
+
},
|
274
|
+
'minimum_daylight_illuminance': {
|
275
|
+
'illuminance': 90,
|
276
|
+
'hours': 2000
|
277
|
+
}
|
278
|
+
}
|
279
|
+
],
|
280
|
+
'BREEAM::Other_buildings::Occupied_spaces': [
|
281
|
+
{
|
282
|
+
'type': 'Other buildings',
|
283
|
+
'credits': 1,
|
284
|
+
'area': 80,
|
285
|
+
'average_daylight_illuminance': {
|
286
|
+
'illuminance': 300,
|
287
|
+
'hours': 2000
|
288
|
+
},
|
289
|
+
'minimum_daylight_illuminance': {
|
290
|
+
'illuminance': 90,
|
291
|
+
'hours': 2000
|
292
|
+
}
|
293
|
+
}
|
294
|
+
]
|
295
|
+
}
|
296
|
+
|
297
|
+
|
298
|
+
def breeam_daylight_assessment_4b(
|
299
|
+
results: Union[str, AnnualDaylight], model: Union[str, Path, Model] = None,
|
300
|
+
grids_filter: str = '*', sub_folder: str = None):
|
301
|
+
"""Calculate credits for BREEAM 4b.
|
302
|
+
|
303
|
+
Args:
|
304
|
+
results: Path to results folder or a Results class object.
|
305
|
+
model: A model as a path or a HB Model object. If None, the function
|
306
|
+
will look for a model in the parent of the results folder. If a model
|
307
|
+
does not exist in this directory the function will raise an error.
|
308
|
+
Defaults to None.
|
309
|
+
grids_filter: The name of a grid or a pattern to filter the grids.
|
310
|
+
Defaults to '*'.
|
311
|
+
sub_folder: Relative path for a subfolder to write the output. If None,
|
312
|
+
the files will not be written. Defaults to None.
|
313
|
+
|
314
|
+
Returns:
|
315
|
+
Tuple:
|
316
|
+
- credit_summary: Summary of each building type.
|
317
|
+
- program_summary: Summary of program type / space type.
|
318
|
+
"""
|
319
|
+
if not isinstance(results, AnnualDaylight):
|
320
|
+
results = AnnualDaylight(results)
|
321
|
+
|
322
|
+
grids_info = results._filter_grids(grids_filter=grids_filter)
|
323
|
+
|
324
|
+
# check to see if there is a HBJSON with sensor grid meshes for areas
|
325
|
+
grid_areas = {}
|
326
|
+
grid_program_types = {}
|
327
|
+
if model is None:
|
328
|
+
found_file = False
|
329
|
+
for base_file in Path(results.folder).parent.iterdir():
|
330
|
+
if base_file.suffix in ('.hbjson', '.hbpkl'):
|
331
|
+
hb_model: Model = Model.from_file(base_file)
|
332
|
+
found_file = True
|
333
|
+
break
|
334
|
+
if not found_file:
|
335
|
+
raise FileNotFoundError(
|
336
|
+
'Found no hbjson or hbpkl file in parent of results folder.')
|
337
|
+
else:
|
338
|
+
if isinstance(model, Model):
|
339
|
+
hb_model = model
|
340
|
+
else:
|
341
|
+
hb_model = Model.from_file(model)
|
342
|
+
|
343
|
+
filt_grids = _filter_by_pattern(
|
344
|
+
hb_model.properties.radiance.sensor_grids, filter=grids_filter)
|
345
|
+
for s_grid in filt_grids:
|
346
|
+
if s_grid.mesh is not None:
|
347
|
+
grid_areas[s_grid.identifier] = int(np.array(s_grid.mesh.face_areas).sum())
|
348
|
+
else:
|
349
|
+
grid_areas[s_grid.identifier] = None
|
350
|
+
hb_room = hb_model.rooms_by_identifier([s_grid.room_identifier])[0]
|
351
|
+
try:
|
352
|
+
program_type_id = hb_room.properties.energy.program_type.identifier
|
353
|
+
except AttributeError as e:
|
354
|
+
raise ImportError('honeybee_energy library must be installed to use '
|
355
|
+
'breeam_daylight_assessment method. {}'.format(e))
|
356
|
+
if program_type_id in program_type_metrics:
|
357
|
+
grid_program_types[s_grid.identifier] = program_type_id
|
358
|
+
|
359
|
+
if not grid_areas:
|
360
|
+
grid_areas = {grid_info['full_id']: None for grid_info in grids_info}
|
361
|
+
|
362
|
+
sensor_grid_mapper = {}
|
363
|
+
for sg in hb_model.properties.radiance.sensor_grids:
|
364
|
+
sensor_grid_mapper[sg.identifier] = sg
|
365
|
+
|
366
|
+
grid_summary = {}
|
367
|
+
type_summary = {}
|
368
|
+
minimum_illuminance_sensors = {}
|
369
|
+
for grid_info in grids_info:
|
370
|
+
program_type = grid_program_types.get(grid_info['full_id'], None)
|
371
|
+
if program_type is None:
|
372
|
+
continue
|
373
|
+
if program_type not in type_summary:
|
374
|
+
type_summary[program_type] = {} # add dict for program type
|
375
|
+
type_summary[program_type][grid_info['full_id']] = []
|
376
|
+
|
377
|
+
array = results._array_from_states(grid_info, zero_array=True)
|
378
|
+
# calculate average along axis 0 (average for each hour)
|
379
|
+
avg_ill = array.mean(axis=0)
|
380
|
+
|
381
|
+
metrics_list = program_type_metrics[program_type]
|
382
|
+
for metrics in metrics_list:
|
383
|
+
metrics_summary = {}
|
384
|
+
metrics_summary['type'] = metrics['type']
|
385
|
+
metrics_summary['area'] = grid_areas[grid_info['full_id']]
|
386
|
+
# calculate number of hours where avg. illuminance > target illuminance
|
387
|
+
target_ill = metrics['average_daylight_illuminance']['illuminance']
|
388
|
+
hrs_abv_avg = (avg_ill >= target_ill).sum()
|
389
|
+
# check if value is >= target hours
|
390
|
+
target_hrs = metrics['average_daylight_illuminance']['hours']
|
391
|
+
avg_comply = hrs_abv_avg >= target_hrs
|
392
|
+
|
393
|
+
# calculate number of hours where illuminance > target illuminance
|
394
|
+
if program_type == 'BREEAM::Prison_buildings::Cells_and_custody_cells':
|
395
|
+
min_comply = True # no minimum daylight illuminance for this space
|
396
|
+
else:
|
397
|
+
target_ill = metrics['minimum_daylight_illuminance']['illuminance']
|
398
|
+
hrs_abv_target = (array >= target_ill).sum(axis=1)
|
399
|
+
# get the minimum, i.e., worst lit point
|
400
|
+
hrs_abv_min = np.min(hrs_abv_target)
|
401
|
+
# check if values is >= target hours
|
402
|
+
target_hrs = metrics['minimum_daylight_illuminance']['hours']
|
403
|
+
min_comply = hrs_abv_min >= target_hrs
|
404
|
+
|
405
|
+
minimum_illuminance_index = int(np.argsort(hrs_abv_target)[0])
|
406
|
+
minimum_illuminance_sensor = \
|
407
|
+
sensor_grid_mapper[grid_info['full_id']].sensors[minimum_illuminance_index]
|
408
|
+
minimum_illuminance_sensors[grid_info['full_id']] = \
|
409
|
+
minimum_illuminance_sensor.to_dict()
|
410
|
+
|
411
|
+
metrics_summary['credits'] = metrics['credits']
|
412
|
+
if avg_comply and min_comply:
|
413
|
+
metrics_summary['comply'] = True
|
414
|
+
else:
|
415
|
+
metrics_summary['comply'] = False
|
416
|
+
metrics_summary['average-comply'] = True if avg_comply else False
|
417
|
+
metrics_summary['minimum-comply'] = True if min_comply else False
|
418
|
+
|
419
|
+
metrics_summary['count'] = grid_info['count']
|
420
|
+
|
421
|
+
metrics_summary['average-illuminance-hours'] = hrs_abv_avg
|
422
|
+
metrics_summary['minimum-illuminance-hours'] = hrs_abv_min
|
423
|
+
|
424
|
+
type_summary[program_type][grid_info['full_id']].append(metrics_summary)
|
425
|
+
|
426
|
+
grid_summary[grid_info['full_id']] = {
|
427
|
+
'type': metrics['type'],
|
428
|
+
'program-type': program_type,
|
429
|
+
'display-name': grid_info['name'],
|
430
|
+
'average-illuminance-hours': hrs_abv_avg.item(),
|
431
|
+
'minimum-illuminance-hours': hrs_abv_min.item()
|
432
|
+
}
|
433
|
+
|
434
|
+
program_summary = []
|
435
|
+
for program_type, _grid_summary in type_summary.items():
|
436
|
+
program_type_summary = {}
|
437
|
+
program_type_summary['program_type'] = program_type
|
438
|
+
program_type_summary['credits'] = 0 # set 0 by default
|
439
|
+
program_type_summary['comply'] = False # set False by default
|
440
|
+
|
441
|
+
metrics_summary = {}
|
442
|
+
for grid_id, metrics_list in _grid_summary.items():
|
443
|
+
for metric in metrics_list:
|
444
|
+
if metric['credits'] not in metrics_summary:
|
445
|
+
metrics_summary[metric['credits']] = {}
|
446
|
+
metrics_summary[metric['credits']]['type'] = metric['type']
|
447
|
+
if 'total_area' not in metrics_summary[metric['credits']]:
|
448
|
+
metrics_summary[metric['credits']]['total_area'] = 0
|
449
|
+
metrics_summary[metric['credits']]['total_area'] += metric['area']
|
450
|
+
if 'area_comply' not in metrics_summary[metric['credits']]:
|
451
|
+
metrics_summary[metric['credits']]['area_comply'] = 0
|
452
|
+
if metric['comply']:
|
453
|
+
metrics_summary[metric['credits']]['area_comply'] += metric['area']
|
454
|
+
|
455
|
+
for credit, metric_summary in metrics_summary.items():
|
456
|
+
area_comply_pct = metric_summary['area_comply'] / metric_summary['total_area'] * 100
|
457
|
+
metric_summary['area_comply_%'] = area_comply_pct
|
458
|
+
for metric in program_type_metrics[program_type]:
|
459
|
+
if credit == metric['credits']:
|
460
|
+
if area_comply_pct >= metric['area']:
|
461
|
+
metric_summary['comply'] = True
|
462
|
+
else:
|
463
|
+
metric_summary['comply'] = False
|
464
|
+
|
465
|
+
for credit, metric_summary in metrics_summary.items():
|
466
|
+
if metric_summary['comply'] and credit > program_type_summary['credits']:
|
467
|
+
program_type_summary['comply'] = True
|
468
|
+
program_type_summary['credits'] = credit
|
469
|
+
program_type_summary['total_area'] = metric_summary['total_area']
|
470
|
+
program_type_summary['area_comply'] = metric_summary['area_comply']
|
471
|
+
program_type_summary['area_comply_%'] = metric_summary['area_comply_%']
|
472
|
+
program_type_summary['type'] = metric_summary['type']
|
473
|
+
else:
|
474
|
+
program_type_summary['total_area'] = metric_summary['total_area']
|
475
|
+
program_type_summary['area_comply'] = metric_summary['area_comply']
|
476
|
+
program_type_summary['area_comply_%'] = metric_summary['area_comply_%']
|
477
|
+
program_type_summary['type'] = metric_summary['type']
|
478
|
+
|
479
|
+
avg_hrs, min_hrs, areas = [], [], []
|
480
|
+
for grid_id, metrics_list in _grid_summary.items():
|
481
|
+
for metric in metrics_list:
|
482
|
+
areas.append(metric['area'])
|
483
|
+
avg_hrs.append(metric['average-illuminance-hours'])
|
484
|
+
min_hrs.append(metric['minimum-illuminance-hours'])
|
485
|
+
break # only need to get the first one
|
486
|
+
|
487
|
+
area_proportions = np.array(areas) / program_type_summary['total_area']
|
488
|
+
|
489
|
+
weighted_hours_avg = area_proportions * np.array(avg_hrs)
|
490
|
+
total_weighted_hours_avg = int(np.sum(weighted_hours_avg))
|
491
|
+
program_type_summary['average-illuminance-hours'] = total_weighted_hours_avg
|
492
|
+
|
493
|
+
weighted_hours_min = area_proportions * np.array(min_hrs)
|
494
|
+
total_weighted_hours_min = int(np.sum(weighted_hours_min))
|
495
|
+
program_type_summary['minimum-illuminance-hours'] = total_weighted_hours_min
|
496
|
+
|
497
|
+
program_summary.append(program_type_summary)
|
498
|
+
|
499
|
+
building_type_summary = {}
|
500
|
+
for _program_summary in program_summary:
|
501
|
+
if _program_summary['type'] not in building_type_summary:
|
502
|
+
building_type_summary[_program_summary['type']] = []
|
503
|
+
building_type_summary[_program_summary['type']].append(_program_summary)
|
504
|
+
|
505
|
+
credit_summary = []
|
506
|
+
for building_type, summary in building_type_summary.items():
|
507
|
+
_building_type_summary = {}
|
508
|
+
_building_type_summary['type'] = building_type
|
509
|
+
if all([v['comply'] for v in summary]):
|
510
|
+
_building_type_summary['comply'] = True
|
511
|
+
_building_type_summary['credits'] = min([v['credits'] for v in summary])
|
512
|
+
else:
|
513
|
+
_building_type_summary['comply'] = False
|
514
|
+
_building_type_summary['credits'] = 0
|
515
|
+
_building_type_summary['total_area'] = sum([v['total_area'] for v in summary])
|
516
|
+
|
517
|
+
credit_summary.append(_building_type_summary)
|
518
|
+
|
519
|
+
if sub_folder:
|
520
|
+
sub_folder = Path(sub_folder)
|
521
|
+
sub_folder.mkdir(parents=True, exist_ok=True)
|
522
|
+
|
523
|
+
minimum_illuminance_points_file = sub_folder.joinpath('minimum_illuminance_sensors.json')
|
524
|
+
minimum_illuminance_points_file.write_text(
|
525
|
+
json.dumps(minimum_illuminance_sensors, indent=2))
|
526
|
+
credit_summary_file = sub_folder.joinpath('summary.json')
|
527
|
+
credit_summary_file.write_text(json.dumps(credit_summary, indent=2))
|
528
|
+
program_summary_file = sub_folder.joinpath('program_summary.json')
|
529
|
+
program_summary_file.write_text(json.dumps(program_summary, indent=2))
|
530
|
+
grid_summary_file = sub_folder.joinpath('grid_summary.json')
|
531
|
+
grid_summary_file.write_text(json.dumps(grid_summary, indent=2))
|
532
|
+
|
533
|
+
pf_folder = sub_folder.joinpath('pass_fail')
|
534
|
+
pf_folder.mkdir(parents=True, exist_ok=True)
|
535
|
+
grids_info_file = pf_folder.joinpath('grids_info.json')
|
536
|
+
grids_info_file.write_text(json.dumps(grids_info, indent=2))
|
537
|
+
for program_type, grid_summary in type_summary.items():
|
538
|
+
for grid_id, metrics_list in grid_summary.items():
|
539
|
+
fill_value = 0
|
540
|
+
for metric in metrics_list:
|
541
|
+
if metric['comply']:
|
542
|
+
fill_value = 3
|
543
|
+
break
|
544
|
+
elif metric['average-comply']:
|
545
|
+
fill_value = 2
|
546
|
+
elif metric['minimum-comply']:
|
547
|
+
fill_value = 1
|
548
|
+
pf_file = pf_folder.joinpath(f'{grid_id}.pf')
|
549
|
+
pf_array = np.full(metric['count'], fill_value)
|
550
|
+
np.savetxt(pf_file, pf_array, fmt='%d')
|
551
|
+
|
552
|
+
return credit_summary, program_summary
|
@@ -0,0 +1,33 @@
|
|
1
|
+
"""Modules for post-processing simulation outputs."""
|
2
|
+
import click
|
3
|
+
|
4
|
+
from honeybee.cli import main
|
5
|
+
from .grid import grid
|
6
|
+
from .mtxop import mtxop
|
7
|
+
from .postprocess import post_process
|
8
|
+
from .schedule import schedule
|
9
|
+
from .translate import translate
|
10
|
+
from .viewfactor import view_factor
|
11
|
+
from .merge import merge
|
12
|
+
from .datacollection import datacollection
|
13
|
+
|
14
|
+
|
15
|
+
# command group for all postprocess extension commands.
|
16
|
+
@click.group(help='honeybee radiance postprocess commands.')
|
17
|
+
@click.version_option()
|
18
|
+
def postprocess():
|
19
|
+
pass
|
20
|
+
|
21
|
+
|
22
|
+
# add sub-commands to postprocess
|
23
|
+
postprocess.add_command(grid)
|
24
|
+
postprocess.add_command(mtxop)
|
25
|
+
postprocess.add_command(post_process, name='post-process')
|
26
|
+
postprocess.add_command(schedule)
|
27
|
+
postprocess.add_command(translate)
|
28
|
+
postprocess.add_command(view_factor)
|
29
|
+
postprocess.add_command(merge)
|
30
|
+
postprocess.add_command(datacollection, name='data-collection')
|
31
|
+
|
32
|
+
# add postprocess sub-commands to honeybee CLI
|
33
|
+
main.add_command(postprocess)
|