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.
Files changed (50) hide show
  1. honeybee_radiance_postprocess/__init__.py +1 -0
  2. honeybee_radiance_postprocess/__main__.py +4 -0
  3. honeybee_radiance_postprocess/annual.py +73 -0
  4. honeybee_radiance_postprocess/annualdaylight.py +289 -0
  5. honeybee_radiance_postprocess/annualirradiance.py +35 -0
  6. honeybee_radiance_postprocess/breeam/__init__.py +1 -0
  7. honeybee_radiance_postprocess/breeam/breeam.py +552 -0
  8. honeybee_radiance_postprocess/cli/__init__.py +33 -0
  9. honeybee_radiance_postprocess/cli/abnt.py +392 -0
  10. honeybee_radiance_postprocess/cli/breeam.py +96 -0
  11. honeybee_radiance_postprocess/cli/datacollection.py +133 -0
  12. honeybee_radiance_postprocess/cli/grid.py +295 -0
  13. honeybee_radiance_postprocess/cli/leed.py +143 -0
  14. honeybee_radiance_postprocess/cli/merge.py +161 -0
  15. honeybee_radiance_postprocess/cli/mtxop.py +161 -0
  16. honeybee_radiance_postprocess/cli/postprocess.py +1092 -0
  17. honeybee_radiance_postprocess/cli/schedule.py +103 -0
  18. honeybee_radiance_postprocess/cli/translate.py +216 -0
  19. honeybee_radiance_postprocess/cli/two_phase.py +252 -0
  20. honeybee_radiance_postprocess/cli/util.py +121 -0
  21. honeybee_radiance_postprocess/cli/viewfactor.py +157 -0
  22. honeybee_radiance_postprocess/cli/well.py +110 -0
  23. honeybee_radiance_postprocess/data_type.py +102 -0
  24. honeybee_radiance_postprocess/dynamic.py +273 -0
  25. honeybee_radiance_postprocess/electriclight.py +24 -0
  26. honeybee_radiance_postprocess/en17037.py +304 -0
  27. honeybee_radiance_postprocess/helper.py +266 -0
  28. honeybee_radiance_postprocess/ies/__init__.py +1 -0
  29. honeybee_radiance_postprocess/ies/lm.py +224 -0
  30. honeybee_radiance_postprocess/ies/lm_schedule.py +248 -0
  31. honeybee_radiance_postprocess/leed/__init__.py +1 -0
  32. honeybee_radiance_postprocess/leed/leed.py +801 -0
  33. honeybee_radiance_postprocess/leed/leed_schedule.py +256 -0
  34. honeybee_radiance_postprocess/metrics.py +439 -0
  35. honeybee_radiance_postprocess/reader.py +80 -0
  36. honeybee_radiance_postprocess/results/__init__.py +4 -0
  37. honeybee_radiance_postprocess/results/annual_daylight.py +752 -0
  38. honeybee_radiance_postprocess/results/annual_irradiance.py +196 -0
  39. honeybee_radiance_postprocess/results/results.py +1416 -0
  40. honeybee_radiance_postprocess/type_hints.py +38 -0
  41. honeybee_radiance_postprocess/util.py +211 -0
  42. honeybee_radiance_postprocess/vis_metadata.py +49 -0
  43. honeybee_radiance_postprocess/well/__init__.py +1 -0
  44. honeybee_radiance_postprocess/well/well.py +509 -0
  45. honeybee_radiance_postprocess-0.4.555.dist-info/METADATA +79 -0
  46. honeybee_radiance_postprocess-0.4.555.dist-info/RECORD +50 -0
  47. honeybee_radiance_postprocess-0.4.555.dist-info/WHEEL +5 -0
  48. honeybee_radiance_postprocess-0.4.555.dist-info/entry_points.txt +2 -0
  49. honeybee_radiance_postprocess-0.4.555.dist-info/licenses/LICENSE +661 -0
  50. 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
+ [![Build Status](https://github.com/ladybug-tools/honeybee-radiance-postprocess/actions/workflows/ci.yaml/badge.svg)](https://github.com/ladybug-tools/honeybee-radiance-postprocess/actions)
33
+ [![Coverage Status](https://coveralls.io/repos/github/ladybug-tools/honeybee-radiance-postprocess/badge.svg?branch=master)](https://coveralls.io/github/ladybug-tools/honeybee-radiance-postprocess)
34
+
35
+ [![Python 3.10](https://img.shields.io/badge/python-3.10-orange.svg)](https://www.python.org/downloads/release/python-3100/) [![Python 3.7](https://img.shields.io/badge/python-3.7-blue.svg)](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,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.9.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ honeybee-radiance-postprocess = honeybee_radiance_postprocess.cli:postprocess