Example #1
0
    def tiles(self):
        """
        Generator that yields an algebra-ready data dictionary for each tile in
        the aggregator's tile range.
        """
        # Check if any tiles have been matched
        if not self.tilerange:
            return

        algebra_parser = RasterAlgebraParser()

        for tilex in range(self.tilerange[0], self.tilerange[2] + 1):
            for tiley in range(self.tilerange[1], self.tilerange[3] + 1):

                # Prepare a data dictionary with named tiles for algebra evaluation
                data = {}
                for name, layerid in self.layer_dict.items():
                    tile = get_raster_tile(layerid, self.zoom, tilex, tiley)
                    if tile:
                        data[name] = tile
                    else:
                        break

                # Ignore this tile if it is missing in any of the input layers
                if len(data) < len(self.layer_dict):
                    continue

                # Compute raster algebra
                result = algebra_parser.evaluate_raster_algebra(
                    data, self.formula)

                # Convert band data to masked array
                result_data = numpy.ma.masked_values(
                    result.bands[0].data(),
                    result.bands[0].nodata_value,
                )

                # Apply rasterized geometry as mask if clip geometry was provided
                if self.geom:
                    result_data = self.mask_by_geom(result, result_data)

                yield result_data.compressed()
Example #2
0
    def tiles(self):
        """
        Generator that yields an algebra-ready data dictionary for each tile in
        the aggregator's tile range.
        """
        # Check if any tiles have been matched
        if not self.tilerange:
            return

        algebra_parser = RasterAlgebraParser()

        for tilex in range(self.tilerange[0], self.tilerange[2] + 1):
            for tiley in range(self.tilerange[1], self.tilerange[3] + 1):

                # Prepare a data dictionary with named tiles for algebra evaluation
                data = {}
                for name, layerid in self.layer_dict.items():
                    tile = get_raster_tile(layerid, self.zoom, tilex, tiley)
                    if tile:
                        data[name] = tile
                    else:
                        break

                # Ignore this tile if it is missing in any of the input layers
                if len(data) < len(self.layer_dict):
                    continue

                # Compute raster algebra
                result = algebra_parser.evaluate_raster_algebra(data, self.formula)

                # Convert band data to masked array
                result_data = numpy.ma.masked_values(
                    result.bands[0].data(),
                    result.bands[0].nodata_value,
                )

                # Apply rasterized geometry as mask if clip geometry was provided
                if self.geom:
                    result_data = self.mask_by_geom(result, result_data)

                yield result_data.compressed()
Example #3
0
    def get_tile(self, layer_id, zlevel=None):
        """
        Returns a tile for rendering. If the tile does not exists, higher
        level tiles are searched and warped to lower level if found.
        """
        if self.is_pixel_request:
            tilez = self.max_zoom
            # Derive the tile index from the input coordinates.
            xcoord = float(self.kwargs.get('xcoord'))
            ycoord = float(self.kwargs.get('ycoord'))
            bbox = [xcoord, ycoord, xcoord, ycoord]
            indexrange = tile_index_range(bbox, tilez)
            tilex = indexrange[0]
            tiley = indexrange[1]
        else:
            # Get tile indices from the request url parameters.
            tilez = int(self.kwargs.get('z'))
            tilex = int(self.kwargs.get('x'))
            tiley = int(self.kwargs.get('y'))

        return get_raster_tile(layer_id, tilez, tilex, tiley)
Example #4
0
 def get(self, request):
     # Initiate algebra parser
     parser = RasterAlgebraParser()
     # Get formula from request
     formula = request.GET.get('formula')
     # Get id list from request
     ids = self.get_ids()
     # Compute tile index range
     zoom, xmin, ymin, xmax, ymax = self.get_tile_range()
     # Check maximum size of target raster in pixels
     max_pixels = getattr(settings, 'RASTER_EXPORT_MAX_PIXELS', EXPORT_MAX_PIXELS)
     if WEB_MERCATOR_TILESIZE * (xmax - xmin) * WEB_MERCATOR_TILESIZE * (ymax - ymin) > max_pixels:
         raise RasterAlgebraException('Export raster too large.')
     # Construct an empty raster with the output dimensions
     result_raster = self.construct_raster(zoom, xmin, xmax, ymin, ymax)
     target = result_raster.bands[0]
     # Get raster data as 1D arrays and store in dict that can be used
     # for formula evaluation.
     for xindex, x in enumerate(range(xmin, xmax + 1)):
         for yindex, y in enumerate(range(ymin, ymax + 1)):
             data = {}
             for name, layerid in ids.items():
                 tile = get_raster_tile(layerid, zoom, x, y)
                 if tile:
                     data[name] = tile
             # Ignore this tile if data is not found for all layers
             if len(data) != len(ids):
                 continue
             # Evaluate raster algebra expression, return 400 if not successful
             try:
                 # Evaluate raster algebra expression
                 tile_result = parser.evaluate_raster_algebra(data, formula)
             except:
                 raise RasterAlgebraException('Failed to evaluate raster algebra.')
             # Update nodata value on target
             target.nodata_value = tile_result.bands[0].nodata_value
             # Update results raster with algebra
             target.data(
                 data=tile_result.bands[0].data(),
                 size=(WEB_MERCATOR_TILESIZE, WEB_MERCATOR_TILESIZE),
                 offset=(xindex * WEB_MERCATOR_TILESIZE, yindex * WEB_MERCATOR_TILESIZE),
             )
     # Create filename base with datetime stamp
     filename_base = 'algebra_export'
     # Add name slug to filename if provided
     if request.GET.get('filename', ''):
         # Sluggify name
         slug = slugify(request.GET.get('filename'))
         # Remove all unwanted characters
         slug = "".join([c for c in slug if re.match(r'\w|\-', c)])
         # Limit length of custom name slug
         slug = slug[:MAX_EXPORT_NAME_LENGTH]
         # Add name slug to filename base
         filename_base += '_' + slug
     filename_base += '_{0}'.format(datetime.now().strftime('%Y_%m_%d_%H_%M'))
     # Compress resulting raster file into a zip archive
     raster_workdir = getattr(settings, 'RASTER_WORKDIR', None)
     dest = NamedTemporaryFile(dir=raster_workdir, suffix='.zip')
     dest_zip = zipfile.ZipFile(dest.name, 'w', allowZip64=True)
     dest_zip.write(
         filename=self.exportfile.name,
         arcname=filename_base + '.tif',
         compress_type=zipfile.ZIP_DEFLATED,
     )
     # Write README.txt and COLORMAP.txt files to zip file
     self.write_readme(dest_zip)
     self.write_colormap(dest_zip)
     # Close zip file before returning
     dest_zip.close()
     # Create file based response containing zip file and return for download
     response = FileResponse(
         open(dest.name, 'rb'),
         content_type='application/zip'
     )
     response['Content-Disposition'] = 'attachment; filename="{0}"'.format(filename_base + '.zip')
     return response
Example #5
0
 def get_raster_tile(self, layerid, zoom, tilex, tiley):
     return get_raster_tile(layerid, zoom, tilex, tiley)