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 @@
|
|
1
|
+
"""honeybee-radiance-postprocess library."""
|
@@ -0,0 +1,73 @@
|
|
1
|
+
"""Shared functions for post-processing annual results."""
|
2
|
+
from typing import Union
|
3
|
+
try:
|
4
|
+
import cupy as np
|
5
|
+
is_gpu = True
|
6
|
+
except ImportError:
|
7
|
+
is_gpu = False
|
8
|
+
import numpy as np
|
9
|
+
|
10
|
+
from ladybug.analysisperiod import AnalysisPeriod
|
11
|
+
from .util import filter_array
|
12
|
+
|
13
|
+
is_cpu = not is_gpu
|
14
|
+
|
15
|
+
|
16
|
+
def occupancy_schedule_8_to_6(
|
17
|
+
timestep: int = 1, as_list: bool = False) -> Union[np.ndarray, list]:
|
18
|
+
"""Create an occupancy schedule for LEED (8 am to 6 pm).
|
19
|
+
|
20
|
+
Args:
|
21
|
+
timestep: An integer value noting the number of timesteps per hour.
|
22
|
+
Defaults to 1.
|
23
|
+
as_list: Boolean toggle to output the schedule as a Python list instead
|
24
|
+
of a NumPy array. Defaults to False.
|
25
|
+
|
26
|
+
Returns:
|
27
|
+
A schedule as an array or list.
|
28
|
+
"""
|
29
|
+
full_analysis_period = np.array(AnalysisPeriod(timestep=timestep).hoys)
|
30
|
+
analysis_period = np.array(AnalysisPeriod(st_hour=8, end_hour=17, timestep=timestep).hoys)
|
31
|
+
schedule = np.zeros(8760 * timestep).astype(int)
|
32
|
+
hours = np.where(np.isin(full_analysis_period, analysis_period))[0]
|
33
|
+
schedule[hours] = 1
|
34
|
+
if as_list:
|
35
|
+
schedule = schedule.tolist()
|
36
|
+
|
37
|
+
return schedule
|
38
|
+
|
39
|
+
|
40
|
+
def schedule_to_hoys(
|
41
|
+
schedule: Union[list, np.ndarray],
|
42
|
+
sun_up_hours: Union[list, np.ndarray] = None, as_list: bool = False
|
43
|
+
) -> Union[np.ndarray, list]:
|
44
|
+
"""Convert a schedule to hoys.
|
45
|
+
|
46
|
+
Args:
|
47
|
+
schedule: A list of 8760 values for the occupancy schedule.
|
48
|
+
sun_up_hours: An optional list of sun up hours as integers. If sun up
|
49
|
+
hours are provided the function will exclude all values from the
|
50
|
+
schedule that are not among the sun up hours. Defaults to None.
|
51
|
+
as_list: Boolean toggle to output the schedule as a Python list instead
|
52
|
+
of a NumPy array. Defaults to False.
|
53
|
+
|
54
|
+
Returns:
|
55
|
+
An array or list of occupancy expressed as hoys.
|
56
|
+
"""
|
57
|
+
assert len(schedule) == 8760
|
58
|
+
if not isinstance(schedule, np.ndarray):
|
59
|
+
schedule = np.array(schedule).astype(int)
|
60
|
+
|
61
|
+
hours = np.arange(0, 8760, 1)
|
62
|
+
if sun_up_hours:
|
63
|
+
sun_up_hours = np.array(sun_up_hours).astype(int)
|
64
|
+
mask = np.ones(schedule.size, dtype=bool)
|
65
|
+
mask[sun_up_hours] = False
|
66
|
+
schedule[mask] = 0
|
67
|
+
|
68
|
+
occ_hoys = filter_array(hours, np.array(schedule))
|
69
|
+
|
70
|
+
if as_list:
|
71
|
+
occ_hoys = occ_hoys.tolist()
|
72
|
+
|
73
|
+
return occ_hoys
|
@@ -0,0 +1,289 @@
|
|
1
|
+
"""Functions for post-processing annual daylight outputs.
|
2
|
+
|
3
|
+
Note: These functions will most likely be moved to a separate package in the near future.
|
4
|
+
"""
|
5
|
+
import json
|
6
|
+
import os
|
7
|
+
try:
|
8
|
+
import cupy as np
|
9
|
+
is_gpu = True
|
10
|
+
except ImportError:
|
11
|
+
is_gpu = False
|
12
|
+
import numpy as np
|
13
|
+
|
14
|
+
from ladybug.color import Colorset
|
15
|
+
from ladybug.datatype.fraction import Fraction
|
16
|
+
from ladybug.legend import LegendParameters
|
17
|
+
from honeybee_radiance.postprocess.annual import filter_schedule_by_hours, \
|
18
|
+
_process_input_folder
|
19
|
+
|
20
|
+
from .metrics import da_array2d, cda_array2d, udi_array2d, \
|
21
|
+
udi_lower_array2d, udi_upper_array2d
|
22
|
+
from .util import filter_array
|
23
|
+
|
24
|
+
|
25
|
+
def metrics_to_files(ill_file, occ_pattern, output_folder, threshold=300,
|
26
|
+
min_t=100, max_t=3000, grid_name=None, total_hours=None,
|
27
|
+
sun_down_occ_hours=0):
|
28
|
+
"""Compute annual metrics for an ill file and write the results to a folder.
|
29
|
+
|
30
|
+
This function generates 5 different files or daylight autonomy, continuous daylight
|
31
|
+
autonomy, lower than useful daylight illuminance, useful daylight illuminance and
|
32
|
+
higher than useful daylight illuminance.
|
33
|
+
|
34
|
+
Args:
|
35
|
+
ill_file: Path to an ill file generated by Radiance. The ill file should be
|
36
|
+
tab separated and shot NOT have a header. The results for each sensor point
|
37
|
+
should be available in a row and and each column should be the illuminance
|
38
|
+
value for a sun_up_hour. The number of columns should match the number of
|
39
|
+
sun up hours.
|
40
|
+
occ_pattern: A list of 0 and 1 values for hours of occupancy.
|
41
|
+
output_folder: An output folder where the results will be written to. The folder
|
42
|
+
will be created if not exist.
|
43
|
+
threshold: Threshold illuminance level for daylight autonomy. Default: 300.
|
44
|
+
min_t: Minimum threshold for useful daylight illuminance. Default: 100.
|
45
|
+
max_t: Maximum threshold for useful daylight illuminance. Default: 3000.
|
46
|
+
grid_name: An optional name for grid name which will be used to name the output
|
47
|
+
files. If None the name of the input file will be used.
|
48
|
+
total_hours: An integer for the total number of occupied hours in the
|
49
|
+
occupancy schedule. If None, it will be assumed that all of the
|
50
|
+
occupied hours are sun-up hours and are already accounted for
|
51
|
+
in the the occ_pattern.
|
52
|
+
|
53
|
+
Returns:
|
54
|
+
Tuple(file.da, file.cda, file.udi, file.udi, file.udi)
|
55
|
+
|
56
|
+
"""
|
57
|
+
if not os.path.isdir(output_folder):
|
58
|
+
os.makedirs(output_folder)
|
59
|
+
|
60
|
+
grid_name = grid_name or os.path.split(ill_file)[-1][-4:]
|
61
|
+
da = os.path.join(output_folder, 'da', '%s.da' % grid_name).replace('\\', '/')
|
62
|
+
cda = os.path.join(output_folder, 'cda', '%s.cda' % grid_name).replace('\\', '/')
|
63
|
+
udi = os.path.join(output_folder, 'udi', '%s.udi' % grid_name).replace('\\', '/')
|
64
|
+
udi_lower = \
|
65
|
+
os.path.join(output_folder, 'udi_lower', '%s.udi' % grid_name).replace('\\', '/')
|
66
|
+
udi_upper = \
|
67
|
+
os.path.join(output_folder, 'udi_upper', '%s.udi' % grid_name).replace('\\', '/')
|
68
|
+
|
69
|
+
for file_path in [da, cda, udi, udi_upper, udi_lower]:
|
70
|
+
folder = os.path.dirname(file_path)
|
71
|
+
if not os.path.isdir(folder):
|
72
|
+
os.makedirs(folder)
|
73
|
+
|
74
|
+
mask = np.array(occ_pattern)
|
75
|
+
results = np.load(ill_file)
|
76
|
+
results_occ = np.apply_along_axis(filter_array, 1, results, mask=mask)
|
77
|
+
|
78
|
+
dar = da_array2d(results_occ, total_occ=total_hours, threshold=threshold)
|
79
|
+
np.savetxt(da, dar, fmt='%.2f')
|
80
|
+
|
81
|
+
cdar = cda_array2d(results_occ, total_occ=total_hours, threshold=threshold)
|
82
|
+
np.savetxt(cda, cdar, fmt='%.2f')
|
83
|
+
|
84
|
+
udir = udi_array2d(results_occ, total_occ=total_hours, min_t=min_t, max_t=max_t)
|
85
|
+
np.savetxt(udi, udir, fmt='%.2f')
|
86
|
+
|
87
|
+
udi_lowerr = udi_lower_array2d(results_occ, total_occ=total_hours, min_t=min_t,
|
88
|
+
sun_down_occ_hours=sun_down_occ_hours)
|
89
|
+
np.savetxt(udi_lower, udi_lowerr, fmt='%.2f')
|
90
|
+
|
91
|
+
udi_upperr = udi_upper_array2d(results_occ, total_occ=total_hours, max_t=max_t)
|
92
|
+
np.savetxt(udi_upper, udi_upperr, fmt='%.2f')
|
93
|
+
|
94
|
+
return da, cda, udi_lower, udi, udi_upper
|
95
|
+
|
96
|
+
|
97
|
+
# TODO - support a list of schedules/schedule folder to match the input grids
|
98
|
+
def metrics_to_folder(
|
99
|
+
results_folder, schedule=None, threshold=300, min_t=100, max_t=3000,
|
100
|
+
grids_filter='*', sub_folder='metrics'
|
101
|
+
):
|
102
|
+
"""Compute annual metrics in a folder and write them in a subfolder.
|
103
|
+
|
104
|
+
This folder is an output folder of annual daylight recipe. Folder should include
|
105
|
+
grids_info.json and sun-up-hours.txt - the script uses the list in grids_info.json
|
106
|
+
to find the result files for each sensor grid.
|
107
|
+
|
108
|
+
Args:
|
109
|
+
results_folder: Results folder.
|
110
|
+
schedule: An annual schedule for 8760 hours of the year as a list of values.
|
111
|
+
threshold: Threshold illuminance level for daylight autonomy. Default: 300.
|
112
|
+
min_t: Minimum threshold for useful daylight illuminance. Default: 100.
|
113
|
+
max_t: Maximum threshold for useful daylight illuminance. Default: 3000.
|
114
|
+
grids_filter: A pattern to filter the grids. By default all the grids will be
|
115
|
+
processed.
|
116
|
+
sub_folder: An optional relative path for subfolder to copy results files.
|
117
|
+
Default: metrics
|
118
|
+
|
119
|
+
Returns:
|
120
|
+
str -- Path to results folder.
|
121
|
+
|
122
|
+
"""
|
123
|
+
grids, sun_up_hours = _process_input_folder(results_folder, grids_filter)
|
124
|
+
occ_pattern, total_occ, sun_down_occ_hours = \
|
125
|
+
filter_schedule_by_hours(sun_up_hours=sun_up_hours, schedule=schedule)
|
126
|
+
|
127
|
+
metrics_folder = os.path.join(results_folder, sub_folder)
|
128
|
+
if not os.path.isdir(metrics_folder):
|
129
|
+
os.makedirs(metrics_folder)
|
130
|
+
|
131
|
+
for grid in grids:
|
132
|
+
ill_file = os.path.join(results_folder, '%s.npy' % grid['full_id'])
|
133
|
+
metrics_to_files(
|
134
|
+
ill_file, occ_pattern, metrics_folder, threshold, min_t,
|
135
|
+
max_t, grid['full_id'], total_occ, sun_down_occ_hours
|
136
|
+
)
|
137
|
+
|
138
|
+
# copy info.json to all results folders
|
139
|
+
for folder_name in ['da', 'cda', 'udi_lower', 'udi', 'udi_upper']:
|
140
|
+
grid_info = os.path.join(metrics_folder, folder_name, 'grids_info.json')
|
141
|
+
with open(grid_info, 'w') as outf:
|
142
|
+
json.dump(grids, outf)
|
143
|
+
|
144
|
+
metric_info_dict = _annual_daylight_vis_metadata()
|
145
|
+
for metric, data in metric_info_dict.items():
|
146
|
+
file_path = os.path.join(metrics_folder, metric, 'vis_metadata.json')
|
147
|
+
with open(file_path, 'w') as fp:
|
148
|
+
json.dump(data, fp, indent=4)
|
149
|
+
|
150
|
+
return metrics_folder
|
151
|
+
|
152
|
+
|
153
|
+
def _annual_daylight_vis_metadata():
|
154
|
+
"""Return visualization metadata for annual daylight."""
|
155
|
+
udi_l_lpar = LegendParameters(min=0, max=100, colors=Colorset.nuanced())
|
156
|
+
udi_u_lpar = LegendParameters(min=0, max=100, colors=Colorset.glare_study())
|
157
|
+
udi_lpar = LegendParameters(min=0, max=100, colors=Colorset.annual_comfort())
|
158
|
+
cda_lpar = LegendParameters(min=0, max=100, colors=Colorset.annual_comfort())
|
159
|
+
da_lpar = LegendParameters(min=0, max=100, colors=Colorset.annual_comfort())
|
160
|
+
|
161
|
+
metric_info_dict = {
|
162
|
+
'udi_lower': {
|
163
|
+
'type': 'VisualizationMetaData',
|
164
|
+
'data_type': Fraction('Useful Daylight Illuminance Lower').to_dict(),
|
165
|
+
'unit': '%',
|
166
|
+
'legend_parameters': udi_l_lpar.to_dict()
|
167
|
+
},
|
168
|
+
'udi_upper': {
|
169
|
+
'type': 'VisualizationMetaData',
|
170
|
+
'data_type': Fraction('Useful Daylight Illuminance Upper').to_dict(),
|
171
|
+
'unit': '%',
|
172
|
+
'legend_parameters': udi_u_lpar.to_dict()
|
173
|
+
},
|
174
|
+
'udi': {
|
175
|
+
'type': 'VisualizationMetaData',
|
176
|
+
'data_type': Fraction('Useful Daylight Illuminance').to_dict(),
|
177
|
+
'unit': '%',
|
178
|
+
'legend_parameters': udi_lpar.to_dict()
|
179
|
+
},
|
180
|
+
'cda': {
|
181
|
+
'type': 'VisualizationMetaData',
|
182
|
+
'data_type': Fraction('Continuous Daylight Autonomy').to_dict(),
|
183
|
+
'unit': '%',
|
184
|
+
'legend_parameters': cda_lpar.to_dict()
|
185
|
+
},
|
186
|
+
'da': {
|
187
|
+
'type': 'VisualizationMetaData',
|
188
|
+
'data_type': Fraction('Daylight Autonomy').to_dict(),
|
189
|
+
'unit': '%',
|
190
|
+
'legend_parameters': da_lpar.to_dict()
|
191
|
+
}
|
192
|
+
}
|
193
|
+
|
194
|
+
return metric_info_dict
|
195
|
+
|
196
|
+
|
197
|
+
def _annual_daylight_config():
|
198
|
+
"""Return vtk-config for annual daylight. """
|
199
|
+
cfg = {
|
200
|
+
"data": [
|
201
|
+
{
|
202
|
+
"identifier": "Useful Daylight Illuminance Lower",
|
203
|
+
"object_type": "grid",
|
204
|
+
"unit": "Percentage",
|
205
|
+
"path": "udi_lower",
|
206
|
+
"hide": False,
|
207
|
+
"legend_parameters": {
|
208
|
+
"hide_legend": False,
|
209
|
+
"min": 0,
|
210
|
+
"max": 100,
|
211
|
+
"color_set": "nuanced",
|
212
|
+
},
|
213
|
+
},
|
214
|
+
{
|
215
|
+
"identifier": "Useful Daylight Illuminance Upper",
|
216
|
+
"object_type": "grid",
|
217
|
+
"unit": "Percentage",
|
218
|
+
"path": "udi_upper",
|
219
|
+
"hide": False,
|
220
|
+
"legend_parameters": {
|
221
|
+
"hide_legend": False,
|
222
|
+
"min": 0,
|
223
|
+
"max": 100,
|
224
|
+
"color_set": "glare_study",
|
225
|
+
"label_parameters": {
|
226
|
+
"color": [34, 247, 10],
|
227
|
+
"size": 0,
|
228
|
+
"bold": True,
|
229
|
+
},
|
230
|
+
},
|
231
|
+
},
|
232
|
+
{
|
233
|
+
"identifier": "Useful Daylight Illuminance",
|
234
|
+
"object_type": "grid",
|
235
|
+
"unit": "Percentage",
|
236
|
+
"path": "udi",
|
237
|
+
"hide": False,
|
238
|
+
"legend_parameters": {
|
239
|
+
"hide_legend": False,
|
240
|
+
"min": 0,
|
241
|
+
"max": 100,
|
242
|
+
"color_set": "annual_comfort",
|
243
|
+
"label_parameters": {
|
244
|
+
"color": [34, 247, 10],
|
245
|
+
"size": 0,
|
246
|
+
"bold": True,
|
247
|
+
},
|
248
|
+
},
|
249
|
+
},
|
250
|
+
{
|
251
|
+
"identifier": "Continuous Daylight Autonomy",
|
252
|
+
"object_type": "grid",
|
253
|
+
"unit": "Percentage",
|
254
|
+
"path": "cda",
|
255
|
+
"hide": False,
|
256
|
+
"legend_parameters": {
|
257
|
+
"hide_legend": False,
|
258
|
+
"min": 0,
|
259
|
+
"max": 100,
|
260
|
+
"color_set": "annual_comfort",
|
261
|
+
"label_parameters": {
|
262
|
+
"color": [34, 247, 10],
|
263
|
+
"size": 0,
|
264
|
+
"bold": True,
|
265
|
+
},
|
266
|
+
},
|
267
|
+
},
|
268
|
+
{
|
269
|
+
"identifier": "Daylight Autonomy",
|
270
|
+
"object_type": "grid",
|
271
|
+
"unit": "Percentage",
|
272
|
+
"path": "da",
|
273
|
+
"hide": False,
|
274
|
+
"legend_parameters": {
|
275
|
+
"hide_legend": False,
|
276
|
+
"min": 0,
|
277
|
+
"max": 100,
|
278
|
+
"color_set": "annual_comfort",
|
279
|
+
"label_parameters": {
|
280
|
+
"color": [34, 247, 10],
|
281
|
+
"size": 0,
|
282
|
+
"bold": True,
|
283
|
+
},
|
284
|
+
},
|
285
|
+
},
|
286
|
+
]
|
287
|
+
}
|
288
|
+
|
289
|
+
return cfg
|
@@ -0,0 +1,35 @@
|
|
1
|
+
"""Functions for post-processing annual irradiance outputs."""
|
2
|
+
|
3
|
+
from ladybug.datatype.energyflux import EnergyFlux
|
4
|
+
from ladybug.datatype.energyintensity import EnergyIntensity
|
5
|
+
from ladybug.legend import LegendParameters
|
6
|
+
|
7
|
+
|
8
|
+
def _annual_irradiance_vis_metadata():
|
9
|
+
"""Return visualization metadata for annual irradiance."""
|
10
|
+
cumulative_radiation_lpar = LegendParameters(min=0)
|
11
|
+
peak_irradiance_lpar = LegendParameters(min=0)
|
12
|
+
average_irradiance_lpar = LegendParameters(min=0)
|
13
|
+
|
14
|
+
metric_info_dict = {
|
15
|
+
'cumulative_radiation': {
|
16
|
+
'type': 'VisualizationMetaData',
|
17
|
+
'data_type': EnergyIntensity('Cumulative Radiance').to_dict(),
|
18
|
+
'unit': 'kWh/m2',
|
19
|
+
'legend_parameters': cumulative_radiation_lpar.to_dict()
|
20
|
+
},
|
21
|
+
'peak_irradiance': {
|
22
|
+
'type': 'VisualizationMetaData',
|
23
|
+
'data_type': EnergyFlux('Peak Irradiance').to_dict(),
|
24
|
+
'unit': 'W/m2',
|
25
|
+
'legend_parameters': peak_irradiance_lpar.to_dict()
|
26
|
+
},
|
27
|
+
'average_irradiance': {
|
28
|
+
'type': 'VisualizationMetaData',
|
29
|
+
'data_type': EnergyFlux('Average Irradiance').to_dict(),
|
30
|
+
'unit': 'W/m2',
|
31
|
+
'legend_parameters': average_irradiance_lpar.to_dict()
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
return metric_info_dict
|
@@ -0,0 +1 @@
|
|
1
|
+
"""honeybee-radiance-postprocess library."""
|