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,619 @@
|
|
|
1
|
+
# coding=utf-8
|
|
2
|
+
"""Object storing rules for how a given ScheduleDay gets applied over a year."""
|
|
3
|
+
from __future__ import division
|
|
4
|
+
|
|
5
|
+
from .day import ScheduleDay
|
|
6
|
+
from ..reader import parse_idf_string
|
|
7
|
+
|
|
8
|
+
from honeybee._lockable import lockable
|
|
9
|
+
|
|
10
|
+
from ladybug.dt import Date
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@lockable
|
|
14
|
+
class ScheduleRule(object):
|
|
15
|
+
"""Schedule rule including a ScheduleDay and when it should be applied.
|
|
16
|
+
|
|
17
|
+
Note that a ScheduleRule cannot be assigned to Rooms, Shades, etc. The
|
|
18
|
+
ScheduleRule must be added to a ScheduleRuleset and then the ScheduleRuleset
|
|
19
|
+
can be applied to such objects.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
schedule_day: A ScheduleDay object associated with this rule.
|
|
23
|
+
apply_sunday: Boolean noting whether to apply schedule_day on Sundays.
|
|
24
|
+
apply_monday: Boolean noting whether to apply schedule_day on Mondays.
|
|
25
|
+
apply_tuesday: Boolean noting whether to apply schedule_day on Tuesdays.
|
|
26
|
+
apply_wednesday: Boolean noting whether to apply schedule_day on Wednesdays.
|
|
27
|
+
apply_thursday: Boolean noting whether to apply schedule_day on Thursdays.
|
|
28
|
+
apply_friday: Boolean noting whether to apply schedule_day on Fridays.
|
|
29
|
+
apply_saturday: Boolean noting whether to apply schedule_day on Saturdays.
|
|
30
|
+
start_date: A ladybug Date object for the start of the period over which
|
|
31
|
+
the schedule_day will be applied. If None, Jan 1 will be used.
|
|
32
|
+
end_date: A ladybug Date object for the end of the period over which
|
|
33
|
+
the schedule_day will be applied. If None, Dec 31 will be used.
|
|
34
|
+
|
|
35
|
+
Properties:
|
|
36
|
+
* schedule_day
|
|
37
|
+
* apply_sunday
|
|
38
|
+
* apply_monday
|
|
39
|
+
* apply_tuesday
|
|
40
|
+
* apply_wednesday
|
|
41
|
+
* apply_thursday
|
|
42
|
+
* apply_friday
|
|
43
|
+
* apply_saturday
|
|
44
|
+
* start_date
|
|
45
|
+
* end_date
|
|
46
|
+
* apply_weekday
|
|
47
|
+
* apply_weekend
|
|
48
|
+
* apply_all
|
|
49
|
+
* days_applied
|
|
50
|
+
* week_apply_tuple
|
|
51
|
+
* is_reversed
|
|
52
|
+
"""
|
|
53
|
+
__slots__ = ('_schedule_day', '_apply_sunday', '_apply_monday', '_apply_tuesday',
|
|
54
|
+
'_apply_wednesday', '_apply_thursday', '_apply_friday',
|
|
55
|
+
'_apply_saturday', '_start_date', '_end_date', '_start_doy',
|
|
56
|
+
'_end_doy', '_locked')
|
|
57
|
+
|
|
58
|
+
_year_start = Date(1, 1)
|
|
59
|
+
_year_end = Date(12, 31)
|
|
60
|
+
|
|
61
|
+
def __init__(self, schedule_day, apply_sunday=False, apply_monday=False,
|
|
62
|
+
apply_tuesday=False, apply_wednesday=False, apply_thursday=False,
|
|
63
|
+
apply_friday=False, apply_saturday=False, start_date=None, end_date=None):
|
|
64
|
+
"""Initialize Schedule Rule."""
|
|
65
|
+
self._locked = False # unlocked by default
|
|
66
|
+
self.schedule_day = schedule_day
|
|
67
|
+
self.apply_sunday = apply_sunday
|
|
68
|
+
self.apply_monday = apply_monday
|
|
69
|
+
self.apply_tuesday = apply_tuesday
|
|
70
|
+
self.apply_wednesday = apply_wednesday
|
|
71
|
+
self.apply_thursday = apply_thursday
|
|
72
|
+
self.apply_friday = apply_friday
|
|
73
|
+
self.apply_saturday = apply_saturday
|
|
74
|
+
|
|
75
|
+
# process the start date and end date
|
|
76
|
+
if start_date is not None:
|
|
77
|
+
self._check_date(start_date, 'start_date')
|
|
78
|
+
self._start_date = start_date
|
|
79
|
+
else:
|
|
80
|
+
self._start_date = self._year_start
|
|
81
|
+
self._start_doy = self._doy_non_leap_year(self._start_date)
|
|
82
|
+
self.end_date = end_date
|
|
83
|
+
|
|
84
|
+
@property
|
|
85
|
+
def schedule_day(self):
|
|
86
|
+
"""Get or set the ScheduleDay object associated with this rule.."""
|
|
87
|
+
return self._schedule_day
|
|
88
|
+
|
|
89
|
+
@schedule_day.setter
|
|
90
|
+
def schedule_day(self, value):
|
|
91
|
+
assert isinstance(value, ScheduleDay), \
|
|
92
|
+
'Expected ScheduleDay for ScheduleRule. Got {}.'.format(type(value))
|
|
93
|
+
self._schedule_day = value
|
|
94
|
+
|
|
95
|
+
@property
|
|
96
|
+
def apply_sunday(self):
|
|
97
|
+
"""Get or set a boolean noting whether to apply schedule_day on Sundays."""
|
|
98
|
+
return self._apply_sunday
|
|
99
|
+
|
|
100
|
+
@apply_sunday.setter
|
|
101
|
+
def apply_sunday(self, value):
|
|
102
|
+
self._apply_sunday = bool(value)
|
|
103
|
+
|
|
104
|
+
@property
|
|
105
|
+
def apply_monday(self):
|
|
106
|
+
"""Get or set a boolean noting whether to apply schedule_day on Mondays."""
|
|
107
|
+
return self._apply_monday
|
|
108
|
+
|
|
109
|
+
@apply_monday.setter
|
|
110
|
+
def apply_monday(self, value):
|
|
111
|
+
self._apply_monday = bool(value)
|
|
112
|
+
|
|
113
|
+
@property
|
|
114
|
+
def apply_tuesday(self):
|
|
115
|
+
"""Get or set a boolean noting whether to apply schedule_day on Tuesdays."""
|
|
116
|
+
return self._apply_tuesday
|
|
117
|
+
|
|
118
|
+
@apply_tuesday.setter
|
|
119
|
+
def apply_tuesday(self, value):
|
|
120
|
+
self._apply_tuesday = bool(value)
|
|
121
|
+
|
|
122
|
+
@property
|
|
123
|
+
def apply_wednesday(self):
|
|
124
|
+
"""Get or set a boolean noting whether to apply schedule_day on Wednesdays."""
|
|
125
|
+
return self._apply_wednesday
|
|
126
|
+
|
|
127
|
+
@apply_wednesday.setter
|
|
128
|
+
def apply_wednesday(self, value):
|
|
129
|
+
self._apply_wednesday = bool(value)
|
|
130
|
+
|
|
131
|
+
@property
|
|
132
|
+
def apply_thursday(self):
|
|
133
|
+
"""Get or set a boolean noting whether to apply schedule_day on Thursdays."""
|
|
134
|
+
return self._apply_thursday
|
|
135
|
+
|
|
136
|
+
@apply_thursday.setter
|
|
137
|
+
def apply_thursday(self, value):
|
|
138
|
+
self._apply_thursday = bool(value)
|
|
139
|
+
|
|
140
|
+
@property
|
|
141
|
+
def apply_friday(self):
|
|
142
|
+
"""Get or set a boolean noting whether to apply schedule_day on Fridays."""
|
|
143
|
+
return self._apply_friday
|
|
144
|
+
|
|
145
|
+
@apply_friday.setter
|
|
146
|
+
def apply_friday(self, value):
|
|
147
|
+
self._apply_friday = bool(value)
|
|
148
|
+
|
|
149
|
+
@property
|
|
150
|
+
def apply_saturday(self):
|
|
151
|
+
"""Get or set a boolean noting whether to apply schedule_day on Saturdays."""
|
|
152
|
+
return self._apply_saturday
|
|
153
|
+
|
|
154
|
+
@apply_saturday.setter
|
|
155
|
+
def apply_saturday(self, value):
|
|
156
|
+
self._apply_saturday = bool(value)
|
|
157
|
+
|
|
158
|
+
@property
|
|
159
|
+
def apply_weekday(self):
|
|
160
|
+
"""Get or set a boolean noting whether to apply schedule_day on week days."""
|
|
161
|
+
return self._apply_monday and self._apply_tuesday and self._apply_wednesday and \
|
|
162
|
+
self._apply_thursday and self._apply_friday
|
|
163
|
+
|
|
164
|
+
@apply_weekday.setter
|
|
165
|
+
def apply_weekday(self, value):
|
|
166
|
+
self._apply_monday = self._apply_tuesday = self._apply_wednesday = \
|
|
167
|
+
self._apply_thursday = self._apply_friday = bool(value)
|
|
168
|
+
|
|
169
|
+
@property
|
|
170
|
+
def apply_weekend(self):
|
|
171
|
+
"""Get or set a boolean noting whether to apply schedule_day on weekends."""
|
|
172
|
+
return self._apply_sunday and self._apply_saturday
|
|
173
|
+
|
|
174
|
+
@apply_weekend.setter
|
|
175
|
+
def apply_weekend(self, value):
|
|
176
|
+
self._apply_sunday = self._apply_saturday = bool(value)
|
|
177
|
+
|
|
178
|
+
@property
|
|
179
|
+
def apply_all(self):
|
|
180
|
+
"""Get or set a boolean noting whether to apply schedule_day on all days."""
|
|
181
|
+
return self._apply_sunday and self._apply_monday and self._apply_tuesday and \
|
|
182
|
+
self._apply_wednesday and self._apply_thursday and self._apply_friday and \
|
|
183
|
+
self._apply_saturday
|
|
184
|
+
|
|
185
|
+
@apply_all.setter
|
|
186
|
+
def apply_all(self, value):
|
|
187
|
+
self._apply_sunday = self._apply_monday = self._apply_tuesday = \
|
|
188
|
+
self._apply_wednesday = self._apply_thursday = self._apply_friday = \
|
|
189
|
+
self._apply_saturday = bool(value)
|
|
190
|
+
|
|
191
|
+
@property
|
|
192
|
+
def start_date(self):
|
|
193
|
+
"""Get or set a ladybug Date object for the start of the period."""
|
|
194
|
+
return self._start_date
|
|
195
|
+
|
|
196
|
+
@start_date.setter
|
|
197
|
+
def start_date(self, value):
|
|
198
|
+
if value is not None:
|
|
199
|
+
self._check_date(value, 'start_date')
|
|
200
|
+
self._start_date = value
|
|
201
|
+
else:
|
|
202
|
+
self._start_date = self._year_start
|
|
203
|
+
self._start_doy = self._doy_non_leap_year(self._start_date)
|
|
204
|
+
|
|
205
|
+
@property
|
|
206
|
+
def end_date(self):
|
|
207
|
+
"""Get or set a ladybug Date object for the end of the period."""
|
|
208
|
+
return self._end_date
|
|
209
|
+
|
|
210
|
+
@end_date.setter
|
|
211
|
+
def end_date(self, value):
|
|
212
|
+
if value is not None:
|
|
213
|
+
self._check_date(value, 'end_date')
|
|
214
|
+
self._end_date = value
|
|
215
|
+
else:
|
|
216
|
+
self._end_date = self._year_end
|
|
217
|
+
self._end_doy = self._doy_non_leap_year(self._end_date)
|
|
218
|
+
|
|
219
|
+
@property
|
|
220
|
+
def days_applied(self):
|
|
221
|
+
"""Get a list of text values for the days applied."""
|
|
222
|
+
day_names = ('sunday', 'monday', 'tuesday', 'wednesday', 'thursday',
|
|
223
|
+
'friday', 'saturday')
|
|
224
|
+
days = [name for name, apply in zip(day_names, self.week_apply_tuple) if apply]
|
|
225
|
+
return days
|
|
226
|
+
|
|
227
|
+
@property
|
|
228
|
+
def week_apply_tuple(self):
|
|
229
|
+
"""Get a tuple of 7 booleans for each of the days of the week."""
|
|
230
|
+
return (self._apply_sunday, self._apply_monday, self._apply_tuesday,
|
|
231
|
+
self._apply_wednesday, self._apply_thursday, self._apply_friday,
|
|
232
|
+
self._apply_saturday)
|
|
233
|
+
|
|
234
|
+
@property
|
|
235
|
+
def is_reversed(self):
|
|
236
|
+
"""A property to note whether the start date is after the end date.
|
|
237
|
+
|
|
238
|
+
This indicates that the rule applies through the end of the year into
|
|
239
|
+
the start of the year.
|
|
240
|
+
"""
|
|
241
|
+
return self._start_date > self._end_date
|
|
242
|
+
|
|
243
|
+
def apply_day_by_name(self, day_name):
|
|
244
|
+
"""Set the rule to apply to the day of the week by its name.
|
|
245
|
+
|
|
246
|
+
Args:
|
|
247
|
+
day_name: A text string for the day on which this rule should be applied.
|
|
248
|
+
The following options are acceptable:
|
|
249
|
+
'sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday',
|
|
250
|
+
'saturday', 'weekday', 'weekend', 'all'
|
|
251
|
+
"""
|
|
252
|
+
day_name = day_name.lower()
|
|
253
|
+
if day_name == 'sunday':
|
|
254
|
+
self.apply_sunday = True
|
|
255
|
+
elif day_name == 'monday':
|
|
256
|
+
self.apply_monday = True
|
|
257
|
+
elif day_name == 'tuesday':
|
|
258
|
+
self.apply_tuesday = True
|
|
259
|
+
elif day_name == 'wednesday':
|
|
260
|
+
self.apply_wednesday = True
|
|
261
|
+
elif day_name == 'thursday':
|
|
262
|
+
self.apply_thursday = True
|
|
263
|
+
elif day_name == 'friday':
|
|
264
|
+
self.apply_friday = True
|
|
265
|
+
elif day_name == 'saturday':
|
|
266
|
+
self.apply_saturday = True
|
|
267
|
+
elif day_name == 'weekday':
|
|
268
|
+
self.apply_weekday = True
|
|
269
|
+
elif day_name == 'weekend':
|
|
270
|
+
self.apply_weekend = True
|
|
271
|
+
elif day_name == 'all':
|
|
272
|
+
self.apply_all = True
|
|
273
|
+
else:
|
|
274
|
+
raise ValueError('ScheduleRule input "{}" is not an acceptable '
|
|
275
|
+
'day name.'.format(day_name))
|
|
276
|
+
|
|
277
|
+
def apply_day_by_dow(self, dow):
|
|
278
|
+
"""Set the rule to apply to the day of the week by its dow integer.
|
|
279
|
+
|
|
280
|
+
Args:
|
|
281
|
+
week_day_index: An integer from 1-8 for the day of the week. Values
|
|
282
|
+
correspond to the following:
|
|
283
|
+
|
|
284
|
+
1 - Sunday
|
|
285
|
+
2 - Monday
|
|
286
|
+
3 - Tuesday
|
|
287
|
+
4 - Wednesday
|
|
288
|
+
5 - Thursday
|
|
289
|
+
6 - Friday
|
|
290
|
+
7 - Saturday
|
|
291
|
+
"""
|
|
292
|
+
if dow == 1:
|
|
293
|
+
self.apply_sunday = True
|
|
294
|
+
elif dow == 2:
|
|
295
|
+
self.apply_monday = True
|
|
296
|
+
elif dow == 3:
|
|
297
|
+
self.apply_tuesday = True
|
|
298
|
+
elif dow == 4:
|
|
299
|
+
self.apply_wednesday = True
|
|
300
|
+
elif dow == 5:
|
|
301
|
+
self.apply_thursday = True
|
|
302
|
+
elif dow == 6:
|
|
303
|
+
self.apply_friday = True
|
|
304
|
+
elif dow == 7:
|
|
305
|
+
self.apply_saturday = True
|
|
306
|
+
else:
|
|
307
|
+
raise ValueError('ScheduleRule input "{}" is not an acceptable '
|
|
308
|
+
'dow integer.'.format(dow))
|
|
309
|
+
|
|
310
|
+
def does_rule_apply(self, doy, dow=None):
|
|
311
|
+
"""Check if this rule applies to a given day of the year and day of the week.
|
|
312
|
+
|
|
313
|
+
Args:
|
|
314
|
+
doy: An integer between 1 anf 365 for the day of the year to test.
|
|
315
|
+
dow: An integer between 1 anf 7 for the day of the week to test. If None,
|
|
316
|
+
this value will be derived from the doy, assuming the first day of
|
|
317
|
+
the year is a Sunday.
|
|
318
|
+
"""
|
|
319
|
+
dow = dow if dow is not None else doy % 7
|
|
320
|
+
return self.does_rule_apply_doy(doy) and self.week_apply_tuple[dow - 1]
|
|
321
|
+
|
|
322
|
+
def does_rule_apply_leap_year(self, doy, dow=None):
|
|
323
|
+
"""Check if this rule applies to a given day of a leap year and day of the week.
|
|
324
|
+
|
|
325
|
+
Args:
|
|
326
|
+
doy: An integer between 1 anf 366 for the day of the leap year to test.
|
|
327
|
+
dow: An integer between 1 anf 7 for the day of the week to test. If None,
|
|
328
|
+
this value will be derived from the doy, assuming the first day of
|
|
329
|
+
the year is a Sunday.
|
|
330
|
+
"""
|
|
331
|
+
dow = dow if dow is not None else doy % 7
|
|
332
|
+
return self.does_rule_apply_doy_leap_year(doy) and self.week_apply_tuple[dow - 1]
|
|
333
|
+
|
|
334
|
+
def does_rule_apply_doy(self, doy):
|
|
335
|
+
"""Check if this rule applies to a given day of the year.
|
|
336
|
+
|
|
337
|
+
Args:
|
|
338
|
+
doy: An integer between 1 anf 365 for the day of the year to test.
|
|
339
|
+
"""
|
|
340
|
+
if self.is_reversed:
|
|
341
|
+
return doy <= self._end_doy or self._start_doy <= doy
|
|
342
|
+
else:
|
|
343
|
+
return self._start_doy <= doy <= self._end_doy
|
|
344
|
+
|
|
345
|
+
def does_rule_apply_doy_leap_year(self, doy):
|
|
346
|
+
"""Check if this rule applies to a given day of a leap year.
|
|
347
|
+
|
|
348
|
+
Args:
|
|
349
|
+
doy: An integer between 1 anf 366 for the day of the leap year to test.
|
|
350
|
+
"""
|
|
351
|
+
st_doy = self._start_doy if self._start_date.month <= 2 else self._start_doy + 1
|
|
352
|
+
end_doy = self._end_doy if self._end_date.month <= 2 else self._end_doy + 1
|
|
353
|
+
if self.is_reversed:
|
|
354
|
+
return doy <= end_doy or st_doy <= doy
|
|
355
|
+
else:
|
|
356
|
+
return st_doy <= doy <= end_doy
|
|
357
|
+
|
|
358
|
+
@classmethod
|
|
359
|
+
def from_days_applied(cls, schedule_day, applicable_days=None,
|
|
360
|
+
start_date=None, end_date=None):
|
|
361
|
+
"""Initialize a ScheduleRule using a list of days when the rule is applied.
|
|
362
|
+
|
|
363
|
+
Args:
|
|
364
|
+
schedule_day: A ScheduleDay object associated with this rule.
|
|
365
|
+
applicable_days: A list of text strings for the days when theScheduleRule
|
|
366
|
+
will be applied. For example ['monday', 'weekend'].
|
|
367
|
+
The following options are acceptable:
|
|
368
|
+
'sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday',
|
|
369
|
+
'saturday', 'weekday', 'weekend', 'all'
|
|
370
|
+
start_date: A ladybug Date object for the start of the period over which
|
|
371
|
+
the schedule_day will be applied. If None, Jan 1 will be used.
|
|
372
|
+
end_date: A ladybug Date object for the end of the period over which
|
|
373
|
+
the schedule_day will be applied. If None, Dec 31 will be used.
|
|
374
|
+
"""
|
|
375
|
+
rule = cls(schedule_day, start_date=start_date, end_date=end_date)
|
|
376
|
+
if applicable_days is not None:
|
|
377
|
+
for day in applicable_days:
|
|
378
|
+
rule.apply_day_by_name(day)
|
|
379
|
+
return rule
|
|
380
|
+
|
|
381
|
+
@classmethod
|
|
382
|
+
def from_dict(cls, data):
|
|
383
|
+
"""Create a ScheduleRule from a dictionary.
|
|
384
|
+
|
|
385
|
+
Args:
|
|
386
|
+
data: ScheduleRule dictionary following the format below.
|
|
387
|
+
|
|
388
|
+
.. code-block:: python
|
|
389
|
+
|
|
390
|
+
{
|
|
391
|
+
"type": 'ScheduleRule'
|
|
392
|
+
"schedule_day": {
|
|
393
|
+
"type": 'ScheduleDay',
|
|
394
|
+
"identifier": 'Office Occupancy',
|
|
395
|
+
"values": [0, 1, 0],
|
|
396
|
+
"times": [(0, 0), (9, 0), (17, 0)],
|
|
397
|
+
"interpolate": False
|
|
398
|
+
},
|
|
399
|
+
"apply_sunday": False,
|
|
400
|
+
"apply_monday": True,
|
|
401
|
+
"apply_tuesday": True,
|
|
402
|
+
"apply_wednesday": True,
|
|
403
|
+
"apply_thursday": True,
|
|
404
|
+
"apply_friday": True,
|
|
405
|
+
"apply_saturday": False,
|
|
406
|
+
"start_date": (1, 1),
|
|
407
|
+
"end_date": (12, 31)
|
|
408
|
+
}
|
|
409
|
+
"""
|
|
410
|
+
assert data['type'] == 'ScheduleRule', \
|
|
411
|
+
'Expected ScheduleRule. Got {}.'.format(data['type'])
|
|
412
|
+
|
|
413
|
+
schedule_day = ScheduleDay.from_dict(data['schedule_day'])
|
|
414
|
+
sun, mon, tues, wed, thurs, fri, sat, start, end = \
|
|
415
|
+
cls._extract_apply_from_dict(data)
|
|
416
|
+
|
|
417
|
+
return cls(schedule_day, sun, mon, tues, wed, thurs, fri, sat, start, end)
|
|
418
|
+
|
|
419
|
+
@classmethod
|
|
420
|
+
def from_dict_abridged(cls, data, schedule_day):
|
|
421
|
+
"""Create a ScheduleRule object from an abridged dictionary.
|
|
422
|
+
|
|
423
|
+
Args:
|
|
424
|
+
data: A ScheduleRuleAbridged dictionary in following the format below.
|
|
425
|
+
schedule_day: A honeybee ScheduleDay object that will be assigned to
|
|
426
|
+
this ScheduleRule.
|
|
427
|
+
|
|
428
|
+
.. code-block:: python
|
|
429
|
+
|
|
430
|
+
{
|
|
431
|
+
"type": 'ScheduleRuleAbridged',
|
|
432
|
+
"schedule_day": str,
|
|
433
|
+
"apply_sunday": False,
|
|
434
|
+
"apply_monday": True,
|
|
435
|
+
"apply_tuesday": True,
|
|
436
|
+
"apply_wednesday": True,
|
|
437
|
+
"apply_thursday": True,
|
|
438
|
+
"apply_friday": True,
|
|
439
|
+
"apply_saturday": False,
|
|
440
|
+
"start_date": (1, 1),
|
|
441
|
+
"end_date": (12, 31)
|
|
442
|
+
}
|
|
443
|
+
"""
|
|
444
|
+
assert data['type'] == 'ScheduleRuleAbridged', \
|
|
445
|
+
'Expected ScheduleRuleAbridged dictionary. Got {}.'.format(data['type'])
|
|
446
|
+
|
|
447
|
+
sun, mon, tues, wed, thurs, fri, sat, start, end = \
|
|
448
|
+
cls._extract_apply_from_dict(data)
|
|
449
|
+
|
|
450
|
+
return cls(schedule_day, sun, mon, tues, wed, thurs, fri, sat, start, end)
|
|
451
|
+
|
|
452
|
+
def to_dict(self, abridged=False):
|
|
453
|
+
"""ScheduleRule dictionary representation.
|
|
454
|
+
|
|
455
|
+
Args:
|
|
456
|
+
abridged: Boolean to note whether the full dictionary describing the
|
|
457
|
+
object should be returned (False) or just an abridged version (True),
|
|
458
|
+
which only specifies the identifier of the schedule_day. Default: False.
|
|
459
|
+
"""
|
|
460
|
+
base = {'type': 'ScheduleRule'} if not abridged \
|
|
461
|
+
else {'type': 'ScheduleRuleAbridged'}
|
|
462
|
+
base['schedule_day'] = self.schedule_day.to_dict() if not abridged \
|
|
463
|
+
else self.schedule_day.identifier
|
|
464
|
+
base['apply_sunday'] = self.apply_sunday
|
|
465
|
+
base['apply_monday'] = self.apply_monday
|
|
466
|
+
base['apply_tuesday'] = self.apply_tuesday
|
|
467
|
+
base['apply_wednesday'] = self.apply_wednesday
|
|
468
|
+
base['apply_thursday'] = self.apply_thursday
|
|
469
|
+
base['apply_friday'] = self.apply_friday
|
|
470
|
+
base['apply_saturday'] = self.apply_saturday
|
|
471
|
+
base['start_date'] = self.start_date.to_array()
|
|
472
|
+
base['end_date'] = self.end_date.to_array()
|
|
473
|
+
return base
|
|
474
|
+
|
|
475
|
+
def duplicate(self):
|
|
476
|
+
"""Get a copy of this object."""
|
|
477
|
+
return self.__copy__()
|
|
478
|
+
|
|
479
|
+
def lock(self):
|
|
480
|
+
"""The lock() method will also lock the schedule_day."""
|
|
481
|
+
self._locked = True
|
|
482
|
+
self.schedule_day.lock()
|
|
483
|
+
|
|
484
|
+
def unlock(self):
|
|
485
|
+
"""The unlock() method will also unlock the schedule_day."""
|
|
486
|
+
self._locked = False
|
|
487
|
+
self.schedule_day.unlock()
|
|
488
|
+
|
|
489
|
+
@staticmethod
|
|
490
|
+
def extract_all_from_schedule_week(week_idf_string, day_schedule_dict,
|
|
491
|
+
start_date=None, end_date=None):
|
|
492
|
+
"""Extract all ScheduleRule objects from an IDF string of a Schedule:Week.
|
|
493
|
+
|
|
494
|
+
Args:
|
|
495
|
+
week_idf_string: A text string fully describing an EnergyPlus
|
|
496
|
+
Schedule:Week:Daily or Schedule:Week:Compact.
|
|
497
|
+
day_schedule_dict: A dictionary with the identifiers of ScheduleDay objects
|
|
498
|
+
as keys and the corresponding ScheduleDay objects as values. These objects
|
|
499
|
+
will be used to build the ScheduleRules using the week_idf_string.
|
|
500
|
+
start_date: A ladybug Date object for the start of the period over which
|
|
501
|
+
the ScheduleRules apply. If None, Jan 1 will be used.
|
|
502
|
+
end_date: A ladybug Date object for the end of the period over which
|
|
503
|
+
the ScheduleRules apply. If None, Dec 31 will be used.
|
|
504
|
+
|
|
505
|
+
Returns:
|
|
506
|
+
schedule_rules -- A list of ScheduleRule objects that together describe
|
|
507
|
+
the Schedule:Week.
|
|
508
|
+
"""
|
|
509
|
+
schedule_rules = []
|
|
510
|
+
if week_idf_string.startswith('Schedule:Week:Daily,'):
|
|
511
|
+
ep_strs = parse_idf_string(week_idf_string)
|
|
512
|
+
applied_day_ids = []
|
|
513
|
+
for i, day_sch_id in enumerate(ep_strs[1:8]):
|
|
514
|
+
if day_sch_id not in applied_day_ids: # make a new rule
|
|
515
|
+
rule = ScheduleRule(day_schedule_dict[day_sch_id],
|
|
516
|
+
start_date=start_date, end_date=end_date)
|
|
517
|
+
rule.apply_day_by_dow(i + 1)
|
|
518
|
+
schedule_rules.append(rule)
|
|
519
|
+
applied_day_ids.append(day_sch_id)
|
|
520
|
+
else: # edit one of the existing rules to apply it to the new day
|
|
521
|
+
sch_rule_index = applied_day_ids.index(day_sch_id)
|
|
522
|
+
rule = schedule_rules[sch_rule_index]
|
|
523
|
+
rule.apply_day_by_dow(i + 1)
|
|
524
|
+
else:
|
|
525
|
+
ep_strs = parse_idf_string(week_idf_string, 'Schedule:Week:Compact,')
|
|
526
|
+
for i in range(1, len(ep_strs), 2):
|
|
527
|
+
day_type, day_sch_id = ep_strs[i].lower(), ep_strs[i + 1]
|
|
528
|
+
rule = ScheduleRule(day_schedule_dict[day_sch_id])
|
|
529
|
+
if 'alldays' in day_type:
|
|
530
|
+
rule.apply_all = True
|
|
531
|
+
elif 'weekdays' in day_type:
|
|
532
|
+
rule.apply_weekday = True
|
|
533
|
+
elif 'weekends' in day_type:
|
|
534
|
+
rule.apply_weekend = True
|
|
535
|
+
elif 'sunday' in day_type:
|
|
536
|
+
rule.apply_sunday = True
|
|
537
|
+
elif 'monday' in day_type:
|
|
538
|
+
rule.apply_monday = True
|
|
539
|
+
elif 'tuesday' in day_type:
|
|
540
|
+
rule.apply_tuesday = True
|
|
541
|
+
elif 'wednesday' in day_type:
|
|
542
|
+
rule.apply_wednesday = True
|
|
543
|
+
elif 'thursday' in day_type:
|
|
544
|
+
rule.apply_thursday = True
|
|
545
|
+
elif 'friday' in day_type:
|
|
546
|
+
rule.apply_friday = True
|
|
547
|
+
elif 'saturday' in day_type:
|
|
548
|
+
rule.apply_saturday = True
|
|
549
|
+
elif 'allotherdays' in day_type:
|
|
550
|
+
apply_mtx = [rul.week_apply_tuple for rul in schedule_rules]
|
|
551
|
+
for j, dow in enumerate(zip(*apply_mtx)):
|
|
552
|
+
if not any(dow):
|
|
553
|
+
rule.apply_day_by_dow(j + 1)
|
|
554
|
+
if len(rule.days_applied) != 0:
|
|
555
|
+
schedule_rules.append(rule)
|
|
556
|
+
return schedule_rules
|
|
557
|
+
|
|
558
|
+
@staticmethod
|
|
559
|
+
def _extract_apply_from_dict(data):
|
|
560
|
+
"""Extract the apply values from a dictionary."""
|
|
561
|
+
apply_sunday = data['apply_sunday'] if 'apply_sunday' in data else False
|
|
562
|
+
apply_monday = data['apply_monday'] if 'apply_monday' in data else False
|
|
563
|
+
apply_tuesday = data['apply_tuesday'] if 'apply_tuesday' in data else False
|
|
564
|
+
apply_wednesday = data['apply_wednesday'] if 'apply_wednesday' in data else False
|
|
565
|
+
apply_thursday = data['apply_thursday'] if 'apply_thursday' in data else False
|
|
566
|
+
apply_friday = data['apply_friday'] if 'apply_friday' in data else False
|
|
567
|
+
apply_saturday = data['apply_saturday'] if 'apply_saturday' in data else False
|
|
568
|
+
start_date = Date.from_array(data['start_date']) if \
|
|
569
|
+
'start_date' in data else ScheduleRule._year_start
|
|
570
|
+
end_date = Date.from_array(data['end_date']) if \
|
|
571
|
+
'end_date' in data else ScheduleRule._year_end
|
|
572
|
+
|
|
573
|
+
return apply_sunday, apply_monday, apply_tuesday, apply_wednesday, \
|
|
574
|
+
apply_thursday, apply_friday, apply_saturday, start_date, end_date
|
|
575
|
+
|
|
576
|
+
@staticmethod
|
|
577
|
+
def _check_date(date, date_name='date'):
|
|
578
|
+
assert isinstance(date, Date), 'Expected ladybug Date for ' \
|
|
579
|
+
'ScheduleRule {}. Got {}.'.format(date_name, type(date))
|
|
580
|
+
|
|
581
|
+
@staticmethod
|
|
582
|
+
def _doy_non_leap_year(date):
|
|
583
|
+
"""Get a doy for a non-leap-year even when the input date is for a leap year."""
|
|
584
|
+
if not date.leap_year:
|
|
585
|
+
return date.doy
|
|
586
|
+
else:
|
|
587
|
+
return date.doy if date <= Date(2, 29, True) else date.doy - 1
|
|
588
|
+
|
|
589
|
+
def __key(self):
|
|
590
|
+
"""A tuple based on the object properties, useful for hashing."""
|
|
591
|
+
return (hash(self.schedule_day), self.schedule_day, self.apply_sunday,
|
|
592
|
+
self.apply_monday, self.apply_tuesday, self.apply_wednesday,
|
|
593
|
+
self.apply_thursday, self.apply_friday, self.apply_saturday,
|
|
594
|
+
hash(self.start_date), hash(self.end_date))
|
|
595
|
+
|
|
596
|
+
def __hash__(self):
|
|
597
|
+
return hash(self.__key())
|
|
598
|
+
|
|
599
|
+
def __eq__(self, other):
|
|
600
|
+
return isinstance(other, ScheduleRule) and self.__key() == other.__key()
|
|
601
|
+
|
|
602
|
+
def __ne__(self, other):
|
|
603
|
+
return not self.__eq__(other)
|
|
604
|
+
|
|
605
|
+
def __copy__(self):
|
|
606
|
+
return ScheduleRule(
|
|
607
|
+
self.schedule_day.duplicate(), self.apply_sunday,
|
|
608
|
+
self.apply_monday, self.apply_tuesday, self.apply_wednesday,
|
|
609
|
+
self.apply_thursday, self.apply_friday, self.apply_saturday,
|
|
610
|
+
self.start_date, self.end_date)
|
|
611
|
+
|
|
612
|
+
def ToString(self):
|
|
613
|
+
"""Overwrite .NET ToString."""
|
|
614
|
+
return self.__repr__()
|
|
615
|
+
|
|
616
|
+
def __repr__(self):
|
|
617
|
+
return 'ScheduleRule: {} [days applied: {}] [date range: {} - {}]'.format(
|
|
618
|
+
self.schedule_day.display_name, ', '.join(self.days_applied),
|
|
619
|
+
self.start_date, self.end_date)
|