honeybee-radiance 1.66.190__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.

Potentially problematic release.


This version of honeybee-radiance might be problematic. Click here for more details.

Files changed (152) hide show
  1. honeybee_radiance/__init__.py +11 -0
  2. honeybee_radiance/__main__.py +4 -0
  3. honeybee_radiance/_extend_honeybee.py +93 -0
  4. honeybee_radiance/cli/__init__.py +88 -0
  5. honeybee_radiance/cli/dc.py +400 -0
  6. honeybee_radiance/cli/edit.py +529 -0
  7. honeybee_radiance/cli/glare.py +118 -0
  8. honeybee_radiance/cli/grid.py +859 -0
  9. honeybee_radiance/cli/lib.py +458 -0
  10. honeybee_radiance/cli/modifier.py +133 -0
  11. honeybee_radiance/cli/mtx.py +226 -0
  12. honeybee_radiance/cli/multiphase.py +1034 -0
  13. honeybee_radiance/cli/octree.py +640 -0
  14. honeybee_radiance/cli/postprocess.py +1186 -0
  15. honeybee_radiance/cli/raytrace.py +219 -0
  16. honeybee_radiance/cli/rpict.py +125 -0
  17. honeybee_radiance/cli/schedule.py +56 -0
  18. honeybee_radiance/cli/setconfig.py +63 -0
  19. honeybee_radiance/cli/sky.py +545 -0
  20. honeybee_radiance/cli/study.py +66 -0
  21. honeybee_radiance/cli/sunpath.py +331 -0
  22. honeybee_radiance/cli/threephase.py +255 -0
  23. honeybee_radiance/cli/translate.py +400 -0
  24. honeybee_radiance/cli/util.py +121 -0
  25. honeybee_radiance/cli/view.py +261 -0
  26. honeybee_radiance/cli/viewfactor.py +347 -0
  27. honeybee_radiance/config.json +6 -0
  28. honeybee_radiance/config.py +427 -0
  29. honeybee_radiance/dictutil.py +50 -0
  30. honeybee_radiance/dynamic/__init__.py +5 -0
  31. honeybee_radiance/dynamic/group.py +479 -0
  32. honeybee_radiance/dynamic/multiphase.py +557 -0
  33. honeybee_radiance/dynamic/state.py +718 -0
  34. honeybee_radiance/dynamic/stategeo.py +352 -0
  35. honeybee_radiance/geometry/__init__.py +13 -0
  36. honeybee_radiance/geometry/bubble.py +42 -0
  37. honeybee_radiance/geometry/cone.py +215 -0
  38. honeybee_radiance/geometry/cup.py +54 -0
  39. honeybee_radiance/geometry/cylinder.py +197 -0
  40. honeybee_radiance/geometry/geometrybase.py +37 -0
  41. honeybee_radiance/geometry/instance.py +40 -0
  42. honeybee_radiance/geometry/mesh.py +38 -0
  43. honeybee_radiance/geometry/polygon.py +174 -0
  44. honeybee_radiance/geometry/ring.py +214 -0
  45. honeybee_radiance/geometry/source.py +182 -0
  46. honeybee_radiance/geometry/sphere.py +178 -0
  47. honeybee_radiance/geometry/tube.py +46 -0
  48. honeybee_radiance/lib/__init__.py +1 -0
  49. honeybee_radiance/lib/_loadmodifiers.py +72 -0
  50. honeybee_radiance/lib/_loadmodifiersets.py +69 -0
  51. honeybee_radiance/lib/modifiers.py +58 -0
  52. honeybee_radiance/lib/modifiersets.py +63 -0
  53. honeybee_radiance/lightpath.py +204 -0
  54. honeybee_radiance/lightsource/__init__.py +1 -0
  55. honeybee_radiance/lightsource/_gendaylit.py +479 -0
  56. honeybee_radiance/lightsource/dictutil.py +49 -0
  57. honeybee_radiance/lightsource/ground.py +160 -0
  58. honeybee_radiance/lightsource/sky/__init__.py +7 -0
  59. honeybee_radiance/lightsource/sky/_skybase.py +177 -0
  60. honeybee_radiance/lightsource/sky/certainirradiance.py +232 -0
  61. honeybee_radiance/lightsource/sky/cie.py +378 -0
  62. honeybee_radiance/lightsource/sky/climatebased.py +501 -0
  63. honeybee_radiance/lightsource/sky/hemisphere.py +160 -0
  64. honeybee_radiance/lightsource/sky/skydome.py +113 -0
  65. honeybee_radiance/lightsource/sky/skymatrix.py +163 -0
  66. honeybee_radiance/lightsource/sky/strutil.py +34 -0
  67. honeybee_radiance/lightsource/sky/sunmatrix.py +212 -0
  68. honeybee_radiance/lightsource/sunpath.py +247 -0
  69. honeybee_radiance/modifier/__init__.py +3 -0
  70. honeybee_radiance/modifier/material/__init__.py +30 -0
  71. honeybee_radiance/modifier/material/absdf.py +477 -0
  72. honeybee_radiance/modifier/material/antimatter.py +54 -0
  73. honeybee_radiance/modifier/material/ashik2.py +51 -0
  74. honeybee_radiance/modifier/material/brtdfunc.py +81 -0
  75. honeybee_radiance/modifier/material/bsdf.py +292 -0
  76. honeybee_radiance/modifier/material/dielectric.py +53 -0
  77. honeybee_radiance/modifier/material/glass.py +431 -0
  78. honeybee_radiance/modifier/material/glow.py +246 -0
  79. honeybee_radiance/modifier/material/illum.py +51 -0
  80. honeybee_radiance/modifier/material/interface.py +49 -0
  81. honeybee_radiance/modifier/material/light.py +206 -0
  82. honeybee_radiance/modifier/material/materialbase.py +36 -0
  83. honeybee_radiance/modifier/material/metal.py +167 -0
  84. honeybee_radiance/modifier/material/metal2.py +41 -0
  85. honeybee_radiance/modifier/material/metdata.py +41 -0
  86. honeybee_radiance/modifier/material/metfunc.py +41 -0
  87. honeybee_radiance/modifier/material/mirror.py +340 -0
  88. honeybee_radiance/modifier/material/mist.py +86 -0
  89. honeybee_radiance/modifier/material/plasdata.py +58 -0
  90. honeybee_radiance/modifier/material/plasfunc.py +59 -0
  91. honeybee_radiance/modifier/material/plastic.py +354 -0
  92. honeybee_radiance/modifier/material/plastic2.py +58 -0
  93. honeybee_radiance/modifier/material/prism1.py +57 -0
  94. honeybee_radiance/modifier/material/prism2.py +48 -0
  95. honeybee_radiance/modifier/material/spotlight.py +50 -0
  96. honeybee_radiance/modifier/material/trans.py +518 -0
  97. honeybee_radiance/modifier/material/trans2.py +49 -0
  98. honeybee_radiance/modifier/material/transdata.py +50 -0
  99. honeybee_radiance/modifier/material/transfunc.py +53 -0
  100. honeybee_radiance/modifier/mixture/__init__.py +6 -0
  101. honeybee_radiance/modifier/mixture/mixdata.py +49 -0
  102. honeybee_radiance/modifier/mixture/mixfunc.py +54 -0
  103. honeybee_radiance/modifier/mixture/mixpict.py +52 -0
  104. honeybee_radiance/modifier/mixture/mixtext.py +66 -0
  105. honeybee_radiance/modifier/mixture/mixturebase.py +28 -0
  106. honeybee_radiance/modifier/modifierbase.py +40 -0
  107. honeybee_radiance/modifier/pattern/__init__.py +9 -0
  108. honeybee_radiance/modifier/pattern/brightdata.py +49 -0
  109. honeybee_radiance/modifier/pattern/brightfunc.py +47 -0
  110. honeybee_radiance/modifier/pattern/brighttext.py +81 -0
  111. honeybee_radiance/modifier/pattern/colordata.py +56 -0
  112. honeybee_radiance/modifier/pattern/colorfunc.py +47 -0
  113. honeybee_radiance/modifier/pattern/colorpict.py +54 -0
  114. honeybee_radiance/modifier/pattern/colortext.py +73 -0
  115. honeybee_radiance/modifier/pattern/patternbase.py +34 -0
  116. honeybee_radiance/modifier/texture/__init__.py +4 -0
  117. honeybee_radiance/modifier/texture/texdata.py +29 -0
  118. honeybee_radiance/modifier/texture/texfunc.py +26 -0
  119. honeybee_radiance/modifier/texture/texturebase.py +27 -0
  120. honeybee_radiance/modifierset.py +1091 -0
  121. honeybee_radiance/mutil.py +60 -0
  122. honeybee_radiance/postprocess/__init__.py +1 -0
  123. honeybee_radiance/postprocess/annual.py +108 -0
  124. honeybee_radiance/postprocess/annualdaylight.py +425 -0
  125. honeybee_radiance/postprocess/annualglare.py +201 -0
  126. honeybee_radiance/postprocess/annualirradiance.py +187 -0
  127. honeybee_radiance/postprocess/electriclight.py +119 -0
  128. honeybee_radiance/postprocess/en17037.py +261 -0
  129. honeybee_radiance/postprocess/leed.py +304 -0
  130. honeybee_radiance/postprocess/solartracking.py +90 -0
  131. honeybee_radiance/primitive.py +554 -0
  132. honeybee_radiance/properties/__init__.py +1 -0
  133. honeybee_radiance/properties/_base.py +390 -0
  134. honeybee_radiance/properties/aperture.py +197 -0
  135. honeybee_radiance/properties/door.py +198 -0
  136. honeybee_radiance/properties/face.py +123 -0
  137. honeybee_radiance/properties/model.py +1291 -0
  138. honeybee_radiance/properties/room.py +490 -0
  139. honeybee_radiance/properties/shade.py +186 -0
  140. honeybee_radiance/properties/shademesh.py +116 -0
  141. honeybee_radiance/putil.py +44 -0
  142. honeybee_radiance/reader.py +214 -0
  143. honeybee_radiance/sensor.py +166 -0
  144. honeybee_radiance/sensorgrid.py +1008 -0
  145. honeybee_radiance/view.py +1101 -0
  146. honeybee_radiance/writer.py +951 -0
  147. honeybee_radiance-1.66.190.dist-info/METADATA +89 -0
  148. honeybee_radiance-1.66.190.dist-info/RECORD +152 -0
  149. honeybee_radiance-1.66.190.dist-info/WHEEL +5 -0
  150. honeybee_radiance-1.66.190.dist-info/entry_points.txt +2 -0
  151. honeybee_radiance-1.66.190.dist-info/licenses/LICENSE +661 -0
  152. honeybee_radiance-1.66.190.dist-info/top_level.txt +1 -0
@@ -0,0 +1,501 @@
1
+ """Generate a point-in-time climate-based sky."""
2
+ from __future__ import division
3
+ import argparse
4
+ import shlex
5
+
6
+ import ladybug.futil as futil
7
+ from ladybug.dt import DateTime
8
+ from ladybug.analysisperiod import AnalysisPeriod
9
+ from ladybug.location import Location
10
+ from ladybug.sunpath import Sunpath
11
+ from ladybug.wea import Wea
12
+ from ladybug.epw import EPW
13
+ import honeybee.typing as typing
14
+
15
+ from ._skybase import _PointInTime
16
+
17
+
18
+ class ClimateBased(_PointInTime):
19
+ """Point-in-time Climate-based sky.
20
+
21
+ The output of Climatebased sky is similar to using command Radiance's gendaylit
22
+ command. For more information see gendaylit documentation.
23
+
24
+ Args:
25
+ altitude: Solar altitude. The altitude is measured in degrees above the horizon.
26
+ azimuth: Solar azimuth. The azimuth is measured in degrees east of North.
27
+ East is 90, South is 180 and West is 270. Note that this input is
28
+ different from the Radiance convention. In Radiance the azimuth degrees
29
+ are measured in west of South.
30
+ direct_normal_irradiance: Direct normal irradiance (W/m2).
31
+ diffuse_horizontal_irradiance: Diffuse horizontal irradiance (W/m2).
32
+ ground_reflectance: Average ground reflectance (Default: 0.2).
33
+ is_colored: Boolean to note whether the sky will be rendered in full
34
+ color (True) or it will simple be a grey sky with the same average
35
+ value as the colored sky (False). (Default: False).
36
+
37
+ Properties:
38
+ * altitude
39
+ * azimuth
40
+ * direct_normal_irradiance
41
+ * diffuse_horizontal_irradiance
42
+ * ground_hemisphere
43
+ * sky_hemisphere
44
+ * ground_reflectance
45
+ * is_colored
46
+ * is_point_in_time
47
+ * is_climate_based
48
+ """
49
+
50
+ __slots__ = (
51
+ '_altitude', '_azimuth', '_diffuse_horizontal_irradiance',
52
+ '_direct_normal_irradiance', '_is_colored'
53
+ )
54
+
55
+ def __init__(
56
+ self, altitude, azimuth,
57
+ direct_normal_irradiance, diffuse_horizontal_irradiance,
58
+ ground_reflectance=0.2, is_colored=False
59
+ ):
60
+ """Create a climate-based standard sky."""
61
+ _PointInTime.__init__(self, ground_reflectance)
62
+ self.altitude = altitude
63
+ self.azimuth = azimuth
64
+ self.direct_normal_irradiance = direct_normal_irradiance
65
+ self.diffuse_horizontal_irradiance = diffuse_horizontal_irradiance
66
+ self.is_colored = is_colored
67
+
68
+ @property
69
+ def altitude(self):
70
+ """Get or set a number between -90 and 90 for the solar altitude.
71
+
72
+ The altitude is measured in degrees above the horizon.
73
+ """
74
+ return self._altitude
75
+
76
+ @altitude.setter
77
+ def altitude(self, value):
78
+ value = typing.float_in_range(value, -90, 90, 'Solar altitude')
79
+ self._altitude = value
80
+
81
+ @property
82
+ def azimuth(self):
83
+ """Get or set a number between 0 and 360 for the solar azimuth.
84
+
85
+ The azimuth is measured in degrees east of North. East is 90, South is 180 and
86
+ West is 270. Note that this input is different from Radiance convention. In
87
+ Radiance the azimuth degrees are measured in west of South.
88
+ """
89
+ return self._azimuth
90
+
91
+ @azimuth.setter
92
+ def azimuth(self, value):
93
+ value = typing.float_in_range(value, 0, 360, 'Solar azimuth')
94
+ self._azimuth = value
95
+
96
+ @property
97
+ def direct_normal_irradiance(self):
98
+ """Get or set direct normal irradiance (W/m2).
99
+ """
100
+ return self._direct_normal_irradiance
101
+
102
+ @direct_normal_irradiance.setter
103
+ def direct_normal_irradiance(self, value):
104
+ value = typing.int_positive(value, 'Direct normal irradiance')
105
+ self._direct_normal_irradiance = value
106
+
107
+ @property
108
+ def diffuse_horizontal_irradiance(self):
109
+ """Get or set diffuse horizontal irradiance (W/m2).
110
+ """
111
+ return self._diffuse_horizontal_irradiance
112
+
113
+ @diffuse_horizontal_irradiance.setter
114
+ def diffuse_horizontal_irradiance(self, value):
115
+ value = typing.int_positive(value, 'Diffuse horizontal irradiance')
116
+ self._diffuse_horizontal_irradiance = value
117
+
118
+ @property
119
+ def is_colored(self):
120
+ """Get or set a boolean for whether the sky is rendered in full color."""
121
+ return self._is_colored
122
+
123
+ @is_colored.setter
124
+ def is_colored(self, value):
125
+ self._is_colored = bool(value)
126
+
127
+ @property
128
+ def is_climate_based(self):
129
+ """Return True if the sky is created based on values from weather data."""
130
+ return True
131
+
132
+ @classmethod
133
+ def from_lat_long(
134
+ cls, latitude, longitude, time_zone, month, day, hour,
135
+ direct_normal_irradiance, diffuse_horizontal_irradiance,
136
+ north_angle=0, ground_reflectance=0.2, is_colored=False
137
+ ):
138
+ """Create a climate based sky from latitude, longitude and a date/time.
139
+
140
+ Args:
141
+ latitude: Location latitude between -90 and 90.
142
+ longitude: Location longitude between -180 (west) and 180 (east).
143
+ time_zone: Time zone between -12 hours (west) and +14 hours (east). If
144
+ None, the time will be interpreted as solar time at the given longitude.
145
+ month: An integer between 1-12 for month.
146
+ day: An integer between 1 to 28-31 depending on the input month.
147
+ hour: A float number larger or equal to 0 and smaller than 24.
148
+ direct_normal_irradiance: Direct normal irradiance (W/m2).
149
+ diffuse_horizontal_irradiance: Diffuse horizontal irradiance (W/m2).
150
+ north_angle: North angle in degrees. A number between -360 and 360 for the
151
+ counterclockwise difference between the North and the positive Y-axis in
152
+ degrees. 90 is West and 270 is East (Default: 0).
153
+ ground_reflectance: Average ground reflectance (Default: 0.2).
154
+ is_colored: Boolean to note whether the sky will be rendered in full
155
+ color (True) or it will simple be a grey sky with the same average
156
+ value as the colored sky (False). (Default: False).
157
+ """
158
+ # calculate altitude and azimuth using ladybug's sunpath
159
+ sp = Sunpath(latitude, longitude, time_zone, north_angle)
160
+ sun = sp.calculate_sun(month, day, hour)
161
+ return cls(
162
+ sun.altitude, sun.azimuth_from_y_axis,
163
+ direct_normal_irradiance, diffuse_horizontal_irradiance,
164
+ ground_reflectance, is_colored
165
+ )
166
+
167
+ @classmethod
168
+ def from_location(
169
+ cls, location, month, day, hour,
170
+ direct_normal_irradiance, diffuse_horizontal_irradiance,
171
+ north_angle=0, ground_reflectance=0.2, is_colored=False
172
+ ):
173
+ """Create a standard climate-based sky for a location.
174
+
175
+ Args:
176
+ location: A Ladybug location.
177
+ month: An integer between 1-12 for month.
178
+ day: An integer between 1 to 28-31 depending on the input month.
179
+ hour: A float number larger or equal to 0 and smaller than 24.
180
+ direct_normal_irradiance: Direct normal irradiance (W/m2).
181
+ diffuse_horizontal_irradiance: Diffuse horizontal irradiance (W/m2).
182
+ north_angle: North angle in degrees. A number between -360 and 360 for the
183
+ counterclockwise difference between the North and the positive Y-axis in
184
+ degrees. 90 is West and 270 is East (Default: 0).
185
+ ground_reflectance: Average ground reflectance (Default: 0.2).
186
+ is_colored: Boolean to note whether the sky will be rendered in full
187
+ color (True) or it will simple be a grey sky with the same average
188
+ value as the colored sky (False). (Default: False).
189
+ """
190
+ assert isinstance(location, Location), \
191
+ 'location must be from type Location not {}'.format(type(location))
192
+ return cls.from_lat_long(
193
+ location.latitude, location.longitude, location.time_zone, month, day, hour,
194
+ direct_normal_irradiance, diffuse_horizontal_irradiance, north_angle,
195
+ ground_reflectance, is_colored)
196
+
197
+ @classmethod
198
+ def from_wea(
199
+ cls, wea, month, day, hour, north_angle=0,
200
+ ground_reflectance=0.2, is_colored=False
201
+ ):
202
+ """Create a standard climate-based sky from a Wea.
203
+
204
+ Args:
205
+ wea: A Ladybug wea object.
206
+ month: An integer between 1-12 for month.
207
+ day: An integer between 1 to 28-31 depending on the input month.
208
+ hour: A float number larger or equal to 0 and smaller than 24.
209
+ north_angle: North angle in degrees. A number between -360 and 360 for the
210
+ counterclockwise difference between the North and the positive Y-axis in
211
+ degrees. 90 is West and 270 is East (Default: 0).
212
+ ground_reflectance: Average ground reflectance (Default: 0.2).
213
+ is_colored: Boolean to note whether the sky will be rendered in full
214
+ color (True) or it will simple be a grey sky with the same average
215
+ value as the colored sky (False). (Default: False).
216
+ """
217
+ assert isinstance(wea, Wea), \
218
+ 'wea must be from type Wea not {}'.format(type(wea))
219
+ location = wea.location
220
+ direct_normal_irradiance, diffuse_horizontal_irradiance = \
221
+ wea.get_irradiance_value(month, day, hour)
222
+ return cls.from_lat_long(
223
+ location.latitude, location.longitude, location.time_zone, month, day, hour,
224
+ direct_normal_irradiance, diffuse_horizontal_irradiance, north_angle,
225
+ ground_reflectance, is_colored)
226
+
227
+ @classmethod
228
+ def from_wea_monthly_average(
229
+ cls, wea, month, hour, north_angle=0, ground_reflectance=0.2, is_colored=False
230
+ ):
231
+ """Create a monthly averaged climate-based sky from a Wea and a hour of the day.
232
+
233
+ Args:
234
+ wea: A Ladybug wea object.
235
+ month: An integer between 1-12 for month.
236
+ hour: A float number larger or equal to 0 and smaller than 24.
237
+ north_angle: North angle in degrees. A number between -360 and 360 for the
238
+ counterclockwise difference between the North and the positive Y-axis in
239
+ degrees. 90 is West and 270 is East (Default: 0).
240
+ ground_reflectance: Average ground reflectance (Default: 0.2).
241
+ is_colored: Boolean to note whether the sky will be rendered in full
242
+ color (True) or it will simple be a grey sky with the same average
243
+ value as the colored sky (False). (Default: False).
244
+ """
245
+ assert isinstance(wea, Wea), \
246
+ 'wea must be from type Wea not {}'.format(type(wea))
247
+ a_period = AnalysisPeriod(
248
+ st_month=month, st_hour=hour, end_month=month, end_hour=hour,
249
+ timestep=wea.timestep, is_leap_year=wea.is_leap_year)
250
+ filtered_wea = wea.filter_by_analysis_period(a_period)
251
+ location = wea.location
252
+ dir_normal_irradiance = filtered_wea.direct_normal_irradiance.average
253
+ dif_horizontal_irradiance = filtered_wea.diffuse_horizontal_irradiance.average
254
+ return cls.from_lat_long(
255
+ location.latitude, location.longitude, location.time_zone, month, 15, hour,
256
+ dir_normal_irradiance, dif_horizontal_irradiance, north_angle,
257
+ ground_reflectance, is_colored)
258
+
259
+ @classmethod
260
+ def from_epw(
261
+ cls, epw, month, day, hour, north_angle=0,
262
+ ground_reflectance=0.2, is_colored=False
263
+ ):
264
+ """Create a standard climate-based sky from a EPW.
265
+
266
+ Args:
267
+ epw: A Ladybug EPW objects.
268
+ month: An integer between 1-12 for month.
269
+ day: An integer between 1 to 28-31 depending on the input month.
270
+ hour: A float number larger or equal to 0 and smaller than 24.
271
+ north_angle: North angle in degrees. A number between -360 and 360 for the
272
+ counterclockwise difference between the North and the positive Y-axis in
273
+ degrees. 90 is West and 270 is East (Default: 0).
274
+ ground_reflectance: Average ground reflectance (Default: 0.2).
275
+ is_colored: Boolean to note whether the sky will be rendered in full
276
+ color (True) or it will simple be a grey sky with the same average
277
+ value as the colored sky (False). (Default: False).
278
+ """
279
+ assert isinstance(epw, EPW), \
280
+ 'epw must be from type EPW not {}'.format(type(epw))
281
+ location = epw.location
282
+ hoy = int(DateTime(month, day, hour).hoy)
283
+ direct_normal_irradiance = epw.direct_normal_radiation[hoy]
284
+ diffuse_horizontal_irradiance = epw.diffuse_horizontal_radiation[hoy]
285
+ return cls.from_lat_long(
286
+ location.latitude, location.longitude, location.time_zone, month, day, hour,
287
+ direct_normal_irradiance, diffuse_horizontal_irradiance, north_angle,
288
+ ground_reflectance, is_colored)
289
+
290
+ @classmethod
291
+ def from_epw_monthly_average(
292
+ cls, epw, month, hour, north_angle=0, ground_reflectance=0.2, is_colored=False
293
+ ):
294
+ """Create a monthly averaged climate-based sky from an EPW and a hour of the day.
295
+
296
+ Args:
297
+ epw: A Ladybug EPW objects.
298
+ month: An integer between 1-12 for month.
299
+ hour: A float number larger or equal to 0 and smaller than 24.
300
+ north_angle: North angle in degrees. A number between -360 and 360 for the
301
+ counterclockwise difference between the North and the positive Y-axis in
302
+ degrees. 90 is West and 270 is East (Default: 0).
303
+ ground_reflectance: Average ground reflectance (Default: 0.2).
304
+ is_colored: Boolean to note whether the sky will be rendered in full
305
+ color (True) or it will simple be a grey sky with the same average
306
+ value as the colored sky (False). (Default: False).
307
+ """
308
+ assert isinstance(epw, EPW), \
309
+ 'epw must be from type EPW not {}'.format(type(epw))
310
+ location = epw.location
311
+ a_period = AnalysisPeriod(
312
+ st_month=month, st_hour=hour, end_month=month, end_hour=hour,
313
+ is_leap_year=epw.is_leap_year)
314
+ dn = epw.direct_normal_radiation.filter_by_analysis_period(a_period).average
315
+ dh = epw.diffuse_horizontal_radiation.filter_by_analysis_period(a_period).average
316
+ return cls.from_lat_long(
317
+ location.latitude, location.longitude, location.time_zone, month, 15, hour,
318
+ dn, dh, north_angle, ground_reflectance, is_colored)
319
+
320
+ @classmethod
321
+ def from_dict(cls, data):
322
+ """Create a ClimateBased sky from a dictionary.
323
+
324
+ Args:
325
+ data: A python dictionary in the following format
326
+
327
+ .. code-block:: python
328
+
329
+ {
330
+ 'type': 'ClimateBased',
331
+ 'altitude': 0.0,
332
+ 'azimuth': 0.0,
333
+ 'direct_normal_irradiance': 800,
334
+ 'diffuse_horizontal_irradiance': 120,
335
+ 'ground_reflectance': 0.2, # optional float for ground reflectance
336
+ 'is_colored': True # boolean for whether the sky is colored
337
+ }
338
+
339
+ """
340
+ assert 'type' in data, \
341
+ 'Input dict is missing type. Not a valid ClimateBased dictionary.'
342
+ assert data['type'] == 'ClimateBased', \
343
+ 'Input type must be ClimateBased not %s' % data['type']
344
+
345
+ gr = data['ground_reflectance'] if 'ground_reflectance' in data else 0.2
346
+ ic = data['is_colored'] if 'is_colored' in data else False
347
+ return cls(
348
+ data['altitude'], data['azimuth'],
349
+ data['direct_normal_irradiance'], data['diffuse_horizontal_irradiance'],
350
+ gr, ic
351
+ )
352
+
353
+ @classmethod
354
+ def from_string(cls, sky_string):
355
+ """Create a ClimateBased sky from a string.
356
+
357
+ Args:
358
+ sky_string: A text string representing a ClimateBased sky. This can
359
+ either be a minimal string representation of the sky (eg.
360
+ "climate-based -alt 71.6 -az 185.2 -dni 800 -dhi 120").
361
+ Or it can be a detailed specification of time and location (eg.
362
+ "climate-based 21 Jun 12:00 -lat 41.78 -lon -87.75 -dni 800 -dhi 120").
363
+ Any sky string can optionally have a "-g" property of a fractional
364
+ number, which sets the reflectance of the ground. If unspecified,
365
+ the ground will have a reflectance of 0.2. The detailed string can
366
+ optionally have a "-tz" property with an integer between -12 and +14
367
+ to denote the time zone. If unspecified, the time will be interpreted
368
+ as solar time at the given longitude. The detailed string can also
369
+ have a "-n" property between 0 and 360 to set the counterclockwise
370
+ difference between the North and the positive Y-axis in degrees.
371
+ All other properties specified in the string are required.
372
+
373
+ Usage:
374
+
375
+ .. code-block:: python
376
+
377
+ # minimal string representation of the sky
378
+ sky_string = "climate-based -alt 71.6 -az 185.2 -dni 800 -dhi 120"
379
+ sky = ClimateBased.from_string(sky_string)
380
+
381
+ # detailed location-specific representation of the sky
382
+ sky_string = "climate-based 21 Jun 12:00 -lat 41.78 -lon -87.75 -tz -6 " \
383
+ " -dni 800 -dhi 120 -n 0 -g 0.2"
384
+ sky = ClimateBased.from_string(sky_string)
385
+ """
386
+ # check the input and parse the datetime if it exists
387
+ lower_str = sky_string.lower()
388
+ assert lower_str.startswith('climate-based'), 'Expected string representation ' \
389
+ 'of ClimateBased sky "{}" to start with "climate-based".'.format(sky_string)
390
+ split_str = shlex.split(lower_str)
391
+ try:
392
+ dtime = DateTime.from_date_time_string(' '.join(split_str[1:4]))
393
+ except (ValueError, IndexError): # simpler sky representation
394
+ dtime = None
395
+
396
+ # make a parser for all of the other sky properties
397
+ pars = argparse.ArgumentParser()
398
+ pars.add_argument('-dni', action='store', dest='dni', type=float, default=0)
399
+ pars.add_argument('-dhi', action='store', dest='dhi', type=float, default=0)
400
+ pars.add_argument('-g', action='store', dest='g', type=float, default=0.2)
401
+ pars.add_argument('-c', action='store_true', dest='c', default=False)
402
+
403
+ # create the sky object
404
+ if dtime is None:
405
+ pars.add_argument('-alt', action='store', dest='alt', type=float, default=90)
406
+ pars.add_argument('-az', action='store', dest='az', type=float, default=0)
407
+ props = pars.parse_args(split_str[1:])
408
+ return cls(props.alt, props.az, props.dni, props.dhi, props.g, props.c)
409
+ else:
410
+ pars.add_argument('-lat', action='store', dest='lat', type=float, default=0)
411
+ pars.add_argument('-lon', action='store', dest='lon', type=float, default=0)
412
+ pars.add_argument('-tz', action='store', dest='tz', type=int, default=0)
413
+ pars.add_argument('-n', action='store', dest='n', type=float, default=0)
414
+ props = pars.parse_args(split_str[4:])
415
+ return cls.from_lat_long(
416
+ props.lat, props.lon, props.tz, dtime.month, dtime.day,
417
+ dtime.float_hour, props.dni, props.dhi, props.n, props.g, props.c)
418
+
419
+ # TODO: add support for additional parameters
420
+ # TODO: add gendaylit to radiance-command and use it for validating inputs
421
+ def to_radiance(self, output_type=0):
422
+ """Return Radiance description of the sky.
423
+
424
+ Args:
425
+ output_type: An integer between 0 to 2 for output type.
426
+ * 0 = output in W/m2/sr visible (default)
427
+ * 1 = output in W/m2/sr solar
428
+ * 2 = output in lm/m2/sr luminance
429
+ """
430
+ full_color = ' -C' if self.is_colored else ''
431
+ output = typing.int_in_range(output_type, 0, 2, 'Sky output type')
432
+ command = '!gendaylit -ang %.6f %.6f -O %d -W %d %d -g %.3f%s' % (
433
+ self.altitude, self.azimuth - 180.0, output, self.direct_normal_irradiance,
434
+ self._diffuse_horizontal_irradiance, self.ground_reflectance, full_color
435
+ )
436
+
437
+ return '%s\n\n%s\n\n%s\n' % (
438
+ command, self.sky_hemisphere, self.ground_hemisphere
439
+ )
440
+
441
+ def to_dict(self):
442
+ """Translate sky to a dictionary."""
443
+ base = {
444
+ 'type': 'ClimateBased',
445
+ 'altitude': self.altitude,
446
+ 'azimuth': self.azimuth,
447
+ 'direct_normal_irradiance': self.direct_normal_irradiance,
448
+ 'diffuse_horizontal_irradiance': self.diffuse_horizontal_irradiance,
449
+ 'ground_reflectance': self.ground_reflectance,
450
+ 'ground_hemisphere': self.ground_hemisphere.to_dict(),
451
+ 'sky_hemisphere': self.sky_hemisphere.to_dict()
452
+ }
453
+ if self.is_colored:
454
+ base['is_colored'] = True
455
+ return base
456
+
457
+ def to_file(self, folder, name=None, mkdir=False):
458
+ """Write sky hemisphere to a sky_hemisphere.rad Radiance file.
459
+
460
+ Args:
461
+ folder: Target folder.
462
+ name: File name.
463
+ mkdir: A boolean to note if the directory should be created if doesn't
464
+ exist (default: False).
465
+
466
+ Returns:
467
+ Full path to the newly created file.
468
+ """
469
+ content = self.to_radiance()
470
+ name = typing.valid_string(name) if name \
471
+ else '%.3f_%.3f_%d_%d.sky' % (
472
+ self.altitude, self.azimuth,
473
+ self.direct_normal_irradiance, self.diffuse_horizontal_irradiance
474
+ )
475
+ return futil.write_to_file_by_name(folder, name, content, mkdir)
476
+
477
+ def __eq__(self, value):
478
+ if type(value) != type(self) \
479
+ or value.altitude != self.altitude \
480
+ or value.azimuth != self.azimuth \
481
+ or value.direct_normal_irradiance != self.direct_normal_irradiance \
482
+ or value.diffuse_horizontal_irradiance != \
483
+ self.diffuse_horizontal_irradiance \
484
+ or self.ground_reflectance != value.ground_reflectance \
485
+ or self.is_colored != value.is_colored \
486
+ or self.ground_hemisphere != value.ground_hemisphere \
487
+ or self.sky_hemisphere != value.sky_hemisphere:
488
+ return False
489
+ return True
490
+
491
+ def __ne__(self, value):
492
+ return not self.__eq__(value)
493
+
494
+ def __repr__(self):
495
+ """Sky representation."""
496
+ is_colored = ' -c' if self.is_colored else ''
497
+ return 'climate-based -alt {} -az {} -dni {} -dhi {} -g {}{}'.format(
498
+ self.altitude, self.azimuth,
499
+ self.direct_normal_irradiance, self.diffuse_horizontal_irradiance,
500
+ self.ground_reflectance, is_colored
501
+ )
@@ -0,0 +1,160 @@
1
+ """Radiance sky hemisphere."""
2
+ import honeybee.typing as typing
3
+ import ladybug.futil as futil
4
+
5
+
6
+ class Hemisphere(object):
7
+ """Radiance sky hemisphere.
8
+
9
+ Sky hemisphere relies on skyfunc and must be used with one of the
10
+ Radiance sky commands.
11
+
12
+ .. code-block:: shell
13
+
14
+ skyfunc glow sky_glow
15
+ 0
16
+ 0
17
+ 4 1 1 1 0
18
+ sky_glow source sky
19
+ 0
20
+ 0
21
+ 4 0 0 1 180
22
+
23
+ Note:
24
+ For more information see Chapter `6.3.2 Example: CIE Overcast Sky` in
25
+ Rendering with Radiance. The chapter is also accessible online at the
26
+ link below.
27
+ https://www.radiance-online.org/community/workshops/2003-berkeley/presentations/Mardaljevic/rwr_ch6.pdf
28
+
29
+ Properties:
30
+ * r_emittance
31
+ * g_emittance
32
+ * b_emittance
33
+ * modifier
34
+
35
+ """
36
+ def __init__(self, modifier='skyfunc'):
37
+ """Create sky hemisphere.
38
+
39
+ Args:
40
+ modifier: Optional input to change the modifier from skyfunc.
41
+
42
+ """
43
+ self.modifier = modifier
44
+ self._r_emittance = 1.0
45
+ self._g_emittance = 1.0
46
+ self._b_emittance = 1.0
47
+
48
+ @property
49
+ def r_emittance(self):
50
+ """Sky hemisphere emittance values for red channel (Default is 1.0)."""
51
+ return self._r_emittance
52
+
53
+ @r_emittance.setter
54
+ def r_emittance(self, value):
55
+ self._r_emittance = typing.float_in_range(value, 0, 1, 'r_emittance')
56
+
57
+ @property
58
+ def g_emittance(self):
59
+ """Sky hemisphere emittance values for green channel (Default is 1.0)."""
60
+ return self._g_emittance
61
+
62
+ @g_emittance.setter
63
+ def g_emittance(self, value):
64
+ self._g_emittance = typing.float_in_range(value, 0, 1, 'g_emittance')
65
+
66
+ @property
67
+ def b_emittance(self):
68
+ """Sky hemisphere emittance values for blue channel (Default is 1.0)."""
69
+ return self._b_emittance
70
+
71
+ @b_emittance.setter
72
+ def b_emittance(self, value):
73
+ self._b_emittance = typing.float_in_range(value, 0, 1, 'b_emittance')
74
+
75
+ @property
76
+ def modifier(self):
77
+ "Sky hemisphere modifier."
78
+ return self._modifier
79
+
80
+ @modifier.setter
81
+ def modifier(self, value):
82
+ "Sky hemisphere modifier."
83
+ self._modifier = str(value)
84
+
85
+ @classmethod
86
+ def from_dict(cls, input_dict):
87
+ """Create sky_hemisphere from_dict.
88
+
89
+ Args:
90
+ input_dict: A python dictionary in the following format
91
+
92
+ .. code-block:: python
93
+
94
+ {
95
+ 'type': 'SkyHemisphere',
96
+ 'r_emittance': r_emittance,
97
+ 'g_emittance': g_emittance,
98
+ 'b_emittance': b_emittance,
99
+ 'modifier': modifier
100
+ }
101
+ """
102
+ assert 'type' in input_dict, \
103
+ 'Input dict is missing type. Not a valid sky_hemisphere dictionary.'
104
+ assert input_dict['type'] == 'SkyHemisphere', \
105
+ 'Input type must be SkyHemisphere not %s' % input_dict['type']
106
+ sky_hemisphere = cls()
107
+ sky_hemisphere.r_emittance = input_dict['r_emittance']
108
+ sky_hemisphere.g_emittance = input_dict['g_emittance']
109
+ sky_hemisphere.b_emittance = input_dict['b_emittance']
110
+ sky_hemisphere.modifier = input_dict['modifier']
111
+ return sky_hemisphere
112
+
113
+ def to_file(self, folder='.', name=None, mkdir=False):
114
+ """Write sky hemisphere to a sky_hemisphere.rad Radiance file.
115
+
116
+ Args:
117
+ folder: Target folder.
118
+ name: File name.
119
+ mkdir: A boolean to note if the directory should be created if doesn't
120
+ exist (default: False).
121
+
122
+ Returns:
123
+ Full path to the newly created file.
124
+ """
125
+ content = self.to_radiance() + '\n'
126
+ name = typing.valid_string(name) if name else 'sky_hemisphere.rad'
127
+ return futil.write_to_file_by_name(folder, name, content, mkdir)
128
+
129
+ def to_radiance(self):
130
+ """Get sky hemisphere as a Radiance input string."""
131
+ sky_hemisphere = '%s glow sky_glow\n0\n0\n4 %.3f %.3f %.3f 0\n' \
132
+ 'sky_glow source sky\n0\n0\n4 0 0 1 180' % (
133
+ self._modifier, self.r_emittance, self.g_emittance, self.b_emittance
134
+ )
135
+
136
+ return sky_hemisphere
137
+
138
+ def to_dict(self):
139
+ """Translate sky hemisphere to a dictionary."""
140
+ return {
141
+ 'type': 'SkyHemisphere',
142
+ 'r_emittance': self.r_emittance,
143
+ 'g_emittance': self.g_emittance,
144
+ 'b_emittance': self.b_emittance,
145
+ 'modifier': self.modifier
146
+ }
147
+
148
+ def __eq__(self, value):
149
+ if type(value) != type(self):
150
+ return False
151
+ if (value.modifier, value.r_emittance, value.g_emittance, value.b_emittance) != \
152
+ (self.modifier, self.r_emittance, self.g_emittance, self.b_emittance):
153
+ return False
154
+ return True
155
+
156
+ def __ne__(self, value):
157
+ return not self.__eq__(value)
158
+
159
+ def __repr__(self):
160
+ return self.to_radiance()