Repository: NREL/hescore-hpxml

Issue:
Verify that hpxml2hescore works on workflow HPXML
The hpxml2hescore script should be able to process workflow HPXML without loosing any information. Run all the regression set HPXML files through scoring tool API submit_hpxml() method and compare the results to the regression set results and Identify any differences.

I have identified one issue so far:

HEScore designates insulated ducts using  `DuctInsulationMaterial/Unknown` and uninsulated ducts using `DuctInsulationMaterial/None`. But hpxml2hescore maps these both to `"insulated": false.`

Discussion:

Patch:
diff --git a/docs/source/translation/hvac_distribution.rst b/docs/source/translation/hvac_distribution.rst
index 12766e8e..3676c227 100644
--- a/docs/source/translation/hvac_distribution.rst
+++ b/docs/source/translation/hvac_distribution.rst
@@ -81,8 +81,8 @@ Duct Insulation
 
 If the any of the ``Ducts`` elements in a particular
 :ref:`location <ductlocationmapping>` have a ``DuctInsulationRValue`` or
-``DuctInsulationThickness`` that is greater than zero, all of the ducts in that
-location are considered insulated.
+``DuctInsulationThickness`` that is greater than zero or have a ``DuctInsulationMaterial`` that is not ``None``, 
+all of the ducts in that location are considered insulated.
 
 Duct Sealing
 ************
diff --git a/hescorehpxml/base.py b/hescorehpxml/base.py
index 55b7e4ee..58119ed2 100644
--- a/hescorehpxml/base.py
+++ b/hescorehpxml/base.py
@@ -577,7 +577,8 @@ class HPXMLtoHEScoreTranslatorBase(object):
             duct_fracs_by_hescore_duct_loc[hescore_duct_location] += frac_duct_area
 
             # Duct Insulation
-            duct_has_ins = self.xpath(duct_el, 'h:DuctInsulationRValue > 0 or h:DuctInsulationThickness > 0')
+            duct_has_ins = self.xpath(duct_el, 'h:DuctInsulationRValue > 0 or h:DuctInsulationThickness > 0 or\
+                                      count(h:DuctInsulationMaterial[not(h:None)]) > 0')
             hescore_duct_loc_has_insulation[hescore_duct_location] = \
                 hescore_duct_loc_has_insulation[hescore_duct_location] or duct_has_ins
 


Test patch:
diff --git a/tests/test_translation.py b/tests/test_translation.py
index dab1f7eb..2c401201 100644
--- a/tests/test_translation.py
+++ b/tests/test_translation.py
@@ -3042,6 +3042,70 @@ class TestHEScoreV3(unittest.TestCase, ComparatorBase):
         d_v3 = tr_v3.hpxml_to_hescore()
         self.assertEqual(d_v3['building']['systems']['hvac'][0]['hvac_distribution'][0]['location'], 'unvented_crawl')
 
+    def test_v3_duct_insulation(self):
+        tr = self._load_xmlfile('hescore_min_v3')
+        res = tr.hpxml_to_hescore()
+        self.assertEqual(res['building']['systems']['hvac'][0]['hvac_distribution'][0]['insulated'], False)
+
+        E = self.element_maker()
+        el = self.xpath('//h:Ducts/h:DuctLocation')
+        duct_ins_mat = E.DuctInsulationMaterial(
+            E.Batt('unknown')
+        )
+        el.addprevious(duct_ins_mat)
+        res = tr.hpxml_to_hescore()
+        self.assertEqual(res['building']['systems']['hvac'][0]['hvac_distribution'][0]['insulated'], True)
+        el.getparent().remove(duct_ins_mat)
+
+        duct_ins_mat = E.DuctInsulationMaterial(
+            E.LooseFill('unknown')
+        )
+        el.addprevious(duct_ins_mat)
+        res = tr.hpxml_to_hescore()
+        self.assertEqual(res['building']['systems']['hvac'][0]['hvac_distribution'][0]['insulated'], True)
+        el.getparent().remove(duct_ins_mat)
+
+        duct_ins_mat = E.DuctInsulationMaterial(
+            E.Rigid('unknown')
+        )
+        el.addprevious(duct_ins_mat)
+        res = tr.hpxml_to_hescore()
+        self.assertEqual(res['building']['systems']['hvac'][0]['hvac_distribution'][0]['insulated'], True)
+        el.getparent().remove(duct_ins_mat)
+
+        duct_ins_mat = E.DuctInsulationMaterial(
+            E.SprayFoam('unknown')
+        )
+        el.addprevious(duct_ins_mat)
+        res = tr.hpxml_to_hescore()
+        self.assertEqual(res['building']['systems']['hvac'][0]['hvac_distribution'][0]['insulated'], True)
+        el.getparent().remove(duct_ins_mat)
+
+        duct_ins_mat = E.DuctInsulationMaterial(
+            E.Other()
+        )
+        el.addprevious(duct_ins_mat)
+        res = tr.hpxml_to_hescore()
+        self.assertEqual(res['building']['systems']['hvac'][0]['hvac_distribution'][0]['insulated'], True)
+        el.getparent().remove(duct_ins_mat)
+
+        none_type = getattr(E, 'None')
+        duct_ins_mat = E.DuctInsulationMaterial(
+            none_type
+        )
+        el.addprevious(duct_ins_mat)
+        res = tr.hpxml_to_hescore()
+        self.assertEqual(res['building']['systems']['hvac'][0]['hvac_distribution'][0]['insulated'], False)
+        el.getparent().remove(duct_ins_mat)
+
+        duct_ins_mat = E.DuctInsulationMaterial(
+            E.Unknown()
+        )
+        el.addprevious(duct_ins_mat)
+        res = tr.hpxml_to_hescore()
+        self.assertEqual(res['building']['systems']['hvac'][0]['hvac_distribution'][0]['insulated'], True)
+        el.getparent().remove(duct_ins_mat)
+
 
 if __name__ == "__main__":
     unittest.main()