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,554 @@
1
+ """Base class for all Radiance Primitives.
2
+
3
+ The term "Primitive" can refer to either a geometry object or a modifer that can
4
+ be applied to geometry in order to change its reflectance, transmittance, etc.
5
+ All primitives share a similar format for how they are represented within .rad
6
+ files and the Primitive class provides common code used to serialize/de-serialize
7
+ such objects from .rad strings among other functionalities.
8
+
9
+ Because the Primitive class is so abstract, you most likely want to use one of
10
+ the sub-classes of Primitive instead of using this class directly. You will find
11
+ such sub-classes in the honeybee_radiance.modifier and honeybee_radiance.geometry
12
+ sub-packages. More information on Radiance Primitives can be found at:
13
+
14
+ http://radsite.lbl.gov/radiance/refer/ray.html
15
+ """
16
+ from honeybee.typing import valid_rad_string, list_with_length
17
+ from honeybee._lockable import lockable
18
+
19
+ from honeybee_radiance.reader import string_to_dicts
20
+
21
+
22
+ class Void(object):
23
+ """Void modifier.
24
+
25
+ Properties:
26
+ * identifier
27
+ * display_name
28
+ * is_modifier
29
+ * is_opaque
30
+ """
31
+ __slots__ = ()
32
+
33
+ @property
34
+ def identifier(self):
35
+ """Void."""
36
+ return 'void'
37
+
38
+ @property
39
+ def display_name(self):
40
+ """Void."""
41
+ return 'void'
42
+
43
+ @property
44
+ def is_modifier(self):
45
+ """True."""
46
+ return True
47
+
48
+ @property
49
+ def is_opaque(self):
50
+ """False for a void."""
51
+ return False
52
+
53
+ @property
54
+ def is_void(self):
55
+ """True for a void."""
56
+ return True
57
+
58
+ def to_radiance(self):
59
+ """Return full radiance definition."""
60
+ return 'void'
61
+
62
+ def to_dict(self):
63
+ """Return void."""
64
+ return None
65
+
66
+ @classmethod
67
+ def from_dict(cls, value):
68
+ return cls()
69
+
70
+ def __key(self):
71
+ """A tuple based on the object properties, useful for hashing."""
72
+ return (self.identifier,)
73
+
74
+ def __hash__(self):
75
+ return hash(self.__key())
76
+
77
+ def __eq__(self, other):
78
+ return isinstance(other, self.__class__) and \
79
+ self.__key() == other.__key()
80
+
81
+ def __ne__(self, other):
82
+ return not self.__eq__(other)
83
+
84
+ def ToString(self):
85
+ """Overwrite .NET ToString."""
86
+ return self.to_radiance()
87
+
88
+ def __repr__(self):
89
+ return self.to_radiance()
90
+
91
+
92
+ VOID = Void()
93
+
94
+
95
+ @lockable
96
+ class Primitive(object):
97
+ """Base class for Radiance Primitives.
98
+
99
+ Args:
100
+ identifier: Text string for a unique Primitive ID. Must not contain spaces
101
+ or special characters. This will be used to identify the object across
102
+ a model and in the exported Radiance files.
103
+ modifier: Modifier. It can be primitive, mixture, texture or pattern.
104
+ (Default: None).
105
+ values: An array 3 arrays for primitive data. Each of the 3 sub-arrays
106
+ refer to a line number in the radiance primitive definitions and the
107
+ values in each array correspond to values occurring within each line.
108
+ For example, [[], [], ['0.500', '0.500', '0.500', '0.000', '0.050']]
109
+ corresponds to values one would find for a Plastic material.
110
+ (Default: [[], [], []]).
111
+ is_opaque: A boolean to indicate whether this primitive is opaque.
112
+ dependencies: A list of primitives that this primitive depends on. This
113
+ argument is only useful for defining advanced primitives that are
114
+ defined based on other primitives. (Default: []).
115
+
116
+ Properties:
117
+ * identifier
118
+ * display_name
119
+ * values
120
+ * modifier
121
+ * dependencies
122
+ * is_geometry
123
+ * is_modifier
124
+ * is_material
125
+ * is_texture
126
+ * is_pattern
127
+ * is_mixture
128
+ * is_opaque
129
+ * is_void
130
+ """
131
+ __slots__ = ('_identifier', '_display_name', '_modifier', '_values',
132
+ '_is_opaque', '_dependencies', '_type', '_locked')
133
+
134
+ # All Radiance geometry types
135
+ GEOMETRYTYPES = set(('source', 'sphere', 'bubble', 'polygon', 'cone', 'cup',
136
+ 'cylinder', 'tube', 'ring', 'instance', 'mesh'))
137
+
138
+ # All Radiance material types
139
+ MATERIALTYPES = \
140
+ set(('plastic', 'glass', 'trans', 'metal', 'mirror', 'illum',
141
+ 'mixedfunc', 'dielectric', 'transdata', 'light', 'glow', 'BSDF',
142
+ 'aBSDF', 'spotlight', 'prism1', 'prism2', 'mist', 'plastic2',
143
+ 'metal2', 'trans2', 'ashik2', 'dielectric', 'interface',
144
+ 'plasfunc', 'metfunc', 'transfunc', 'BRTDfunc',
145
+ 'plasdata', 'metdata', 'transdata', 'antimatter'))
146
+
147
+ TEXTURETYPES = set(('texfunc', 'texdata'))
148
+
149
+ PATTERNTYPES = set(('colorfunc', 'brightfunc', 'colordata', 'brightdata',
150
+ 'colorpict', 'colortext', 'brighttext'))
151
+
152
+ MIXTURETYPES = set(('mixfunc', 'mixdata', 'mixpict', 'mixtext'))
153
+
154
+ # All modifier types (everything except geometry)
155
+ MODIFIERTYPES = set().union(MATERIALTYPES, MIXTURETYPES, TEXTURETYPES, PATTERNTYPES)
156
+
157
+ # All Radiance primitive types
158
+ TYPES = set().union(GEOMETRYTYPES, MODIFIERTYPES)
159
+
160
+ # Modifiers that are not usually opaque. This will be used to set is_opaque property
161
+ # if it is not overridded by the user by setting the is_opaque property
162
+ NONEOPAQUETYPES = set(('glass', 'trans', 'trans2', 'transdata', 'transfunc',
163
+ 'dielectric', 'BSDF', 'aBSDF', 'mixfunc', 'BRTDfunc', 'mist',
164
+ 'prism1', 'prism2'))
165
+
166
+ def __init__(self, identifier, modifier=None, values=None, is_opaque=None,
167
+ dependencies=None):
168
+ """Create primitive base."""
169
+ self.identifier = identifier
170
+ self._display_name = None
171
+ self.type = self.__class__.__name__.lower()
172
+ self.modifier = modifier
173
+ self.values = values or [[], [], []]
174
+ self._is_opaque = is_opaque
175
+ self._dependencies = []
176
+ dependencies = dependencies or []
177
+ for dep in dependencies:
178
+ self.add_dependent(dep)
179
+
180
+ @classmethod
181
+ def from_string(cls, primitive_string):
182
+ """Create a Radiance primitive from a string.
183
+
184
+ If the primitive modifier is not void or it has other dependencies,
185
+ the modifier and/or dependencies must also be part of the input string.
186
+ """
187
+ pr_dict = string_to_dicts(primitive_string)
188
+ assert len(pr_dict) == 1, \
189
+ 'Input string includes more than one Radiance objects.'
190
+ return cls.from_primitive_dict(pr_dict[0])
191
+
192
+ @classmethod
193
+ def from_primitive_dict(cls, primitive_dict):
194
+ """Initialize the object from a primitive dict.
195
+
196
+ The primitive_dict is a dictionary following the base Primitive schema
197
+ of a Radiance object. This base Primitive schema is the same for all
198
+ Radiance Primitives (including Modifiers and Geometry) whereas the
199
+ from_dict classmethod accepts a different schema that is customized
200
+ to each subclass inheriting from the Radiance Primitive.
201
+
202
+ Args:
203
+ data: A dictionary in the format below
204
+
205
+ .. code-block:: python
206
+
207
+ {
208
+ "modifier": {}, # primitive modifier (Default: None)
209
+ "type": "", # lowercase string for the primitive type
210
+ "identifier": "", # primitive identifier
211
+ "display_name": "", # primitive display name
212
+ "values": [], # values
213
+ "dependencies": []
214
+ }
215
+ """
216
+ modifier, dependencies = cls.filter_dict_input(primitive_dict)
217
+
218
+ cls_ = cls(
219
+ identifier=primitive_dict['identifier'],
220
+ modifier=modifier,
221
+ values=primitive_dict['values'],
222
+ dependencies=dependencies
223
+ )
224
+ if 'display_name' in primitive_dict and \
225
+ primitive_dict['display_name'] is not None:
226
+ cls_.display_name = primitive_dict['display_name']
227
+
228
+ if cls_.type == 'primitive':
229
+ cls_.type = primitive_dict['type']
230
+
231
+ return cls_
232
+
233
+ @classmethod
234
+ def from_dict(cls, data):
235
+ """Initialize the object from a dictionary.
236
+
237
+ Args:
238
+ data: A dictionary in the format below.
239
+
240
+ .. code-block:: python
241
+
242
+ {
243
+ "modifier": {}, # primitive modifier (Default: None)
244
+ "type": "", # lowercase string for the primitive type
245
+ "identifier": "", # primitive identifier
246
+ "display_name": "", # primitive display name
247
+ "values": [], # values
248
+ "dependencies": []
249
+ }
250
+ """
251
+ return cls.from_primitive_dict(data)
252
+
253
+ @property
254
+ def type(self):
255
+ """Get or set a string for the primitive type.
256
+
257
+ This should always be lower case in order to match the radiance convention.
258
+ """
259
+ return self._type
260
+
261
+ @type.setter
262
+ def type(self, type_str):
263
+ _mapper = {'bsdf': 'BSDF', 'absdf': 'aBSDF', 'brtdfunc': 'BRTDfunc'}
264
+
265
+ if type_str != 'primitive':
266
+ if type_str not in self.TYPES:
267
+ # try base classes for subclasses
268
+ for base in self.__class__.__mro__:
269
+ if base.__name__.lower() in _mapper:
270
+ type_str = _mapper[base.__name__.lower()]
271
+ break
272
+ if base.__name__.lower() in self.TYPES:
273
+ type_str = base.__name__.lower()
274
+ break
275
+
276
+ assert type_str in self.TYPES, \
277
+ "%s is not a supported Radiance primitive type." % type_str + \
278
+ "Try one of these primitives:\n%s" % str(self.TYPES)
279
+
280
+ self._type = type_str
281
+
282
+ @property
283
+ def identifier(self):
284
+ """Get or set a text string for the unique primitive identifier."""
285
+ return self._identifier
286
+
287
+ @identifier.setter
288
+ def identifier(self, identifier):
289
+ self._identifier = valid_rad_string(identifier)
290
+
291
+ @property
292
+ def display_name(self):
293
+ """Get or set a string for the object name without any character restrictions.
294
+
295
+ If not set, this will be equal to the identifier.
296
+ """
297
+ if self._display_name is None:
298
+ return self._identifier
299
+ return self._display_name
300
+
301
+ @display_name.setter
302
+ def display_name(self, value):
303
+ try:
304
+ self._display_name = str(value)
305
+ except UnicodeEncodeError: # Python 2 machine lacking the character set
306
+ self._display_name = value # keep it as unicode
307
+
308
+ @property
309
+ def values(self):
310
+ """Get or set the values of the current primitive as a list of three lists.
311
+
312
+ Each sub-list represents a line of the primitive's radiance representation
313
+ and contain the properties that define the primitive.
314
+
315
+ Usage:
316
+
317
+ .. code-block:: python
318
+
319
+ # This will erase all values except the first line, which has 9 custom items
320
+ primitive.values = [
321
+ [0.5, 0.5, 0.5, "/usr/oak.pic", ".", "frac(U)", "frac(V)", "-s", 1.1667],
322
+ [],
323
+ []
324
+ ]
325
+ """
326
+ self._update_values()
327
+ return self._values
328
+
329
+ @values.setter
330
+ def values(self, new_values):
331
+ self._values = list_with_length(new_values, 3, list, 'radiance primitive values')
332
+
333
+ @property
334
+ def modifier(self):
335
+ """Get or set an object for the primitive modifier."""
336
+ return self._modifier
337
+
338
+ @modifier.setter
339
+ def modifier(self, modifier):
340
+ if not modifier or modifier == 'void':
341
+ self._modifier = VOID
342
+ else:
343
+ try:
344
+ assert modifier.is_modifier, \
345
+ 'A {} cannot be a modifier. ' \
346
+ 'Modifiers must be materials, mixtures, ' \
347
+ 'textures or patterns'.format(type(modifier))
348
+ except AttributeError:
349
+ raise TypeError('Invalid modifier: %s' % modifier)
350
+ except AssertionError as e:
351
+ raise AssertionError(e)
352
+ else:
353
+ self._modifier = modifier
354
+
355
+ @property
356
+ def dependencies(self):
357
+ """Get list of dependencies for this primitive.
358
+
359
+ Additional dependencies can be added with the add_dependent method.
360
+ """
361
+ return self._dependencies
362
+
363
+ @property
364
+ def is_geometry(self):
365
+ """Get a boolean noting whether this object is a Radiance geometry."""
366
+ return False
367
+
368
+ @property
369
+ def is_modifier(self):
370
+ """Get a boolean indicating whether this object is a Radiance modifier.
371
+
372
+ Modifiers include materials, mixtures, textures and patterns.
373
+ """
374
+ return self.type in self.MODIFIERTYPES
375
+
376
+ @property
377
+ def is_material(self):
378
+ """Get a boolean noting whether this object is a material modifier."""
379
+ return self.type in self.MATERIALTYPES
380
+
381
+ @property
382
+ def is_texture(self):
383
+ """Get a boolean noting whether this object is a texture modifier."""
384
+ return self.type in self.TEXTURETYPES
385
+
386
+ @property
387
+ def is_pattern(self):
388
+ """Get a boolean noting whether this object is a pattern modifier."""
389
+ return self.type in self.PATTERNTYPES
390
+
391
+ @property
392
+ def is_mixture(self):
393
+ """Get a boolean noting whether this object is a mixture modifier."""
394
+ return self.type in self.MIXTURETYPES
395
+
396
+ @property
397
+ def is_opaque(self):
398
+ """Get or set a boolean to indicate whether this primitive is opaque.
399
+
400
+ This property is used to separate opaque and non-opaque geometries as
401
+ well as modifiers.
402
+ """
403
+ if self._is_opaque: # opaque modifier
404
+ return self._is_opaque
405
+ elif self.type in self.NONEOPAQUETYPES: # non-opaque modifier
406
+ return False
407
+ else: # it's a geometry or it has a void modifier; check the modifier
408
+ return self.modifier.is_void or self.modifier.is_opaque
409
+
410
+ @is_opaque.setter
411
+ def is_opaque(self, is_opaque):
412
+ self._is_opaque = bool(is_opaque)
413
+
414
+ @property
415
+ def is_void(self):
416
+ """Only true for a void."""
417
+ return False
418
+
419
+ def _update_values(self):
420
+ """update value dictionaries.
421
+
422
+ _update_values must be implemented in each subclass.
423
+ """
424
+ pass
425
+
426
+ def add_dependent(self, dep):
427
+ """Add dependent."""
428
+ assert isinstance(dep, Primitive), \
429
+ '{} is not a valid dependent type'.format(type(dep))
430
+ self._dependencies.append(dep)
431
+
432
+ @staticmethod
433
+ def _to_radiance(primitive, minimal=False):
434
+ """Return Radiance representation of primitive."""
435
+ header = "%s %s %s" % (primitive.modifier.identifier,
436
+ primitive.type, primitive.identifier)
437
+ output = [header]
438
+ for line_count in range(3):
439
+ try:
440
+ values = (str(v) for v in primitive.values[line_count])
441
+ except BaseException:
442
+ values = [] # line will be displayed as 0
443
+ else:
444
+ count = len(primitive.values[line_count])
445
+ line = '%d %s' % (count, ' '.join(values).rstrip()) if count else '0'
446
+ output.append(line)
447
+
448
+ return ' '.join(output) if minimal else '\n'.join(output)
449
+
450
+ def to_radiance(self, minimal=False, include_modifier=True,
451
+ include_dependencies=True):
452
+ """Return full radiance definition.
453
+
454
+ Args:
455
+ minimal: Boolean to note whether the radiance string should be written
456
+ in a minimal format (with spaces instead of line breaks). Default: False.
457
+ include_modifier: Boolean to note whether the modifier of this primitive
458
+ should be included in the string. Default: True.
459
+ include_dependencies: Boolean to note whether the dependencies of this
460
+ primitive should be included in the string. Default: True.
461
+ """
462
+ output = []
463
+
464
+ if include_dependencies:
465
+ for dep in self.dependencies:
466
+ if isinstance(dep, Void):
467
+ continue
468
+ output.append(self._to_radiance(dep, minimal))
469
+
470
+ if include_modifier and not self.modifier.is_void:
471
+ output.append(self._to_radiance(self.modifier, minimal))
472
+ output.append(self._to_radiance(self, minimal))
473
+
474
+ return '\n'.join(output)
475
+
476
+ def to_dict(self):
477
+ """Translate this object to a dictionary."""
478
+ base = {
479
+ "modifier": self.modifier.to_dict(),
480
+ "type": self.type,
481
+ "identifier": self.identifier,
482
+ "values": self.values,
483
+ "dependencies": [dep.to_dict() for dep in self.dependencies]
484
+ }
485
+ if self._display_name is not None:
486
+ base['display_name'] = self.display_name
487
+ return base
488
+
489
+ def duplicate(self):
490
+ """Get a copy of this object."""
491
+ return self.__copy__()
492
+
493
+ @staticmethod
494
+ def filter_dict_input(input_dict):
495
+ """Filter a dictionary of a Primitive to get modifier and dependency objects."""
496
+ try: # see if the mutil module has already been imported
497
+ mutil
498
+ except NameError:
499
+ # import the module here (instead of at top) to avoid a circular import
500
+ import honeybee_radiance.mutil as mutil # imports all modifiers classes
501
+
502
+ # try to get modifier
503
+ if 'modifier' not in input_dict or input_dict['modifier'] is None or \
504
+ input_dict['modifier'] == 'void':
505
+ modifier = VOID
506
+ else:
507
+ modifier = mutil.dict_to_modifier(input_dict['modifier'])
508
+
509
+ if 'dependencies' not in input_dict:
510
+ dependencies = []
511
+ else:
512
+ dependencies = [
513
+ mutil.dict_to_modifier(dep) for dep in input_dict['dependencies']
514
+ ]
515
+
516
+ return modifier, dependencies
517
+
518
+ def __key(self):
519
+ """A tuple based on the object properties, useful for hashing."""
520
+ return (hash(self.modifier), self.type, self.identifier) + \
521
+ tuple(hash(tuple(vals)) for vals in self.values) + \
522
+ tuple(hash(dep) for dep in self._dependencies)
523
+
524
+ def __hash__(self):
525
+ return hash(self.__key())
526
+
527
+ def __eq__(self, other):
528
+ return isinstance(other, self.__class__) and \
529
+ self.__key() == other.__key()
530
+
531
+ def __ne__(self, other):
532
+ return not self.__eq__(other)
533
+
534
+ def __copy__(self):
535
+ mod, depend = self._dup_mod_and_depend()
536
+ values_copy = [line[:] for line in self._values] # copy each line
537
+ new_obj = self.__class__(
538
+ self.identifier, mod, values_copy, self._is_opaque, depend)
539
+ new_obj._display_name = self._display_name
540
+ return new_obj
541
+
542
+ def _dup_mod_and_depend(self):
543
+ """Duplicate this object's modifer and its dependencies."""
544
+ mod = None if isinstance(self._modifier, Void) else self._modifier.duplicate()
545
+ dependencies = [dep.duplicate() for dep in self._dependencies]
546
+ return mod, dependencies
547
+
548
+ def ToString(self):
549
+ """Overwrite .NET ToString."""
550
+ return self.__repr__()
551
+
552
+ def __repr__(self):
553
+ """Return primitive definition."""
554
+ return self.to_radiance()
@@ -0,0 +1 @@
1
+ """honeybee-radiance properties."""