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,443 @@
1
+ # coding=utf-8
2
+ """EnergyPlus Simulation Run Period."""
3
+ from __future__ import division
4
+
5
+ from ladybug.dt import Date
6
+ from ladybug.analysisperiod import AnalysisPeriod
7
+ from honeybee.typing import valid_string
8
+
9
+ from .daylightsaving import DaylightSavingTime
10
+ from ..reader import parse_idf_string
11
+ from ..writer import generate_idf_string
12
+
13
+
14
+ class RunPeriod(object):
15
+ """EnergyPlus Simulation Run Period.
16
+
17
+ Args:
18
+ start_date: A ladybug Date for the start of the run period. (Default: 1 Jan)
19
+ end_date: A ladybug Date for the end of the run period. (Default: 31 Dec)
20
+ start_day_of_week: Text for the day of the week on which the simulation
21
+ starts. Default: 'Sunday'. Choose from the following:
22
+
23
+ * Sunday
24
+ * Monday
25
+ * Tuesday
26
+ * Wednesday
27
+ * Thursday
28
+ * Friday
29
+ * Saturday
30
+
31
+ holidays: A list of Ladybug Date objects for the holidays within the
32
+ simulation. If None, no holidays are applied. Default: None.
33
+ daylight_saving_time: A DaylightSavingTime object to dictate the start and
34
+ end dates of daylight saving time. If None, no daylight saving time is
35
+ applied to the simulation. Default: None.
36
+
37
+ Properties:
38
+ * start_date
39
+ * end_date
40
+ * start_day_of_week
41
+ * holidays
42
+ * daylight_saving_time
43
+ * is_leap_year
44
+ """
45
+ __slots__ = ('_start_date', '_end_date', '_start_day_of_week', '_holidays',
46
+ '_daylight_saving_time')
47
+ DAYS_OF_THE_WEEK = (
48
+ 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday')
49
+
50
+ def __init__(self, start_date=Date(1, 1), end_date=Date(12, 31),
51
+ start_day_of_week='Sunday', holidays=None, daylight_saving_time=None):
52
+ """Initialize RunPeriod."""
53
+ # process the dates
54
+ if start_date is not None:
55
+ self._check_date(start_date, 'start_date')
56
+ self._start_date = start_date
57
+ else:
58
+ self._start_date = Date(1, 1)
59
+ self.end_date = end_date
60
+
61
+ self.start_day_of_week = start_day_of_week
62
+ self.holidays = holidays
63
+ self.daylight_saving_time = daylight_saving_time
64
+
65
+ @property
66
+ def start_date(self):
67
+ """Get or set a ladybug Date object for the start of the run period."""
68
+ return self._start_date
69
+
70
+ @start_date.setter
71
+ def start_date(self, value):
72
+ if value is not None:
73
+ self._check_date(value, 'start_date')
74
+ self._start_date = value
75
+ else:
76
+ self._start_date = Date(1, 1)
77
+
78
+ @property
79
+ def end_date(self):
80
+ """Get or set a ladybug Date object for the end of the run period."""
81
+ return self._end_date
82
+
83
+ @end_date.setter
84
+ def end_date(self, value):
85
+ if value is not None:
86
+ self._check_date(value, 'start_date')
87
+ self._end_date = value
88
+ else:
89
+ self._end_date = Date(12, 31)
90
+
91
+ @property
92
+ def start_day_of_week(self):
93
+ """Get or set text for the day of the week on which the simulation starts.
94
+
95
+ Choose from the following:
96
+
97
+ * Sunday
98
+ * Monday
99
+ * Tuesday
100
+ * Wednesday
101
+ * Thursday
102
+ * Friday
103
+ * Saturday
104
+ """
105
+ return self._start_day_of_week
106
+
107
+ @start_day_of_week.setter
108
+ def start_day_of_week(self, value):
109
+ clean_input = valid_string(value).lower()
110
+ for key in self.DAYS_OF_THE_WEEK:
111
+ if key.lower() == clean_input:
112
+ value = key
113
+ break
114
+ else:
115
+ raise ValueError(
116
+ 'start_day_of_week {} is not recognized.\nChoose from the '
117
+ 'following:\n{}'.format(value, self.DAYS_OF_THE_WEEK))
118
+ self._start_day_of_week = value
119
+
120
+ @property
121
+ def holidays(self):
122
+ """Get or set a list of ladybug Date objects for holidays."""
123
+ return self._holidays
124
+
125
+ @holidays.setter
126
+ def holidays(self, value):
127
+ if value is not None:
128
+ if not isinstance(value, tuple):
129
+ value = tuple(value)
130
+ for date in value:
131
+ assert isinstance(date, Date), 'Expected ladybug Date for ' \
132
+ 'RunPeriod holiday. Got {}.'.format(type(date))
133
+ self._holidays = value
134
+
135
+ @property
136
+ def daylight_saving_time(self):
137
+ """Get or set a DaylightSavingTime object for start and end of daylight savings.
138
+ """
139
+ return self._daylight_saving_time
140
+
141
+ @daylight_saving_time.setter
142
+ def daylight_saving_time(self, value):
143
+ if value is not None:
144
+ assert isinstance(value, DaylightSavingTime), 'Expected DaylightSavingTime' \
145
+ ' for RunPeriod run_period. Got {}.'.format(type(value))
146
+ if value.start_date.leap_year is not self.start_date.leap_year:
147
+ leap = self.start_date.leap_year
148
+ value._start_date = Date(value._start_date.month,
149
+ value._start_date.day, leap)
150
+ value._end_date = Date(value._end_date.month,
151
+ value._end_date.day, leap)
152
+ self._daylight_saving_time = value
153
+
154
+ @property
155
+ def is_leap_year(self):
156
+ """Get or set a boolean noting whether the RunPeriod is for a leap year simulation.
157
+ """
158
+ return self.start_date.leap_year
159
+
160
+ @is_leap_year.setter
161
+ def is_leap_year(self, value):
162
+ value = bool(value)
163
+ self._start_date = Date(self._start_date.month, self._start_date.day, value)
164
+ self._end_date = Date(self._end_date.month, self._end_date.day, value)
165
+ if self._daylight_saving_time is not None:
166
+ st_dt = self._daylight_saving_time._start_date
167
+ ed_dt = self._daylight_saving_time._end_date
168
+ self._daylight_saving_time._start_date = Date(st_dt.month, st_dt.day, value)
169
+ self._daylight_saving_time._end_date = Date(ed_dt.month, ed_dt.day, value)
170
+
171
+ @classmethod
172
+ def from_analysis_period(cls, analysis_period=None, start_day_of_week='Sunday',
173
+ holidays=None, daylight_saving_time=None):
174
+ """Initialize a RunPeriod object from a ladybug AnalysisPeriod.
175
+
176
+ Note that the st_hour and end_hour properties of the AnalysisPeriod are
177
+ completely ignored when using this classmethod since EnergyPlus cannot start
178
+ or end a simulation at an interval less than a day.
179
+
180
+ Args:
181
+ analysis_period: A ladybug AnalysisPeriod object that has the start
182
+ and end dates for the simulation. Default: an AnalysisPeriod for the
183
+ whole year.
184
+ start_day_of_week: Text for the day of the week on which the simulation
185
+ starts. Default: 'Sunday'. Choose from the following:
186
+
187
+ * Sunday
188
+ * Monday
189
+ * Tuesday
190
+ * Wednesday
191
+ * Thursday
192
+ * Friday
193
+ * Saturday
194
+
195
+ holidays: A list of Ladybug Date objects for the holidays within the
196
+ simulation. If None, no holidays are applied. Default: None.
197
+ daylight_saving_time: A DaylightSavingTime object to dictate the start and
198
+ end dates of daylight saving time. If None, no daylight saving time is
199
+ applied to the simulation. Default: None.
200
+ """
201
+ assert isinstance(analysis_period, AnalysisPeriod), 'Expected AnalysisPeriod ' \
202
+ 'for RunPeriod.from_analysis_period. Got {}.'.format(type(analysis_period))
203
+ st_date = Date(analysis_period.st_month, analysis_period.st_day,
204
+ analysis_period.is_leap_year)
205
+ end_date = Date(analysis_period.end_month, analysis_period.end_day,
206
+ analysis_period.is_leap_year)
207
+ return cls(st_date, end_date, start_day_of_week, holidays, daylight_saving_time)
208
+
209
+ @classmethod
210
+ def from_idf(cls, idf_string, holiday_strings=None, daylight_saving_string=None):
211
+ """Create a RunPeriod object from an EnergyPlus IDF text string.
212
+
213
+ Args:
214
+ idf_string: A text string fully describing an EnergyPlus RunPeriod
215
+ definition.
216
+ holiday_strings: A list of IDF RunPeriodControl:SpecialDays strings
217
+ that represent the holidays applied to the simulation.
218
+ daylight_saving_string: An IDF RunPeriodControl:DaylightSavingTime string
219
+ that notes the start and ends dates of Daylight Savings time.
220
+ """
221
+ # check the inputs
222
+ ep_strs = parse_idf_string(idf_string, 'RunPeriod,')
223
+
224
+ # extract the required properties
225
+ start_year = int(ep_strs[3]) if ep_strs[3] != '' else 2017
226
+ leap_year = True if start_year % 4 == 0 else False
227
+ start_date = Date(int(ep_strs[1]), int(ep_strs[2]), leap_year)
228
+ end_date = Date(int(ep_strs[4]), int(ep_strs[5]), leap_year)
229
+
230
+ # extract the optional properties
231
+ start_day_of_week = 'Sunday'
232
+ try:
233
+ start_day_of_week = ep_strs[7] if ep_strs[7] != '' else 'Sunday'
234
+ except IndexError:
235
+ pass # shorter RunPeriod definition
236
+ holidays = None
237
+ if holiday_strings is not None:
238
+ holidays = []
239
+ for hol_str in holiday_strings:
240
+ ep_hol_str = parse_idf_string(hol_str, 'RunPeriodControl:SpecialDays,')
241
+ hol_vals = ep_hol_str[1].split('/')
242
+ holidays.append(Date(int(hol_vals[0]), int(hol_vals[1]), leap_year))
243
+ daylight_saving = DaylightSavingTime.from_idf(daylight_saving_string) if \
244
+ daylight_saving_string is not None else None
245
+ if daylight_saving is not None:
246
+ st_dt = daylight_saving._start_date
247
+ ed_dt = daylight_saving._end_date
248
+ daylight_saving._start_date = Date(st_dt.month, st_dt.day, leap_year)
249
+ daylight_saving._end_date = Date(ed_dt.month, ed_dt.day, leap_year)
250
+
251
+ return cls(start_date, end_date, start_day_of_week, holidays, daylight_saving)
252
+
253
+ @classmethod
254
+ def from_dict(cls, data):
255
+ """Create a RunPeriod object from a dictionary.
256
+
257
+ Args:
258
+ data: A RunPeriod dictionary in following the format below.
259
+
260
+ .. code-block:: python
261
+
262
+ {
263
+ "type": "RunPeriod",
264
+ "start_date": (1, 1),
265
+ "end_date": (12, 31),
266
+ "start_day_of_week": 'Monday',
267
+ "holidays": [(1, 1), (7, 4)],
268
+ "daylight_saving_time": {}, # DaylightSavingTime dictionary representation
269
+ "leap_year": False
270
+ }
271
+ """
272
+ # check that it is the correct type
273
+ assert data['type'] == 'RunPeriod', \
274
+ 'Expected RunPeriod dictionary. Got {}.'.format(data['type'])
275
+
276
+ # set a default leap_year value
277
+ leap_year = False if 'leap_year' not in data else data['leap_year']
278
+
279
+ # process the properties
280
+ start_date = Date(data['start_date'][0], data['start_date'][1], leap_year) if \
281
+ 'start_date' in data else Date(1, 1, leap_year)
282
+ end_date = Date(data['end_date'][0], data['end_date'][1], leap_year) if \
283
+ 'end_date' in data else Date(12, 31)
284
+ start_day_of_week = data['start_day_of_week'] if \
285
+ 'start_day_of_week' in data else 'Sunday'
286
+ holidays = None
287
+ if 'holidays' in data and data['holidays'] is not None:
288
+ holidays = tuple(Date(hol[0], hol[1], leap_year) for hol in data['holidays'])
289
+ daylight_saving = None
290
+ if 'daylight_saving_time' in data and data['daylight_saving_time'] is not None:
291
+ daylight_saving = DaylightSavingTime.from_dict(data['daylight_saving_time'])
292
+ if daylight_saving is not None:
293
+ st_dt = daylight_saving._start_date
294
+ ed_dt = daylight_saving._end_date
295
+ daylight_saving._start_date = Date(st_dt.month, st_dt.day, leap_year)
296
+ daylight_saving._end_date = Date(ed_dt.month, ed_dt.day, leap_year)
297
+
298
+ return cls(start_date, end_date, start_day_of_week, holidays, daylight_saving)
299
+
300
+ @classmethod
301
+ def from_string(cls, run_period_string):
302
+ """Create an RunPeriod object from an RunPeriod string."""
303
+ # split the various objects that make us the run period
304
+ run_per_objs = run_period_string.split('\n\n')
305
+ holidays, dl_saving = None, None
306
+ if len(run_per_objs) > 1:
307
+ for obj in run_per_objs:
308
+ if obj.startswith('RunPeriodControl:DaylightSavingTime'):
309
+ dl_saving = obj
310
+ elif obj.startswith('RunPeriodControl:SpecialDays'):
311
+ holidays = []
312
+ lines = obj.split('\n')
313
+ for i in range(0, len(lines), 3):
314
+ holidays.append('\n'.join(lines[i:i+3]))
315
+ return cls.from_idf(run_per_objs[0], holidays, dl_saving)
316
+
317
+ def to_idf(self):
318
+ """Get an EnergyPlus string representation of the RunPeriod.
319
+
320
+ Returns:
321
+ A tuple with three elements
322
+
323
+ - run_period: An IDF string representation of the RunPeriod object.
324
+
325
+ - holidays: A list of IDF RunPeriodControl:SpecialDays strings that
326
+ represent the holidays applied to the simulation. Will be None
327
+ if no holidays are applied to this RunPeriod.
328
+
329
+ - daylight_saving_time: An IDF RunPeriodControl:DaylightSavingTime string
330
+ that notes the start and ends dates of Daylight Savings time. Will be
331
+ None if no daylight_saving_time is applied to this RunPeriod.
332
+
333
+ .. code-block:: shell
334
+
335
+ RunPeriod, ! Winter Simulation
336
+ Winter Simulation, !- Name
337
+ 12, !- Begin Month
338
+ 1, !- Begin Day of Month
339
+ , !- Begin Year
340
+ 3, !- End Month
341
+ 31, !- End Day of Month
342
+ , !- End Year
343
+ UseWeatherFile, !- Day of Week for Start Day
344
+ Yes, !- Use Weather File Holidays and Special Days
345
+ Yes, !- Use Weather File Daylight Saving Period
346
+ No, !- Apply Weekend Holiday Rule
347
+ Yes, !- Use Weather File Rain Indicators
348
+ Yes; !- Use Weather File Snow Indicators
349
+
350
+
351
+ """
352
+ year = 2016 if self.is_leap_year else 2017
353
+ values = ('CustomRunPeriod', self.start_date.month, self.start_date.day, year,
354
+ self.end_date.month, self.end_date.day, year,
355
+ self.start_day_of_week, 'No', 'No', 'No', 'Yes', 'Yes')
356
+ comments = ('name', 'start month', 'start day', 'start year',
357
+ 'end month', 'end day', 'end year', 'start day of week',
358
+ 'use weather file holidays', 'use weather file daylight savings',
359
+ 'apply weekend holiday', 'use epw rain', 'use epw snow')
360
+ run_period = generate_idf_string('RunPeriod', values, comments)
361
+
362
+ holidays = [self._holiday_to_idf(hol, i) for i, hol in
363
+ enumerate(self.holidays)] if self.holidays is not None else None
364
+
365
+ daylight_saving_time = self.daylight_saving_time.to_idf() if \
366
+ self.daylight_saving_time is not None else None
367
+
368
+ return run_period, holidays, daylight_saving_time
369
+
370
+ def to_dict(self):
371
+ """RunPeriod dictionary representation."""
372
+ base = {
373
+ 'type': 'RunPeriod',
374
+ 'start_date': (self.start_date.month, self.start_date.day),
375
+ 'end_date': (self.end_date.month, self.end_date.day),
376
+ 'start_day_of_week': self.start_day_of_week,
377
+ 'leap_year': self.is_leap_year
378
+ }
379
+ if self.holidays is not None:
380
+ base['holidays'] = [(hol.month, hol.day) for hol in self.holidays]
381
+ if self.daylight_saving_time is not None:
382
+ base['daylight_saving_time'] = self.daylight_saving_time.to_dict()
383
+ return base
384
+
385
+ def duplicate(self):
386
+ """Get a copy of this object."""
387
+ return self.__copy__()
388
+
389
+ @staticmethod
390
+ def _check_date(date, date_name='date'):
391
+ assert isinstance(date, Date), 'Expected ladybug Date for ' \
392
+ 'RunPeriod {}. Got {}.'.format(date_name, type(date))
393
+
394
+ @staticmethod
395
+ def _holiday_to_idf(date, count):
396
+ """Convert a ladybug Date object to an IDF holiday string.
397
+
398
+ .. code-block:: shell
399
+
400
+ RunPeriodControl:SpecialDays,
401
+ three_day_weekend, !- Name
402
+ 11/15, !- Start Date
403
+ 3, !- Duration {days}
404
+ Holiday; !- Special Day Type
405
+ """
406
+ values = ('Holiday_{}'.format(count), '{}/{}'.format(date.month, date.day))
407
+ comments = ('name', 'date')
408
+ return generate_idf_string('RunPeriodControl:SpecialDays', values, comments)
409
+
410
+ def ToString(self):
411
+ """Overwrite .NET ToString."""
412
+ return self.__repr__()
413
+
414
+ def __copy__(self):
415
+ dst = self.daylight_saving_time.duplicate() if self.daylight_saving_time \
416
+ is not None else None
417
+ return RunPeriod(self.start_date, self.end_date, self.start_day_of_week,
418
+ self.holidays, dst)
419
+
420
+ def __key(self):
421
+ """A tuple based on the object properties, useful for hashing."""
422
+ hol_tup = tuple(hash(hol) for hol in self.holidays) if \
423
+ self.holidays is not None else (None,)
424
+ return (hash(self.start_date), hash(self.end_date), self.start_day_of_week,
425
+ hash(self.daylight_saving_time)) + hol_tup
426
+
427
+ def __hash__(self):
428
+ return hash(self.__key())
429
+
430
+ def __eq__(self, other):
431
+ return isinstance(other, RunPeriod) and self.__key() == other.__key()
432
+
433
+ def __ne__(self, other):
434
+ return not self.__eq__(other)
435
+
436
+ def __repr__(self):
437
+ """Represent run period."""
438
+ run_per, holidays, dl_saving = self.to_idf()
439
+ if holidays is not None:
440
+ run_per = run_per + '\n\n' + '\n'.join(holidays)
441
+ if dl_saving is not None:
442
+ run_per = run_per + '\n\n' + dl_saving
443
+ return run_per