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])
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])
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)
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)
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)
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()
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)
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()
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
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)
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
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])
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])
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