def calculate_monthly_average()

in analysis/webservice/algorithms/TimeSeries.py [0:0]


    def calculate_monthly_average(self, month=None, bounding_polygon_wkt=None, ds=None):

        min_date, max_date = self.get_min_max_date(ds=ds)

        monthly_averages, monthly_counts = [], []
        monthly_mins, monthly_maxes = [], []
        bounding_polygon = shapely.wkt.loads(bounding_polygon_wkt)
        for year in range(min_date.year, max_date.year + 1):
            beginning_of_month = datetime(year, month, 1)
            end_of_month = datetime(year, month, calendar.monthrange(year, month)[1], 23, 59, 59)
            start = (pytz.UTC.localize(beginning_of_month) - EPOCH).total_seconds()
            end = (pytz.UTC.localize(end_of_month) - EPOCH).total_seconds()
            tile_stats = self._get_tile_service().find_tiles_in_polygon(bounding_polygon, ds, start, end,
                                                                  fl=('id,'
                                                                      'tile_avg_val_d,tile_count_i,'
                                                                      'tile_min_val_d,tile_max_val_d,'
                                                                      'tile_min_lat,tile_max_lat,'
                                                                      'tile_min_lon,tile_max_lon'),
                                                                  fetch_data=False)
            if len(tile_stats) == 0:
                continue

            # Split list into tiles on the border of the bounding box and tiles completely inside the bounding box.
            border_tiles, inner_tiles = [], []
            for tile in tile_stats:
                inner_tiles.append(tile) if bounding_polygon.contains(shapely.geometry.box(tile.bbox.min_lon,
                                                                                           tile.bbox.min_lat,
                                                                                           tile.bbox.max_lon,
                                                                                           tile.bbox.max_lat)) else border_tiles.append(
                    tile)

            # We can use the stats of the inner tiles directly
            tile_means = [tile.tile_stats.mean for tile in inner_tiles]
            tile_mins = [tile.tile_stats.min for tile in inner_tiles]
            tile_maxes = [tile.tile_stats.max for tile in inner_tiles]
            tile_counts = [tile.tile_stats.count for tile in inner_tiles]

            # Border tiles need have the data loaded, masked, and stats recalculated
            border_tiles = list(self._get_tile_service().fetch_data_for_tiles(*border_tiles))
            border_tiles = self._get_tile_service().mask_tiles_to_polygon(bounding_polygon, border_tiles)
            for tile in border_tiles:
                tile.update_stats()
                tile_means.append(tile.tile_stats.mean)
                tile_mins.append(tile.tile_stats.min)
                tile_maxes.append(tile.tile_stats.max)
                tile_counts.append(tile.tile_stats.count)

            tile_means = np.array(tile_means)
            tile_mins = np.array(tile_mins)
            tile_maxes = np.array(tile_maxes)
            tile_counts = np.array(tile_counts)

            sum_tile_counts = np.sum(tile_counts) * 1.0

            monthly_averages += [np.average(tile_means, None, tile_counts / sum_tile_counts).item()]
            monthly_mins += [np.average(tile_mins, None, tile_counts / sum_tile_counts).item()]
            monthly_maxes += [np.average(tile_maxes, None, tile_counts / sum_tile_counts).item()]
            monthly_counts += [sum_tile_counts]

        count_sum = np.sum(monthly_counts) * 1.0
        weights = np.array(monthly_counts) / count_sum

        return np.average(monthly_averages, None, weights).item(), \
               np.average(monthly_averages, None, weights).item(), \
               np.average(monthly_averages, None, weights).item()