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,640 @@
|
|
|
1
|
+
"""honeybee radiance octree commands."""
|
|
2
|
+
import click
|
|
3
|
+
import sys
|
|
4
|
+
import logging
|
|
5
|
+
import os
|
|
6
|
+
import json
|
|
7
|
+
|
|
8
|
+
from honeybee_radiance_folder import ModelFolder
|
|
9
|
+
from honeybee_radiance_command.oconv import Oconv
|
|
10
|
+
from honeybee_radiance.config import folders
|
|
11
|
+
|
|
12
|
+
_logger = logging.getLogger(__name__)
|
|
13
|
+
OCTREE_RES = 32768 # resolution of the octree to use
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@click.group(help='Commands to generate Radiance octree.')
|
|
17
|
+
def octree():
|
|
18
|
+
pass
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@octree.command('from-folder')
|
|
22
|
+
@click.argument('folder', type=click.Path(exists=True, file_okay=False, dir_okay=True))
|
|
23
|
+
@click.option(
|
|
24
|
+
'--output', '-o', show_default=True, help='Path to output file (.oct). If a relative path'
|
|
25
|
+
' is provided it should be relative to project folder.'
|
|
26
|
+
)
|
|
27
|
+
@click.option(
|
|
28
|
+
'--default/--black', ' /-b', default=True, show_default=True,
|
|
29
|
+
help='Flag to note whether the octree should be created completely with '
|
|
30
|
+
'black materials.'
|
|
31
|
+
)
|
|
32
|
+
@click.option(
|
|
33
|
+
'--include-aperture/--exclude-aperture', ' /-xa', default=True,
|
|
34
|
+
show_default=True,
|
|
35
|
+
help='Flag to note whether static apertures should be included in the octree.'
|
|
36
|
+
)
|
|
37
|
+
@click.option(
|
|
38
|
+
'--black-groups/--exclude-groups', ' /-xg', default=True, show_default=True,
|
|
39
|
+
help='Flag to note whether dynamic aperture groups should blacked-out in '
|
|
40
|
+
'the octree or they should simply be excluded, letting light pass through.'
|
|
41
|
+
)
|
|
42
|
+
@click.option(
|
|
43
|
+
'--first-shade-state/--exclude-shade-groups', ' /-xs', help='Flag to note whether '
|
|
44
|
+
'dynamic shade groups should be included in the octree as the first shade state '
|
|
45
|
+
'or they should simply be excluded.', default=True, show_default=True
|
|
46
|
+
)
|
|
47
|
+
@click.option(
|
|
48
|
+
'--include-ies/--exclude-ies', ' /-xi', default=True,
|
|
49
|
+
show_default=True,
|
|
50
|
+
help='Flag to note whether IES files should be included in the octree.'
|
|
51
|
+
)
|
|
52
|
+
@click.option(
|
|
53
|
+
'--add-before', type=click.STRING, multiple=True, default=None, show_default=True,
|
|
54
|
+
help='Path for a file to be added to octree before scene files.'
|
|
55
|
+
)
|
|
56
|
+
@click.option(
|
|
57
|
+
'--add-after', type=click.STRING, multiple=True, default=None, show_default=True,
|
|
58
|
+
help='Path for a file to be added to octree after scene files.'
|
|
59
|
+
)
|
|
60
|
+
@click.option(
|
|
61
|
+
'--dry-run', is_flag=True, default=False, show_default=True,
|
|
62
|
+
help='A flag to show the command without running it.'
|
|
63
|
+
)
|
|
64
|
+
def create_octree_from_folder(
|
|
65
|
+
folder, output, default, include_aperture, black_groups, first_shade_state,
|
|
66
|
+
include_ies, add_before, add_after, dry_run
|
|
67
|
+
):
|
|
68
|
+
"""Generate a static octree from a folder.
|
|
69
|
+
|
|
70
|
+
\b
|
|
71
|
+
Args:
|
|
72
|
+
folder: Path to a Radiance model folder.
|
|
73
|
+
"""
|
|
74
|
+
model_folder = ModelFolder.from_model_folder(folder)
|
|
75
|
+
try:
|
|
76
|
+
black_out = False if default else True
|
|
77
|
+
scene_files = model_folder.scene_files(black_out=black_out)
|
|
78
|
+
if include_aperture: # no black out here
|
|
79
|
+
try:
|
|
80
|
+
aperture_files = model_folder.aperture_files()
|
|
81
|
+
scene_files += aperture_files
|
|
82
|
+
except Exception:
|
|
83
|
+
pass # no apertures available in the model
|
|
84
|
+
if black_groups:
|
|
85
|
+
try:
|
|
86
|
+
group_files = model_folder.aperture_group_files_black()
|
|
87
|
+
scene_files += group_files
|
|
88
|
+
except Exception:
|
|
89
|
+
pass # no aperture groups available in the model
|
|
90
|
+
if first_shade_state:
|
|
91
|
+
try:
|
|
92
|
+
dyn_folder = model_folder.dynamic_scene_folder(full=True)
|
|
93
|
+
dyn_shades = model_folder.dynamic_scene()
|
|
94
|
+
shd_g_files = [os.path.join(dyn_folder, grp.states[0].default)
|
|
95
|
+
for grp in dyn_shades]
|
|
96
|
+
scene_files += shd_g_files
|
|
97
|
+
except Exception:
|
|
98
|
+
pass # no shade groups available in the model
|
|
99
|
+
if include_ies:
|
|
100
|
+
try:
|
|
101
|
+
ies_folder = model_folder.ies_folder()
|
|
102
|
+
ies_files = [os.path.join(ies_folder, fp)
|
|
103
|
+
for fp in os.listdir(ies_folder)
|
|
104
|
+
if fp.endswith('rad')]
|
|
105
|
+
scene_files += ies_files
|
|
106
|
+
except Exception:
|
|
107
|
+
pass # no aperture groups available in the model
|
|
108
|
+
if add_after:
|
|
109
|
+
scene_files += list(add_after)
|
|
110
|
+
if add_before:
|
|
111
|
+
scene_files = list(add_before) + scene_files
|
|
112
|
+
cmd = Oconv(output=output, inputs=scene_files)
|
|
113
|
+
cmd.options.f = True
|
|
114
|
+
cmd.options.r = OCTREE_RES
|
|
115
|
+
if dry_run:
|
|
116
|
+
click.echo(cmd)
|
|
117
|
+
else:
|
|
118
|
+
env = None
|
|
119
|
+
if folders.env != {}:
|
|
120
|
+
env = folders.env
|
|
121
|
+
env = dict(os.environ, **env) if env else None
|
|
122
|
+
cmd.run(env=env, cwd=model_folder.folder)
|
|
123
|
+
except Exception:
|
|
124
|
+
_logger.exception('Failed to generate octree.')
|
|
125
|
+
sys.exit(1)
|
|
126
|
+
else:
|
|
127
|
+
sys.exit(0)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
@octree.command('from-folder-multiphase')
|
|
131
|
+
@click.argument('folder', type=click.Path(exists=True, file_okay=False, dir_okay=True))
|
|
132
|
+
@click.option(
|
|
133
|
+
'--sun-path',
|
|
134
|
+
type=click.Path(exists=True, file_okay=True, dir_okay=False, resolve_path=True),
|
|
135
|
+
default=None, show_default=True,
|
|
136
|
+
help='Path for a sun-path file that will be added to octrees for direct sunlight '
|
|
137
|
+
'studies. If sunpath is provided an extra octree for direct_sun will be created.'
|
|
138
|
+
)
|
|
139
|
+
@click.option(
|
|
140
|
+
'--phase', type=click.Choice(['2', '3', '5']), default='5', show_default=True,
|
|
141
|
+
help='Select a multiphase study for which octrees will be created. 3-phase includes '
|
|
142
|
+
'2-phase, and 5-phase includes 3-phase and 2-phase.'
|
|
143
|
+
)
|
|
144
|
+
@click.option("--output-folder", help="Output folder into which the files be written.",
|
|
145
|
+
default="octree", show_default=True)
|
|
146
|
+
def create_octree_from_folder_multiphase(folder, sun_path, phase, output_folder):
|
|
147
|
+
"""Generate a set of octrees from a folder.
|
|
148
|
+
|
|
149
|
+
This command will generate octrees for both default and direct studies. It will do so
|
|
150
|
+
for static apertures and aperture groups, creating one octree for each light path,
|
|
151
|
+
i.e., all other light paths are blacked.
|
|
152
|
+
|
|
153
|
+
\b
|
|
154
|
+
Args:
|
|
155
|
+
folder: Path to a Radiance model folder.
|
|
156
|
+
"""
|
|
157
|
+
model_folder = ModelFolder.from_model_folder(folder)
|
|
158
|
+
|
|
159
|
+
# check if sunpath file exist - otherwise continue without it
|
|
160
|
+
if sun_path and not os.path.isfile(sun_path):
|
|
161
|
+
sun_path = None
|
|
162
|
+
|
|
163
|
+
if phase == '5' and not sun_path:
|
|
164
|
+
raise RuntimeError(
|
|
165
|
+
'To generate octrees for a 5 Phase study you must provide a sunpath.'
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
phases = {
|
|
169
|
+
'2': ['two_phase'],
|
|
170
|
+
'3': ['two_phase', 'three_phase'],
|
|
171
|
+
'5': ['two_phase', 'three_phase', 'five_phase']
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
try:
|
|
175
|
+
scene_mapping = model_folder.octree_scene_mapping()
|
|
176
|
+
if not os.path.isdir(output_folder):
|
|
177
|
+
os.mkdir(output_folder)
|
|
178
|
+
octree_mapping = []
|
|
179
|
+
for study, states in scene_mapping.items():
|
|
180
|
+
if study not in phases[phase]:
|
|
181
|
+
continue
|
|
182
|
+
study_type = []
|
|
183
|
+
for state in states:
|
|
184
|
+
info, commands = _generate_octrees_info(
|
|
185
|
+
state, output_folder, study, sun_path)
|
|
186
|
+
study_type.append(info)
|
|
187
|
+
|
|
188
|
+
for cmd in commands:
|
|
189
|
+
env = None
|
|
190
|
+
if folders.env != {}:
|
|
191
|
+
env = folders.env
|
|
192
|
+
env = dict(os.environ, **env) if env else None
|
|
193
|
+
cmd.run(env=env, cwd=model_folder.folder)
|
|
194
|
+
|
|
195
|
+
octree_mapping.append({study: study_type})
|
|
196
|
+
octree_output = os.path.join(
|
|
197
|
+
model_folder.folder, output_folder, '%s.json' % study
|
|
198
|
+
)
|
|
199
|
+
with open(octree_output, 'w') as fp:
|
|
200
|
+
json.dump(study_type, fp, indent=2)
|
|
201
|
+
|
|
202
|
+
octree_output = os.path.join(
|
|
203
|
+
model_folder.folder, output_folder, 'multi_phase.json'
|
|
204
|
+
)
|
|
205
|
+
with open(octree_output, 'w') as fp:
|
|
206
|
+
json.dump(octree_mapping, fp, indent=2)
|
|
207
|
+
|
|
208
|
+
except Exception:
|
|
209
|
+
_logger.exception('Failed to generate octrees.')
|
|
210
|
+
sys.exit(1)
|
|
211
|
+
else:
|
|
212
|
+
sys.exit(0)
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
@octree.command('from-abstracted-groups')
|
|
216
|
+
@click.argument('folder', type=click.Path(exists=True, file_okay=False, dir_okay=True))
|
|
217
|
+
@click.option(
|
|
218
|
+
'--sun-path', '-sp',
|
|
219
|
+
type=click.Path(exists=True, file_okay=True, dir_okay=False, resolve_path=True),
|
|
220
|
+
default=None, show_default=True,
|
|
221
|
+
help='Path for a sun-path file that will be added to octrees for direct sunlight '
|
|
222
|
+
'studies. If sunpath is provided an extra octree for direct_sun will be created.'
|
|
223
|
+
)
|
|
224
|
+
@click.option('--output-folder', help='Output folder relative to the model folder into '
|
|
225
|
+
'which the files be written.', default='octree', show_default=True)
|
|
226
|
+
def create_octree_from_abstracted_groups(folder, sun_path, output_folder):
|
|
227
|
+
"""Generate a set of octrees from a folder containing abstracted aperture groups.
|
|
228
|
+
|
|
229
|
+
This command assumes that each aperture group in the radiance folder contains
|
|
230
|
+
only two states. The first is a 100 percent transmittance specular (or beam)
|
|
231
|
+
representation of the aperture group and the second is a 100 percent transmittance
|
|
232
|
+
diffuse representation of the aperture group. This abstracted representation is
|
|
233
|
+
intended to simulate contributions of dynamic groups when an external source
|
|
234
|
+
is able to provide specular and diffuse transmittances at each timestep.
|
|
235
|
+
For example, EnergyPlus can provide such values, which together can account
|
|
236
|
+
for several types of complex dynamic fenestration types.
|
|
237
|
+
|
|
238
|
+
Each aperture group will get at least two octrees (one with specular and one
|
|
239
|
+
with diffuse). If a sun-path is provided, a third octree will be added with
|
|
240
|
+
the suns included.
|
|
241
|
+
|
|
242
|
+
\b
|
|
243
|
+
Args:
|
|
244
|
+
folder: Path to a Radiance model folder.
|
|
245
|
+
"""
|
|
246
|
+
model_folder = ModelFolder.from_model_folder(folder)
|
|
247
|
+
try:
|
|
248
|
+
# first, check to see if there are any aperture groups in the model
|
|
249
|
+
output_folder = os.path.join(model_folder.folder, output_folder)
|
|
250
|
+
if not os.path.isdir(output_folder):
|
|
251
|
+
os.mkdir(output_folder)
|
|
252
|
+
group_info_file = os.path.join(output_folder, 'group_info.json')
|
|
253
|
+
group_info, groups_exist = [], True
|
|
254
|
+
try:
|
|
255
|
+
grp_folder = model_folder.aperture_group_folder()
|
|
256
|
+
ap_groups = model_folder.aperture_groups()
|
|
257
|
+
if len(ap_groups) == 0:
|
|
258
|
+
groups_exist = False
|
|
259
|
+
except Exception:
|
|
260
|
+
groups_exist = False
|
|
261
|
+
|
|
262
|
+
if groups_exist:
|
|
263
|
+
# get the static scene files with blacked-out apertures
|
|
264
|
+
scene_files = model_folder.scene_files(black_out=False)
|
|
265
|
+
try:
|
|
266
|
+
aperture_files = model_folder.aperture_files(black_out=True)
|
|
267
|
+
scene_files += aperture_files
|
|
268
|
+
except Exception:
|
|
269
|
+
pass # no apertures available in the model
|
|
270
|
+
|
|
271
|
+
# get the environment variables
|
|
272
|
+
env = None
|
|
273
|
+
if folders.env != {}:
|
|
274
|
+
env = folders.env
|
|
275
|
+
env = dict(os.environ, **env) if env else None
|
|
276
|
+
|
|
277
|
+
# loop through the aperture groups and create the octrees
|
|
278
|
+
for i, a_grp in enumerate(ap_groups):
|
|
279
|
+
# create a sub-folder and get black versions of all other aperture groups
|
|
280
|
+
sub_folder = os.path.join(output_folder, a_grp.identifier)
|
|
281
|
+
if not os.path.isdir(sub_folder):
|
|
282
|
+
os.mkdir(sub_folder)
|
|
283
|
+
blk_grp = [_model_rel(grp_folder, ag.states[0].black)
|
|
284
|
+
for j, ag in enumerate(ap_groups) if j != i]
|
|
285
|
+
blk_grp = [bg.replace('\\', '/') for bg in blk_grp]
|
|
286
|
+
grp_scene_files = scene_files + blk_grp
|
|
287
|
+
# command for the octree for specular transmittance
|
|
288
|
+
spec_file = os.path.join(sub_folder, 'spec.oct')
|
|
289
|
+
spec_scene_files = grp_scene_files + \
|
|
290
|
+
[_model_rel(grp_folder, a_grp.states[0].default)]
|
|
291
|
+
cmd_s = Oconv(output=spec_file, inputs=spec_scene_files)
|
|
292
|
+
# command for the octree for diffuse transmittance
|
|
293
|
+
diff_file = os.path.join(sub_folder, 'diff.oct')
|
|
294
|
+
diff_scene_files = grp_scene_files + \
|
|
295
|
+
[_model_rel(grp_folder, a_grp.states[1].default)]
|
|
296
|
+
cmd_d = Oconv(output=diff_file, inputs=diff_scene_files)
|
|
297
|
+
cmds = [cmd_s, cmd_d]
|
|
298
|
+
# add info about the generated files
|
|
299
|
+
grp_info_dict = {
|
|
300
|
+
'identifier': a_grp.identifier,
|
|
301
|
+
'spec': os.path.basename(spec_file),
|
|
302
|
+
'diff': os.path.basename(diff_file)
|
|
303
|
+
}
|
|
304
|
+
# command for the octree with suns
|
|
305
|
+
if sun_path and os.path.isfile(sun_path):
|
|
306
|
+
spec_sun_file = os.path.join(sub_folder, 'spec_sun.oct')
|
|
307
|
+
spec_sun_scene_files = [sun_path] + spec_scene_files
|
|
308
|
+
cmd_ss = Oconv(output=spec_sun_file, inputs=spec_sun_scene_files)
|
|
309
|
+
cmds.append(cmd_ss)
|
|
310
|
+
grp_info_dict['sun'] = os.path.basename(spec_sun_file)
|
|
311
|
+
# run all of the commands to create the octrees
|
|
312
|
+
for cmd in cmds:
|
|
313
|
+
cmd.options.f = True
|
|
314
|
+
cmd.options.r = OCTREE_RES
|
|
315
|
+
cmd.run(env=env, cwd=model_folder.folder)
|
|
316
|
+
group_info.append(grp_info_dict)
|
|
317
|
+
|
|
318
|
+
# write out a JSON with information about the octrees and groups
|
|
319
|
+
with open(group_info_file, 'w') as fp:
|
|
320
|
+
json.dump(group_info, fp, indent=2)
|
|
321
|
+
except Exception:
|
|
322
|
+
_logger.exception('Failed to generate abstracted group octrees.')
|
|
323
|
+
sys.exit(1)
|
|
324
|
+
else:
|
|
325
|
+
sys.exit(0)
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
@octree.command('from-shade-trans-groups')
|
|
329
|
+
@click.argument('folder', type=click.Path(exists=True, file_okay=False, dir_okay=True))
|
|
330
|
+
@click.option(
|
|
331
|
+
'--sun-path', '-sp',
|
|
332
|
+
type=click.Path(exists=True, file_okay=True, dir_okay=False, resolve_path=True),
|
|
333
|
+
default=None, show_default=True,
|
|
334
|
+
help='Path for a sun-path file that will be added to octrees for direct sunlight '
|
|
335
|
+
'studies. If sunpath is provided an extra octree for direct_sun will be created.'
|
|
336
|
+
)
|
|
337
|
+
@click.option('--output-folder', help='Output folder relative to the model folder into '
|
|
338
|
+
'which the files be written.', default='octree', show_default=True)
|
|
339
|
+
def create_octree_from_shade_trans_groups(folder, sun_path, output_folder):
|
|
340
|
+
"""Generate a set of octrees from a folder containing shade transmittance groups.
|
|
341
|
+
|
|
342
|
+
This command assumes that each shade group in the radiance folder contains
|
|
343
|
+
only two states. The first is a completely opaque representation of the shade
|
|
344
|
+
group and the second is a completely transparent representation of the shade
|
|
345
|
+
group. This abstracted representation is intended to simulate dynamic shade
|
|
346
|
+
transmittance that changes at each timestep.
|
|
347
|
+
|
|
348
|
+
Each shade group will get an octree. If a sun-path is provided, an additional
|
|
349
|
+
octree will be added for each group.
|
|
350
|
+
|
|
351
|
+
\b
|
|
352
|
+
Args:
|
|
353
|
+
folder: Path to a Radiance model folder.
|
|
354
|
+
"""
|
|
355
|
+
model_folder = ModelFolder.from_model_folder(folder)
|
|
356
|
+
try:
|
|
357
|
+
# first, check to see if there are any shade groups in the model
|
|
358
|
+
output_folder = os.path.join(model_folder.folder, output_folder)
|
|
359
|
+
if not os.path.isdir(output_folder):
|
|
360
|
+
os.mkdir(output_folder)
|
|
361
|
+
group_info_file = os.path.join(output_folder, 'trans_info.json')
|
|
362
|
+
group_info, groups_exist = [], True
|
|
363
|
+
try:
|
|
364
|
+
grp_folder = model_folder.dynamic_scene_folder()
|
|
365
|
+
shd_groups = model_folder.dynamic_scene()
|
|
366
|
+
if len(shd_groups) == 0:
|
|
367
|
+
groups_exist = False
|
|
368
|
+
except Exception:
|
|
369
|
+
groups_exist = False
|
|
370
|
+
|
|
371
|
+
if groups_exist:
|
|
372
|
+
# get the static scene files
|
|
373
|
+
scene_files = model_folder.scene_files(black_out=False)
|
|
374
|
+
try:
|
|
375
|
+
aperture_files = model_folder.aperture_files(black_out=False)
|
|
376
|
+
scene_files += aperture_files
|
|
377
|
+
except Exception:
|
|
378
|
+
pass # no apertures available in the model
|
|
379
|
+
|
|
380
|
+
# get the environment variables
|
|
381
|
+
env = None
|
|
382
|
+
if folders.env != {}:
|
|
383
|
+
env = folders.env
|
|
384
|
+
env = dict(os.environ, **env) if env else None
|
|
385
|
+
|
|
386
|
+
# loop through the shade groups and create the octrees
|
|
387
|
+
for i, s_grp in enumerate(shd_groups):
|
|
388
|
+
# gather files to represent the transparent shade group
|
|
389
|
+
dyn_grp = [_model_rel(grp_folder, sg.states[0].default)
|
|
390
|
+
for j, sg in enumerate(shd_groups) if j != i]
|
|
391
|
+
dyn_grp = [sg.replace('\\', '/') for sg in dyn_grp]
|
|
392
|
+
grp_scene_files = scene_files + dyn_grp
|
|
393
|
+
oct_file = os.path.join(output_folder, '{}.oct'.format(s_grp.identifier))
|
|
394
|
+
# command for the octree
|
|
395
|
+
cmds = [Oconv(output=oct_file, inputs=grp_scene_files)]
|
|
396
|
+
# add info about the generated files
|
|
397
|
+
grp_info_dict = {
|
|
398
|
+
'identifier': s_grp.identifier,
|
|
399
|
+
'default': os.path.basename(oct_file)
|
|
400
|
+
}
|
|
401
|
+
# command for the octree with suns
|
|
402
|
+
if sun_path and os.path.isfile(sun_path):
|
|
403
|
+
sun_file = os.path.join(
|
|
404
|
+
output_folder, '{}_sun.oct'.format(s_grp.identifier))
|
|
405
|
+
sun_scene_files = [sun_path] + grp_scene_files
|
|
406
|
+
cmd_ss = Oconv(output=sun_file, inputs=sun_scene_files)
|
|
407
|
+
cmds.append(cmd_ss)
|
|
408
|
+
grp_info_dict['sun'] = os.path.basename(sun_file)
|
|
409
|
+
# run all of the commands to create the octrees
|
|
410
|
+
for cmd in cmds:
|
|
411
|
+
cmd.options.f = True
|
|
412
|
+
cmd.options.r = OCTREE_RES
|
|
413
|
+
cmd.run(env=env, cwd=model_folder.folder)
|
|
414
|
+
group_info.append(grp_info_dict)
|
|
415
|
+
|
|
416
|
+
# write out a JSON with information about the octrees and groups
|
|
417
|
+
with open(group_info_file, 'w') as fp:
|
|
418
|
+
json.dump(group_info, fp, indent=2)
|
|
419
|
+
except Exception:
|
|
420
|
+
_logger.exception('Failed to generate shade trans group octrees.')
|
|
421
|
+
sys.exit(1)
|
|
422
|
+
else:
|
|
423
|
+
sys.exit(0)
|
|
424
|
+
|
|
425
|
+
|
|
426
|
+
def _model_rel(folder, rel_file):
|
|
427
|
+
"""Get a file path relative to a model folder."""
|
|
428
|
+
return os.path.join(folder, os.path.normpath(rel_file)).replace('\\', '/')
|
|
429
|
+
|
|
430
|
+
|
|
431
|
+
def _generate_octrees_info(state, output_folder='octree', study='two_phase',
|
|
432
|
+
sun_path=None):
|
|
433
|
+
"""Get octree information for default, direct, and direct sun. The
|
|
434
|
+
functions also generates the Radiance commands (oconv) for creating the
|
|
435
|
+
octrees.
|
|
436
|
+
|
|
437
|
+
Example of valid argument 'state':
|
|
438
|
+
{
|
|
439
|
+
'light_path': '__static_apertures__',
|
|
440
|
+
'identifier': '__static_apertures__',
|
|
441
|
+
'scene_files': ['model/scene/envelope.mat', 'model/scene/envelope.rad'],
|
|
442
|
+
'scene_files_direct': ['model/scene/envelope.mat', 'model/scene/envelope.rad'],
|
|
443
|
+
'scene_files_direct': ['model/scene/envelope.mat', 'model/scene/envelope.rad'],
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
Args:
|
|
447
|
+
state: A state as a dictionary with information about which files to include in
|
|
448
|
+
each octree.
|
|
449
|
+
output_folder: Folder name to where the octrees will we generated.
|
|
450
|
+
study: A string of the study. There are either 'two_phase', 'three_phase', or
|
|
451
|
+
'five_phase'.
|
|
452
|
+
sun_path: Path for a sun-path file that will be added to octrees for direct
|
|
453
|
+
sunlight studies. If sunpath is provided an extra octree for direct_sun
|
|
454
|
+
will be created.
|
|
455
|
+
|
|
456
|
+
Returns:
|
|
457
|
+
Two elements:
|
|
458
|
+
- octree information as dictionary
|
|
459
|
+
- oconv commands as a list
|
|
460
|
+
"""
|
|
461
|
+
commands = []
|
|
462
|
+
info = {
|
|
463
|
+
'identifier': state['identifier'],
|
|
464
|
+
'light_path': state['light_path']}
|
|
465
|
+
|
|
466
|
+
# default
|
|
467
|
+
if 'scene_files' in state:
|
|
468
|
+
scene_files = state['scene_files']
|
|
469
|
+
if len(' '.join(scene_files)) > 8000:
|
|
470
|
+
if not os.path.isdir('scene'):
|
|
471
|
+
os.mkdir('scene')
|
|
472
|
+
scene_file = os.path.join('scene', state['identifier'] + '.rad')
|
|
473
|
+
scene_description = []
|
|
474
|
+
for sf in scene_files:
|
|
475
|
+
with open(sf, 'r') as sf:
|
|
476
|
+
scene_description.append(sf.read())
|
|
477
|
+
with open(scene_file, 'w') as sf:
|
|
478
|
+
sf.write('\n'.join(scene_description))
|
|
479
|
+
scene_files = [scene_file]
|
|
480
|
+
octree_name = state['identifier']
|
|
481
|
+
output = os.path.join(
|
|
482
|
+
output_folder, '%s.oct' % octree_name)
|
|
483
|
+
cmd = Oconv(output=output, inputs=scene_files)
|
|
484
|
+
cmd.options.f = True
|
|
485
|
+
cmd.options.r = OCTREE_RES
|
|
486
|
+
commands.append(cmd)
|
|
487
|
+
|
|
488
|
+
info['octree'] = '%s.oct' % octree_name
|
|
489
|
+
|
|
490
|
+
# direct - don't add them for 5 phase
|
|
491
|
+
if 'scene_files_direct' in state and study != 'five_phase':
|
|
492
|
+
scene_files_direct = state['scene_files_direct']
|
|
493
|
+
if len(' '.join(scene_files_direct)) > 8000:
|
|
494
|
+
if not os.path.isdir('scene'):
|
|
495
|
+
os.mkdir('scene')
|
|
496
|
+
scene_file = os.path.join('scene', '_'.join([state['identifier'], 'direct']) + '.rad')
|
|
497
|
+
scene_description = []
|
|
498
|
+
for sf in scene_files_direct:
|
|
499
|
+
with open(sf, 'r') as sf:
|
|
500
|
+
scene_description.append(sf.read())
|
|
501
|
+
with open(scene_file, 'w') as sf:
|
|
502
|
+
sf.write('\n'.join(scene_description))
|
|
503
|
+
scene_files_direct = [scene_file]
|
|
504
|
+
octree_direct_name = '%s_direct' % state['identifier']
|
|
505
|
+
output_direct = os.path.join(
|
|
506
|
+
output_folder, '%s.oct' % octree_direct_name)
|
|
507
|
+
cmd = Oconv(output=output_direct,
|
|
508
|
+
inputs=scene_files_direct)
|
|
509
|
+
cmd.options.f = True
|
|
510
|
+
cmd.options.r = OCTREE_RES
|
|
511
|
+
commands.append(cmd)
|
|
512
|
+
|
|
513
|
+
info['octree_direct'] = '%s.oct' % octree_direct_name
|
|
514
|
+
|
|
515
|
+
# direct sun - don't add them for 3-phase
|
|
516
|
+
if sun_path and study != 'three_phase':
|
|
517
|
+
scene_files_direct = state['scene_files_direct']
|
|
518
|
+
if len(' '.join(scene_files_direct)) > 8000:
|
|
519
|
+
if not os.path.isdir('scene'):
|
|
520
|
+
os.mkdir('scene')
|
|
521
|
+
scene_file = os.path.join('scene', '_'.join([state['identifier'], 'direct']) + '.rad')
|
|
522
|
+
scene_description = []
|
|
523
|
+
for sf in scene_files_direct:
|
|
524
|
+
with open(sf, 'r') as sf:
|
|
525
|
+
scene_description.append(sf.read())
|
|
526
|
+
with open(scene_file, 'w') as sf:
|
|
527
|
+
sf.write('\n'.join(scene_description))
|
|
528
|
+
scene_files_direct = [scene_file]
|
|
529
|
+
scene_files_direct_sun = [sun_path] + scene_files_direct
|
|
530
|
+
octree_direct_sun_name = '%s_direct_sun' % state['identifier']
|
|
531
|
+
output_direct = \
|
|
532
|
+
os.path.join(output_folder, '%s.oct' %
|
|
533
|
+
octree_direct_sun_name)
|
|
534
|
+
cmd = Oconv(output=output_direct,
|
|
535
|
+
inputs=scene_files_direct_sun)
|
|
536
|
+
cmd.options.f = True
|
|
537
|
+
cmd.options.r = OCTREE_RES
|
|
538
|
+
|
|
539
|
+
commands.append(cmd)
|
|
540
|
+
|
|
541
|
+
info['octree_direct_sun'] = '%s.oct' % octree_direct_sun_name
|
|
542
|
+
|
|
543
|
+
return info, commands
|
|
544
|
+
|
|
545
|
+
|
|
546
|
+
@octree.command('from-folder-static')
|
|
547
|
+
@click.argument('folder', type=click.Path(exists=True, file_okay=False, dir_okay=True))
|
|
548
|
+
@click.option(
|
|
549
|
+
'--output', '-o', show_default=True, help='Path to output file (.oct). If a relative path'
|
|
550
|
+
' is provided it should be relative to project folder.'
|
|
551
|
+
)
|
|
552
|
+
@click.option(
|
|
553
|
+
'--add-before', type=click.STRING, multiple=True, default=None, show_default=True,
|
|
554
|
+
help='Path for a file to be added to octree before scene files.'
|
|
555
|
+
)
|
|
556
|
+
@click.option(
|
|
557
|
+
'--add-after', type=click.STRING, multiple=True, default=None, show_default=True,
|
|
558
|
+
help='Path for a file to be added to octree after scene files.'
|
|
559
|
+
)
|
|
560
|
+
@click.option(
|
|
561
|
+
'--dry-run', is_flag=True, default=False, show_default=True,
|
|
562
|
+
help='A flag to show the command without running it.'
|
|
563
|
+
)
|
|
564
|
+
def create_static_octree_from_folder(
|
|
565
|
+
folder, output, add_before, add_after, dry_run
|
|
566
|
+
):
|
|
567
|
+
"""Generate a static octree from a folder.
|
|
568
|
+
|
|
569
|
+
The octree will include the default state of aperture and shade groups if
|
|
570
|
+
any of those are in the model folder.
|
|
571
|
+
|
|
572
|
+
\b
|
|
573
|
+
Args:
|
|
574
|
+
folder: Path to a Radiance model folder.
|
|
575
|
+
"""
|
|
576
|
+
model_folder = ModelFolder.from_model_folder(folder)
|
|
577
|
+
|
|
578
|
+
try:
|
|
579
|
+
scene_files = model_folder.scene_files()
|
|
580
|
+
try:
|
|
581
|
+
aperture_files = model_folder.aperture_files()
|
|
582
|
+
scene_files += aperture_files
|
|
583
|
+
except Exception:
|
|
584
|
+
pass # no apertures available in the model
|
|
585
|
+
try:
|
|
586
|
+
ap_group_folder = model_folder.aperture_group_folder(full=True)
|
|
587
|
+
aperture_groups = model_folder.aperture_groups()
|
|
588
|
+
ap_g_files = [
|
|
589
|
+
os.path.relpath(
|
|
590
|
+
os.path.join(ap_group_folder, grp.states[0].default),
|
|
591
|
+
model_folder.folder)
|
|
592
|
+
for grp in aperture_groups
|
|
593
|
+
]
|
|
594
|
+
if len(' '.join(ap_g_files)) > 8000:
|
|
595
|
+
if not os.path.isdir('scene'):
|
|
596
|
+
os.mkdir('scene')
|
|
597
|
+
scene_file = os.path.join('scene', 'aperture_groups' + '.rad')
|
|
598
|
+
scene_description = []
|
|
599
|
+
for sf in ap_g_files:
|
|
600
|
+
with open(sf, 'r') as sf:
|
|
601
|
+
scene_description.append(sf.read())
|
|
602
|
+
with open(scene_file, 'w') as sf:
|
|
603
|
+
sf.write('\n'.join(scene_description))
|
|
604
|
+
scene_files += [scene_file]
|
|
605
|
+
else:
|
|
606
|
+
scene_files += ap_g_files
|
|
607
|
+
except Exception:
|
|
608
|
+
pass # no aperture groups available in the model
|
|
609
|
+
try:
|
|
610
|
+
dyn_folder = model_folder.dynamic_scene_folder(full=True)
|
|
611
|
+
dyn_shades = model_folder.dynamic_scene()
|
|
612
|
+
shd_g_files = [
|
|
613
|
+
os.path.relpath(
|
|
614
|
+
os.path.join(dyn_folder, grp.states[0].default),
|
|
615
|
+
model_folder.folder)
|
|
616
|
+
for grp in dyn_shades
|
|
617
|
+
]
|
|
618
|
+
scene_files += shd_g_files
|
|
619
|
+
except Exception:
|
|
620
|
+
pass # no shade groups available in the model
|
|
621
|
+
if add_after:
|
|
622
|
+
scene_files += list(add_after)
|
|
623
|
+
if add_before:
|
|
624
|
+
scene_files = list(add_before) + scene_files
|
|
625
|
+
cmd = Oconv(output=output, inputs=scene_files)
|
|
626
|
+
cmd.options.f = True
|
|
627
|
+
cmd.options.r = OCTREE_RES
|
|
628
|
+
if dry_run:
|
|
629
|
+
click.echo(cmd)
|
|
630
|
+
else:
|
|
631
|
+
env = None
|
|
632
|
+
if folders.env != {}:
|
|
633
|
+
env = folders.env
|
|
634
|
+
env = dict(os.environ, **env) if env else None
|
|
635
|
+
cmd.run(env=env, cwd=model_folder.folder)
|
|
636
|
+
except Exception:
|
|
637
|
+
_logger.exception('Failed to generate octree.')
|
|
638
|
+
sys.exit(1)
|
|
639
|
+
else:
|
|
640
|
+
sys.exit(0)
|