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,509 @@
|
|
1
|
+
"""Functions for WELL post-processing."""
|
2
|
+
from typing import Tuple, Union
|
3
|
+
from pathlib import Path
|
4
|
+
import json
|
5
|
+
import numpy as np
|
6
|
+
|
7
|
+
from ladybug.analysisperiod import AnalysisPeriod
|
8
|
+
from ladybug.datacollection import HourlyContinuousCollection
|
9
|
+
from ladybug.datatype.generic import GenericType
|
10
|
+
from ladybug.header import Header
|
11
|
+
from honeybee.model import Model
|
12
|
+
from honeybee.units import conversion_factor_to_meters
|
13
|
+
from honeybee_radiance.writer import _filter_by_pattern
|
14
|
+
|
15
|
+
from ..metrics import da_array2d
|
16
|
+
from ..annual import occupancy_schedule_8_to_6
|
17
|
+
from ..results.annual_daylight import AnnualDaylight
|
18
|
+
from ..util import filter_array, recursive_dict_merge
|
19
|
+
from ..ies.lm import dynamic_schedule_direct_illuminance
|
20
|
+
from ..en17037 import en17037_to_folder
|
21
|
+
|
22
|
+
|
23
|
+
def _create_grid_summary(
|
24
|
+
grid_info, sda_grid, sda_blinds_up_grid, sda_blinds_down_grid, pass_sda,
|
25
|
+
total_floor, area_weighted=True):
|
26
|
+
"""Create a WELL summary for a single grid.
|
27
|
+
|
28
|
+
Args:
|
29
|
+
grid_info: Grid information.
|
30
|
+
sda_grid: Spatial Daylight Autonomy.
|
31
|
+
pass_sda: The percentage of the sensor points or floor area that
|
32
|
+
passes sDA.
|
33
|
+
total_floor: The number of sensor points or floor area.
|
34
|
+
area_weighted: Boolean to determine if the results are area
|
35
|
+
weighted. Defaults to True.
|
36
|
+
|
37
|
+
Returns:
|
38
|
+
Tuple:
|
39
|
+
- summary_grid: Summary of each grid individually.
|
40
|
+
"""
|
41
|
+
grid_id = grid_info['full_id']
|
42
|
+
grid_name = grid_info['name']
|
43
|
+
grid_summary = {
|
44
|
+
grid_id: {}
|
45
|
+
}
|
46
|
+
|
47
|
+
if area_weighted:
|
48
|
+
_grid_summary = {
|
49
|
+
grid_id: {
|
50
|
+
'name': grid_name,
|
51
|
+
'full_id': grid_id,
|
52
|
+
'sda': round(sda_grid, 2),
|
53
|
+
'sda_blinds_up': round(sda_blinds_up_grid, 2),
|
54
|
+
'sda_blinds_down': round(sda_blinds_down_grid, 2),
|
55
|
+
'floor_area_passing_sda': round(pass_sda, 2),
|
56
|
+
'total_floor_area': round(total_floor, 2)
|
57
|
+
}
|
58
|
+
}
|
59
|
+
else:
|
60
|
+
_grid_summary = {
|
61
|
+
grid_id: {
|
62
|
+
'name': grid_name,
|
63
|
+
'full_id': grid_id,
|
64
|
+
'sda': round(sda_grid, 2),
|
65
|
+
'sda_blinds_up': round(sda_blinds_up_grid, 2),
|
66
|
+
'sda_blinds_down': round(sda_blinds_down_grid, 2),
|
67
|
+
'sensor_count_passing_sda': int(round(pass_sda, 2)),
|
68
|
+
'total_sensor_count': total_floor
|
69
|
+
}
|
70
|
+
}
|
71
|
+
|
72
|
+
recursive_dict_merge(grid_summary, _grid_summary)
|
73
|
+
|
74
|
+
return grid_summary
|
75
|
+
|
76
|
+
|
77
|
+
def _well_summary(
|
78
|
+
pass_sda_grids: list, grids_info: list,
|
79
|
+
grid_areas: list, pass_sda_blinds_up_grids: list,
|
80
|
+
pass_sda_blinds_down_grids: list) -> Tuple[dict, dict]:
|
81
|
+
"""Create combined summary and summary for each grid individually.
|
82
|
+
|
83
|
+
Args:
|
84
|
+
pass_sda_grids: A list where each sublist is a list of True/False that
|
85
|
+
tells if each sensor point passes sDA.
|
86
|
+
grids_info: A list of grid information.
|
87
|
+
grid_areas: A list where each sublist is the area of each sensor point.
|
88
|
+
The alternative is a list of None values for each grid information.
|
89
|
+
|
90
|
+
Returns:
|
91
|
+
Tuple:
|
92
|
+
- summary: Summary of of all grids combined.
|
93
|
+
- summary_grid: Summary of each grid individually.
|
94
|
+
"""
|
95
|
+
summary = {}
|
96
|
+
summary_grid = {}
|
97
|
+
|
98
|
+
if all(grid_area is not None for grid_area in grid_areas):
|
99
|
+
# weighted by mesh face area
|
100
|
+
total_area = 0
|
101
|
+
total_area_pass_sda = 0
|
102
|
+
for (pass_sda, grid_area, grid_info, pass_sda_blinds_up,
|
103
|
+
pass_sda_blinds_down) in \
|
104
|
+
zip(pass_sda_grids, grid_areas, grids_info,
|
105
|
+
pass_sda_blinds_up_grids, pass_sda_blinds_down_grids):
|
106
|
+
total_grid_area = grid_area.sum()
|
107
|
+
|
108
|
+
area_pass_sda = grid_area[pass_sda].sum()
|
109
|
+
area_pass_sda_blind_up = grid_area[pass_sda_blinds_up].sum()
|
110
|
+
area_pass_sda_blinds_down = grid_area[pass_sda_blinds_down].sum()
|
111
|
+
sda_grid = area_pass_sda / total_grid_area * 100
|
112
|
+
sda_blinds_up_grid = area_pass_sda_blind_up / total_grid_area * 100
|
113
|
+
sda_blinds_down_grid = area_pass_sda_blinds_down / total_grid_area * 100
|
114
|
+
|
115
|
+
# grid summary
|
116
|
+
grid_summary = \
|
117
|
+
_create_grid_summary(
|
118
|
+
grid_info, sda_grid, sda_blinds_up_grid, sda_blinds_down_grid,
|
119
|
+
area_pass_sda, total_grid_area, area_weighted=True
|
120
|
+
)
|
121
|
+
|
122
|
+
recursive_dict_merge(summary_grid, grid_summary)
|
123
|
+
|
124
|
+
total_area += total_grid_area
|
125
|
+
total_area_pass_sda += area_pass_sda
|
126
|
+
|
127
|
+
summary['sda'] = round(total_area_pass_sda / total_area * 100, 2)
|
128
|
+
summary['floor_area_passing_sda'] = total_area_pass_sda
|
129
|
+
summary['total_floor_area'] = total_area
|
130
|
+
else:
|
131
|
+
# assume all sensor points cover the same area
|
132
|
+
total_sensor_count = 0
|
133
|
+
total_sensor_count_pass_sda = 0
|
134
|
+
for (pass_sda, grid_info, pass_sda_blinds_up, pass_sda_blinds_down) in \
|
135
|
+
zip(pass_sda_grids, grids_info, pass_sda_blinds_up_grids,
|
136
|
+
pass_sda_blinds_down_grids):
|
137
|
+
grid_count = grid_info['count']
|
138
|
+
|
139
|
+
sensor_count_pass_sda = pass_sda.sum()
|
140
|
+
sensor_count_pass_sda_blinds_up = pass_sda_blinds_up.sum()
|
141
|
+
sensor_count_pass_sda_blinds_down = pass_sda_blinds_down.sum()
|
142
|
+
sda_grid = sensor_count_pass_sda / grid_count * 100
|
143
|
+
sda_blinds_up_grid = sensor_count_pass_sda_blinds_up / grid_count * 100
|
144
|
+
sda_blinds_down_grid = sensor_count_pass_sda_blinds_down / grid_count * 100
|
145
|
+
|
146
|
+
# grid summary
|
147
|
+
grid_summary = \
|
148
|
+
_create_grid_summary(
|
149
|
+
grid_info, sda_grid, sda_blinds_up_grid, sda_blinds_down_grid,
|
150
|
+
sensor_count_pass_sda, grid_count, area_weighted=False
|
151
|
+
)
|
152
|
+
|
153
|
+
recursive_dict_merge(summary_grid, grid_summary)
|
154
|
+
|
155
|
+
total_sensor_count += grid_count
|
156
|
+
total_sensor_count_pass_sda += sensor_count_pass_sda
|
157
|
+
|
158
|
+
summary['sda'] = round(total_sensor_count_pass_sda / total_sensor_count * 100, 2)
|
159
|
+
summary['sensor_count_passing_sda'] = int(total_sensor_count_pass_sda)
|
160
|
+
summary['total_sensor_count'] = total_sensor_count
|
161
|
+
|
162
|
+
return summary, summary_grid
|
163
|
+
|
164
|
+
|
165
|
+
def well_annual_daylight(
|
166
|
+
results: Union[str, AnnualDaylight], daylight_hours: list, sub_folder,
|
167
|
+
grids_filter: str = '*', states_schedule: dict = None):
|
168
|
+
"""Calculate credits for WELL L06.
|
169
|
+
|
170
|
+
Args:
|
171
|
+
results: Path to results folder or a Results class object.
|
172
|
+
daylight_hours: Schedule of daylight hours used for EN 17037
|
173
|
+
sub_folder: Relative path for a subfolder to write the output.
|
174
|
+
grids_filter: The name of a grid or a pattern to filter the grids.
|
175
|
+
Defaults to '*'.
|
176
|
+
states_schedule: A custom dictionary of shading states. In case this is
|
177
|
+
left empty, the function will calculate a shading schedule by using
|
178
|
+
the shade_transmittance input. If a states schedule is provided it
|
179
|
+
will check that it is complying with the 2% rule. Defaults to None.
|
180
|
+
|
181
|
+
Returns:
|
182
|
+
Tuple:
|
183
|
+
- well_summary: Summary of WELL analysis.
|
184
|
+
- ies_lm_summary: Summary of IES LM analysis.
|
185
|
+
- ies_lm_summary_grid: Summary of IES LM analysis for each grid.
|
186
|
+
- da_grids: List of daylight autonomy values for each grid. Each item
|
187
|
+
in the list is a NumPy array of DA values.
|
188
|
+
- states_schedule: A dictionary of annual shading schedules for each
|
189
|
+
aperture group.
|
190
|
+
- fail_to_comply: A dictionary with the hoys where the 2% rule failed.
|
191
|
+
- grids_info: Grid information.
|
192
|
+
"""
|
193
|
+
schedule = occupancy_schedule_8_to_6(as_list=True)
|
194
|
+
|
195
|
+
if not isinstance(results, AnnualDaylight):
|
196
|
+
results = AnnualDaylight(results, schedule=schedule, cache_arrays=False)
|
197
|
+
else:
|
198
|
+
# set schedule to default leed schedule
|
199
|
+
results.schedule = schedule
|
200
|
+
|
201
|
+
occ_mask = results.occ_mask
|
202
|
+
total_occ = results.total_occ
|
203
|
+
|
204
|
+
grids_info = results._filter_grids(grids_filter=grids_filter)
|
205
|
+
|
206
|
+
if not states_schedule:
|
207
|
+
states_schedule, fail_to_comply, shd_trans_dict = dynamic_schedule_direct_illuminance(
|
208
|
+
results, grids_filter=grids_filter, use_states=True)
|
209
|
+
else:
|
210
|
+
raise NotImplementedError(
|
211
|
+
'Custom input for argument states_schedule is not yet implemented.'
|
212
|
+
)
|
213
|
+
|
214
|
+
# check to see if there is a HBJSON with sensor grid meshes for areas
|
215
|
+
grid_areas, units_conversion = [], 1
|
216
|
+
for base_file in Path(results.folder).parent.iterdir():
|
217
|
+
if base_file.suffix in ('.hbjson', '.hbpkl'):
|
218
|
+
hb_model = Model.from_file(base_file)
|
219
|
+
units_conversion = conversion_factor_to_meters(hb_model.units)
|
220
|
+
filt_grids = _filter_by_pattern(
|
221
|
+
hb_model.properties.radiance.sensor_grids, filter=grids_filter)
|
222
|
+
for s_grid in filt_grids:
|
223
|
+
if s_grid.mesh is not None:
|
224
|
+
grid_areas.append(s_grid.mesh.face_areas)
|
225
|
+
grid_areas = [np.array(grid) for grid in grid_areas]
|
226
|
+
break
|
227
|
+
if not grid_areas:
|
228
|
+
grid_areas = [None] * len(grids_info)
|
229
|
+
|
230
|
+
# spatial daylight autonomy
|
231
|
+
l06_da_grids = []
|
232
|
+
l06_pass_sda_grids = []
|
233
|
+
l06_pass_sda_blinds_up_grids = []
|
234
|
+
l06_pass_sda_blinds_down_grids = []
|
235
|
+
l01_da_grids = []
|
236
|
+
l01_pass_sda_grids = []
|
237
|
+
l01_pass_sda_blinds_up_grids = []
|
238
|
+
l01_pass_sda_blinds_down_grids = []
|
239
|
+
for grid_info in grids_info:
|
240
|
+
light_paths = []
|
241
|
+
for lp in grid_info['light_path']:
|
242
|
+
for _lp in lp:
|
243
|
+
if _lp == '__static_apertures__' and len(lp) > 1:
|
244
|
+
pass
|
245
|
+
else:
|
246
|
+
light_paths.append(_lp)
|
247
|
+
base_zero_array = np.apply_along_axis(filter_array, 1, np.zeros(
|
248
|
+
(grid_info['count'], len(results.sun_up_hours))), occ_mask)
|
249
|
+
arrays_blinds_up = [base_zero_array.copy()]
|
250
|
+
arrays_blinds_down = [base_zero_array.copy()]
|
251
|
+
# combine total array for all light paths
|
252
|
+
array = results._array_from_states(grid_info, states=states_schedule, zero_array=True)
|
253
|
+
array = np.apply_along_axis(filter_array, 1, array, occ_mask)
|
254
|
+
|
255
|
+
for light_path in light_paths:
|
256
|
+
# do an extra pass to calculate with blinds always up or down
|
257
|
+
if light_path != '__static_apertures__':
|
258
|
+
array_blinds_up = results._get_array(
|
259
|
+
grid_info, light_path, state=0, res_type='total')
|
260
|
+
array_filter = np.apply_along_axis(
|
261
|
+
filter_array, 1, array_blinds_up, occ_mask)
|
262
|
+
arrays_blinds_up.append(array_filter)
|
263
|
+
array_blinds_down = results._get_array(
|
264
|
+
grid_info, light_path, state=1, res_type='total')
|
265
|
+
array_filter = np.apply_along_axis(
|
266
|
+
filter_array, 1, array_blinds_down, occ_mask)
|
267
|
+
arrays_blinds_down.append(array_filter)
|
268
|
+
else:
|
269
|
+
static_array = results._get_array(
|
270
|
+
grid_info, light_path, state=0, res_type='total')
|
271
|
+
array_filter = np.apply_along_axis(
|
272
|
+
filter_array, 1, static_array, occ_mask)
|
273
|
+
arrays_blinds_up.append(array_filter)
|
274
|
+
arrays_blinds_down.append(array_filter)
|
275
|
+
|
276
|
+
array_blinds_up = sum(arrays_blinds_up)
|
277
|
+
array_blinds_down = sum(arrays_blinds_down)
|
278
|
+
# calculate da per grid
|
279
|
+
da_grid = da_array2d(array, total_occ=total_occ, threshold=300)
|
280
|
+
|
281
|
+
l06_da_grids.append(da_grid)
|
282
|
+
da_blinds_up_grid = da_array2d(
|
283
|
+
array_blinds_up, total_occ=total_occ, threshold=300)
|
284
|
+
da_blinds_down_grid = da_array2d(
|
285
|
+
array_blinds_down, total_occ=total_occ, threshold=300)
|
286
|
+
# calculate sda per grid
|
287
|
+
l06_pass_sda_grids.append(da_grid >= 50)
|
288
|
+
l06_pass_sda_blinds_up_grids.append(da_blinds_up_grid >= 50)
|
289
|
+
l06_pass_sda_blinds_down_grids.append(da_blinds_down_grid >= 50)
|
290
|
+
|
291
|
+
array_blinds_up = sum(arrays_blinds_up)
|
292
|
+
array_blinds_down = sum(arrays_blinds_down)
|
293
|
+
# calculate da per grid
|
294
|
+
da_grid = da_array2d(array, total_occ=total_occ, threshold=200)
|
295
|
+
|
296
|
+
l01_da_grids.append(da_grid)
|
297
|
+
da_blinds_up_grid = da_array2d(
|
298
|
+
array_blinds_up, total_occ=total_occ, threshold=200)
|
299
|
+
da_blinds_down_grid = da_array2d(
|
300
|
+
array_blinds_down, total_occ=total_occ, threshold=200)
|
301
|
+
# calculate sda per grid
|
302
|
+
l01_pass_sda_grids.append(da_grid >= 40)
|
303
|
+
l01_pass_sda_blinds_up_grids.append(da_blinds_up_grid >= 40)
|
304
|
+
l01_pass_sda_blinds_down_grids.append(da_blinds_down_grid >= 40)
|
305
|
+
|
306
|
+
# create summaries for all grids and each grid individually
|
307
|
+
l06_ies_lm_summary, l06_ies_lm_summary_grid = _well_summary(
|
308
|
+
l06_pass_sda_grids, grids_info, grid_areas,
|
309
|
+
l06_pass_sda_blinds_up_grids, l06_pass_sda_blinds_down_grids)
|
310
|
+
l01_ies_lm_summary, l01_ies_lm_summary_grid = _well_summary(
|
311
|
+
l01_pass_sda_grids, grids_info, grid_areas,
|
312
|
+
l01_pass_sda_blinds_up_grids, l01_pass_sda_blinds_down_grids)
|
313
|
+
|
314
|
+
sub_folder = Path(sub_folder)
|
315
|
+
en17037_folder = en17037_to_folder(
|
316
|
+
results, schedule=daylight_hours,
|
317
|
+
sub_folder=sub_folder.joinpath('en17037'))
|
318
|
+
|
319
|
+
l06_well_summary = []
|
320
|
+
l01_well_summary = []
|
321
|
+
l06_well_summary_ies_lm = {}
|
322
|
+
l06_well_summary_en17037 = {}
|
323
|
+
l01_well_summary_ies_lm = {}
|
324
|
+
l01_well_summary_en17037 = {}
|
325
|
+
l06_well_summary_ies_lm['method'] = 'IES LM-83-12'
|
326
|
+
l06_well_summary_en17037['method'] = 'EN 17037'
|
327
|
+
l01_well_summary_ies_lm['method'] = 'IES LM-83-12'
|
328
|
+
l01_well_summary_en17037['method'] = 'EN 17037'
|
329
|
+
|
330
|
+
l06_combined_da_target = []
|
331
|
+
l06_combined_da_minimum = []
|
332
|
+
l01_combined_da_target = []
|
333
|
+
for grid_info in grids_info:
|
334
|
+
l06_grid_da_target = np.loadtxt(en17037_folder.joinpath('da', 'target_illuminance_300', f'{grid_info["full_id"]}.da'))
|
335
|
+
l06_grid_da_minimum = np.loadtxt(en17037_folder.joinpath('da', 'minimum_illuminance_100', f'{grid_info["full_id"]}.da'))
|
336
|
+
l06_combined_da_target.append(l06_grid_da_target >= 50)
|
337
|
+
l06_combined_da_minimum.append(l06_grid_da_minimum >= 50)
|
338
|
+
|
339
|
+
array = results._array_from_states(
|
340
|
+
grid_info, res_type='total', zero_array=True)
|
341
|
+
if np.any(array):
|
342
|
+
array = np.apply_along_axis(
|
343
|
+
filter_array, 1, array, occ_mask)
|
344
|
+
l01_grid_da_target = da_array2d(array, total_occ=4380, threshold=200)
|
345
|
+
l01_combined_da_target.append(l01_grid_da_target >= 50)
|
346
|
+
|
347
|
+
l06_combined_sda_target_illuminance = np.concatenate(l06_combined_da_target).mean() * 100
|
348
|
+
l06_combined_sda_minimum_illuminance = np.concatenate(l06_combined_da_minimum).mean() * 100
|
349
|
+
|
350
|
+
l01_combined_sda_target_illuminance = np.concatenate(l01_combined_da_target).mean() * 100
|
351
|
+
|
352
|
+
if l01_combined_sda_target_illuminance > 30:
|
353
|
+
l01_well_summary_en17037['comply'] = True
|
354
|
+
else:
|
355
|
+
l01_well_summary_en17037['comply'] = False
|
356
|
+
|
357
|
+
if l06_combined_sda_target_illuminance > 50 and l06_combined_sda_minimum_illuminance > 95:
|
358
|
+
l06_well_summary_en17037['points'] = 2
|
359
|
+
elif l06_combined_sda_target_illuminance > 50:
|
360
|
+
l06_well_summary_en17037['points'] = 1
|
361
|
+
else:
|
362
|
+
l06_well_summary_en17037['points'] = 0
|
363
|
+
|
364
|
+
# credits
|
365
|
+
if not fail_to_comply:
|
366
|
+
if l06_ies_lm_summary['sda'] >= 75:
|
367
|
+
l06_ies_lm_summary['credits'] = 3
|
368
|
+
l06_well_summary_ies_lm['points'] = 2
|
369
|
+
elif l06_ies_lm_summary['sda'] >= 55:
|
370
|
+
l06_ies_lm_summary['credits'] = 2
|
371
|
+
l06_well_summary_ies_lm['points'] = 1
|
372
|
+
elif l06_ies_lm_summary['sda'] >= 40:
|
373
|
+
l06_ies_lm_summary['credits'] = 1
|
374
|
+
l06_well_summary_ies_lm['points'] = 0
|
375
|
+
else:
|
376
|
+
l06_ies_lm_summary['credits'] = 0
|
377
|
+
l06_well_summary_ies_lm['points'] = 0
|
378
|
+
|
379
|
+
if all(grid_summary['sda'] >= 55 for grid_summary in l06_ies_lm_summary_grid.values()):
|
380
|
+
if l06_ies_lm_summary['credits'] <= 2:
|
381
|
+
l06_ies_lm_summary['credits'] += 1
|
382
|
+
else:
|
383
|
+
l06_ies_lm_summary['credits'] = 'Exemplary performance'
|
384
|
+
|
385
|
+
if l01_ies_lm_summary['sda'] >= 30:
|
386
|
+
l01_well_summary_ies_lm['comply'] = True
|
387
|
+
else:
|
388
|
+
l01_well_summary_ies_lm['comply'] = False
|
389
|
+
|
390
|
+
l06_well_summary_ies_lm['sda'] = l06_ies_lm_summary['sda']
|
391
|
+
l01_well_summary_ies_lm['sda'] = l01_ies_lm_summary['sda']
|
392
|
+
else:
|
393
|
+
l06_ies_lm_summary['credits'] = 0
|
394
|
+
fail_to_comply_rooms = ', '.join(list(fail_to_comply.keys()))
|
395
|
+
note = (
|
396
|
+
'0 credits have been awarded. The following sensor grids have at '
|
397
|
+
'least one hour where 2% of the floor area receives direct '
|
398
|
+
f'illuminance of 1000 lux or more: {fail_to_comply_rooms}.'
|
399
|
+
)
|
400
|
+
l06_ies_lm_summary['note'] = note
|
401
|
+
l06_well_summary_ies_lm['points'] = 0
|
402
|
+
l06_well_summary_ies_lm['sda'] = l06_ies_lm_summary['sda']
|
403
|
+
l06_well_summary_ies_lm['note'] = note
|
404
|
+
|
405
|
+
l01_ies_lm_summary['note'] = note
|
406
|
+
l01_well_summary_ies_lm['comply'] = False
|
407
|
+
l01_well_summary_ies_lm['sda'] = l01_ies_lm_summary['sda']
|
408
|
+
l01_well_summary_ies_lm['note'] = note
|
409
|
+
|
410
|
+
l06_well_summary_ies_lm['total_floor_area'] = sum(np.sum(arr) for arr in grid_areas)
|
411
|
+
l01_well_summary_ies_lm['total_floor_area'] = sum(np.sum(arr) for arr in grid_areas)
|
412
|
+
|
413
|
+
# convert to datacollection
|
414
|
+
def to_datacollection(aperture_group: str, values: np.ndarray):
|
415
|
+
# convert values to 0 and 1 (0 = no shading, 1 = shading)
|
416
|
+
header = Header(data_type=GenericType(aperture_group, ''), unit='',
|
417
|
+
analysis_period=AnalysisPeriod())
|
418
|
+
hourly_data = HourlyContinuousCollection(header=header, values=values)
|
419
|
+
return hourly_data.to_dict()
|
420
|
+
|
421
|
+
states_schedule = {k:to_datacollection(k, v['schedule']) for k, v in states_schedule.to_dict().items()}
|
422
|
+
|
423
|
+
ies_lm_folder = sub_folder.joinpath('ies_lm')
|
424
|
+
ies_lm_folder.mkdir(parents=True, exist_ok=True)
|
425
|
+
|
426
|
+
l06_ies_lm_folder = ies_lm_folder.joinpath('l06_ies_lm_summary')
|
427
|
+
l01_ies_lm_folder = ies_lm_folder.joinpath('l01_ies_lm_summary')
|
428
|
+
|
429
|
+
l06_ies_lm_folder.mkdir(parents=True, exist_ok=True)
|
430
|
+
l01_ies_lm_folder.mkdir(parents=True, exist_ok=True)
|
431
|
+
|
432
|
+
ies_lm_summary_file = l06_ies_lm_folder.joinpath('ies_lm_summary.json')
|
433
|
+
ies_lm_summary_file.write_text(json.dumps(l06_ies_lm_summary, indent=2))
|
434
|
+
ies_lm_summary_file = l01_ies_lm_folder.joinpath('ies_lm_summary.json')
|
435
|
+
ies_lm_summary_file.write_text(json.dumps(l01_ies_lm_summary, indent=2))
|
436
|
+
|
437
|
+
ies_lm_summary_grid_file = l06_ies_lm_folder.joinpath('ies_lm_summary_grid.json')
|
438
|
+
ies_lm_summary_grid_file.write_text(json.dumps(l06_ies_lm_summary_grid, indent=2))
|
439
|
+
ies_lm_summary_grid_file = l01_ies_lm_folder.joinpath('ies_lm_summary_grid.json')
|
440
|
+
ies_lm_summary_grid_file.write_text(json.dumps(l01_ies_lm_summary_grid, indent=2))
|
441
|
+
|
442
|
+
states_schedule_file = l06_ies_lm_folder.joinpath('states_schedule.json')
|
443
|
+
states_schedule_file.write_text(json.dumps(states_schedule))
|
444
|
+
states_schedule_file = l01_ies_lm_folder.joinpath('states_schedule.json')
|
445
|
+
states_schedule_file.write_text(json.dumps(states_schedule))
|
446
|
+
|
447
|
+
grids_info_file = l06_ies_lm_folder.joinpath('grids_info.json')
|
448
|
+
grids_info_file.write_text(json.dumps(grids_info, indent=2))
|
449
|
+
grids_info_file = l01_ies_lm_folder.joinpath('grids_info.json')
|
450
|
+
grids_info_file.write_text(json.dumps(grids_info, indent=2))
|
451
|
+
|
452
|
+
for (da, grid_info) in \
|
453
|
+
zip(l06_da_grids, grids_info):
|
454
|
+
grid_id = grid_info['full_id']
|
455
|
+
da_file = l06_ies_lm_folder.joinpath('results', 'da', f'{grid_id}.da')
|
456
|
+
da_file.parent.mkdir(parents=True, exist_ok=True)
|
457
|
+
np.savetxt(da_file, da, fmt='%.2f')
|
458
|
+
for (da, grid_info) in \
|
459
|
+
zip(l01_da_grids, grids_info):
|
460
|
+
grid_id = grid_info['full_id']
|
461
|
+
da_file = l01_ies_lm_folder.joinpath('results', 'da', f'{grid_id}.da')
|
462
|
+
da_file.parent.mkdir(parents=True, exist_ok=True)
|
463
|
+
np.savetxt(da_file, da, fmt='%.2f')
|
464
|
+
|
465
|
+
sda_pf_folder = ies_lm_folder.joinpath('pass_fail')
|
466
|
+
sda_pf_folder.mkdir(parents=True, exist_ok=True)
|
467
|
+
for l01_pf, grid_info in zip(l01_pass_sda_grids, grids_info):
|
468
|
+
grid_id = grid_info['full_id']
|
469
|
+
l01_sda_pf_folder = sda_pf_folder.joinpath('L01')
|
470
|
+
l01_sda_pf_folder.mkdir(parents=True, exist_ok=True)
|
471
|
+
l01_pf_file = l01_sda_pf_folder.joinpath(f'{grid_id}.pf')
|
472
|
+
l01_pf = l01_pf.astype(int)
|
473
|
+
np.savetxt(l01_pf_file, l01_pf, fmt='%d')
|
474
|
+
grids_info_file = l01_sda_pf_folder.joinpath('grids_info.json')
|
475
|
+
grids_info_file.write_text(json.dumps(grids_info, indent=2))
|
476
|
+
for l06_pf, grid_info in zip(l06_pass_sda_grids, grids_info):
|
477
|
+
grid_id = grid_info['full_id']
|
478
|
+
l06_sda_pf_folder = sda_pf_folder.joinpath('L06')
|
479
|
+
l06_sda_pf_folder.mkdir(parents=True, exist_ok=True)
|
480
|
+
l06_pf_file = l06_sda_pf_folder.joinpath(f'{grid_id}.pf')
|
481
|
+
l06_pf = l06_pf.astype(int)
|
482
|
+
np.savetxt(l06_pf_file, l06_pf, fmt='%d')
|
483
|
+
grids_info_file = l06_sda_pf_folder.joinpath('grids_info.json')
|
484
|
+
grids_info_file.write_text(json.dumps(grids_info, indent=2))
|
485
|
+
|
486
|
+
da_grids_info_file = l06_ies_lm_folder.joinpath(
|
487
|
+
'results', 'da', 'grids_info.json')
|
488
|
+
da_grids_info_file.write_text(json.dumps(grids_info, indent=2))
|
489
|
+
da_grids_info_file = l01_ies_lm_folder.joinpath(
|
490
|
+
'results', 'da', 'grids_info.json')
|
491
|
+
da_grids_info_file.write_text(json.dumps(grids_info, indent=2))
|
492
|
+
|
493
|
+
states_schedule_err_file = \
|
494
|
+
l06_ies_lm_folder.joinpath('states_schedule_err.json')
|
495
|
+
states_schedule_err_file.write_text(json.dumps(fail_to_comply))
|
496
|
+
states_schedule_err_file = \
|
497
|
+
l01_ies_lm_folder.joinpath('states_schedule_err.json')
|
498
|
+
states_schedule_err_file.write_text(json.dumps(fail_to_comply))
|
499
|
+
|
500
|
+
l06_well_summary.append(l06_well_summary_ies_lm)
|
501
|
+
l06_well_summary.append(l06_well_summary_en17037)
|
502
|
+
well_summary_file = sub_folder.joinpath('l06_well_summary.json')
|
503
|
+
well_summary_file.write_text(json.dumps(l06_well_summary, indent=2))
|
504
|
+
l01_well_summary.append(l01_well_summary_ies_lm)
|
505
|
+
l01_well_summary.append(l01_well_summary_en17037)
|
506
|
+
well_summary_file = sub_folder.joinpath('l01_well_summary.json')
|
507
|
+
well_summary_file.write_text(json.dumps(l01_well_summary, indent=2))
|
508
|
+
|
509
|
+
return (l06_well_summary, l01_well_summary, states_schedule, fail_to_comply, grids_info)
|
@@ -0,0 +1,79 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: honeybee-radiance-postprocess
|
3
|
+
Version: 0.4.555
|
4
|
+
Summary: Postprocessing of Radiance results and matrices
|
5
|
+
Home-page: https://github.com/ladybug-tools/honeybee-radiance-postprocess
|
6
|
+
Author: Ladybug Tools
|
7
|
+
Author-email: info@ladybug.tools
|
8
|
+
License: GPLv3
|
9
|
+
Classifier: Programming Language :: Python :: 3.7
|
10
|
+
Classifier: Programming Language :: Python :: 3.8
|
11
|
+
Classifier: Programming Language :: Python :: 3.9
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
15
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
16
|
+
Classifier: Operating System :: OS Independent
|
17
|
+
Description-Content-Type: text/markdown
|
18
|
+
License-File: LICENSE
|
19
|
+
Requires-Dist: honeybee-radiance==1.66.191
|
20
|
+
Requires-Dist: numpy<2.0.0
|
21
|
+
Dynamic: author
|
22
|
+
Dynamic: author-email
|
23
|
+
Dynamic: classifier
|
24
|
+
Dynamic: description
|
25
|
+
Dynamic: description-content-type
|
26
|
+
Dynamic: home-page
|
27
|
+
Dynamic: license
|
28
|
+
Dynamic: license-file
|
29
|
+
Dynamic: requires-dist
|
30
|
+
Dynamic: summary
|
31
|
+
|
32
|
+
[](https://github.com/ladybug-tools/honeybee-radiance-postprocess/actions)
|
33
|
+
[](https://coveralls.io/github/ladybug-tools/honeybee-radiance-postprocess)
|
34
|
+
|
35
|
+
[](https://www.python.org/downloads/release/python-3100/) [](https://www.python.org/downloads/release/python-370/)
|
36
|
+
|
37
|
+
# honeybee-radiance-postprocess
|
38
|
+
|
39
|
+
Library and CLI for postprocessing of Radiance results and matrices.
|
40
|
+
|
41
|
+
## Installation
|
42
|
+
```console
|
43
|
+
pip install honeybee-radiance-postprocess
|
44
|
+
```
|
45
|
+
|
46
|
+
## QuickStart
|
47
|
+
```python
|
48
|
+
import honeybee_radiance_postprocess
|
49
|
+
|
50
|
+
```
|
51
|
+
|
52
|
+
## [API Documentation](http://ladybug-tools.github.io/honeybee-radiance-postprocess/docs)
|
53
|
+
|
54
|
+
## Local Development
|
55
|
+
1. Clone this repo locally
|
56
|
+
```console
|
57
|
+
git clone git@github.com:ladybug-tools/honeybee-radiance-postprocess
|
58
|
+
|
59
|
+
# or
|
60
|
+
|
61
|
+
git clone https://github.com/ladybug-tools/honeybee-radiance-postprocess
|
62
|
+
```
|
63
|
+
2. Install dependencies:
|
64
|
+
```console
|
65
|
+
cd honeybee-radiance-postprocess
|
66
|
+
pip install -r dev-requirements.txt
|
67
|
+
pip install -r requirements.txt
|
68
|
+
```
|
69
|
+
|
70
|
+
3. Run Tests:
|
71
|
+
```console
|
72
|
+
python -m pytest tests/
|
73
|
+
```
|
74
|
+
|
75
|
+
4. Generate Documentation:
|
76
|
+
```console
|
77
|
+
sphinx-apidoc -f -e -d 4 -o ./docs ./honeybee_radiance_postprocess
|
78
|
+
sphinx-build -b html ./docs ./docs/_build/docs
|
79
|
+
```
|
@@ -0,0 +1,50 @@
|
|
1
|
+
honeybee_radiance_postprocess/__init__.py,sha256=kQXElEqFnLGNnrMSpA51XDHoqBup849FHeAqWASIy6w,45
|
2
|
+
honeybee_radiance_postprocess/__main__.py,sha256=-glg9xAgYK3-Pm5Kx_8cMUeaqUj62ZaHaDPBhrrUD94,104
|
3
|
+
honeybee_radiance_postprocess/annual.py,sha256=rVRgKXwJCDdXDJcBPqbt7aKIBR5EFQaVuFHP6ZbGDHI,2384
|
4
|
+
honeybee_radiance_postprocess/annualdaylight.py,sha256=nhD3a5MAVaDpU3Zt1pEoAIdYtpMc7xH5OZHkxGAnEaQ,11346
|
5
|
+
honeybee_radiance_postprocess/annualirradiance.py,sha256=1ZBUizL95S4uWfLh5B6Hwbu893LsNEyUuKz8dQsNe1M,1304
|
6
|
+
honeybee_radiance_postprocess/data_type.py,sha256=tCzPJ7dL97JOa1WPe4aSooaIpckhF4BfC1UJCEU6v2E,3740
|
7
|
+
honeybee_radiance_postprocess/dynamic.py,sha256=RPJh2SsjASYJCsG5QRkazVCvzWjzMxm9eeuinb3O8QA,9226
|
8
|
+
honeybee_radiance_postprocess/electriclight.py,sha256=f1HTIoYI8s8pOGdS50QHy9OA6_RVw7IwLYrIEvZTdvU,821
|
9
|
+
honeybee_radiance_postprocess/en17037.py,sha256=ejb84XyquVgmYK35d5TuM8msfA6LDF4OH-p__36GcCw,10888
|
10
|
+
honeybee_radiance_postprocess/helper.py,sha256=NzGWfEmYlSzg4CpTuB9PMRSpKCIbN7gsDLVcmj3pr0c,9428
|
11
|
+
honeybee_radiance_postprocess/metrics.py,sha256=Q7sMfSoVH366vMm3JWjF8rMnU-nc50QyG5n2MAq4kSk,14772
|
12
|
+
honeybee_radiance_postprocess/reader.py,sha256=fEuqU-87vloLofwMxdCLKV4ZXoW1eMOXydsTgUwMCFk,2762
|
13
|
+
honeybee_radiance_postprocess/type_hints.py,sha256=39kLNk9FxcQVGdL6bkP49jIFsf_1brP6r6w3khl9hqc,1212
|
14
|
+
honeybee_radiance_postprocess/util.py,sha256=h7fipG9it_cfIk-kFP3X_IassVmfmphPiLxpydW43R4,6295
|
15
|
+
honeybee_radiance_postprocess/vis_metadata.py,sha256=7ywIgdiuNKcctxifhpy7-Q2oaSX2ngQBeA0Kh7q1Gg0,1780
|
16
|
+
honeybee_radiance_postprocess/breeam/__init__.py,sha256=kQXElEqFnLGNnrMSpA51XDHoqBup849FHeAqWASIy6w,45
|
17
|
+
honeybee_radiance_postprocess/breeam/breeam.py,sha256=cSco6g0Qyv1XgfyY18Z9rabQfWPLGRBcYQumdMv5Y4k,20672
|
18
|
+
honeybee_radiance_postprocess/cli/__init__.py,sha256=_mYHnIOpH0qJ4QK56SB3qUT2Duuts2GR2U_0t_uE-2s,958
|
19
|
+
honeybee_radiance_postprocess/cli/abnt.py,sha256=X-z-VmSycIKnIJE4e-QeoEgVNIOOkUqonCMhV7noAaM,15793
|
20
|
+
honeybee_radiance_postprocess/cli/breeam.py,sha256=geLsR2NQe8DWEE2f0aY0rQCq_BbGpZXU0g48XdSu8WY,3255
|
21
|
+
honeybee_radiance_postprocess/cli/datacollection.py,sha256=2yA_JMv9WLS9oAJJyEXfoKTf2mlLDn73ZB1IKhLh_bo,4629
|
22
|
+
honeybee_radiance_postprocess/cli/grid.py,sha256=IMjfyw-XPaoSu550T_BuulRSawla8kYaxatbgf7Fgms,11344
|
23
|
+
honeybee_radiance_postprocess/cli/leed.py,sha256=vup_tVcSnSO5R7U_WPVDAhtSSRrPzTUgV4j9lyxvxEk,5546
|
24
|
+
honeybee_radiance_postprocess/cli/merge.py,sha256=NgQ5RM1-GrJQs_25IPzBvQ5PAn6oTKiB_N9SeHBxgCA,5840
|
25
|
+
honeybee_radiance_postprocess/cli/mtxop.py,sha256=pbQsc4EnzsRStBX1-KcgIKmuTlVYiG1IyNjiqbwS2V0,5103
|
26
|
+
honeybee_radiance_postprocess/cli/postprocess.py,sha256=Qvr5gEB9oQH4-4jww2ttxP1bWseBydxzRHymyrpcPWQ,39445
|
27
|
+
honeybee_radiance_postprocess/cli/schedule.py,sha256=6uIy98Co4zm-ZRcELo4Lfx_aN3lNiqPe-BSimXwt1F8,3877
|
28
|
+
honeybee_radiance_postprocess/cli/translate.py,sha256=W3G5aBN7pGx5sX3VoV1xZM6HL06Fw95iJb7vV-r6u7w,7396
|
29
|
+
honeybee_radiance_postprocess/cli/two_phase.py,sha256=njkWBRxOqdRSp0JxLloWTGWmKruyONetgnIbjXhrrXw,8393
|
30
|
+
honeybee_radiance_postprocess/cli/util.py,sha256=Be9cGmYhcV2W37ma6SgQPCWCpWLLLlroxRYN_l58kY0,4077
|
31
|
+
honeybee_radiance_postprocess/cli/viewfactor.py,sha256=RJ0ai9ykhdryYOgYkY9tAim9MhXPD1gVAR3Js9UaEgE,5380
|
32
|
+
honeybee_radiance_postprocess/cli/well.py,sha256=wWz-aWon4E_tLar0mepolW8WJdk6hF869wZPZSkbNrE,3772
|
33
|
+
honeybee_radiance_postprocess/ies/__init__.py,sha256=kQXElEqFnLGNnrMSpA51XDHoqBup849FHeAqWASIy6w,45
|
34
|
+
honeybee_radiance_postprocess/ies/lm.py,sha256=6oT4XzWwr6njKRBjY0xL9TzBqQUAeQLwzen57BHOp4E,9746
|
35
|
+
honeybee_radiance_postprocess/ies/lm_schedule.py,sha256=nZlORbRQvPiA8VeRfh7ML8cMAYUxmHOgsNCxAHuOr18,10042
|
36
|
+
honeybee_radiance_postprocess/leed/__init__.py,sha256=kQXElEqFnLGNnrMSpA51XDHoqBup849FHeAqWASIy6w,45
|
37
|
+
honeybee_radiance_postprocess/leed/leed.py,sha256=yGaUP_wR-BjEQgPmKUZCOuSVvITkiiIiCbEu2pYlSJw,35907
|
38
|
+
honeybee_radiance_postprocess/leed/leed_schedule.py,sha256=8NUISE6RbENK1IgMA5cC2-UorrvwwQi1rKPPZr0KNZE,10279
|
39
|
+
honeybee_radiance_postprocess/results/__init__.py,sha256=1agBQbfT4Tf8KqSZzlfKYX8MeZryY4jJ1KB4HWqaDDk,182
|
40
|
+
honeybee_radiance_postprocess/results/annual_daylight.py,sha256=ulv8kZvS6UkhCjaXSJKXQeVhUReRdx4M0tGvy7rA8CI,34586
|
41
|
+
honeybee_radiance_postprocess/results/annual_irradiance.py,sha256=nA1VubesNDtRxgXpHSZxFMV67XxUntIHIu5H9qtDBSk,8483
|
42
|
+
honeybee_radiance_postprocess/results/results.py,sha256=twfOF_ZNflxujWqpzigz4_pZ1vcSpF8cQxWIy7ajt0Y,56378
|
43
|
+
honeybee_radiance_postprocess/well/__init__.py,sha256=kQXElEqFnLGNnrMSpA51XDHoqBup849FHeAqWASIy6w,45
|
44
|
+
honeybee_radiance_postprocess/well/well.py,sha256=KO0BOs4-P_PnsGFfasoz1xgaNac4zqOQ9JqTjmMapuU,22598
|
45
|
+
honeybee_radiance_postprocess-0.4.555.dist-info/licenses/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
|
46
|
+
honeybee_radiance_postprocess-0.4.555.dist-info/METADATA,sha256=EDzS6YTr5oFuFMH4tLAsTvQ8h5Rjibn1U4xWqD4MtUo,2575
|
47
|
+
honeybee_radiance_postprocess-0.4.555.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
48
|
+
honeybee_radiance_postprocess-0.4.555.dist-info/entry_points.txt,sha256=gFtVPx6UItXt27GfEZZO00eOZChJJEL6JwGSAB_O3rs,96
|
49
|
+
honeybee_radiance_postprocess-0.4.555.dist-info/top_level.txt,sha256=4-sFbzy7ewP2EDqJV3jeFlAFx7SuxtoBBELWaKAnLdA,30
|
50
|
+
honeybee_radiance_postprocess-0.4.555.dist-info/RECORD,,
|