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.
Files changed (162) hide show
  1. honeybee_energy/__init__.py +24 -0
  2. honeybee_energy/__main__.py +4 -0
  3. honeybee_energy/_extend_honeybee.py +145 -0
  4. honeybee_energy/altnumber.py +21 -0
  5. honeybee_energy/baseline/__init__.py +2 -0
  6. honeybee_energy/baseline/create.py +608 -0
  7. honeybee_energy/baseline/data/__init__.py +1 -0
  8. honeybee_energy/baseline/data/constructions.csv +64 -0
  9. honeybee_energy/baseline/data/fen_ratios.csv +15 -0
  10. honeybee_energy/baseline/data/lpd_building.csv +21 -0
  11. honeybee_energy/baseline/data/pci_2016.csv +22 -0
  12. honeybee_energy/baseline/data/pci_2019.csv +22 -0
  13. honeybee_energy/baseline/data/pci_2022.csv +22 -0
  14. honeybee_energy/baseline/data/shw.csv +21 -0
  15. honeybee_energy/baseline/pci.py +512 -0
  16. honeybee_energy/baseline/result.py +371 -0
  17. honeybee_energy/boundarycondition.py +128 -0
  18. honeybee_energy/cli/__init__.py +69 -0
  19. honeybee_energy/cli/baseline.py +475 -0
  20. honeybee_energy/cli/edit.py +327 -0
  21. honeybee_energy/cli/lib.py +1154 -0
  22. honeybee_energy/cli/result.py +810 -0
  23. honeybee_energy/cli/setconfig.py +124 -0
  24. honeybee_energy/cli/settings.py +569 -0
  25. honeybee_energy/cli/simulate.py +380 -0
  26. honeybee_energy/cli/translate.py +1714 -0
  27. honeybee_energy/cli/validate.py +224 -0
  28. honeybee_energy/config.json +11 -0
  29. honeybee_energy/config.py +842 -0
  30. honeybee_energy/construction/__init__.py +1 -0
  31. honeybee_energy/construction/_base.py +374 -0
  32. honeybee_energy/construction/air.py +325 -0
  33. honeybee_energy/construction/dictutil.py +89 -0
  34. honeybee_energy/construction/dynamic.py +607 -0
  35. honeybee_energy/construction/opaque.py +460 -0
  36. honeybee_energy/construction/shade.py +319 -0
  37. honeybee_energy/construction/window.py +1096 -0
  38. honeybee_energy/construction/windowshade.py +847 -0
  39. honeybee_energy/constructionset.py +1655 -0
  40. honeybee_energy/dictutil.py +56 -0
  41. honeybee_energy/generator/__init__.py +5 -0
  42. honeybee_energy/generator/loadcenter.py +204 -0
  43. honeybee_energy/generator/pv.py +535 -0
  44. honeybee_energy/hvac/__init__.py +21 -0
  45. honeybee_energy/hvac/_base.py +124 -0
  46. honeybee_energy/hvac/_template.py +270 -0
  47. honeybee_energy/hvac/allair/__init__.py +22 -0
  48. honeybee_energy/hvac/allair/_base.py +349 -0
  49. honeybee_energy/hvac/allair/furnace.py +168 -0
  50. honeybee_energy/hvac/allair/psz.py +131 -0
  51. honeybee_energy/hvac/allair/ptac.py +163 -0
  52. honeybee_energy/hvac/allair/pvav.py +109 -0
  53. honeybee_energy/hvac/allair/vav.py +128 -0
  54. honeybee_energy/hvac/detailed.py +337 -0
  55. honeybee_energy/hvac/doas/__init__.py +28 -0
  56. honeybee_energy/hvac/doas/_base.py +345 -0
  57. honeybee_energy/hvac/doas/fcu.py +127 -0
  58. honeybee_energy/hvac/doas/radiant.py +329 -0
  59. honeybee_energy/hvac/doas/vrf.py +81 -0
  60. honeybee_energy/hvac/doas/wshp.py +91 -0
  61. honeybee_energy/hvac/heatcool/__init__.py +23 -0
  62. honeybee_energy/hvac/heatcool/_base.py +177 -0
  63. honeybee_energy/hvac/heatcool/baseboard.py +61 -0
  64. honeybee_energy/hvac/heatcool/evapcool.py +72 -0
  65. honeybee_energy/hvac/heatcool/fcu.py +92 -0
  66. honeybee_energy/hvac/heatcool/gasunit.py +53 -0
  67. honeybee_energy/hvac/heatcool/radiant.py +269 -0
  68. honeybee_energy/hvac/heatcool/residential.py +77 -0
  69. honeybee_energy/hvac/heatcool/vrf.py +54 -0
  70. honeybee_energy/hvac/heatcool/windowac.py +70 -0
  71. honeybee_energy/hvac/heatcool/wshp.py +62 -0
  72. honeybee_energy/hvac/idealair.py +699 -0
  73. honeybee_energy/internalmass.py +310 -0
  74. honeybee_energy/lib/__init__.py +1 -0
  75. honeybee_energy/lib/_loadconstructions.py +194 -0
  76. honeybee_energy/lib/_loadconstructionsets.py +117 -0
  77. honeybee_energy/lib/_loadmaterials.py +83 -0
  78. honeybee_energy/lib/_loadprogramtypes.py +125 -0
  79. honeybee_energy/lib/_loadschedules.py +87 -0
  80. honeybee_energy/lib/_loadtypelimits.py +64 -0
  81. honeybee_energy/lib/constructions.py +207 -0
  82. honeybee_energy/lib/constructionsets.py +95 -0
  83. honeybee_energy/lib/materials.py +67 -0
  84. honeybee_energy/lib/programtypes.py +125 -0
  85. honeybee_energy/lib/schedules.py +61 -0
  86. honeybee_energy/lib/scheduletypelimits.py +31 -0
  87. honeybee_energy/load/__init__.py +1 -0
  88. honeybee_energy/load/_base.py +190 -0
  89. honeybee_energy/load/daylight.py +397 -0
  90. honeybee_energy/load/dictutil.py +47 -0
  91. honeybee_energy/load/equipment.py +771 -0
  92. honeybee_energy/load/hotwater.py +543 -0
  93. honeybee_energy/load/infiltration.py +460 -0
  94. honeybee_energy/load/lighting.py +480 -0
  95. honeybee_energy/load/people.py +497 -0
  96. honeybee_energy/load/process.py +472 -0
  97. honeybee_energy/load/setpoint.py +816 -0
  98. honeybee_energy/load/ventilation.py +550 -0
  99. honeybee_energy/material/__init__.py +1 -0
  100. honeybee_energy/material/_base.py +166 -0
  101. honeybee_energy/material/dictutil.py +59 -0
  102. honeybee_energy/material/frame.py +367 -0
  103. honeybee_energy/material/gas.py +1087 -0
  104. honeybee_energy/material/glazing.py +854 -0
  105. honeybee_energy/material/opaque.py +1351 -0
  106. honeybee_energy/material/shade.py +1360 -0
  107. honeybee_energy/measure.py +472 -0
  108. honeybee_energy/programtype.py +723 -0
  109. honeybee_energy/properties/__init__.py +1 -0
  110. honeybee_energy/properties/aperture.py +333 -0
  111. honeybee_energy/properties/door.py +342 -0
  112. honeybee_energy/properties/extension.py +244 -0
  113. honeybee_energy/properties/face.py +274 -0
  114. honeybee_energy/properties/model.py +2640 -0
  115. honeybee_energy/properties/room.py +1747 -0
  116. honeybee_energy/properties/shade.py +314 -0
  117. honeybee_energy/properties/shademesh.py +262 -0
  118. honeybee_energy/reader.py +48 -0
  119. honeybee_energy/result/__init__.py +1 -0
  120. honeybee_energy/result/colorobj.py +648 -0
  121. honeybee_energy/result/emissions.py +290 -0
  122. honeybee_energy/result/err.py +101 -0
  123. honeybee_energy/result/eui.py +100 -0
  124. honeybee_energy/result/generation.py +160 -0
  125. honeybee_energy/result/loadbalance.py +890 -0
  126. honeybee_energy/result/match.py +202 -0
  127. honeybee_energy/result/osw.py +90 -0
  128. honeybee_energy/result/rdd.py +59 -0
  129. honeybee_energy/result/zsz.py +190 -0
  130. honeybee_energy/run.py +1577 -0
  131. honeybee_energy/schedule/__init__.py +1 -0
  132. honeybee_energy/schedule/day.py +626 -0
  133. honeybee_energy/schedule/dictutil.py +59 -0
  134. honeybee_energy/schedule/fixedinterval.py +1012 -0
  135. honeybee_energy/schedule/rule.py +619 -0
  136. honeybee_energy/schedule/ruleset.py +1867 -0
  137. honeybee_energy/schedule/typelimit.py +310 -0
  138. honeybee_energy/shw.py +315 -0
  139. honeybee_energy/simulation/__init__.py +1 -0
  140. honeybee_energy/simulation/control.py +214 -0
  141. honeybee_energy/simulation/daylightsaving.py +185 -0
  142. honeybee_energy/simulation/dictutil.py +51 -0
  143. honeybee_energy/simulation/output.py +646 -0
  144. honeybee_energy/simulation/parameter.py +606 -0
  145. honeybee_energy/simulation/runperiod.py +443 -0
  146. honeybee_energy/simulation/shadowcalculation.py +295 -0
  147. honeybee_energy/simulation/sizing.py +546 -0
  148. honeybee_energy/ventcool/__init__.py +5 -0
  149. honeybee_energy/ventcool/_crack_data.py +91 -0
  150. honeybee_energy/ventcool/afn.py +289 -0
  151. honeybee_energy/ventcool/control.py +269 -0
  152. honeybee_energy/ventcool/crack.py +126 -0
  153. honeybee_energy/ventcool/fan.py +493 -0
  154. honeybee_energy/ventcool/opening.py +365 -0
  155. honeybee_energy/ventcool/simulation.py +314 -0
  156. honeybee_energy/writer.py +1078 -0
  157. honeybee_energy-1.116.106.dist-info/METADATA +113 -0
  158. honeybee_energy-1.116.106.dist-info/RECORD +162 -0
  159. honeybee_energy-1.116.106.dist-info/WHEEL +5 -0
  160. honeybee_energy-1.116.106.dist-info/entry_points.txt +2 -0
  161. honeybee_energy-1.116.106.dist-info/licenses/LICENSE +661 -0
  162. honeybee_energy-1.116.106.dist-info/top_level.txt +1 -0
@@ -0,0 +1,327 @@
1
+ """honeybee energy commands for editing model energy properties."""
2
+ import click
3
+ import sys
4
+ import logging
5
+ import os
6
+ import json
7
+
8
+ from honeybee.model import Model
9
+ from honeybee.typing import clean_rad_string
10
+
11
+ from honeybee_energy.schedule.fixedinterval import ScheduleFixedInterval
12
+ from honeybee_energy.lib.scheduletypelimits import fractional
13
+ from honeybee_energy.properties.model import ModelEnergyProperties
14
+
15
+ _logger = logging.getLogger(__name__)
16
+
17
+
18
+ @click.group(help='Commands for editing model energy properties.')
19
+ def edit():
20
+ pass
21
+
22
+
23
+ @edit.command('reset-resource-ids')
24
+ @click.argument('model-file', type=click.Path(
25
+ exists=True, file_okay=True, dir_okay=False, resolve_path=True))
26
+ @click.option(
27
+ '--by-name/--by-name-and-uuid', ' /-uuid', help='Flag to note whether '
28
+ 'newly-generated resource object IDs should be derived only from a '
29
+ 'cleaned display_name or whether this new ID should also have a unique '
30
+ 'set of 8 characters appended to it to guarantee uniqueness.', default=True
31
+ )
32
+ @click.option(
33
+ '--reset-materials/--keep-materials', ' /-m', help='Flag to note whether '
34
+ 'the IDs of all materials in the model should be reset.',
35
+ default=True, show_default=True
36
+ )
37
+ @click.option(
38
+ '--reset-constructions/--keep-constructions', ' /-c', help='Flag to note whether '
39
+ 'the IDs of all constructions in the model should be reset.',
40
+ default=True, show_default=True
41
+ )
42
+ @click.option(
43
+ '--reset-construction-sets/--keep-construction-sets', ' /-cs', help='Flag to '
44
+ 'note whether the IDs of all construction sets in the model should be reset.',
45
+ default=True, show_default=True
46
+ )
47
+ @click.option(
48
+ '--reset-schedules/--keep-schedules', ' /-s', help='Flag to note whether '
49
+ 'the IDs of all schedules in the model should be reset.',
50
+ default=True, show_default=True
51
+ )
52
+ @click.option(
53
+ '--reset-programs/--keep-programs', ' /-p', help='Flag to note whether '
54
+ 'the IDs of all programs in the model should be reset. This will also include '
55
+ 'resetting the IDs of all load objects in the program.',
56
+ default=True, show_default=True
57
+ )
58
+ @click.option(
59
+ '--output-file', '-f', help='Optional hbjson file to output the JSON '
60
+ 'string of the converted model. By default this will be printed out to '
61
+ 'stdout', type=click.File('w'), default='-', show_default=True
62
+ )
63
+ def reset_resource_ids(
64
+ model_file, by_name,
65
+ reset_materials, reset_constructions, reset_construction_sets,
66
+ reset_schedules, reset_programs, output_file
67
+ ):
68
+ """Reset the identifiers of resource objects in a Model file.
69
+
70
+ This is useful when human-readable names are needed when the model is
71
+ exported to other formats like IDF and OSM and the uniqueness of the
72
+ identifiers is less of a concern.
73
+
74
+ \b
75
+ Args:
76
+ model_file: Full path to a Honeybee Model (HBJSON) file.
77
+ """
78
+ try:
79
+ # load the model file and separately load up the resource objects
80
+ if sys.version_info < (3, 0):
81
+ with open(model_file) as inf:
82
+ data = json.load(inf)
83
+ else:
84
+ with open(model_file, encoding='utf-8') as inf:
85
+ data = json.load(inf)
86
+ # reset the identifiers of resources in the dictionary
87
+ add_uuid = not by_name
88
+ model_dict = ModelEnergyProperties.reset_resource_ids_in_dict(
89
+ data, add_uuid, reset_materials, reset_constructions,
90
+ reset_construction_sets, reset_schedules, reset_programs)
91
+ # write the dictionary into a JSON
92
+ output_file.write(json.dumps(model_dict))
93
+ except Exception as e:
94
+ _logger.exception('Resetting resource identifiers failed.\n{}'.format(e))
95
+ sys.exit(1)
96
+ else:
97
+ sys.exit(0)
98
+
99
+
100
+ @edit.command('modifiers-from-constructions')
101
+ @click.argument('model-file', type=click.Path(
102
+ exists=True, file_okay=True, dir_okay=False, resolve_path=True))
103
+ @click.option('--solar/--visible', ' /-v', help='Flag to note whether the assigned '
104
+ 'radiance modifiers should follow the solar properties of the '
105
+ 'constructions or the visible properties.', default=True)
106
+ @click.option('--dynamic-groups/--static-groups', ' /-sg', help='Flag to note whether '
107
+ 'dynamic window constructions and shaded window constructions should '
108
+ 'be translated to dynamic aperture groups or just the static (bare) '
109
+ 'construction should be used.', default=True)
110
+ @click.option('--dynamic-shade/--static-shade', ' /-ss', help='Flag to note whether '
111
+ 'dynamic shade transmittance schedules should be translated to dynamic '
112
+ 'shade groups or just a static, fully-opaque construction should '
113
+ 'be used.', default=True)
114
+ @click.option('--exterior-offset', '-o', help='A number for the distance at which the '
115
+ 'exterior Room faces should be offset in meters. This is used to account '
116
+ 'for the fact that the exterior material layer of the construction '
117
+ 'usually needs a different modifier from the interior. If set to 0, '
118
+ 'no offset will occur and all assigned modifiers will be interior.',
119
+ type=float, default=0, show_default=True)
120
+ @click.option('--output-file', '-f', help='Optional hbjson file to output the JSON '
121
+ 'string of the converted model. By default this will be printed out to '
122
+ 'stdout', type=click.File('w'), default='-', show_default=True)
123
+ def modifiers_from_constructions(
124
+ model_file, solar, dynamic_groups, dynamic_shade, exterior_offset, output_file
125
+ ):
126
+ """Assign honeybee Radiance modifiers based on energy construction properties.
127
+
128
+ Note that the honeybee-radiance extension must be installed in order for this
129
+ command to be run successfully.
130
+
131
+ Also note that setting the --exterior-offset to a non-zero value will add the
132
+ offset faces as orphaned faces, which changes how the model simulates in EnergyPlus.
133
+
134
+ \b
135
+ Args:
136
+ model_file: Full path to a Honeybee Model (HBJSON or HBpkl) file.
137
+ """
138
+ try:
139
+ # import dependencies and set up reused variables
140
+ try:
141
+ from honeybee_radiance.lib.modifiers import air_boundary
142
+ from honeybee_radiance.dynamic.state import RadianceShadeState
143
+ except ImportError as e:
144
+ raise ImportError('honeybee_radiance library must be installed to use '
145
+ 'modifiers-from-constructions method. {}'.format(e))
146
+ # re-serialize the Model to Python
147
+ model = Model.from_file(model_file)
148
+ # assign the radiance properties based on the interior energy constructions
149
+ if solar:
150
+ model.properties.energy.assign_radiance_solar_interior()
151
+ else:
152
+ model.properties.energy.assign_radiance_visible_interior()
153
+ # offset the exterior faces and give them modifiers for the exterior
154
+ if exterior_offset is not None and exterior_offset > 0:
155
+ exterior_offset = exterior_offset if model.units == 'Meters' else \
156
+ exterior_offset / model.conversion_factor_to_meters(model.units)
157
+ ref_type = 'Solar' if solar else 'Visible'
158
+ model.properties.energy.offset_and_assign_exterior_face_modifiers(
159
+ reflectance_type=ref_type, offset=exterior_offset
160
+ )
161
+ # assign trans modifiers for any shades with constant transmittance schedules
162
+ tr_sch_dict = {}
163
+ for shade in model.shades:
164
+ t_sch = shade.properties.energy.transmittance_schedule
165
+ if t_sch is not None:
166
+ if t_sch.is_constant: # just use a trans modifier
167
+ if solar:
168
+ shade.properties.radiance.modifier = \
169
+ shade.properties.energy.radiance_modifier_solar()
170
+ else:
171
+ shade.properties.radiance.modifier = \
172
+ shade.properties.energy.radiance_modifier_visible()
173
+ else: # represent the shade as a dynamic group
174
+ try:
175
+ tr_sch_dict[t_sch.identifier].append(shade)
176
+ except KeyError:
177
+ tr_sch_dict[t_sch.identifier] = [shade]
178
+ # assign dynamic shade groups if requested
179
+ if dynamic_shade:
180
+ for grp_name, group in tr_sch_dict.items():
181
+ grp_name = clean_rad_string(grp_name)
182
+ for shd in group:
183
+ shd.properties.radiance.dynamic_group_identifier = grp_name
184
+ on_state = RadianceShadeState(shd.properties.radiance.modifier)
185
+ off_state = RadianceShadeState(air_boundary)
186
+ shd.properties.radiance.states = [on_state, off_state]
187
+ # assign dynamic aperture groups if requested
188
+ if dynamic_groups:
189
+ model.properties.energy.assign_dynamic_aperture_groups()
190
+ # write the Model JSON string
191
+ output_file.write(json.dumps(model.to_dict()))
192
+ except Exception as e:
193
+ _logger.exception(
194
+ 'Assignment of model radiance modifiers from energy construction '
195
+ 'failed.\n{}'.format(e)
196
+ )
197
+ sys.exit(1)
198
+ else:
199
+ sys.exit(0)
200
+
201
+
202
+ @edit.command('lighting-from-daylight')
203
+ @click.argument('model-file', type=click.Path(
204
+ exists=True, file_okay=True, dir_okay=False, resolve_path=True))
205
+ @click.argument(
206
+ 'daylight-folder',
207
+ type=click.Path(exists=True, file_okay=False, dir_okay=True, resolve_path=True)
208
+ )
209
+ @click.option(
210
+ '--ill-setpoint', '-i', help='A number for the illuminance setpoint in lux beyond '
211
+ 'which electric lights are dimmed if there is sufficient daylight.',
212
+ default=300, type=int, show_default=True
213
+ )
214
+ @click.option(
215
+ '--min-power-in', '-p',
216
+ help='A number between 0 and 1 for the the lowest power the lighting system can '
217
+ 'dim down to, expressed as a fraction of maximum input power.', default=0.3,
218
+ type=float, show_default=True
219
+ )
220
+ @click.option(
221
+ '--min-light-out', '-l',
222
+ help='A number between 0 and 1 the lowest lighting output the lighting system can '
223
+ 'dim down to, expressed as a fraction of maximum light output. Note that setting '
224
+ 'this to 1 means lights are not dimmed at all until the illuminance setpoint is '
225
+ 'reached. This can be used to approximate manual light-switching behavior when '
226
+ 'used in conjunction with the --off_at_min output below.', default=0.2,
227
+ type=float, show_default=True
228
+ )
229
+ @click.option(
230
+ '--on-at-min/--off-at-min', ' /-oam', help='Flag to note whether lights should '
231
+ 'switch off completely when they get to the minimum power input.',
232
+ default=True, show_default=True
233
+ )
234
+ @click.option(
235
+ '--output-file', '-f', help='Optional hbjson file to output the JSON '
236
+ 'string of the converted model. By default this will be printed out to '
237
+ 'stdout', type=click.File('w'), default='-', show_default=True
238
+ )
239
+ def lighting_from_daylight(
240
+ model_file, daylight_folder, ill_setpoint, min_power_in, min_light_out,
241
+ on_at_min, output_file
242
+ ):
243
+ """Assign HB-energy lighting schedules using Radiance annual-daylight results.
244
+
245
+ Note that the honeybee-radiance extension must be installed in order for this
246
+ command to be run successfully.
247
+
248
+ Also note that the Honeybee model must have sensor grids with room_identifiers
249
+ assigned to them for them to affect the HB-Energy lighting schedules. If such
250
+ grids are found, the lighting schedules of the Rooms will be adjusted according
251
+ to whether the illuminance values at the sensor locations are at a target
252
+ illuminance setpoint.
253
+
254
+ Each grid should have sensors at the locations in space where daylight dimming
255
+ sensors are located. Grids with two or more sensors can be used to model setups
256
+ where fractions of each room are controlled by different sensors. If the sensor
257
+ grids are distributed over the entire floor of the rooms, the resulting schedules
258
+ will be idealized, where light dimming has been optimized to supply the minimum
259
+ illuminance setpoint everywhere in the room.
260
+
261
+ \b
262
+ Args:
263
+ model_file: Full path to a Honeybee Model (HBJSON or HBpkl) file.
264
+ daylight_folder: Path to an annual-daylight results folder. This folder is
265
+ an output folder of the annual daylight recipe. The folder should
266
+ include grids_info.json and sun-up-hours.txt. The command uses the
267
+ list in grids_info.json to find the result files for each sensor grid.
268
+ """
269
+ try:
270
+ # load up relevant honeybee-radiance dependencies
271
+ try:
272
+ from honeybee_radiance.postprocess.annualdaylight import \
273
+ _process_input_folder
274
+ from honeybee_radiance.postprocess.electriclight import \
275
+ _file_to_dimming_fraction
276
+ except ImportError as e:
277
+ raise ImportError('honeybee_radiance library must be installed to use '
278
+ 'lighting-from-daylight. {}'.format(e))
279
+
280
+ # re-serialize the Model to Python and get a map from grids to room IDs
281
+ model = Model.from_file(model_file)
282
+ room_map = {}
283
+ for grid in model.properties.radiance.sensor_grids:
284
+ room_map[grid.room_identifier] = grid.full_identifier
285
+
286
+ # get the dimming fractions for each sensor grid from the .ill files
287
+ grids, sun_up_hours = _process_input_folder(daylight_folder, '*')
288
+ sun_up_hours = [int(h) for h in sun_up_hours]
289
+ off_at_min = not on_at_min
290
+ dim_fracts = {}
291
+ for grid_info in grids:
292
+ ill_file = os.path.join(daylight_folder, '%s.ill' % grid_info['full_id'])
293
+ fract_list = _file_to_dimming_fraction(
294
+ ill_file, sun_up_hours, ill_setpoint, min_power_in,
295
+ min_light_out, off_at_min
296
+ )
297
+ dim_fracts[grid_info['full_id']] = fract_list
298
+
299
+ # loop through the rooms of the model and assign the lighting dimming
300
+ for room in model.rooms:
301
+ light = room.properties.energy.lighting
302
+ if light is not None:
303
+ base_schedule = light.schedule.values_at_timestep(1) \
304
+ if isinstance(light.schedule, ScheduleFixedInterval) \
305
+ else light.schedule.values(1)
306
+ try:
307
+ dim_fract = dim_fracts[room_map[room.identifier]]
308
+ sch_vals = [b_val * d_val for b_val, d_val in
309
+ zip(base_schedule, dim_fract)]
310
+ sch_id = '{} Daylight Control'.format(room.identifier)
311
+ new_sch = ScheduleFixedInterval(sch_id, sch_vals, fractional)
312
+ new_light = light.duplicate()
313
+ new_light.schedule = new_sch
314
+ room.properties.energy.lighting = new_light
315
+ except KeyError:
316
+ pass # no grid is associated with the room
317
+
318
+ # write the Model JSON string
319
+ output_file.write(json.dumps(model.to_dict()))
320
+ except Exception as e:
321
+ _logger.exception(
322
+ 'Assignment of model lighting schedules from annual-daylight results '
323
+ 'failed.\n{}'.format(e)
324
+ )
325
+ sys.exit(1)
326
+ else:
327
+ sys.exit(0)