honeybee-radiance-postprocess 0.4.226__tar.gz → 0.4.228__tar.gz
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-0.4.226 → honeybee-radiance-postprocess-0.4.228}/PKG-INFO +1 -1
- {honeybee-radiance-postprocess-0.4.226 → honeybee-radiance-postprocess-0.4.228}/honeybee_radiance_postprocess/cli/postprocess.py +70 -8
- {honeybee-radiance-postprocess-0.4.226 → honeybee-radiance-postprocess-0.4.228}/honeybee_radiance_postprocess/cli/translate.py +70 -1
- honeybee-radiance-postprocess-0.4.228/honeybee_radiance_postprocess/helper.py +177 -0
- {honeybee-radiance-postprocess-0.4.226 → honeybee-radiance-postprocess-0.4.228}/honeybee_radiance_postprocess.egg-info/PKG-INFO +1 -1
- honeybee-radiance-postprocess-0.4.226/honeybee_radiance_postprocess/helper.py +0 -159
- {honeybee-radiance-postprocess-0.4.226 → honeybee-radiance-postprocess-0.4.228}/CODE_OF_CONDUCT.md +0 -0
- {honeybee-radiance-postprocess-0.4.226 → honeybee-radiance-postprocess-0.4.228}/CONTRIBUTING.md +0 -0
- {honeybee-radiance-postprocess-0.4.226 → honeybee-radiance-postprocess-0.4.228}/LICENSE +0 -0
- {honeybee-radiance-postprocess-0.4.226 → honeybee-radiance-postprocess-0.4.228}/MANIFEST.in +0 -0
- {honeybee-radiance-postprocess-0.4.226 → honeybee-radiance-postprocess-0.4.228}/README.md +0 -0
- {honeybee-radiance-postprocess-0.4.226 → honeybee-radiance-postprocess-0.4.228}/dev-requirements.txt +0 -0
- {honeybee-radiance-postprocess-0.4.226 → honeybee-radiance-postprocess-0.4.228}/honeybee_radiance_postprocess/__init__.py +0 -0
- {honeybee-radiance-postprocess-0.4.226 → honeybee-radiance-postprocess-0.4.228}/honeybee_radiance_postprocess/__main__.py +0 -0
- {honeybee-radiance-postprocess-0.4.226 → honeybee-radiance-postprocess-0.4.228}/honeybee_radiance_postprocess/annual.py +0 -0
- {honeybee-radiance-postprocess-0.4.226 → honeybee-radiance-postprocess-0.4.228}/honeybee_radiance_postprocess/annualdaylight.py +0 -0
- {honeybee-radiance-postprocess-0.4.226 → honeybee-radiance-postprocess-0.4.228}/honeybee_radiance_postprocess/cli/__init__.py +0 -0
- {honeybee-radiance-postprocess-0.4.226 → honeybee-radiance-postprocess-0.4.228}/honeybee_radiance_postprocess/cli/grid.py +0 -0
- {honeybee-radiance-postprocess-0.4.226 → honeybee-radiance-postprocess-0.4.228}/honeybee_radiance_postprocess/cli/leed.py +0 -0
- {honeybee-radiance-postprocess-0.4.226 → honeybee-radiance-postprocess-0.4.228}/honeybee_radiance_postprocess/cli/mtxop.py +0 -0
- {honeybee-radiance-postprocess-0.4.226 → honeybee-radiance-postprocess-0.4.228}/honeybee_radiance_postprocess/cli/schedule.py +0 -0
- {honeybee-radiance-postprocess-0.4.226 → honeybee-radiance-postprocess-0.4.228}/honeybee_radiance_postprocess/cli/two_phase.py +0 -0
- {honeybee-radiance-postprocess-0.4.226 → honeybee-radiance-postprocess-0.4.228}/honeybee_radiance_postprocess/cli/util.py +0 -0
- {honeybee-radiance-postprocess-0.4.226 → honeybee-radiance-postprocess-0.4.228}/honeybee_radiance_postprocess/dynamic.py +0 -0
- {honeybee-radiance-postprocess-0.4.226 → honeybee-radiance-postprocess-0.4.228}/honeybee_radiance_postprocess/electriclight.py +0 -0
- {honeybee-radiance-postprocess-0.4.226 → honeybee-radiance-postprocess-0.4.228}/honeybee_radiance_postprocess/en17037.py +0 -0
- {honeybee-radiance-postprocess-0.4.226 → honeybee-radiance-postprocess-0.4.228}/honeybee_radiance_postprocess/leed.py +0 -0
- {honeybee-radiance-postprocess-0.4.226 → honeybee-radiance-postprocess-0.4.228}/honeybee_radiance_postprocess/metrics.py +0 -0
- {honeybee-radiance-postprocess-0.4.226 → honeybee-radiance-postprocess-0.4.228}/honeybee_radiance_postprocess/reader.py +0 -0
- {honeybee-radiance-postprocess-0.4.226 → honeybee-radiance-postprocess-0.4.228}/honeybee_radiance_postprocess/results.py +0 -0
- {honeybee-radiance-postprocess-0.4.226 → honeybee-radiance-postprocess-0.4.228}/honeybee_radiance_postprocess/type_hints.py +0 -0
- {honeybee-radiance-postprocess-0.4.226 → honeybee-radiance-postprocess-0.4.228}/honeybee_radiance_postprocess/util.py +0 -0
- {honeybee-radiance-postprocess-0.4.226 → honeybee-radiance-postprocess-0.4.228}/honeybee_radiance_postprocess.egg-info/SOURCES.txt +0 -0
- {honeybee-radiance-postprocess-0.4.226 → honeybee-radiance-postprocess-0.4.228}/honeybee_radiance_postprocess.egg-info/dependency_links.txt +0 -0
- {honeybee-radiance-postprocess-0.4.226 → honeybee-radiance-postprocess-0.4.228}/honeybee_radiance_postprocess.egg-info/entry_points.txt +0 -0
- {honeybee-radiance-postprocess-0.4.226 → honeybee-radiance-postprocess-0.4.228}/honeybee_radiance_postprocess.egg-info/requires.txt +0 -0
- {honeybee-radiance-postprocess-0.4.226 → honeybee-radiance-postprocess-0.4.228}/honeybee_radiance_postprocess.egg-info/top_level.txt +0 -0
- {honeybee-radiance-postprocess-0.4.226 → honeybee-radiance-postprocess-0.4.228}/requirements.txt +0 -0
- {honeybee-radiance-postprocess-0.4.226 → honeybee-radiance-postprocess-0.4.228}/setup.cfg +0 -0
- {honeybee-radiance-postprocess-0.4.226 → honeybee-radiance-postprocess-0.4.228}/setup.py +0 -0
@@ -697,6 +697,7 @@ def annual_metrics_file(
|
|
697
697
|
@click.option(
|
698
698
|
'--grids-info', '-gi', help='An optional JSON file with grid information. '
|
699
699
|
'If no file is provided the command will look for a file in the folder.',
|
700
|
+
default=None, show_default=True,
|
700
701
|
type=click.Path(exists=True, file_okay=True, dir_okay=False, resolve_path=True)
|
701
702
|
)
|
702
703
|
@click.option(
|
@@ -726,27 +727,88 @@ def grid_summary_metric(
|
|
726
727
|
if grids_info:
|
727
728
|
with open(grids_info) as gi:
|
728
729
|
grids_info = json.load(gi)
|
729
|
-
else:
|
730
|
-
gi_file = folder.joinpath('grids_info.json')
|
731
|
-
with open(gi_file) as gi:
|
732
|
-
grids_info = json.load(gi)
|
733
730
|
|
734
731
|
# get grid metrics
|
735
732
|
if grid_metrics:
|
736
733
|
with open(grid_metrics) as gm:
|
737
734
|
grid_metrics = json.load(gm)
|
735
|
+
|
736
|
+
# check to see if there is a HBJSON with sensor grid meshes for areas
|
737
|
+
if model:
|
738
|
+
grid_areas = model_grid_areas(model, grids_info)
|
738
739
|
else:
|
739
|
-
|
740
|
-
|
740
|
+
grid_areas = None
|
741
|
+
|
742
|
+
grid_summary(folder, extension, grid_areas, grids_info, name, grid_metrics)
|
743
|
+
|
744
|
+
except Exception:
|
745
|
+
_logger.exception('Failed to calculate grid summary.')
|
746
|
+
sys.exit(1)
|
747
|
+
else:
|
748
|
+
sys.exit(0)
|
749
|
+
|
750
|
+
|
751
|
+
@post_process.command('grid-summary-annual-daylight')
|
752
|
+
@click.argument(
|
753
|
+
'folder',
|
754
|
+
type=click.Path(exists=True, file_okay=False, dir_okay=True, resolve_path=True)
|
755
|
+
)
|
756
|
+
@click.option(
|
757
|
+
'--model', '-m', help='An optional HBJSON model file. This will be used to '
|
758
|
+
'find the area of the grids. The area is used when calculating percentages '
|
759
|
+
'of floor area.',
|
760
|
+
type=click.Path(exists=True, file_okay=True, dir_okay=False, resolve_path=True)
|
761
|
+
)
|
762
|
+
@click.option(
|
763
|
+
'--grids-info', '-gi', help='An optional JSON file with grid information. '
|
764
|
+
'If no file is provided the command will look for a file in the folder.',
|
765
|
+
default=None, show_default=True,
|
766
|
+
type=click.Path(exists=True, file_okay=True, dir_okay=False, resolve_path=True)
|
767
|
+
)
|
768
|
+
@click.option(
|
769
|
+
'--name', '-n', help='Optional filename of grid summary.',
|
770
|
+
type=str, default='grid_summary', show_default=True
|
771
|
+
)
|
772
|
+
@click.option(
|
773
|
+
'--grid-metrics', '-gm', help='An optional JSON file with additional '
|
774
|
+
'custom metrics to calculate.', default=None,
|
775
|
+
type=click.Path(exists=True, file_okay=True, dir_okay=False, resolve_path=True)
|
776
|
+
)
|
777
|
+
def grid_summary_annual_daylight_metric(
|
778
|
+
folder, model, grids_info, name, grid_metrics
|
779
|
+
):
|
780
|
+
"""Calculate a grid summary.
|
781
|
+
|
782
|
+
\b
|
783
|
+
Args:
|
784
|
+
folder: A folder with annual daylight metrics.
|
785
|
+
"""
|
786
|
+
try:
|
787
|
+
# create Path object
|
788
|
+
folder = Path(folder)
|
789
|
+
|
790
|
+
# get grids information
|
791
|
+
if grids_info:
|
792
|
+
with open(grids_info) as gi:
|
741
793
|
grids_info = json.load(gi)
|
742
794
|
|
795
|
+
# get grid metrics
|
796
|
+
if grid_metrics:
|
797
|
+
with open(grid_metrics) as gm:
|
798
|
+
grid_metrics = json.load(gm)
|
799
|
+
|
743
800
|
# check to see if there is a HBJSON with sensor grid meshes for areas
|
744
801
|
if model:
|
745
802
|
grid_areas = model_grid_areas(model, grids_info)
|
746
803
|
else:
|
747
|
-
grid_areas =
|
804
|
+
grid_areas = None
|
748
805
|
|
749
|
-
|
806
|
+
for metric in ['da', 'cda', 'udi', 'udi_lower', 'udi_upper']:
|
807
|
+
metric_folder = folder.joinpath(metric)
|
808
|
+
extension = metric.split('_')[0]
|
809
|
+
grid_summary(
|
810
|
+
metric_folder, extension, grids_info, grid_areas, name,
|
811
|
+
grid_metrics)
|
750
812
|
|
751
813
|
except Exception:
|
752
814
|
_logger.exception('Failed to calculate grid summary.')
|
@@ -1,9 +1,11 @@
|
|
1
1
|
"""Commands to translate objects."""
|
2
2
|
import sys
|
3
3
|
import logging
|
4
|
+
from pathlib import Path
|
5
|
+
import shutil
|
4
6
|
import numpy as np
|
5
7
|
import click
|
6
|
-
|
8
|
+
import json
|
7
9
|
|
8
10
|
from ..reader import binary_to_array
|
9
11
|
|
@@ -129,3 +131,70 @@ def binary_to_npy(mtx_file, conversion, name, output_folder):
|
|
129
131
|
sys.exit(1)
|
130
132
|
else:
|
131
133
|
sys.exit(0)
|
134
|
+
|
135
|
+
|
136
|
+
@translate.command('annual-daylight-npy-to-ill')
|
137
|
+
@click.argument(
|
138
|
+
'folder',
|
139
|
+
type=click.Path(exists=True, file_okay=False, dir_okay=True, resolve_path=True)
|
140
|
+
)
|
141
|
+
@click.option(
|
142
|
+
'--output-folder', '-of', help='Output folder. If not provided the output '
|
143
|
+
'folder will be created in the same directory as the results folder. The '
|
144
|
+
'new folder will be called results_ill.', default=None,
|
145
|
+
type=click.Path(exists=False, file_okay=False, dir_okay=True, resolve_path=True)
|
146
|
+
)
|
147
|
+
def annual_daylight_npy_to_ill(folder, output_folder):
|
148
|
+
"""Convert an annual daylight results folder to older version.
|
149
|
+
|
150
|
+
This command reads an annual daylight results folder with results saved as
|
151
|
+
npy files (NumPy), and converts the npy files to text files in the old
|
152
|
+
results folder format.
|
153
|
+
|
154
|
+
\b
|
155
|
+
Args:
|
156
|
+
folder: Results folder. This folder is an output folder of annual
|
157
|
+
daylight recipe. Folder should include grids_info.json and
|
158
|
+
sun-up-hours.txt.
|
159
|
+
"""
|
160
|
+
try:
|
161
|
+
folder = Path(folder)
|
162
|
+
static_ill_folder = folder.joinpath('__static_apertures__/default/total')
|
163
|
+
if not static_ill_folder.exists():
|
164
|
+
raise FileNotFoundError(
|
165
|
+
'No results were found for static apertures in the results '
|
166
|
+
'folder.')
|
167
|
+
grids_info_file = folder.joinpath('grids_info.json')
|
168
|
+
if not grids_info_file.exists():
|
169
|
+
raise FileNotFoundError(
|
170
|
+
'The file grids_info.json was not found in the results folder.')
|
171
|
+
sun_up_hours_file = folder.joinpath('sun-up-hours.txt')
|
172
|
+
if not sun_up_hours_file.exists():
|
173
|
+
raise FileNotFoundError(
|
174
|
+
'The file sun-up-hours.txt was not found in the results folder.')
|
175
|
+
|
176
|
+
if output_folder is None:
|
177
|
+
output_folder = folder.parent.joinpath('results_ill')
|
178
|
+
else:
|
179
|
+
output_folder = Path(output_folder)
|
180
|
+
output_folder.mkdir(parents=True, exist_ok=True)
|
181
|
+
|
182
|
+
with open(grids_info_file) as json_file:
|
183
|
+
grids_info = json.load(json_file)
|
184
|
+
|
185
|
+
for grid_info in grids_info:
|
186
|
+
full_id = grid_info['full_id']
|
187
|
+
npy_file = static_ill_folder.joinpath(f'{full_id}.npy')
|
188
|
+
|
189
|
+
array = np.load(npy_file)
|
190
|
+
output = Path(output_folder, full_id + '.ill')
|
191
|
+
np.savetxt(output, array, fmt='%.7e', delimiter='\t')
|
192
|
+
|
193
|
+
# copy grids_info and sun-up-hours
|
194
|
+
shutil.copy(grids_info_file, output_folder.joinpath('grids_info.json'))
|
195
|
+
shutil.copy(sun_up_hours_file, output_folder.joinpath('sun-up-hours.txt'))
|
196
|
+
except Exception:
|
197
|
+
_logger.exception('Converting annual daylight results folder failed.')
|
198
|
+
sys.exit(1)
|
199
|
+
else:
|
200
|
+
sys.exit(0)
|
@@ -0,0 +1,177 @@
|
|
1
|
+
"""Helper functions."""
|
2
|
+
import json
|
3
|
+
import numpy as np
|
4
|
+
|
5
|
+
from honeybee.model import Model
|
6
|
+
|
7
|
+
|
8
|
+
def model_grid_areas(model, grids_info):
|
9
|
+
if isinstance(model, Model):
|
10
|
+
hb_model = model
|
11
|
+
else:
|
12
|
+
hb_model = Model.from_file(model)
|
13
|
+
|
14
|
+
full_ids = [grid_info['full_id'] for grid_info in grids_info]
|
15
|
+
sensor_grids = hb_model.properties.radiance.sensor_grids
|
16
|
+
grid_areas = []
|
17
|
+
for s_grid in sensor_grids:
|
18
|
+
if s_grid.identifier in full_ids:
|
19
|
+
if s_grid.mesh is not None:
|
20
|
+
grid_areas.append(s_grid.mesh.face_areas)
|
21
|
+
grid_areas = [np.array(grid) for grid in grid_areas]
|
22
|
+
if not grid_areas:
|
23
|
+
grid_areas = [None] * len(full_ids)
|
24
|
+
|
25
|
+
return grid_areas
|
26
|
+
|
27
|
+
|
28
|
+
def grid_summary(
|
29
|
+
folder, extension, grid_areas=None, grids_info=None, name='grid_summary',
|
30
|
+
grid_metrics=None
|
31
|
+
):
|
32
|
+
"""Calculate a grid summary for a single metric.
|
33
|
+
|
34
|
+
Args:
|
35
|
+
folder: A folder with results.
|
36
|
+
extension: Extension of the files to collect data from.
|
37
|
+
grid_areas: A list of area of each sensor.
|
38
|
+
grids_info: Grid information as a dictionary.
|
39
|
+
name: Optional filename of grid summary.
|
40
|
+
grid_metrics: Additional customized metrics to calculate.
|
41
|
+
"""
|
42
|
+
if grids_info is None:
|
43
|
+
gi_file = folder.joinpath('grids_info.json')
|
44
|
+
if not gi_file.exists():
|
45
|
+
raise FileNotFoundError(
|
46
|
+
f'The file grids_info.json was not found in the folder: {folder}.')
|
47
|
+
with open(gi_file) as gi:
|
48
|
+
grids_info = json.load(gi)
|
49
|
+
|
50
|
+
if grid_areas is None:
|
51
|
+
grid_areas = [None] * len(grids_info)
|
52
|
+
|
53
|
+
# set up the default data types
|
54
|
+
dtype = [
|
55
|
+
('Sensor Grid', 'O'),
|
56
|
+
('Mean', np.float32),
|
57
|
+
('Minimum', np.float32),
|
58
|
+
('Maximum', np.float32),
|
59
|
+
('Uniformity Ratio', np.float32)
|
60
|
+
]
|
61
|
+
|
62
|
+
if grid_metrics is not None:
|
63
|
+
for gr_m in grid_metrics:
|
64
|
+
gr_m_h = []
|
65
|
+
for k, v in gr_m.items():
|
66
|
+
gr_m_h.append(k + str(v))
|
67
|
+
dtype.append((' '.join(gr_m_h), np.float32))
|
68
|
+
|
69
|
+
header = [dt[0] for dt in dtype]
|
70
|
+
|
71
|
+
arrays = []
|
72
|
+
for grid_info, grid_area in zip(grids_info, grid_areas):
|
73
|
+
full_id = grid_info['full_id']
|
74
|
+
array = np.loadtxt(folder.joinpath(f'{full_id}.{extension}'))
|
75
|
+
_mean = array.mean()
|
76
|
+
_min = array.min()
|
77
|
+
_max = array.max()
|
78
|
+
_uniformity_ratio = _min / _mean * 100
|
79
|
+
|
80
|
+
data = [full_id, _mean, _min, _max, _uniformity_ratio]
|
81
|
+
|
82
|
+
if grid_metrics is not None:
|
83
|
+
# get grid metrics
|
84
|
+
grid_metrics_data = \
|
85
|
+
_get_grid_metrics(array, grid_metrics, grid_info, grid_area)
|
86
|
+
data.extend(grid_metrics_data)
|
87
|
+
|
88
|
+
arrays.append(tuple(data))
|
89
|
+
|
90
|
+
# create structured array
|
91
|
+
struct_array = np.array(arrays, dtype=dtype)
|
92
|
+
|
93
|
+
# write header to file
|
94
|
+
with open(folder.joinpath(f'{name}.csv'), 'w') as grid_summary_file:
|
95
|
+
grid_summary_file.write(','.join(header))
|
96
|
+
# write structured array to grid_summary_file
|
97
|
+
fmt = ['%s' , '%.2f', '%.2f', '%.2f', '%.2f']
|
98
|
+
if grid_metrics is not None:
|
99
|
+
fmt.extend(['%.2f' for _gr_m in grid_metrics])
|
100
|
+
with open(folder.joinpath(f'{name}.csv'), 'a') as grid_summary_file:
|
101
|
+
grid_summary_file.write('\n')
|
102
|
+
np.savetxt(grid_summary_file, struct_array, delimiter=',', fmt=fmt)
|
103
|
+
|
104
|
+
return grid_summary_file
|
105
|
+
|
106
|
+
|
107
|
+
def _calculate_percentage(gr_metric_bool, grid_info, grid_area=None):
|
108
|
+
"""Calculate percentage of floor area where True.
|
109
|
+
|
110
|
+
Args:
|
111
|
+
gr_metric_bool: A NumPy array of booleans.
|
112
|
+
grid_info: Grid information.
|
113
|
+
grid_area: A NumPy array of area for each sensor. (Default: None).
|
114
|
+
|
115
|
+
Returns:
|
116
|
+
The percentage of floor area where gr_metric_bool is True.
|
117
|
+
"""
|
118
|
+
if grid_area is not None:
|
119
|
+
gr_metric_pct = \
|
120
|
+
grid_area[gr_metric_bool].sum() / grid_area.sum() * 100
|
121
|
+
else:
|
122
|
+
gr_metric_pct = \
|
123
|
+
gr_metric_bool.sum() / grid_info['count'] * 100
|
124
|
+
return gr_metric_pct
|
125
|
+
|
126
|
+
|
127
|
+
def _numeric_type(array, gr_metric):
|
128
|
+
if 'minimum' in gr_metric:
|
129
|
+
gr_metric_bool = array > gr_metric['minimum']
|
130
|
+
elif 'exclusiveMinimum' in gr_metric:
|
131
|
+
gr_metric_bool = array >= gr_metric['minimum']
|
132
|
+
elif 'maximum' in gr_metric:
|
133
|
+
gr_metric_bool = array < gr_metric['maximum']
|
134
|
+
elif 'exclusiveMaximum' in gr_metric:
|
135
|
+
gr_metric_bool = array <= gr_metric['exclusiveMaximum']
|
136
|
+
return gr_metric_bool
|
137
|
+
|
138
|
+
|
139
|
+
def _grid_summary_all_any(array, gr_metric, grid_info, grid_area, keyword):
|
140
|
+
gr_metric_arrays = []
|
141
|
+
for gr_m in gr_metric[keyword]:
|
142
|
+
assert len(gr_m) == 1
|
143
|
+
gr_metric_arrays.append(_numeric_type(array, gr_m))
|
144
|
+
if keyword == 'allOf':
|
145
|
+
gr_metric_bool = np.all(gr_metric_arrays, axis=0)
|
146
|
+
else:
|
147
|
+
gr_metric_bool = np.any(gr_metric_arrays, axis=0)
|
148
|
+
gr_metric_pct = \
|
149
|
+
_calculate_percentage(gr_metric_bool, grid_info, grid_area)
|
150
|
+
return gr_metric_pct
|
151
|
+
|
152
|
+
|
153
|
+
def _get_grid_metrics(array, grid_metrics, grid_info, grid_area):
|
154
|
+
grid_metrics_data = []
|
155
|
+
for gr_metric in grid_metrics:
|
156
|
+
if len(gr_metric) == 1:
|
157
|
+
if 'allOf' in gr_metric:
|
158
|
+
gr_metric_pct = \
|
159
|
+
_grid_summary_all_any(
|
160
|
+
array, gr_metric, grid_info, grid_area, 'allOf')
|
161
|
+
elif 'anyOf' in gr_metric:
|
162
|
+
gr_metric_pct = \
|
163
|
+
_grid_summary_all_any(
|
164
|
+
array, gr_metric, grid_info, grid_area, 'anyOf')
|
165
|
+
else:
|
166
|
+
gr_metric_bool = _numeric_type(array, gr_metric)
|
167
|
+
gr_metric_pct = \
|
168
|
+
_calculate_percentage(gr_metric_bool, grid_info, grid_area)
|
169
|
+
elif len(gr_metric) == 2:
|
170
|
+
gr_metric_arrays = []
|
171
|
+
for k, threshold in gr_metric.items():
|
172
|
+
gr_metric_arrays.append(_numeric_type(array, {k: threshold}))
|
173
|
+
gr_metric_bool = np.all(gr_metric_arrays, axis=0)
|
174
|
+
gr_metric_pct = \
|
175
|
+
_calculate_percentage(gr_metric_bool, grid_info, grid_area)
|
176
|
+
grid_metrics_data.append(gr_metric_pct)
|
177
|
+
return grid_metrics_data
|
@@ -1,159 +0,0 @@
|
|
1
|
-
"""Helper functions."""
|
2
|
-
import numpy as np
|
3
|
-
|
4
|
-
from honeybee.model import Model
|
5
|
-
|
6
|
-
|
7
|
-
def model_grid_areas(model, grids_info):
|
8
|
-
if isinstance(model, Model):
|
9
|
-
hb_model = model
|
10
|
-
else:
|
11
|
-
hb_model = Model.from_file(model)
|
12
|
-
|
13
|
-
full_ids = [grid_info['full_id'] for grid_info in grids_info]
|
14
|
-
sensor_grids = hb_model.properties.radiance.sensor_grids
|
15
|
-
grid_areas = []
|
16
|
-
for s_grid in sensor_grids:
|
17
|
-
if s_grid.identifier in full_ids:
|
18
|
-
if s_grid.mesh is not None:
|
19
|
-
grid_areas.append(s_grid.mesh.face_areas)
|
20
|
-
grid_areas = [np.array(grid) for grid in grid_areas]
|
21
|
-
if not grid_areas:
|
22
|
-
grid_areas = [None] * len(full_ids)
|
23
|
-
|
24
|
-
return grid_areas
|
25
|
-
|
26
|
-
|
27
|
-
def grid_summary(
|
28
|
-
folder, extension, grids_info, grid_areas, name='grid_summary',
|
29
|
-
grid_metrics=None
|
30
|
-
):
|
31
|
-
"""Calculate a grid summary for a single metric.
|
32
|
-
|
33
|
-
Args:
|
34
|
-
folder: A folder with results.
|
35
|
-
extension: Extension of the files to collect data from.
|
36
|
-
grids_info: Grid information as a dictionary.
|
37
|
-
grid_areas:
|
38
|
-
name: Optional filename of grid summary.
|
39
|
-
grid_metrics: Additional customized metrics to calculate.
|
40
|
-
"""
|
41
|
-
# set up the default data types
|
42
|
-
dtype = [
|
43
|
-
('Sensor Grid', 'O'),
|
44
|
-
('Mean', np.float32),
|
45
|
-
('Minimum', np.float32),
|
46
|
-
('Maximum', np.float32),
|
47
|
-
('Uniformity Ratio', np.float32)
|
48
|
-
]
|
49
|
-
|
50
|
-
if grid_metrics is not None:
|
51
|
-
for gr_m in grid_metrics:
|
52
|
-
gr_m_h = []
|
53
|
-
for k, v in gr_m.items():
|
54
|
-
gr_m_h.append(k + str(v))
|
55
|
-
dtype.append((' '.join(gr_m_h), np.float32))
|
56
|
-
|
57
|
-
header = [dt[0] for dt in dtype]
|
58
|
-
|
59
|
-
arrays = []
|
60
|
-
for grid_info, grid_area in zip(grids_info, grid_areas):
|
61
|
-
full_id = grid_info['full_id']
|
62
|
-
array = np.loadtxt(folder.joinpath(f'{full_id}.{extension}'))
|
63
|
-
_mean = array.mean()
|
64
|
-
_min = array.min()
|
65
|
-
_max = array.max()
|
66
|
-
_uniformity_ratio = _min / _mean * 100
|
67
|
-
|
68
|
-
data = [full_id, _mean, _min, _max, _uniformity_ratio]
|
69
|
-
|
70
|
-
grid_metrics_data = []
|
71
|
-
if grid_metrics is not None:
|
72
|
-
for gr_metric in grid_metrics:
|
73
|
-
if len(gr_metric) == 1:
|
74
|
-
for k, v in gr_metric.items():
|
75
|
-
if k == 'anyOff' or k == 'allOff':
|
76
|
-
gr_metric_arrays = []
|
77
|
-
for vv in v:
|
78
|
-
for kk, threshold in vv.items():
|
79
|
-
if kk == 'minimum':
|
80
|
-
gr_metric_arrays.append(array > threshold)
|
81
|
-
elif kk == 'exclusiveMinimum':
|
82
|
-
gr_metric_arrays.append(array >= threshold)
|
83
|
-
elif kk == 'maximum':
|
84
|
-
gr_metric_arrays.append(array < threshold)
|
85
|
-
elif kk == 'exclusiveMaximum':
|
86
|
-
gr_metric_arrays.append(array <= threshold)
|
87
|
-
if k == 'anyOff':
|
88
|
-
gr_metric_bool = np.any(gr_metric_arrays, axis=0)
|
89
|
-
else:
|
90
|
-
gr_metric_bool = np.all(gr_metric_arrays, axis=0)
|
91
|
-
gr_metric_pct = \
|
92
|
-
_calculate_percentage(gr_metric_bool, grid_info, grid_area)
|
93
|
-
else:
|
94
|
-
threshold = v
|
95
|
-
if k == 'minimum':
|
96
|
-
gr_metric_bool = array > threshold
|
97
|
-
elif k == 'exclusiveMinimum':
|
98
|
-
gr_metric_bool = array >= threshold
|
99
|
-
elif k == 'maximum':
|
100
|
-
gr_metric_bool = array < threshold
|
101
|
-
elif k == 'exclusiveMaximum':
|
102
|
-
gr_metric_bool = array <= threshold
|
103
|
-
gr_metric_pct = \
|
104
|
-
_calculate_percentage(gr_metric_bool, grid_info, grid_area)
|
105
|
-
elif len(gr_metric) == 2:
|
106
|
-
gr_metric_arrays = []
|
107
|
-
for k, threshold in gr_metric.items():
|
108
|
-
if k == 'minimum':
|
109
|
-
gr_metric_arrays.append(array > threshold)
|
110
|
-
elif k == 'exclusiveMinimum':
|
111
|
-
gr_metric_arrays.append(array >= threshold)
|
112
|
-
elif k == 'maximum':
|
113
|
-
gr_metric_arrays.append(array < threshold)
|
114
|
-
elif k == 'exclusiveMaximum':
|
115
|
-
gr_metric_arrays.append(array <= threshold)
|
116
|
-
gr_metric_bool = np.all(gr_metric_arrays, axis=0)
|
117
|
-
gr_metric_pct = \
|
118
|
-
_calculate_percentage(gr_metric_bool, grid_info, grid_area)
|
119
|
-
grid_metrics_data.append(gr_metric_pct)
|
120
|
-
|
121
|
-
data.extend(grid_metrics_data)
|
122
|
-
|
123
|
-
arrays.append(tuple(data))
|
124
|
-
|
125
|
-
# create structured array
|
126
|
-
struct_array = np.array(arrays, dtype=dtype)
|
127
|
-
|
128
|
-
# write header to file
|
129
|
-
with open(folder.joinpath(f'{name}.csv'), 'w') as file:
|
130
|
-
file.write(','.join(header))
|
131
|
-
# write structured array to file
|
132
|
-
fmt = ['%s' , '%.2f', '%.2f', '%.2f', '%.2f']
|
133
|
-
if grid_metrics is not None:
|
134
|
-
fmt.extend(['%.2f' for d in grid_metrics])
|
135
|
-
with open(folder.joinpath(f'{name}.csv'), 'a') as file:
|
136
|
-
file.write('\n')
|
137
|
-
np.savetxt(file, struct_array, delimiter=',', fmt=fmt)
|
138
|
-
|
139
|
-
return file
|
140
|
-
|
141
|
-
|
142
|
-
def _calculate_percentage(gr_metric_bool, grid_info, grid_area=None):
|
143
|
-
"""Calculate percentage of floor area where True.
|
144
|
-
|
145
|
-
Args:
|
146
|
-
gr_metric_bool: A NumPy array of booleans.
|
147
|
-
grid_info: Grid information.
|
148
|
-
grid_area: A NumPy array of area for each sensor. (Default: None).
|
149
|
-
|
150
|
-
Returns:
|
151
|
-
The percentage of floor area where gr_metric_bool is True.
|
152
|
-
"""
|
153
|
-
if grid_area is not None:
|
154
|
-
gr_metric_pct = \
|
155
|
-
grid_area[gr_metric_bool].sum() / grid_area.sum() * 100
|
156
|
-
else:
|
157
|
-
gr_metric_pct = \
|
158
|
-
gr_metric_bool.sum() / grid_info['count'] * 100
|
159
|
-
return gr_metric_pct
|
{honeybee-radiance-postprocess-0.4.226 → honeybee-radiance-postprocess-0.4.228}/CODE_OF_CONDUCT.md
RENAMED
File without changes
|
{honeybee-radiance-postprocess-0.4.226 → honeybee-radiance-postprocess-0.4.228}/CONTRIBUTING.md
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{honeybee-radiance-postprocess-0.4.226 → honeybee-radiance-postprocess-0.4.228}/dev-requirements.txt
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{honeybee-radiance-postprocess-0.4.226 → honeybee-radiance-postprocess-0.4.228}/requirements.txt
RENAMED
File without changes
|
File without changes
|
File without changes
|