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,38 @@
|
|
1
|
+
"""Type hints for honeybee-radiance-postprocess."""
|
2
|
+
from typing import Tuple, List
|
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.datacollection import HourlyContinuousCollection
|
11
|
+
|
12
|
+
|
13
|
+
annual_metric = Tuple[List[np.ndarray], List[dict]]
|
14
|
+
annual_daylight_metrics = Tuple[
|
15
|
+
List[np.ndarray],
|
16
|
+
List[np.ndarray],
|
17
|
+
List[np.ndarray],
|
18
|
+
List[np.ndarray],
|
19
|
+
List[np.ndarray],
|
20
|
+
List[dict]
|
21
|
+
]
|
22
|
+
annual_irradiance_metrics = Tuple[
|
23
|
+
List[np.ndarray],
|
24
|
+
List[np.ndarray],
|
25
|
+
List[np.ndarray],
|
26
|
+
List[dict]
|
27
|
+
]
|
28
|
+
spatial_daylight_autonomy = Tuple[List[np.float64], List[dict]]
|
29
|
+
annual_sunlight_exposure = Tuple[List[np.float64], List[np.ndarray], List[dict]]
|
30
|
+
total = Tuple[List[np.ndarray], List[dict]]
|
31
|
+
point_in_time = Tuple[List[np.ndarray], List[dict]]
|
32
|
+
average_values = Tuple[List[np.ndarray], List[dict]]
|
33
|
+
median_values = Tuple[List[np.ndarray], List[dict]]
|
34
|
+
cumulative_values = Tuple[List[np.ndarray], List[dict]]
|
35
|
+
peak_values = Tuple[List[np.ndarray], List[dict]]
|
36
|
+
annual_data = Tuple[List[List[HourlyContinuousCollection]], List[dict], dict]
|
37
|
+
annual_uniformity_ratio = \
|
38
|
+
Tuple[List[float], List[HourlyContinuousCollection], List[dict]]
|
@@ -0,0 +1,211 @@
|
|
1
|
+
"""Post-processing utility functions."""
|
2
|
+
from typing import Tuple
|
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 honeybee_radiance.writer import _filter_by_pattern
|
11
|
+
|
12
|
+
is_cpu = not is_gpu
|
13
|
+
|
14
|
+
|
15
|
+
def binary_mtx_dimension(filepath: str) -> Tuple[int, int, int, int, str]:
|
16
|
+
"""Return binary Radiance matrix dimensions if exist.
|
17
|
+
|
18
|
+
This function returns NROWS, NCOLS, NCOMP and number of header lines including the
|
19
|
+
white line after last header line.
|
20
|
+
|
21
|
+
Args:
|
22
|
+
filepath: Full path to Radiance file.
|
23
|
+
|
24
|
+
Returns:
|
25
|
+
nrows, ncols, ncomp, line_count, fmt
|
26
|
+
"""
|
27
|
+
try:
|
28
|
+
inf = open(filepath, 'rb', encoding='utf-8')
|
29
|
+
except Exception:
|
30
|
+
inf = open(filepath, 'rb')
|
31
|
+
try:
|
32
|
+
first_line = next(inf).rstrip().decode('utf-8')
|
33
|
+
if first_line[:10] != '#?RADIANCE':
|
34
|
+
error_message = (
|
35
|
+
f'File with Radiance header must start with #?RADIANCE not '
|
36
|
+
f'{first_line}.'
|
37
|
+
)
|
38
|
+
raise ValueError(error_message)
|
39
|
+
|
40
|
+
header_lines = [first_line]
|
41
|
+
nrows = ncols = ncomp = None
|
42
|
+
for line in inf:
|
43
|
+
line = line.rstrip().decode('utf-8')
|
44
|
+
header_lines.append(line)
|
45
|
+
if line[:6] == 'NROWS=':
|
46
|
+
nrows = int(line.split('=')[-1])
|
47
|
+
if line[:6] == 'NCOLS=':
|
48
|
+
ncols = int(line.split('=')[-1])
|
49
|
+
if line[:6] == 'NCOMP=':
|
50
|
+
ncomp = int(line.split('=')[-1])
|
51
|
+
if line[:7] == 'FORMAT=':
|
52
|
+
fmt = line.split('=')[-1]
|
53
|
+
break
|
54
|
+
|
55
|
+
if not nrows or not ncols:
|
56
|
+
error_message = (
|
57
|
+
f'NROWS or NCOLS was not found in the Radiance header. NROWS '
|
58
|
+
f'is {nrows} and NCOLS is {ncols}. The header must have both '
|
59
|
+
f'elements.'
|
60
|
+
)
|
61
|
+
raise ValueError(error_message)
|
62
|
+
return nrows, ncols, ncomp, len(header_lines) + 1, fmt
|
63
|
+
finally:
|
64
|
+
inf.close()
|
65
|
+
|
66
|
+
|
67
|
+
def check_array_dim(array: np.ndarray, dim: int):
|
68
|
+
"""Check NumPy array dimension.
|
69
|
+
|
70
|
+
Args:
|
71
|
+
array: A NumPy array.
|
72
|
+
dim: The dimension to check against.
|
73
|
+
"""
|
74
|
+
assert array.ndim == dim, \
|
75
|
+
f'Expected {dim}-dimensional array. Dimension of array is {array.ndim}'
|
76
|
+
|
77
|
+
|
78
|
+
def filter_array2d(array: np.ndarray, mask: np.ndarray) -> np.ndarray:
|
79
|
+
"""Filter a NumPy array by a masking array. The array will be passed as is
|
80
|
+
if the mask is None.
|
81
|
+
|
82
|
+
Args:
|
83
|
+
array: A NumPy array to filter.
|
84
|
+
mask: A NumPy array of ones/zeros or True/False.
|
85
|
+
|
86
|
+
Returns:
|
87
|
+
A filtered NumPy array.
|
88
|
+
"""
|
89
|
+
if is_cpu:
|
90
|
+
array_filter = np.apply_along_axis(
|
91
|
+
filter_array, 1, array, mask=mask)
|
92
|
+
else:
|
93
|
+
mask = np.asarray(mask).astype(bool)
|
94
|
+
array_filter = array[:, mask]
|
95
|
+
|
96
|
+
return array_filter
|
97
|
+
|
98
|
+
|
99
|
+
def filter_array(array: np.ndarray, mask: np.ndarray) -> np.ndarray:
|
100
|
+
"""Filter a NumPy array by a masking array. The array will be passed as is
|
101
|
+
if the mask is None.
|
102
|
+
|
103
|
+
Args:
|
104
|
+
array: A NumPy array to filter.
|
105
|
+
mask: A NumPy array of ones/zeros or True/False.
|
106
|
+
|
107
|
+
Returns:
|
108
|
+
A filtered NumPy array.
|
109
|
+
"""
|
110
|
+
if mask is not None:
|
111
|
+
return array[mask.astype(bool)]
|
112
|
+
return array
|
113
|
+
|
114
|
+
|
115
|
+
def hoys_mask(sun_up_hours: list, hoys: list) -> np.ndarray:
|
116
|
+
"""Create a NumPy masking array from a list of hoys.
|
117
|
+
|
118
|
+
Args:
|
119
|
+
sun_up_hours: A list of sun up hours.
|
120
|
+
hoys: A list hoys to select.
|
121
|
+
|
122
|
+
Returns:
|
123
|
+
A NumPy array of booleans.
|
124
|
+
"""
|
125
|
+
if len(hoys) != 0:
|
126
|
+
hoys_mask = np.where(np.isin(np.array(sun_up_hours), np.array(hoys)), True, False)
|
127
|
+
return hoys_mask
|
128
|
+
|
129
|
+
|
130
|
+
def array_memory_size(
|
131
|
+
sensors: int, sun_up_hours: int, ncomp: int = None,
|
132
|
+
dtype: np.dtype = np.float32, gigabyte: bool = True) -> float:
|
133
|
+
"""Calculate the memory size of an array before creating or loading an
|
134
|
+
array.
|
135
|
+
|
136
|
+
Args:
|
137
|
+
sensors: Number of sensors in the array.
|
138
|
+
sun_up_hours: Number of sun up hours in the array.
|
139
|
+
ncomp: Optional number of components for each element in the array,
|
140
|
+
e.g., if the data is in RGB format then this value must be set
|
141
|
+
to 3. Defaults to None.
|
142
|
+
dtype: The data type of the array. Defaults to np.float32.
|
143
|
+
gigabyte: Boolean toggle to output the memory size in gigabytes.
|
144
|
+
Defaults to True.
|
145
|
+
|
146
|
+
Returns:
|
147
|
+
float: The memory size of an array.
|
148
|
+
"""
|
149
|
+
# check if dtype is valid
|
150
|
+
dtypes = tuple(np.sctypes['float'])
|
151
|
+
if not isinstance(dtype, dtypes):
|
152
|
+
try:
|
153
|
+
dtype = dtype()
|
154
|
+
except TypeError as err:
|
155
|
+
error_message = (
|
156
|
+
f'Unable to instantiate input dtype. Expected any of the '
|
157
|
+
f'following: {dtypes}. Received: {type(dtype)}.'
|
158
|
+
)
|
159
|
+
raise TypeError(error_message) from err
|
160
|
+
|
161
|
+
# calculate memory size
|
162
|
+
size = sensors * sun_up_hours * dtype.itemsize
|
163
|
+
if ncomp:
|
164
|
+
size *= ncomp
|
165
|
+
if gigabyte:
|
166
|
+
size /= (1024 ** 3)
|
167
|
+
|
168
|
+
return size
|
169
|
+
|
170
|
+
|
171
|
+
def recursive_dict_merge(dict_1: dict, dict_2: dict):
|
172
|
+
"""Recursive merging of two dictionaries.
|
173
|
+
|
174
|
+
Args:
|
175
|
+
dict_1: Original dictionary.
|
176
|
+
dict_2: Dictionary to merge with dict_1.
|
177
|
+
"""
|
178
|
+
for k in dict_2:
|
179
|
+
if (k in dict_1 and isinstance(dict_1[k], dict) and
|
180
|
+
isinstance(dict_2[k], dict)):
|
181
|
+
recursive_dict_merge(dict_1[k], dict_2[k])
|
182
|
+
else:
|
183
|
+
dict_1[k] = dict_2[k]
|
184
|
+
|
185
|
+
|
186
|
+
def _filter_grids_by_pattern(grids_info, filter_pattern):
|
187
|
+
"""Filter grids_info by a pattern.
|
188
|
+
|
189
|
+
Args:
|
190
|
+
grids_info: Grid information.
|
191
|
+
filter_pattern: Pattern to filter grids by.
|
192
|
+
|
193
|
+
Returns:
|
194
|
+
A list of filtered grids.
|
195
|
+
"""
|
196
|
+
grids = _filter_by_pattern(grids_info, filter=filter_pattern)
|
197
|
+
|
198
|
+
return grids
|
199
|
+
|
200
|
+
|
201
|
+
def get_delimiter(delimiter_input):
|
202
|
+
if delimiter_input == 'tab' or delimiter_input == '\t':
|
203
|
+
return '\t'
|
204
|
+
elif delimiter_input == 'space' or delimiter_input == ' ':
|
205
|
+
return ' '
|
206
|
+
elif delimiter_input == 'comma' or delimiter_input == ',':
|
207
|
+
return ','
|
208
|
+
elif delimiter_input == 'semicolon' or delimiter_input == ';':
|
209
|
+
return ';'
|
210
|
+
else:
|
211
|
+
raise ValueError(f'Unsupported delimiter: {delimiter_input}')
|
@@ -0,0 +1,49 @@
|
|
1
|
+
"""Functions for visualization metadata."""
|
2
|
+
from ladybug.legend import LegendParameters
|
3
|
+
from ladybug.color import Color
|
4
|
+
from ladybug.datatype.generic import GenericType
|
5
|
+
|
6
|
+
|
7
|
+
def _abnt_nbr_15575_daylight_levels_vis_metadata():
|
8
|
+
"""Return visualization metadata for ABNT NBR 15575 Daylight levels."""
|
9
|
+
level_value = {
|
10
|
+
0: 'Não atende',
|
11
|
+
1: 'Mínimo',
|
12
|
+
2: 'Intermediário',
|
13
|
+
3: 'Superior'
|
14
|
+
}
|
15
|
+
|
16
|
+
colors = [Color(255, 198, 143), Color(255, 255, 209), Color(192, 231, 189), Color(83, 169, 206)]
|
17
|
+
illuminance_levels_lpar = \
|
18
|
+
LegendParameters(min=0, max=3, colors=colors, segment_count=4,
|
19
|
+
title='Níveis de iluminamento')
|
20
|
+
illuminance_levels_lpar.ordinal_dictionary = level_value
|
21
|
+
|
22
|
+
metric_info_dict = {
|
23
|
+
'4_930AM': {
|
24
|
+
'type': 'VisualizationMetaData',
|
25
|
+
'data_type': GenericType('23 de abril 9:30h', '').to_dict(),
|
26
|
+
'unit': '',
|
27
|
+
'legend_parameters': illuminance_levels_lpar.to_dict()
|
28
|
+
},
|
29
|
+
'4_330PM': {
|
30
|
+
'type': 'VisualizationMetaData',
|
31
|
+
'data_type': GenericType('23 de abril 15:30h', '').to_dict(),
|
32
|
+
'unit': '',
|
33
|
+
'legend_parameters': illuminance_levels_lpar.to_dict()
|
34
|
+
},
|
35
|
+
'10_930AM': {
|
36
|
+
'type': 'VisualizationMetaData',
|
37
|
+
'data_type': GenericType('23 de outubro 9:30h', '').to_dict(),
|
38
|
+
'unit': '',
|
39
|
+
'legend_parameters': illuminance_levels_lpar.to_dict()
|
40
|
+
},
|
41
|
+
'10_330PM': {
|
42
|
+
'type': 'VisualizationMetaData',
|
43
|
+
'data_type': GenericType('23 de outubro 15:30h', '').to_dict(),
|
44
|
+
'unit': '',
|
45
|
+
'legend_parameters': illuminance_levels_lpar.to_dict()
|
46
|
+
}
|
47
|
+
}
|
48
|
+
|
49
|
+
return metric_info_dict
|
@@ -0,0 +1 @@
|
|
1
|
+
"""honeybee-radiance-postprocess library."""
|