honeybee-energy 1.116.106__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.
- honeybee_energy/__init__.py +24 -0
- honeybee_energy/__main__.py +4 -0
- honeybee_energy/_extend_honeybee.py +145 -0
- honeybee_energy/altnumber.py +21 -0
- honeybee_energy/baseline/__init__.py +2 -0
- honeybee_energy/baseline/create.py +608 -0
- honeybee_energy/baseline/data/__init__.py +1 -0
- honeybee_energy/baseline/data/constructions.csv +64 -0
- honeybee_energy/baseline/data/fen_ratios.csv +15 -0
- honeybee_energy/baseline/data/lpd_building.csv +21 -0
- honeybee_energy/baseline/data/pci_2016.csv +22 -0
- honeybee_energy/baseline/data/pci_2019.csv +22 -0
- honeybee_energy/baseline/data/pci_2022.csv +22 -0
- honeybee_energy/baseline/data/shw.csv +21 -0
- honeybee_energy/baseline/pci.py +512 -0
- honeybee_energy/baseline/result.py +371 -0
- honeybee_energy/boundarycondition.py +128 -0
- honeybee_energy/cli/__init__.py +69 -0
- honeybee_energy/cli/baseline.py +475 -0
- honeybee_energy/cli/edit.py +327 -0
- honeybee_energy/cli/lib.py +1154 -0
- honeybee_energy/cli/result.py +810 -0
- honeybee_energy/cli/setconfig.py +124 -0
- honeybee_energy/cli/settings.py +569 -0
- honeybee_energy/cli/simulate.py +380 -0
- honeybee_energy/cli/translate.py +1714 -0
- honeybee_energy/cli/validate.py +224 -0
- honeybee_energy/config.json +11 -0
- honeybee_energy/config.py +842 -0
- honeybee_energy/construction/__init__.py +1 -0
- honeybee_energy/construction/_base.py +374 -0
- honeybee_energy/construction/air.py +325 -0
- honeybee_energy/construction/dictutil.py +89 -0
- honeybee_energy/construction/dynamic.py +607 -0
- honeybee_energy/construction/opaque.py +460 -0
- honeybee_energy/construction/shade.py +319 -0
- honeybee_energy/construction/window.py +1096 -0
- honeybee_energy/construction/windowshade.py +847 -0
- honeybee_energy/constructionset.py +1655 -0
- honeybee_energy/dictutil.py +56 -0
- honeybee_energy/generator/__init__.py +5 -0
- honeybee_energy/generator/loadcenter.py +204 -0
- honeybee_energy/generator/pv.py +535 -0
- honeybee_energy/hvac/__init__.py +21 -0
- honeybee_energy/hvac/_base.py +124 -0
- honeybee_energy/hvac/_template.py +270 -0
- honeybee_energy/hvac/allair/__init__.py +22 -0
- honeybee_energy/hvac/allair/_base.py +349 -0
- honeybee_energy/hvac/allair/furnace.py +168 -0
- honeybee_energy/hvac/allair/psz.py +131 -0
- honeybee_energy/hvac/allair/ptac.py +163 -0
- honeybee_energy/hvac/allair/pvav.py +109 -0
- honeybee_energy/hvac/allair/vav.py +128 -0
- honeybee_energy/hvac/detailed.py +337 -0
- honeybee_energy/hvac/doas/__init__.py +28 -0
- honeybee_energy/hvac/doas/_base.py +345 -0
- honeybee_energy/hvac/doas/fcu.py +127 -0
- honeybee_energy/hvac/doas/radiant.py +329 -0
- honeybee_energy/hvac/doas/vrf.py +81 -0
- honeybee_energy/hvac/doas/wshp.py +91 -0
- honeybee_energy/hvac/heatcool/__init__.py +23 -0
- honeybee_energy/hvac/heatcool/_base.py +177 -0
- honeybee_energy/hvac/heatcool/baseboard.py +61 -0
- honeybee_energy/hvac/heatcool/evapcool.py +72 -0
- honeybee_energy/hvac/heatcool/fcu.py +92 -0
- honeybee_energy/hvac/heatcool/gasunit.py +53 -0
- honeybee_energy/hvac/heatcool/radiant.py +269 -0
- honeybee_energy/hvac/heatcool/residential.py +77 -0
- honeybee_energy/hvac/heatcool/vrf.py +54 -0
- honeybee_energy/hvac/heatcool/windowac.py +70 -0
- honeybee_energy/hvac/heatcool/wshp.py +62 -0
- honeybee_energy/hvac/idealair.py +699 -0
- honeybee_energy/internalmass.py +310 -0
- honeybee_energy/lib/__init__.py +1 -0
- honeybee_energy/lib/_loadconstructions.py +194 -0
- honeybee_energy/lib/_loadconstructionsets.py +117 -0
- honeybee_energy/lib/_loadmaterials.py +83 -0
- honeybee_energy/lib/_loadprogramtypes.py +125 -0
- honeybee_energy/lib/_loadschedules.py +87 -0
- honeybee_energy/lib/_loadtypelimits.py +64 -0
- honeybee_energy/lib/constructions.py +207 -0
- honeybee_energy/lib/constructionsets.py +95 -0
- honeybee_energy/lib/materials.py +67 -0
- honeybee_energy/lib/programtypes.py +125 -0
- honeybee_energy/lib/schedules.py +61 -0
- honeybee_energy/lib/scheduletypelimits.py +31 -0
- honeybee_energy/load/__init__.py +1 -0
- honeybee_energy/load/_base.py +190 -0
- honeybee_energy/load/daylight.py +397 -0
- honeybee_energy/load/dictutil.py +47 -0
- honeybee_energy/load/equipment.py +771 -0
- honeybee_energy/load/hotwater.py +543 -0
- honeybee_energy/load/infiltration.py +460 -0
- honeybee_energy/load/lighting.py +480 -0
- honeybee_energy/load/people.py +497 -0
- honeybee_energy/load/process.py +472 -0
- honeybee_energy/load/setpoint.py +816 -0
- honeybee_energy/load/ventilation.py +550 -0
- honeybee_energy/material/__init__.py +1 -0
- honeybee_energy/material/_base.py +166 -0
- honeybee_energy/material/dictutil.py +59 -0
- honeybee_energy/material/frame.py +367 -0
- honeybee_energy/material/gas.py +1087 -0
- honeybee_energy/material/glazing.py +854 -0
- honeybee_energy/material/opaque.py +1351 -0
- honeybee_energy/material/shade.py +1360 -0
- honeybee_energy/measure.py +472 -0
- honeybee_energy/programtype.py +723 -0
- honeybee_energy/properties/__init__.py +1 -0
- honeybee_energy/properties/aperture.py +333 -0
- honeybee_energy/properties/door.py +342 -0
- honeybee_energy/properties/extension.py +244 -0
- honeybee_energy/properties/face.py +274 -0
- honeybee_energy/properties/model.py +2640 -0
- honeybee_energy/properties/room.py +1747 -0
- honeybee_energy/properties/shade.py +314 -0
- honeybee_energy/properties/shademesh.py +262 -0
- honeybee_energy/reader.py +48 -0
- honeybee_energy/result/__init__.py +1 -0
- honeybee_energy/result/colorobj.py +648 -0
- honeybee_energy/result/emissions.py +290 -0
- honeybee_energy/result/err.py +101 -0
- honeybee_energy/result/eui.py +100 -0
- honeybee_energy/result/generation.py +160 -0
- honeybee_energy/result/loadbalance.py +890 -0
- honeybee_energy/result/match.py +202 -0
- honeybee_energy/result/osw.py +90 -0
- honeybee_energy/result/rdd.py +59 -0
- honeybee_energy/result/zsz.py +190 -0
- honeybee_energy/run.py +1577 -0
- honeybee_energy/schedule/__init__.py +1 -0
- honeybee_energy/schedule/day.py +626 -0
- honeybee_energy/schedule/dictutil.py +59 -0
- honeybee_energy/schedule/fixedinterval.py +1012 -0
- honeybee_energy/schedule/rule.py +619 -0
- honeybee_energy/schedule/ruleset.py +1867 -0
- honeybee_energy/schedule/typelimit.py +310 -0
- honeybee_energy/shw.py +315 -0
- honeybee_energy/simulation/__init__.py +1 -0
- honeybee_energy/simulation/control.py +214 -0
- honeybee_energy/simulation/daylightsaving.py +185 -0
- honeybee_energy/simulation/dictutil.py +51 -0
- honeybee_energy/simulation/output.py +646 -0
- honeybee_energy/simulation/parameter.py +606 -0
- honeybee_energy/simulation/runperiod.py +443 -0
- honeybee_energy/simulation/shadowcalculation.py +295 -0
- honeybee_energy/simulation/sizing.py +546 -0
- honeybee_energy/ventcool/__init__.py +5 -0
- honeybee_energy/ventcool/_crack_data.py +91 -0
- honeybee_energy/ventcool/afn.py +289 -0
- honeybee_energy/ventcool/control.py +269 -0
- honeybee_energy/ventcool/crack.py +126 -0
- honeybee_energy/ventcool/fan.py +493 -0
- honeybee_energy/ventcool/opening.py +365 -0
- honeybee_energy/ventcool/simulation.py +314 -0
- honeybee_energy/writer.py +1078 -0
- honeybee_energy-1.116.106.dist-info/METADATA +113 -0
- honeybee_energy-1.116.106.dist-info/RECORD +162 -0
- honeybee_energy-1.116.106.dist-info/WHEEL +5 -0
- honeybee_energy-1.116.106.dist-info/entry_points.txt +2 -0
- honeybee_energy-1.116.106.dist-info/licenses/LICENSE +661 -0
- honeybee_energy-1.116.106.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,1154 @@
|
|
|
1
|
+
"""honeybee energy standards library commands."""
|
|
2
|
+
import click
|
|
3
|
+
import sys
|
|
4
|
+
import os
|
|
5
|
+
import logging
|
|
6
|
+
import json
|
|
7
|
+
import zipfile
|
|
8
|
+
from datetime import datetime
|
|
9
|
+
|
|
10
|
+
from honeybee.config import folders as hb_folders
|
|
11
|
+
from honeybee_energy.config import folders
|
|
12
|
+
from honeybee_energy.schedule.typelimit import ScheduleTypeLimit
|
|
13
|
+
from honeybee_energy.material.dictutil import dict_to_material, MATERIAL_TYPES
|
|
14
|
+
from honeybee_energy.run import run_osw, from_osm_osw, _parse_os_cli_failure
|
|
15
|
+
|
|
16
|
+
from honeybee_energy.lib.materials import opaque_material_by_identifier, \
|
|
17
|
+
window_material_by_identifier, OPAQUE_MATERIALS, WINDOW_MATERIALS
|
|
18
|
+
from honeybee_energy.lib.constructions import opaque_construction_by_identifier, \
|
|
19
|
+
window_construction_by_identifier, shade_construction_by_identifier, \
|
|
20
|
+
OPAQUE_CONSTRUCTIONS, WINDOW_CONSTRUCTIONS, SHADE_CONSTRUCTIONS, \
|
|
21
|
+
lib_dict_abridged_to_construction
|
|
22
|
+
from honeybee_energy.lib.constructionsets import construction_set_by_identifier, \
|
|
23
|
+
CONSTRUCTION_SETS, lib_dict_abridged_to_construction_set
|
|
24
|
+
from honeybee_energy.lib.scheduletypelimits import schedule_type_limit_by_identifier, \
|
|
25
|
+
SCHEDULE_TYPE_LIMITS
|
|
26
|
+
from honeybee_energy.lib.schedules import schedule_by_identifier, SCHEDULES, \
|
|
27
|
+
lib_dict_abridged_to_schedule
|
|
28
|
+
from honeybee_energy.lib.programtypes import program_type_by_identifier, PROGRAM_TYPES, \
|
|
29
|
+
lib_dict_abridged_to_program_type
|
|
30
|
+
|
|
31
|
+
from honeybee_energy.lib._loadtypelimits import load_type_limits_from_folder, \
|
|
32
|
+
_schedule_type_limits
|
|
33
|
+
from honeybee_energy.lib._loadschedules import load_schedules_from_folder, \
|
|
34
|
+
_default_schedules
|
|
35
|
+
from honeybee_energy.lib._loadprogramtypes import load_programtypes_from_folder, \
|
|
36
|
+
_default_programs
|
|
37
|
+
from honeybee_energy.lib._loadmaterials import load_materials_from_folder, \
|
|
38
|
+
_default_mats
|
|
39
|
+
from honeybee_energy.lib._loadconstructions import load_constructions_from_folder, \
|
|
40
|
+
_default_constrs
|
|
41
|
+
from honeybee_energy.lib._loadconstructionsets import \
|
|
42
|
+
load_constructionsets_from_folder, _default_sets
|
|
43
|
+
|
|
44
|
+
_logger = logging.getLogger(__name__)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@click.group(help='Commands for retrieving objects from the standards library.')
|
|
48
|
+
def lib():
|
|
49
|
+
pass
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@lib.command('opaque-materials')
|
|
53
|
+
@click.option('--output-file', '-f', help='Optional file to output the JSON string of '
|
|
54
|
+
'the object. By default, it will be printed out to stdout',
|
|
55
|
+
type=click.File('w'), default='-', show_default=True)
|
|
56
|
+
def opaque_materials(output_file):
|
|
57
|
+
"""Get a list of all opaque materials in the standards library."""
|
|
58
|
+
try:
|
|
59
|
+
output_file.write(json.dumps(OPAQUE_MATERIALS))
|
|
60
|
+
except Exception as e:
|
|
61
|
+
_logger.exception('Failed to load opaque materials.\n{}'.format(e))
|
|
62
|
+
sys.exit(1)
|
|
63
|
+
else:
|
|
64
|
+
sys.exit(0)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
@lib.command('window-materials')
|
|
68
|
+
@click.option('--output-file', '-f', help='Optional file to output the JSON string of '
|
|
69
|
+
'the object. By default, it will be printed out to stdout',
|
|
70
|
+
type=click.File('w'), default='-', show_default=True)
|
|
71
|
+
def window_materials(output_file):
|
|
72
|
+
"""Get a list of all window materials in the standards library."""
|
|
73
|
+
try:
|
|
74
|
+
output_file.write(json.dumps(WINDOW_MATERIALS))
|
|
75
|
+
except Exception as e:
|
|
76
|
+
_logger.exception('Failed to load window materials.\n{}'.format(e))
|
|
77
|
+
sys.exit(1)
|
|
78
|
+
else:
|
|
79
|
+
sys.exit(0)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
@lib.command('opaque-constructions')
|
|
83
|
+
@click.option('--output-file', '-f', help='Optional file to output the JSON string of '
|
|
84
|
+
'the object. By default, it will be printed out to stdout',
|
|
85
|
+
type=click.File('w'), default='-', show_default=True)
|
|
86
|
+
def opaque_constructions(output_file):
|
|
87
|
+
"""Get a list of all opaque constructions in the standards library."""
|
|
88
|
+
try:
|
|
89
|
+
output_file.write(json.dumps(OPAQUE_CONSTRUCTIONS))
|
|
90
|
+
except Exception as e:
|
|
91
|
+
_logger.exception('Failed to load opaque constructions.\n{}'.format(e))
|
|
92
|
+
sys.exit(1)
|
|
93
|
+
else:
|
|
94
|
+
sys.exit(0)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
@lib.command('window-constructions')
|
|
98
|
+
@click.option('--output-file', '-f', help='Optional file to output the JSON string of '
|
|
99
|
+
'the object. By default, it will be printed out to stdout',
|
|
100
|
+
type=click.File('w'), default='-', show_default=True)
|
|
101
|
+
def window_constructions(output_file):
|
|
102
|
+
"""Get a list of all window constructions in the standards library."""
|
|
103
|
+
try:
|
|
104
|
+
output_file.write(json.dumps(WINDOW_CONSTRUCTIONS))
|
|
105
|
+
except Exception as e:
|
|
106
|
+
_logger.exception('Failed to load window constructions.\n{}'.format(e))
|
|
107
|
+
sys.exit(1)
|
|
108
|
+
else:
|
|
109
|
+
sys.exit(0)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
@lib.command('shade-constructions')
|
|
113
|
+
@click.option('--output-file', '-f', help='Optional file to output the JSON string of '
|
|
114
|
+
'the object. By default, it will be printed out to stdout',
|
|
115
|
+
type=click.File('w'), default='-', show_default=True)
|
|
116
|
+
def shade_constructions(output_file):
|
|
117
|
+
"""Get a list of all shade constructions in the standards library."""
|
|
118
|
+
try:
|
|
119
|
+
output_file.write(json.dumps(SHADE_CONSTRUCTIONS))
|
|
120
|
+
except Exception as e:
|
|
121
|
+
_logger.exception('Failed to load shade constructions.\n{}'.format(e))
|
|
122
|
+
sys.exit(1)
|
|
123
|
+
else:
|
|
124
|
+
sys.exit(0)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
@lib.command('construction-sets')
|
|
128
|
+
@click.option('--output-file', '-f', help='Optional file to output the JSON string of '
|
|
129
|
+
'the object. By default, it will be printed out to stdout',
|
|
130
|
+
type=click.File('w'), default='-', show_default=True)
|
|
131
|
+
def construction_sets(output_file):
|
|
132
|
+
"""Get a list of all construction sets in the standards library."""
|
|
133
|
+
try:
|
|
134
|
+
output_file.write(json.dumps(CONSTRUCTION_SETS))
|
|
135
|
+
except Exception as e:
|
|
136
|
+
_logger.exception('Failed to load construction sets.\n{}'.format(e))
|
|
137
|
+
sys.exit(1)
|
|
138
|
+
else:
|
|
139
|
+
sys.exit(0)
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
@lib.command('schedule-type-limits')
|
|
143
|
+
@click.option('--output-file', '-f', help='Optional file to output the JSON string of '
|
|
144
|
+
'the object. By default, it will be printed out to stdout',
|
|
145
|
+
type=click.File('w'), default='-', show_default=True)
|
|
146
|
+
def schedule_type_limits(output_file):
|
|
147
|
+
"""Get a list of all schedule type limits in the standards library."""
|
|
148
|
+
try:
|
|
149
|
+
output_file.write(json.dumps(SCHEDULE_TYPE_LIMITS))
|
|
150
|
+
except Exception as e:
|
|
151
|
+
_logger.exception('Failed to load schedule type limits.\n{}'.format(e))
|
|
152
|
+
sys.exit(1)
|
|
153
|
+
else:
|
|
154
|
+
sys.exit(0)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
@lib.command('schedules')
|
|
158
|
+
@click.option('--output-file', '-f', help='Optional file to output the JSON string of '
|
|
159
|
+
'the object. By default, it will be printed out to stdout',
|
|
160
|
+
type=click.File('w'), default='-', show_default=True)
|
|
161
|
+
def schedules(output_file):
|
|
162
|
+
"""Get a list of all schedules in the standards library."""
|
|
163
|
+
try:
|
|
164
|
+
output_file.write(json.dumps(SCHEDULES))
|
|
165
|
+
except Exception as e:
|
|
166
|
+
_logger.exception('Failed to load schedules.\n{}'.format(e))
|
|
167
|
+
sys.exit(1)
|
|
168
|
+
else:
|
|
169
|
+
sys.exit(0)
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
@lib.command('program-types')
|
|
173
|
+
@click.option('--output-file', '-f', help='Optional file to output the JSON string of '
|
|
174
|
+
'the object. By default, it will be printed out to stdout',
|
|
175
|
+
type=click.File('w'), default='-', show_default=True)
|
|
176
|
+
def program_types(output_file):
|
|
177
|
+
"""Get a list of all program_types in the standards library."""
|
|
178
|
+
try:
|
|
179
|
+
output_file.write(json.dumps(PROGRAM_TYPES))
|
|
180
|
+
except Exception as e:
|
|
181
|
+
_logger.exception('Failed to load program types.\n{}'.format(e))
|
|
182
|
+
sys.exit(1)
|
|
183
|
+
else:
|
|
184
|
+
sys.exit(0)
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
@lib.command('opaque-material-by-id')
|
|
188
|
+
@click.argument('material-id', type=str)
|
|
189
|
+
@click.option('--output-file', '-f', help='Optional file to output the JSON string of '
|
|
190
|
+
'the object. By default, it will be printed out to stdout',
|
|
191
|
+
type=click.File('w'), default='-', show_default=True)
|
|
192
|
+
def opaque_material_by_id(material_id, output_file):
|
|
193
|
+
"""Get an opaque material definition from the standards lib with its identifier.
|
|
194
|
+
|
|
195
|
+
\b
|
|
196
|
+
Args:
|
|
197
|
+
material_id: The identifier of an opaque material in the library.
|
|
198
|
+
"""
|
|
199
|
+
try:
|
|
200
|
+
output_file.write(
|
|
201
|
+
json.dumps(opaque_material_by_identifier(material_id).to_dict())
|
|
202
|
+
)
|
|
203
|
+
except Exception as e:
|
|
204
|
+
_logger.exception(
|
|
205
|
+
'Retrieval from opaque material library failed.\n{}'.format(e))
|
|
206
|
+
sys.exit(1)
|
|
207
|
+
else:
|
|
208
|
+
sys.exit(0)
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
@lib.command('window-material-by-id')
|
|
212
|
+
@click.argument('material-id', type=str)
|
|
213
|
+
@click.option('--output-file', '-f', help='Optional file to output the JSON string of '
|
|
214
|
+
'the object. By default, it will be printed out to stdout',
|
|
215
|
+
type=click.File('w'), default='-', show_default=True)
|
|
216
|
+
def window_material_by_id(material_id, output_file):
|
|
217
|
+
"""Get a window material definition from the standards lib with its identifier.
|
|
218
|
+
|
|
219
|
+
\b
|
|
220
|
+
Args:
|
|
221
|
+
material_id: The identifier of an window material in the library.
|
|
222
|
+
"""
|
|
223
|
+
try:
|
|
224
|
+
output_file.write(
|
|
225
|
+
json.dumps(window_material_by_identifier(material_id).to_dict())
|
|
226
|
+
)
|
|
227
|
+
except Exception as e:
|
|
228
|
+
_logger.exception(
|
|
229
|
+
'Retrieval from window material library failed.\n{}'.format(e))
|
|
230
|
+
sys.exit(1)
|
|
231
|
+
else:
|
|
232
|
+
sys.exit(0)
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
@lib.command('opaque-construction-by-id')
|
|
236
|
+
@click.argument('construction-id', type=str)
|
|
237
|
+
@click.option('--complete/--abridged', ' /-a', help='Flag to note whether an abridged '
|
|
238
|
+
'definition should be returned.', default=True)
|
|
239
|
+
@click.option('--output-file', '-f', help='Optional file to output the JSON string of '
|
|
240
|
+
'the object. By default, it will be printed out to stdout',
|
|
241
|
+
type=click.File('w'), default='-', show_default=True)
|
|
242
|
+
def opaque_construction_by_id(construction_id, complete, output_file):
|
|
243
|
+
"""Get an opaque construction definition from the standards lib with its identifier.
|
|
244
|
+
|
|
245
|
+
\b
|
|
246
|
+
Args:
|
|
247
|
+
construction_id: The identifier of an opaque construction in the library.
|
|
248
|
+
"""
|
|
249
|
+
try:
|
|
250
|
+
abridged = not complete
|
|
251
|
+
output_file.write(json.dumps(opaque_construction_by_identifier(
|
|
252
|
+
construction_id).to_dict(abridged=abridged)))
|
|
253
|
+
except Exception as e:
|
|
254
|
+
_logger.exception(
|
|
255
|
+
'Retrieval from opaque construction library failed.\n{}'.format(e))
|
|
256
|
+
sys.exit(1)
|
|
257
|
+
else:
|
|
258
|
+
sys.exit(0)
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
@lib.command('window-construction-by-id')
|
|
262
|
+
@click.argument('construction-id', type=str)
|
|
263
|
+
@click.option('--complete/--abridged', ' /-a', help='Flag to note whether an abridged '
|
|
264
|
+
'definition should be returned.', default=True)
|
|
265
|
+
@click.option('--output-file', '-f', help='Optional file to output the JSON string of '
|
|
266
|
+
'the object. By default, it will be printed out to stdout',
|
|
267
|
+
type=click.File('w'), default='-', show_default=True)
|
|
268
|
+
def window_construction_by_id(construction_id, complete, output_file):
|
|
269
|
+
"""Get a window construction definition from the standards lib with its identifier.
|
|
270
|
+
|
|
271
|
+
\b
|
|
272
|
+
Args:
|
|
273
|
+
construction_id: The identifier of a window construction in the library.
|
|
274
|
+
"""
|
|
275
|
+
try:
|
|
276
|
+
abridged = not complete
|
|
277
|
+
output_file.write(json.dumps(window_construction_by_identifier(
|
|
278
|
+
construction_id).to_dict(abridged=abridged)))
|
|
279
|
+
except Exception as e:
|
|
280
|
+
_logger.exception(
|
|
281
|
+
'Retrieval from window construction library failed.\n{}'.format(e))
|
|
282
|
+
sys.exit(1)
|
|
283
|
+
else:
|
|
284
|
+
sys.exit(0)
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
@lib.command('shade-construction-by-id')
|
|
288
|
+
@click.argument('construction-id', type=str)
|
|
289
|
+
@click.option('--output-file', '-f', help='Optional file to output the JSON string of '
|
|
290
|
+
'the object. By default, it will be printed out to stdout',
|
|
291
|
+
type=click.File('w'), default='-', show_default=True)
|
|
292
|
+
def shade_construction_by_id(construction_id, output_file):
|
|
293
|
+
"""Get a shade construction definition from the standards lib with its identifier.
|
|
294
|
+
|
|
295
|
+
\b
|
|
296
|
+
Args:
|
|
297
|
+
construction_id: The identifier of a shade construction in the library.
|
|
298
|
+
"""
|
|
299
|
+
try:
|
|
300
|
+
output_file.write(json.dumps(shade_construction_by_identifier(
|
|
301
|
+
construction_id).to_dict()))
|
|
302
|
+
except Exception as e:
|
|
303
|
+
_logger.exception(
|
|
304
|
+
'Retrieval from shade construction library failed.\n{}'.format(e))
|
|
305
|
+
sys.exit(1)
|
|
306
|
+
else:
|
|
307
|
+
sys.exit(0)
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
@lib.command('construction-set-by-id')
|
|
311
|
+
@click.argument('construction-set-id', type=str)
|
|
312
|
+
@click.option('--none-defaults/--include-defaults', ' /-d', help='Flag to note whether '
|
|
313
|
+
'default constructions in the set should be included in or should be '
|
|
314
|
+
'None.', default=True, show_default=True)
|
|
315
|
+
@click.option('--complete/--abridged', ' /-a', help='Flag to note whether an abridged '
|
|
316
|
+
'definition should be returned.', default=True, show_default=True)
|
|
317
|
+
@click.option('--output-file', '-f', help='Optional file to output the JSON string of '
|
|
318
|
+
'the object. By default, it will be printed out to stdout',
|
|
319
|
+
type=click.File('w'), default='-', show_default=True)
|
|
320
|
+
def construction_set_by_id(construction_set_id, none_defaults, complete, output_file):
|
|
321
|
+
"""Get a construction set definition from the standards lib with its identifier.
|
|
322
|
+
|
|
323
|
+
\b
|
|
324
|
+
Args:
|
|
325
|
+
construction_set_id: The identifier of a construction set in the library.
|
|
326
|
+
"""
|
|
327
|
+
try:
|
|
328
|
+
abridged = not complete
|
|
329
|
+
c_set = construction_set_by_identifier(construction_set_id)
|
|
330
|
+
output_file.write(json.dumps(c_set.to_dict(
|
|
331
|
+
none_for_defaults=none_defaults, abridged=abridged)))
|
|
332
|
+
except Exception as e:
|
|
333
|
+
_logger.exception(
|
|
334
|
+
'Retrieval from construction set library failed.\n{}'.format(e))
|
|
335
|
+
sys.exit(1)
|
|
336
|
+
else:
|
|
337
|
+
sys.exit(0)
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
@lib.command('schedule-type-limit-by-id')
|
|
341
|
+
@click.argument('schedule-type-limit-id', type=str)
|
|
342
|
+
@click.option('--output-file', '-f', help='Optional file to output the JSON string of '
|
|
343
|
+
'the object. By default, it will be printed out to stdout',
|
|
344
|
+
type=click.File('w'), default='-', show_default=True)
|
|
345
|
+
def schedule_type_limit_by_id(schedule_type_limit_id, output_file):
|
|
346
|
+
"""Get a schedule type limit definition from the standards lib with its identifier.
|
|
347
|
+
|
|
348
|
+
\b
|
|
349
|
+
Args:
|
|
350
|
+
schedule_type_limit_id: The identifier of a schedule type limit in the library.
|
|
351
|
+
"""
|
|
352
|
+
try:
|
|
353
|
+
output_file.write(json.dumps(schedule_type_limit_by_identifier(
|
|
354
|
+
schedule_type_limit_id).to_dict()))
|
|
355
|
+
except Exception as e:
|
|
356
|
+
_logger.exception(
|
|
357
|
+
'Retrieval from schedule type limit library failed.\n{}'.format(e))
|
|
358
|
+
sys.exit(1)
|
|
359
|
+
else:
|
|
360
|
+
sys.exit(0)
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
@lib.command('schedule-by-id')
|
|
364
|
+
@click.argument('schedule-id', type=str)
|
|
365
|
+
@click.option('--complete/--abridged', ' /-a', help='Flag to note whether an abridged '
|
|
366
|
+
'definition should be returned.', default=True, show_default=True)
|
|
367
|
+
@click.option('--output-file', '-f', help='Optional file to output the JSON string of '
|
|
368
|
+
'the object. By default, it will be printed out to stdout',
|
|
369
|
+
type=click.File('w'), default='-', show_default=True)
|
|
370
|
+
def schedule_by_id(schedule_id, complete, output_file):
|
|
371
|
+
"""Get a schedule definition from the standards lib with its identifier.
|
|
372
|
+
|
|
373
|
+
\b
|
|
374
|
+
Args:
|
|
375
|
+
schedule_id: The identifier of a schedule in the library.
|
|
376
|
+
"""
|
|
377
|
+
try:
|
|
378
|
+
abridged = not complete
|
|
379
|
+
output_file.write(json.dumps(schedule_by_identifier(
|
|
380
|
+
schedule_id).to_dict(abridged=abridged)))
|
|
381
|
+
except Exception as e:
|
|
382
|
+
_logger.exception('Retrieval from schedule library failed.\n{}'.format(e))
|
|
383
|
+
sys.exit(1)
|
|
384
|
+
else:
|
|
385
|
+
sys.exit(0)
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
@lib.command('program-type-by-id')
|
|
389
|
+
@click.argument('program-type-id', type=str)
|
|
390
|
+
@click.option('--complete/--abridged', ' /-a', help='Flag to note whether an abridged '
|
|
391
|
+
'definition should be returned.', default=True, show_default=True)
|
|
392
|
+
@click.option('--output-file', '-f', help='Optional file to output the JSON string of '
|
|
393
|
+
'the object. By default, it will be printed out to stdout',
|
|
394
|
+
type=click.File('w'), default='-', show_default=True)
|
|
395
|
+
def program_type_by_id(program_type_id, complete, output_file):
|
|
396
|
+
"""Get a program type definition from the standards lib with its identifier.
|
|
397
|
+
|
|
398
|
+
\b
|
|
399
|
+
Args:
|
|
400
|
+
program_type_id: The identifier of a program type in the library.
|
|
401
|
+
"""
|
|
402
|
+
try:
|
|
403
|
+
abridged = not complete
|
|
404
|
+
output_file.write(json.dumps(program_type_by_identifier(
|
|
405
|
+
program_type_id).to_dict(abridged=abridged)))
|
|
406
|
+
except Exception as e:
|
|
407
|
+
_logger.exception('Retrieval from program type library failed.\n{}'.format(e))
|
|
408
|
+
sys.exit(1)
|
|
409
|
+
else:
|
|
410
|
+
sys.exit(0)
|
|
411
|
+
|
|
412
|
+
|
|
413
|
+
@lib.command('materials-by-id')
|
|
414
|
+
@click.argument('material-ids', nargs=-1)
|
|
415
|
+
@click.option('--output-file', '-f', help='Optional file to output the JSON strings of '
|
|
416
|
+
'the objects. By default, it will be printed out to stdout',
|
|
417
|
+
type=click.File('w'), default='-', show_default=True)
|
|
418
|
+
def materials_by_id(material_ids, output_file):
|
|
419
|
+
"""Get several material definitions from the standards lib at once.
|
|
420
|
+
|
|
421
|
+
\b
|
|
422
|
+
Args:
|
|
423
|
+
material_ids: Any number of material identifiers to be retrieved from
|
|
424
|
+
the library.
|
|
425
|
+
"""
|
|
426
|
+
try:
|
|
427
|
+
mats = []
|
|
428
|
+
for mat_id in material_ids:
|
|
429
|
+
try:
|
|
430
|
+
mats.append(opaque_material_by_identifier(mat_id))
|
|
431
|
+
except ValueError:
|
|
432
|
+
mats.append(window_material_by_identifier(mat_id))
|
|
433
|
+
output_file.write(json.dumps([mat.to_dict() for mat in mats]))
|
|
434
|
+
except Exception as e:
|
|
435
|
+
_logger.exception(
|
|
436
|
+
'Retrieval from material library failed.\n{}'.format(e))
|
|
437
|
+
sys.exit(1)
|
|
438
|
+
else:
|
|
439
|
+
sys.exit(0)
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
@lib.command('constructions-by-id')
|
|
443
|
+
@click.argument('construction-ids', nargs=-1)
|
|
444
|
+
@click.option('--complete/--abridged', ' /-a', help='Flag to note whether an abridged '
|
|
445
|
+
'definition should be returned.', default=True, show_default=True)
|
|
446
|
+
@click.option('--output-file', '-f', help='Optional file to output the JSON strings of '
|
|
447
|
+
'the objects. By default, it will be printed out to stdout',
|
|
448
|
+
type=click.File('w'), default='-', show_default=True)
|
|
449
|
+
def constructions_by_id(construction_ids, complete, output_file):
|
|
450
|
+
"""Get several construction definitions from the standards lib at once.
|
|
451
|
+
|
|
452
|
+
\b
|
|
453
|
+
Args:
|
|
454
|
+
construction_ids: Any number of construction identifiers to be retrieved
|
|
455
|
+
from the library.
|
|
456
|
+
"""
|
|
457
|
+
try:
|
|
458
|
+
abridged = not complete
|
|
459
|
+
cons = []
|
|
460
|
+
for con_id in construction_ids:
|
|
461
|
+
try:
|
|
462
|
+
cons.append(opaque_construction_by_identifier(
|
|
463
|
+
con_id).to_dict(abridged=abridged))
|
|
464
|
+
except ValueError:
|
|
465
|
+
try:
|
|
466
|
+
cons.append(window_construction_by_identifier(
|
|
467
|
+
con_id).to_dict(abridged=abridged))
|
|
468
|
+
except ValueError:
|
|
469
|
+
cons.append(shade_construction_by_identifier(con_id).to_dict())
|
|
470
|
+
output_file.write(json.dumps(cons))
|
|
471
|
+
except Exception as e:
|
|
472
|
+
_logger.exception(
|
|
473
|
+
'Retrieval from construction library failed.\n{}'.format(e))
|
|
474
|
+
sys.exit(1)
|
|
475
|
+
else:
|
|
476
|
+
sys.exit(0)
|
|
477
|
+
|
|
478
|
+
|
|
479
|
+
@lib.command('construction-sets-by-id')
|
|
480
|
+
@click.argument('construction-set-ids', nargs=-1)
|
|
481
|
+
@click.option('--none-defaults/--include-defaults', ' /-d', help='Flag to note whether '
|
|
482
|
+
'default constructions in the set should be included in detail or should '
|
|
483
|
+
'be None.', default=True, show_default=True)
|
|
484
|
+
@click.option('--complete/--abridged', ' /-a', help='Flag to note whether an abridged '
|
|
485
|
+
'definition should be returned.',
|
|
486
|
+
default=True, show_default=True)
|
|
487
|
+
@click.option('--output-file', '-f', help='Optional file to output the JSON string of '
|
|
488
|
+
'the object. By default, it will be printed out to stdout',
|
|
489
|
+
type=click.File('w'), default='-', show_default=True)
|
|
490
|
+
def construction_sets_by_id(construction_set_ids, none_defaults, complete, output_file):
|
|
491
|
+
"""Get several construction set definitions from the standards lib at once.
|
|
492
|
+
|
|
493
|
+
\b
|
|
494
|
+
Args:
|
|
495
|
+
construction_set_ids: Any number of construction set identifiers to be retrieved
|
|
496
|
+
from the library.
|
|
497
|
+
"""
|
|
498
|
+
try:
|
|
499
|
+
abridged = not complete
|
|
500
|
+
cons = []
|
|
501
|
+
for con_id in construction_set_ids:
|
|
502
|
+
cons.append(construction_set_by_identifier(con_id))
|
|
503
|
+
output_file.write(json.dumps([con.to_dict(
|
|
504
|
+
none_for_defaults=none_defaults, abridged=abridged) for con in cons]))
|
|
505
|
+
except Exception as e:
|
|
506
|
+
_logger.exception(
|
|
507
|
+
'Retrieval from construction set library failed.\n{}'.format(e))
|
|
508
|
+
sys.exit(1)
|
|
509
|
+
else:
|
|
510
|
+
sys.exit(0)
|
|
511
|
+
|
|
512
|
+
|
|
513
|
+
@lib.command('schedule-type-limits-by-id')
|
|
514
|
+
@click.argument('schedule-type-limit-ids', nargs=-1)
|
|
515
|
+
@click.option('--output-file', '-f', help='Optional file to output the JSON strings of '
|
|
516
|
+
'the objects. By default, it will be printed out to stdout',
|
|
517
|
+
type=click.File('w'), default='-', show_default=True)
|
|
518
|
+
def schedule_type_limits_by_id(schedule_type_limit_ids, output_file):
|
|
519
|
+
"""Get several schedule type limit definitions from the standards lib at once.
|
|
520
|
+
|
|
521
|
+
\b
|
|
522
|
+
Args:
|
|
523
|
+
schedule_type_limit_ids: Any number of schedule type limit identifiers to be
|
|
524
|
+
retrieved from the library.
|
|
525
|
+
"""
|
|
526
|
+
try:
|
|
527
|
+
stls = []
|
|
528
|
+
for stl_id in schedule_type_limit_ids:
|
|
529
|
+
stls.append(schedule_type_limit_by_identifier(stl_id))
|
|
530
|
+
output_file.write(json.dumps([stl.to_dict() for stl in stls]))
|
|
531
|
+
except Exception as e:
|
|
532
|
+
_logger.exception(
|
|
533
|
+
'Retrieval from schedule type limit library failed.\n{}'.format(e))
|
|
534
|
+
sys.exit(1)
|
|
535
|
+
else:
|
|
536
|
+
sys.exit(0)
|
|
537
|
+
|
|
538
|
+
|
|
539
|
+
@lib.command('schedules-by-id')
|
|
540
|
+
@click.argument('schedule-ids', nargs=-1)
|
|
541
|
+
@click.option('--complete/--abridged', ' /-a', help='Flag to note whether an abridged '
|
|
542
|
+
'definition should be returned.', default=True, show_default=True)
|
|
543
|
+
@click.option('--output-file', '-f', help='Optional file to output the JSON strings of '
|
|
544
|
+
'the objects. By default, it will be printed out to stdout',
|
|
545
|
+
type=click.File('w'), default='-', show_default=True)
|
|
546
|
+
def schedules_by_id(schedule_ids, complete, output_file):
|
|
547
|
+
"""Get several schedule definitions from the standards lib at once.
|
|
548
|
+
|
|
549
|
+
\b
|
|
550
|
+
Args:
|
|
551
|
+
schedule_ids: Any number of schedule identifiers to be retrieved from
|
|
552
|
+
the library.
|
|
553
|
+
"""
|
|
554
|
+
try:
|
|
555
|
+
abridged = not complete
|
|
556
|
+
schs = []
|
|
557
|
+
for sch_id in schedule_ids:
|
|
558
|
+
schs.append(schedule_by_identifier(sch_id))
|
|
559
|
+
output_file.write(json.dumps([sch.to_dict(abridged=abridged) for sch in schs]))
|
|
560
|
+
except Exception as e:
|
|
561
|
+
_logger.exception('Retrieval from schedule library failed.\n{}'.format(e))
|
|
562
|
+
sys.exit(1)
|
|
563
|
+
else:
|
|
564
|
+
sys.exit(0)
|
|
565
|
+
|
|
566
|
+
|
|
567
|
+
@lib.command('program-types-by-id')
|
|
568
|
+
@click.argument('program-type-ids', nargs=-1)
|
|
569
|
+
@click.option('--complete/--abridged', ' /-a', help='Flag to note whether an abridged '
|
|
570
|
+
'definition should be returned.', default=True, show_default=True)
|
|
571
|
+
@click.option('--output-file', '-f', help='Optional file to output the JSON strings of '
|
|
572
|
+
'the objects. By default, it will be printed out to stdout',
|
|
573
|
+
type=click.File('w'), default='-', show_default=True)
|
|
574
|
+
def program_types_by_id(program_type_ids, complete, output_file):
|
|
575
|
+
"""Get several program type definitions from the standards lib at once.
|
|
576
|
+
|
|
577
|
+
\b
|
|
578
|
+
Args:
|
|
579
|
+
program_type_ids: Any number of program type identifiers to be retrieved
|
|
580
|
+
from the library.
|
|
581
|
+
"""
|
|
582
|
+
try:
|
|
583
|
+
abridged = not complete
|
|
584
|
+
prgs = []
|
|
585
|
+
for prg_id in program_type_ids:
|
|
586
|
+
prgs.append(program_type_by_identifier(prg_id))
|
|
587
|
+
output_file.write(json.dumps([prg.to_dict(abridged=abridged) for prg in prgs]))
|
|
588
|
+
except Exception as e:
|
|
589
|
+
_logger.exception('Retrieval from program type library failed.\n{}'.format(e))
|
|
590
|
+
sys.exit(1)
|
|
591
|
+
else:
|
|
592
|
+
sys.exit(0)
|
|
593
|
+
|
|
594
|
+
|
|
595
|
+
@lib.command('to-model-properties')
|
|
596
|
+
@click.option(
|
|
597
|
+
'--standards-folder', '-s', default=None, help='A directory containing sub-folders '
|
|
598
|
+
'of resource objects (constructions, constructionsets, schedules, programtypes) '
|
|
599
|
+
'to be loaded as ModelEnergyProperties. Note that this standards folder MUST '
|
|
600
|
+
'contain these sub-folders. Each sub-folder can contain JSON files of objects '
|
|
601
|
+
'following honeybee schema or IDF files (if appropriate). If unspecified, the '
|
|
602
|
+
'current user honeybee default standards folder will be used.', type=click.Path(
|
|
603
|
+
exists=True, file_okay=False, dir_okay=True, resolve_path=True)
|
|
604
|
+
)
|
|
605
|
+
@click.option(
|
|
606
|
+
'--exclude-abridged/--include-abridged', ' /-a', help='Flag to note whether '
|
|
607
|
+
'fully abridged objects in the user standards library should be included in '
|
|
608
|
+
'the output file. This is useful when some of the sub-objects contained within '
|
|
609
|
+
'the user standards are referenced in another installed standards package that '
|
|
610
|
+
'is not a part of the user personal standards library (eg. honeybee-energy-'
|
|
611
|
+
'standards). When abridged objects are excluded, only objects that contain all '
|
|
612
|
+
'sub-objects within the user library will be in the output-file.',
|
|
613
|
+
default=True, show_default=True
|
|
614
|
+
)
|
|
615
|
+
@click.option(
|
|
616
|
+
'--output-file', '-f', help='Optional JSON file to output the JSON string of '
|
|
617
|
+
'the translation. By default this will be printed out to stdout',
|
|
618
|
+
type=click.File('w'), default='-', show_default=True
|
|
619
|
+
)
|
|
620
|
+
def to_model_properties(standards_folder, exclude_abridged, output_file):
|
|
621
|
+
"""Translate a lib folder of standards to a JSON of honeybee ModelEnergyProperties.
|
|
622
|
+
|
|
623
|
+
This is useful in workflows where one must import everything within a user's
|
|
624
|
+
standards folder and requires all objects to be in a consistent format.
|
|
625
|
+
All objects in the resulting ModelEnergyProperties will be abridged and
|
|
626
|
+
duplicated objects in the folder will be removed such that there
|
|
627
|
+
is only one of each object.
|
|
628
|
+
"""
|
|
629
|
+
try:
|
|
630
|
+
# set the folder to the default standards_folder if unspecified
|
|
631
|
+
folder = standards_folder if standards_folder is not None else \
|
|
632
|
+
folders.standards_data_folder
|
|
633
|
+
|
|
634
|
+
# load schedules from the standards folder
|
|
635
|
+
sch_folder = os.path.join(folder, 'schedules')
|
|
636
|
+
type_lim = load_type_limits_from_folder(sch_folder)
|
|
637
|
+
tl_with_default = type_lim.copy()
|
|
638
|
+
tl_with_default.update(_schedule_type_limits)
|
|
639
|
+
scheds = load_schedules_from_folder(sch_folder, tl_with_default)
|
|
640
|
+
|
|
641
|
+
# load program types from the standards folder
|
|
642
|
+
prog_folder = os.path.join(folder, 'programtypes')
|
|
643
|
+
all_progs, misc_p_scheds = load_programtypes_from_folder(prog_folder, scheds)
|
|
644
|
+
|
|
645
|
+
# load constructions from the standards folder
|
|
646
|
+
con_folder = os.path.join(folder, 'constructions')
|
|
647
|
+
opaque_m, window_m = load_materials_from_folder(con_folder)
|
|
648
|
+
all_m = opaque_m.copy()
|
|
649
|
+
all_m.update(window_m)
|
|
650
|
+
opaque_c, window_c, shade_c, opaque_mc, window_mc, misc_m, misc_c_scheds = \
|
|
651
|
+
load_constructions_from_folder(con_folder, all_m, scheds)
|
|
652
|
+
all_m.update(opaque_mc)
|
|
653
|
+
all_m.update(window_mc)
|
|
654
|
+
all_c = opaque_c.copy()
|
|
655
|
+
all_c.update(window_c)
|
|
656
|
+
all_c.update(shade_c)
|
|
657
|
+
|
|
658
|
+
# load construction sets from the standards folder
|
|
659
|
+
con_set_folder = os.path.join(folder, 'constructionsets')
|
|
660
|
+
all_con_sets, misc_c = load_constructionsets_from_folder(con_set_folder, all_c)
|
|
661
|
+
|
|
662
|
+
# get sets of unique objects
|
|
663
|
+
all_scheds = set(list(scheds.values()) + misc_p_scheds + misc_c_scheds)
|
|
664
|
+
sched_tl = [sch.schedule_type_limit for sch in all_scheds
|
|
665
|
+
if sch.schedule_type_limit is not None]
|
|
666
|
+
all_typ_lim = set(list(type_lim.values()) + sched_tl)
|
|
667
|
+
all_cons = set(list(all_c.values()) + misc_c)
|
|
668
|
+
misc_c_mats = []
|
|
669
|
+
for m_con in misc_c:
|
|
670
|
+
try:
|
|
671
|
+
misc_c_mats.extend(m_con.materials)
|
|
672
|
+
if m_con.has_frame:
|
|
673
|
+
misc_c_mats.append(m_con.frame)
|
|
674
|
+
if m_con.has_shade:
|
|
675
|
+
if m_con.is_switchable_glazing:
|
|
676
|
+
misc_c_mats.append(m_con.switched_glass_material)
|
|
677
|
+
except AttributeError: # not a construction with materials
|
|
678
|
+
pass
|
|
679
|
+
all_mats = set(list(all_m.values()) + misc_m + misc_c_mats)
|
|
680
|
+
|
|
681
|
+
# add all object dictionaries into one object
|
|
682
|
+
base = {'type': 'ModelEnergyProperties'}
|
|
683
|
+
base['schedule_type_limits'] = [tl.to_dict() for tl in all_typ_lim]
|
|
684
|
+
base['schedules'] = [sch.to_dict(abridged=True) for sch in all_scheds]
|
|
685
|
+
base['program_types'] = \
|
|
686
|
+
[pro.to_dict(abridged=True) for pro in all_progs.values()]
|
|
687
|
+
base['materials'] = [m.to_dict() for m in all_mats]
|
|
688
|
+
base['constructions'] = []
|
|
689
|
+
for con in all_cons:
|
|
690
|
+
try:
|
|
691
|
+
base['constructions'].append(con.to_dict(abridged=True))
|
|
692
|
+
except TypeError: # no abridged option
|
|
693
|
+
base['constructions'].append(con.to_dict())
|
|
694
|
+
base['construction_sets'] = \
|
|
695
|
+
[cs.to_dict(abridged=True) for cs in all_con_sets.values()]
|
|
696
|
+
|
|
697
|
+
# if set to include abridged, add any of such objects to the dictionary
|
|
698
|
+
if not exclude_abridged:
|
|
699
|
+
_add_abridged_objects(base['schedules'], sch_folder, ('ScheduleTypeLimit',))
|
|
700
|
+
_add_abridged_objects(base['program_types'], prog_folder)
|
|
701
|
+
_add_abridged_objects(base['constructions'], con_folder, MATERIAL_TYPES)
|
|
702
|
+
_add_abridged_objects(base['construction_sets'], con_set_folder)
|
|
703
|
+
|
|
704
|
+
# write out the JSON file
|
|
705
|
+
output_file.write(json.dumps(base, indent=4))
|
|
706
|
+
except Exception as e:
|
|
707
|
+
_logger.exception('Loading standards to properties failed.\n{}'.format(e))
|
|
708
|
+
sys.exit(1)
|
|
709
|
+
else:
|
|
710
|
+
sys.exit(0)
|
|
711
|
+
|
|
712
|
+
|
|
713
|
+
def _add_abridged_objects(model_prop_array, lib_folder, ex_types=()):
|
|
714
|
+
"""Add abridged resource objects to an existing model properties array.
|
|
715
|
+
|
|
716
|
+
Args:
|
|
717
|
+
model_prop_array: An array of resource object dictionaries from a
|
|
718
|
+
ModelEnergyProperties dictionary.
|
|
719
|
+
lib_folder: A folder from which abridged objects will be loaded.
|
|
720
|
+
exclude_types: An optional tuple of object types to be excluded
|
|
721
|
+
from the result.
|
|
722
|
+
"""
|
|
723
|
+
obj_ids = set(obj['identifier'] for obj in model_prop_array)
|
|
724
|
+
for f in os.listdir(lib_folder):
|
|
725
|
+
f_path = os.path.join(lib_folder, f)
|
|
726
|
+
if os.path.isfile(f_path) and f_path.endswith('.json'):
|
|
727
|
+
with open(f_path) as json_file:
|
|
728
|
+
data = json.load(json_file)
|
|
729
|
+
if 'type' in data: # single object
|
|
730
|
+
if data['identifier'] not in obj_ids and data['type'] not in ex_types:
|
|
731
|
+
model_prop_array.append(data)
|
|
732
|
+
else: # a collection of several objects
|
|
733
|
+
for obj_identifier in data:
|
|
734
|
+
if obj_identifier not in obj_ids and \
|
|
735
|
+
data[obj_identifier]['type'] not in ex_types:
|
|
736
|
+
model_prop_array.append(data[obj_identifier])
|
|
737
|
+
|
|
738
|
+
|
|
739
|
+
@lib.command('purge')
|
|
740
|
+
@click.option(
|
|
741
|
+
'--standards-folder', '-s', default=None, help='A directory containing sub-folders '
|
|
742
|
+
'of resource objects (constructions, constructionsets, schedules, programtypes) '
|
|
743
|
+
'to be purged of files. If unspecified, the current user honeybee '
|
|
744
|
+
'default standards folder will be used.', type=click.Path(
|
|
745
|
+
exists=True, file_okay=False, dir_okay=True, resolve_path=True)
|
|
746
|
+
)
|
|
747
|
+
@click.option(
|
|
748
|
+
'--json-only/--all', ' /-a', help='Flag to note whether only JSON files should '
|
|
749
|
+
'be purged from the library or all files should be purged, including IDF files. '
|
|
750
|
+
'Given that all objects added to the library through the `add` command will always '
|
|
751
|
+
'be JSON, only purging the JSONs is useful when one wishes to clear these objects '
|
|
752
|
+
'while preserving objects that originated from other sources.',
|
|
753
|
+
default=True, show_default=True
|
|
754
|
+
)
|
|
755
|
+
@click.option(
|
|
756
|
+
'--backup/--no-backup', ' /-xb', help='Flag to note whether a backup .zip file '
|
|
757
|
+
'of the user standards library should be made before the purging operation. '
|
|
758
|
+
'This is done by default in case the user ever wants to recover their old '
|
|
759
|
+
'standards but can be turned off if a backup is not desired.',
|
|
760
|
+
default=True, show_default=True
|
|
761
|
+
)
|
|
762
|
+
@click.option(
|
|
763
|
+
'--log-file', '-log', help='Optional file to output a log of the purging process. '
|
|
764
|
+
'By default this will be printed out to stdout',
|
|
765
|
+
type=click.File('w'), default='-', show_default=True
|
|
766
|
+
)
|
|
767
|
+
def purge_lib(standards_folder, json_only, backup, log_file):
|
|
768
|
+
"""Purge the library of all user energy standards that it contains.
|
|
769
|
+
|
|
770
|
+
This is useful when a user's standard library has become filled with duplicated
|
|
771
|
+
objects or the user wishes to start fresh by re-exporting updated objects.
|
|
772
|
+
"""
|
|
773
|
+
try:
|
|
774
|
+
# set the folder to the default standards_folder if unspecified
|
|
775
|
+
folder = standards_folder if standards_folder is not None else \
|
|
776
|
+
folders.standards_data_folder
|
|
777
|
+
resources = ('constructions', 'constructionsets', 'schedules', 'programtypes')
|
|
778
|
+
sub_folders = [os.path.join(folder, std) for std in resources]
|
|
779
|
+
|
|
780
|
+
# make a backup of the folder if requested
|
|
781
|
+
if backup:
|
|
782
|
+
r_names, s_files, s_paths = [], [], []
|
|
783
|
+
for sf, r_name in zip(sub_folders, resources):
|
|
784
|
+
for s_file in os.listdir(sf):
|
|
785
|
+
s_path = os.path.join(sf, s_file)
|
|
786
|
+
if os.path.isfile(s_path):
|
|
787
|
+
r_names.append(r_name)
|
|
788
|
+
s_files.append(s_file)
|
|
789
|
+
s_paths.append(s_path)
|
|
790
|
+
if len(s_paths) != 0: # there are resources to back up
|
|
791
|
+
backup_name = '.standards_backup_{}.zip'.format(
|
|
792
|
+
str(datetime.now()).split('.')[0].replace(':', '-'))
|
|
793
|
+
backup_file = os.path.join(os.path.dirname(folder), backup_name)
|
|
794
|
+
with zipfile.ZipFile(backup_file, 'w') as zf:
|
|
795
|
+
for r_name, s_file, s_path in zip(r_names, s_files, s_paths):
|
|
796
|
+
zf.write(s_path, os.path.join(r_name, s_file))
|
|
797
|
+
|
|
798
|
+
# loop through the sub-folders and delete the files
|
|
799
|
+
rel_files = []
|
|
800
|
+
for sf in sub_folders:
|
|
801
|
+
for s_file in os.listdir(sf):
|
|
802
|
+
s_path = os.path.join(sf, s_file)
|
|
803
|
+
if os.path.isfile(s_path):
|
|
804
|
+
if json_only:
|
|
805
|
+
if s_file.lower().endswith('.json'):
|
|
806
|
+
rel_files.append(s_path)
|
|
807
|
+
else:
|
|
808
|
+
rel_files.append(s_path)
|
|
809
|
+
purged_files, fail_files = [], []
|
|
810
|
+
for rf in rel_files:
|
|
811
|
+
try:
|
|
812
|
+
os.remove(rf)
|
|
813
|
+
purged_files.append(rf)
|
|
814
|
+
except Exception:
|
|
815
|
+
fail_files.append(rf)
|
|
816
|
+
|
|
817
|
+
# report all of the deleted files in the log file
|
|
818
|
+
if len(rel_files) == 0:
|
|
819
|
+
log_file.write('The standards folder is empty so no files were removed.')
|
|
820
|
+
if len(purged_files) != 0:
|
|
821
|
+
msg = 'The following files were removed in the purging ' \
|
|
822
|
+
'operations:\n{}\n'.format(' \n'.join(purged_files))
|
|
823
|
+
log_file.write(msg)
|
|
824
|
+
if len(fail_files) != 0:
|
|
825
|
+
msg = 'The following files could not be removed in the purging ' \
|
|
826
|
+
'operations:\n{}\n'.format(' \n'.join(fail_files))
|
|
827
|
+
log_file.write(msg)
|
|
828
|
+
except Exception as e:
|
|
829
|
+
_logger.exception('Purging user standards library failed.\n{}'.format(e))
|
|
830
|
+
sys.exit(1)
|
|
831
|
+
else:
|
|
832
|
+
sys.exit(0)
|
|
833
|
+
|
|
834
|
+
|
|
835
|
+
@lib.command('add')
|
|
836
|
+
@click.argument('properties-file', type=click.Path(
|
|
837
|
+
exists=True, file_okay=True, dir_okay=False, resolve_path=True))
|
|
838
|
+
@click.option(
|
|
839
|
+
'--standards-folder', '-s', default=None, help='A directory containing sub-folders '
|
|
840
|
+
'of resource objects (constructions, constructionsets, schedules, programtypes) '
|
|
841
|
+
'to which the properties-file objects will be added. If unspecified, the current '
|
|
842
|
+
'user honeybee default standards folder will be used.', type=click.Path(
|
|
843
|
+
exists=True, file_okay=False, dir_okay=True, resolve_path=True)
|
|
844
|
+
)
|
|
845
|
+
@click.option(
|
|
846
|
+
'--log-file', '-log', help='Optional file to output a log of the purging process. '
|
|
847
|
+
'By default this will be printed out to stdout',
|
|
848
|
+
type=click.File('w'), default='-', show_default=True
|
|
849
|
+
)
|
|
850
|
+
def add_to_lib(properties_file, standards_folder, log_file):
|
|
851
|
+
"""Add an object or set of objects to the user's standard library.
|
|
852
|
+
|
|
853
|
+
\b
|
|
854
|
+
Args:
|
|
855
|
+
properties_file: A JSON file of a ModelEnergyProperties object containing
|
|
856
|
+
the objects to be written into the user standards library. All sub-objects
|
|
857
|
+
within this ModelEnergyProperties object must be Abridged if the sub-object
|
|
858
|
+
has an abridged schema and these abridged schemas are allowed to
|
|
859
|
+
reference either other objects in the ModelEnergyProperties or existing
|
|
860
|
+
objects within the standards library.
|
|
861
|
+
"""
|
|
862
|
+
try:
|
|
863
|
+
# set the folder to the default standards_folder if unspecified
|
|
864
|
+
folder = standards_folder if standards_folder is not None else \
|
|
865
|
+
folders.standards_data_folder
|
|
866
|
+
|
|
867
|
+
# load up the model energy properties from the JSON
|
|
868
|
+
with open(properties_file) as inf:
|
|
869
|
+
data = json.load(inf)
|
|
870
|
+
assert 'type' in data, 'Properties file lacks required type key.'
|
|
871
|
+
assert data['type'] == 'ModelEnergyProperties', 'Expected ' \
|
|
872
|
+
'ModelEnergyProperties JSON object. Got {}.'.format(data['type'])
|
|
873
|
+
success_objects, dup_id_objects, mis_dep_objects = [], [], []
|
|
874
|
+
|
|
875
|
+
# extract, check, and write the schedule type limits
|
|
876
|
+
sch_tl = {}
|
|
877
|
+
if 'schedule_type_limits' in data and data['schedule_type_limits'] is not None:
|
|
878
|
+
for stl_obj in data['schedule_type_limits']:
|
|
879
|
+
msg = _object_message('Schedule Type Limit', stl_obj)
|
|
880
|
+
if stl_obj['identifier'] in _schedule_type_limits:
|
|
881
|
+
dup_id_objects.append(msg)
|
|
882
|
+
else:
|
|
883
|
+
try:
|
|
884
|
+
sch_tl[stl_obj['identifier']] = \
|
|
885
|
+
ScheduleTypeLimit.from_dict(stl_obj)
|
|
886
|
+
success_objects.append(msg)
|
|
887
|
+
except (ValueError, KeyError, AssertionError):
|
|
888
|
+
mis_dep_objects.append(msg)
|
|
889
|
+
if sch_tl:
|
|
890
|
+
sch_tl_dict = {tl.identifier: tl.to_dict() for tl in sch_tl.values()}
|
|
891
|
+
stl_json = os.path.join(folder, 'schedules', 'custom_type_limits.json')
|
|
892
|
+
_update_user_json(sch_tl_dict, stl_json)
|
|
893
|
+
|
|
894
|
+
# extract, check, and write the schedules
|
|
895
|
+
scheds = {}
|
|
896
|
+
if 'schedules' in data and data['schedules'] is not None:
|
|
897
|
+
for sch in data['schedules']:
|
|
898
|
+
msg = _object_message('Schedule', sch)
|
|
899
|
+
if sch['identifier'] in SCHEDULES:
|
|
900
|
+
dup_id_objects.append(msg)
|
|
901
|
+
else:
|
|
902
|
+
try:
|
|
903
|
+
scheds[sch['identifier']] = \
|
|
904
|
+
lib_dict_abridged_to_schedule(sch, sch_tl)
|
|
905
|
+
success_objects.append(msg)
|
|
906
|
+
except (ValueError, KeyError, AssertionError):
|
|
907
|
+
mis_dep_objects.append(msg)
|
|
908
|
+
if scheds:
|
|
909
|
+
sch_dict = {s.identifier: s.to_dict(abridged=True) for s in scheds.values()}
|
|
910
|
+
sch_json = os.path.join(folder, 'schedules', 'custom_schedules.json')
|
|
911
|
+
_update_user_json(sch_dict, sch_json)
|
|
912
|
+
|
|
913
|
+
# extract, check, and write the program types
|
|
914
|
+
progs = {}
|
|
915
|
+
if 'program_types' in data and data['program_types'] is not None:
|
|
916
|
+
for prog in data['program_types']:
|
|
917
|
+
msg = _object_message('Program', prog)
|
|
918
|
+
if prog['identifier'] in PROGRAM_TYPES:
|
|
919
|
+
dup_id_objects.append(msg)
|
|
920
|
+
else:
|
|
921
|
+
try:
|
|
922
|
+
progs[prog['identifier']] = \
|
|
923
|
+
lib_dict_abridged_to_program_type(prog, scheds)
|
|
924
|
+
success_objects.append(msg)
|
|
925
|
+
except (ValueError, KeyError, AssertionError):
|
|
926
|
+
mis_dep_objects.append(msg)
|
|
927
|
+
if progs:
|
|
928
|
+
prog_dict = {p.identifier: p.to_dict(abridged=True) for p in progs.values()}
|
|
929
|
+
program_json = os.path.join(folder, 'programtypes', 'custom_programs.json')
|
|
930
|
+
_update_user_json(prog_dict, program_json)
|
|
931
|
+
|
|
932
|
+
# extract, check, and write the materials
|
|
933
|
+
mats = {}
|
|
934
|
+
if 'materials' in data and data['materials'] is not None and \
|
|
935
|
+
len(data['materials']) != 0:
|
|
936
|
+
all_mats = OPAQUE_MATERIALS + WINDOW_MATERIALS
|
|
937
|
+
for mat_obj in data['materials']:
|
|
938
|
+
msg = _object_message('Material', mat_obj)
|
|
939
|
+
if mat_obj['identifier'] in all_mats:
|
|
940
|
+
dup_id_objects.append(msg)
|
|
941
|
+
else:
|
|
942
|
+
try:
|
|
943
|
+
mats[mat_obj['identifier']] = dict_to_material(mat_obj)
|
|
944
|
+
success_objects.append(msg)
|
|
945
|
+
except (ValueError, KeyError, AssertionError):
|
|
946
|
+
mis_dep_objects.append(msg)
|
|
947
|
+
if mats:
|
|
948
|
+
mat_dict = {m.identifier: m.to_dict() for m in mats.values()}
|
|
949
|
+
mat_json = os.path.join(folder, 'constructions', 'custom_materials.json')
|
|
950
|
+
_update_user_json(mat_dict, mat_json)
|
|
951
|
+
|
|
952
|
+
# extract, check, and write the constructions
|
|
953
|
+
cons = {}
|
|
954
|
+
if 'constructions' in data and data['constructions'] is not None and \
|
|
955
|
+
len(data['constructions']) != 0:
|
|
956
|
+
all_cons = OPAQUE_CONSTRUCTIONS + WINDOW_CONSTRUCTIONS + SHADE_CONSTRUCTIONS
|
|
957
|
+
for con in data['constructions']:
|
|
958
|
+
msg = _object_message('Construction', con)
|
|
959
|
+
if con['identifier'] in all_cons:
|
|
960
|
+
dup_id_objects.append(msg)
|
|
961
|
+
else:
|
|
962
|
+
try:
|
|
963
|
+
cons[con['identifier']] = \
|
|
964
|
+
lib_dict_abridged_to_construction(con, mats, scheds)
|
|
965
|
+
success_objects.append(msg)
|
|
966
|
+
except (ValueError, KeyError, AssertionError):
|
|
967
|
+
mis_dep_objects.append(msg)
|
|
968
|
+
if cons:
|
|
969
|
+
con_dict = {}
|
|
970
|
+
for c in cons.values():
|
|
971
|
+
try:
|
|
972
|
+
con_dict[c.identifier] = c.to_dict(abridged=True)
|
|
973
|
+
except TypeError: # ShadeConstruction
|
|
974
|
+
con_dict[c.identifier] = c.to_dict()
|
|
975
|
+
con_json = os.path.join(folder, 'constructions', 'custom_constructions.json')
|
|
976
|
+
_update_user_json(con_dict, con_json)
|
|
977
|
+
|
|
978
|
+
# extract, check, and write the construction sets
|
|
979
|
+
con_sets = {}
|
|
980
|
+
if 'construction_sets' in data and data['construction_sets'] is not None:
|
|
981
|
+
for cs in data['construction_sets']:
|
|
982
|
+
msg = _object_message('Construction Set', cs)
|
|
983
|
+
if cs['identifier'] in CONSTRUCTION_SETS:
|
|
984
|
+
dup_id_objects.append(msg)
|
|
985
|
+
else:
|
|
986
|
+
try:
|
|
987
|
+
con_sets[cs['identifier']] = \
|
|
988
|
+
lib_dict_abridged_to_construction_set(cs, cons)
|
|
989
|
+
success_objects.append(msg)
|
|
990
|
+
except (ValueError, KeyError, AssertionError):
|
|
991
|
+
mis_dep_objects.append(msg)
|
|
992
|
+
if con_sets:
|
|
993
|
+
cs_dict = {c.identifier: c.to_dict(abridged=True) for c in con_sets.values()}
|
|
994
|
+
cs_json = os.path.join(folder, 'constructionsets', 'custom_sets.json')
|
|
995
|
+
_update_user_json(cs_dict, cs_json)
|
|
996
|
+
|
|
997
|
+
# write a report of the objects that were or were not added
|
|
998
|
+
success_objects, dup_id_objects, mis_dep_objects
|
|
999
|
+
m_start = 'THESE OBJECTS'
|
|
1000
|
+
if len(success_objects) != 0:
|
|
1001
|
+
msg = '{} WERE SUCCESSFULLY ADDED TO THE STANDARDS LIBRARY:\n{}\n\n'.format(
|
|
1002
|
+
m_start, ' \n'.join(success_objects))
|
|
1003
|
+
log_file.write(msg)
|
|
1004
|
+
if len(dup_id_objects) != 0:
|
|
1005
|
+
msg = '{} WERE NOT ADDED SINCE THEY ALREADY EXIST IN THE STANDARDS ' \
|
|
1006
|
+
'LIBRARY:\n{}\n\n'.format(m_start, ' \n'.join(dup_id_objects))
|
|
1007
|
+
log_file.write(msg)
|
|
1008
|
+
if len(mis_dep_objects) != 0:
|
|
1009
|
+
msg = '{} WERE NOT ADDED BECAUSE THEY ARE INVALID OR ARE MISSING ' \
|
|
1010
|
+
'DEPENDENT OBJECTS:\n{}\n\n'.format(m_start, ' \n'.join(mis_dep_objects))
|
|
1011
|
+
log_file.write(msg)
|
|
1012
|
+
except Exception as e:
|
|
1013
|
+
_logger.exception('Adding to user standards library failed.\n{}'.format(e))
|
|
1014
|
+
sys.exit(1)
|
|
1015
|
+
else:
|
|
1016
|
+
sys.exit(0)
|
|
1017
|
+
|
|
1018
|
+
|
|
1019
|
+
def _object_message(obj_type, obj_dict):
|
|
1020
|
+
"""Get the reporting message of an object to add to the user library."""
|
|
1021
|
+
obj_name = obj_dict['display_name'] if 'display_name' in obj_dict and \
|
|
1022
|
+
obj_dict['display_name'] is not None else obj_dict['identifier']
|
|
1023
|
+
return '{}: {}'.format(obj_type, obj_name)
|
|
1024
|
+
|
|
1025
|
+
|
|
1026
|
+
def _update_user_json(dict_to_add, user_json, indent=4):
|
|
1027
|
+
"""Update a JSON file within a user standards folder."""
|
|
1028
|
+
if os.path.isfile(user_json):
|
|
1029
|
+
with open(user_json) as inf:
|
|
1030
|
+
exist_data = json.load(inf)
|
|
1031
|
+
dict_to_add.update(exist_data)
|
|
1032
|
+
with open(user_json, 'w') as outf:
|
|
1033
|
+
json.dump(dict_to_add, outf, indent=indent)
|
|
1034
|
+
|
|
1035
|
+
|
|
1036
|
+
@lib.command('add-osm')
|
|
1037
|
+
@click.argument('osm-file', type=click.Path(
|
|
1038
|
+
exists=True, file_okay=True, dir_okay=False, resolve_path=True))
|
|
1039
|
+
@click.option(
|
|
1040
|
+
'--standards-folder', '-s', default=None, help='A directory containing sub-folders '
|
|
1041
|
+
'of resource objects (constructions, constructionsets, schedules, programtypes) '
|
|
1042
|
+
'to which the properties-file objects will be added. If unspecified, the current '
|
|
1043
|
+
'user honeybee default standards folder will be used.', type=click.Path(
|
|
1044
|
+
exists=True, file_okay=False, dir_okay=True, resolve_path=True))
|
|
1045
|
+
@click.option(
|
|
1046
|
+
'--indent', '-i', help='Optional integer to specify the indentation in '
|
|
1047
|
+
'the output JSON file. Specifying an value here can produce more read-able'
|
|
1048
|
+
' JSONs.', type=int, default=None, show_default=True)
|
|
1049
|
+
@click.option(
|
|
1050
|
+
'--osw-folder', '-osw', help='Folder on this computer, into which the '
|
|
1051
|
+
'working files will be written. If None, it will be written into the a '
|
|
1052
|
+
'temp folder in the default simulation folder.', default=None,
|
|
1053
|
+
type=click.Path(file_okay=False, dir_okay=True, resolve_path=True))
|
|
1054
|
+
@click.option(
|
|
1055
|
+
'--log-file', '-log', help='Optional file to output a log of the addition process. '
|
|
1056
|
+
'By default this will be printed out to stdout',
|
|
1057
|
+
type=click.File('w'), default='-', show_default=True)
|
|
1058
|
+
def add_osm_to_lib(osm_file, standards_folder, indent, osw_folder, log_file):
|
|
1059
|
+
"""Add all objects within an OSM file to the user's standard library.
|
|
1060
|
+
|
|
1061
|
+
\b
|
|
1062
|
+
Args:
|
|
1063
|
+
osm_file: Path to a OpenStudio Model (OSM) file.
|
|
1064
|
+
"""
|
|
1065
|
+
try:
|
|
1066
|
+
# set the folder to the default standards_folder if unspecified
|
|
1067
|
+
folder = standards_folder if standards_folder is not None else \
|
|
1068
|
+
folders.standards_data_folder
|
|
1069
|
+
# translate the OSM to a HBJSON
|
|
1070
|
+
model_dict = _translate_osm_to_hbjson(osm_file, osw_folder)
|
|
1071
|
+
base_name = os.path.basename(osm_file).lower().replace('.osm', '')
|
|
1072
|
+
|
|
1073
|
+
# write each of the objects from the dictionary into the standards folder
|
|
1074
|
+
added_objs = []
|
|
1075
|
+
# write the materials
|
|
1076
|
+
con_folder = os.path.join(folder, 'constructions')
|
|
1077
|
+
mat_json = os.path.join(con_folder, '{}_materials.json'.format(base_name))
|
|
1078
|
+
mat_dict = {}
|
|
1079
|
+
for mat in model_dict['properties']['energy']['materials']:
|
|
1080
|
+
if mat['identifier'] not in _default_mats:
|
|
1081
|
+
added_objs.append(mat['identifier'])
|
|
1082
|
+
mat_dict[mat['identifier']] = mat
|
|
1083
|
+
_update_user_json(mat_dict, mat_json, indent)
|
|
1084
|
+
# write the constructions
|
|
1085
|
+
con_json = os.path.join(con_folder, '{}_constructions.json'.format(base_name))
|
|
1086
|
+
con_dict = {}
|
|
1087
|
+
for con in model_dict['properties']['energy']['constructions']:
|
|
1088
|
+
if con['identifier'] not in _default_constrs:
|
|
1089
|
+
added_objs.append(con['identifier'])
|
|
1090
|
+
con_dict[con['identifier']] = con
|
|
1091
|
+
_update_user_json(con_dict, con_json, indent)
|
|
1092
|
+
# write the construction sets
|
|
1093
|
+
c_set_folder = os.path.join(folder, 'constructionsets')
|
|
1094
|
+
c_set_json = os.path.join(c_set_folder, '{}.json'.format(base_name))
|
|
1095
|
+
c_set_dict = {}
|
|
1096
|
+
for c_set in model_dict['properties']['energy']['construction_sets']:
|
|
1097
|
+
if c_set['identifier'] not in _default_sets:
|
|
1098
|
+
added_objs.append(c_set['identifier'])
|
|
1099
|
+
c_set_dict[c_set['identifier']] = c_set
|
|
1100
|
+
_update_user_json(c_set_dict, c_set_json, indent)
|
|
1101
|
+
# write the type limits
|
|
1102
|
+
sched_folder = os.path.join(folder, 'schedules')
|
|
1103
|
+
stl_json = os.path.join(sched_folder, '{}_type_limits.json'.format(base_name))
|
|
1104
|
+
sch_tl_dict = {}
|
|
1105
|
+
for stl in model_dict['properties']['energy']['schedule_type_limits']:
|
|
1106
|
+
if stl['identifier'] not in _schedule_type_limits:
|
|
1107
|
+
added_objs.append(stl['identifier'])
|
|
1108
|
+
sch_tl_dict[stl['identifier']] = stl
|
|
1109
|
+
_update_user_json(sch_tl_dict, stl_json, indent)
|
|
1110
|
+
# write the schedules
|
|
1111
|
+
sch_json = os.path.join(sched_folder, '{}_schedules.json'.format(base_name))
|
|
1112
|
+
sch_dict = {}
|
|
1113
|
+
for sch in model_dict['properties']['energy']['schedules']:
|
|
1114
|
+
if sch['identifier'] not in _default_schedules:
|
|
1115
|
+
added_objs.append(sch['identifier'])
|
|
1116
|
+
sch_dict[sch['identifier']] = sch
|
|
1117
|
+
_update_user_json(sch_dict, sch_json, indent)
|
|
1118
|
+
# write the programs
|
|
1119
|
+
prog_folder = os.path.join(folder, 'programtypes')
|
|
1120
|
+
prog_json = os.path.join(prog_folder, '{}.json'.format(base_name))
|
|
1121
|
+
prog_dict = {}
|
|
1122
|
+
for prog in model_dict['properties']['energy']['program_types']:
|
|
1123
|
+
if prog['identifier'] not in _default_programs:
|
|
1124
|
+
added_objs.append(prog['identifier'])
|
|
1125
|
+
prog_dict[prog['identifier']] = prog
|
|
1126
|
+
_update_user_json(prog_dict, prog_json, indent)
|
|
1127
|
+
|
|
1128
|
+
# write a message into the log file
|
|
1129
|
+
msg = 'The following objects were successfully added:\n{}'.format(
|
|
1130
|
+
'\n'.join(added_objs))
|
|
1131
|
+
log_file.write(msg)
|
|
1132
|
+
except Exception as e:
|
|
1133
|
+
_logger.exception('Adding to user standards library failed.\n{}'.format(e))
|
|
1134
|
+
sys.exit(1)
|
|
1135
|
+
else:
|
|
1136
|
+
sys.exit(0)
|
|
1137
|
+
|
|
1138
|
+
|
|
1139
|
+
def _translate_osm_to_hbjson(osm_file, osw_folder):
|
|
1140
|
+
"""Translate an OSM to a HBJSON for use in resource extraction commands."""
|
|
1141
|
+
# come up with a temporary path to write the HBJSON
|
|
1142
|
+
out_directory = os.path.join(
|
|
1143
|
+
hb_folders.default_simulation_folder, 'temp_translate')
|
|
1144
|
+
f_name = os.path.basename(osm_file).lower().replace('.osm', '.hbjson')
|
|
1145
|
+
out_path = os.path.join(out_directory, f_name)
|
|
1146
|
+
# run the OSW to translate the OSM to HBJSON
|
|
1147
|
+
osw = from_osm_osw(osm_file, out_path, osw_folder)
|
|
1148
|
+
# load the resulting HBJSON to a dictionary and return it
|
|
1149
|
+
_, idf = run_osw(osw, silent=True)
|
|
1150
|
+
if idf is not None and os.path.isfile(idf):
|
|
1151
|
+
with open(out_path) as json_file:
|
|
1152
|
+
return json.load(json_file)
|
|
1153
|
+
else:
|
|
1154
|
+
_parse_os_cli_failure(os.path.dirname(osw))
|