Skip to content

Commit

Permalink
Merge branch 'master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
chriswmackey committed Sep 17, 2021
2 parents 1d2137c + ffb9852 commit d808fc4
Show file tree
Hide file tree
Showing 60 changed files with 1,018 additions and 227 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Expand Up @@ -32,7 +32,7 @@ jobs:
rm -r honeybee-openstudio-gem-$HONEYBEE_OPENSTUDIO_GEM_VERSION
rm honeybee-openstudio-gem.tar.gz
env:
HONEYBEE_OPENSTUDIO_GEM_VERSION: "2.23.3"
HONEYBEE_OPENSTUDIO_GEM_VERSION: "2.23.4"
- name: install python dependencies
run: |
python -m pip install --upgrade pip
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -12,3 +12,4 @@ tox.ini
/.cache
/.vscode
honeybee.log*
.env
2 changes: 1 addition & 1 deletion build_image.sh
Expand Up @@ -19,7 +19,7 @@ mv OpenStudio-*-Ubuntu-*/ ${OPENSTUDIO_FILENAME}

# Get the gem

export HONEYBEE_OPENSTUDIO_GEM_VERSION="2.23.3"
export HONEYBEE_OPENSTUDIO_GEM_VERSION="2.23.4"
export HONEYBEE_OPENSTUDIO_GEM_URL="https://github.com/ladybug-tools/honeybee-openstudio-gem/archive/v${HONEYBEE_OPENSTUDIO_GEM_VERSION}.tar.gz"
export HONEYBEE_OPENSTUDIO_GEM_TAR='honeybee-openstudio-gem.tar.gz'
export HONEYBEE_GEM_FILENAME='honeybee-gem'
Expand Down
23 changes: 22 additions & 1 deletion honeybee_energy/construction/_base.py
Expand Up @@ -33,18 +33,20 @@ class _ConstructionBase(object):
* r_factor
* is_symmetric
* has_shade
* user_data
"""
# generic air material used to compute indoor film coefficients.
_air = EnergyWindowMaterialGas('generic air', gas_type='Air')

__slots__ = ('_identifier', '_display_name', '_materials', '_locked')
__slots__ = ('_identifier', '_display_name', '_materials', '_locked', '_user_data')

def __init__(self, identifier, materials):
"""Initialize energy construction."""
self._locked = False # unlocked by default
self.identifier = identifier
self._display_name = None
self.materials = materials
self._user_data = None

@property
def identifier(self):
Expand Down Expand Up @@ -154,6 +156,24 @@ def has_shade(self):
# This is False for all construction types except WindowConstructionShade.
return False

@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

def duplicate(self):
"""Get a copy of this construction."""
return self.__copy__()
Expand Down Expand Up @@ -283,6 +303,7 @@ def __copy__(self):
new_con = self.__class__(
self.identifier, [mat.duplicate() for mat in self.materials])
new_con._display_name = self._display_name
new_con._user_data = None if self._user_data is None else self._user_data.copy()
return new_con

def __len__(self):
Expand Down
28 changes: 27 additions & 1 deletion honeybee_energy/construction/air.py
Expand Up @@ -33,10 +33,11 @@ class AirBoundaryConstruction(object):
* display_name
* air_mixing_per_area
* air_mixing_schedule
* user_data
"""

__slots__ = ('_identifier', '_display_name', '_air_mixing_per_area',
'_air_mixing_schedule', '_locked')
'_air_mixing_schedule', '_locked', '_user_data')

def __init__(self, identifier, air_mixing_per_area=0.1,
air_mixing_schedule=always_on):
Expand All @@ -46,6 +47,7 @@ def __init__(self, identifier, air_mixing_per_area=0.1,
self._display_name = None
self.air_mixing_per_area = air_mixing_per_area
self.air_mixing_schedule = air_mixing_schedule
self._user_data = None

@property
def identifier(self):
Expand Down Expand Up @@ -102,6 +104,23 @@ def air_mixing_schedule(self, value):
else:
self._air_mixing_schedule = always_on

@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)
"""
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

@classmethod
def from_dict(cls, data):
"""Create a AirBoundaryConstruction from a dictionary.
Expand Down Expand Up @@ -129,6 +148,8 @@ def from_dict(cls, data):
new_obj = cls(data['identifier'], a_mix, a_sch)
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

@classmethod
Expand Down Expand Up @@ -159,6 +180,8 @@ def from_dict_abridged(cls, data, schedule_dict):
new_obj = cls(data['identifier'], a_mix, a_sch)
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

def to_idf(self):
Expand Down Expand Up @@ -198,6 +221,8 @@ def to_dict(self, abridged=False):
else self.air_mixing_schedule.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

def to_radiance_solar(self):
Expand Down Expand Up @@ -226,6 +251,7 @@ def __copy__(self):
new_con = AirBoundaryConstruction(
self.identifier, self._air_mixing_per_area, self._air_mixing_schedule)
new_con._display_name = self._display_name
new_con.user_data = None if self._user_data is None else self._user_data.copy()
return new_con

def __key(self):
Expand Down
29 changes: 28 additions & 1 deletion honeybee_energy/construction/dynamic.py
Expand Up @@ -45,10 +45,11 @@ class WindowConstructionDynamic(object):
* thickness
* glazing_count
* gap_count
* user_data
"""

__slots__ = ('_identifier', '_display_name', '_constructions', '_schedule',
'_locked')
'_locked', '_user_data')

def __init__(self, identifier, constructions, schedule):
"""Initialize dynamic window construction."""
Expand All @@ -57,6 +58,7 @@ def __init__(self, identifier, constructions, schedule):
self._display_name = None
self.constructions = constructions
self.schedule = schedule
self._user_data = None

@property
def identifier(self):
Expand Down Expand Up @@ -261,6 +263,24 @@ def gap_count(self):
"""The number of gas gaps contained within the first construction."""
return self._constructions[0].gap_count

@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

@classmethod
def from_dict(cls, data):
"""Create a WindowConstructionDynamic from a dictionary.
Expand Down Expand Up @@ -292,6 +312,8 @@ def from_dict(cls, data):
new_obj = cls(data['identifier'], constrs, schedule)
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

@classmethod
Expand Down Expand Up @@ -326,6 +348,8 @@ def from_dict_abridged(cls, data, materials, schedules):
new_obj = cls(data['identifier'], constrs, schedule)
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

def to_idf(self):
Expand Down Expand Up @@ -363,6 +387,8 @@ def to_dict(self, abridged=False):
else self.schedule.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

def lock(self):
Expand All @@ -385,6 +411,7 @@ def __copy__(self):
new_con = WindowConstructionDynamic(
self.identifier, self.constructions, self.schedule)
new_con._display_name = self._display_name
new_con.user_data = None if self._user_data is None else self._user_data.copy()
return new_con

def __len__(self):
Expand Down
7 changes: 7 additions & 0 deletions honeybee_energy/construction/opaque.py
Expand Up @@ -44,6 +44,7 @@ class OpaqueConstruction(_ConstructionBase):
* outside_visible_reflectance
* mass_area_density
* area_heat_capacity
* user_data
"""
__slots__ = ()

Expand Down Expand Up @@ -200,6 +201,8 @@ def from_dict(cls, data):
new_obj = cls(data['identifier'], mat_layers)
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

@classmethod
Expand Down Expand Up @@ -231,6 +234,8 @@ def from_dict_abridged(cls, data, materials):
new_obj = cls(data['identifier'], mat_layers)
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

def to_idf(self):
Expand Down Expand Up @@ -276,6 +281,8 @@ def to_dict(self, abridged=False):
[m.to_dict() for m in self.materials]
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

@staticmethod
Expand Down
27 changes: 26 additions & 1 deletion honeybee_energy/construction/shade.py
Expand Up @@ -34,10 +34,11 @@ class ShadeConstruction(object):
* visible_reflectance
* is_specular
* is_default
* user_data
"""

__slots__ = ('_identifier', '_display_name', '_solar_reflectance',
'_visible_reflectance', '_is_specular', '_locked')
'_visible_reflectance', '_is_specular', '_locked', '_user_data')

def __init__(self, identifier, solar_reflectance=0.2, visible_reflectance=0.2,
is_specular=False):
Expand All @@ -48,6 +49,7 @@ def __init__(self, identifier, solar_reflectance=0.2, visible_reflectance=0.2,
self.solar_reflectance = solar_reflectance
self.visible_reflectance = visible_reflectance
self.is_specular = is_specular
self._user_data = None

@property
def identifier(self):
Expand Down Expand Up @@ -113,6 +115,24 @@ def is_default(self):
"""Boolean to note whether all properties follow the EnergyPlus default."""
return self._solar_reflectance == 0.2 and \
self._visible_reflectance == 0.2 and not self._is_specular

@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

def glazing_construction(self):
"""Get a WindowConstruction that EnergyPlus uses for specular reflection.
Expand Down Expand Up @@ -153,6 +173,8 @@ def from_dict(cls, data):
new_obj = cls(data['identifier'], s_ref, v_ref, spec)
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

def to_idf(self, host_shade_identifier):
Expand Down Expand Up @@ -195,6 +217,8 @@ def to_dict(self):
base['is_specular'] = self.is_specular
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

def duplicate(self):
Expand All @@ -220,6 +244,7 @@ def __copy__(self):
self.identifier, self._solar_reflectance, self._visible_reflectance,
self._is_specular)
new_con._display_name = self._display_name
new_con._user_data = None if self._user_data is None else self._user_data.copy()
return new_con

def __key(self):
Expand Down
6 changes: 6 additions & 0 deletions honeybee_energy/construction/window.py
Expand Up @@ -56,6 +56,7 @@ class WindowConstruction(_ConstructionBase):
* glazing_count
* gap_count
* glazing_materials
* user_data
"""
__slots__ = ()

Expand Down Expand Up @@ -463,6 +464,8 @@ def from_dict(cls, data):
new_obj = cls(data['identifier'], mat_layers)
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

@classmethod
Expand Down Expand Up @@ -493,6 +496,8 @@ def from_dict_abridged(cls, data, materials):
new_obj = cls(data['identifier'], mat_layers)
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

def to_idf(self):
Expand Down Expand Up @@ -564,6 +569,7 @@ def to_dict(self, abridged=False):
[m.to_dict() for m in self.materials]
if self._display_name is not None:
base['display_name'] = self.display_name

return base

def to_simple_construction(self):
Expand Down

0 comments on commit d808fc4

Please sign in to comment.