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,545 @@
1
+ """honeybee radiance sky commands."""
2
+ import click
3
+ import sys
4
+ import os
5
+ import logging
6
+ import json
7
+
8
+ from ladybug.dt import DateTime
9
+ from ladybug.futil import write_to_file_by_name
10
+ from ladybug.wea import Wea
11
+ from honeybee_radiance_command.gendaymtx import Gendaymtx, GendaymtxOptions
12
+ from honeybee_radiance_command._command_util import run_command
13
+
14
+ import honeybee_radiance.lightsource.sky as hbsky
15
+ from honeybee_radiance.config import folders
16
+
17
+
18
+ _logger = logging.getLogger(__name__)
19
+
20
+
21
+ @click.group(help='Commands to generate Radiance skies.')
22
+ def sky():
23
+ pass
24
+
25
+
26
+ @sky.command('cie')
27
+ @click.argument('day', type=int, default=21)
28
+ @click.argument('month', type=str, default='Jun')
29
+ @click.argument('time', type=str, default='12:00')
30
+ @click.option('--latitude', '-lat', type=float, default=0, show_default=True,
31
+ help='Location latitude between -90 (south) and 90 (north).')
32
+ @click.option('--longitude', '-lon', type=float, default=0, show_default=True,
33
+ help='Location longitude between -180 (west) and 180 (east).')
34
+ @click.option('--time-zone', '-tz', type=int, default=None,
35
+ help='Time zone between -12 hours (west) and +14 hours (east). If '
36
+ 'unspecified, the time will be interpreted as solar time at the '
37
+ 'given longitude.')
38
+ @click.option('--sky-type', '-type', type=int, default=0, show_default=True, help='An '
39
+ 'integer from 0-5 to indicate CIE Sky Type. 0 = Sunny with sun, 1 = Sunny'
40
+ ' without sun, 2 = Intermediate with sun, 3 = Intermediate without sun, '
41
+ '4 = Cloudy sky, 5 = Uniform cloudy sky.')
42
+ @click.option('--north', '-n', type=float, default=0, show_default=True, help='A '
43
+ 'number between -360 and 360 for the counterclockwise difference between '
44
+ 'the North and the positive Y-axis in degrees. 90 is West; 270 is East')
45
+ @click.option('--ground', '-g', type=float, default=0.2, show_default=True,
46
+ help='Fractional value for ground reflectance.')
47
+ @click.option('--altitude', '-alt', type=float, default=None,
48
+ help='Solar altitude measured in degrees above the horizon.')
49
+ @click.option('--azimuth', '-az', type=float, default=None,
50
+ help='Solar azimuth measured in degrees east of North. East is 90, South '
51
+ 'is 180 and West is 270. Note that this is different from Radiance '
52
+ 'convention where the azimuth degrees are measured in west of South.')
53
+ @click.option('--folder', help='Output folder.', default='.', show_default=True)
54
+ @click.option('--name', help='Sky file name.', default=None, show_default=True)
55
+ def sky_cie(day, month, time, latitude, longitude, time_zone, sky_type,
56
+ north, ground, altitude, azimuth, folder, name):
57
+ """Get a CIE sky file from parameters.
58
+
59
+ These can be a minimal representation of the sky through altitude and azimuth (eg.
60
+ "cie -alt 71.6 -az 185.2 -type 0"). Or it can be a detailed specification of
61
+ time and location (eg. "cie 21 Jun 12:00 -lat 41.78 -lon -87.75 -type 0").
62
+ Both the altitude and azimuth must be specified for the minimal representation
63
+ to be used. Otherwise, this command defaults to the detailed specification
64
+ of time and location.
65
+
66
+ \b
67
+ Args:
68
+ day: An intger for the day of the month (between 1 and 28-31).
69
+ month: Text for the 3-letter abbreviation of the month of the year (eg. "Mar").
70
+ time: Text for the time of day (from 0:00 to 23:59).
71
+ """
72
+ try:
73
+ if altitude is not None and azimuth is not None:
74
+ sky_obj = hbsky.CIE(altitude, azimuth, sky_type, ground)
75
+ else:
76
+ dtime = DateTime.from_date_time_string('{} {} {}'.format(day, month, time))
77
+ sky_obj = hbsky.CIE.from_lat_long(
78
+ latitude, longitude, time_zone, dtime.month, dtime.day, dtime.float_hour,
79
+ sky_type, north, ground)
80
+ sky_obj.to_file(folder, name, True)
81
+ except Exception:
82
+ _logger.exception('Failed to generate sky.')
83
+ sys.exit(1)
84
+
85
+
86
+ @sky.command('climate-based')
87
+ @click.argument('day', type=int, default=21)
88
+ @click.argument('month', type=str, default='Jun')
89
+ @click.argument('time', type=str, default='12:00')
90
+ @click.option('--latitude', '-lat', type=float, default=0, show_default=True,
91
+ help='Location latitude between -90 (south) and 90 (north).')
92
+ @click.option('--longitude', '-lon', type=float, default=0, show_default=True,
93
+ help='Location longitude between -180 (west) and 180 (east).')
94
+ @click.option('--time-zone', '-tz', type=int, default=None,
95
+ help='Time zone between -12 hours (west) and +14 hours (east). If '
96
+ 'unspecified, the time will be interpreted as solar time at the '
97
+ 'given longitude.')
98
+ @click.option('--direct-normal-irradiance', '-dni', type=float, default=0,
99
+ show_default=True, help='Direct normal irradiance (W/m2).')
100
+ @click.option('--diffuse_horizontal_irradiance', '-dhi', type=float, default=0,
101
+ show_default=True, help='Diffuse horizontal irradiance (W/m2).')
102
+ @click.option('--north', '-n', type=float, default=0, show_default=True, help='A '
103
+ 'number between -360 and 360 for the counterclockwise difference between '
104
+ 'the North and the positive Y-axis in degrees. 90 is West; 270 is East')
105
+ @click.option('--ground', '-g', type=float, default=0.2, show_default=True,
106
+ help='Fractional value for ground reflectance.')
107
+ @click.option('--altitude', '-alt', type=float, default=None,
108
+ help='Solar altitude measured in degrees above the horizon.')
109
+ @click.option('--azimuth', '-az', type=float, default=None,
110
+ help='Solar azimuth measured in degrees east of North. East is 90, South '
111
+ 'is 180 and West is 270. Note that this is different from Radiance '
112
+ 'convention where the azimuth degrees are measured in west of South.')
113
+ @click.option('--folder', help='Output folder.', default='.', show_default=True)
114
+ @click.option('--name', help='Sky file name.', default=None, show_default=True)
115
+ def sky_climate_based(
116
+ day, month, time, latitude, longitude, time_zone, direct_normal_irradiance,
117
+ diffuse_horizontal_irradiance, north, ground, altitude, azimuth, folder, name):
118
+ """Get a ClimateBased sky file from parameters.
119
+
120
+ These can be a minimal representation of the sky through altitude and azimuth (eg.
121
+ "climate-based -alt 71.6 -az 185.2 -dni 800 -dhi 120"). Or it can be a detailed
122
+ specification of time and location (eg. "climate-based 21 Jun 12:00 -lat 41.78
123
+ -lon -87.75 -dni 800 -dhi 120"). Both the altitude and azimuth must be specified
124
+ for the minimal representation to be used. Otherwise, this command defaults
125
+ to the detailed specification of time and location.
126
+
127
+ \b
128
+ Args:
129
+ day: An intger for the day of the month (between 1 and 28-31).
130
+ month: Text for the 3-letter abbreviation of the month of the year (eg. "Mar").
131
+ time: Text for the time of day (from 0:00 to 23:59).
132
+ """
133
+ try:
134
+ if altitude is not None and azimuth is not None:
135
+ sky_obj = hbsky.ClimateBased(
136
+ altitude, azimuth, direct_normal_irradiance,
137
+ diffuse_horizontal_irradiance, ground)
138
+ else:
139
+ dtime = DateTime.from_date_time_string('{} {} {}'.format(day, month, time))
140
+ sky_obj = hbsky.ClimateBased.from_lat_long(
141
+ latitude, longitude, time_zone, dtime.month, dtime.day, dtime.float_hour,
142
+ direct_normal_irradiance, diffuse_horizontal_irradiance,
143
+ north, ground)
144
+ sky_obj.to_file(folder, name, True)
145
+ except Exception:
146
+ _logger.exception('Failed to generate sky.')
147
+ sys.exit(1)
148
+
149
+
150
+ @sky.command('irradiance')
151
+ @click.argument('irrad', default=558.659, type=float)
152
+ @click.option('--ground', '-g', type=float, default=0.2, show_default=True,
153
+ help='Fractional value for ground reflectance.')
154
+ @click.option('--cloudy/--uniform', '-u', default=True,
155
+ help='Flag to note whether the sky is uniform instead of cloudy.')
156
+ @click.option('--folder', help='Output folder.', default='.', show_default=True)
157
+ @click.option('--name', help='Sky file name.', default=None, show_default=True)
158
+ def sky_with_certain_irrad(irrad, ground, cloudy, folder, name):
159
+ """Generate an overcast / cloudy sky with certain irradiance value.
160
+
161
+ \b
162
+ Args:
163
+ irrad: Desired irradiance value in W/m2. (Default: 558.659).
164
+ """
165
+ try:
166
+ uniform = not cloudy
167
+ c_sky = hbsky.CertainIrradiance(irrad, ground, uniform)
168
+ c_sky.to_file(folder, name, True)
169
+ except Exception:
170
+ _logger.exception('Failed to generate sky.')
171
+ sys.exit(1)
172
+
173
+
174
+ @sky.command('illuminance')
175
+ @click.argument('illum', default=100000, type=float)
176
+ @click.option('--ground', '-g', type=float, default=0.2, show_default=True,
177
+ help='Fractional value for ground reflectance.')
178
+ @click.option('--cloudy/--uniform', '-u', default=True,
179
+ help='Flag to note whether the sky is uniform instead of cloudy.')
180
+ @click.option('--folder', help='Output folder.', default='.', show_default=True)
181
+ @click.option('--name', help='Sky file name.', default=None, show_default=True)
182
+ def sky_with_certain_illum(illum, ground, cloudy, folder, name):
183
+ """Generate an overcast / cloudy sky with certain illuminance value.
184
+
185
+ \b
186
+ Args:
187
+ illum: Desired illuminance value in lux. (Default: 100000).
188
+ """
189
+ try:
190
+ uniform = not cloudy
191
+ c_sky = hbsky.CertainIrradiance.from_illuminance(illum, ground, uniform)
192
+ c_sky.to_file(folder, name, True)
193
+ except Exception:
194
+ _logger.exception('Failed to generate sky.')
195
+ sys.exit(1)
196
+
197
+
198
+ @sky.command('skydome')
199
+ @click.option(
200
+ '--sky-density', type=int, help='Sky patch subdivision density. This values is '
201
+ 'similar to -m option in gendaymtx command. Default is 1 which means 145 sky '
202
+ 'patches and 1 patch for the ground. One can add to the resolution typically by '
203
+ 'factors of two (2, 4, 8, ...) which yields a higher resolution sky using the '
204
+ 'Reinhart patch subdivision', default=1, show_default=True)
205
+ @click.option('--folder', help='Output folder.', default='.', show_default=True)
206
+ @click.option('--name', help='Sky file name.', default=None, show_default=True)
207
+ def sky_dome(sky_density, folder, name):
208
+ """Virtual skydome for daylight coefficient studies with constant radiance.
209
+
210
+ Use this sky to calculate daylight matrix.
211
+ """
212
+ try:
213
+ c_sky = hbsky.SkyDome(sky_density=sky_density)
214
+ c_sky.to_file(folder, name, True)
215
+ except Exception:
216
+ _logger.exception('Failed to generate sky.')
217
+ sys.exit(1)
218
+
219
+
220
+ @sky.command('uniform-sky')
221
+ @click.option('--ground-emittance', '-g', type=float, help='Ground emittance value.',
222
+ default=0.2, show_default=True)
223
+ @click.option('--folder', help='Output folder.', default='.', show_default=True)
224
+ @click.option('--name', help='Sky file name.', default='uniform_sky', show_default=True)
225
+ def uniform_sky(ground_emittance, folder, name):
226
+ """Virtual skydome with uniform characteristics.
227
+
228
+ This sky is usually used to create an octree that is sent to rcontrib command.
229
+ """
230
+ try:
231
+ c_sky = hbsky.UniformSky(ground_emittance=ground_emittance)
232
+ c_sky.to_file(folder, name, True)
233
+ except Exception:
234
+ _logger.exception('Failed to generate sky.')
235
+ sys.exit(1)
236
+
237
+
238
+ @sky.command('mtx')
239
+ @click.argument('wea', type=click.Path(
240
+ exists=True, file_okay=True, dir_okay=False, resolve_path=True))
241
+ @click.option(
242
+ '--north', default=0, type=float, show_default=True,
243
+ help='Angle to north (0-360). 90 is west and 270 is east')
244
+ @click.option(
245
+ '--sky-type', type=click.Choice(['sun-only', 'no-sun', 'total']),
246
+ default='total'
247
+ )
248
+ @click.option(
249
+ '--sky-density', type=int, default=1, help='The density of generated sky. This '
250
+ 'input corresponds to gendaymtx -m option. -m 1 generates 146 patch starting with '
251
+ '0 for the ground and continuing to 145 for the zenith. Increasing the -m parameter '
252
+ 'yields a higher resolution sky using the Reinhart patch subdivision. For example, '
253
+ 'setting -m 4 yields a sky with 2305 patches plus one patch for the ground.'
254
+ )
255
+ @click.option(
256
+ '--output-format', type=click.Choice(['float', 'double', 'ASCII']),
257
+ default='ASCII'
258
+ )
259
+ @click.option(
260
+ '--hourly/--cumulative', is_flag=True, default=True, help='Flag to generate a '
261
+ 'cumulative or hourly sky.'
262
+ )
263
+ @click.option(
264
+ '--visible/--solar', is_flag=True, default=True, help='A flag to indicate the '
265
+ 'output type. Visible is equal to -O0 and solar is -O1 in gendaymtx options. '
266
+ 'Default: visible.'
267
+ )
268
+ @click.option(
269
+ '--all-hours/--sun-up-hours', is_flag=True, default=True, help='A flag to indicate '
270
+ 'if only sun up hours should be included in the sky. By default all the hours from '
271
+ 'the input wea file will be included.'
272
+ )
273
+ @click.option('--folder', type=click.Path(
274
+ exists=False, file_okay=False, dir_okay=True, resolve_path=True), default='.',
275
+ help='Output folder.')
276
+ @click.option('--name', default='sky', help='File name.')
277
+ @click.option(
278
+ '--log-file', help='Optional log file to output the name of the newly'
279
+ ' created modifier files. By default the list will be printed out to stdout',
280
+ type=click.File('w'), default='-')
281
+ @click.option(
282
+ '--dry-run', is_flag=True, default=False, show_default=True,
283
+ help='A flag to show the command without running it.'
284
+ )
285
+ def sunpath_from_wea_rad(
286
+ wea, north, sky_type, sky_density, output_format, hourly, visible, all_hours,
287
+ folder, name, log_file, dry_run
288
+ ):
289
+ """Generate a climate-based sky matrix from a Wea file using radiance's gendaymtx.
290
+
291
+ \b
292
+ Args:
293
+ wea: Path to a wea file. This can also be an epw file.
294
+ """
295
+ try:
296
+ if not os.path.exists(folder):
297
+ os.makedirs(folder)
298
+ with open(wea) as inf:
299
+ first_word = inf.read(5)
300
+ is_wea = True if first_word == 'place' else False
301
+ if not is_wea:
302
+ _wea_file = os.path.join(os.path.dirname(wea), 'epw_to_wea.wea')
303
+ wea = Wea.from_epw_file(wea).write(_wea_file)
304
+ output = os.path.join(folder, '%s.mtx' % name)
305
+ opt = GendaymtxOptions()
306
+ opt.r = north
307
+ opt.O = '0' if visible else '1'
308
+ if sky_type == 'total':
309
+ pass
310
+ elif sky_type == 'sun-only':
311
+ opt.d = True
312
+ elif sky_type == 'no-sun':
313
+ opt.s = True
314
+
315
+ if output_format == 'ASCII':
316
+ pass
317
+ elif output_format == 'float':
318
+ opt.o = 'f'
319
+ elif output_format == 'double':
320
+ opt.o = 'd'
321
+
322
+ if not hourly:
323
+ opt.A = True
324
+
325
+ if not all_hours:
326
+ opt.u = True
327
+ if sky_density > 1:
328
+ opt.m = sky_density
329
+
330
+ cmd = Gendaymtx(wea=wea, options=opt, output=output)
331
+ if dry_run:
332
+ print(cmd.to_radiance())
333
+ sys.exit(0)
334
+
335
+ try:
336
+ run_command(cmd.to_radiance(), env=folders.env)
337
+ except RuntimeError as e: # likely a nighttime Wea; write blank .mtx file
338
+ with open(output, 'w') as wf:
339
+ wf.write('')
340
+ files = [{'path': os.path.relpath(output, folder), 'full_path': output}]
341
+ log_file.write(json.dumps(files))
342
+
343
+ except Exception:
344
+ _logger.exception('Failed to generate sunpath.')
345
+ sys.exit(1)
346
+ else:
347
+ sys.exit(0)
348
+
349
+
350
+ @sky.command('adjust-for-metric')
351
+ @click.argument('sky', type=click.Path(
352
+ exists=True, file_okay=True, dir_okay=False, resolve_path=True))
353
+ @click.option(
354
+ '--metric', '-m', default='illuminance', show_default=True,
355
+ help='Text for the type of metric to be output from the calculation. Choose from: '
356
+ 'illuminance, irradiance, luminance, radiance.'
357
+ )
358
+ @click.option('--folder', help='Output folder.', default='.', show_default=True)
359
+ @click.option('--name', help='Sky file name.', default=None, show_default=True)
360
+ def adjust_sky_for_metric(sky, metric, folder, name):
361
+ """Adjust a sky file to ensure it is suitable for a given metric.
362
+
363
+ Specifically, this ensures that skies being created with gendaylit have a -O
364
+ option that aligns with visible vs. solar energy.
365
+
366
+ \b
367
+ Args:
368
+ sky: Path to a .sky file to be adjusted based on the metric.
369
+ """
370
+ try:
371
+ with open(sky) as inf:
372
+ content = inf.read()
373
+ if content.startswith('!gendaylit'):
374
+ split_content = content.split('\n')
375
+ first_line = split_content[0].replace('-O 0', '-O 1') if metric in \
376
+ ('irradiance', 'radiance') else split_content[0].replace('-O 1', '-O 0')
377
+ split_content[0] = first_line
378
+ content = '\n'.join(split_content)
379
+ name = '{}.sky'.format(metric) if name is None else name
380
+ write_to_file_by_name(folder, name, content, True)
381
+ except Exception:
382
+ _logger.exception('Failed to adjust sky.')
383
+ sys.exit(1)
384
+
385
+
386
+ @sky.command('leed-illuminance')
387
+ @click.argument('wea', type=click.Path(
388
+ exists=True, file_okay=True, dir_okay=False, resolve_path=True))
389
+ @click.option(
390
+ '--north', '-n', type=float, default=0, show_default=True, help='A '
391
+ 'number between -360 and 360 for the counterclockwise difference between '
392
+ 'the North and the positive Y-axis in degrees. 90 is West; 270 is East')
393
+ @click.option('--folder', type=click.Path(
394
+ exists=False, file_okay=False, dir_okay=True, resolve_path=True), default='.',
395
+ help='Output folder for the two generated .sky files.')
396
+ @click.option(
397
+ '--name', help='Sky file base name. Each of the two output skies will have this '
398
+ 'base name concatenated with 9AM or 3PM', default='', show_default=True)
399
+ @click.option(
400
+ '--log-file', help='Optional log file to output the information about the two '
401
+ 'generated sky files. By default the list will be printed out to stdout',
402
+ type=click.File('w'), default='-')
403
+ def leed_illuminance(wea, north, folder, name, log_file):
404
+ """Generate two climate-based lear skies for LEED v4.1 Daylight Option 2.
405
+
406
+ This involves evaluating the input TMY Wea, finding the clearest day within
407
+ 15 days of September and March, and using that to generate skies at 9AM and 3PM.
408
+
409
+ \b
410
+ Args:
411
+ wea: Path to a Typical Meteorological Year (TMY) .wea file. The file must
412
+ be annual with a timestep of 1 for a non-leap year. This can also be
413
+ an .epw
414
+ """
415
+ try:
416
+ with open(wea) as inf:
417
+ first_word = inf.read(5)
418
+ is_wea = True if first_word == 'place' else False
419
+ if not is_wea:
420
+ _wea_file = os.path.join(os.path.dirname(wea), 'epw_to_wea.wea')
421
+ wea = Wea.from_epw_file(wea).write(_wea_file)
422
+ # get HOYs for the time around the equinoxes
423
+ mar_9, sep_9 = DateTime(3, 21, 9).hoy, DateTime(9, 21, 9).hoy
424
+ mar_3, sep_3 = DateTime(3, 21, 15).hoy, DateTime(9, 21, 15).hoy
425
+ hoys_mar9 = list(range(int(mar_9 - (15 * 24)), int(mar_9 + (15 * 24)), 24))
426
+ hoys_sep9 = list(range(int(sep_9 - (15 * 24)), int(sep_9 + (15 * 24)), 24))
427
+ hoys_mar3 = list(range(int(mar_3 - (15 * 24)), int(mar_3 + (15 * 24)), 24))
428
+ hoys_sep3 = list(range(int(sep_3 - (15 * 24)), int(sep_3 + (15 * 24)), 24))
429
+
430
+ # analyze the Wea file to get the sunniest days around the equinoxes
431
+ wea_obj = Wea.from_file(wea)
432
+ dni = wea_obj.direct_normal_irradiance
433
+ dhi = wea_obj.diffuse_horizontal_irradiance
434
+ irr_mar9 = [x for _, x in sorted(zip([dni[h] for h in hoys_mar9], hoys_mar9))]
435
+ irr_sep9 = [x for _, x in sorted(zip([dni[h] for h in hoys_sep9], hoys_sep9))]
436
+ irr_mar3 = [x for _, x in sorted(zip([dni[h] for h in hoys_mar3], hoys_mar3))]
437
+ irr_sep3 = [x for _, x in sorted(zip([dni[h] for h in hoys_sep3], hoys_sep3))]
438
+
439
+ # create the clear sky objects from the averaged irradiance
440
+ dni_9 = (dni[irr_mar9[-1]] + dni[irr_sep9[-1]]) / 2
441
+ dhi_9 = (dhi[irr_mar9[-1]] + dhi[irr_sep9[-1]]) / 2
442
+ dni_3 = (dni[irr_mar3[-1]] + dni[irr_sep3[-1]]) / 2
443
+ dhi_3 = (dhi[irr_mar3[-1]] + dhi[irr_sep3[-1]]) / 2
444
+ sky_obj_9 = hbsky.ClimateBased.from_location(
445
+ wea_obj.location, 3, 21, 9, dni_9, dhi_9, north)
446
+ sky_obj_3 = hbsky.ClimateBased.from_location(
447
+ wea_obj.location, 3, 21, 15, dni_3, dhi_3, north)
448
+
449
+ # write out the sky files and the log file
450
+ output_9 = sky_obj_9.to_file(folder, '{}9AM.sky'.format(name), True)
451
+ output_3 = sky_obj_3.to_file(folder, '{}3PM.sky'.format(name), True)
452
+ files = [
453
+ {
454
+ 'id': '{}9AM'.format(name),
455
+ 'path': os.path.relpath(output_9, folder),
456
+ 'full_path': output_9
457
+ },
458
+ {
459
+ 'id': '{}3PM'.format(name),
460
+ 'path': os.path.relpath(output_3, folder),
461
+ 'full_path': output_3
462
+ }
463
+ ]
464
+ log_file.write(json.dumps(files))
465
+ except Exception:
466
+ _logger.exception('Failed to create LEED skies.')
467
+ sys.exit(1)
468
+
469
+
470
+ @sky.command('abnt-nbr-15575')
471
+ @click.argument('wea', type=click.Path(
472
+ exists=True, file_okay=True, dir_okay=False, resolve_path=True))
473
+ @click.option(
474
+ '--north', '-n', type=float, default=0, show_default=True, help='A '
475
+ 'number between -360 and 360 for the counterclockwise difference between '
476
+ 'the North and the positive Y-axis in degrees. 90 is West; 270 is East.')
477
+ @click.option('--folder', type=click.Path(
478
+ exists=False, file_okay=False, dir_okay=True, resolve_path=True), default='.',
479
+ help='Output folder for the four generated .sky files.')
480
+ @click.option(
481
+ '--log-file', help='Optional log file to output the information about the '
482
+ 'four generated sky files. By default the list will be printed out to stdout.',
483
+ type=click.File('w'), default='-')
484
+ def abnt_nbr_15575(wea, north, folder, log_file):
485
+ """Generate four CIE skies for ABNT NBR 15575.
486
+
487
+ The four skies are:
488
+ - April 23rd at 9:30AM and 3:30PM.
489
+ - October 23rd at 9:30AM and 3:30PM.
490
+
491
+ \b
492
+ Args:
493
+ wea: Path to a Typical Meteorological Year (TMY) .wea file. This can
494
+ also be an .epw. The file is only used to extract the location.
495
+ """
496
+ try:
497
+ with open(wea, errors='ignore') as inf:
498
+ first_word = inf.read(5)
499
+ is_wea = True if first_word == 'place' else False
500
+ if not is_wea:
501
+ wea = Wea.from_epw_file(wea)
502
+ else:
503
+ wea = Wea.from_file(wea)
504
+
505
+ sky_type = 3
506
+ sky_obj_4_930am = hbsky.CIE.from_location(
507
+ wea.location, 4, 23, 9.5, sky_type=sky_type, north_angle=north)
508
+ sky_obj_4_330pm = hbsky.CIE.from_location(
509
+ wea.location, 4, 23, 15.5, sky_type=sky_type, north_angle=north)
510
+ sky_obj_10_930am = hbsky.CIE.from_location(
511
+ wea.location, 10, 23, 9.5, sky_type=sky_type, north_angle=north)
512
+ sky_obj_10_330pm = hbsky.CIE.from_location(
513
+ wea.location, 10, 23, 15.5, sky_type=sky_type, north_angle=north)
514
+
515
+ # write out the sky files and the log file
516
+ output_4_930am = sky_obj_4_930am.to_file(folder, '4_930AM.sky', True)
517
+ output_4_330pm = sky_obj_4_330pm.to_file(folder, '4_330PM.sky', True)
518
+ output_10_930am = sky_obj_10_930am.to_file(folder, '10_930AM.sky', True)
519
+ output_10_330pm = sky_obj_10_330pm.to_file(folder, '10_330PM.sky', True)
520
+ files = [
521
+ {
522
+ 'id': '4_930AM',
523
+ 'path': os.path.relpath(output_4_930am, folder),
524
+ 'full_path': output_4_930am
525
+ },
526
+ {
527
+ 'id': '4_330PM',
528
+ 'path': os.path.relpath(output_4_330pm, folder),
529
+ 'full_path': output_4_330pm
530
+ },
531
+ {
532
+ 'id': '10_930AM',
533
+ 'path': os.path.relpath(output_10_930am, folder),
534
+ 'full_path': output_10_930am
535
+ },
536
+ {
537
+ 'id': '10_330PM',
538
+ 'path': os.path.relpath(output_10_330pm, folder),
539
+ 'full_path': output_10_330pm
540
+ }
541
+ ]
542
+ log_file.write(json.dumps(files))
543
+ except Exception:
544
+ _logger.exception('Failed to create ABNT NBR 15575 skies.')
545
+ sys.exit(1)
@@ -0,0 +1,66 @@
1
+ """honeybee radiance study command."""
2
+ import click
3
+ import sys
4
+ import logging
5
+ import os
6
+ import shutil
7
+ import json
8
+
9
+ from ladybug.wea import Wea
10
+
11
+
12
+ _logger = logging.getLogger(__name__)
13
+
14
+
15
+ @click.group(help='Commands to create info files for studies.')
16
+ def study():
17
+ pass
18
+
19
+
20
+ @study.command('study-info')
21
+ @click.argument(
22
+ 'wea', type=click.Path(exists=True, dir_okay=False, resolve_path=True))
23
+ @click.argument('timestep', type=click.INT)
24
+ @click.option('--folder', '-f', help='Output folder.', default='.', show_default=True)
25
+ @click.option(
26
+ '--name', '-n', help='Output file name study info.',
27
+ type=click.STRING, default='study_info', show_default=True
28
+ )
29
+ def study_info(wea, timestep, folder, name):
30
+ """Create a study info file.
31
+
32
+ This command generates a study info file with the timestep and the hoys of
33
+ the wea.
34
+
35
+ \b
36
+ Args:
37
+ wea: Path to wea file.
38
+ timestep: Timestep of the study.
39
+ """
40
+ try:
41
+ study_info = {}
42
+ with open(wea) as inf:
43
+ first_word = inf.read(5)
44
+ is_wea = True if first_word == 'place' else False
45
+ if not is_wea:
46
+ _wea_file = os.path.join(os.path.dirname(wea), 'epw_to_wea.wea')
47
+ if os.path.splitext(wea)[-1] != '.epw':
48
+ wea = shutil.copyfile(wea, os.path.splitext(wea)[0] + '.epw')
49
+ wea = Wea.from_epw_file(wea).write(_wea_file)
50
+ wea = Wea.from_file(wea, timestep=timestep)
51
+ study_info['timestep'] = timestep
52
+ study_info['study_hours'] = wea.hoys
53
+
54
+ if not os.path.isdir(folder):
55
+ os.makedirs(folder)
56
+
57
+ # write JSON
58
+ file_path = os.path.join(folder, '%s.json' % name)
59
+ with open(file_path, 'w') as fp:
60
+ json.dump(study_info, fp)
61
+
62
+ except Exception:
63
+ _logger.exception('Failed to generate study info file.')
64
+ sys.exit(1)
65
+ else:
66
+ sys.exit(0)