Skip to content

Commit

Permalink
fix(model): Add method to reset and number all object identifiers
Browse files Browse the repository at this point in the history
  • Loading branch information
chriswmackey committed Jan 30, 2024
1 parent 83a5629 commit acb5997
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 14 deletions.
32 changes: 28 additions & 4 deletions honeybee/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -1288,14 +1288,38 @@ def add_prefix(self, prefix):
for shade_mesh in self._shade_meshes:
shade_mesh.add_prefix(prefix)

def reset_room_ids(self):
"""Reset the identifiers of the Model Rooms to be derived from display_names.
def reset_ids(self, tru):
"""Reset the identifiers of all Model objects to be derived from display_names.
In the event that duplicate Room identifiers are found in the Model, an
integer will be automatically appended to the new Room ID to make it
In the event that duplicate identifiers are found, an
integer will be automatically appended to the new ID to make it
unique. This is similar to the routines that automatically assign unique
names to OpenStudio SDK objects.
"""
self.reset_room_ids()
face_dict, ap_dict, dr_dict, shd_dict, sm_dict = {}, {}, {}, {}, {}
for face in self.faces:
face.identifier = clean_and_number_string(
face.display_name, face_dict, 'Face identifier')
for ap in self.apertures:
ap.identifier = clean_and_number_string(
ap.display_name, ap_dict, 'Aperture identifier')
for dr in self.doors:
dr.identifier = clean_and_number_string(
dr.display_name, dr_dict, 'Door identifier')
for shade in self.shades:
shade.identifier = clean_and_number_string(
shade.display_name, shd_dict, 'Shade identifier')
for shade_mesh in self.shade_meshes:
shade_mesh.identifier = clean_and_number_string(
shade_mesh.display_name, sm_dict, 'ShadeMesh identifier')

def reset_room_ids(self):
"""Reset the identifiers of the Model Rooms to be derived from display_names.
In the event that duplicate Room identifiers are found, an integer will
be automatically appended to the new Room ID to make it unique.
"""
room_dict = {}
for room in self.rooms:
room.identifier = clean_and_number_string(
Expand Down
7 changes: 7 additions & 0 deletions honeybee/typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ def clean_string(value, input_name=''):
string is empty after stripping or has more than 100 characters.
"""
try:
value = value.replace(' ', '_') # spaces > underscores for readability
val = re.sub(r'[^.A-Za-z0-9_-]', '', value)
except TypeError:
raise TypeError('Input {} must be a text string. Got {}: {}.'.format(
Expand All @@ -191,6 +192,7 @@ def clean_rad_string(value, input_name=''):
raising an error if no legal characters are found.
"""
try:
value = value.replace(' ', '_') # spaces > underscores for readability
val = re.sub(r'[^.A-Za-z0-9_-]', '', value)
except TypeError:
raise TypeError('Input {} must be a text string. Got {}: {}.'.format(
Expand Down Expand Up @@ -228,6 +230,7 @@ def clean_and_id_string(value, input_name=''):
The resulting string will be valid for both Radiance and EnergyPlus.
"""
try:
value = value.replace(' ', '_') # spaces > underscores for readability
val = re.sub(r'[^.A-Za-z0-9_-]', '', value)
except TypeError:
raise TypeError('Input {} must be a text string. Got {}: {}.'.format(
Expand All @@ -243,6 +246,7 @@ def clean_and_id_rad_string(value, input_name=''):
This includes stripping out illegal characters and white spaces.
"""
try:
value = value.replace(' ', '_') # spaces > underscores for readability
val = re.sub(r'[^.A-Za-z0-9_-]', '', value)
except TypeError:
raise TypeError('Input {} must be a text string. Got {}: {}.'.format(
Expand Down Expand Up @@ -280,6 +284,7 @@ def clean_and_number_string(value, existing_dict, input_name=''):
the model already.
"""
try:
value = value.replace(' ', '_') # spaces > underscores for readability
val = re.sub(r'[^.A-Za-z0-9_-]', '_', value)
except TypeError:
raise TypeError('Input {} must be a text string. Got {}: {}.'.format(
Expand All @@ -306,6 +311,7 @@ def clean_and_number_rad_string(value, existing_dict, input_name=''):
the model already.
"""
try:
value = value.replace(' ', '_') # spaces > underscores for readability
val = re.sub(r'[^.A-Za-z0-9_-]', '_', value)
except TypeError:
raise TypeError('Input {} must be a text string. Got {}: {}.'.format(
Expand Down Expand Up @@ -357,6 +363,7 @@ def truncate_and_id_string(value, truncate_len=32, uuid_len=0, input_name=''):
with different types of character restrictions.
"""
try:
value = value.replace(' ', '_') # spaces > underscores for readability
val = re.sub(r'[^.A-Za-z0-9_-]', '', value)
except TypeError:
raise TypeError('Input {} must be a text string. Got {}: {}.'.format(
Expand Down
20 changes: 10 additions & 10 deletions tests/typing_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ def test_clean_string():
long_str = 'This is an exceptionally long text string that should never be used ' \
'for the name of anything in EnergyPlus for whatever reason'

assert clean_string(correct_str) == '0.5in.GypsumWall'
assert clean_string(incorrect_str) == '0.5in.GypsumWall'
assert clean_string(correct_str) == '0.5_in._GypsumWall'
assert clean_string(incorrect_str) == '0.5_in._GypsumWall'
with pytest.raises(AssertionError):
clean_string(long_str)

Expand All @@ -29,8 +29,8 @@ def test_clean_rad_string():
long_str = 'This is an exceptionally long text string that should never be used ' \
'for the name of anything in EnergyPlus but is actually ok for Radiance'

assert clean_rad_string(correct_str) == '0.5in.GypsumWall'
assert clean_rad_string(incorrect_str) == '0.5in.GypsumWall'
assert clean_rad_string(correct_str) == '0.5_in._GypsumWall'
assert clean_rad_string(incorrect_str) == '0.5_in._GypsumWall'
clean_rad_string(long_str)


Expand All @@ -54,8 +54,8 @@ def test_clean_and_id_string():
long_str = 'This is an exceptionally long text string that should never be used ' \
'for the name of anything in EnergyPlus for whatever reason'

assert clean_and_id_string(correct_str).startswith('0.5in.GypsumWall')
assert clean_and_id_string(incorrect_str).startswith('0.5in.GypsumWall')
assert clean_and_id_string(correct_str).startswith('0.5_in._GypsumWall')
assert clean_and_id_string(incorrect_str).startswith('0.5_in._GypsumWall')
assert len(clean_and_id_string(long_str)) < 70


Expand All @@ -66,8 +66,8 @@ def test_clean_and_id_rad_string():
long_str = 'This is an exceptionally long text string that should never be used ' \
'for the name of anything in EnergyPlus but is actually ok for Radiance'

assert clean_and_id_rad_string(correct_str).startswith('0.5in.GypsumWall')
assert clean_and_id_rad_string(incorrect_str).startswith('0.5in.GypsumWall')
assert clean_and_id_rad_string(correct_str).startswith('0.5_in._GypsumWall')
assert clean_and_id_rad_string(incorrect_str).startswith('0.5_in._GypsumWall')
assert len(clean_and_id_rad_string(long_str)) > 70


Expand Down Expand Up @@ -247,9 +247,9 @@ def test_truncate_and_id_string():
"""Test the truncate_and_id_string method."""
test_str = 'This is a test string to be truncated and IDd'
trunc_str = truncate_and_id_string(test_str, 32)
assert trunc_str == 'Thisisateststringtobetruncatedan'
assert trunc_str == 'This_is_a_test_string_to_be_trun'
trunc_str = truncate_and_id_string(test_str, 32, 8)
assert trunc_str[:24] == 'Thisisateststringtobetru'
assert trunc_str[:24] == 'This_is_a_test_string_to'


def test_invalid_dict_error():
Expand Down

0 comments on commit acb5997

Please sign in to comment.