honeybee-grasshopper-radiance 1.35.1__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 (170) hide show
  1. honeybee_grasshopper_radiance/__init__.py +7 -0
  2. honeybee_grasshopper_radiance/src/HB Adjust HDR.py +107 -0
  3. honeybee_grasshopper_radiance/src/HB Ambient Resolution.py +63 -0
  4. honeybee_grasshopper_radiance/src/HB Annual Average Values.py +205 -0
  5. honeybee_grasshopper_radiance/src/HB Annual Cumulative Values.py +191 -0
  6. honeybee_grasshopper_radiance/src/HB Annual Daylight Metrics.py +209 -0
  7. honeybee_grasshopper_radiance/src/HB Annual Daylight.py +153 -0
  8. honeybee_grasshopper_radiance/src/HB Annual Glare Metrics.py +137 -0
  9. honeybee_grasshopper_radiance/src/HB Annual Irradiance.py +112 -0
  10. honeybee_grasshopper_radiance/src/HB Annual Peak Values.py +224 -0
  11. honeybee_grasshopper_radiance/src/HB Annual Results to Data.py +246 -0
  12. honeybee_grasshopper_radiance/src/HB Annual Sunlight Exposure.py +147 -0
  13. honeybee_grasshopper_radiance/src/HB Aperture Group Schedule.py +69 -0
  14. honeybee_grasshopper_radiance/src/HB Apply Face Modifier.py +107 -0
  15. honeybee_grasshopper_radiance/src/HB Apply ModifierSet.py +71 -0
  16. honeybee_grasshopper_radiance/src/HB Apply Shade Modifier.py +110 -0
  17. honeybee_grasshopper_radiance/src/HB Apply Window Modifier.py +120 -0
  18. honeybee_grasshopper_radiance/src/HB Assign Grids and Views.py +58 -0
  19. honeybee_grasshopper_radiance/src/HB Automatic Aperture Group.py +100 -0
  20. honeybee_grasshopper_radiance/src/HB BSDF Modifier.py +78 -0
  21. honeybee_grasshopper_radiance/src/HB CIE Standard Sky.py +75 -0
  22. honeybee_grasshopper_radiance/src/HB Certain Illuminance.py +41 -0
  23. honeybee_grasshopper_radiance/src/HB Check Scene.py +208 -0
  24. honeybee_grasshopper_radiance/src/HB Climatebased Sky.py +75 -0
  25. honeybee_grasshopper_radiance/src/HB Cumulative Radiation.py +98 -0
  26. honeybee_grasshopper_radiance/src/HB Custom Sky.py +74 -0
  27. honeybee_grasshopper_radiance/src/HB Daylight Control Schedule.py +211 -0
  28. honeybee_grasshopper_radiance/src/HB Daylight Factor.py +82 -0
  29. honeybee_grasshopper_radiance/src/HB Deconstruct Modifier.py +47 -0
  30. honeybee_grasshopper_radiance/src/HB Deconstruct ModifierSet Interior.py +67 -0
  31. honeybee_grasshopper_radiance/src/HB Deconstruct ModifierSet.py +80 -0
  32. honeybee_grasshopper_radiance/src/HB Deconstruct Wea.py +44 -0
  33. honeybee_grasshopper_radiance/src/HB Direct Sun Hours.py +88 -0
  34. honeybee_grasshopper_radiance/src/HB Dynamic Aperture Group.py +90 -0
  35. honeybee_grasshopper_radiance/src/HB Dynamic Shade Group.py +95 -0
  36. honeybee_grasshopper_radiance/src/HB Dynamic State Geometry.py +68 -0
  37. honeybee_grasshopper_radiance/src/HB Dynamic State.py +44 -0
  38. honeybee_grasshopper_radiance/src/HB Exterior Modifier Subset.py +68 -0
  39. honeybee_grasshopper_radiance/src/HB Extract HDR.py +225 -0
  40. honeybee_grasshopper_radiance/src/HB False Color.py +246 -0
  41. honeybee_grasshopper_radiance/src/HB Get Dynamic Groups.py +57 -0
  42. honeybee_grasshopper_radiance/src/HB Get Grids and Views.py +82 -0
  43. honeybee_grasshopper_radiance/src/HB Glare Postprocess.py +225 -0
  44. honeybee_grasshopper_radiance/src/HB Glass Modifier 3.py +62 -0
  45. honeybee_grasshopper_radiance/src/HB Glass Modifier.py +58 -0
  46. honeybee_grasshopper_radiance/src/HB HDR to GIF.py +72 -0
  47. honeybee_grasshopper_radiance/src/HB Imageless Annual Glare.py +108 -0
  48. honeybee_grasshopper_radiance/src/HB Interior Modifier Subset.py +83 -0
  49. honeybee_grasshopper_radiance/src/HB Metal Modifier 3.py +70 -0
  50. honeybee_grasshopper_radiance/src/HB Metal Modifier.py +68 -0
  51. honeybee_grasshopper_radiance/src/HB Mirror Modifier 3.py +56 -0
  52. honeybee_grasshopper_radiance/src/HB Mirror Modifier.py +55 -0
  53. honeybee_grasshopper_radiance/src/HB Model to Rad Folder.py +75 -0
  54. honeybee_grasshopper_radiance/src/HB ModifierSet.py +127 -0
  55. honeybee_grasshopper_radiance/src/HB Opaque Modifier 3.py +68 -0
  56. honeybee_grasshopper_radiance/src/HB Opaque Modifier.py +67 -0
  57. honeybee_grasshopper_radiance/src/HB Point-In-Time Grid-Based.py +93 -0
  58. honeybee_grasshopper_radiance/src/HB Point-In-Time View-Based.py +127 -0
  59. honeybee_grasshopper_radiance/src/HB Radial Grid from Rooms.py +160 -0
  60. honeybee_grasshopper_radiance/src/HB Radial Sensor Grid.py +99 -0
  61. honeybee_grasshopper_radiance/src/HB Radiance Parameter.py +163 -0
  62. honeybee_grasshopper_radiance/src/HB Search Modifier Sets.py +58 -0
  63. honeybee_grasshopper_radiance/src/HB Search Modifiers.py +58 -0
  64. honeybee_grasshopper_radiance/src/HB Section Plane View.py +69 -0
  65. honeybee_grasshopper_radiance/src/HB Sensor Grid from Apertures.py +153 -0
  66. honeybee_grasshopper_radiance/src/HB Sensor Grid from Faces.py +147 -0
  67. honeybee_grasshopper_radiance/src/HB Sensor Grid from Rooms.py +210 -0
  68. honeybee_grasshopper_radiance/src/HB Sensor Grid.py +82 -0
  69. honeybee_grasshopper_radiance/src/HB Shade Modifier Subset.py +62 -0
  70. honeybee_grasshopper_radiance/src/HB Sky View.py +86 -0
  71. honeybee_grasshopper_radiance/src/HB Spatial Daylight Autonomy.py +86 -0
  72. honeybee_grasshopper_radiance/src/HB Subface Modifier Subset.py +90 -0
  73. honeybee_grasshopper_radiance/src/HB Translucent Modifier 3.py +77 -0
  74. honeybee_grasshopper_radiance/src/HB Translucent Modifier.py +77 -0
  75. honeybee_grasshopper_radiance/src/HB View from Viewport.py +85 -0
  76. honeybee_grasshopper_radiance/src/HB View.py +96 -0
  77. honeybee_grasshopper_radiance/src/HB Visualize Sky.py +141 -0
  78. honeybee_grasshopper_radiance/src/HB Wea From Clear Sky.py +61 -0
  79. honeybee_grasshopper_radiance/src/HB Wea From EPW.py +50 -0
  80. honeybee_grasshopper_radiance/src/HB Wea From Tau Clear Sky.py +56 -0
  81. honeybee_grasshopper_radiance/src/HB Wea from Zhang-Huang.py +63 -0
  82. honeybee_grasshopper_radiance/src/__init__.py +1 -0
  83. honeybee_grasshopper_radiance/user_objects/HB Adjust HDR.ghuser +0 -0
  84. honeybee_grasshopper_radiance/user_objects/HB Ambient Resolution.ghuser +0 -0
  85. honeybee_grasshopper_radiance/user_objects/HB Annual Average Values.ghuser +0 -0
  86. honeybee_grasshopper_radiance/user_objects/HB Annual Cumulative Values.ghuser +0 -0
  87. honeybee_grasshopper_radiance/user_objects/HB Annual Daylight Metrics.ghuser +0 -0
  88. honeybee_grasshopper_radiance/user_objects/HB Annual Daylight.ghuser +0 -0
  89. honeybee_grasshopper_radiance/user_objects/HB Annual Glare Metrics.ghuser +0 -0
  90. honeybee_grasshopper_radiance/user_objects/HB Annual Irradiance.ghuser +0 -0
  91. honeybee_grasshopper_radiance/user_objects/HB Annual Peak Values.ghuser +0 -0
  92. honeybee_grasshopper_radiance/user_objects/HB Annual Results to Data.ghuser +0 -0
  93. honeybee_grasshopper_radiance/user_objects/HB Annual Sunlight Exposure.ghuser +0 -0
  94. honeybee_grasshopper_radiance/user_objects/HB Aperture Group Schedule.ghuser +0 -0
  95. honeybee_grasshopper_radiance/user_objects/HB Apply Face Modifier.ghuser +0 -0
  96. honeybee_grasshopper_radiance/user_objects/HB Apply ModifierSet.ghuser +0 -0
  97. honeybee_grasshopper_radiance/user_objects/HB Apply Shade Modifier.ghuser +0 -0
  98. honeybee_grasshopper_radiance/user_objects/HB Apply Window Modifier.ghuser +0 -0
  99. Views.ghuser +0 -0
  100. honeybee_grasshopper_radiance/user_objects/HB Automatic Aperture Group.ghuser +0 -0
  101. honeybee_grasshopper_radiance/user_objects/HB BSDF Modifier.ghuser +0 -0
  102. honeybee_grasshopper_radiance/user_objects/HB CIE Standard Sky.ghuser +0 -0
  103. honeybee_grasshopper_radiance/user_objects/HB Certain Illuminance.ghuser +0 -0
  104. honeybee_grasshopper_radiance/user_objects/HB Check Scene.ghuser +0 -0
  105. honeybee_grasshopper_radiance/user_objects/HB Climatebased Sky.ghuser +0 -0
  106. honeybee_grasshopper_radiance/user_objects/HB Cumulative Radiation.ghuser +0 -0
  107. honeybee_grasshopper_radiance/user_objects/HB Custom Sky.ghuser +0 -0
  108. honeybee_grasshopper_radiance/user_objects/HB Daylight Control Schedule.ghuser +0 -0
  109. honeybee_grasshopper_radiance/user_objects/HB Daylight Factor.ghuser +0 -0
  110. honeybee_grasshopper_radiance/user_objects/HB Deconstruct Modifier.ghuser +0 -0
  111. honeybee_grasshopper_radiance/user_objects/HB Deconstruct ModifierSet Interior.ghuser +0 -0
  112. honeybee_grasshopper_radiance/user_objects/HB Deconstruct ModifierSet.ghuser +0 -0
  113. honeybee_grasshopper_radiance/user_objects/HB Deconstruct Wea.ghuser +0 -0
  114. honeybee_grasshopper_radiance/user_objects/HB Direct Sun Hours.ghuser +0 -0
  115. honeybee_grasshopper_radiance/user_objects/HB Dynamic Aperture Group.ghuser +0 -0
  116. honeybee_grasshopper_radiance/user_objects/HB Dynamic Shade Group.ghuser +0 -0
  117. honeybee_grasshopper_radiance/user_objects/HB Dynamic State Geometry.ghuser +0 -0
  118. honeybee_grasshopper_radiance/user_objects/HB Dynamic State.ghuser +0 -0
  119. honeybee_grasshopper_radiance/user_objects/HB Exterior Modifier Subset.ghuser +0 -0
  120. honeybee_grasshopper_radiance/user_objects/HB Extract HDR.ghuser +0 -0
  121. honeybee_grasshopper_radiance/user_objects/HB Face Radiance Attributes.ghuser +0 -0
  122. honeybee_grasshopper_radiance/user_objects/HB False Color.ghuser +0 -0
  123. honeybee_grasshopper_radiance/user_objects/HB Get Dynamic Groups.ghuser +0 -0
  124. Views.ghuser +0 -0
  125. honeybee_grasshopper_radiance/user_objects/HB Glare Postprocess.ghuser +0 -0
  126. honeybee_grasshopper_radiance/user_objects/HB Glass Modifier 3.ghuser +0 -0
  127. honeybee_grasshopper_radiance/user_objects/HB Glass Modifier.ghuser +0 -0
  128. honeybee_grasshopper_radiance/user_objects/HB HDR to GIF.ghuser +0 -0
  129. honeybee_grasshopper_radiance/user_objects/HB Imageless Annual Glare.ghuser +0 -0
  130. honeybee_grasshopper_radiance/user_objects/HB Interior Modifier Subset.ghuser +0 -0
  131. honeybee_grasshopper_radiance/user_objects/HB Metal Modifier 3.ghuser +0 -0
  132. honeybee_grasshopper_radiance/user_objects/HB Metal Modifier.ghuser +0 -0
  133. honeybee_grasshopper_radiance/user_objects/HB Mirror Modifier 3.ghuser +0 -0
  134. honeybee_grasshopper_radiance/user_objects/HB Mirror Modifier.ghuser +0 -0
  135. honeybee_grasshopper_radiance/user_objects/HB Model to Rad Folder.ghuser +0 -0
  136. honeybee_grasshopper_radiance/user_objects/HB ModifierSet.ghuser +0 -0
  137. honeybee_grasshopper_radiance/user_objects/HB Opaque Modifier 3.ghuser +0 -0
  138. honeybee_grasshopper_radiance/user_objects/HB Opaque Modifier.ghuser +0 -0
  139. honeybee_grasshopper_radiance/user_objects/HB Point-In-Time Grid-Based.ghuser +0 -0
  140. honeybee_grasshopper_radiance/user_objects/HB Point-In-Time View-Based.ghuser +0 -0
  141. honeybee_grasshopper_radiance/user_objects/HB Radial Grid from Rooms.ghuser +0 -0
  142. honeybee_grasshopper_radiance/user_objects/HB Radial Sensor Grid.ghuser +0 -0
  143. honeybee_grasshopper_radiance/user_objects/HB Radiance Parameter.ghuser +0 -0
  144. honeybee_grasshopper_radiance/user_objects/HB Room Radiance Attributes.ghuser +0 -0
  145. honeybee_grasshopper_radiance/user_objects/HB Search Modifier Sets.ghuser +0 -0
  146. honeybee_grasshopper_radiance/user_objects/HB Search Modifiers.ghuser +0 -0
  147. honeybee_grasshopper_radiance/user_objects/HB Section Plane View.ghuser +0 -0
  148. honeybee_grasshopper_radiance/user_objects/HB Sensor Grid from Apertures.ghuser +0 -0
  149. honeybee_grasshopper_radiance/user_objects/HB Sensor Grid from Faces.ghuser +0 -0
  150. honeybee_grasshopper_radiance/user_objects/HB Sensor Grid from Rooms.ghuser +0 -0
  151. honeybee_grasshopper_radiance/user_objects/HB Sensor Grid.ghuser +0 -0
  152. honeybee_grasshopper_radiance/user_objects/HB Shade Modifier Subset.ghuser +0 -0
  153. honeybee_grasshopper_radiance/user_objects/HB Sky View.ghuser +0 -0
  154. honeybee_grasshopper_radiance/user_objects/HB Spatial Daylight Autonomy.ghuser +0 -0
  155. honeybee_grasshopper_radiance/user_objects/HB Subface Modifier Subset.ghuser +0 -0
  156. honeybee_grasshopper_radiance/user_objects/HB Translucent Modifier 3.ghuser +0 -0
  157. honeybee_grasshopper_radiance/user_objects/HB Translucent Modifier.ghuser +0 -0
  158. honeybee_grasshopper_radiance/user_objects/HB View from Viewport.ghuser +0 -0
  159. honeybee_grasshopper_radiance/user_objects/HB View.ghuser +0 -0
  160. honeybee_grasshopper_radiance/user_objects/HB Visualize Sky.ghuser +0 -0
  161. honeybee_grasshopper_radiance/user_objects/HB Wea From Clear Sky.ghuser +0 -0
  162. honeybee_grasshopper_radiance/user_objects/HB Wea From EPW.ghuser +0 -0
  163. honeybee_grasshopper_radiance/user_objects/HB Wea From Tau Clear Sky.ghuser +0 -0
  164. honeybee_grasshopper_radiance/user_objects/HB Wea from Zhang-Huang.ghuser +0 -0
  165. honeybee_grasshopper_radiance/user_objects/__init__.py +1 -0
  166. honeybee_grasshopper_radiance-1.35.1.dist-info/METADATA +64 -0
  167. honeybee_grasshopper_radiance-1.35.1.dist-info/RECORD +170 -0
  168. honeybee_grasshopper_radiance-1.35.1.dist-info/WHEEL +5 -0
  169. honeybee_grasshopper_radiance-1.35.1.dist-info/licenses/LICENSE +661 -0
  170. honeybee_grasshopper_radiance-1.35.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,224 @@
1
+ # This file is part of Honeybee.
2
+ #
3
+ # Copyright (c) 2025, Ladybug Tools.
4
+ # You should have received a copy of the GNU Affero General Public License
5
+ # along with Honeybee; If not, see <http://www.gnu.org/licenses/>.
6
+ #
7
+ # @license AGPL-3.0-or-later <https://spdx.org/licenses/AGPL-3.0-or-later>
8
+
9
+ """
10
+ Get peak irradiance or sum of illuminance values over an annual irradiance or
11
+ daylight simulation.
12
+ _
13
+ The _hoys_ input can also be used to filter the data for a particular time period or
14
+ hour/timestep of the simulation.
15
+
16
+ -
17
+ Args:
18
+ _results: An list of annual Radiance result files from either the "HB Annual Daylight"
19
+ or the "HB Annual Irradiance" component (containing the .ill files and
20
+ the sun-up-hours.txt). This can also be just the path to the folder
21
+ containing these result files.
22
+ dyn_sch_: Optional dynamic Aperture Group Schedules from the "HB Aperture Group
23
+ Schedule" component, which will be used to customize the behavior
24
+ of any dyanmic aperture geometry in the output metrics. If unsupplied,
25
+ all dynamic aperture groups will be in their default state in for
26
+ the output metrics.
27
+ _hoys_: An optional numbers or list of numbers to select the hours of the year (HOYs)
28
+ for which results will be computed. These HOYs can be obtained from the
29
+ "LB Calculate HOY" or the "LB Analysis Period" components. If None, all
30
+ hours of the results will be used.
31
+ grid_filter_: The name of a grid or a pattern to filter the grids. For instance,
32
+ first_floor_* will simulate only the sensor grids that have an
33
+ identifier that starts with first_floor_. By default all the grids
34
+ will be processed.
35
+ coincident_: Boolean to indicate whether output values represent the the peak
36
+ value for each sensor throughout the entire analysis (False) or
37
+ they represent the highest overall value across each sensor grid
38
+ at a particular timestep (True). (Default: False).
39
+
40
+ Returns:
41
+ report: Reports, errors, warnings, etc.
42
+ hoys: An integer for each sesnor grid that represents the hour of the year at
43
+ which the peak occurs. This will be None unless coincident_ is
44
+ set to True.
45
+ values: Peak illuminance or irradiance valules for each sensor in lux or W/m2.
46
+ Each value is for a different sensor of the grid. These can be plugged
47
+ into the "LB Spatial Heatmap" component along with meshes of the sensor
48
+ grids to visualize results.
49
+ """
50
+
51
+ ghenv.Component.Name = 'HB Annual Peak Values'
52
+ ghenv.Component.NickName = 'PeakValues'
53
+ ghenv.Component.Message = '1.9.0'
54
+ ghenv.Component.Category = 'HB-Radiance'
55
+ ghenv.Component.SubCategory = '4 :: Results'
56
+ ghenv.Component.AdditionalHelpFromDocStrings = '2'
57
+
58
+ import os
59
+ import subprocess
60
+
61
+ try:
62
+ from ladybug.futil import write_to_file
63
+ except ImportError as e:
64
+ raise ImportError('\nFailed to import ladybug:\n\t{}'.format(e))
65
+
66
+ try:
67
+ from honeybee.config import folders
68
+ except ImportError as e:
69
+ raise ImportError('\nFailed to import honeybee:\n\t{}'.format(e))
70
+
71
+ try:
72
+ from honeybee_radiance.postprocess.annualdaylight import _process_input_folder
73
+ except ImportError as e:
74
+ raise ImportError('\nFailed to import honeybee_radiance:\n\t{}'.format(e))
75
+
76
+ try:
77
+ from honeybee_radiance_postprocess.dynamic import DynamicSchedule
78
+ except ImportError as e:
79
+ raise ImportError('\nFailed to import honeybee_radiance:\n\t{}'.format(e))
80
+
81
+ try:
82
+ from pollination_handlers.outputs.helper import read_sensor_grid_result
83
+ except ImportError as e:
84
+ raise ImportError('\nFailed to import pollination_handlers:\n\t{}'.format(e))
85
+
86
+ try:
87
+ from ladybug_rhino.grasshopper import all_required_inputs, list_to_data_tree, \
88
+ give_warning
89
+ except ImportError as e:
90
+ raise ImportError('\nFailed to import ladybug_rhino:\n\t{}'.format(e))
91
+
92
+
93
+ def parse_sun_up_hours(sun_up_hours, hoys, timestep):
94
+ """Parse the sun-up hours from the result file .txt file.
95
+
96
+ Args:
97
+ sun_up_hours: A list of integers for the sun-up hours.
98
+ hoys: A list of 8760 * timestep values for the hoys to select. If an empty
99
+ list is passed, None will be returned.
100
+ timestep: Integer for the timestep of the analysis.
101
+ """
102
+ if len(hoys) != 0:
103
+ schedule = [False] * (8760 * timestep)
104
+ for hr in hoys:
105
+ schedule[int(hr * timestep)] = True
106
+ su_pattern = [schedule[int(h * timestep)] for h in sun_up_hours]
107
+ return su_pattern
108
+
109
+
110
+ def peak_values(ill_file, su_pattern, coincident):
111
+ """Compute average values for a given result file."""
112
+ max_vals, max_i = [], None
113
+ with open(ill_file) as results:
114
+ if coincident:
115
+ all_values = [[float(r) for r in pt_res.split()] for pt_res in results] \
116
+ if su_pattern is None else \
117
+ [[float(r) for r, is_hoy in zip(pt_res.split(), su_pattern) if is_hoy]
118
+ for pt_res in results]
119
+ max_val, max_i = 0, 0
120
+ for i, t_step in enumerate(zip(*all_values)):
121
+ tot_val = sum(t_step)
122
+ if tot_val > max_val:
123
+ max_val = tot_val
124
+ max_i = i
125
+ for sensor in all_values:
126
+ max_vals.append(sensor[max_i])
127
+ else:
128
+ if su_pattern is None: # no HOY filter on results
129
+ for pt_res in results:
130
+ values = [float(r) for r in pt_res.split()]
131
+ max_vals.append(max(values))
132
+ else:
133
+ for pt_res in results:
134
+ values = [float(r) for r, is_hoy in zip(pt_res.split(), su_pattern) if is_hoy]
135
+ max_vals.append(max(values))
136
+ return max_vals, max_i
137
+
138
+
139
+ if all_required_inputs(ghenv.Component):
140
+ # set up the default values
141
+ grid_filter_ = '*' if grid_filter_ is None else grid_filter_
142
+ res_folder = os.path.dirname(_results[0]) if os.path.isfile(_results[0]) \
143
+ else _results[0]
144
+
145
+ # check to see if results use the newer numpy arrays
146
+ if os.path.isdir(os.path.join(res_folder, '__static_apertures__')) or \
147
+ os.path.isfile(os.path.join(res_folder, 'grid_states.json')):
148
+ cmds = [folders.python_exe_path, '-m', 'honeybee_radiance_postprocess',
149
+ 'post-process', 'peak-values', res_folder, '-sf', 'metrics']
150
+ if len(_hoys_) != 0:
151
+ hoys_str = '\n'.join(str(h) for h in _hoys_)
152
+ hoys_file = os.path.join(res_folder, 'hoys.txt')
153
+ write_to_file(hoys_file, hoys_str)
154
+ cmds.extend(['--hoys-file', hoys_file])
155
+ if grid_filter_ != '*':
156
+ cmds.extend(['--grids-filter', grid_filter_])
157
+ if coincident_:
158
+ cmds.append('--coincident')
159
+ if len(dyn_sch_) != 0:
160
+ if os.path.isfile(os.path.join(res_folder, 'grid_states.json')):
161
+ dyn_sch = dyn_sch_[0] if isinstance(dyn_sch_[0], DynamicSchedule) else \
162
+ DynamicSchedule.from_group_schedules(dyn_sch_)
163
+ dyn_sch_file = dyn_sch.to_json(folder=res_folder)
164
+ cmds.extend(['--states', dyn_sch_file])
165
+ else:
166
+ msg = 'No dynamic aperture groups were found in the Model.\n' \
167
+ 'The input dynamic schedules will be ignored.'
168
+ print(msg)
169
+ give_warning(ghenv.Component, msg)
170
+ use_shell = True if os.name == 'nt' else False
171
+ custom_env = os.environ.copy()
172
+ custom_env['PYTHONHOME'] = ''
173
+ process = subprocess.Popen(
174
+ cmds, cwd=res_folder, shell=use_shell, env=custom_env,
175
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE)
176
+ stdout = process.communicate() # wait for the process to finish
177
+ if stdout[-1] != '':
178
+ print(stdout[-1])
179
+ raise ValueError('Failed to compute peak values.')
180
+ avg_dir = os.path.join(res_folder, 'metrics', 'peak_values')
181
+ if os.path.isdir(avg_dir):
182
+ values = read_sensor_grid_result(avg_dir, 'peak','full_id', False)
183
+ values = list_to_data_tree(values)
184
+ with open(os.path.join(avg_dir, 'max_hoys.txt'), 'r') as max_hoys:
185
+ hoys = [line.rstrip() for line in max_hoys.readlines()]
186
+ if coincident_:
187
+ hoys = map(int, hoys)
188
+ else:
189
+ hoys = [None] * len(hoys)
190
+
191
+ else:
192
+ if len(dyn_sch_) != 0:
193
+ msg = 'Dynamic Schedules are currently only supported for Annual Daylight ' \
194
+ 'simulations.\nThe input schedules will be ignored.'
195
+ print(msg)
196
+ give_warning(ghenv.Component, msg)
197
+
198
+ # extract the timestep if it exists
199
+ timestep = 1
200
+ tstep_file = os.path.join(res_folder, 'timestep.txt')
201
+ if os.path.isfile(tstep_file):
202
+ with open(tstep_file) as tf:
203
+ timestep = int(tf.readline())
204
+
205
+ # parse the sun-up-hours
206
+ grids, sun_up_hours = _process_input_folder(res_folder, grid_filter_)
207
+ su_pattern = parse_sun_up_hours(sun_up_hours, _hoys_, timestep)
208
+ filt_suh = [suh for suh in sun_up_hours if int(suh) in _hoys_] \
209
+ if len(_hoys_) != 0 else sun_up_hours
210
+ # compute the average values
211
+ values, hoys = [], []
212
+ for grid_info in grids:
213
+ ill_file = os.path.join(res_folder, '%s.ill' % grid_info['full_id'])
214
+ dgp_file = os.path.join(res_folder, '%s.dgp' % grid_info['full_id'])
215
+ if os.path.isfile(dgp_file):
216
+ max_list, max_i = peak_values(dgp_file, su_pattern, coincident_)
217
+ else:
218
+ max_list, max_i = peak_values(ill_file, su_pattern, coincident_)
219
+ values.append(max_list)
220
+ if max_i is not None:
221
+ hoys.append(filt_suh[max_i])
222
+ else:
223
+ hoys.append(max_i)
224
+ values = list_to_data_tree(values)
@@ -0,0 +1,246 @@
1
+ # This file is part of Honeybee.
2
+ #
3
+ # Copyright (c) 2025, Ladybug Tools.
4
+ # You should have received a copy of the GNU Affero General Public License
5
+ # along with Honeybee; If not, see <http://www.gnu.org/licenses/>.
6
+ #
7
+ # @license AGPL-3.0-or-later <https://spdx.org/licenses/AGPL-3.0-or-later>
8
+
9
+ """
10
+ Import the hourly illuminance or irradiance results of an annual daylight or irradiance
11
+ study to a list of data collections.
12
+ _
13
+ The resulting data collections can be visulized using the ladybug components or
14
+ deconstructed for detailed analysis with native Grasshopper math components.
15
+
16
+ -
17
+ Args:
18
+ _results: An list of annual Radiance result files from the "HB Annual Daylight"
19
+ component (containing the .ill files and the sun-up-hours.txt).
20
+ This can also be just the path to the folder containing these
21
+ result files.
22
+ dyn_sch_: Optional dynamic Aperture Group Schedules from the "HB Aperture Group
23
+ Schedule" component, which will be used to customize the behavior
24
+ of any dyanmic aperture geometry in the output metrics. If unsupplied,
25
+ all dynamic aperture groups will be in their default state in for
26
+ the output metrics.
27
+ _sel_pts: A point or list of points, which will be used to filter the sensors
28
+ for which data collections will be imported.
29
+ _all_pts: The data tree of all sensor points that were used in the simulation.
30
+ This is required in order to look up the index of the _sel_pts in
31
+ the results matrices.
32
+ sel_vecs_: An optional vector or list of vectors, which will be used to filter
33
+ the sensors for which data collections will be imported. If there
34
+ is an input here, the all_vecs_ must be connected.
35
+ all_vecs_: The data tree of all sensor directions that were used in the simulation.
36
+ This is required in order to look up the index of the sel_vecs_ in
37
+ the results matrices.
38
+
39
+ Returns:
40
+ report: Reports, errors, warnings, etc.
41
+ data: A list of hourly data collections containing illuminance or irradiance results.
42
+ These can be visulized using the ladybug components or deconstructed
43
+ for detailed analysis with native Grasshopper math components.
44
+ """
45
+
46
+ ghenv.Component.Name = 'HB Annual Results to Data'
47
+ ghenv.Component.NickName = 'AnnualToData'
48
+ ghenv.Component.Message = '1.9.0'
49
+ ghenv.Component.Category = 'HB-Radiance'
50
+ ghenv.Component.SubCategory = '4 :: Results'
51
+ ghenv.Component.AdditionalHelpFromDocStrings = '2'
52
+
53
+ import os
54
+ import json
55
+ import subprocess
56
+
57
+ try:
58
+ from ladybug.datatype.illuminance import Illuminance
59
+ from ladybug.datatype.energyflux import Irradiance
60
+ from ladybug.datatype.time import Time
61
+ from ladybug.datatype.fraction import Fraction
62
+ from ladybug.analysisperiod import AnalysisPeriod
63
+ from ladybug.header import Header
64
+ from ladybug.datacollection import HourlyContinuousCollection
65
+ from ladybug.futil import write_to_file
66
+ except ImportError as e:
67
+ raise ImportError('\nFailed to import ladybug:\n\t{}'.format(e))
68
+
69
+ try:
70
+ from honeybee.config import folders
71
+ except ImportError as e:
72
+ raise ImportError('\nFailed to import honeybee:\n\t{}'.format(e))
73
+
74
+ try:
75
+ from honeybee_radiance.postprocess.annualdaylight import _process_input_folder
76
+ except ImportError as e:
77
+ raise ImportError('\nFailed to import honeybee_radiance:\n\t{}'.format(e))
78
+
79
+ try:
80
+ from honeybee_radiance_postprocess.dynamic import DynamicSchedule
81
+ except ImportError as e:
82
+ raise ImportError('\nFailed to import honeybee_radiance:\n\t{}'.format(e))
83
+
84
+ try:
85
+ from ladybug_rhino.config import tolerance
86
+ from ladybug_rhino.togeometry import to_point3d, to_vector3d
87
+ from ladybug_rhino.grasshopper import all_required_inputs, list_to_data_tree, \
88
+ data_tree_to_list, give_warning
89
+ except ImportError as e:
90
+ raise ImportError('\nFailed to import ladybug_rhino:\n\t{}'.format(e))
91
+
92
+
93
+ def file_to_data(ill_file, point_filter, su_pattern, header, timestep, grid_id):
94
+ """Get a list of data collections for a given result file."""
95
+ data_colls = []
96
+ new_header = header.duplicate()
97
+ new_header.metadata['sensor grid'] = grid_id
98
+ with open(ill_file) as results:
99
+ if point_filter is None:
100
+ for pt_res in results:
101
+ base_values = [0] * 8760 * timestep
102
+ for val, hr in zip(pt_res.split(), su_pattern):
103
+ base_values[hr] = float(val)
104
+ data_colls.append(HourlyContinuousCollection(new_header, base_values))
105
+ else:
106
+ for i, pt_res in enumerate(results):
107
+ if i in point_filter:
108
+ new_header = new_header.duplicate()
109
+ new_header.metadata['sensor index'] = i
110
+ base_values = [0] * 8760 * timestep
111
+ for val, hr in zip(pt_res.split(), su_pattern):
112
+ base_values[hr] = float(val)
113
+ data_colls.append(HourlyContinuousCollection(new_header, base_values))
114
+ return data_colls
115
+
116
+
117
+ def find_point_in_grid(s_pt, all_pts):
118
+ """Find the index of a point in a list of list of grids."""
119
+ m_pts = []
120
+ for i, grid_pts in enumerate(all_pts):
121
+ for j, g_pt in enumerate(grid_pts):
122
+ if g_pt.is_equivalent(s_pt, tolerance):
123
+ m_pts.append((i, j))
124
+ return m_pts
125
+
126
+
127
+ def find_vec_in_grid(s_v, all_vecs, pt_filter):
128
+ """Find the index of a vector in a list of list of grids."""
129
+ m_vecs = []
130
+ for i, grid in enumerate(pt_filter):
131
+ for j in grid:
132
+ if all_vecs[i][j].is_equivalent(s_v, tolerance):
133
+ m_vecs.append((i, j))
134
+ return m_vecs
135
+
136
+
137
+ if all_required_inputs(ghenv.Component):
138
+ # get the relevant .ill files
139
+ res_folder = os.path.dirname(_results[0]) if os.path.isfile(_results[0]) \
140
+ else _results[0]
141
+ grids, sun_up_hours = _process_input_folder(res_folder, '*')
142
+
143
+ # set up the sensor filter
144
+ pt_filter = [None for i in grids]
145
+ if len(_sel_pts) != 0 or len(sel_vecs_) != 0:
146
+ pt_filter = [[] for i in grids]
147
+
148
+ # check the sel_pts and all_pts input
149
+ if len(_sel_pts) != 0:
150
+ all_pts = [[to_point3d(pt) for pt in dat[-1]] for dat in data_tree_to_list(_all_pts)]
151
+ assert len(all_pts) != 0, '_all_pts must be connected in order to use _sel_pts.'
152
+ sel_pts = [to_point3d(pt) for pt in _sel_pts]
153
+ for s_pt in sel_pts:
154
+ m_pts = find_point_in_grid(s_pt, all_pts)
155
+ for i, j in m_pts:
156
+ pt_filter[i].append(j)
157
+
158
+ # check the sel_vecs and all_vecs input
159
+ if len(sel_vecs_) != 0:
160
+ new_pt_filter = [[] for i in grids]
161
+ all_vecs = [[to_vector3d(v) for v in dat[-1]] for dat in data_tree_to_list(all_vecs_)]
162
+ assert len(all_vecs) != 0, 'all_vecs_ must be connected in order to use sel_vecs_.'
163
+ sel_vecs = [to_vector3d(v) for v in sel_vecs_]
164
+ for s_v in sel_vecs:
165
+ m_vs = find_point_in_grid(s_v, all_vecs) if len(_sel_pts) == 0 else \
166
+ find_vec_in_grid(s_v, all_vecs, pt_filter)
167
+ for i, j in m_vs:
168
+ new_pt_filter[i].append(j)
169
+ pt_filter = new_pt_filter
170
+
171
+ # check to see if results use the newer numpy arrays
172
+ if os.path.isdir(os.path.join(res_folder, '__static_apertures__')) or \
173
+ os.path.isfile(os.path.join(res_folder, 'grid_states.json')):
174
+ cmds = [folders.python_exe_path, '-m', 'honeybee_radiance_postprocess',
175
+ 'post-process', 'annual-to-data', res_folder]
176
+ if pt_filter[0] is not None:
177
+ sen_dict = {g['full_id']: s_ind for g, s_ind in zip(grids, pt_filter)}
178
+ si_file = os.path.join(res_folder, 'sensor_indices.json')
179
+ write_to_file(si_file, json.dumps(sen_dict))
180
+ cmds.extend(['--sensor-index', si_file])
181
+ if len(dyn_sch_) != 0:
182
+ if os.path.isfile(os.path.join(res_folder, 'grid_states.json')):
183
+ dyn_sch = dyn_sch_[0] if isinstance(dyn_sch_[0], DynamicSchedule) else \
184
+ DynamicSchedule.from_group_schedules(dyn_sch_)
185
+ dyn_sch_file = dyn_sch.to_json(folder=res_folder)
186
+ cmds.extend(['--states', dyn_sch_file])
187
+ else:
188
+ msg = 'No dynamic aperture groups were found in the Model.\n' \
189
+ 'The input dynamic schedules will be ignored.'
190
+ print(msg)
191
+ give_warning(ghenv.Component, msg)
192
+ use_shell = True if os.name == 'nt' else False
193
+ custom_env = os.environ.copy()
194
+ custom_env['PYTHONHOME'] = ''
195
+ process = subprocess.Popen(
196
+ cmds, cwd=res_folder, shell=use_shell, env=custom_env,
197
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE)
198
+ stdout, stderr = process.communicate() # wait for the process to finish
199
+ if stderr != '':
200
+ print(stderr)
201
+ raise ValueError('Failed to compute data collections.')
202
+ data_dicts = json.loads(stdout)
203
+ data = [[HourlyContinuousCollection.from_dict(d) for d in data]
204
+ for data in data_dicts]
205
+ data = list_to_data_tree(data)
206
+
207
+ else:
208
+ if len(dyn_sch_) != 0:
209
+ msg = 'Dynamic Schedules are currently only supported for Annual Daylight ' \
210
+ 'simulations.\nThe input schedules will be ignored.'
211
+ print(msg)
212
+ give_warning(ghenv.Component, msg)
213
+
214
+ # extract the timestep if it exists
215
+ timestep, has_t_step = 1, False
216
+ tstep_file = os.path.join(res_folder, 'timestep.txt')
217
+ if os.path.isfile(tstep_file): # it's an annual irradiance simulation
218
+ with open(tstep_file) as tf:
219
+ timestep = int(tf.readline())
220
+ has_t_step = True
221
+
222
+ # parse the sun-up-hours
223
+ sun_up_hours = [int(h * timestep) for h in sun_up_hours]
224
+
225
+ # create the header that will be used for all of the data collections
226
+ aper = AnalysisPeriod(timestep=timestep)
227
+ if 'direct_sun_hours' in res_folder:
228
+ head = Header(Time(), 'hr', aper)
229
+ elif has_t_step:
230
+ head = Header(Irradiance(), 'W/m2', aper)
231
+ else:
232
+ head = Header(Illuminance(), 'lux', aper)
233
+ dgp_head = Header(Fraction(), 'fraction', aper, metadata={'type': 'Daylight Glare Probability (DGP)'})
234
+
235
+ # create the data collections from the .ill files
236
+ data = []
237
+ for grid_info, p_filt in zip(grids, pt_filter):
238
+ grid_id = grid_info['full_id']
239
+ ill_file = os.path.join(res_folder, '%s.ill' % grid_id)
240
+ dgp_file = os.path.join(res_folder, '%s.dgp' % grid_id)
241
+ if os.path.isfile(dgp_file):
242
+ data_list = file_to_data(dgp_file, p_filt, sun_up_hours, dgp_head, timestep, grid_id)
243
+ else:
244
+ data_list = file_to_data(ill_file, p_filt, sun_up_hours, head, timestep, grid_id)
245
+ data.append(data_list)
246
+ data = list_to_data_tree(data)
@@ -0,0 +1,147 @@
1
+ # Honeybee: A Plugin for Environmental Analysis (GPL)
2
+ # This file is part of Honeybee.
3
+ #
4
+ # Copyright (c) 2025, Ladybug Tools.
5
+ # You should have received a copy of the GNU Affero General Public License
6
+ # along with Honeybee; If not, see <http://www.gnu.org/licenses/>.
7
+ #
8
+ # @license AGPL-3.0-or-later <https://spdx.org/licenses/AGPL-3.0-or-later>
9
+
10
+ """
11
+ Calculate Annual Sunlight Exposure from a results folder.
12
+ _
13
+ Note: This component will only output a LEED compliant ASE if you've run the
14
+ simulation with all operable shading devices retracted. If you are using
15
+ results with operable shading devices, then this output is NOT LEED compliant.
16
+
17
+ -
18
+ Args:
19
+ _results: An annual results folder containing direct illuminance results.
20
+ This can be the output of the "HB Annual Daylight" component. This can
21
+ also be just the path to the results folder.
22
+ _occ_sch_: An annual occupancy schedule as a Ladybug Data Collection or a HB-Energy
23
+ schedule object. This can also be the identifier of a schedule in
24
+ your HB-Energy schedule library. Any value in this schedule that is
25
+ 0.1 or above will be considered occupied. If None, a schedule from
26
+ 8AM to 6PM on all days will be used.
27
+ _threshold_: The threshold (lux) that determines if a sensor is
28
+ overlit (default: 1000).
29
+ _target_hrs_: The number of occupied hours that cannot receive higher
30
+ illuminance than the direct threshold (default: 250).
31
+ grid_filter_: The name of a grid or a pattern to filter the grids. For instance,
32
+ first_floor_* will simulate only the sensor grids that have an
33
+ identifier that starts with first_floor_. By default all the grids
34
+ will be processed.
35
+
36
+ Returns:
37
+ report: Reports, errors, warnings, etc.
38
+ ASE: Annual sunlight exposure as a percentage for each sensor grid.
39
+ hrs_above: The number of hours above the threshold for each sensor point.
40
+ These can be plugged into the "LB Spatial Heatmap" component along with
41
+ meshes of the sensor grids to visualize results.
42
+ """
43
+
44
+ ghenv.Component.Name = "HB Annual Sunlight Exposure"
45
+ ghenv.Component.NickName = 'ASE'
46
+ ghenv.Component.Message = '1.9.0'
47
+ ghenv.Component.Category = 'HB-Radiance'
48
+ ghenv.Component.SubCategory = '4 :: Results'
49
+ ghenv.Component.AdditionalHelpFromDocStrings = '1'
50
+
51
+ import os
52
+ import subprocess
53
+
54
+ try:
55
+ from ladybug.datacollection import BaseCollection
56
+ from ladybug.futil import write_to_file
57
+ except ImportError as e:
58
+ raise ImportError('\nFailed to import ladybug:\n\t{}'.format(e))
59
+
60
+ try:
61
+ from honeybee.config import folders
62
+ except ImportError as e:
63
+ raise ImportError('\nFailed to import honeybee:\n\t{}'.format(e))
64
+
65
+ try:
66
+ from honeybee_energy.lib.schedules import schedule_by_identifier
67
+ except ImportError as e: # honeybee schedule library is not available
68
+ schedule_by_identifier = None
69
+
70
+ try:
71
+ from pollination_handlers.outputs.daylight import read_ase_from_folder, \
72
+ read_hours_from_folder
73
+ except ImportError as e:
74
+ raise ImportError('\nFailed to import pollination_handlers:\n\t{}'.format(e))
75
+
76
+ try:
77
+ from ladybug_rhino.grasshopper import all_required_inputs, list_to_data_tree
78
+ except ImportError as e:
79
+ raise ImportError('\nFailed to import ladybug_rhino:\n\t{}'.format(e))
80
+
81
+
82
+ if all_required_inputs(ghenv.Component):
83
+ # set default values for the thresholds and the grid filter
84
+ grid_filter_ = '*' if grid_filter_ is None else grid_filter_
85
+ _direct_threshold_ = _threshold_ if _threshold_ else 1000
86
+ _occ_hours_ = _target_hrs_ if _target_hrs_ else 250
87
+
88
+ # process the schedule
89
+ if _occ_sch_ is None:
90
+ schedule = None
91
+ elif isinstance(_occ_sch_, BaseCollection):
92
+ schedule = _occ_sch_.values
93
+ elif isinstance(_occ_sch_, str):
94
+ if schedule_by_identifier is not None:
95
+ try:
96
+ schedule = schedule_by_identifier(_occ_sch_).values()
97
+ except TypeError: # it's probably a ScheduleFixedInterval
98
+ schedule = schedule_by_identifier(_occ_sch_).values
99
+ else:
100
+ raise ValueError('honeybee-energy must be installed to reference '
101
+ 'occupancy schedules by identifier.')
102
+ else: # assume that it is a honeybee schedule object
103
+ try:
104
+ schedule = _occ_sch_.values()
105
+ except TypeError: # it's probably a ScheduleFixedInterval
106
+ schedule = _occ_sch_.values
107
+ if schedule is not None:
108
+ bin_schedule = []
109
+ for val in schedule:
110
+ bin_val = 1 if val >= 0.1 else 0
111
+ bin_schedule.append(bin_val)
112
+ schedule = bin_schedule
113
+
114
+ # compute the annual metrics
115
+ res_folder = os.path.dirname(_results[0]) if os.path.isfile(_results[0]) \
116
+ else _results[0]
117
+ if os.path.isfile(os.path.join(res_folder, 'grid_states.json')):
118
+ cmds = [
119
+ folders.python_exe_path, '-m', 'honeybee_radiance_postprocess',
120
+ 'post-process', 'annual-sunlight-exposure', res_folder, '-sf', 'metrics',
121
+ '-dt', str(_direct_threshold_), '-oh', str(_occ_hours_)
122
+ ]
123
+ if grid_filter_ != '*':
124
+ cmds.extend(['--grids-filter', grid_filter_])
125
+ if schedule is not None:
126
+ sch_str = '\n'.join(str(h) for h in schedule)
127
+ sch_file = os.path.join(res_folder, 'schedule.txt')
128
+ write_to_file(sch_file, sch_str)
129
+ cmds.extend(['--schedule', sch_file])
130
+ use_shell = True if os.name == 'nt' else False
131
+ custom_env = os.environ.copy()
132
+ custom_env['PYTHONHOME'] = ''
133
+ process = subprocess.Popen(
134
+ cmds, cwd=res_folder, shell=use_shell, env=custom_env,
135
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE)
136
+ stdout = process.communicate() # wait for the process to finish
137
+ if stdout[-1] != '':
138
+ print(stdout[-1])
139
+ raise ValueError('Failed to compute annual sunlight exposure.')
140
+ metric_dir = os.path.join(res_folder, 'metrics')
141
+ ASE = read_ase_from_folder(os.path.join(metric_dir, 'ase'))
142
+ hrs_above = list_to_data_tree(read_hours_from_folder(os.path.join(metric_dir, 'hours_above')))
143
+ else:
144
+ raise ValueError(
145
+ 'Invalid results folder!\n'
146
+ 'Make sure an enhanced daylight simulation was run'
147
+ )
@@ -0,0 +1,69 @@
1
+ # Honeybee: A Plugin for Environmental Analysis (GPL)
2
+ # This file is part of Honeybee.
3
+ #
4
+ # Copyright (c) 2025, Ladybug Tools.
5
+ # You should have received a copy of the GNU Affero General Public License
6
+ # along with Honeybee; If not, see <http://www.gnu.org/licenses/>.
7
+ #
8
+ # @license AGPL-3.0-or-later <https://spdx.org/licenses/AGPL-3.0-or-later>
9
+
10
+ """
11
+ Create a Dynamic Aperture Group Schedule, which can be used to process any dynamic
12
+ aperture geometry that was run in an annual simulation.
13
+
14
+ -
15
+ Args:
16
+ _group_aps: Honeybee Apertures that are a part of the same dynamic group and will
17
+ be assigned the same schedule for postprocessing. Typically, this is
18
+ the output of the "HB Dynamic Aperture Group" component but it can
19
+ also be the output of the "HB Get Dynamic Groups" component, which
20
+ returns all of the dynamic groups on a particular Model.
21
+ _schedule: A list of 8760 integers refering to the index of the aperture group state
22
+ to be used at each hour of the simulation. This can also be a single integer
23
+ for a static state to be used for the entire period of the simulation
24
+ or a pattern of integers that is less than 8760 in length and will be
25
+ repeated until the 8760 is reached. Note that 0 refers to the first
26
+ state, 1 refers to the second state, and so on. -1 can be used to
27
+ completely discout the aperture from the simulation for a given hour.
28
+
29
+ Returns:
30
+ dyn_sch: A dynamic schedule object for the input aperture group, which can be plugged
31
+ into any of the Results components with a syn_sch input.
32
+ """
33
+
34
+ ghenv.Component.Name = 'HB Aperture Group Schedule'
35
+ ghenv.Component.NickName = 'GroupSch'
36
+ ghenv.Component.Message = '1.9.0'
37
+ ghenv.Component.Category = 'HB-Radiance'
38
+ ghenv.Component.SubCategory = '4 :: Results'
39
+ ghenv.Component.AdditionalHelpFromDocStrings = '1'
40
+
41
+ try:
42
+ from honeybee.aperture import Aperture
43
+ except ImportError as e:
44
+ raise ImportError('\nFailed to import honeybee:\n\t{}'.format(e))
45
+
46
+ try:
47
+ from honeybee_radiance_postprocess.dynamic import ApertureGroupSchedule
48
+ except ImportError as e:
49
+ raise ImportError('\nFailed to import honeybee_radiance:\n\t{}'.format(e))
50
+
51
+ try:
52
+ from ladybug_rhino.grasshopper import all_required_inputs, recipe_result
53
+ except ImportError as e:
54
+ raise ImportError('\nFailed to import ladybug_rhino:\n\t{}'.format(e))
55
+
56
+
57
+ if all_required_inputs(ghenv.Component):
58
+ dyn_sch = []
59
+ dyn_ids = set()
60
+ for ap in _group_aps:
61
+ assert isinstance(ap, Aperture), 'Expected Aperture. Got {}.'.format(type(ap))
62
+ dyn_grp_id = ap.properties.radiance.dynamic_group_identifier
63
+ if dyn_grp_id is None:
64
+ raise ValueError(
65
+ 'Input Aperture "{}" is not a part of a dynamic group.'.format(ap.display_name))
66
+ if dyn_grp_id not in dyn_ids:
67
+ dyn_ids.add(dyn_grp_id)
68
+ _ap_group_sch = ApertureGroupSchedule(dyn_grp_id, _schedule)
69
+ dyn_sch.append(_ap_group_sch)