docs: def getAsKmlPngAnimation(self, tableName, timeStampedRasters=[], rasterIdFieldName='id', rasterFieldName='raster',
                               documentName='default', noDataValue=0, alpha=1.0, drawOrder=0, cellSize=None,
                               resampleMethod='NearestNeighbour', discreet=False):
          """
          Return a sequence of rasters with timestamps as a kml with time markers for animation.
  
          :param tableName: Name of the table to extract rasters from
          :param timeStampedRasters: List of dictionaries with keys: rasterId, dateTime
                 rasterId = a unique integer identifier used to locate the raster (usually value of primary key column)
                 dateTime = a datetime object representing the time the raster occurs
  
                 e.g:
                 timeStampedRasters = [{ 'rasterId': 1, 'dateTime': datetime(1970, 1, 1)},
                                       { 'rasterId': 2, 'dateTime': datetime(1970, 1, 2)},
                                       { 'rasterId': 3, 'dateTime': datetime(1970, 1, 3)}]
  
          :param rasterIdFieldName: Name of the id field for rasters (usually the primary key field)
          :param rasterFieldName: Name of the field where rasters are stored (of type raster)
          :param documentName: The name to give to the KML document (will be listed in legend under this name)
          :param noDataValue: The value to be used as the no data value (default is 0)
          :param alpha: The transparency to apply to each raster cell
          :param drawOrder: The draw order determines the order images are stacked if multiple are showing.
          :param cellSize: Specify this parameter to resample the rasters to a different size the cells (e.g.: 30 to
                           resample to cells with dimensions 30 x 30 in units of the raster spatial reference system).
                           NOTE: the processing time increases exponentially with shrinking cellSize values.
  
          :rtype : (string, list)
  
          """
  
  
          if not self.isNumber(noDataValue):
              raise ValueError('RASTER CONVERSION ERROR: noDataValue must be a number.')
  
          if not self.isNumber(drawOrder):
              raise ValueError('RASTER CONVERSION ERROR: drawOrder must be a number.')
  
          if not (alpha >= 0 and alpha <= 1.0):
              raise ValueError("RASTER CONVERSION ERROR: alpha must be between 0.0 and 1.0.")
  
  
          # Extract raster Ids and validate
          rasterIds = []
  
          for timeStampedRaster in timeStampedRasters:
              # Validate dictionary
              if 'rasterId' not in timeStampedRaster:
                  raise ValueError('RASTER CONVERSION ERROR: rasterId must be provided for each raster.')
              elif 'dateTime' not in timeStampedRaster:
                  raise ValueError('RASTER CONVERSION ERROR: dateTime must be provided for each raster.')
  
              rasterIds.append(str(timeStampedRaster['rasterId']))
  
          # Get the color ramp and parameters
          minValue, maxValue = self.getMinMaxOfRasters(session=self._session,
                                                       table=tableName,
                                                       rasterIds=rasterIds,
                                                       rasterIdField=rasterIdFieldName,
                                                       rasterField=rasterFieldName,
                                                       noDataValue=noDataValue)
  
          mappedColorRamp = ColorRampGenerator.mapColorRampToValues(colorRamp=self._colorRamp,
                                                                    minValue=minValue,
                                                                    maxValue=maxValue,
                                                                    alpha=alpha)
  
          # Join strings in list to create ramp
          rampString = mappedColorRamp.getPostGisColorRampString()
  
  
          # Get a PNG representation of each raster
          result = self.getRastersAsPngs(session=self._session,
                                         tableName=tableName,
                                         rasterIds=rasterIds,
                                         postGisRampString=rampString,
                                         rasterField=rasterFieldName,
                                         rasterIdField=rasterIdFieldName,
                                         cellSize=cellSize,
                                         resampleMethod=resampleMethod)
  
          binaryPNGs = []
  
          for row in result:
              binaryPNGs.append(row.png)
  
          # Determine extents for the KML wrapper file via query
          statement = '''
                      SELECT (foo.metadata).*
                      FROM (
                      SELECT ST_MetaData(ST_Transform({0}, 4326, 'Bilinear')) as metadata
                      FROM {1}
                      WHERE {2}={3}
                      ) As foo;
                      '''.format(rasterFieldName, tableName, rasterIdFieldName, rasterIds[0])
  
          result = self._session.execute(statement)
  
          for row in result:
              upperLeftY = row.upperlefty
              scaleY = row.scaley
              height = row.height
  
              upperLeftX = row.upperleftx
              scaleX = row.scalex
              width = row.width
  
          north = upperLeftY
          south = upperLeftY + (scaleY * height)
          east = upperLeftX + (scaleX * width)
          west = upperLeftX
  
          # Default to time delta to None
          deltaTime = None
  
          # Calculate delta time between images if more than one
          time1 = timeStampedRasters[0]['dateTime']
  
          if len(timeStampedRasters) >= 2:
              time2 = timeStampedRasters[1]['dateTime']
              deltaTime = time2 - time1
  
          # 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
  
          if not discreet:
              # Embed the color ramp in SLD format
              document.append(ET.fromstring(mappedColorRamp.getColorMapAsContinuousSLD()))
          else:
              values = []
              document.append(ET.fromstring(mappedColorRamp.getColorMapAsDiscreetSLD(values)))
  
          # Apply special style to hide legend items
          style = ET.SubElement(document, 'Style', id='check-hide-children')
          listStyle = ET.SubElement(style, 'ListStyle')
          listItemType = ET.SubElement(listStyle, 'listItemType')
          listItemType.text = 'checkHideChildren'
          styleUrl = ET.SubElement(document, 'styleUrl')
          styleUrl.text = '#check-hide-children'
  
          for index, timeStampedRaster in enumerate(timeStampedRasters):
              # Extract variable
              if deltaTime:
                  dateTime = timeStampedRaster['dateTime']
                  prevDateTime = dateTime - deltaTime
  
  
              # GroundOverlay
              groundOverlay = ET.SubElement(document, 'GroundOverlay')
              overlayName = ET.SubElement(groundOverlay, 'name')
              overlayName.text = 'Overlay'
  
              if deltaTime:
                  # Create TimeSpan tag
                  timeSpan = ET.SubElement(groundOverlay, 'TimeSpan')
  
                  # Create begin tag
                  begin = ET.SubElement(timeSpan, 'begin')
                  begin.text = prevDateTime.strftime('%Y-%m-%dT%H:%M:%S')
                  end = ET.SubElement(timeSpan, 'end')
                  end.text = dateTime.strftime('%Y-%m-%dT%H:%M:%S')
  
              # DrawOrder
              drawOrderElement = ET.SubElement(groundOverlay, 'drawOrder')
              drawOrderElement.text = str(drawOrder)
  
              # Define Region
              regionElement = ET.SubElement(groundOverlay, 'Region')
              latLonBox = ET.SubElement(regionElement, 'LatLonBox')
  
              northElement = ET.SubElement(latLonBox, 'north')
              northElement.text = str(north)
  
              southElement = ET.SubElement(latLonBox, 'south')
              southElement.text = str(south)
  
              eastElement = ET.SubElement(latLonBox, 'east')
              eastElement.text = str(east)
  
              westElement = ET.SubElement(latLonBox, 'west')
              westElement.text = str(west)
  
              # Href to PNG
              iconElement = ET.SubElement(groundOverlay, 'Icon')
              hrefElement = ET.SubElement(iconElement, 'href')
              hrefElement.text = 'raster{0}.png'.format(index)
  
              # LatLonBox
              latLonBox = ET.SubElement(groundOverlay, 'LatLonBox')
  
              northElement = ET.SubElement(latLonBox, 'north')
              northElement.text = str(north)
  
              southElement = ET.SubElement(latLonBox, 'south')
              southElement.text = str(south)
  
              eastElement = ET.SubElement(latLonBox, 'east')
              eastElement.text = str(east)
  
              westElement = ET.SubElement(latLonBox, 'west')
              westElement.text = str(west)
  
          return ET.tostring(kml), binaryPNGs