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.
- honeybee_radiance/__init__.py +11 -0
- honeybee_radiance/__main__.py +4 -0
- honeybee_radiance/_extend_honeybee.py +93 -0
- honeybee_radiance/cli/__init__.py +88 -0
- honeybee_radiance/cli/dc.py +400 -0
- honeybee_radiance/cli/edit.py +529 -0
- honeybee_radiance/cli/glare.py +118 -0
- honeybee_radiance/cli/grid.py +859 -0
- honeybee_radiance/cli/lib.py +458 -0
- honeybee_radiance/cli/modifier.py +133 -0
- honeybee_radiance/cli/mtx.py +226 -0
- honeybee_radiance/cli/multiphase.py +1034 -0
- honeybee_radiance/cli/octree.py +640 -0
- honeybee_radiance/cli/postprocess.py +1186 -0
- honeybee_radiance/cli/raytrace.py +219 -0
- honeybee_radiance/cli/rpict.py +125 -0
- honeybee_radiance/cli/schedule.py +56 -0
- honeybee_radiance/cli/setconfig.py +63 -0
- honeybee_radiance/cli/sky.py +545 -0
- honeybee_radiance/cli/study.py +66 -0
- honeybee_radiance/cli/sunpath.py +331 -0
- honeybee_radiance/cli/threephase.py +255 -0
- honeybee_radiance/cli/translate.py +400 -0
- honeybee_radiance/cli/util.py +121 -0
- honeybee_radiance/cli/view.py +261 -0
- honeybee_radiance/cli/viewfactor.py +347 -0
- honeybee_radiance/config.json +6 -0
- honeybee_radiance/config.py +427 -0
- honeybee_radiance/dictutil.py +50 -0
- honeybee_radiance/dynamic/__init__.py +5 -0
- honeybee_radiance/dynamic/group.py +479 -0
- honeybee_radiance/dynamic/multiphase.py +557 -0
- honeybee_radiance/dynamic/state.py +718 -0
- honeybee_radiance/dynamic/stategeo.py +352 -0
- honeybee_radiance/geometry/__init__.py +13 -0
- honeybee_radiance/geometry/bubble.py +42 -0
- honeybee_radiance/geometry/cone.py +215 -0
- honeybee_radiance/geometry/cup.py +54 -0
- honeybee_radiance/geometry/cylinder.py +197 -0
- honeybee_radiance/geometry/geometrybase.py +37 -0
- honeybee_radiance/geometry/instance.py +40 -0
- honeybee_radiance/geometry/mesh.py +38 -0
- honeybee_radiance/geometry/polygon.py +174 -0
- honeybee_radiance/geometry/ring.py +214 -0
- honeybee_radiance/geometry/source.py +182 -0
- honeybee_radiance/geometry/sphere.py +178 -0
- honeybee_radiance/geometry/tube.py +46 -0
- honeybee_radiance/lib/__init__.py +1 -0
- honeybee_radiance/lib/_loadmodifiers.py +72 -0
- honeybee_radiance/lib/_loadmodifiersets.py +69 -0
- honeybee_radiance/lib/modifiers.py +58 -0
- honeybee_radiance/lib/modifiersets.py +63 -0
- honeybee_radiance/lightpath.py +204 -0
- honeybee_radiance/lightsource/__init__.py +1 -0
- honeybee_radiance/lightsource/_gendaylit.py +479 -0
- honeybee_radiance/lightsource/dictutil.py +49 -0
- honeybee_radiance/lightsource/ground.py +160 -0
- honeybee_radiance/lightsource/sky/__init__.py +7 -0
- honeybee_radiance/lightsource/sky/_skybase.py +177 -0
- honeybee_radiance/lightsource/sky/certainirradiance.py +232 -0
- honeybee_radiance/lightsource/sky/cie.py +378 -0
- honeybee_radiance/lightsource/sky/climatebased.py +501 -0
- honeybee_radiance/lightsource/sky/hemisphere.py +160 -0
- honeybee_radiance/lightsource/sky/skydome.py +113 -0
- honeybee_radiance/lightsource/sky/skymatrix.py +163 -0
- honeybee_radiance/lightsource/sky/strutil.py +34 -0
- honeybee_radiance/lightsource/sky/sunmatrix.py +212 -0
- honeybee_radiance/lightsource/sunpath.py +247 -0
- honeybee_radiance/modifier/__init__.py +3 -0
- honeybee_radiance/modifier/material/__init__.py +30 -0
- honeybee_radiance/modifier/material/absdf.py +477 -0
- honeybee_radiance/modifier/material/antimatter.py +54 -0
- honeybee_radiance/modifier/material/ashik2.py +51 -0
- honeybee_radiance/modifier/material/brtdfunc.py +81 -0
- honeybee_radiance/modifier/material/bsdf.py +292 -0
- honeybee_radiance/modifier/material/dielectric.py +53 -0
- honeybee_radiance/modifier/material/glass.py +431 -0
- honeybee_radiance/modifier/material/glow.py +246 -0
- honeybee_radiance/modifier/material/illum.py +51 -0
- honeybee_radiance/modifier/material/interface.py +49 -0
- honeybee_radiance/modifier/material/light.py +206 -0
- honeybee_radiance/modifier/material/materialbase.py +36 -0
- honeybee_radiance/modifier/material/metal.py +167 -0
- honeybee_radiance/modifier/material/metal2.py +41 -0
- honeybee_radiance/modifier/material/metdata.py +41 -0
- honeybee_radiance/modifier/material/metfunc.py +41 -0
- honeybee_radiance/modifier/material/mirror.py +340 -0
- honeybee_radiance/modifier/material/mist.py +86 -0
- honeybee_radiance/modifier/material/plasdata.py +58 -0
- honeybee_radiance/modifier/material/plasfunc.py +59 -0
- honeybee_radiance/modifier/material/plastic.py +354 -0
- honeybee_radiance/modifier/material/plastic2.py +58 -0
- honeybee_radiance/modifier/material/prism1.py +57 -0
- honeybee_radiance/modifier/material/prism2.py +48 -0
- honeybee_radiance/modifier/material/spotlight.py +50 -0
- honeybee_radiance/modifier/material/trans.py +518 -0
- honeybee_radiance/modifier/material/trans2.py +49 -0
- honeybee_radiance/modifier/material/transdata.py +50 -0
- honeybee_radiance/modifier/material/transfunc.py +53 -0
- honeybee_radiance/modifier/mixture/__init__.py +6 -0
- honeybee_radiance/modifier/mixture/mixdata.py +49 -0
- honeybee_radiance/modifier/mixture/mixfunc.py +54 -0
- honeybee_radiance/modifier/mixture/mixpict.py +52 -0
- honeybee_radiance/modifier/mixture/mixtext.py +66 -0
- honeybee_radiance/modifier/mixture/mixturebase.py +28 -0
- honeybee_radiance/modifier/modifierbase.py +40 -0
- honeybee_radiance/modifier/pattern/__init__.py +9 -0
- honeybee_radiance/modifier/pattern/brightdata.py +49 -0
- honeybee_radiance/modifier/pattern/brightfunc.py +47 -0
- honeybee_radiance/modifier/pattern/brighttext.py +81 -0
- honeybee_radiance/modifier/pattern/colordata.py +56 -0
- honeybee_radiance/modifier/pattern/colorfunc.py +47 -0
- honeybee_radiance/modifier/pattern/colorpict.py +54 -0
- honeybee_radiance/modifier/pattern/colortext.py +73 -0
- honeybee_radiance/modifier/pattern/patternbase.py +34 -0
- honeybee_radiance/modifier/texture/__init__.py +4 -0
- honeybee_radiance/modifier/texture/texdata.py +29 -0
- honeybee_radiance/modifier/texture/texfunc.py +26 -0
- honeybee_radiance/modifier/texture/texturebase.py +27 -0
- honeybee_radiance/modifierset.py +1091 -0
- honeybee_radiance/mutil.py +60 -0
- honeybee_radiance/postprocess/__init__.py +1 -0
- honeybee_radiance/postprocess/annual.py +108 -0
- honeybee_radiance/postprocess/annualdaylight.py +425 -0
- honeybee_radiance/postprocess/annualglare.py +201 -0
- honeybee_radiance/postprocess/annualirradiance.py +187 -0
- honeybee_radiance/postprocess/electriclight.py +119 -0
- honeybee_radiance/postprocess/en17037.py +261 -0
- honeybee_radiance/postprocess/leed.py +304 -0
- honeybee_radiance/postprocess/solartracking.py +90 -0
- honeybee_radiance/primitive.py +554 -0
- honeybee_radiance/properties/__init__.py +1 -0
- honeybee_radiance/properties/_base.py +390 -0
- honeybee_radiance/properties/aperture.py +197 -0
- honeybee_radiance/properties/door.py +198 -0
- honeybee_radiance/properties/face.py +123 -0
- honeybee_radiance/properties/model.py +1291 -0
- honeybee_radiance/properties/room.py +490 -0
- honeybee_radiance/properties/shade.py +186 -0
- honeybee_radiance/properties/shademesh.py +116 -0
- honeybee_radiance/putil.py +44 -0
- honeybee_radiance/reader.py +214 -0
- honeybee_radiance/sensor.py +166 -0
- honeybee_radiance/sensorgrid.py +1008 -0
- honeybee_radiance/view.py +1101 -0
- honeybee_radiance/writer.py +951 -0
- honeybee_radiance-1.66.190.dist-info/METADATA +89 -0
- honeybee_radiance-1.66.190.dist-info/RECORD +152 -0
- honeybee_radiance-1.66.190.dist-info/WHEEL +5 -0
- honeybee_radiance-1.66.190.dist-info/entry_points.txt +2 -0
- honeybee_radiance-1.66.190.dist-info/licenses/LICENSE +661 -0
- 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()
|