# coding=utf-8
"""Energy Construction Set."""
from __future__ import division
from .construction.dictutil import dict_to_construction
from .construction.opaque import OpaqueConstruction
from .construction.window import WindowConstruction
from .construction.windowshade import WindowConstructionShade
from .construction.dynamic import WindowConstructionDynamic
from .construction.shade import ShadeConstruction
from .construction.air import AirBoundaryConstruction
import honeybee_energy.lib.constructions as _lib
from honeybee._lockable import lockable
from honeybee.typing import valid_ep_string, clean_rad_string
[docs]
@lockable
class ConstructionSet(object):
"""Set containing all energy constructions needed to create an energy model.
Args:
identifier: Text string for a unique ConstructionSet ID. Must be < 100
characters and not contain any EnergyPlus special characters. This
will be used to identify the object across a model and in the
exported IDF.
wall_set: An optional WallConstructionSet object for this ConstructionSet.
If None, it will be the honeybee generic default WallConstructionSet.
floor_set: An optional FloorConstructionSet object for this ConstructionSet.
If None, it will be the honeybee generic default FloorConstructionSet.
roof_ceiling_set: An optional RoofCeilingConstructionSet object for this
ConstructionSet. If None, it will be the honeybee generic default
RoofCeilingConstructionSet.
aperture_set: An optional ApertureConstructionSet object for this
ConstructionSet. If None, it will be the honeybee generic default
ApertureConstructionSet.
door_set: An optional DoorConstructionSet object for this ConstructionSet.
If None, it will be the honeybee generic default DoorConstructionSet.
shade_construction: An optional ShadeConstruction to set the reflectance
properties of all outdoor shades to which this ConstructionSet is
assigned. If None, it will be the honeybee generic shade construction.
air_boundary_construction: An optional AirBoundaryConstruction or
OpaqueConstruction to set the properties of Faces with an AirBoundary
type. If None, it will be the honeybee generic air boundary construction.
Properties:
* identifier
* display_name
* wall_set
* floor_set
* roof_ceiling_set
* aperture_set
* door_set
* shade_construction
* air_boundary_construction
* constructions
* modified_constructions
* constructions_unique
* modified_constructions_unique
* materials_unique
* modified_materials_unique
* user_data
"""
__slots__ = ('_identifier', '_display_name', '_wall_set', '_floor_set',
'_roof_ceiling_set', '_aperture_set', '_door_set',
'_shade_construction', '_air_boundary_construction',
'_locked', '_user_data')
def __init__(self, identifier, wall_set=None, floor_set=None, roof_ceiling_set=None,
aperture_set=None, door_set=None, shade_construction=None,
air_boundary_construction=None):
"""Initialize energy construction set."""
self._locked = False # unlocked by default
self.identifier = identifier
self._display_name = None
self.wall_set = wall_set
self.floor_set = floor_set
self.roof_ceiling_set = roof_ceiling_set
self.aperture_set = aperture_set
self.door_set = door_set
self.shade_construction = shade_construction
self.air_boundary_construction = air_boundary_construction
self._user_data = None
@property
def identifier(self):
"""Get or set a text string for a unique construction set identifier."""
return self._identifier
@identifier.setter
def identifier(self, identifier):
self._identifier = valid_ep_string(identifier, 'construction set identifier')
@property
def display_name(self):
"""Get or set a string for the object name without any character restrictions.
If not set, this will be equal to the identifier.
"""
if self._display_name is None:
return self._identifier
return self._display_name
@display_name.setter
def display_name(self, value):
if value is not None:
try:
value = str(value)
except UnicodeEncodeError: # Python 2 machine lacking the character set
pass # keep it as unicode
self._display_name = value
@property
def wall_set(self):
"""Get or set the WallConstructionSet assigned to this ConstructionSet."""
return self._wall_set
@wall_set.setter
def wall_set(self, value):
if value is not None:
assert isinstance(value, WallConstructionSet), \
'Expected WallConstructionSet. Got {}'.format(type(value))
self._wall_set = value
else:
self._wall_set = WallConstructionSet()
@property
def floor_set(self):
"""Get or set the FloorConstructionSet assigned to this ConstructionSet."""
return self._floor_set
@floor_set.setter
def floor_set(self, value):
if value is not None:
assert isinstance(value, FloorConstructionSet), \
'Expected FloorConstructionSet. Got {}'.format(type(value))
self._floor_set = value
else:
self._floor_set = FloorConstructionSet()
@property
def roof_ceiling_set(self):
"""Get or set the RoofCeilingConstructionSet assigned to this ConstructionSet."""
return self._roof_ceiling_set
@roof_ceiling_set.setter
def roof_ceiling_set(self, value):
if value is not None:
assert isinstance(value, RoofCeilingConstructionSet), \
'Expected RoofCeilingConstructionSet. Got {}'.format(type(value))
self._roof_ceiling_set = value
else:
self._roof_ceiling_set = RoofCeilingConstructionSet()
@property
def aperture_set(self):
"""Get or set the ApertureConstructionSet assigned to this ConstructionSet."""
return self._aperture_set
@aperture_set.setter
def aperture_set(self, value):
if value is not None:
assert isinstance(value, ApertureConstructionSet), \
'Expected ApertureConstructionSet. Got {}'.format(type(value))
self._aperture_set = value
else:
self._aperture_set = ApertureConstructionSet()
@property
def door_set(self):
"""Get or set the DoorConstructionSet assigned to this ConstructionSet."""
return self._door_set
@door_set.setter
def door_set(self, value):
if value is not None:
assert isinstance(value, DoorConstructionSet), \
'Expected DoorConstructionSet. Got {}'.format(type(value))
self._door_set = value
else:
self._door_set = DoorConstructionSet()
@property
def shade_construction(self):
"""Get or set the ShadeConstruction assigned to this ConstructionSet."""
if self._shade_construction is None:
return _lib.generic_shade
return self._shade_construction
@shade_construction.setter
def shade_construction(self, value):
if value is not None:
assert isinstance(value, ShadeConstruction), \
'Expected ShadeConstruction. Got {}'.format(type(value))
value.lock() # lock editing in case construction has multiple references
self._shade_construction = value
@property
def air_boundary_construction(self):
"""Get or set the AirBoundaryConstruction assigned to this ConstructionSet."""
if self._air_boundary_construction is None:
return _lib.air_boundary
return self._air_boundary_construction
@air_boundary_construction.setter
def air_boundary_construction(self, value):
if value is not None:
assert isinstance(value, (AirBoundaryConstruction, OpaqueConstruction)), \
'Expected AirBoundaryConstruction or OpaqueConstruction. ' \
'Got {}'.format(type(value))
value.lock() # lock editing in case construction has multiple references
self._air_boundary_construction = value
@property
def constructions(self):
"""List of all constructions contained within the set."""
return self.wall_set.constructions + \
self.floor_set.constructions + \
self.roof_ceiling_set.constructions + \
self.aperture_set.constructions + \
self.door_set.constructions + \
[self.shade_construction, self.air_boundary_construction]
@property
def modified_constructions(self):
"""List of all constructions that are not defaulted within the set."""
mod_constructions = self.wall_set.modified_constructions + \
self.floor_set.modified_constructions + \
self.roof_ceiling_set.modified_constructions + \
self.aperture_set.modified_constructions + \
self.door_set.modified_constructions
if self._shade_construction is not None:
mod_constructions.append(self._shade_construction)
if self._air_boundary_construction is not None:
mod_constructions.append(self._air_boundary_construction)
return mod_constructions
@property
def constructions_unique(self):
"""List of all unique constructions contained within the set."""
return list(set(self.constructions))
@property
def modified_constructions_unique(self):
"""List of all unique constructions that are not defaulted within the set."""
return list(set(self.modified_constructions))
@property
def materials_unique(self):
"""List of all unique materials contained within the set."""
materials = []
for constr in self.constructions:
try:
materials.extend(constr.materials)
if constr.has_frame:
materials.append(constr.frame)
except AttributeError:
pass # ShadeConstruction or AirBoundaryConstruction
return list(set(materials))
@property
def modified_materials_unique(self):
"""List of all unique materials that are not defaulted within the set."""
materials = []
for constr in self.modified_constructions:
try:
materials.extend(constr.materials)
if constr.has_frame:
materials.append(constr.frame)
except AttributeError:
pass # ShadeConstruction or AirBoundaryConstruction
return list(set(materials))
@property
def user_data(self):
"""Get or set an optional dictionary for additional meta data for this object.
This will be None until it has been set. All keys and values of this
dictionary should be of a standard Python type to ensure correct
serialization of the object to/from JSON (eg. str, float, int, list, dict)
"""
if self._user_data is not None:
return self._user_data
@user_data.setter
def user_data(self, value):
if value is not None:
assert isinstance(value, dict), 'Expected dictionary for honeybee_energy' \
'object user_data. Got {}.'.format(type(value))
self._user_data = value
[docs]
def get_face_construction(self, face_type, boundary_condition):
"""Get a construction object that will be assigned to a given type of face.
Args:
face_type: Text string for the type of face (eg. 'Wall', 'Floor',
'Roof', 'AirBoundary').
boundary_condition: Text string for the boundary condition
(eg. 'Outdoors', 'Surface', 'Adiabatic', 'Ground')
"""
if face_type == 'Wall':
return self._get_constr_from_set(self.wall_set, boundary_condition)
elif face_type == 'Floor':
return self._get_constr_from_set(self.floor_set, boundary_condition)
elif face_type == 'RoofCeiling':
return self._get_constr_from_set(self.roof_ceiling_set, boundary_condition)
elif face_type == 'AirBoundary':
return self.air_boundary_construction
else:
raise NotImplementedError(
'Face type {} is not recognized for ConstructionSet'.format(face_type))
[docs]
def get_aperture_construction(self, boundary_condition, is_operable,
parent_face_type):
"""Get a construction object that will be assigned to a given type of aperture.
Args:
boundary_condition: Text string for the boundary condition
(eg. 'Outdoors', 'Surface')
is_operable: Boolean to note whether the aperture is operable.
parent_face_type: Text string for the type of face to which the aperture
is a child (eg. 'Wall', 'Floor', 'Roof').
"""
if boundary_condition == 'Outdoors':
if not is_operable:
if parent_face_type == 'Wall':
return self.aperture_set.window_construction
else:
return self.aperture_set.skylight_construction
else:
return self.aperture_set.operable_construction
elif boundary_condition == 'Surface':
return self.aperture_set.interior_construction
else:
raise NotImplementedError(
'Boundary condition {} is not recognized for apertures in '
'ConstructionSet'.format(boundary_condition))
[docs]
def get_door_construction(self, boundary_condition, is_glass, parent_face_type):
"""Get a construction object that will be assigned to a given type of door.
Args:
boundary_condition: Text string for the boundary condition
(eg. 'Outdoors', 'Surface')
is_glass: Boolean to note whether the door is glass (instead of opaque).
parent_face_type: Text string for the type of face to which the door
is a child (eg. 'Wall', 'Floor', 'Roof').
"""
if boundary_condition == 'Outdoors':
if not is_glass:
if parent_face_type == 'Wall':
return self.door_set.exterior_construction
else:
return self.door_set.overhead_construction
else:
return self.door_set.exterior_glass_construction
elif boundary_condition == 'Surface':
if not is_glass:
return self.door_set.interior_construction
else:
return self.door_set.interior_glass_construction
else:
raise NotImplementedError(
'Boundary condition {} is not recognized for doors in '
'ConstructionSet'.format(boundary_condition))
[docs]
@classmethod
def from_dict(cls, data):
"""Create a ConstructionSet from a dictionary.
Note that the dictionary must be a non-abridged version for this
classmethod to work.
Args:
data: Dictionary describing the ConstructionSet with the
format below.
.. code-block:: python
{
"type": 'ConstructionSet',
"identifier": str, # ConstructionSet identifier
"display_name": str, # ConstructionSet display name
"wall_set": {}, # A WallConstructionSet dictionary
"floor_set": {}, # A FloorConstructionSet dictionary
"roof_ceiling_set": {}, # A RoofCeilingConstructionSet dictionary
"aperture_set": {}, # A ApertureConstructionSet dictionary
"door_set": {}, # A DoorConstructionSet dictionary
"shade_construction": {}, # ShadeConstruction dictionary
"air_boundary_construction": {}, # AirBoundaryConstruction dictionary
}
"""
assert data['type'] == 'ConstructionSet', \
'Expected ConstructionSet. Got {}.'.format(data['type'])
# build each of the sub-construction sets
wall_set = WallConstructionSet.from_dict(data['wall_set']) if 'wall_set' \
in data and data['wall_set'] is not None else None
floor_set = FloorConstructionSet.from_dict(data['floor_set']) if 'floor_set' \
in data and data['floor_set'] is not None else None
roof_ceiling_set = \
RoofCeilingConstructionSet.from_dict(data['roof_ceiling_set']) \
if 'roof_ceiling_set' in data and data['roof_ceiling_set'] \
is not None else None
aperture_set = ApertureConstructionSet.from_dict(data['aperture_set']) if \
'aperture_set' in data and data['aperture_set'] is not None else None
door_set = DoorConstructionSet.from_dict(data['door_set']) if \
'door_set' in data and data['door_set'] is not None else None
shade_con = ShadeConstruction.from_dict(data['shade_construction']) if \
'shade_construction' in data and data['shade_construction'] is not None \
else None
air_con = None
if 'air_boundary_construction' in data and \
data['air_boundary_construction'] is not None:
if data['air_boundary_construction']['type'] == 'AirBoundaryConstruction':
air_con = AirBoundaryConstruction.from_dict(
data['air_boundary_construction'])
else:
air_con = OpaqueConstruction.from_dict(data['air_boundary_construction'])
new_obj = cls(data['identifier'], wall_set, floor_set, roof_ceiling_set,
aperture_set, door_set, shade_con, air_con)
if 'display_name' in data and data['display_name'] is not None:
new_obj.display_name = data['display_name']
if 'user_data' in data and data['user_data'] is not None:
new_obj.user_data = data['user_data']
return new_obj
[docs]
@classmethod
def from_dict_abridged(cls, data, construction_dict):
"""Create a ConstructionSet from an abridged dictionary.
Args:
data: A ConstructionSetAbridged dictionary.
construction_dict: A dictionary with construction identifiers as keys and
honeybee construction objects as values. These will be used to
assign the constructions to the ConstructionSet object.
.. code-block:: python
{
"type": 'ConstructionSetAbridged',
"identifier": str, # ConstructionSet identifier
"display_name": str, # ConstructionSet display name
"wall_set": {}, # A WallConstructionSetAbridged dictionary
"floor_set": {}, # A FloorConstructionSetAbridged dictionary
"roof_ceiling_set": {}, # A RoofCeilingConstructionSetAbridged dictionary
"aperture_set": {}, # A ApertureConstructionSetAbridged dictionary
"door_set": {}, # A DoorConstructionSetAbridged dictionary
"shade_construction": str, # ShadeConstruction identifier
"air_boundary_construction": str # AirBoundaryConstruction identifier
}
"""
assert data['type'] == 'ConstructionSetAbridged', \
'Expected ConstructionSetAbridged. Got {}.'.format(data['type'])
try:
wall_set, floor_set, roof_ceiling_set, aperture_set, door_set, shade_con, \
air_con = cls._get_subsets_from_abridged(data, construction_dict)
except KeyError as e:
raise ValueError(
'The following construction is missing from the model: {}'.format(e)
)
new_obj = cls(data['identifier'], wall_set, floor_set, roof_ceiling_set,
aperture_set, door_set, shade_con, air_con)
if 'display_name' in data and data['display_name'] is not None:
new_obj.display_name = data['display_name']
if 'user_data' in data and data['user_data'] is not None:
new_obj.user_data = data['user_data']
return new_obj
[docs]
def to_dict(self, abridged=False, none_for_defaults=True):
"""Get ConstructionSet as a dictionary.
Args:
abridged: Boolean noting whether detailed materials and construction
objects should be written into the ConstructionSet (False) or just
an abridged version (True). Default: False.
none_for_defaults: Boolean to note whether default constructions in the
set should be included in detail (False) or should be None (True).
Default: True.
"""
base = {'type': 'ConstructionSet'} if not \
abridged else {'type': 'ConstructionSetAbridged'}
base['identifier'] = self.identifier
base['wall_set'] = self.wall_set.to_dict(abridged, none_for_defaults)
base['floor_set'] = self.floor_set.to_dict(abridged, none_for_defaults)
base['roof_ceiling_set'] = \
self.roof_ceiling_set.to_dict(abridged, none_for_defaults)
base['aperture_set'] = self.aperture_set.to_dict(abridged, none_for_defaults)
base['door_set'] = self.door_set.to_dict(abridged, none_for_defaults)
if none_for_defaults:
if abridged:
base['shade_construction'] = self._shade_construction.identifier \
if self._shade_construction is not None else None
else:
base['shade_construction'] = self._shade_construction.to_dict() \
if self._shade_construction is not None else None
else:
base['shade_construction'] = self.shade_construction.identifier \
if abridged else self.shade_construction.to_dict()
if none_for_defaults:
if abridged:
base['air_boundary_construction'] = \
self._air_boundary_construction.identifier if \
self._air_boundary_construction is not None else None
else:
base['air_boundary_construction'] = \
self._air_boundary_construction.to_dict() if \
self._air_boundary_construction is not None else None
else:
base['air_boundary_construction'] = \
self.air_boundary_construction.identifier \
if abridged else self.air_boundary_construction.to_dict()
if self._display_name is not None:
base['display_name'] = self.display_name
if self._user_data is not None:
base['user_data'] = self.user_data
return base
[docs]
def to_radiance_solar_interior(self):
"""Honeybee Radiance modifier set for the interior solar properties."""
# convert all interior constructions into modifiers
unique_mods = {}
for constr in self.constructions_unique:
unique_mods[constr.identifier] = constr.to_radiance_solar_interior() \
if isinstance(constr, OpaqueConstruction) else constr.to_radiance_solar()
return self._create_modifier_set('Solar_Interior', unique_mods)
[docs]
def to_radiance_visible_interior(self):
"""Honeybee Radiance modifier set for the interior visible properties."""
# convert all interior constructions into modifiers
unique_mods = {}
for constr in self.constructions_unique:
unique_mods[constr.identifier] = constr.to_radiance_visible_interior() \
if isinstance(constr, OpaqueConstruction) \
else constr.to_radiance_visible()
return self._create_modifier_set('Visible_Interior', unique_mods)
[docs]
def to_radiance_solar_exterior(self):
"""Honeybee Radiance modifier set for the exterior solar properties."""
# convert all exterior constructions into modifiers
unique_mods = {}
for constr in self.constructions_unique:
unique_mods[constr.identifier] = constr.to_radiance_solar_exterior() \
if isinstance(constr, OpaqueConstruction) else constr.to_radiance_solar()
return self._create_modifier_set('Solar_Exterior', unique_mods)
[docs]
def to_radiance_visible_exterior(self):
"""Honeybee Radiance modifier set for the exterior visible properties."""
# convert all exterior constructions into modifiers
unique_mods = {}
for constr in self.constructions_unique:
unique_mods[constr.identifier] = constr.to_radiance_visible_exterior() \
if isinstance(constr, OpaqueConstruction) \
else constr.to_radiance_visible()
return self._create_modifier_set('Visible_Exterior', unique_mods)
[docs]
def duplicate(self):
"""Get a copy of this ConstructionSet."""
return self.__copy__()
[docs]
def lock(self):
"""The lock() method to will also lock the WallConstructionSet, etc."""
self._locked = True
self._wall_set.lock()
self._floor_set.lock()
self._roof_ceiling_set.lock()
self._aperture_set.lock()
self._door_set.lock()
[docs]
def unlock(self):
"""The unlock() method will also unlock the WallConstructionSet, etc."""
self._locked = False
self._wall_set.unlock()
self._floor_set.unlock()
self._roof_ceiling_set.unlock()
self._aperture_set.unlock()
self._door_set.unlock()
def _create_modifier_set(self, mod_type, unique_mods):
"""Create a modifier set from a dictionary of radiance modifiers."""
# import the radiance dependency
try:
from honeybee_radiance.modifierset import ModifierSet
except ImportError as e:
raise ImportError('honeybee_radiance library must be installed to use '
'to_radiance_solar() method. {}'.format(e))
# create the modifier set object
mod_set = ModifierSet(
'{}_{}'.format(clean_rad_string(self.identifier), mod_type))
mod_set.wall_set.exterior_modifier = \
unique_mods[self.wall_set.exterior_construction.identifier]
mod_set.wall_set.interior_modifier = \
unique_mods[self.wall_set.interior_construction.identifier]
mod_set.floor_set.exterior_modifier = \
unique_mods[self.floor_set.exterior_construction.identifier]
mod_set.floor_set.interior_modifier = \
unique_mods[self.floor_set.interior_construction.identifier]
mod_set.roof_ceiling_set.exterior_modifier = \
unique_mods[self.roof_ceiling_set.exterior_construction.identifier]
mod_set.roof_ceiling_set.interior_modifier = \
unique_mods[self.roof_ceiling_set.interior_construction.identifier]
mod_set.aperture_set.window_modifier = \
unique_mods[self.aperture_set.window_construction.identifier]
mod_set.aperture_set.interior_modifier = \
unique_mods[self.aperture_set.interior_construction.identifier]
mod_set.aperture_set.skylight_modifier = \
unique_mods[self.aperture_set.skylight_construction.identifier]
mod_set.aperture_set.operable_modifier = \
unique_mods[self.aperture_set.operable_construction.identifier]
mod_set.door_set.exterior_modifier = \
unique_mods[self.door_set.exterior_construction.identifier]
mod_set.door_set.interior_modifier = \
unique_mods[self.door_set.interior_construction.identifier]
mod_set.door_set.exterior_glass_modifier = \
unique_mods[self.door_set.exterior_glass_construction.identifier]
mod_set.door_set.interior_glass_modifier = \
unique_mods[self.door_set.interior_glass_construction.identifier]
mod_set.door_set.overhead_modifier = \
unique_mods[self.door_set.overhead_construction.identifier]
mod_set.shade_set.exterior_modifier = \
unique_mods[self.shade_construction.identifier]
mod_set.air_boundary_modifier = \
unique_mods[self.air_boundary_construction.identifier]
return mod_set
def _get_constr_from_set(self, face_type_set, boundary_condition):
"""Get a specific construction from a face_type_set."""
if boundary_condition == 'Outdoors':
return face_type_set.exterior_construction
elif boundary_condition == 'Surface' or boundary_condition == 'Adiabatic':
return face_type_set.interior_construction
else:
return face_type_set.ground_construction
@staticmethod
def _get_subsets_from_abridged(data, constructions):
"""Get subset objects from and abridged dictionary."""
wall_set = ConstructionSet._make_construction_subset(
data, WallConstructionSet(), 'wall_set', constructions)
floor_set = ConstructionSet._make_construction_subset(
data, FloorConstructionSet(), 'floor_set', constructions)
roof_ceiling_set = ConstructionSet._make_construction_subset(
data, RoofCeilingConstructionSet(), 'roof_ceiling_set', constructions)
aperture_set = ConstructionSet._make_aperture_subset(
data, ApertureConstructionSet(), constructions)
door_set = ConstructionSet._make_door_subset(
data, DoorConstructionSet(), constructions)
if 'shade_construction' in data and data['shade_construction'] is not None:
shade = constructions[data['shade_construction']]
else:
shade = None
if 'air_boundary_construction' in data and \
data['air_boundary_construction'] is not None:
air = constructions[data['air_boundary_construction']]
else:
air = None
return wall_set, floor_set, roof_ceiling_set, aperture_set, door_set, shade, air
@staticmethod
def _make_construction_subset(data, sub_set, sub_set_id, constructions):
"""Make a wall set, floor set, or roof ceiling set from dictionary."""
if sub_set_id in data:
if 'exterior_construction' in data[sub_set_id] and \
data[sub_set_id]['exterior_construction'] is not None:
sub_set.exterior_construction = \
constructions[data[sub_set_id]['exterior_construction']]
if 'interior_construction' in data[sub_set_id] and \
data[sub_set_id]['interior_construction'] is not None:
sub_set.interior_construction = \
constructions[data[sub_set_id]['interior_construction']]
if 'ground_construction' in data[sub_set_id] and \
data[sub_set_id]['ground_construction'] is not None:
sub_set.ground_construction = \
constructions[data[sub_set_id]['ground_construction']]
return sub_set
@staticmethod
def _make_aperture_subset(data, sub_set, constructions):
"""Make an ApertureConstructionSet from a dictionary."""
if 'aperture_set' in data:
if 'window_construction' in data['aperture_set'] and \
data['aperture_set']['window_construction'] is not None:
sub_set.window_construction = \
constructions[data['aperture_set']['window_construction']]
if 'interior_construction' in data['aperture_set'] and \
data['aperture_set']['interior_construction'] is not None:
sub_set.interior_construction = \
constructions[data['aperture_set']['interior_construction']]
if 'skylight_construction' in data['aperture_set'] and \
data['aperture_set']['skylight_construction'] is not None:
sub_set.skylight_construction = \
constructions[data['aperture_set']['skylight_construction']]
if 'operable_construction' in data['aperture_set'] and \
data['aperture_set']['operable_construction'] is not None:
sub_set.operable_construction = \
constructions[data['aperture_set']['operable_construction']]
return sub_set
@staticmethod
def _make_door_subset(data, sub_set, constructions):
"""Make a DoorConstructionSet from dictionary."""
if 'door_set' in data:
if 'exterior_construction' in data['door_set'] and \
data['door_set']['exterior_construction'] is not None:
sub_set.exterior_construction = \
constructions[data['door_set']['exterior_construction']]
if 'interior_construction' in data['door_set'] and \
data['door_set']['interior_construction'] is not None:
sub_set.interior_construction = \
constructions[data['door_set']['interior_construction']]
if 'exterior_glass_construction' in data['door_set'] and \
data['door_set']['exterior_glass_construction'] is not None:
sub_set.exterior_glass_construction = \
constructions[data['door_set']['exterior_glass_construction']]
if 'interior_glass_construction' in data['door_set'] and \
data['door_set']['interior_glass_construction'] is not None:
sub_set.interior_glass_construction = \
constructions[data['door_set']['interior_glass_construction']]
if 'overhead_construction' in data['door_set'] and \
data['door_set']['overhead_construction'] is not None:
sub_set.overhead_construction = \
constructions[data['door_set']['overhead_construction']]
return sub_set
[docs]
def ToString(self):
"""Overwrite .NET ToString."""
return self.__repr__()
def __copy__(self):
new_obj = ConstructionSet(self.identifier,
self.wall_set.duplicate(),
self.floor_set.duplicate(),
self.roof_ceiling_set.duplicate(),
self.aperture_set.duplicate(),
self.door_set.duplicate(),
self._shade_construction,
self._air_boundary_construction)
new_obj._display_name = self._display_name
new_obj.user_data = None if self._user_data is None else self._user_data.copy()
return new_obj
def __key(self):
"""A tuple based on the object properties, useful for hashing."""
return (self.identifier,) + tuple(hash(cnstr) for cnstr in self.constructions)
def __hash__(self):
return hash(self.__key())
def __eq__(self, other):
return isinstance(other, ConstructionSet) and self.__key() == other.__key()
def __ne__(self, other):
return not self.__eq__(other)
def __repr__(self):
return 'Energy Construction Set: {}'.format(self.display_name)
@lockable
class _FaceSetBase(object):
"""Base class for the sets assigned to Faces.
This includesWallConstructionSet, FloorConstructionSet, and the
RoofCeilingConstructionSet.
Args:
exterior_construction: An OpaqueConstruction object for faces with an
Outdoors boundary condition.
interior_construction: An OpaqueConstruction object for faces with a
Surface or Adiabatic boundary condition.
ground_construction: : An OpaqueConstruction object for faces with a
Ground boundary condition.
"""
__slots__ = ('_exterior_construction', '_interior_construction',
'_ground_construction', '_locked')
def __init__(self, exterior_construction=None, interior_construction=None,
ground_construction=None):
"""Initialize set."""
self._locked = False # unlocked by default
self.exterior_construction = exterior_construction
self.interior_construction = interior_construction
self.ground_construction = ground_construction
@property
def exterior_construction(self):
"""Get or set the OpaqueConstruction for exterior Faces."""
return self._exterior_construction
@exterior_construction.setter
def exterior_construction(self, value):
self._exterior_construction = value
@property
def interior_construction(self):
"""Get or set the OpaqueConstruction for interior Faces."""
return self._interior_construction
@interior_construction.setter
def interior_construction(self, value):
self._interior_construction = value
@property
def ground_construction(self):
"""Get or set the OpaqueConstruction for underground Faces."""
return self._ground_construction
@ground_construction.setter
def ground_construction(self, value):
self._ground_construction = value
@property
def constructions(self):
"""List of all constructions contained within the set."""
return [self.exterior_construction,
self.interior_construction,
self.ground_construction]
@property
def modified_constructions(self):
"""List of all constructions that are not defaulted within the set."""
constructions = []
if self._exterior_construction is not None:
constructions.append(self._exterior_construction)
if self._interior_construction is not None:
constructions.append(self._interior_construction)
if self._ground_construction is not None:
constructions.append(self._ground_construction)
return constructions
@property
def is_modified(self):
"""Boolean noting whether any constructions are modified from the default."""
return self._exterior_construction is not None or \
self._interior_construction is not None or \
self._ground_construction is not None
@classmethod
def from_dict(cls, data):
"""Create a SubSet from a dictionary.
Note that the dictionary must be a non-abridged version for this
classmethod to work.
Args:
data: Dictionary describing the Set of the object.
"""
assert data['type'] == cls.__name__, \
'Expected {}. Got {}.'.format(cls.__name__, data['type'])
extc = OpaqueConstruction.from_dict(data['exterior_construction']) \
if 'exterior_construction' in data and data['exterior_construction'] \
is not None else None
intc = OpaqueConstruction.from_dict(data['interior_construction']) \
if 'interior_construction' in data and data['interior_construction'] \
is not None else None
gndc = OpaqueConstruction.from_dict(data['ground_construction']) \
if 'ground_construction' in data and data['ground_construction'] \
is not None else None
return cls(extc, intc, gndc)
def to_dict(self, abridged=False, none_for_defaults=True):
"""Get the Set as a dictionary.
Args:
abridged: Boolean noting whether detailed materials and construction
objects should be written into the ConstructionSet (False) or just
an abridged version (True). Default: False.
none_for_defaults: Boolean to note whether default constructions in the
set should be included in detail (False) or should be None (True).
Default: True.
"""
base = {'type': self.__class__.__name__ + 'Abridged'} if abridged else \
{'type': self.__class__.__name__}
if none_for_defaults:
if abridged:
base['exterior_construction'] = self._exterior_construction.identifier \
if self._exterior_construction is not None else None
base['interior_construction'] = self._interior_construction.identifier \
if self._interior_construction is not None else None
base['ground_construction'] = self._ground_construction.identifier \
if self._ground_construction is not None else None
else:
base['exterior_construction'] = self._exterior_construction.to_dict() \
if self._exterior_construction is not None else None
base['interior_construction'] = self._interior_construction.to_dict() \
if self._interior_construction is not None else None
base['ground_construction'] = self._ground_construction.to_dict() \
if self._ground_construction is not None else None
else:
base['exterior_construction'] = self.exterior_construction.identifier \
if abridged else self.exterior_construction.to_dict()
base['interior_construction'] = self.interior_construction.identifier \
if abridged else self.exterior_construction.to_dict()
base['ground_construction'] = self.ground_construction.identifier \
if abridged else self.exterior_construction.to_dict()
return base
def duplicate(self):
"""Get a copy of this set."""
return self.__copy__()
def _check_construction(self, value):
"""Check an OpaqueConstruction before assigning it."""
assert isinstance(value, OpaqueConstruction), \
'Expected OpaqueConstruction. Got {}'.format(type(value))
value.lock() # lock editing in case construction has multiple references
def ToString(self):
"""Overwrite .NET ToString."""
return self.__repr__()
def __len__(self):
return 3
def __iter__(self):
return iter(self.constructions)
def __copy__(self):
new_obj = self.__class__(
self._exterior_construction, self._interior_construction,
self._ground_construction)
return(new_obj)
def __repr__(self):
return 'Base Face Set'
[docs]
@lockable
class WallConstructionSet(_FaceSetBase):
"""Set containing all energy constructions needed to for an energy model's Walls.
Properties:
* exterior_construction
* interior_construction
* ground_construction
* constructions
* modified_constructions
* is_modified
"""
__slots__ = ()
@property
def exterior_construction(self):
"""Get or set the OpaqueConstruction for exterior walls."""
if self._exterior_construction is None:
return _lib.generic_exterior_wall
return self._exterior_construction
@exterior_construction.setter
def exterior_construction(self, value):
if value is not None:
self._check_construction(value)
self._exterior_construction = value
@property
def interior_construction(self):
"""Get or set the OpaqueConstruction for interior walls."""
if self._interior_construction is None:
return _lib.generic_interior_wall
return self._interior_construction
@interior_construction.setter
def interior_construction(self, value):
if value is not None:
self._check_construction(value)
self._interior_construction = value
@property
def ground_construction(self):
"""Get or set the OpaqueConstruction for underground walls."""
if self._ground_construction is None:
return _lib.generic_underground_wall
return self._ground_construction
@ground_construction.setter
def ground_construction(self, value):
if value is not None:
self._check_construction(value)
self._ground_construction = value
def __repr__(self):
return 'Wall Construction Set: [Exterior: {}] [Interior: {}]' \
' [Ground: {}]'.format(self.exterior_construction.display_name,
self.interior_construction.display_name,
self.ground_construction.display_name)
[docs]
@lockable
class FloorConstructionSet(_FaceSetBase):
"""Set containing all energy constructions needed to for an energy model's Floors.
Properties:
* exterior_construction
* interior_construction
* ground_construction
* constructions
* modified_constructions
* is_modified
"""
__slots__ = ()
@property
def exterior_construction(self):
"""Get or set the OpaqueConstruction for exterior-exposed floors."""
if self._exterior_construction is None:
return _lib.generic_exposed_floor
return self._exterior_construction
@exterior_construction.setter
def exterior_construction(self, value):
if value is not None:
self._check_construction(value)
self._exterior_construction = value
@property
def interior_construction(self):
"""Get or set the OpaqueConstruction for interior floors."""
if self._interior_construction is None:
return _lib.generic_interior_floor
return self._interior_construction
@interior_construction.setter
def interior_construction(self, value):
if value is not None:
self._check_construction(value)
self._interior_construction = value
@property
def ground_construction(self):
"""Get or set the OpaqueConstruction for ground-contact floor slabs."""
if self._ground_construction is None:
return _lib.generic_ground_slab
return self._ground_construction
@ground_construction.setter
def ground_construction(self, value):
if value is not None:
self._check_construction(value)
self._ground_construction = value
def __repr__(self):
return 'Floor Construction Set: [Exterior: {}] [Interior: {}]' \
' [Ground: {}]'.format(self.exterior_construction.display_name,
self.interior_construction.display_name,
self.ground_construction.display_name)
[docs]
@lockable
class RoofCeilingConstructionSet(_FaceSetBase):
"""Set containing all energy constructions needed to for an energy model's Roofs.
Properties:
* exterior_construction
* interior_construction
* ground_construction
* constructions
* modified_constructions
* is_modified
"""
__slots__ = ()
@property
def exterior_construction(self):
"""Get or set the OpaqueConstruction for exterior roofs."""
if self._exterior_construction is None:
return _lib.generic_roof
return self._exterior_construction
@exterior_construction.setter
def exterior_construction(self, value):
if value is not None:
self._check_construction(value)
self._exterior_construction = value
@property
def interior_construction(self):
"""Get or set the OpaqueConstruction for interior ceilings."""
if self._interior_construction is None:
return _lib.generic_interior_ceiling
return self._interior_construction
@interior_construction.setter
def interior_construction(self, value):
if value is not None:
self._check_construction(value)
self._interior_construction = value
@property
def ground_construction(self):
"""Get or set the OpaqueConstruction for underground roofs."""
if self._ground_construction is None:
return _lib.generic_underground_roof
return self._ground_construction
@ground_construction.setter
def ground_construction(self, value):
if value is not None:
self._check_construction(value)
self._ground_construction = value
def __repr__(self):
return 'RoofCeiling Construction Set: [Exterior: {}] [Interior: {}]' \
' [Ground: {}]'.format(self.exterior_construction.display_name,
self.interior_construction.display_name,
self.ground_construction.display_name)
[docs]
@lockable
class ApertureConstructionSet(object):
"""Set containing all constructions needed to for an energy model's Apertures.
Args:
window_construction: A WindowConstruction object for apertures
with an Outdoors boundary condition, False is_operable property,
and a Wall face type for their parent face.
interior_construction: A WindowConstruction object for all apertures
with a Surface boundary condition.
skylight_construction: : A WindowConstruction object for apertures with a
Outdoors boundary condition, False is_operable property, and a
RoofCeiling or Floor face type for their parent face.
operable_construction: A WindowConstruction object for all apertures
with an Outdoors boundary condition and True is_operable property.
Properties:
* window_construction
* interior_construction
* skylight_construction
* operable_construction
* constructions
* modified_constructions
* is_modified
"""
__slots__ = ('_window_construction', '_interior_construction',
'_skylight_construction', '_operable_construction', '_locked')
def __init__(self, window_construction=None, interior_construction=None,
skylight_construction=None, operable_construction=None):
"""Initialize aperture set."""
self._locked = False # unlocked by default
self.window_construction = window_construction
self.interior_construction = interior_construction
self.skylight_construction = skylight_construction
self.operable_construction = operable_construction
@property
def window_construction(self):
"""Get or set the WindowConstruction for exterior fixed windows in walls."""
if self._window_construction is None:
return _lib.generic_double_pane
return self._window_construction
@window_construction.setter
def window_construction(self, value):
if value is not None:
self._check_window_construction(value)
self._window_construction = value
@property
def interior_construction(self):
"""Get or set the WindowConstruction for all interior apertures."""
if self._interior_construction is None:
return _lib.generic_single_pane
return self._interior_construction
@interior_construction.setter
def interior_construction(self, value):
if value is not None:
self._check_window_construction(value)
self._interior_construction = value
@property
def skylight_construction(self):
"""Get or set the WindowConstruction for exterior fixed windows in roofs."""
if self._skylight_construction is None:
return _lib.generic_double_pane
return self._skylight_construction
@skylight_construction.setter
def skylight_construction(self, value):
if value is not None:
self._check_window_construction(value)
self._skylight_construction = value
@property
def operable_construction(self):
"""Get or set the WindowConstruction for all exterior operable windows."""
if self._operable_construction is None:
return _lib.generic_double_pane
return self._operable_construction
@operable_construction.setter
def operable_construction(self, value):
if value is not None:
self._check_window_construction(value)
self._operable_construction = value
@property
def constructions(self):
"""List of all constructions contained within the set."""
return [self.window_construction,
self.interior_construction,
self.skylight_construction,
self.operable_construction]
@property
def modified_constructions(self):
"""List of all constructions that are not defaulted within the set."""
constructions = []
if self._window_construction is not None:
constructions.append(self._window_construction)
if self._interior_construction is not None:
constructions.append(self._interior_construction)
if self._skylight_construction is not None:
constructions.append(self._skylight_construction)
if self._operable_construction is not None:
constructions.append(self._operable_construction)
return constructions
@property
def is_modified(self):
"""Boolean noting whether any constructions are modified from the default."""
return self._window_construction is not None or \
self._interior_construction is not None or \
self._skylight_construction is not None or \
self._operable_construction is not None
[docs]
@classmethod
def from_dict(cls, data):
"""Create a ApertureConstructionSet from a dictionary.
Note that the dictionary must be a non-abridged version for this
classmethod to work.
Args:
data: Dictionary describing the Set of the object.
"""
assert data['type'] == 'ApertureConstructionSet', \
'Expected ApertureConstructionSet. Got {}.'.format(data['type'])
winc = dict_to_construction(data['window_construction']) \
if 'window_construction' in data and data['window_construction'] \
is not None else None
intc = dict_to_construction(data['interior_construction']) \
if 'interior_construction' in data and data['interior_construction'] \
is not None else None
skyc = dict_to_construction(data['skylight_construction']) \
if 'skylight_construction' in data and data['skylight_construction'] \
is not None else None
opc = dict_to_construction(data['operable_construction'])\
if 'operable_construction' in data and data['operable_construction'] \
is not None else None
return cls(winc, intc, skyc, opc)
[docs]
def to_dict(self, abridged=False, none_for_defaults=True):
"""Get ApertureConstructionSet as a dictionary.
Args:
abridged: Boolean noting whether detailed materials and construction
objects should be written into the ConstructionSet (False) or just
an abridged version (True). Default: False.
none_for_defaults: Boolean to note whether default constructions in the
set should be included in detail (False) or should be None (True).
Default: True.
"""
base = {'type': 'ApertureConstructionSetAbridged'} if abridged \
else {'type': 'ApertureConstructionSet'}
if none_for_defaults:
if abridged:
base['window_construction'] = self._window_construction.identifier if \
self._window_construction is not None else None
base['interior_construction'] = \
self._interior_construction.identifier if \
self._interior_construction is not None else None
base['skylight_construction'] = \
self._skylight_construction.identifier if \
self._skylight_construction is not None else None
base['operable_construction'] = \
self._operable_construction.identifier if \
self._operable_construction is not None else None
else:
base['window_construction'] = self._window_construction.to_dict() \
if self._window_construction is not None else None
base['interior_construction'] = self._interior_construction.to_dict() \
if self._interior_construction is not None else None
base['skylight_construction'] = self._skylight_construction.to_dict() \
if self._skylight_construction is not None else None
base['operable_construction'] = \
self._operable_construction.to_dict() if \
self._operable_construction is not None else None
else:
base['window_construction'] = self.window_construction.identifier if \
abridged else self.window_construction.to_dict()
base['interior_construction'] = self.interior_construction.identifier if \
abridged else self.interior_construction.to_dict()
base['skylight_construction'] = self.skylight_construction.identifier if \
abridged else self.skylight_construction.to_dict()
base['operable_construction'] = self.operable_construction.identifier if \
abridged else self.operable_construction.to_dict()
return base
[docs]
def duplicate(self):
"""Get a copy of this set."""
return self.__copy__()
def _check_window_construction(self, value):
"""Check that a construction is valid before assigning it."""
val_w = (WindowConstruction, WindowConstructionShade, WindowConstructionDynamic)
assert isinstance(value, val_w), \
'Expected Window Construction. Got {}'.format(type(value))
value.lock() # lock editing in case construction has multiple references
[docs]
def ToString(self):
"""Overwrite .NET ToString."""
return self.__repr__()
def __len__(self):
return 4
def __iter__(self):
return iter(self.constructions)
def __copy__(self):
new_obj = self.__class__(
self._window_construction, self._interior_construction,
self._skylight_construction, self._operable_construction
)
return(new_obj)
def __repr__(self):
return 'Aperture Construction Set: [Window: {}] [Interior: {}]' \
' [Skylight: {}] [Operable: {}]'.format(
self.window_construction.display_name,
self.interior_construction.display_name,
self.skylight_construction.display_name,
self.operable_construction.display_name)
[docs]
@lockable
class DoorConstructionSet(object):
"""Set containing all energy constructions needed to for an energy model's Roofs.
Args:
exterior_construction: An OpaqueConstruction object for opaque doors with an
Outdoors boundary condition and a Wall face type for their parent face.
interior_construction: An OpaqueConstruction object for all opaque doors
with a Surface boundary condition.
exterior_glass_construction: A WindowConstruction object for all glass
doors with an Outdoors boundary condition.
interior_glass_construction: A WindowConstruction object for all glass
doors with a Surface boundary condition.
overhead_construction: An OpaqueConstruction object for opaque doors with
an Outdoors boundary condition and a RoofCeiling or Floor face type for
their parent face.
Properties:
* exterior_construction
* interior_construction
* exterior_glass_construction
* interior_glass_construction
* overhead_construction
* constructions
* modified_constructions
* is_modified
"""
__slots__ = ('_exterior_construction', '_interior_construction',
'_exterior_glass_construction', '_interior_glass_construction',
'_overhead_construction', '_locked')
def __init__(self, exterior_construction=None, interior_construction=None,
exterior_glass_construction=None, interior_glass_construction=None,
overhead_construction=None):
"""Initialize door set."""
self._locked = False # unlocked by default
self.exterior_construction = exterior_construction
self.interior_construction = interior_construction
self.exterior_glass_construction = exterior_glass_construction
self.interior_glass_construction = interior_glass_construction
self.overhead_construction = overhead_construction
@property
def exterior_construction(self):
"""Get or set the OpaqueConstruction for exterior opaque doors in walls."""
if self._exterior_construction is None:
return _lib.generic_exterior_door
return self._exterior_construction
@exterior_construction.setter
def exterior_construction(self, value):
if value is not None:
self._check_construction(value)
self._exterior_construction = value
@property
def interior_construction(self):
"""Get or set the OpaqueConstruction for all interior opaque doors."""
if self._interior_construction is None:
return _lib.generic_interior_door
return self._interior_construction
@interior_construction.setter
def interior_construction(self, value):
if value is not None:
self._check_construction(value)
self._interior_construction = value
@property
def exterior_glass_construction(self):
"""Get or set the WindowConstruction for exterior glass doors."""
if self._exterior_glass_construction is None:
return _lib.generic_double_pane
return self._exterior_glass_construction
@exterior_glass_construction.setter
def exterior_glass_construction(self, value):
if value is not None:
self._check_window_construction(value)
self._exterior_glass_construction = value
@property
def interior_glass_construction(self):
"""Get or set the WindowConstruction for all interior glass doors."""
if self._interior_glass_construction is None:
return _lib.generic_single_pane
return self._interior_glass_construction
@interior_glass_construction.setter
def interior_glass_construction(self, value):
if value is not None:
self._check_window_construction(value)
self._interior_glass_construction = value
@property
def overhead_construction(self):
"""Get or set the OpaqueConstruction for exterior opaque doors in roofs/floors.
"""
if self._overhead_construction is None:
return _lib.generic_exterior_door
return self._overhead_construction
@overhead_construction.setter
def overhead_construction(self, value):
if value is not None:
self._check_construction(value)
self._overhead_construction = value
@property
def constructions(self):
"""List of all constructions contained within the set."""
return [self.exterior_construction,
self.interior_construction,
self.exterior_glass_construction,
self.interior_glass_construction,
self.overhead_construction]
@property
def modified_constructions(self):
"""List of all constructions that are not defaulted within the set."""
constructions = []
if self._exterior_construction is not None:
constructions.append(self._exterior_construction)
if self._interior_construction is not None:
constructions.append(self._interior_construction)
if self._exterior_glass_construction is not None:
constructions.append(self._exterior_glass_construction)
if self._interior_glass_construction is not None:
constructions.append(self._interior_glass_construction)
if self._overhead_construction is not None:
constructions.append(self._overhead_construction)
return constructions
@property
def is_modified(self):
"""Boolean noting whether any constructions are modified from the default."""
return self._exterior_construction is not None or \
self._interior_construction is not None or \
self._exterior_glass_construction is not None or \
self._interior_glass_construction is not None or \
self._overhead_construction is None
[docs]
@classmethod
def from_dict(cls, data):
"""Create a DoorConstructionSet from a dictionary.
Note that the dictionary must be a non-abridged version for this
classmethod to work.
Args:
data: Dictionary describing the Set of the object.
"""
assert data['type'] == 'DoorConstructionSet', \
'Expected DoorConstructionSet. Got {}.'.format(data['type'])
extc = OpaqueConstruction.from_dict(data['exterior_construction']) \
if 'exterior_construction' in data and data['exterior_construction'] \
is not None else None
intc = OpaqueConstruction.from_dict(data['interior_construction']) \
if 'interior_construction' in data and data['interior_construction'] \
is not None else None
egc = dict_to_construction(data['exterior_glass_construction']) \
if 'exterior_glass_construction' in data and \
data['exterior_glass_construction'] is not None else None
igc = dict_to_construction(data['interior_glass_construction']) \
if 'interior_glass_construction' in data and \
data['interior_glass_construction'] is not None else None
ohc = OpaqueConstruction.from_dict(data['overhead_construction']) \
if 'overhead_construction' in data and data['overhead_construction'] \
is not None else None
return cls(extc, intc, egc, igc, ohc)
[docs]
def to_dict(self, abridged=False, none_for_defaults=True):
"""Get the DoorConstructionSet as a dictionary.
Args:
abridged: Boolean noting whether detailed materials and construction
objects should be written into the ConstructionSet (False) or just
an abridged version (True). Default: False.
none_for_defaults: Boolean to note whether default constructions in the
set should be included in detail (False) or should be None (True).
Default: True.
"""
base = {'type': 'DoorConstructionSetAbridged'} if abridged \
else {'type': 'DoorConstructionSet'}
if none_for_defaults:
if abridged:
base['exterior_construction'] = self._exterior_construction.identifier \
if self._exterior_construction is not None else None
base['interior_construction'] = self._interior_construction.identifier \
if self._interior_construction is not None else None
base['exterior_glass_construction'] = \
self._exterior_glass_construction.identifier if \
self._exterior_glass_construction is not None else None
base['interior_glass_construction'] = \
self._interior_glass_construction.identifier if \
self._interior_glass_construction is not None else None
base['overhead_construction'] = self._overhead_construction.identifier \
if self._overhead_construction is not None else None
else:
base['exterior_construction'] = self._exterior_construction.to_dict() \
if self._exterior_construction is not None else None
base['interior_construction'] = self._interior_construction.to_dict() \
if self._interior_construction is not None else None
base['exterior_glass_construction'] = \
self._exterior_glass_construction.to_dict() \
if self._exterior_glass_construction is not None else None
base['interior_glass_construction'] = \
self._interior_glass_construction.to_dict() if \
self._interior_glass_construction is not None else None
base['overhead_construction'] = self._overhead_construction.to_dict() \
if self._overhead_construction is not None else None
else:
base['exterior_construction'] = self.exterior_construction.identifier if \
abridged else self.exterior_construction.to_dict()
base['interior_construction'] = self.interior_construction.identifier if \
abridged else self.interior_construction.to_dict()
base['exterior_glass_construction'] = \
self.exterior_glass_construction.identifier if \
abridged else self.exterior_glass_construction.to_dict()
base['interior_glass_construction'] = \
self.interior_glass_construction.identifier if \
abridged else self.interior_glass_construction.to_dict()
base['overhead_construction'] = self.overhead_construction.identifier if \
abridged else self.overhead_construction.to_dict()
return base
[docs]
def duplicate(self):
"""Get a copy of this set."""
return self.__copy__()
def _check_construction(self, value):
"""Check an OpaqueConstruction before assigning it."""
assert isinstance(value, OpaqueConstruction), \
'Expected OpaqueConstruction. Got {}'.format(type(value))
value.lock() # lock editing in case construction has multiple references
def _check_window_construction(self, value):
"""Check that a construction is valid before assigning it."""
val_w = (WindowConstruction, WindowConstructionShade, WindowConstructionDynamic)
assert isinstance(value, val_w), \
'Expected Window Construction. Got {}'.format(type(value))
value.lock() # lock editing in case construction has multiple references
[docs]
def ToString(self):
"""Overwrite .NET ToString."""
return self.__repr__()
def __len__(self):
return 5
def __iter__(self):
return iter(self.constructions)
def __copy__(self):
new_obj = self.__class__(
self._exterior_construction, self._interior_construction,
self._exterior_glass_construction, self._interior_glass_construction,
self._overhead_construction)
return(new_obj)
def __repr__(self):
return 'Door Construction Set: [Exterior: {}] [Interior: {}]' \
' [Exterior Glass: {}] [Interior Glass: {}] [Overhead: {}]'.format(
self.exterior_construction.display_name,
self.interior_construction.display_name,
self.exterior_glass_construction.display_name,
self.interior_glass_construction.display_name,
self.overhead_construction.display_name)