dragonfly-display 0.3.7__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.
@@ -0,0 +1,2 @@
1
+ """dragonfly-display library."""
2
+ import dragonfly_display._extend_dragonfly
@@ -0,0 +1,4 @@
1
+ from dragonfly_display.cli import display
2
+
3
+ if __name__ == '__main__':
4
+ display()
@@ -0,0 +1,10 @@
1
+ # coding=utf-8
2
+ # import the core dragonfly modules
3
+ from dragonfly.model import Model
4
+
5
+ # import the extension functions
6
+ from .model import model_to_vis_set, model_comparison_to_vis_set
7
+
8
+ # inject the methods onto the classes
9
+ Model.to_vis_set = model_to_vis_set
10
+ Model.to_vis_set_comparison = model_comparison_to_vis_set
@@ -0,0 +1,537 @@
1
+ """dragonfly-display commands."""
2
+ import click
3
+ import sys
4
+ import os
5
+ import logging
6
+ import json
7
+ import base64
8
+ import pickle
9
+ import tempfile
10
+ import uuid
11
+
12
+ from ladybug.color import Color
13
+ from honeybee_display.attr import FaceAttribute, RoomAttribute
14
+
15
+ from dragonfly.model import Model
16
+ from dragonfly.cli import main
17
+
18
+
19
+ _logger = logging.getLogger(__name__)
20
+
21
+
22
+ # command group for all display extension commands.
23
+ @click.group(help='dragonfly display commands.')
24
+ @click.version_option()
25
+ def display():
26
+ pass
27
+
28
+
29
+ @display.command('model-to-vis')
30
+ @click.argument('model-file', type=click.Path(
31
+ exists=True, file_okay=True, dir_okay=False, resolve_path=True))
32
+ @click.option(
33
+ '--multiplier/--full-geometry', ' /-fg', help='Flag to note if the '
34
+ 'multipliers on each Building story should be passed along to the '
35
+ 'generated Honeybee Room objects or if full geometry objects should be '
36
+ 'written for each story in the building.', default=True, show_default=True)
37
+ @click.option(
38
+ '--plenum/--no-plenum', '-p/-np', help='Flag to indicate whether '
39
+ 'ceiling/floor plenum depths assigned to Room2Ds should generate '
40
+ 'distinct 3D Rooms in the translation.', default=True, show_default=True)
41
+ @click.option(
42
+ '--no-ceil-adjacency/--ceil-adjacency', ' /-a', help='Flag to indicate '
43
+ 'whether adjacencies should be solved between interior stories when '
44
+ 'Room2D floor and ceiling geometries are coplanar. This ensures '
45
+ 'that Surface boundary conditions are used instead of Adiabatic ones.',
46
+ default=True, show_default=True)
47
+ @click.option(
48
+ '--merge-method', help='Text to describe how the Room2Ds should '
49
+ 'be merged into individual Rooms during the translation. Specifying a '
50
+ 'value here can be an effective way to reduce the number of Room '
51
+ 'volumes in the resulting 3D Honeybee Model and, ultimately, yield '
52
+ 'a faster simulation time in the destination engine with fewer results '
53
+ 'to manage. Choose from: None, Zones, PlenumZones, Stories, PlenumStories.',
54
+ type=str, default='None', show_default=True)
55
+ @click.option(
56
+ '--color-by', '-c', help='Text for the property that dictates the colors of '
57
+ 'the Model geometry. Choose from: type, boundary_condition, none. '
58
+ 'If none, only a wireframe of the Model will be generated (assuming the '
59
+ '--exclude-wireframe option is not used). None is useful when the primary '
60
+ 'purpose of the visualization is to display results in relation to the Model '
61
+ 'geometry or display some room_attr or face_attr as an AnalysisGeometry '
62
+ 'or Text labels.', type=str, default='type', show_default=True)
63
+ @click.option(
64
+ '--wireframe/--exclude-wireframe', ' /-xw', help='Flag to note whether a '
65
+ 'ContextGeometry dedicated to the Model Wireframe (in DisplayLineSegment3D) should '
66
+ 'be included in the output VisualizationSet.', default=True, show_default=True)
67
+ @click.option(
68
+ '--mesh/--faces', help='Flag to note whether the colored model geometries should '
69
+ 'be represented with DisplayMesh3D objects instead of DisplayFace3D objects. '
70
+ 'Meshes can usually be rendered faster and they scale well for large models '
71
+ 'but all geometry is triangulated (meaning that their wireframe in certain '
72
+ 'platforms might not appear ideal).', default=True, show_default=True)
73
+ @click.option(
74
+ '--show-color-by/--hide-color-by', ' /-hcb', help='Flag to note whether the '
75
+ 'color-by geometry should be hidden or shown by default. Hiding the color-by '
76
+ 'geometry is useful when the primary purpose of the visualization is to display '
77
+ 'grid-data or room/face attributes but it is still desirable to have the option '
78
+ 'to turn on the geometry.', default=True, show_default=True)
79
+ @click.option(
80
+ '--room-attr', '-r', help='An optional text string of an attribute that the Model '
81
+ 'Rooms have, which will be used to construct a visualization of this attribute '
82
+ 'in the resulting VisualizationSet. Multiple instances of this option can be passed '
83
+ 'and a separate VisualizationData will be added to the AnalysisGeometry that '
84
+ 'represents the attribute in the resulting VisualizationSet (or a separate '
85
+ 'ContextGeometry layer if --text-attr is True). Room attributes '
86
+ 'input here can have . that separates the nested attributes from '
87
+ 'one another. For example, properties.energy.program_type.',
88
+ type=click.STRING, multiple=True, default=None, show_default=True)
89
+ @click.option(
90
+ '--face-attr', '-f', help='An optional text string of an attribute that the Model '
91
+ 'Faces have, which will be used to construct a visualization of this attribute in '
92
+ 'the resulting VisualizationSet. Multiple instances of this option can be passed and'
93
+ ' a separate VisualizationData will be added to the AnalysisGeometry that '
94
+ 'represents the attribute in the resulting VisualizationSet (or a separate '
95
+ 'ContextGeometry layer if --text-attr is True). Face attributes '
96
+ 'input here can have . that separates the nested attributes from '
97
+ 'one another. For example, properties.energy.construction.',
98
+ type=click.STRING, multiple=True, default=None, show_default=True)
99
+ @click.option(
100
+ '--color-attr/--text-attr', help='Flag to note whether to note whether the '
101
+ 'input room-attr and face-attr should be expressed as a colored AnalysisGeometry '
102
+ 'or a ContextGeometry as text labels.', default=True, show_default=True)
103
+ @click.option(
104
+ '--grid-display-mode', '-m', help='Text that dictates how the ContextGeometry '
105
+ 'for Model SensorGrids should display in the resulting visualization. The Default '
106
+ 'option will draw sensor points whenever there is no grid_data_path and will not '
107
+ 'draw them at all when grid data is provided, assuming the AnalysisGeometry of '
108
+ 'the grids is sufficient. Choose from: Default, Points, Wireframe, Surface, '
109
+ 'SurfaceWithEdges, None.',
110
+ type=str, default='Default', show_default=True)
111
+ @click.option(
112
+ '--show-grid/--hide-grid', ' /-hg', help='Flag to note whether the SensorGrid '
113
+ 'ContextGeometry should be hidden or shown by default.',
114
+ default=True, show_default=True)
115
+ @click.option(
116
+ '--output-format', '-of', help='Text for the output format of the resulting '
117
+ 'VisualizationSet File (.vsf). Choose from: vsf, json, pkl, vtkjs, html. Note '
118
+ 'that both vsf and json refer to the the JSON version of the VisualizationSet '
119
+ 'file and the distinction between the two is only for help in coordinating file '
120
+ 'extensions (since both .vsf and .json can be acceptable). Also note that '
121
+ 'ladybug-vtk must be installed in order for the vtkjs or html options to be usable '
122
+ 'and the html format refers to a web page with the vtkjs file embedded within it.',
123
+ type=str, default='vsf', show_default=True)
124
+ @click.option(
125
+ '--output-file', help='Optional file to output the string of the visualization '
126
+ 'file contents. By default, it will be printed out to stdout.',
127
+ type=click.File('w'), default='-', show_default=True)
128
+ def model_to_vis_set_cli(
129
+ model_file, multiplier, plenum, no_ceil_adjacency, merge_method,
130
+ color_by, wireframe, mesh, show_color_by,
131
+ room_attr, face_attr, color_attr, grid_display_mode, show_grid,
132
+ output_format, output_file
133
+ ):
134
+ """Translate a Dragonfly Model file (.dfjson) to a VisualizationSet file (.vsf).
135
+
136
+ This command can also optionally translate the Dragonfly Model to a .vtkjs file,
137
+ which can be visualized in the open source Visual ToolKit (VTK) platform.
138
+
139
+ \b
140
+ Args:
141
+ model_file: Full path to a Dragonfly Model (DFJSON or DFpkl) file.
142
+ """
143
+ try:
144
+ # process all of the CLI input so that it can be passed to the function
145
+ full_geometry = not multiplier
146
+ no_plenum = not plenum
147
+ ceil_adjacency = not no_ceil_adjacency
148
+ exclude_wireframe = not wireframe
149
+ faces = not mesh
150
+ hide_color_by = not show_color_by
151
+ room_attrs = [] if len(room_attr) == 0 or room_attr[0] == '' else room_attr
152
+ face_attrs = [] if len(face_attr) == 0 or face_attr[0] == '' else face_attr
153
+ text_labels = not color_attr
154
+ hide_grid = not show_grid
155
+
156
+ # pass the input to the function in order to convert the model
157
+ model_to_vis_set(
158
+ model_file, full_geometry, no_plenum, ceil_adjacency, merge_method,
159
+ color_by, exclude_wireframe, faces, hide_color_by,
160
+ room_attrs, face_attrs, text_labels, grid_display_mode,
161
+ hide_grid, output_format, output_file)
162
+ except Exception as e:
163
+ _logger.exception('Failed to translate Model to VisualizationSet.\n{}'.format(e))
164
+ sys.exit(1)
165
+ else:
166
+ sys.exit(0)
167
+
168
+
169
+ def model_to_vis_set(
170
+ model_file, full_geometry=False, no_plenum=False, ceil_adjacency=False,
171
+ merge_method='Default', color_by='type', exclude_wireframe=False,
172
+ faces=False, hide_color_by=False,
173
+ room_attr=(), face_attr=(), text_attr=False, grid_display_mode='Default',
174
+ hide_grid=False, output_format='vsf', output_file=None,
175
+ multiplier=True, plenum=True, no_ceil_adjacency=True, wireframe=True, mesh=True,
176
+ show_color_by=True, color_attr=True, show_grid=True
177
+ ):
178
+ """Translate a Dragonfly Model file (.dfjson) to a VisualizationSet file (.vsf).
179
+
180
+ This function can also optionally translate the Dragonfly Model to a .vtkjs file,
181
+ which can be visualized in the open source Visual ToolKit (VTK) platform.
182
+
183
+ Args:
184
+ model_file: Path to a Dragonfly Model (DFJSON or DFpkl) file.
185
+ full_geometry: Boolean to note if the multipliers on each Story should
186
+ be passed along to the generated Honeybee Room objects or if full
187
+ geometry objects should be written for each story in the building.
188
+ no_plenum: Boolean to indicate whether ceiling/floor plenum depths
189
+ assigned to Room2Ds should generate distinct 3D Rooms in the
190
+ translation. (Default: False).
191
+ ceil_adjacency: Boolean to indicate whether adjacencies should be solved
192
+ between interior stories when Room2D floor and ceiling geometries
193
+ are coplanar. This ensures that Surface boundary conditions are used
194
+ instead of Adiabatic ones.
195
+ merge_method: An optional text string to describe how the Room2Ds should
196
+ be merged into individual Rooms during the translation. Specifying a
197
+ value here can be an effective way to reduce the number of Room volumes
198
+ in the resulting Model. Note that Room2Ds will only be merged if they
199
+ form a contiguous volume. Otherwise, there will be multiple Rooms per
200
+ zone or story, each with an integer added at the end of their
201
+ identifiers. Choose from the following options:
202
+
203
+ * None - No merging of Room2Ds will occur
204
+ * Zones - Room2Ds in the same zone will be merged
205
+ * PlenumZones - Only plenums in the same zone will be merged
206
+ * Stories - Rooms in the same story will be merged
207
+ * PlenumStories - Only plenums in the same story will be merged
208
+
209
+ color_by: Text for the property that dictates the colors of the Model
210
+ geometry. Choose from: type, boundary_condition, none. If none, only
211
+ a wireframe of the Model will be generated (assuming the exclude_wireframe
212
+ option is not used). None is useful when the primary purpose of the
213
+ visualization is to display results in relation to the Model geometry
214
+ or display some room_attr or face_attr as an AnalysisGeometry or Text labels.
215
+ exclude_wireframe: Boolean to note whether a ContextGeometry dedicated to
216
+ the Model Wireframe (in DisplayLineSegment3D) should be included in
217
+ the output visualization.
218
+ faces: Boolean to note whether the colored model geometries should be
219
+ represented with DisplayMesh3D objects instead of DisplayFace3D objects.
220
+ Meshes can usually be rendered faster and they scale well for large models
221
+ but all geometry is triangulated (meaning that their wireframe in certain
222
+ platforms might not appear ideal).
223
+ hide_color_by: Boolean to note whether the color-by geometry should be
224
+ hidden or shown by default. Hiding the color-by geometry is useful
225
+ when the primary purpose of the visualization is to display grid_data
226
+ or room/face attributes but it is still desirable to have the option
227
+ to turn on the geometry.
228
+ room_attr: An optional text string of an attribute that the Model Rooms
229
+ have, which will be used to construct a visualization of this attribute
230
+ in the resulting VisualizationSet. A list of text can also
231
+ be passed and a separate VisualizationData will be added to the
232
+ AnalysisGeometry that represents the attribute in the resulting
233
+ VisualizationSet (or a separate ContextGeometry layer if text_attr
234
+ is True). Room attributes input here can have . that separates the nested
235
+ attributes from one another. For example, properties.energy.program_type.
236
+ face_attr: An optional text string of an attribute that the Model Faces
237
+ have, which will be used to construct a visualization of this attribute
238
+ in the resulting VisualizationSet. A list of text can also be passed and
239
+ a separate VisualizationData will be added to the AnalysisGeometry that '
240
+ represents the attribute in the resulting VisualizationSet (or a separate '
241
+ ContextGeometry layer if text_attr is True). Face attributes input
242
+ here can have . that separates the nested attributes from one another.
243
+ For example, properties.energy.construction.
244
+ text_attr: Boolean to note whether to note whether the input room_attr
245
+ and face_attr should be expressed as a colored AnalysisGeometry
246
+ or a ContextGeometry as text labels.
247
+ grid_display_mode: Text that dictates how the ContextGeometry for Model
248
+ SensorGrids should display in the resulting visualization. The Default
249
+ option will draw sensor points whenever there is no grid_data_path
250
+ and will not draw them at all when grid data is provided, assuming
251
+ the AnalysisGeometry of the grids is sufficient. Choose from: Default,
252
+ Points, Wireframe, Surface, SurfaceWithEdges, None.
253
+ hide_grid: Boolean to note whether the SensorGrid ContextGeometry should
254
+ be hidden or shown by default.
255
+ output_format: Text for the output format of the resulting VisualizationSet
256
+ File (.vsf). Choose from: vsf, json, pkl, vtkjs, html. Note that both
257
+ vsf and json refer to the the JSON version of the VisualizationSet
258
+ file and the distinction between the two is only for help in
259
+ coordinating file extensions (since both .vsf and .json can be
260
+ acceptable). Also note that ladybug-vtk must be installed in order
261
+ for the vtkjs or html options to be usable and the html format
262
+ refers to a web page with the vtkjs file embedded within it.
263
+ output_file: Optional file to output the string of the visualization
264
+ file contents. If None, the string will simply be returned from
265
+ this method.
266
+ """
267
+ # load the model object and process simpler attributes
268
+ model_obj = Model.from_file(model_file)
269
+ room_attrs = [room_attr] if isinstance(room_attr, str) else room_attr
270
+ face_attrs = [face_attr] if isinstance(face_attr, str) else face_attr
271
+ wireframe = not exclude_wireframe
272
+ mesh = not faces
273
+ color_attr = not text_attr
274
+ reset_coordinates = True if output_format.lower() in ('vtkjs', 'html') else False
275
+
276
+ # load the room and face attributes
277
+ face_attributes = []
278
+ for fa in face_attrs:
279
+ faa = FaceAttribute(name=fa, attrs=[fa], color=color_attr, text=text_attr)
280
+ face_attributes.append(faa)
281
+ room_attributes = []
282
+ for ra in room_attrs:
283
+ raa = RoomAttribute(name=ra, attrs=[ra], color=color_attr, text=text_attr)
284
+ room_attributes.append(raa)
285
+
286
+ # create the VisualizationSet
287
+ multiplier = not full_geometry
288
+ vis_set = model_obj.to_vis_set(
289
+ multiplier, no_plenum, ceil_adjacency, merge_method=merge_method,
290
+ color_by=color_by, include_wireframe=wireframe, use_mesh=mesh,
291
+ hide_color_by=hide_color_by,
292
+ room_attrs=room_attributes, face_attrs=face_attributes,
293
+ grid_display_mode=grid_display_mode, hide_grid=hide_grid,
294
+ reset_coordinates=reset_coordinates
295
+ )
296
+
297
+ # output the VisualizationSet through the CLI
298
+ return _output_vis_set_to_format(vis_set, output_format, output_file)
299
+
300
+
301
+ @display.command('model-comparison-to-vis')
302
+ @click.argument('base-model-file', type=click.Path(
303
+ exists=True, file_okay=True, dir_okay=False, resolve_path=True))
304
+ @click.argument('incoming-model-file', type=click.Path(
305
+ exists=True, file_okay=True, dir_okay=False, resolve_path=True))
306
+ @click.option(
307
+ '--multiplier/--full-geometry', ' /-fg', help='Flag to note if the '
308
+ 'multipliers on each Building story should be passed along to the '
309
+ 'generated Honeybee Room objects or if full geometry objects should be '
310
+ 'written for each story in the building.', default=True, show_default=True)
311
+ @click.option(
312
+ '--plenum/--no-plenum', '-p/-np', help='Flag to indicate whether '
313
+ 'ceiling/floor plenum depths assigned to Room2Ds should generate '
314
+ 'distinct 3D Rooms in the translation.', default=True, show_default=True)
315
+ @click.option(
316
+ '--no-ceil-adjacency/--ceil-adjacency', ' /-a', help='Flag to indicate '
317
+ 'whether adjacencies should be solved between interior stories when '
318
+ 'Room2D floor and ceiling geometries are coplanar. This ensures '
319
+ 'that Surface boundary conditions are used instead of Adiabatic ones.',
320
+ default=True, show_default=True)
321
+ @click.option(
322
+ '--merge-method', help='Text to describe how the Room2Ds should '
323
+ 'be merged into individual Rooms during the translation. Specifying a '
324
+ 'value here can be an effective way to reduce the number of Room '
325
+ 'volumes in the resulting 3D Honeybee Model and, ultimately, yield '
326
+ 'a faster simulation time in the destination engine with fewer results '
327
+ 'to manage. Choose from: None, Zones, PlenumZones, Stories, PlenumStories.',
328
+ type=str, default='None', show_default=True)
329
+ @click.option(
330
+ '--base-color', '-bc', help='An optional hexadecimal code for the color '
331
+ 'of the base model.', type=str, default='#74eded', show_default=True)
332
+ @click.option(
333
+ '--incoming-color', '-ic', help='An optional hexadecimal code for the color '
334
+ 'of the incoming model.', type=str, default='#ed7474', show_default=True)
335
+ @click.option(
336
+ '--output-format', '-of', help='Text for the output format of the resulting '
337
+ 'VisualizationSet File (.vsf). Choose from: vsf, json, pkl, vtkjs, html. Note '
338
+ 'that both vsf and json refer to the the JSON version of the VisualizationSet '
339
+ 'file and the distinction between the two is only for help in coordinating file '
340
+ 'extensions (since both .vsf and .json can be acceptable). Also note that '
341
+ 'ladybug-vtk must be installed in order for the vtkjs or html options to be usable '
342
+ 'and the html format refers to a web page with the vtkjs file embedded within it.',
343
+ type=str, default='vsf', show_default=True)
344
+ @click.option(
345
+ '--output-file', help='Optional file to output the he string of the visualization '
346
+ 'file contents. By default, it will be printed out to stdout',
347
+ type=click.File('w'), default='-', show_default=True)
348
+ def model_comparison_to_vis_set_cli(
349
+ base_model_file, incoming_model_file, multiplier, plenum, no_ceil_adjacency,
350
+ merge_method, base_color, incoming_color, output_format, output_file
351
+ ):
352
+ """Translate two Dragonfly Models to be compared to a VisualizationSet.
353
+
354
+ This command can also optionally translate the Dragonfly Model to a .vtkjs file,
355
+ which can be visualized in the open source Visual ToolKit (VTK) platform.
356
+
357
+ \b
358
+ Args:
359
+ base_model_file: Full path to a Dragonfly Model (DFJSON or HBpkl) file
360
+ representing the base model used in the comparison. Typically, this
361
+ is the model with more data to be kept.
362
+ incoming_model_file: Full path to a Dragonfly Model (DFJSON or HBpkl) file
363
+ representing the incoming model used in the comparison. Typically,
364
+ this is the model with new data to be evaluated against the base model.
365
+ """
366
+ try:
367
+ # process all of the CLI input so that it can be passed to the function
368
+ full_geometry = not multiplier
369
+ no_plenum = not plenum
370
+ ceil_adjacency = not no_ceil_adjacency
371
+
372
+ # pass the input to the function in order to convert the model
373
+ model_comparison_to_vis_set(
374
+ base_model_file, incoming_model_file, full_geometry, no_plenum,
375
+ ceil_adjacency, merge_method, base_color, incoming_color,
376
+ output_format, output_file
377
+ )
378
+ except Exception as e:
379
+ _logger.exception('Failed to translate Model to VisualizationSet.\n{}'.format(e))
380
+ sys.exit(1)
381
+ else:
382
+ sys.exit(0)
383
+
384
+
385
+ def model_comparison_to_vis_set(
386
+ base_model_file, incoming_model_file, full_geometry=False, no_plenum=False,
387
+ ceil_adjacency=False, merge_method='None',
388
+ base_color='#74eded', incoming_color='#ed7474',
389
+ output_format='vsf', output_file=None,
390
+ multiplier=True, plenum=True, no_ceil_adjacency=True
391
+ ):
392
+ """Translate two Honeybee Models to be compared to a VisualizationSet.
393
+
394
+ This command can also optionally translate the Honeybee Model to a .vtkjs file,
395
+ which can be visualized in the open source Visual ToolKit (VTK) platform.
396
+
397
+ Args:
398
+ base_model_file: Full path to a Honeybee Model (HBJSON or HBpkl) file
399
+ representing the base model used in the comparison. Typically, this
400
+ is the model with more data to be kept.
401
+ incoming_model_file: Full path to a Honeybee Model (HBJSON or HBpkl) file
402
+ representing the incoming model used in the comparison. Typically,
403
+ this is the model with new data to be evaluated against the base model.
404
+ full_geometry: Boolean to note if the multipliers on each Story should
405
+ be passed along to the generated Honeybee Room objects or if full
406
+ geometry objects should be written for each story in the building.
407
+ no_plenum: Boolean to indicate whether ceiling/floor plenum depths
408
+ assigned to Room2Ds should generate distinct 3D Rooms in the
409
+ translation. (Default: False).
410
+ ceil_adjacency: Boolean to indicate whether adjacencies should be solved
411
+ between interior stories when Room2D floor and ceiling geometries
412
+ are coplanar. This ensures that Surface boundary conditions are used
413
+ instead of Adiabatic ones.
414
+ merge_method: An optional text string to describe how the Room2Ds should
415
+ be merged into individual Rooms during the translation. Specifying a
416
+ value here can be an effective way to reduce the number of Room volumes
417
+ in the resulting Model. Note that Room2Ds will only be merged if they
418
+ form a contiguous volume. Otherwise, there will be multiple Rooms per
419
+ zone or story, each with an integer added at the end of their
420
+ identifiers. Choose from the following options:
421
+
422
+ * None - No merging of Room2Ds will occur
423
+ * Zones - Room2Ds in the same zone will be merged
424
+ * PlenumZones - Only plenums in the same zone will be merged
425
+ * Stories - Rooms in the same story will be merged
426
+ * PlenumStories - Only plenums in the same story will be merged
427
+
428
+ base_color: An optional hexadecimal code for the color of the base
429
+ model. (Default: #74eded).
430
+ incoming_color: An optional hexadecimal code for the color of the incoming
431
+ model. (Default: #ed7474).
432
+ output_format: Text for the output format of the resulting VisualizationSet
433
+ File (.vsf). Choose from: vsf, json, pkl, vtkjs, html. Note that both
434
+ vsf and json refer to the the JSON version of the VisualizationSet
435
+ file and the distinction between the two is only for help in
436
+ coordinating file extensions (since both .vsf and .json can be
437
+ acceptable). Also note that ladybug-vtk must be installed in order
438
+ for the vtkjs or html options to be usable and the html format
439
+ refers to a web page with the vtkjs file embedded within it.
440
+ output_file: Optional file to output the string of the visualization
441
+ file contents. If None, the string will simply be returned from
442
+ this method.
443
+ """
444
+ # load the model objects and process the colors from the hex codes
445
+ base_model = Model.from_file(base_model_file)
446
+ incoming_model = Model.from_file(incoming_model_file)
447
+ base_color = Color.from_hex(base_color)
448
+ incoming_color = Color.from_hex(incoming_color)
449
+ base_color.a = 128
450
+ incoming_color.a = 128
451
+ reset_coordinates = True if output_format.lower() in ('vtkjs', 'html') else False
452
+
453
+ # create the VisualizationSet
454
+ multiplier = not full_geometry
455
+ vis_set = base_model.to_vis_set_comparison(
456
+ incoming_model, multiplier, no_plenum, ceil_adjacency, merge_method,
457
+ base_color, incoming_color, reset_coordinates=reset_coordinates)
458
+
459
+ # output the VisualizationSet through the CLI
460
+ return _output_vis_set_to_format(vis_set, output_format, output_file)
461
+
462
+
463
+ def _output_vis_set_to_format(vis_set, output_format, output_file):
464
+ """Process a VisualizationSet for output from the CLI.
465
+
466
+ Args:
467
+ vis_set: The VisualizationSet to be output form the CLI.
468
+ output_format: Text for the output format of the resulting VisualizationSet File.
469
+ output_file: Optional file to output the string of the visualization
470
+ file contents. If None, the string will simply be returned from
471
+ this method.
472
+ """
473
+ # output the visualization in the correct format
474
+ output_format = output_format.lower()
475
+ if output_format in ('vsf', 'json'):
476
+ if output_file is None:
477
+ return json.dumps(vis_set.to_dict())
478
+ elif isinstance(output_file, str):
479
+ with open(output_file, 'w') as of:
480
+ of.write(json.dumps(vis_set.to_dict()))
481
+ else:
482
+ output_file.write(json.dumps(vis_set.to_dict()))
483
+ elif output_format == 'pkl':
484
+ if output_file is None:
485
+ return pickle.dumps(vis_set.to_dict())
486
+ elif isinstance(output_file, str):
487
+ with open(output_file, 'w') as of:
488
+ of.write(pickle.dumps(vis_set.to_dict()))
489
+ elif output_file.name == '<stdout>':
490
+ output_file.write(pickle.dumps(vis_set.to_dict()))
491
+ else:
492
+ out_folder, out_file = os.path.split(output_file.name)
493
+ vis_set.to_pkl(out_file, out_folder)
494
+ elif output_format in ('vtkjs', 'html'):
495
+ if output_file is None or (not isinstance(output_file, str)
496
+ and output_file.name == '<stdout>'):
497
+ # get a temporary file
498
+ out_file = str(uuid.uuid4())[:6]
499
+ out_folder = tempfile.gettempdir()
500
+ else:
501
+ f_path = output_file if isinstance(output_file, str) else output_file.name
502
+ out_folder, out_file = os.path.split(f_path)
503
+ if out_file.endswith('.vtkjs'):
504
+ out_file = out_file[:-6]
505
+ elif out_file.endswith('.html'):
506
+ out_file = out_file[:-5]
507
+ try:
508
+ if output_format == 'vtkjs':
509
+ vis_set.to_vtkjs(output_folder=out_folder, file_name=out_file)
510
+ if output_format == 'html':
511
+ vis_set.to_html(output_folder=out_folder, file_name=out_file)
512
+ except AttributeError as ae:
513
+ raise AttributeError(
514
+ 'Ladybug-vtk must be installed in order to use --output-format '
515
+ 'vtkjs.\n{}'.format(ae))
516
+ if output_file is None or (not isinstance(output_file, str)
517
+ and output_file.name == '<stdout>'):
518
+ # load file contents
519
+ out_file_ext = out_file + '.' + output_format
520
+ out_file_path = os.path.join(out_folder, out_file_ext)
521
+ if output_format == 'html':
522
+ with open(out_file_path, encoding='utf-8') as of:
523
+ f_contents = of.read()
524
+ else: # vtkjs can only be read as binary
525
+ with open(out_file_path, 'rb') as of:
526
+ f_contents = of.read()
527
+ b = base64.b64encode(f_contents)
528
+ f_contents = b.decode('utf-8')
529
+ if output_file is None:
530
+ return f_contents
531
+ output_file.write(f_contents)
532
+ else:
533
+ raise ValueError('Unrecognized output-format "{}".'.format(output_format))
534
+
535
+
536
+ # add display sub-group to dragonfly CLI
537
+ main.add_command(display)