honeybee-core 1.64.12__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.
Files changed (48) hide show
  1. honeybee/__init__.py +23 -0
  2. honeybee/__main__.py +4 -0
  3. honeybee/_base.py +331 -0
  4. honeybee/_basewithshade.py +310 -0
  5. honeybee/_lockable.py +99 -0
  6. honeybee/altnumber.py +47 -0
  7. honeybee/aperture.py +997 -0
  8. honeybee/boundarycondition.py +358 -0
  9. honeybee/checkdup.py +173 -0
  10. honeybee/cli/__init__.py +118 -0
  11. honeybee/cli/compare.py +132 -0
  12. honeybee/cli/create.py +265 -0
  13. honeybee/cli/edit.py +559 -0
  14. honeybee/cli/lib.py +103 -0
  15. honeybee/cli/setconfig.py +43 -0
  16. honeybee/cli/validate.py +224 -0
  17. honeybee/colorobj.py +363 -0
  18. honeybee/config.json +5 -0
  19. honeybee/config.py +347 -0
  20. honeybee/dictutil.py +54 -0
  21. honeybee/door.py +746 -0
  22. honeybee/extensionutil.py +208 -0
  23. honeybee/face.py +2360 -0
  24. honeybee/facetype.py +153 -0
  25. honeybee/logutil.py +79 -0
  26. honeybee/model.py +4272 -0
  27. honeybee/orientation.py +132 -0
  28. honeybee/properties.py +845 -0
  29. honeybee/room.py +3485 -0
  30. honeybee/search.py +107 -0
  31. honeybee/shade.py +514 -0
  32. honeybee/shademesh.py +362 -0
  33. honeybee/typing.py +498 -0
  34. honeybee/units.py +88 -0
  35. honeybee/writer/__init__.py +7 -0
  36. honeybee/writer/aperture.py +6 -0
  37. honeybee/writer/door.py +6 -0
  38. honeybee/writer/face.py +6 -0
  39. honeybee/writer/model.py +6 -0
  40. honeybee/writer/room.py +6 -0
  41. honeybee/writer/shade.py +6 -0
  42. honeybee/writer/shademesh.py +6 -0
  43. honeybee_core-1.64.12.dist-info/METADATA +94 -0
  44. honeybee_core-1.64.12.dist-info/RECORD +48 -0
  45. honeybee_core-1.64.12.dist-info/WHEEL +5 -0
  46. honeybee_core-1.64.12.dist-info/entry_points.txt +2 -0
  47. honeybee_core-1.64.12.dist-info/licenses/LICENSE +661 -0
  48. honeybee_core-1.64.12.dist-info/top_level.txt +1 -0
@@ -0,0 +1,43 @@
1
+ """Commands to set honeybee-core configurations."""
2
+ import click
3
+ import sys
4
+ import logging
5
+ import json
6
+
7
+ from honeybee.config import folders
8
+
9
+ _logger = logging.getLogger(__name__)
10
+
11
+
12
+ @click.group(help='Commands to set honeybee-core configurations.')
13
+ def set_config():
14
+ pass
15
+
16
+
17
+ @set_config.command('default-simulation-folder')
18
+ @click.argument('folder-path', required=False, type=click.Path(
19
+ exists=True, file_okay=False, dir_okay=True, resolve_path=True))
20
+ def default_simulation_folder(folder_path):
21
+ """Set the default-simulation-folder configuration variable.
22
+
23
+ \b
24
+ Args:
25
+ folder_path: Path to a folder to be set as the default-simulation-folder.
26
+ If unspecified, the default-simulation-folder will be set back to
27
+ the default.
28
+ """
29
+ try:
30
+ config_file = folders.config_file
31
+ with open(config_file) as inf:
32
+ data = json.load(inf)
33
+ data['default_simulation_folder'] = folder_path if folder_path is not None else ''
34
+ with open(config_file, 'w') as fp:
35
+ json.dump(data, fp, indent=4)
36
+ msg_end = 'reset to default' if folder_path is None \
37
+ else 'set to: {}'.format(folder_path)
38
+ print('default-simulation-folder successfully {}.'.format(msg_end))
39
+ except Exception as e:
40
+ _logger.exception('Failed to set default-simulation-folder.\n{}'.format(e))
41
+ sys.exit(1)
42
+ else:
43
+ sys.exit(0)
@@ -0,0 +1,224 @@
1
+ """honeybee validation commands."""
2
+ import sys
3
+ import logging
4
+ import click
5
+
6
+ from ladybug.commandutil import process_content_to_output
7
+ from honeybee.model import Model
8
+
9
+ _logger = logging.getLogger(__name__)
10
+
11
+
12
+ @click.group(help='Commands for validating Honeybee objects.')
13
+ def validate():
14
+ pass
15
+
16
+
17
+ @validate.command('model')
18
+ @click.argument('model-file', type=click.Path(
19
+ exists=True, file_okay=True, dir_okay=False, resolve_path=True))
20
+ @click.option(
21
+ '--extension', '-e', help='Text for the name of the extension to be checked. '
22
+ 'The value input is case-insensitive such that "radiance" and "Radiance" will '
23
+ 'both result in the model being checked for validity with honeybee-radiance. '
24
+ 'This value can also be set to "Generic" in order to run checks for all installed '
25
+ 'extensions. Using "Generic" will run all except the most limiting of checks '
26
+ '(eg. the DOE2 lack of support for courtyards) with the goal of producing a model '
27
+ 'that can be exported to multiple engines (albeit with a little extra '
28
+ 'postprocessing for particularly limited engines). Some common honeybee extension '
29
+ 'names that can be input here include: Radiance, EnergyPlus, DOE2, IES, IDAICE',
30
+ type=str, default='Generic', show_default=True)
31
+ @click.option(
32
+ '--plain-text/--json', ' /-j', help='Flag to note whether the output validation '
33
+ 'report should be formatted as a JSON object instead of plain text. If set to JSON, '
34
+ 'the output object will contain several attributes. The "honeybee_core" and '
35
+ '"honeybee_schema" attributes will note the versions of these libraries used in '
36
+ 'the validation process. An attribute called "fatal_error" is a text string '
37
+ 'containing an exception if the Model failed to serialize and will be an empty '
38
+ 'string if serialization was successful. An attribute called "errors" will '
39
+ 'contain a list of JSON objects for each invalid issue found in the model. A '
40
+ 'boolean attribute called "valid" will note whether the Model is valid or not.',
41
+ default=True, show_default=True)
42
+ @click.option(
43
+ '--room-overlaps', 'room_overlaps', flag_value='True',
44
+ help='Deprecated flag used to check room collisions. '
45
+ 'Use `honeybee validate room-collisions` instead.')
46
+ @click.option(
47
+ '--output-file', '-f', help='Optional file to output the full report '
48
+ 'of the validation. By default it will be printed out to stdout',
49
+ type=click.File('w'), default='-')
50
+ def validate_model_cli(model_file, extension, plain_text, room_overlaps, output_file):
51
+ """Validate all properties of a Model file against Honeybee schema.
52
+
53
+ This includes checking basic compliance with the 5 rules of honeybee geometry
54
+ as well as checks for all extension attributes. The 5 rules of honeybee geometry
55
+ are as follows.
56
+
57
+ 1. All Face3Ds must be planar to within the model tolerance.
58
+
59
+ 2. All Face3Ds must NOT be self-intersecting (like a bowtie shape)
60
+
61
+ 3. All children sub-faces (Apertures and Doors) must be co-planar with
62
+ their parent Face and lie completely within its boundary.
63
+
64
+ 4. All adjacent object pairs (faces and sub-faces with a Surface boundary
65
+ condition) must have matching areas.
66
+
67
+ 5. All Room volumes must be closed solids.
68
+
69
+ \b
70
+ Args:
71
+ model_file: Full path to a Model JSON file.
72
+ """
73
+ try:
74
+ json = not plain_text
75
+ if room_overlaps == 'True':
76
+ print('--room-overlaps option is deprecated. '
77
+ 'Use `honeybee validate room-collisions` instead.')
78
+ validate_room_collisions(model_file, json, output_file)
79
+ else:
80
+ validate_model(model_file, extension, json, output_file)
81
+ except Exception as e:
82
+ _logger.exception('Model validation failed.\n{}'.format(e))
83
+ sys.exit(1)
84
+ else:
85
+ sys.exit(0)
86
+
87
+
88
+ def validate_model(model_file, extension='Generic', json=False, output_file=None,
89
+ plain_text=True):
90
+ """Validate all properties of a Model file against the Honeybee schema.
91
+
92
+ This includes checking basic compliance with the 5 rules of honeybee geometry
93
+ as well as checks for all extension attributes.
94
+
95
+ Args:
96
+ model_file: Full path to a Honeybee Model file.
97
+ extension_name: Text for the name of the extension to be checked.
98
+ The value input here is case-insensitive such that "radiance"
99
+ and "Radiance" will both result in the model being checked for
100
+ validity with honeybee-radiance. This value can also be set to
101
+ "Generic" in order to run checks for all installed extensions.
102
+ Using "Generic" will run all except the most limiting of checks
103
+ (eg. DOE2's lack of support for courtyards) with the goal of
104
+ producing a model that is export-able to multiple engines (albeit
105
+ with a little extra postprocessing for particularly limited engines).
106
+ Some common dragonfly extension names that can be input here if they
107
+ are installed include:
108
+
109
+ * Radiance
110
+ * EnergyPlus
111
+ * DOE2
112
+ * IES
113
+ * IDAICE
114
+
115
+ json: Boolean to note whether the output validation report should be
116
+ formatted as a JSON object instead of plain text. (Default: False).
117
+ output_file: Optional file to output the full report of the validation.
118
+ If None, the string will simply be returned from this method.
119
+ """
120
+ report = Model.validate(model_file, 'check_for_extension', [extension], json)
121
+ return process_content_to_output(report, output_file)
122
+
123
+
124
+ @validate.command('rooms-solid')
125
+ @click.argument('model-file', type=click.Path(
126
+ exists=True, file_okay=True, dir_okay=False, resolve_path=True))
127
+ @click.option(
128
+ '--plain-text/--json', ' /-j', help='Flag to note whether the output validation '
129
+ 'report should be formatted as a JSON object instead of plain text. If set to JSON, '
130
+ 'the output object will contain several attributes. An attribute called '
131
+ '"fatal_error" is a text string containing an exception if the Model failed to '
132
+ 'serialize and will be an empty string if serialization was successful. An '
133
+ 'attribute called "errors" will contain a list of JSON objects for each '
134
+ 'invalid issue. A boolean attribute called "valid" will note whether the Model '
135
+ 'is valid or not.',
136
+ default=True, show_default=True)
137
+ @click.option(
138
+ '--output-file', '-f', help='Optional file to output the full report '
139
+ 'of the validation. By default it will be printed out to stdout.',
140
+ type=click.File('w'), default='-')
141
+ def validate_rooms_solid_cli(model_file, plain_text, output_file):
142
+ """Validate whether all Room volumes in a model are solid.
143
+
144
+ The returned result can include a list of all naked and non-manifold edges
145
+ preventing closed room volumes when --json is used. This is helpful for visually
146
+ identifying issues in geometry that are preventing the room volume from
147
+ validating as closed.
148
+
149
+ \b
150
+ Args:
151
+ model_file: Full path to a Honeybee Model file.
152
+ """
153
+ try:
154
+ json = not plain_text
155
+ validate_rooms_solid(model_file, json, output_file)
156
+ except Exception as e:
157
+ _logger.exception('Model room volume validation failed.\n{}'.format(e))
158
+ sys.exit(1)
159
+ else:
160
+ sys.exit(0)
161
+
162
+
163
+ def validate_rooms_solid(model_file, json=False, output_file=None, plain_text=True):
164
+ """Get a list of all naked and non-manifold edges preventing closed room volumes.
165
+
166
+ This is helpful for visually identifying issues in geometry that are preventing
167
+ the room volume from reading as closed.
168
+
169
+ Args:
170
+ model_file: Full path to a Honeybee Model file.
171
+ json: Boolean to note whether the output validation report should be
172
+ formatted as a JSON object instead of plain text. (Default: False).
173
+ output_file: Optional file to output the full report of the validation.
174
+ If None, the string will simply be returned from this method.
175
+ """
176
+ report = Model.validate(model_file, 'check_rooms_solid', json_output=json)
177
+ return process_content_to_output(report, output_file)
178
+
179
+
180
+ @validate.command('room-collisions')
181
+ @click.argument('model-file', type=click.Path(
182
+ exists=True, file_okay=True, dir_okay=False, resolve_path=True))
183
+ @click.option(
184
+ '--plain-text/--json', ' /-j', help='Flag to note whether the output validation '
185
+ 'report should be formatted as a JSON object instead of plain text. If set to JSON, '
186
+ 'the output object will contain several attributes. An attribute called '
187
+ '"fatal_error" is a text string containing an exception if the Model failed to '
188
+ 'serialize and will be an empty string if serialization was successful. An '
189
+ 'attribute called "errors" will contain a list of JSON objects for each '
190
+ 'invalid issue. A boolean attribute called "valid" will note whether the Model '
191
+ 'is valid or not.', default=True, show_default=True)
192
+ @click.option(
193
+ '--output-file', '-f', help='Optional file to output the full report '
194
+ 'of the validation. By default it will be printed out to stdout.',
195
+ type=click.File('w'), default='-')
196
+ def validate_room_collisions_cli(model_file, plain_text, output_file):
197
+ """Validate whether Room collide with one another beyond the model tolerance.
198
+
199
+ \b
200
+ Args:
201
+ model_file: Full path to a Honeybee Model file.
202
+ """
203
+ try:
204
+ json = not plain_text
205
+ validate_room_collisions(model_file, json, output_file)
206
+ except Exception as e:
207
+ _logger.exception('Model room volume validation failed.\n{}'.format(e))
208
+ sys.exit(1)
209
+ else:
210
+ sys.exit(0)
211
+
212
+
213
+ def validate_room_collisions(model_file, json=False, output_file=None, plain_text=True):
214
+ """Validate whether Room collide with one another beyond the model tolerance.
215
+
216
+ Args:
217
+ model_file: Full path to a Honeybee Model file.
218
+ json: Boolean to note whether the output validation report should be
219
+ formatted as a JSON object instead of plain text. (Default: False).
220
+ output_file: Optional file to output the full report of the validation.
221
+ If None, the string will simply be returned from this method.
222
+ """
223
+ report = Model.validate(model_file, 'check_room_volume_collisions', json_output=json)
224
+ return process_content_to_output(report, output_file)
honeybee/colorobj.py ADDED
@@ -0,0 +1,363 @@
1
+ # coding=utf-8
2
+ """Module for coloring geometry with attributes."""
3
+ from __future__ import division
4
+
5
+ from .shademesh import ShadeMesh
6
+ from .shade import Shade
7
+ from .door import Door
8
+ from .aperture import Aperture
9
+ from .face import Face
10
+ from .room import Room
11
+ from .facetype import Floor
12
+ from .search import get_attr_nested
13
+
14
+ from ladybug.graphic import GraphicContainer
15
+ from ladybug.legend import LegendParameters, LegendParametersCategorized
16
+ from ladybug_geometry.geometry3d.pointvector import Point3D
17
+
18
+
19
+ class _ColorObject(object):
20
+ """Base class for visualization objects.
21
+
22
+ Properties:
23
+ * legend_parameters
24
+ * attr_name
25
+ * attr_name_end
26
+ * attributes
27
+ * attributes_unique
28
+ * attributes_original
29
+ * min_point
30
+ * max_point
31
+ * graphic_container
32
+ """
33
+ __slots__ = ('_attr_name', '_legend_parameters', '_attr_name_end',
34
+ '_attributes', '_attributes_unique', '_attributes_original',
35
+ '_min_point', '_max_point')
36
+
37
+ def __init__(self, legend_parameters=None):
38
+ """Initialize ColorObject."""
39
+ # assign the legend parameters of this object
40
+ self.legend_parameters = legend_parameters
41
+
42
+ self._attr_name = None
43
+ self._attr_name_end = None
44
+ self._attributes = None
45
+ self._attributes_unique = None
46
+ self._attributes_original = None
47
+ self._min_point = None
48
+ self._max_point = None
49
+
50
+ @property
51
+ def legend_parameters(self):
52
+ """Get or set the legend parameters."""
53
+ return self._legend_parameters
54
+
55
+ @legend_parameters.setter
56
+ def legend_parameters(self, value):
57
+ if value is not None:
58
+ assert isinstance(value, LegendParameters) and not \
59
+ isinstance(value, LegendParametersCategorized), \
60
+ 'Expected LegendParameters. Got {}.'.format(type(value))
61
+ self._legend_parameters = value
62
+ else:
63
+ self._legend_parameters = LegendParameters()
64
+
65
+ @property
66
+ def attr_name(self):
67
+ """Get a text string of an attribute that the input objects should have."""
68
+ return self._attr_name
69
+
70
+ @property
71
+ def attr_name_end(self):
72
+ """Get text for the last attribute in the attr_name.
73
+
74
+ Useful when attr_name is nested.
75
+ """
76
+ return self._attr_name_end
77
+
78
+ @property
79
+ def attributes(self):
80
+ """Get a tuple of text for the attributes assigned to the objects.
81
+
82
+ If the input attr_name is a valid attribute for the object but None is
83
+ assigned, the output will be 'None'. If the input attr_name is not valid
84
+ for the input object, 'N/A' will be returned.
85
+ """
86
+ return self._attributes
87
+
88
+ @property
89
+ def attributes_unique(self):
90
+ """Get a tuple of text for the unique attributes assigned to the objects."""
91
+ return self._attributes_unique
92
+
93
+ @property
94
+ def attributes_original(self):
95
+ """Get a tuple of objects for the attributes assigned to the objects.
96
+
97
+ These will follow the original object typing of the attribute and won't
98
+ be strings like the attributes.
99
+ """
100
+ return self._attributes_original
101
+
102
+ @property
103
+ def min_point(self):
104
+ """Get a Point3D for the minimum of the box around the objects."""
105
+ return self._min_point
106
+
107
+ @property
108
+ def max_point(self):
109
+ """Get a Point3D for the maximum of the box around the objects."""
110
+ return self._max_point
111
+
112
+ @property
113
+ def graphic_container(self):
114
+ """Get a ladybug GraphicContainer that relates to this object.
115
+
116
+ The GraphicContainer possesses almost all things needed to visualize the
117
+ ColorRooms object including the legend, value_colors, etc.
118
+ """
119
+ # produce a range of values from the collected attributes
120
+ attr_dict = {i: val for i, val in enumerate(self._attributes_unique)}
121
+ attr_dict_rev = {val: i for i, val in attr_dict.items()}
122
+ try:
123
+ values = tuple(attr_dict_rev[r_attr] for r_attr in self._attributes)
124
+ except KeyError: # possibly caused by float cast to -0.0
125
+ values = []
126
+ for r_attr in self._attributes:
127
+ if r_attr == '-0.0':
128
+ values.append(attr_dict_rev['0.0'])
129
+ else:
130
+ values.append(attr_dict_rev[r_attr])
131
+
132
+ # produce legend parameters with an ordinal dict for the attributes
133
+ l_par = self.legend_parameters.duplicate()
134
+ if l_par.is_segment_count_default:
135
+ l_par.segment_count = len(self._attributes_unique)
136
+ l_par.ordinal_dictionary = attr_dict
137
+ if l_par.is_title_default:
138
+ l_par.title = self.attr_name_end.replace('_', ' ').title()
139
+
140
+ return GraphicContainer(values, self.min_point, self.max_point, l_par)
141
+
142
+ def _process_attribute_name(self, attr_name):
143
+ """Process the attribute name and assign it to this object."""
144
+ self._attr_name = str(attr_name)
145
+ at_split = self._attr_name.split('.')
146
+ if len(at_split) == 1:
147
+ self._attr_name_end = at_split[-1]
148
+ elif at_split[-1] == 'display_name':
149
+ self._attr_name_end = at_split[-2]
150
+ elif at_split[-1] == '__name__' and at_split[-2] == '__class__':
151
+ self._attr_name_end = at_split[-3]
152
+ else:
153
+ self._attr_name_end = at_split[-1]
154
+
155
+ def _process_attributes(self, hb_objs):
156
+ """Process the attributes of honeybee objects."""
157
+ nd = self.legend_parameters.decimal_count
158
+ attributes = [get_attr_nested(obj, self._attr_name, nd) for obj in hb_objs]
159
+ attributes_unique = set(attributes)
160
+ float_attr = [atr for atr in attributes_unique if isinstance(atr, float)]
161
+ str_attr = [atr for atr in attributes_unique if isinstance(atr, str)]
162
+ float_attr.sort()
163
+ str_attr.sort()
164
+ self._attributes = tuple(str(val) for val in attributes)
165
+ self._attributes_unique = tuple(str_attr) + tuple(str(val) for val in float_attr)
166
+ self._attributes_original = \
167
+ tuple(get_attr_nested(obj, self._attr_name, cast_to_str=False)
168
+ for obj in hb_objs)
169
+
170
+ def _calculate_min_max(self, hb_objs):
171
+ """Calculate maximum and minimum Point3D for a set of rooms."""
172
+ st_rm_min, st_rm_max = hb_objs[0].geometry.min, hb_objs[0].geometry.max
173
+ min_pt = [st_rm_min.x, st_rm_min.y, st_rm_min.z]
174
+ max_pt = [st_rm_max.x, st_rm_max.y, st_rm_max.z]
175
+
176
+ for room in hb_objs[1:]:
177
+ rm_min, rm_max = room.geometry.min, room.geometry.max
178
+ if rm_min.x < min_pt[0]:
179
+ min_pt[0] = rm_min.x
180
+ if rm_min.y < min_pt[1]:
181
+ min_pt[1] = rm_min.y
182
+ if rm_min.z < min_pt[2]:
183
+ min_pt[2] = rm_min.z
184
+ if rm_max.x > max_pt[0]:
185
+ max_pt[0] = rm_max.x
186
+ if rm_max.y > max_pt[1]:
187
+ max_pt[1] = rm_max.y
188
+ if rm_max.z > max_pt[2]:
189
+ max_pt[2] = rm_max.z
190
+
191
+ self._min_point = Point3D(min_pt[0], min_pt[1], min_pt[2])
192
+ self._max_point = Point3D(max_pt[0], max_pt[1], max_pt[2])
193
+
194
+ def ToString(self):
195
+ """Overwrite .NET ToString."""
196
+ return self.__repr__()
197
+
198
+
199
+ class ColorRoom(_ColorObject):
200
+ """Object for visualizing room-level attributes.
201
+
202
+ Args:
203
+ rooms: An array of honeybee Rooms, which will be colored with the attribute.
204
+ attr_name: A text string of an attribute that the input rooms should have.
205
+ This can have '.' that separate the nested attributes from one another.
206
+ For example, 'properties.energy.program_type'.
207
+ legend_parameters: An optional LegendParameter object to change the display
208
+ of the ColorRoom (Default: None).
209
+
210
+ Properties:
211
+ * rooms
212
+ * attr_name
213
+ * legend_parameters
214
+ * attr_name_end
215
+ * attributes
216
+ * attributes_unique
217
+ * attributes_original
218
+ * floor_faces
219
+ * graphic_container
220
+ * min_point
221
+ * max_point
222
+ """
223
+ __slots__ = ('_rooms',)
224
+
225
+ def __init__(self, rooms, attr_name, legend_parameters=None):
226
+ """Initialize ColorRoom."""
227
+ try: # check the input rooms
228
+ rooms = tuple(rooms)
229
+ except TypeError:
230
+ raise TypeError('Input rooms must be an array. Got {}.'.format(type(rooms)))
231
+ assert len(rooms) > 0, 'ColorRooms must have at least one room.'
232
+ for room in rooms:
233
+ assert isinstance(room, Room), 'Expected honeybee Room for ' \
234
+ 'ColorRoom rooms. Got {}.'.format(type(room))
235
+ self._rooms = rooms
236
+ self._calculate_min_max(rooms)
237
+
238
+ # assign the legend parameters of this object
239
+ self.legend_parameters = legend_parameters
240
+
241
+ # get the attributes of the input rooms
242
+ self._process_attribute_name(attr_name)
243
+ self._process_attributes(rooms)
244
+
245
+ @property
246
+ def rooms(self):
247
+ """Get a tuple of honeybee Rooms assigned to this object."""
248
+ return self._rooms
249
+
250
+ @property
251
+ def floor_faces(self):
252
+ """Get a nested array with each sub-array having all floor Face3Ds of each room.
253
+
254
+ This is useful for producing visualizations since coloring floors or rooms
255
+ instead of the entire room solid allows more of the model to be viewed at once.
256
+ """
257
+ flr_faces = []
258
+ for room in self.rooms:
259
+ flr_faces.append(
260
+ [face.geometry for face in room.faces if isinstance(face.type, Floor)])
261
+ return flr_faces
262
+
263
+ def __repr__(self):
264
+ """Color Room representation."""
265
+ return 'Color Room:\n{} Rooms\n{}'.format(len(self.rooms), self.attr_name_end)
266
+
267
+
268
+ class ColorFace(_ColorObject):
269
+ """Object for visualizing face and sub-face level attributes.
270
+
271
+ Args:
272
+ faces: An array of honeybee Faces, Apertures, Doors, Shades and/or ShadeMeshes
273
+ which will be colored with their attributes.
274
+ attr_name: A text string of an attribute that the input faces should have.
275
+ This can have '.' that separate the nested attributes from one another.
276
+ For example, 'properties.energy.construction'.
277
+ legend_parameters: An optional LegendParameter object to change the display
278
+ of the ColorFace (Default: None).
279
+
280
+ Properties:
281
+ * faces
282
+ * attr_name
283
+ * legend_parameters
284
+ * flat_faces
285
+ * flat_geometry
286
+ * attr_name_end
287
+ * attributes
288
+ * attributes_unique
289
+ * attributes_original
290
+ * floor_faces
291
+ * graphic_container
292
+ * min_point
293
+ * max_point
294
+ """
295
+ __slots__ = ('_faces', '_flat_faces', '_flat_geometry')
296
+
297
+ def __init__(self, faces, attr_name, legend_parameters=None):
298
+ """Initialize ColorFace."""
299
+ try: # check the input faces
300
+ faces = tuple(faces)
301
+ except TypeError:
302
+ raise TypeError('Input faces must be an array. Got {}.'.format(type(faces)))
303
+ assert len(faces) > 0, 'ColorFaces must have at least one face.'
304
+ flat_f = []
305
+ for face in faces:
306
+ if isinstance(face, Face):
307
+ flat_f.append(face)
308
+ flat_f.extend(face.shades)
309
+ for ap in face.apertures:
310
+ flat_f.append(ap)
311
+ flat_f.extend(ap.shades)
312
+ for dr in face.doors:
313
+ flat_f.append(dr)
314
+ flat_f.extend(dr.shades)
315
+ elif isinstance(face, (Aperture, Door)):
316
+ flat_f.append(face)
317
+ flat_f.extend(face.shades)
318
+ elif isinstance(face, Shade):
319
+ flat_f.append(face)
320
+ elif isinstance(face, ShadeMesh):
321
+ flat_f.append(face)
322
+ else:
323
+ raise ValueError(
324
+ 'Expected honeybee Face, Aperture, Door, Shade or ShadeMesh '
325
+ 'for ColorFaces. Got {}.'.format(type(face)))
326
+ self._faces = faces
327
+ self._flat_faces = tuple(flat_f)
328
+ self._flat_geometry = tuple(face.geometry if not isinstance(face, Face)
329
+ else face.punched_geometry for face in flat_f)
330
+ self._calculate_min_max(faces)
331
+
332
+ # assign the legend parameters of this object
333
+ self.legend_parameters = legend_parameters
334
+
335
+ # get the attributes of the input faces
336
+ self._process_attribute_name(attr_name)
337
+ self._process_attributes(flat_f)
338
+
339
+ @property
340
+ def faces(self):
341
+ """Get the honeybee Faces, Apertures, Doors and Shades assigned to this object.
342
+ """
343
+ return self._faces
344
+
345
+ @property
346
+ def flat_faces(self):
347
+ """Get non-nested honeybee Faces, Apertures, Doors and Shades on this object.
348
+
349
+ The objects here align with the attributes and graphic_container colors.
350
+ """
351
+ return self._flat_faces
352
+
353
+ @property
354
+ def flat_geometry(self):
355
+ """Get non-nested array of faces on this object.
356
+
357
+ The geometries here align with the attributes and graphic_container colors.
358
+ """
359
+ return self._flat_geometry
360
+
361
+ def __repr__(self):
362
+ """Color Room representation."""
363
+ return 'Color Faces:\n{} Faces\n{}'.format(len(self.faces), self.attr_name_end)
honeybee/config.json ADDED
@@ -0,0 +1,5 @@
1
+ {
2
+ "__comment__": "Add full paths to folders (eg. C:/sim_folder, /usr/local/sim_folder).",
3
+ "default_simulation_folder": "",
4
+ "default_standards_folder": ""
5
+ }