diff --git a/hpxml_version_translator/converter.py b/hpxml_version_translator/converter.py index 21490b8..457a391 100644 --- a/hpxml_version_translator/converter.py +++ b/hpxml_version_translator/converter.py @@ -566,6 +566,112 @@ def get_event_type_from_building_id(building_id): layer.InstallationType._setText(f'continuous - {str(insulation.InsulationLocation)}') insulation.remove(insulation.InsulationLocation) + # Windows and Skylights + for i, win in enumerate(root.xpath('//h:Window|//h:Skylight', **xpkw)): + if hasattr(win, 'VisibleTransmittance'): + add_after( + win, + ['Area', + 'Quantity', + 'Azimuth', + 'Orientation', + 'FrameType', + 'GlassLayers', + 'GlassType', + 'GasFill', + 'Condition', + 'UFactor', + 'SHGC'], + E.VisibleTransmittance(float(win.VisibleTransmittance)) + ) + win.remove(win.VisibleTransmittance[1]) # remove VisibleTransmittance of HPXML v2 + if hasattr(win, 'ExteriorShading'): + ext_shade = str(win.ExteriorShading) + win.ExteriorShading.clear() + win.ExteriorShading.extend([ + E.SystemIdentifier(id=f'exterior-shading-{i}'), + E.Type(ext_shade) + ]) + if hasattr(win, 'InteriorShading'): # insert ExteriorShading right before InteriorShading + win.InteriorShading.addprevious(win.ExteriorShading) + if hasattr(win, 'Treatments'): + if win.Treatments in ['shading', 'solar screen']: + treatment_shade = E.ExteriorShading( + E.SystemIdentifier(id=f'treatment-shading-{i}'), + ) + if win.Treatments == 'solar screen': + treatment_shade.append(E.Type('solar screens')) + add_after( + win, + ['UFactor', + 'SHGC', + 'VisibleTransmittance', + 'NFRCCertified', + 'ThirdPartyCertification', + 'WindowFilm'], + treatment_shade + ) + elif win.Treatments == 'window film': + add_after( + win, + ['UFactor', + 'SHGC', + 'VisibleTransmittance', + 'NFRCCertified', + 'ThirdPartyCertification'], + E.WindowFilm( + E.SystemIdentifier(id=f'window-film-{i}') + ) + ) + win.remove(win.Treatments) + if hasattr(win, 'InteriorShading'): + int_shading = str(win.InteriorShading) + int_shading_factor = float(win.InteriorShadingFactor) + win.InteriorShading.clear() + win.InteriorShading.extend([ + E.SystemIdentifier(id=f'interior-shading-{i}'), + E.Type(int_shading), + E.SummerShadingCoefficient(int_shading_factor), + E.WinterShadingCoefficient(int_shading_factor) + ]) + win.remove(win.InteriorShadingFactor) + if hasattr(win, 'MovableInsulationRValue'): + add_after( + win, + ['UFactor', + 'SHGC', + 'VisibleTransmittance', + 'NFRCCertified', + 'ThirdPartyCertification', + 'ExteriorShading', + 'InteriorShading', + 'StormWindow'], + E.MoveableInsulation( + E.SystemIdentifier(id=f'movable-insulation-{i}'), + E.RValue(float(win.MovableInsulationRValue)) + ) + ) + win.remove(win.MovableInsulationRValue) + if hasattr(win, 'GlassLayers'): + if win.GlassLayers in ['single-paned with low-e storms', 'single-paned with storms']: + storm_window = E.StormWindow( + E.SystemIdentifier(id=f'storm-window-{i}') + ) + if win.GlassLayers == 'single-paned with low-e storms': + storm_window.append(E.GlassType('low-e')) + win.GlassLayers._setText('single-pane') + add_after( + win, + ['UFactor', + 'SHGC', + 'VisibleTransmittance', + 'NFRCCertified', + 'ThirdPartyCertification', + 'ExteriorShading', + 'InteriorShading'], + storm_window + ) + # TODO: Standardize Locations # https://github.com/hpxmlwg/hpxml/pull/156 diff --git a/test/hpxml_files/enclosure_windows_skylights.xml b/test/hpxml_files/enclosure_windows_skylights.xml new file mode 100644 index 0000000..01fbe76 --- /dev/null +++ b/test/hpxml_files/enclosure_windows_skylights.xml @@ -0,0 +1,74 @@ + + + + + + 2021-04-05T14:17:07.685077 + create + + + + + + audit + + + + + + + + + + + + 108.0 + 0 + solar screen + 0.33 + 0.45 + true + 0.9 + light shades + 0.7 + evergreen tree + 5.5 + + + + + single-paned with low-e storms + 0.45 + 0.6 + 0.8 + solar film + + + + window film + 0.45 + 0.6 + + + + + + 20.0 + 0 + solar screen + 0.25 + 0.60 + true + 0.9 + dark shades + 0.65 + building + 3.5 + 6.0 + + + + + + + \ No newline at end of file diff --git a/test/test_converter.py b/test/test_converter.py index 6db56f9..1c23f55 100644 --- a/test/test_converter.py +++ b/test/test_converter.py @@ -277,3 +277,48 @@ def test_walls(): assert wall1.Insulation.Layer[1].InsulationMaterial.Batt == 'fiberglass' assert wall1.Insulation.Layer[1].NominalRValue == 12.0 assert wall1.Insulation.Layer[1].Thickness == 3.5 + + +def test_windows(): + root = convert_hpxml_and_parse(hpxml_dir / 'enclosure_windows_skylights.xml') + + win1 = root.Building.BuildingDetails.Enclosure.Windows.Window[0] + assert win1.Area == 108.0 + assert win1.Azimuth == 0 + assert win1.UFactor == 0.33 + assert win1.SHGC == 0.45 + assert win1.NFRCCertified + assert win1.VisibleTransmittance == 0.9 + assert win1.ExteriorShading[0].Type == 'solar screens' + assert win1.ExteriorShading[1].Type == 'evergreen tree' + assert win1.InteriorShading.Type == 'light shades' + assert win1.InteriorShading.SummerShadingCoefficient == 0.7 + assert win1.InteriorShading.WinterShadingCoefficient == 0.7 + assert win1.MoveableInsulation.RValue == 5.5 + assert win1.AttachedToWall.attrib['idref'] == 'wall-1' + assert not hasattr(win1, 'Treatments') + assert not hasattr(win1, 'InteriorShadingFactor') + assert not hasattr(win1, 'MovableInsulationRValue') + + win2 = root.Building.BuildingDetails.Enclosure.Windows.Window[1] + assert win2.GlassLayers == 'single-pane' + assert win2.StormWindow.GlassType == 'low-e' + assert win2.ExteriorShading[0].Type == 'solar film' + + win3 = root.Building.BuildingDetails.Enclosure.Windows.Window[2] + assert hasattr(win3, 'WindowFilm') + + skylight1 = root.Building.BuildingDetails.Enclosure.Skylights.Skylight[0] + assert skylight1.Area == 20.0 + assert skylight1.UFactor == 0.25 + assert skylight1.SHGC == 0.60 + assert skylight1.ExteriorShading[0].Type == 'solar screens' + assert skylight1.ExteriorShading[1].Type == 'building' + assert skylight1.InteriorShading.Type == 'dark shades' + assert skylight1.InteriorShading.SummerShadingCoefficient == 0.65 + assert skylight1.InteriorShading.WinterShadingCoefficient == 0.65 + assert skylight1.MoveableInsulation.RValue == 3.5 + assert skylight1.Pitch == 6.0 + assert not hasattr(skylight1, 'Treatments') + assert not hasattr(skylight1, 'InteriorShadingFactor') + assert not hasattr(skylight1, 'MovableInsulationRValue')