Quantcast
Channel: Active questions tagged raster-calculator - Geographic Information Systems Stack Exchange
Viewing all articles
Browse latest Browse all 191

Large in-memory raster calculations in PyQGIS

$
0
0

My workflow in a nutshell: I create cost rasters from starting points along a street network (grass7:r.cost), reclassify them according to their distance values (gdal:rastercalculator) and would like to add up all resulting rasters.

After trying to add up all at once I decided to iterate over, which also needs to happen in memory. However I just fail to make it work. The Input does not get accepted no matter if I use QgsRasterLayer or the direct output of the gdal calculation. Those are definitely valid.

    def process_layer(layer, output_prefix, sum_raster):        heat_columns = ['0_100', '100_200', '200_300', '300_400']        featurecounter = 0        for feature in layer.getFeatures():            point_id = feature.id()            point_geom = feature.geometry()            feedback.pushInfo(f"Processing Point ID: {point_id}, Geometry: {point_geom.asWkt()}")            coords = point_geom.asPoint()            x, y = coords.x(), coords.y()            params = {'input': result['output'],'-k': False,'-n': False,'start_coordinates': f"{x},{y}",'max_cost': 400,'null_cost': None,'output': 'TEMPORARY_OUTPUT','nearest': 'TEMPORARY_OUTPUT','outdir': 'TEMPORARY_OUTPUT','GRASS_REGION_CELLSIZE_PARAMETER': 1,'GRASS_RASTER_FORMAT_OPT': '','GRASS_RASTER_FORMAT_META': '','GRASS_SNAP_TOLERANCE_PARAMETER': -1,'GRASS_MIN_AREA_PARAMETER': 0.0001            }            cost_grid_result = processing.run('grass7:r.cost', params)            if cost_grid_result and 'output' in cost_grid_result:                cost_grid_raster = cost_grid_result['output']            else:                feedback.reportError(f"Failed to create cost raster for Point ID: {point_id}")            # Retrieving heat values            point_heat_values = [                [column, feature[column]] if column in feature.fields().names() else [column, None]                for column in heat_columns            ]            # Calculating raster based on heat values            for key, value in point_heat_values:                if value is None:  # Skip if value is None                    continue                a_key = key[:key.find("_")]                b_key = key[key.find("_") + 1:]                intvalue = int(value)                try:                    expression = f'((A > {a_key}) * (A <= {b_key}) * {intvalue}) + ((A <= {a_key}) + (A > {b_key})) * 0'                    params = {'FORMULA': expression,'INPUT_A': cost_grid_raster,'BAND_A': 1,'RTYPE': 1,'OUTPUT': f"memory:recalculated_raster_{point_id}_{key}_{value}"                    }                    recalculated_result = processing.run('gdal:rastercalculator', params)                    recalculated_raster = recalculated_result['OUTPUT']                    # SUMMING UP RASTERS ----------                    if sum_raster is not None:                        #feedback.pushInfo(str(sum_raster))                        #feedback.pushInfo(str(type(sum_raster)))                        #sum_raster_layer = QgsRasterLayer(sum_raster)                        #feedback.pushInfo(str(recalculated_raster))                        #feedback.pushInfo(str(type(recalculated_raster)))                        #recalculated_raster_layer = QgsRasterLayer(recalculated_raster)                        params = {'EXPRESSION': 'A + B','LAYERS': [sum_raster, recalculated_raster],'BANDS': [1, 1],'OUTPUT': 'memory:sum_result'                        }                        feedback.pushInfo(f"Params: {params}")                        try:                            sum_result = processing.run('native:virtualrastercalc', params)                            sum_raster = sum_result['OUTPUT']                        except Exception as e:                            feedback.reportError(f"Exception occurred during sum_raster calculation: {str(e)}")                    else:                        sum_raster = recalculated_raster                except Exception as e:                    feedback.reportError(f"Exception occurred: {str(e)}")                    break  # Exit the loop on failure        return sum_raster    # EXECUTING FUNCTION ----------    sum_raster = None    for layer_name in plugin_updated_list:        layer = results[layer_name]        output_prefix = layer.name()        sum_raster = process_layer(layer, output_prefix, sum_raster)

The Printout:

Processing Point ID: 3, Geometry: Point (459746.35000097844749689 5593918.35010033473372459)Creating cost grid for layer: amenity_updated, Point ID: 3, Max Reach: 400Cost raster generated: C:\Users\raven.schmidt\AppData\Local\Temp\processing_kBndzj\d012bd6872844b53b296c3601f226a26\output.ncCost raster created for Point ID: 3Heat values for point: [['0_100', 25.0], ['100_200', 10.0], ['200_300', 5.0], ['300_400', 1.0]]Processing heat value: Key: 0_100, Value: 25Recalculating raster amenity_updated 3_0_100_25.0Summing with existing sum_raster using native:virtualrastercalc<QgsRasterLayer: 'A + B' (virtualraster)><class 'qgis._core.QgsRasterLayer'>memory:recalculated_raster_3_0_100_25.0<class 'str'>Params: {'EXPRESSION': 'A + B', 'LAYERS': [<QgsRasterLayer: 'A + B' (virtualraster)>, 'memory:recalculated_raster_3_0_100_25.0'], 'BANDS': [1, 1], 'OUTPUT': 'memory:sum_result'}successfull addition

The result's properties:

result properties

more of that

All rasters have the same CRS, extent and cell size.QGIS Version is 3.34.11 LTR

Also, assuming I get this fixed, I would like to replace the gdal and grass algorithms with native:virtualrastercalc so I can do everything in memory. For those I used gdal/grass for the same reason, that native:... just didn't accept my input values.


Viewing all articles
Browse latest Browse all 191

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>