Retrieve a KML representation of the model. Includes polygonized mask map and vector stream network.

        Args:
            session (:mod:`sqlalchemy.orm.session.Session`): SQLAlchemy session object bound to PostGIS enabled database
            path (str, optional): Path to file where KML file will be written. Defaults to None.
            documentName (str, optional): Name of the KML document. This will be the name that appears in the legend.
                Defaults to 'Stream Network'.
            withStreamNetwork (bool, optional): Include stream network. Defaults to True.
            withNodes (bool, optional): Include nodes. Defaults to False.
            styles (dict, optional): Custom styles to apply to KML geometry. Defaults to empty dictionary.

                Valid keys (styles) include:
                   * streamLineColor: tuple/list of RGBA integers (0-255) e.g.: (255, 0, 0, 128)
                   * streamLineWidth: float line width in pixels
                   * nodeIconHref: link to icon image (PNG format) to represent nodes (see: http://kml4earth.appspot.com/icons.html)
                   * nodeIconScale: scale of the icon image
                   * maskLineColor: tuple/list of RGBA integers (0-255) e.g.: (255, 0, 0, 128)
                   * maskLineWidth: float line width in pixels
                   * maskFillColor: tuple/list of RGBA integers (0-255) e.g.: (255, 0, 0, 128)

        Returns:
            str: KML string

def getModelSummaryAsKml(self, session, path=None, documentName=None, withStreamNetwork=True, withNodes=False, styles={}):
        """
        Retrieve a KML representation of the model. Includes polygonized mask map and vector stream network.

        Args:
            session (:mod:`sqlalchemy.orm.session.Session`): SQLAlchemy session object bound to PostGIS enabled database
            path (str, optional): Path to file where KML file will be written. Defaults to None.
            documentName (str, optional): Name of the KML document. This will be the name that appears in the legend.
                Defaults to 'Stream Network'.
            withStreamNetwork (bool, optional): Include stream network. Defaults to True.
            withNodes (bool, optional): Include nodes. Defaults to False.
            styles (dict, optional): Custom styles to apply to KML geometry. Defaults to empty dictionary.

                Valid keys (styles) include:
                   * streamLineColor: tuple/list of RGBA integers (0-255) e.g.: (255, 0, 0, 128)
                   * streamLineWidth: float line width in pixels
                   * nodeIconHref: link to icon image (PNG format) to represent nodes (see: http://kml4earth.appspot.com/icons.html)
                   * nodeIconScale: scale of the icon image
                   * maskLineColor: tuple/list of RGBA integers (0-255) e.g.: (255, 0, 0, 128)
                   * maskLineWidth: float line width in pixels
                   * maskFillColor: tuple/list of RGBA integers (0-255) e.g.: (255, 0, 0, 128)

        Returns:
            str: KML string
        """
        # Get mask map
        watershedMaskCard = self.getCard('WATERSHED_MASK')
        maskFilename = watershedMaskCard.value
        maskExtension = maskFilename.strip('"').split('.')[1]

        maskMap = session.query(RasterMapFile).\
                          filter(RasterMapFile.projectFile == self).\
                          filter(RasterMapFile.fileExtension == maskExtension).\
                          one()

        # Get mask map as a KML polygon
        statement = """
                    SELECT val, ST_AsKML(geom) As polygon
                    FROM (
                    SELECT (ST_DumpAsPolygons({0})).*
                    FROM {1} WHERE id={2}
                    ) As foo
                    ORDER BY val;
                    """.format('raster', maskMap.tableName, maskMap.id)

        result = session.execute(statement)

        maskMapKmlPolygon = ''
        for row in result:
            maskMapKmlPolygon = row.polygon

        # Set Default Styles
        streamLineColorValue = (255, 255, 0, 0)  # Blue
        streamLineWidthValue = 2
        nodeIconHrefValue = 'http://maps.google.com/mapfiles/kml/paddle/red-circle.png'
        nodeIconScaleValue = 1
        maskLineColorValue = (255, 0, 0, 255)
        maskFillColorValue = (128, 64, 64, 64)
        maskLineWidthValue = 2

        # Validate
        if 'streamLineColor' in styles:
            if len(styles['streamLineColor']) < 4:
                log.warning('streamLineColor style must be a list or a tuple of '
                         'four elements representing integer RGBA values.')
            else:
                userLineColor = styles['streamLineColor']
                streamLineColorValue = (userLineColor[3], userLineColor[2], userLineColor[1], userLineColor[0])

        if 'streamLineWidth' in styles:
            try:
                float(styles['streamLineWidth'])
                streamLineWidthValue = styles['streamLineWidth']

            except ValueError:
                log.warning('streamLineWidth must be a valid '
                         'number representing the width of the line in pixels.')

        if 'nodeIconHref' in styles:
            nodeIconHrefValue = styles['nodeIconHref']

        if 'nodeIconScale' in styles:
            try:
                float(styles['nodeIconScale'])
                nodeIconScaleValue = styles['nodeIconScale']

            except ValueError:
                log.warning('nodeIconScaleValue must be a valid number representing'
                         ' the width of the line in pixels.')

        if 'maskLineColor' in styles:
            if len(styles['maskLineColor']) < 4:
                log.warning('maskLineColor style must be a list or a tuple of four '
                         'elements representing integer RGBA values.')
            else:
                userLineColor = styles['maskLineColor']
                maskLineColorValue = (userLineColor[3], userLineColor[2], userLineColor[1], userLineColor[0])

        if 'maskFillColor' in styles:
            if len(styles['maskFillColor']) < 4:
                log.warning('maskFillColor style must be a list or a tuple of four '
                         'elements representing integer RGBA values.')
            else:
                userLineColor = styles['maskFillColor']
                maskFillColorValue = (userLineColor[3], userLineColor[2], userLineColor[1], userLineColor[0])

        if 'maskLineWidth' in styles:
            try:
                float(styles['maskLineWidth'])
                maskLineWidthValue = styles['maskLineWidth']

            except ValueError:
                log.warning('maskLineWidth must be a valid number representing '
                         'the width of the line in pixels.')

        if not documentName:
            documentName = self.name

        # Initialize KML Document
        kml = ET.Element('kml', xmlns='http://www.opengis.net/kml/2.2')
        document = ET.SubElement(kml, 'Document')
        docName = ET.SubElement(document, 'name')
        docName.text = documentName

        # Mask Map
        maskPlacemark = ET.SubElement(document, 'Placemark')
        maskPlacemarkName = ET.SubElement(maskPlacemark, 'name')
        maskPlacemarkName.text = 'Mask Map'

        # Mask Styles
        maskStyles = ET.SubElement(maskPlacemark, 'Style')

        # Set polygon line style
        maskLineStyle = ET.SubElement(maskStyles, 'LineStyle')

        # Set polygon line color and width
        maskLineColor = ET.SubElement(maskLineStyle, 'color')
        maskLineColor.text = '%02X%02X%02X%02X' % maskLineColorValue
        maskLineWidth = ET.SubElement(maskLineStyle, 'width')
        maskLineWidth.text = str(maskLineWidthValue)

        # Set polygon fill color
        maskPolyStyle = ET.SubElement(maskStyles, 'PolyStyle')
        maskPolyColor = ET.SubElement(maskPolyStyle, 'color')
        maskPolyColor.text = '%02X%02X%02X%02X' % maskFillColorValue

        # Mask Geometry
        maskPolygon = ET.fromstring(maskMapKmlPolygon)
        maskPlacemark.append(maskPolygon)

        if withStreamNetwork:
            # Get the channel input file for the stream network
            channelInputFile = self.channelInputFile

            # Retrieve Stream Links
            links = channelInputFile.getFluvialLinks()

            # Stream Network
            for link in links:
                placemark = ET.SubElement(document, 'Placemark')
                placemarkName = ET.SubElement(placemark, 'name')
                placemarkName.text = 'Stream Link {0}'.format(str(link.linkNumber))

                # Create style tag and setup styles
                styles = ET.SubElement(placemark, 'Style')

                # Set line style
                lineStyle = ET.SubElement(styles, 'LineStyle')
                lineColor = ET.SubElement(lineStyle, 'color')
                lineColor.text = '%02X%02X%02X%02X' % streamLineColorValue
                lineWidth = ET.SubElement(lineStyle, 'width')
                lineWidth.text = str(streamLineWidthValue)

                # Add the geometry to placemark
                linkKML = link.getAsKml(session)
                if linkKML:
                    lineString = ET.fromstring(linkKML)
                    placemark.append(lineString)
                else:
                    log.warning("No geometry found for link with id {0}".format(link.id))

                if withNodes:
                    # Create the node styles
                    nodeStyles = ET.SubElement(document, 'Style', id='node_styles')

                    # Hide labels
                    nodeLabelStyle = ET.SubElement(nodeStyles, 'LabelStyle')
                    nodeLabelScale = ET.SubElement(nodeLabelStyle, 'scale')
                    nodeLabelScale.text = str(0)

                    # Style icon
                    nodeIconStyle = ET.SubElement(nodeStyles, 'IconStyle')

                    # Set icon
                    nodeIcon = ET.SubElement(nodeIconStyle, 'Icon')
                    iconHref = ET.SubElement(nodeIcon, 'href')
                    iconHref.text = nodeIconHrefValue

                    # Set icon scale
                    iconScale = ET.SubElement(nodeIconStyle, 'scale')
                    iconScale.text = str(nodeIconScaleValue)

                    for node in link.nodes:
                        # New placemark for each node
                        nodePlacemark = ET.SubElement(document, 'Placemark')
                        nodePlacemarkName = ET.SubElement(nodePlacemark, 'name')
                        nodePlacemarkName.text = str(node.nodeNumber)

                        # Styles for the node
                        nodeStyleUrl = ET.SubElement(nodePlacemark, 'styleUrl')
                        nodeStyleUrl.text = '#node_styles'

                        nodeString = ET.fromstring(node.getAsKml(session))
                        nodePlacemark.append(nodeString)

        kmlString = ET.tostring(kml)

        if path:
            with open(path, 'w') as f:
                f.write(kmlString)

        return kmlString