docs: def getAsKmlGridAnimation(self, tableName, timeStampedRasters=[], rasterIdFieldName='id', rasterFieldName='raster',
                                documentName='default', alpha=1.0,  noDataValue=0, 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 alpha: The transparency to apply to each raster cell
          :param noDataValue: The value to be used as the no data value (default is 0)
  
          :rtype : string
          """
  
          # Validate alpha
          if not (alpha >= 0 and alpha <= 1.0):
              raise ValueError("RASTER CONVERSION ERROR: alpha must be between 0.0 and 1.0.")
  
          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']))
  
          # One color ramp to rule them all
          # Get a single color ramp that is based on the range of values in all the rasters
          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)
  
  
  
          # 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'
  
          # Collect unique values
          uniqueValues = []
  
          # Retrieve the rasters and styles
          for timeStampedRaster in timeStampedRasters:
              # Extract variables
              rasterId = timeStampedRaster['rasterId']
  
              if deltaTime:
                  dateTime = timeStampedRaster['dateTime']
                  prevDateTime = dateTime - deltaTime
  
              # Get polygons for each cell in kml format
              statement = '''
                          SELECT x, y, val, ST_AsKML(geom) AS polygon
                          FROM (
                          SELECT (ST_PixelAsPolygons({0})).*
                          FROM {1} WHERE {2}={3}
                          ) AS foo
                          ORDER BY val;
                          '''.format(rasterFieldName, tableName, rasterIdFieldName, rasterId)
  
              result = self._session.execute(statement)
  
              # Set initial group value
              groupValue = -9999999.0
  
              # Add polygons to the kml file with styling
              for row in result:
                  # Value will be None if it is a no data value
                  if row.val:
                      value = float(row.val)
                  else:
                      value = None
  
                  polygonString = row.polygon
                  i = int(row.x)
                  j = int(row.y)
  
                  # Only create placemarks for values that are not no data values
                  if value:
                      if value not in uniqueValues:
                          uniqueValues.append(value)
  
                      # Create a new placemark for each group of values
                      if value != groupValue:
                          placemark = ET.SubElement(document, 'Placemark')
                          placemarkName = ET.SubElement(placemark, 'name')
                          placemarkName.text = str(value)
  
                          # Create style tag and setup styles
                          style = ET.SubElement(placemark, 'Style')
  
                          # Set polygon line style
                          lineStyle = ET.SubElement(style, 'LineStyle')
  
                          # Set polygon line color and width
                          lineColor = ET.SubElement(lineStyle, 'color')
                          lineColor.text = self.LINE_COLOR
                          lineWidth = ET.SubElement(lineStyle, 'width')
                          lineWidth.text = str(self.LINE_WIDTH)
  
                          # Set polygon fill color
                          polyStyle = ET.SubElement(style, 'PolyStyle')
                          polyColor = ET.SubElement(polyStyle, 'color')
  
                          # Convert alpha from 0.0-1.0 decimal to 00-FF string
                          integerAlpha = mappedColorRamp.getAlphaAsInteger()
  
                          # Get RGB color from color ramp and convert to KML hex ABGR string with alpha
                          integerRGB = mappedColorRamp.getColorForValue(value)
                          hexABGR = '%02X%02X%02X%02X' % (integerAlpha,
                                                          integerRGB[mappedColorRamp.B],
                                                          integerRGB[mappedColorRamp.G],
                                                          integerRGB[mappedColorRamp.R])
  
                          # Set the polygon fill alpha and color
                          polyColor.text = hexABGR
  
                          if deltaTime:
                              # Create TimeSpan tag
                              timeSpan = ET.SubElement(placemark, 'TimeSpan')
  
                              # Create begin and end tags
                              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')
  
                          # Create multigeometry tag
                          multigeometry = ET.SubElement(placemark, 'MultiGeometry')
  
                          # Create the data tag
                          extendedData = ET.SubElement(placemark, 'ExtendedData')
  
                          # Add value to data
                          valueData = ET.SubElement(extendedData, 'Data', name='value')
                          valueValue = ET.SubElement(valueData, 'value')
                          valueValue.text = str(value)
  
                          iData = ET.SubElement(extendedData, 'Data', name='i')
                          valueI = ET.SubElement(iData, 'value')
                          valueI.text = str(i)
  
                          jData = ET.SubElement(extendedData, 'Data', name='j')
                          valueJ = ET.SubElement(jData, 'value')
                          valueJ.text = str(j)
  
                          if deltaTime:
                              tData = ET.SubElement(extendedData, 'Data', name='t')
                              valueT = ET.SubElement(tData, 'value')
                              valueT.text = dateTime.strftime('%Y-%m-%dT%H:%M:%S')
  
                          groupValue = value
  
                      # Get polygon object from kml string and append to the current multigeometry group
                      polygon = ET.fromstring(polygonString)
                      multigeometry.append(polygon)
  
          if not discreet:
              # Embed the color ramp in SLD format
              document.append(ET.fromstring(mappedColorRamp.getColorMapAsContinuousSLD()))
          else:
              # Sort the unique values
              uniqueValues.sort()
              document.append(ET.fromstring(mappedColorRamp.getColorMapAsDiscreetSLD(uniqueValues)))
  
          return ET.tostring(kml)