From 535a0b6c07a4c53178e3b3937a363ada56ed2988 Mon Sep 17 00:00:00 2001 From: Ben Park Date: Fri, 16 Apr 2021 00:43:25 -0600 Subject: [PATCH 01/11] first pass --- hpxml_version_translator/converter.py | 49 ++++++++++++++++++++++++++- test/hpxml_files/enclosure_attics.xml | 39 +++++++++++++++++++++ test/test_converter.py | 13 +++++++ 3 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 test/hpxml_files/enclosure_attics.xml diff --git a/hpxml_version_translator/converter.py b/hpxml_version_translator/converter.py index d9ab9dc..2e43aee 100644 --- a/hpxml_version_translator/converter.py +++ b/hpxml_version_translator/converter.py @@ -259,9 +259,56 @@ def get_event_type_from_building_id(building_id): # TODO: Deprecated items # https://github.com/hpxmlwg/hpxml/pull/167 - # TODO: Enclosure + # Enclosure # https://github.com/hpxmlwg/hpxml/pull/181 + # Attics + for i, attic in enumerate(root.xpath( + 'h:Building/h:BuildingDetails/h:Enclosure/h:AtticAndRoof/h:Attics/h:Attic', **xpkw + ), 1): + enclosure = attic.getparent().getparent().getparent() + if not hasattr(enclosure, 'Attics'): + add_after( + enclosure, + ['AirInfiltration'], + E.Attics() + ) + enclosure.Attics.append(deepcopy(attic)) + this_attic = enclosure.Attics.Attic[i] + + el_not_in_v3 = [ + 'AttachedToRoof', + 'ExteriorAdjacentTo', + 'InteriorAdjacentTo', + 'AtticKneeWall', + 'AtticFloorInsulation', + 'AtticRoofInsulation', + 'Area', + 'Rafters' + ] + for el in el_not_in_v3: + if hasattr(this_attic, el): + this_attic.remove(this_attic[el]) + + if hasattr(this_attic, 'AtticType'): + if this_attic.AtticType == 'vented attic': + this_attic.AtticType = E.AtticType(E.Attic(E.Vented(True))) + elif this_attic.AtticType == 'unvented attic': + this_attic.AtticType = E.AtticType(E.Attic(E.Vented(False))) + elif this_attic.AtticType == 'flat roof': + this_attic.AtticType = E.AtticType(E.FlatRoof()) + elif this_attic.AtticType == 'cathedral ceiling': + this_attic.AtticType = E.AtticType(E.CathedralCeiling()) + elif this_attic.AtticType == 'cape cod': + this_attic.AtticType = E.AtticType(E.Attic(E.CapeCod(True))) + elif this_attic.AtticType in ['other', 'venting unknown attic']: + this_attic.AtticType = E.AtticType(E.Attic(E.Other())) + + if i == len(root.xpath( + 'h:Building/h:BuildingDetails/h:Enclosure/h:AtticAndRoof/h:Attics/h:Attic', **xpkw + )): # remove AtticAndRoof after rearranging all attics + enclosure.remove(enclosure.AtticAndRoof) + # TODO: Adds desuperheater flexibility # https://github.com/hpxmlwg/hpxml/pull/184 diff --git a/test/hpxml_files/enclosure_attics.xml b/test/hpxml_files/enclosure_attics.xml new file mode 100644 index 0000000..e12f274 --- /dev/null +++ b/test/hpxml_files/enclosure_attics.xml @@ -0,0 +1,39 @@ + + + + + + 2021-04-05T14:17:07.685077 + create + + + + + + audit + + + + + + + + ambient + attic + unvented attic + 1000 + + 2x4 + wood + + + + + vented attic + + + + + + + diff --git a/test/test_converter.py b/test/test_converter.py index e879c5e..5f8dc39 100644 --- a/test/test_converter.py +++ b/test/test_converter.py @@ -86,3 +86,16 @@ def test_clothes_dryer(): assert dryer2.EnergyFactor == 5.0 assert dryer2.ControlType == 'temperature' assert not hasattr(dryer2, 'EfficiencyFactor') + + +def test_enclosure_attics(): + root = convert_hpxml_and_parse(hpxml_dir / 'enclosure_attics.xml') + + attic1 = root.Building.BuildingDetails.Enclosure.Attics.Attic[0] + enclosure = attic1.getparent().getparent() + assert not attic1.AtticType.Attic.Vented # unvented attic + assert not hasattr(enclosure, 'AtticAndRoof') + assert not hasattr(enclosure, 'ExteriorAdjacentTo') + + attic2 = root.Building.BuildingDetails.Enclosure.Attics.Attic[1] + assert attic2.AtticType.Attic.Vented # vented attic From e8be3646321613cfb57f730360d9d91eda635a23 Mon Sep 17 00:00:00 2001 From: Ben Park Date: Fri, 16 Apr 2021 00:50:42 -0600 Subject: [PATCH 02/11] change index --- hpxml_version_translator/converter.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hpxml_version_translator/converter.py b/hpxml_version_translator/converter.py index 2e43aee..d6ba64a 100644 --- a/hpxml_version_translator/converter.py +++ b/hpxml_version_translator/converter.py @@ -265,7 +265,7 @@ def get_event_type_from_building_id(building_id): # Attics for i, attic in enumerate(root.xpath( 'h:Building/h:BuildingDetails/h:Enclosure/h:AtticAndRoof/h:Attics/h:Attic', **xpkw - ), 1): + )): enclosure = attic.getparent().getparent().getparent() if not hasattr(enclosure, 'Attics'): add_after( @@ -304,7 +304,7 @@ def get_event_type_from_building_id(building_id): elif this_attic.AtticType in ['other', 'venting unknown attic']: this_attic.AtticType = E.AtticType(E.Attic(E.Other())) - if i == len(root.xpath( + if (i + 1) == len(root.xpath( 'h:Building/h:BuildingDetails/h:Enclosure/h:AtticAndRoof/h:Attics/h:Attic', **xpkw )): # remove AtticAndRoof after rearranging all attics enclosure.remove(enclosure.AtticAndRoof) From f68588b6c99e51cc7401753c1b2f8fcb66695a42 Mon Sep 17 00:00:00 2001 From: Ben Park Date: Mon, 19 Apr 2021 22:50:39 -0600 Subject: [PATCH 03/11] move the Roof to the Enclosure level --- hpxml_version_translator/converter.py | 47 +++++++++++++++++-- ...ics.xml => enclosure_attics_and_roofs.xml} | 11 +++++ test/test_converter.py | 17 ++++++- 3 files changed, 70 insertions(+), 5 deletions(-) rename test/hpxml_files/{enclosure_attics.xml => enclosure_attics_and_roofs.xml} (74%) diff --git a/hpxml_version_translator/converter.py b/hpxml_version_translator/converter.py index d6ba64a..c565d83 100644 --- a/hpxml_version_translator/converter.py +++ b/hpxml_version_translator/converter.py @@ -304,10 +304,49 @@ def get_event_type_from_building_id(building_id): elif this_attic.AtticType in ['other', 'venting unknown attic']: this_attic.AtticType = E.AtticType(E.Attic(E.Other())) - if (i + 1) == len(root.xpath( - 'h:Building/h:BuildingDetails/h:Enclosure/h:AtticAndRoof/h:Attics/h:Attic', **xpkw - )): # remove AtticAndRoof after rearranging all attics - enclosure.remove(enclosure.AtticAndRoof) + # Roofs + for i, roof in enumerate(root.xpath( + 'h:Building/h:BuildingDetails/h:Enclosure/h:AtticAndRoof/h:Roofs/h:Roof', **xpkw + )): + enclosure = roof.getparent().getparent().getparent() + if not hasattr(enclosure, 'Roofs'): + add_after( + enclosure, + ['AirInfiltration', + 'Attics', + 'Foundations', + 'Garages'], + E.Roofs() + ) + enclosure.Roofs.append(deepcopy(roof)) + + if hasattr(roof, 'RoofArea'): + add_after( + enclosure.Roofs.Roof, + ['SystemIdentifier', + 'ExternalResource', + 'AttachedToSpace', + 'InteriorAdjacentTo'], + E.Area(float(roof.RoofArea)) + ) + enclosure.Roofs.Roof.remove(enclosure.Roofs.Roof.RoofArea) + + if hasattr(roof, 'RoofType'): + add_after( + enclosure.Roofs.Roof, + ['SystemIdentifier', + 'ExternalResource', + 'AttachedToSpace', + 'InteriorAdjacentTo', + 'Area', + 'Orientation', + 'Azimuth'], + E.RoofType(str(roof.RoofType)) + ) + enclosure.Roofs.Roof.remove(enclosure.Roofs.Roof.RoofType[1]) # remove the RoofType of HPXML v2 + + # remove AtticAndRoof after rearranging all attics and roofs + enclosure.remove(enclosure.AtticAndRoof) # TODO: Adds desuperheater flexibility # https://github.com/hpxmlwg/hpxml/pull/184 diff --git a/test/hpxml_files/enclosure_attics.xml b/test/hpxml_files/enclosure_attics_and_roofs.xml similarity index 74% rename from test/hpxml_files/enclosure_attics.xml rename to test/hpxml_files/enclosure_attics_and_roofs.xml index e12f274..0aafeba 100644 --- a/test/hpxml_files/enclosure_attics.xml +++ b/test/hpxml_files/enclosure_attics_and_roofs.xml @@ -15,6 +15,17 @@ + + + + dark + 0.7 + 0.9 + shingles + 6.0 + 1118.5 + + diff --git a/test/test_converter.py b/test/test_converter.py index 5f8dc39..bc43dde 100644 --- a/test/test_converter.py +++ b/test/test_converter.py @@ -89,7 +89,7 @@ def test_clothes_dryer(): def test_enclosure_attics(): - root = convert_hpxml_and_parse(hpxml_dir / 'enclosure_attics.xml') + root = convert_hpxml_and_parse(hpxml_dir / 'enclosure_attics_and_roofs.xml') attic1 = root.Building.BuildingDetails.Enclosure.Attics.Attic[0] enclosure = attic1.getparent().getparent() @@ -99,3 +99,18 @@ def test_enclosure_attics(): attic2 = root.Building.BuildingDetails.Enclosure.Attics.Attic[1] assert attic2.AtticType.Attic.Vented # vented attic + + +def test_enclosure_roofs(): + root = convert_hpxml_and_parse(hpxml_dir / 'enclosure_attics_and_roofs.xml') + + roof1 = root.Building.BuildingDetails.Enclosure.Roofs.Roof[0] + enclosure = roof1.getparent().getparent() + assert roof1.Area == 1118.5 + assert roof1.RoofType == 'shingles' + assert roof1.RoofColor == 'dark' + assert roof1.SolarAbsorptance == 0.7 + assert roof1.Emittance == 0.9 + assert roof1.Pitch == 6.0 + assert not hasattr(roof1, 'RoofArea') + assert not hasattr(enclosure, 'AtticAndRoof') From 126d4e3f92b3df3019ce4dd0753d41614af260cf Mon Sep 17 00:00:00 2001 From: Ben Park Date: Mon, 19 Apr 2021 22:58:51 -0600 Subject: [PATCH 04/11] bugfix --- hpxml_version_translator/converter.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/hpxml_version_translator/converter.py b/hpxml_version_translator/converter.py index c565d83..04ee817 100644 --- a/hpxml_version_translator/converter.py +++ b/hpxml_version_translator/converter.py @@ -346,7 +346,10 @@ def get_event_type_from_building_id(building_id): enclosure.Roofs.Roof.remove(enclosure.Roofs.Roof.RoofType[1]) # remove the RoofType of HPXML v2 # remove AtticAndRoof after rearranging all attics and roofs - enclosure.remove(enclosure.AtticAndRoof) + try: + root.Building.BuildingDetails.Enclosure.remove(root.Building.BuildingDetails.Enclosure.AtticAndRoof) + except AttributeError: + pass # TODO: Adds desuperheater flexibility # https://github.com/hpxmlwg/hpxml/pull/184 From 597a1d5c2365d9cf39087f3ac63772a3a5df45fd Mon Sep 17 00:00:00 2001 From: bpark1327 <59635239+bpark1327@users.noreply.github.com> Date: Tue, 20 Apr 2021 23:58:41 -0600 Subject: [PATCH 05/11] Update hpxml_version_translator/converter.py Co-authored-by: Noel Merket --- hpxml_version_translator/converter.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hpxml_version_translator/converter.py b/hpxml_version_translator/converter.py index 04ee817..2f9ea8d 100644 --- a/hpxml_version_translator/converter.py +++ b/hpxml_version_translator/converter.py @@ -273,8 +273,8 @@ def get_event_type_from_building_id(building_id): ['AirInfiltration'], E.Attics() ) - enclosure.Attics.append(deepcopy(attic)) - this_attic = enclosure.Attics.Attic[i] + this_attic = deepcopy(attic) + enclosure.Attics.append(this_attic) el_not_in_v3 = [ 'AttachedToRoof', From 0ece23b6e567ae421bb52fb6f6bbcc2fca519c2b Mon Sep 17 00:00:00 2001 From: Ben Park Date: Wed, 21 Apr 2021 22:56:22 -0600 Subject: [PATCH 06/11] retain --- hpxml_version_translator/converter.py | 11 +++++++---- test/hpxml_files/enclosure_attics_and_roofs.xml | 2 +- test/test_converter.py | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/hpxml_version_translator/converter.py b/hpxml_version_translator/converter.py index 04ee817..c7e2988 100644 --- a/hpxml_version_translator/converter.py +++ b/hpxml_version_translator/converter.py @@ -273,8 +273,7 @@ def get_event_type_from_building_id(building_id): ['AirInfiltration'], E.Attics() ) - enclosure.Attics.append(deepcopy(attic)) - this_attic = enclosure.Attics.Attic[i] + this_attic = deepcopy(attic) el_not_in_v3 = [ 'AttachedToRoof', @@ -301,8 +300,12 @@ def get_event_type_from_building_id(building_id): this_attic.AtticType = E.AtticType(E.CathedralCeiling()) elif this_attic.AtticType == 'cape cod': this_attic.AtticType = E.AtticType(E.Attic(E.CapeCod(True))) - elif this_attic.AtticType in ['other', 'venting unknown attic']: - this_attic.AtticType = E.AtticType(E.Attic(E.Other())) + elif this_attic.AtticType == 'other': + this_attic.AtticType = E.AtticType(E.Other()) + elif this_attic.AtticType == 'venting unknown attic': + this_attic.AtticType = E.AtticType(E.Other(E.extension(E.Attic(E.Vented('unknown'))))) + + enclosure.Attics.append(this_attic) # Roofs for i, roof in enumerate(root.xpath( diff --git a/test/hpxml_files/enclosure_attics_and_roofs.xml b/test/hpxml_files/enclosure_attics_and_roofs.xml index 0aafeba..2a66653 100644 --- a/test/hpxml_files/enclosure_attics_and_roofs.xml +++ b/test/hpxml_files/enclosure_attics_and_roofs.xml @@ -40,7 +40,7 @@ - vented attic + venting unknown attic diff --git a/test/test_converter.py b/test/test_converter.py index bc43dde..2c2f5a4 100644 --- a/test/test_converter.py +++ b/test/test_converter.py @@ -98,7 +98,7 @@ def test_enclosure_attics(): assert not hasattr(enclosure, 'ExteriorAdjacentTo') attic2 = root.Building.BuildingDetails.Enclosure.Attics.Attic[1] - assert attic2.AtticType.Attic.Vented # vented attic + assert attic2.AtticType.Other.extension.Attic.Vented == 'unknown' # venting unknown attic def test_enclosure_roofs(): From b7cfcfb3c964235c6afc90c7ef299a04b8ebc403 Mon Sep 17 00:00:00 2001 From: Ben Park Date: Thu, 22 Apr 2021 09:49:51 -0600 Subject: [PATCH 07/11] change venting unknown attic translation --- hpxml_version_translator/converter.py | 30 +++++++++++++-------------- test/test_converter.py | 2 +- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/hpxml_version_translator/converter.py b/hpxml_version_translator/converter.py index c7e2988..a7803c1 100644 --- a/hpxml_version_translator/converter.py +++ b/hpxml_version_translator/converter.py @@ -275,20 +275,6 @@ def get_event_type_from_building_id(building_id): ) this_attic = deepcopy(attic) - el_not_in_v3 = [ - 'AttachedToRoof', - 'ExteriorAdjacentTo', - 'InteriorAdjacentTo', - 'AtticKneeWall', - 'AtticFloorInsulation', - 'AtticRoofInsulation', - 'Area', - 'Rafters' - ] - for el in el_not_in_v3: - if hasattr(this_attic, el): - this_attic.remove(this_attic[el]) - if hasattr(this_attic, 'AtticType'): if this_attic.AtticType == 'vented attic': this_attic.AtticType = E.AtticType(E.Attic(E.Vented(True))) @@ -303,7 +289,21 @@ def get_event_type_from_building_id(building_id): elif this_attic.AtticType == 'other': this_attic.AtticType = E.AtticType(E.Other()) elif this_attic.AtticType == 'venting unknown attic': - this_attic.AtticType = E.AtticType(E.Other(E.extension(E.Attic(E.Vented('unknown'))))) + this_attic.AtticType = E.AtticType(E.Attic(E.extension(E.Vented('unknown')))) + + el_not_in_v3 = [ + 'AttachedToRoof', + 'ExteriorAdjacentTo', + 'InteriorAdjacentTo', + 'AtticKneeWall', + 'AtticFloorInsulation', + 'AtticRoofInsulation', + 'Area', + 'Rafters' + ] + for el in el_not_in_v3: + if hasattr(this_attic, el): + this_attic.remove(this_attic[el]) enclosure.Attics.append(this_attic) diff --git a/test/test_converter.py b/test/test_converter.py index 2c2f5a4..ab48123 100644 --- a/test/test_converter.py +++ b/test/test_converter.py @@ -98,7 +98,7 @@ def test_enclosure_attics(): assert not hasattr(enclosure, 'ExteriorAdjacentTo') attic2 = root.Building.BuildingDetails.Enclosure.Attics.Attic[1] - assert attic2.AtticType.Other.extension.Attic.Vented == 'unknown' # venting unknown attic + assert attic2.AtticType.Attic.extension.Vented == 'unknown' # venting unknown attic def test_enclosure_roofs(): From 44e1c71c71012797aec11262775c43d16bf8199f Mon Sep 17 00:00:00 2001 From: Ben Park Date: Thu, 22 Apr 2021 16:06:15 -0600 Subject: [PATCH 08/11] preserve Attic/AtticKneeWall, Attic/AtticFloorInsulation, Attic/AtticRoofInsulation, Attic/Area, Attic/Rafters --- hpxml_version_translator/converter.py | 63 +++++++++++++++++++ .../enclosure_attics_and_roofs.xml | 21 +++++++ test/test_converter.py | 11 ++++ 3 files changed, 95 insertions(+) diff --git a/hpxml_version_translator/converter.py b/hpxml_version_translator/converter.py index a7803c1..579f800 100644 --- a/hpxml_version_translator/converter.py +++ b/hpxml_version_translator/converter.py @@ -291,6 +291,69 @@ def get_event_type_from_building_id(building_id): elif this_attic.AtticType == 'venting unknown attic': this_attic.AtticType = E.AtticType(E.Attic(E.extension(E.Vented('unknown')))) + # find the wall with the same id and add AtticWallType = knee wall + if hasattr(this_attic, 'AtticKneeWall'): + knee_wall_id = this_attic.AtticKneeWall.attrib['idref'] + knee_wall = root.xpath( + 'h:Building/h:BuildingDetails/h:Enclosure/h:Walls/h:Wall[h:SystemIdentifier/@id=$sysid]', + sysid=knee_wall_id, **xpkw)[0] + if hasattr(knee_wall, 'AtticWallType'): + knee_wall.AtticWallType._setText('knee wall') + else: + add_after( + knee_wall, + ['SystemIdentifier', + 'ExteriorAdjacentTo', + 'InteriorAdjacentTo'], + E.AtticWallType('knee wall') + ) + # create a FrameFloor adjacent to the attic and assign the area below to Area + # and then copy AtticFloorInsulation over to Insulation of the frame floor + if hasattr(this_attic, 'AtticFloorInsulation'): + attic_floor_insulation = deepcopy(this_attic.AtticFloorInsulation) + attic_floor_insulation.tag = f'{{{hpxml3_ns}}}Insulation' + enclosure.append( + E.FrameFloors( + E.FrameFloor( + E.SystemIdentifier(id='attic_floor'), + E.InteriorAdjacentTo('attic'), + ) + ) + ) + if hasattr(this_attic, 'Area'): + enclosure.FrameFloors.FrameFloor.append(E.Area(this_attic.Area)) + enclosure.FrameFloors.FrameFloor.append(attic_floor_insulation) + # find the roof whose InteriorAdjacentTo is attic and then copy it to Insulation of the roof + # FIXME: add insulation to v2 Roofs and these roofs will be converted into hpxml v3 later + if hasattr(this_attic, 'AtticRoofInsulation'): + roof_insulation = deepcopy(this_attic.AtticRoofInsulation) + roof_insulation.tag = f'{{{hpxml3_ns}}}Insulation' + for i, rf in enumerate(root.xpath( + 'h:Building/h:BuildingDetails/h:Enclosure/h:AtticAndRoof/h:Roofs/h:Roof', **xpkw + )): + add_after( + rf, + ['Pitch', + 'RoofArea', + 'RadiantBarrier', + 'RadiantBarrierLocation'], + roof_insulation + ) + # move Rafters to Roof + # FIXME: move Rafters to v2 Roofs and these roofs will be converted into hpxml v3 later + if hasattr(this_attic, 'Rafters'): + rafters = deepcopy(this_attic.Rafters) + for i, rf in enumerate(root.xpath( + 'h:Building/h:BuildingDetails/h:Enclosure/h:AtticAndRoof/h:Roofs/h:Roof', **xpkw + )): + add_after( + rf, + ['RoofColor', + 'SolarAbsorptance', + 'Emittance'], + rafters + ) + el_not_in_v3 = [ 'AttachedToRoof', 'ExteriorAdjacentTo', diff --git a/test/hpxml_files/enclosure_attics_and_roofs.xml b/test/hpxml_files/enclosure_attics_and_roofs.xml index 2a66653..03da6a0 100644 --- a/test/hpxml_files/enclosure_attics_and_roofs.xml +++ b/test/hpxml_files/enclosure_attics_and_roofs.xml @@ -31,6 +31,7 @@ ambient attic + unvented attic 1000 @@ -41,9 +42,29 @@ venting unknown attic + + + 1 + poor + 5.5 + + + + 3 + good + + cavity + 7.5 + + + + + + + diff --git a/test/test_converter.py b/test/test_converter.py index ab48123..e6e9c42 100644 --- a/test/test_converter.py +++ b/test/test_converter.py @@ -96,6 +96,17 @@ def test_enclosure_attics(): assert not attic1.AtticType.Attic.Vented # unvented attic assert not hasattr(enclosure, 'AtticAndRoof') assert not hasattr(enclosure, 'ExteriorAdjacentTo') + assert enclosure.Walls.Wall[0].AtticWallType == 'knee wall' + assert enclosure.Roofs.Roof[0].Rafters.Size == '2x4' + assert enclosure.Roofs.Roof[0].Rafters.Material == 'wood' + assert enclosure.Roofs.Roof[0].Insulation.InsulationGrade == 3 + assert enclosure.Roofs.Roof[0].Insulation.InsulationCondition == 'good' + assert enclosure.Roofs.Roof[0].Insulation.Layer.InstallationType == 'cavity' + assert enclosure.Roofs.Roof[0].Insulation.Layer.NominalRValue == 7.5 + assert enclosure.FrameFloors.FrameFloor[0].InteriorAdjacentTo == 'attic' + assert enclosure.FrameFloors.FrameFloor[0].Insulation.InsulationGrade == 1 + assert enclosure.FrameFloors.FrameFloor[0].Insulation.InsulationCondition == 'poor' + assert enclosure.FrameFloors.FrameFloor[0].Insulation.AssemblyEffectiveRValue == 5.5 attic2 = root.Building.BuildingDetails.Enclosure.Attics.Attic[1] assert attic2.AtticType.Attic.extension.Vented == 'unknown' # venting unknown attic From 3fe006bb5f1b254a41242450d80514b86a900085 Mon Sep 17 00:00:00 2001 From: bpark1327 Date: Thu, 22 Apr 2021 22:49:56 -0600 Subject: [PATCH 09/11] move AttachedToRoof to after VentilationRate --- hpxml_version_translator/converter.py | 13 ++++++++++++- test/hpxml_files/enclosure_attics_and_roofs.xml | 1 + test/test_converter.py | 1 + 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/hpxml_version_translator/converter.py b/hpxml_version_translator/converter.py index e5321bc..3b18ec5 100644 --- a/hpxml_version_translator/converter.py +++ b/hpxml_version_translator/converter.py @@ -291,6 +291,18 @@ def get_event_type_from_building_id(building_id): elif this_attic.AtticType == 'venting unknown attic': this_attic.AtticType = E.AtticType(E.Attic(E.extension(E.Vented('unknown')))) + # move AttachedToRoof to after VentilationRate + if hasattr(this_attic, 'AttachedToRoof'): + attached_to_roof = deepcopy(this_attic.AttachedToRoof) + add_after( + this_attic, + ['SystemIdentifier', + 'AttachedToSpace', + 'AtticType', + 'VentilationRate'], + attached_to_roof + ) + this_attic.remove(this_attic.AttachedToRoof[0]) # remove the AttachedToRoof of HPXML v2 # find the wall with the same id and add AtticWallType = knee wall if hasattr(this_attic, 'AtticKneeWall'): knee_wall_id = this_attic.AtticKneeWall.attrib['idref'] @@ -355,7 +367,6 @@ def get_event_type_from_building_id(building_id): ) el_not_in_v3 = [ - 'AttachedToRoof', 'ExteriorAdjacentTo', 'InteriorAdjacentTo', 'AtticKneeWall', diff --git a/test/hpxml_files/enclosure_attics_and_roofs.xml b/test/hpxml_files/enclosure_attics_and_roofs.xml index 03da6a0..46be659 100644 --- a/test/hpxml_files/enclosure_attics_and_roofs.xml +++ b/test/hpxml_files/enclosure_attics_and_roofs.xml @@ -29,6 +29,7 @@ + ambient attic diff --git a/test/test_converter.py b/test/test_converter.py index 284fdc3..378b6fd 100644 --- a/test/test_converter.py +++ b/test/test_converter.py @@ -94,6 +94,7 @@ def test_enclosure_attics(): attic1 = root.Building.BuildingDetails.Enclosure.Attics.Attic[0] enclosure = attic1.getparent().getparent() assert not attic1.AtticType.Attic.Vented # unvented attic + assert attic1.AttachedToRoof.attrib['idref'] == 'roof-1' assert not hasattr(enclosure, 'AtticAndRoof') assert not hasattr(enclosure, 'ExteriorAdjacentTo') assert enclosure.Walls.Wall[0].AtticWallType == 'knee wall' From c42739519f6c9bc823628e6d8813c32ae6929b5d Mon Sep 17 00:00:00 2001 From: bpark1327 Date: Thu, 22 Apr 2021 22:51:14 -0600 Subject: [PATCH 10/11] run flake8 --- hpxml_version_translator/converter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hpxml_version_translator/converter.py b/hpxml_version_translator/converter.py index 3b18ec5..e3862dc 100644 --- a/hpxml_version_translator/converter.py +++ b/hpxml_version_translator/converter.py @@ -300,7 +300,7 @@ def get_event_type_from_building_id(building_id): 'AttachedToSpace', 'AtticType', 'VentilationRate'], - attached_to_roof + attached_to_roof ) this_attic.remove(this_attic.AttachedToRoof[0]) # remove the AttachedToRoof of HPXML v2 # find the wall with the same id and add AtticWallType = knee wall From ea90fd3c2711fc63b44bf99631d6bcbbadb29959 Mon Sep 17 00:00:00 2001 From: bpark1327 Date: Mon, 26 Apr 2021 14:37:40 -0600 Subject: [PATCH 11/11] add more tests for attics and bugfix --- hpxml_version_translator/converter.py | 19 +++++++---------- .../enclosure_attics_and_roofs.xml | 21 +++++++++++++++++++ test/test_converter.py | 16 ++++++++++++++ 3 files changed, 45 insertions(+), 11 deletions(-) diff --git a/hpxml_version_translator/converter.py b/hpxml_version_translator/converter.py index d0a00bc..33b7e76 100644 --- a/hpxml_version_translator/converter.py +++ b/hpxml_version_translator/converter.py @@ -309,16 +309,13 @@ def get_event_type_from_building_id(building_id): knee_wall = root.xpath( 'h:Building/h:BuildingDetails/h:Enclosure/h:Walls/h:Wall[h:SystemIdentifier/@id=$sysid]', sysid=knee_wall_id, **xpkw)[0] - if hasattr(knee_wall, 'AtticWallType'): - knee_wall.AtticWallType._setText('knee wall') - else: - add_after( - knee_wall, - ['SystemIdentifier', - 'ExteriorAdjacentTo', - 'InteriorAdjacentTo'], - E.AtticWallType('knee wall') - ) + add_after( + knee_wall, + ['SystemIdentifier', + 'ExteriorAdjacentTo', + 'InteriorAdjacentTo'], + E.AtticWallType('knee wall') + ) # create a FrameFloor adjacent to the attic and assign the area below to Area # and then copy AtticFloorInsulation over to Insulation of the frame floor if hasattr(this_attic, 'AtticFloorInsulation'): @@ -333,7 +330,7 @@ def get_event_type_from_building_id(building_id): ) ) if hasattr(this_attic, 'Area'): - enclosure.FrameFloors.FrameFloor.append(E.Area(this_attic.Area)) + enclosure.FrameFloors.FrameFloor.append(E.Area(float(this_attic.Area))) enclosure.FrameFloors.FrameFloor.append(attic_floor_insulation) # find the roof whose InteriorAdjacentTo is attic and then copy it to Insulation of the roof # FIXME: add insulation to v2 Roofs and these roofs will be converted into hpxml v3 later diff --git a/test/hpxml_files/enclosure_attics_and_roofs.xml b/test/hpxml_files/enclosure_attics_and_roofs.xml index 46be659..ced2434 100644 --- a/test/hpxml_files/enclosure_attics_and_roofs.xml +++ b/test/hpxml_files/enclosure_attics_and_roofs.xml @@ -58,6 +58,27 @@ 7.5 + 1500.0 + + + + vented attic + + + + flat roof + + + + cathedral ceiling + + + + cape cod + + + + other diff --git a/test/test_converter.py b/test/test_converter.py index 1e942f0..e623826 100644 --- a/test/test_converter.py +++ b/test/test_converter.py @@ -105,6 +105,7 @@ def test_enclosure_attics(): assert enclosure.Roofs.Roof[0].Insulation.Layer.InstallationType == 'cavity' assert enclosure.Roofs.Roof[0].Insulation.Layer.NominalRValue == 7.5 assert enclosure.FrameFloors.FrameFloor[0].InteriorAdjacentTo == 'attic' + assert enclosure.FrameFloors.FrameFloor[0].Area == 1500.0 assert enclosure.FrameFloors.FrameFloor[0].Insulation.InsulationGrade == 1 assert enclosure.FrameFloors.FrameFloor[0].Insulation.InsulationCondition == 'poor' assert enclosure.FrameFloors.FrameFloor[0].Insulation.AssemblyEffectiveRValue == 5.5 @@ -112,6 +113,21 @@ def test_enclosure_attics(): attic2 = root.Building.BuildingDetails.Enclosure.Attics.Attic[1] assert attic2.AtticType.Attic.extension.Vented == 'unknown' # venting unknown attic + attic3 = root.Building.BuildingDetails.Enclosure.Attics.Attic[2] + assert attic3.AtticType.Attic.Vented # vented attic + + attic4 = root.Building.BuildingDetails.Enclosure.Attics.Attic[3] + assert hasattr(attic4.AtticType, 'FlatRoof') + + attic5 = root.Building.BuildingDetails.Enclosure.Attics.Attic[4] + assert hasattr(attic5.AtticType, 'CathedralCeiling') + + attic6 = root.Building.BuildingDetails.Enclosure.Attics.Attic[5] + assert attic6.AtticType.Attic.CapeCod + + attic7 = root.Building.BuildingDetails.Enclosure.Attics.Attic[6] + assert hasattr(attic7.AtticType, 'Other') + def test_enclosure_roofs(): root = convert_hpxml_and_parse(hpxml_dir / 'enclosure_attics_and_roofs.xml')