def test_algebra_parser(self):
     parser = RasterAlgebraParser()
     result = parser.evaluate_raster_algebra(self.data,
                                             'x*(x>11) + 2*y + 3*z*(z==30)',
                                             check_aligned=True)
     self.assertEqual(result.bands[0].data().ravel().tolist(),
                      [10, 10, 14, 15])
Example #2
0
 def test_algebra_parser_nodata_none(self):
     if GDAL_VERSION < (2, 1):
         self.skipTest("GDAL >= 2.1 is required for this test.")
     parser = RasterAlgebraParser()
     self.data['z'].bands[0].nodata_value = None
     result = parser.evaluate_raster_algebra({'x': self.data.pop('z')}, 'x')
     self.assertEqual(result.bands[0].data().ravel().tolist(), [30, 31, 32, 33])
Example #3
0
    def get_algebra(self, data, formula):
        parser = RasterAlgebraParser()

        # Evaluate raster algebra expression, return 400 if not successful
        try:
            # Evaluate raster algebra expression
            result = parser.evaluate_raster_algebra(data, formula)
        except:
            raise RasterAlgebraException('Failed to evaluate raster algebra.')

        # Get array from algebra result
        if result.bands[0].nodata_value is None:
            result = result.bands[0].data()
        else:
            result = numpy.ma.masked_values(
                result.bands[0].data(),
                result.bands[0].nodata_value,
            )

        # Get colormap.
        colormap = self.get_colormap()

        # Render tile using the legend data
        img, stats = band_data_to_image(result, colormap)

        # Return rendered image
        return self.write_img_to_response(img, stats)
Example #4
0
 def test_algebra_parser_nodata_none(self):
     if GDAL_VERSION < (2, 1):
         self.skipTest("GDAL >= 2.1 is required for this test.")
     parser = RasterAlgebraParser()
     self.data['z'].bands[0].nodata_value = None
     result = parser.evaluate_raster_algebra({'x': self.data.pop('z')}, 'x')
     self.assertEqual(result.bands[0].data().ravel().tolist(), [30, 31, 32, 33])
Example #5
0
    def get(self, request, *args, **kwargs):
        parser = RasterAlgebraParser()

        # Get layer ids
        ids = self.get_ids()

        # Get raster data as 1D arrays and store in dict that can be used
        # for formula evaluation.
        data = {}
        for name, layerid in ids.items():
            tile = self.get_tile(layerid)
            if tile:
                data[name] = tile
            else:
                # Create empty image if any layer misses the required tile
                img = Image.new("RGBA", (WEB_MERCATOR_TILESIZE, WEB_MERCATOR_TILESIZE), (0, 0, 0, 0))
                return self.write_img_to_response(img, {})

        # Get formula from request
        formula = request.GET.get('formula')

        # Evaluate raster algebra expression, return 400 if not successful
        try:
            # Evaluate raster algebra expression
            result = parser.evaluate_raster_algebra(data, formula)
        except:
            raise RasterAlgebraException('Failed to evaluate raster algebra.')

        # Get array from algebra result
        result = numpy.ma.masked_values(
            result.bands[0].data(),
            result.bands[0].nodata_value,
        )

        # Render tile
        colormap = self.get_colormap()
        if colormap:
            # Render tile using the legend data
            img, stats = band_data_to_image(result, colormap)
        else:
            # Scale to grayscale rgb (can be colorscheme later on)
            result = result.astype('float').ravel()
            result = 255 * (result - numpy.min(result)) / (numpy.max(result) - numpy.min(result))

            # Create rgba matrix from grayscale array
            result = numpy.array((result, result, result, numpy.repeat(255, len(result)))).T
            rgba = result.reshape(WEB_MERCATOR_TILESIZE, WEB_MERCATOR_TILESIZE, 4).astype('uint8')

            # Create image from array
            img = Image.fromarray(rgba)
            stats = {}

        # Return rendered image
        return self.write_img_to_response(img, stats)
Example #6
0
def RasterAlgebra(cr1, cr2, cr3, poids):
    """ les noms sont les noms des critères choisis par l'utilisateur"""

    # rast1 = RasterData.objects.get(name=name1)
    # rast2 = RasterData.objects.get(name=name2)
    # rast3 = RasterData.objects.get(name=name3)

    rast1 = cr1
    rast2 = cr2
    rast3 = cr3

    # #Valeurs fournies l'utilisateur
    # c1, c2, c3 = 3, 5, 7

    # # Poids des critères
    # poids = RatingCriterion(c1, c2, c3)

    # Pondération de cha
    parser = RasterAlgebraParser()
    d1 = dict(zip(['x'], [rast1.raster50]))
    d2 = dict(zip(['x'], [rast2.raster50]))
    d3 = dict(zip(['x'], [rast3.raster50]))

    f1 = "{}*x".format(poids[0])
    f2 = "{}*x".format(poids[1])
    f3 = "{}*x".format(poids[2])

    rast1_pondere = parser.evaluate_raster_algebra(d1, f1)
    rast2_pondere = parser.evaluate_raster_algebra(d2, f2)
    rast3_pondere = parser.evaluate_raster_algebra(d3, f3)

    data = dict(
        zip(['x', 'y', 'z'], [rast1.raster50, rast2.raster50, rast3.raster50]))

    formula = "{}*x + {}*y + {}*z".format(poids[0], poids[1], poids[2])
    rst = parser.evaluate_raster_algebra(data, formula)
    # Enregistrement du resultat
    # dbrest = Result(raster = rst)
    # dbrest.save()
    rasters = [rast1_pondere, rast2_pondere, rast3_pondere, rst]
    return rasters
Example #7
0
    def get_algebra(self, data, formula):
        parser = RasterAlgebraParser()

        # Evaluate raster algebra expression, return 400 if not successful
        try:
            # Evaluate raster algebra expression
            result = parser.evaluate_raster_algebra(data, formula)
        except:
            raise RasterAlgebraException('Failed to evaluate raster algebra.')

        # For pixel value requests, return result as json.
        if self.is_pixel_request:
            xcoord = float(self.kwargs.get('xcoord'))
            ycoord = float(self.kwargs.get('ycoord'))
            val = pixel_value_from_point(result, [xcoord, ycoord])
            return HttpResponse(
                json.dumps({
                    'x': xcoord,
                    'y': ycoord,
                    'value': val
                }),
                content_type='application/json',
            )

        # For tif requests, skip colormap and return georeferenced tif file.
        if self.kwargs.get('frmt') == 'tif':
            vsi_path = os.path.join(VSI_FILESYSTEM_BASE_PATH,
                                    str(uuid.uuid4()))
            rast = result.warp({
                'name': vsi_path,
                'driver': 'tif',
                'compress': 'DEFLATE',
            })
            content_type = IMG_FORMATS['tif'][1]
            return HttpResponse(rast.vsi_buffer, content_type)

        # Get array from algebra result
        if result.bands[0].nodata_value is None:
            result = result.bands[0].data()
        else:
            result = numpy.ma.masked_values(
                result.bands[0].data(),
                result.bands[0].nodata_value,
            )

        # Get colormap.
        colormap = self.get_colormap()

        # Render tile using the legend data
        img, stats = band_data_to_image(result, colormap)

        # Return rendered image
        return self.write_img_to_response(img, stats)
Example #8
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 = self.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 #9
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 #10
0
    def get_algebra(self, data, formula):
        parser = RasterAlgebraParser()

        # Evaluate raster algebra expression, return 400 if not successful
        try:
            # Evaluate raster algebra expression
            result = parser.evaluate_raster_algebra(data, formula)
        except:
            raise RasterAlgebraException('Failed to evaluate raster algebra.')

        # For pixel value requests, return result as json.
        if self.is_pixel_request:
            xcoord = float(self.kwargs.get('xcoord'))
            ycoord = float(self.kwargs.get('ycoord'))
            val = pixel_value_from_point(result, [xcoord, ycoord])
            return HttpResponse(
                json.dumps({
                    'x': xcoord,
                    'y': ycoord,
                    'value': val
                }),
                content_type='application/json',
            )

        # Get array from algebra result
        if result.bands[0].nodata_value is None:
            result = result.bands[0].data()
        else:
            result = numpy.ma.masked_values(
                result.bands[0].data(),
                result.bands[0].nodata_value,
            )

        # Get colormap.
        colormap = self.get_colormap()

        # Render tile using the legend data
        img, stats = band_data_to_image(result, colormap)

        # Return rendered image
        return self.write_img_to_response(img, stats)
Example #11
0
    def get_algebra(self, data, formula):
        parser = RasterAlgebraParser()

        # Evaluate raster algebra expression, return 400 if not successful
        try:
            # Evaluate raster algebra expression
            result = parser.evaluate_raster_algebra(data, formula)
        except:
            raise RasterAlgebraException('Failed to evaluate raster algebra.')

        # Get array from algebra result
        result = numpy.ma.masked_values(
            result.bands[0].data(),
            result.bands[0].nodata_value,
        )

        # Render tile
        colormap = self.get_colormap()
        if colormap:
            # Render tile using the legend data
            img, stats = band_data_to_image(result, colormap)
        else:
            # Scale to grayscale rgb (can be colorscheme later on)
            result = result.astype('float').ravel()
            result = 255 * (result - numpy.min(result)) / (numpy.max(result) -
                                                           numpy.min(result))

            # Create rgba matrix from grayscale array
            result = numpy.array(
                (result, result, result, numpy.repeat(255, len(result)))).T
            rgba = result.reshape(WEB_MERCATOR_TILESIZE, WEB_MERCATOR_TILESIZE,
                                  4).astype('uint8')

            # Create image from array
            img = Image.fromarray(rgba)
            stats = {}

        # Return rendered image
        return self.write_img_to_response(img, stats)
Example #12
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 #13
0
 def test_algebra_parser_nodata_propagation(self):
     parser = RasterAlgebraParser()
     result = parser.evaluate_raster_algebra(self.data, 'x * (z != NULL) + 99 * (z == NULL)')
     self.assertEqual(result.bands[0].data().ravel().tolist(), [10, 99, 12, 13])
Example #14
0
 def test_algebra_parser_same_raster_twice(self):
     parser = RasterAlgebraParser()
     result = parser.evaluate_raster_algebra(self.data2, 'x + y')
     self.assertEqual(result.bands[0].data().ravel().tolist(), [10, 32, 34, 36])
Example #15
0
 def test_algebra_parser_same_raster_twice(self):
     parser = RasterAlgebraParser()
     result = parser.evaluate_raster_algebra(self.data2, 'x + y')
     self.assertEqual(result.bands[0].data().ravel().tolist(), [10, 32, 34, 36])
Example #16
0
 def test_algebra_parser_nodata_propagation(self):
     parser = RasterAlgebraParser()
     result = parser.evaluate_raster_algebra(self.data, 'x * (z != NULL) + 99 * (z == NULL)')
     self.assertEqual(result.bands[0].data().ravel().tolist(), [10, 99, 12, 13])
Example #17
0
 def test_algebra_parser(self):
     parser = RasterAlgebraParser()
     result = parser.evaluate_raster_algebra(self.data, 'x*(x>11) + 2*y + 3*z*(z==30)', check_aligned=True)
     self.assertEqual(result.bands[0].data().ravel().tolist(), [10, 10, 14, 15])
Example #18
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
     if WEB_MERCATOR_TILESIZE * (xmax - xmin) * WEB_MERCATOR_TILESIZE * (ymax - ymin) > EXPORT_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