Example #1
0
    def processAlgorithm(self, parameters, context, feedback):
        crs = self.parameterAsCrs(parameters, self.TARGET_CRS, context)
        extent = self.parameterAsExtent(parameters, self.EXTENT, context, crs)
        value = self.parameterAsDouble(parameters, self.NUMBER, context)
        pixelSize = self.parameterAsDouble(parameters, self.PIXEL_SIZE, context)

        outputFile = self.parameterAsOutputLayer(parameters, self.OUTPUT, context)
        outputFormat = QgsRasterFileWriter.driverForExtension(os.path.splitext(outputFile)[1])

        rows = max([math.ceil(extent.height() / pixelSize) + 1, 1.0])
        cols = max([math.ceil(extent.width() / pixelSize) + 1, 1.0])

        writer = QgsRasterFileWriter(outputFile)
        writer.setOutputProviderKey('gdal')
        writer.setOutputFormat(outputFormat)
        provider = writer.createOneBandRaster(Qgis.Float32, cols, rows, extent, crs)
        provider.setNoDataValue(1, -9999)

        data = [value] * cols
        block = QgsRasterBlock(Qgis.Float32, cols, 1)
        block.setData(struct.pack('{}f'.format(len(data)), *data))

        total = 100.0 / rows if rows else 0
        for i in range(rows):
            if feedback.isCanceled():
                break

            provider.writeBlock(block, 1, 0, i)
            feedback.setProgress(int(i * rows))

        provider.setEditable(False)

        return {self.OUTPUT: outputFile}
Example #2
0
    def processAlgorithm(self, parameters, context, feedback):
        crs = self.parameterAsCrs(parameters, self.TARGET_CRS, context)
        extent = self.parameterAsExtent(parameters, self.EXTENT, context, crs)
        value = self.parameterAsDouble(parameters, self.NUMBER, context)
        pixelSize = self.parameterAsDouble(parameters, self.PIXEL_SIZE, context)

        outputFile = self.parameterAsOutputLayer(parameters, self.OUTPUT, context)
        outputFormat = QgsRasterFileWriter.driverForExtension(os.path.splitext(outputFile)[1])

        rows = max([math.ceil(extent.height() / pixelSize) + 1, 1.0])
        cols = max([math.ceil(extent.width() / pixelSize) + 1, 1.0])

        writer = QgsRasterFileWriter(outputFile)
        writer.setOutputProviderKey('gdal')
        writer.setOutputFormat(outputFormat)
        provider = writer.createOneBandRaster(Qgis.Float32, cols, rows, extent, crs)
        provider.setNoDataValue(1, -9999)

        data = [value] * cols
        block = QgsRasterBlock(Qgis.Float32, cols, 1)
        block.setData(struct.pack('{}f'.format(len(data)), *data))

        total = 100.0 / rows if rows else 0
        for i in range(rows):
            if feedback.isCanceled():
                break

            provider.writeBlock(block, 1, 0, i)
            feedback.setProgress(int(i * rows))

        provider.setEditable(False)

        return {self.OUTPUT: outputFile}
Example #3
0
    def change_cell_value(self, vals, x=None, y=None):
        """Save new bands values to data provider"""

        if not self.rdp.isEditable():
            success = self.rdp.setEditable(True)
            if not success:
                self.uc.show_warn('QGIS can\'t modify this type of raster')
                return

        if not x:
            x = self.px
            y = self.py

        for nr in range(1, min(4, self.band_count + 1)):
            rblock = QgsRasterBlock(self.bands[nr]['qtype'], 1, 1)
            rblock.setValue(0, 0, vals[nr - 1])
            success = self.rdp.writeBlock(rblock, nr, x, y)
            if not success:
                self.uc.show_warn('QGIS can\'t modify this type of raster')
                return

        self.rdp.setEditable(False)
        self.raster.triggerRepaint()

        # prepare raster for next actions
        self.prepare_raster(True)
        self.check_undo_redo_btns()
Example #4
0
    def edit_pixel(self, point, new_value=None, check_bounds=True, inside_geom=None):
        if check_bounds and not self.check_point_inside_layer(point):
            return

        if new_value is None:
            old_value, new_value = self.get_the_old_new_pixel_value(point)
            if new_value is None:
                return
        else:
            old_value = self.get_pixel_value_from_pnt(point)

        if inside_geom and not inside_geom.contains(QgsGeometry.fromPointXY(point)):
            return

        px = int((point.x() - self.bounds[0]) / self.qgs_layer.rasterUnitsPerPixelX())  # num column position in x
        py = int((self.bounds[3] - point.y()) / self.qgs_layer.rasterUnitsPerPixelY())  # num row position in y

        rblock = QgsRasterBlock(self.data_provider.dataType(self.band), 1, 1)
        rblock.setValue(0, 0, new_value)
        if self.data_provider.writeBlock(rblock, self.band, px, py):  # write and check if writing status is ok
            return point, old_value
Example #5
0
    def processAlgorithm(self, parameters, context, feedback):
        inp_rast = self.parameterAsRasterLayer(parameters, self.INPUT, context)

        grib_filename = self.parameterAsString(parameters, self.OUTPUT,
                                               context)
        if not grib_filename:
            raise QgsProcessingException(
                self.tr('You need to specify output filename.'))

        idp = inp_rast.dataProvider()
        map_settings = iface.mapCanvas().mapSettings()
        crs = map_settings.destinationCrs()
        outputFormat = QgsRasterFileWriter.driverForExtension('.tif')

        height = inp_rast.height()
        width = inp_rast.width()
        inp_block = idp.block(1, idp.extent(), width, height)

        rfw = QgsRasterFileWriter(grib_filename + '.tif')
        rfw.setOutputProviderKey('gdal')
        rfw.setOutputFormat(outputFormat)
        rdp = rfw.createMultiBandRaster(Qgis.Float32, width, height,
                                        idp.extent(), crs, 2)

        rdp.setEditable(True)
        x_block = QgsRasterBlock(Qgis.Float32, width, height)
        y_block = QgsRasterBlock(Qgis.Float32, width, height)
        diag = 1. / sqrt(2)

        # resulting raster has no NODATA value set, which
        # is not treated correctly in MDAL 0.2.0. See
        # see https://github.com/lutraconsulting/MDAL/issues/104
        # therefore set some small value to overcome the issue
        dir_map = {
            0: (1e-7, 1),
            1: (diag, diag),
            2: (1, 1e-7),
            3: (diag, -diag),
            4: (1e-7, -1),
            5: (-diag, -diag),
            6: (-1, 1e-7),
            7: (-diag, diag),
            255: (0, 0)
        }
        for row in range(height):
            for col in range(width):
                dir_ind = inp_block.value(row, col)
                try:
                    x_val, y_val = dir_map.get(dir_ind, 255)
                except TypeError:
                    x_val, y_val = (0, 0)
                x_block.setValue(row, col, x_val)
                y_block.setValue(row, col, y_val)

        rdp.writeBlock(x_block, 1)
        rdp.writeBlock(y_block, 2)
        rdp.setNoDataValue(1, inp_block.noDataValue())
        rdp.setNoDataValue(2, inp_block.noDataValue())
        rdp.setEditable(False)

        # rewrite the resulting raster as GRIB using GDAL for setting metadata
        res_tif = gdal.Open(grib_filename + '.tif')
        grib_driver = gdal.GetDriverByName('GRIB')
        grib = grib_driver.CreateCopy(grib_filename, res_tif)
        band_names = ('x-flow', 'y-flow')
        for i in range(2):
            band_nr = i + 1
            band_name = band_names[i]
            grib_band = grib.GetRasterBand(band_nr)
            grib_band.SetMetadataItem('grib_comment', band_name)
            grib_band.SetNoDataValue(255)
            grib_band.SetDescription(band_name)
            res_tif_band_array = res_tif.GetRasterBand(band_nr).ReadAsArray()
            grib_band.WriteArray(res_tif_band_array)
            feedback.setProgress(band_nr * 50)
        grib = None
        return {self.OUTPUT: grib_filename}
Example #6
0
 def write_block(self, const_values=None, low_pass_filter=False):
     """
     Construct raster block for each band, apply the values and write to file.
     If const_values are given (a list of const values for each band) they are used for each selected cell.
     In other case the memory layer with values calculated for each cell selected will be used.
     Alternatively, selected cells values can be filtered using low-pass 3x3 filter.
     """
     if self.logger:
         vals = f"const values ({const_values})" if const_values else "expression values."
         self.logger.debug(f"Writing blocks with {vals}")
     if not self.provider.isEditable():
         res = self.provider.setEditable(True)
         if not res:
             if self.uc:
                 self.uc.show_warn('QGIS can\'t modify this type of raster')
             return None
     if self.logger:
         self.logger.debug("Calculating block origin coordinates...")
     b_orig_x, b_orig_y = self.index_to_point(self.block_row_min,
                                              self.block_col_min)
     cols = self.block_col_max - self.block_col_min + 1
     rows = self.block_row_max - self.block_row_min + 1
     b_end_x = b_orig_x + cols * self.pixel_size_x
     b_end_y = b_orig_y - rows * self.pixel_size_y
     block_bbox = QgsRectangle(b_orig_x, b_end_y, b_end_x, b_orig_y)
     if self.logger:
         self.logger.debug(f"Block bbox: {block_bbox.toString()}")
         self.logger.debug(
             f"Nr of cells in the block: rows={rows}, cols={cols}")
     old_blocks = []
     new_blocks = []
     cell_values = dict()
     if const_values is None and not low_pass_filter:
         for feat in self.cell_pts_layer.getFeatures():
             cell_values[feat.id()] = feat.attribute(self.exp_field_idx)
     for band_nr in self.active_bands:
         block = self.provider.block(band_nr, block_bbox, cols, rows)
         new_blocks.append(block)
         block_data = block.data().data()
         old_block = QgsRasterBlock(self.data_types[band_nr - 1], cols,
                                    rows)
         old_block.setData(block_data)
         for abs_row, abs_col in self.selected_cells:
             row = abs_row - self.block_row_min
             col = abs_col - self.block_col_min
             if const_values:
                 idx = band_nr - 1 if len(self.active_bands) > 1 else 0
                 new_val = const_values[idx]
             elif low_pass_filter:
                 # the filter is applied for cells inside the block only
                 if block.height() < 3 or block.width() < 3:
                     # the selected block is too small for filtering -> keep the old value
                     new_val = None
                 else:
                     new_val = low_pass_filtered(
                         old_block, row, col,
                         self.nodata_values[band_nr - 1])
             else:
                 # set the expression value
                 feat_id = self.selected_cells_feats[(abs_row, abs_col)]
                 if cell_values[feat_id] is not None:
                     new_val = None if math.isnan(cell_values[feat_id]) or \
                                   cell_values[feat_id] is None else cell_values[feat_id]
                 else:
                     new_val = None
             new_val = old_block.value(row,
                                       col) if new_val is None else new_val
             set_res = block.setValue(row, col, new_val)
             if self.logger:
                 self.logger.debug(
                     f"Setting block value for band {band_nr}, row {row}, col: {col}: {set_res}"
                 )
         old_blocks.append(old_block)
         band_res = self.provider.writeBlock(block, band_nr,
                                             self.block_col_min,
                                             self.block_row_min)
         if self.logger:
             self.logger.debug(
                 f"Writing block for band {band_nr}: {band_res}")
     self.provider.setEditable(False)
     change = RasterChange(self.active_bands, self.block_row_min,
                           self.block_col_min, old_blocks, new_blocks)
     self.raster_changed.emit(change)
     return True
    def processAlgorithm(self, parameters, context, feedback):
        inp_rast = self.parameterAsRasterLayer(parameters, self.INPUT, context)

        grib_filename = self.parameterAsString(parameters, self.OUTPUT, context)
        if not grib_filename:
            raise QgsProcessingException(self.tr('You need to specify output filename.'))

        idp = inp_rast.dataProvider()
        map_settings = iface.mapCanvas().mapSettings()
        crs = map_settings.destinationCrs()
        outputFormat = QgsRasterFileWriter.driverForExtension('.tif')

        height = inp_rast.height()
        width = inp_rast.width()
        inp_block = idp.block(1, idp.extent(), width, height)

        rfw = QgsRasterFileWriter(grib_filename + '.tif')
        rfw.setOutputProviderKey('gdal')
        rfw.setOutputFormat(outputFormat)
        rdp = rfw.createMultiBandRaster(
            Qgis.Float32,
            width,
            height,
            idp.extent(),
            crs,
            2
        )

        rdp.setEditable(True)
        x_block = QgsRasterBlock(Qgis.Float32, width, height)
        y_block = QgsRasterBlock(Qgis.Float32, width, height)
        diag = 1. / sqrt(2)

        # resulting raster has no NODATA value set, which
        # is not treated correctly in MDAL 0.2.0. See
        # see https://github.com/lutraconsulting/MDAL/issues/104
        # therefore set some small value to overcome the issue
        dir_map = {
            0: (1e-7, 1),
            1: (diag, diag),
            2: (1, 1e-7),
            3: (diag, -diag),
            4: (1e-7, -1),
            5: (-diag, -diag),
            6: (-1, 1e-7),
            7: (-diag, diag),
            255: (0, 0)
        }
        for row in range(height):
            for col in range(width):
                dir_ind = inp_block.value(row, col)
                try:
                    x_val, y_val = dir_map.get(dir_ind, 255)
                except TypeError:
                    x_val, y_val = (0, 0)
                x_block.setValue(row, col, x_val)
                y_block.setValue(row, col, y_val)

        rdp.writeBlock(x_block, 1)
        rdp.writeBlock(y_block, 2)
        rdp.setNoDataValue(1, inp_block.noDataValue())
        rdp.setNoDataValue(2, inp_block.noDataValue())
        rdp.setEditable(False)

        # rewrite the resulting raster as GRIB using GDAL for setting metadata
        res_tif = gdal.Open(grib_filename + '.tif')
        grib_driver = gdal.GetDriverByName('GRIB')
        grib = grib_driver.CreateCopy(grib_filename, res_tif)
        band_names = ('x-flow', 'y-flow')
        for i in range(2):
            band_nr = i + 1
            band_name = band_names[i]
            grib_band = grib.GetRasterBand(band_nr)
            grib_band.SetMetadataItem('grib_comment', band_name)
            grib_band.SetNoDataValue(255)
            grib_band.SetDescription(band_name)
            res_tif_band_array = res_tif.GetRasterBand(band_nr).ReadAsArray()
            grib_band.WriteArray(res_tif_band_array)
            feedback.setProgress(band_nr * 50)
        grib = None
        return {self.OUTPUT: grib_filename}
    def processAlgorithm(self, parameters, context, feedback):
        """
        Here is where the processing itself takes place.
        """

        if self.parameterAsRasterLayer(parameters, self.INITIAL_ROAD_NETWORK,
                                       context):
            initial_road_network_raster = self.parameterAsRasterLayer(
                parameters, self.INITIAL_ROAD_NETWORK, context)
        else:
            initial_road_network_raster = None

        basic_distance_cost = self.parameterAsDouble(parameters,
                                                     self.BASIC_DISTANCE_COST,
                                                     context)

        if self.parameterAsRasterLayer(parameters,
                                       self.COARSE_ELEVATION_RASTER, context):
            coarse_elevation_raster = self.parameterAsRasterLayer(
                parameters, self.COARSE_ELEVATION_RASTER, context)
        else:
            coarse_elevation_raster = None

        if self.parameterAsMatrix(parameters, self.COARSE_ELEVATION_COSTS,
                                  context):
            coarse_elevation_costs = self.parameterAsMatrix(
                parameters, self.COARSE_ELEVATION_COSTS, context)
            coarse_elevation_costs = CostRasterCreatorHelper.CollapsedTableToMatrix(
                coarse_elevation_costs, 3)
        else:
            coarse_elevation_costs = None

        if self.parameterAsRasterLayer(parameters, self.FINE_ELEVATION_RASTER,
                                       context):
            fine_elevation_raster = self.parameterAsRasterLayer(
                parameters, self.FINE_ELEVATION_RASTER, context)
        else:
            fine_elevation_raster = None

        if self.parameterAsMatrix(parameters, self.FINE_ELEVATION_COSTS,
                                  context):
            fine_elevation_costs = self.parameterAsMatrix(
                parameters, self.FINE_ELEVATION_COSTS, context)
            fine_elevation_costs = CostRasterCreatorHelper.CollapsedTableToMatrix(
                fine_elevation_costs, 3)
        else:
            fine_elevation_costs = None

        if self.parameterAsRasterLayer(parameters, self.COARSE_WATER_RASTER,
                                       context):
            coarse_water_raster = self.parameterAsRasterLayer(
                parameters, self.COARSE_WATER_RASTER, context)
        else:
            coarse_water_raster = None

        if self.parameterAsDouble(parameters, self.COARSE_WATER_COST, context):
            coarse_water_cost = self.parameterAsDouble(parameters,
                                                       self.COARSE_WATER_COST,
                                                       context)
        else:
            coarse_water_cost = None

        if self.parameterAsRasterLayer(parameters, self.FINE_WATER_RASTER,
                                       context):
            fine_water_raster = self.parameterAsRasterLayer(
                parameters, self.FINE_WATER_RASTER, context)
        else:
            fine_water_raster = None

        if self.parameterAsDouble(parameters, self.FINE_WATER_COST, context):
            fine_water_cost = self.parameterAsDouble(parameters,
                                                     self.FINE_WATER_COST,
                                                     context)
        else:
            fine_water_cost = None

        if self.parameterAsRasterLayer(parameters, self.SOIL_RASTER, context):
            soil_raster = self.parameterAsRasterLayer(parameters,
                                                      self.SOIL_RASTER,
                                                      context)
        else:
            soil_raster = None

        if self.parameterAsRasterLayer(parameters, self.ADDITIONAL_COST_RASTER,
                                       context):
            special_raster = self.parameterAsRasterLayer(
                parameters, self.ADDITIONAL_COST_RASTER, context)
        else:
            special_raster = None

        feedback.pushInfo(self.tr("Checking inputs..."))
        # If source was not found, throw an exception to indicate that the algorithm
        # encountered a fatal error. The exception text can be any string, but in this
        # case we use the pre-built invalidSourceError method to return a standard
        # helper text for when a source cannot be evaluated
        if basic_distance_cost is None or basic_distance_cost == 0:
            raise QgsProcessingException(
                self.invalidSourceError(parameters, self.BASIC_DISTANCE_COST))

        # Now, we check to see if the CRS, extent and resolution of every raster is equal, so that their align properly.
        listOfRastersToCheck = list()
        if initial_road_network_raster is not None:
            listOfRastersToCheck.append(initial_road_network_raster)
        if coarse_elevation_raster is not None:
            listOfRastersToCheck.append(coarse_elevation_raster)
        if fine_elevation_raster is not None:
            listOfRastersToCheck.append(fine_elevation_raster)
        if coarse_water_raster is not None:
            listOfRastersToCheck.append(coarse_water_raster)
        if fine_water_raster is not None:
            listOfRastersToCheck.append(fine_water_raster)
        if soil_raster is not None:
            listOfRastersToCheck.append(soil_raster)
        if special_raster is not None:
            listOfRastersToCheck.append(special_raster)

        if len(listOfRastersToCheck) == 0:
            raise QgsProcessingException(
                self.
                tr("At least one input raster is needed ! Please, input one raster."
                   ))

        # We check that every raster has the same CRS, extent and resolution.
        CostRasterCreatorHelper.CheckRastersCompatibility(listOfRastersToCheck)

        # We also check that the matrix of parameters entered for the coarse elevation costs and fine elevation costs
        # are correct : meaning that there are no holes between the thresholds, and that every lower threshold is lower
        # than the upper threshold.
        if coarse_elevation_costs is not None:
            CostRasterCreatorHelper.CheckThresholds(coarse_elevation_costs,
                                                    "Coarse elevation costs")
        if fine_elevation_costs is not None:
            CostRasterCreatorHelper.CheckThresholds(fine_elevation_costs,
                                                    "Fine elevation costs")

        # Then, we create the raster blocks
        if initial_road_network_raster is not None:
            initial_road_network_raster_block = CostRasterCreatorHelper.get_all_block(
                initial_road_network_raster)
        else:
            initial_road_network_raster_block = None

        if coarse_elevation_raster is not None:
            coarse_elevation_raster_block = CostRasterCreatorHelper.get_all_block(
                coarse_elevation_raster)
        else:
            coarse_elevation_raster_block = None

        if fine_elevation_raster is not None:
            fine_elevation_raster_block = CostRasterCreatorHelper.get_all_block(
                fine_elevation_raster)
        else:
            fine_elevation_raster_block = None

        if coarse_water_raster is not None:
            coarse_water_raster_block = CostRasterCreatorHelper.get_all_block(
                coarse_water_raster)
        else:
            coarse_water_raster_block = None

        if fine_water_raster is not None:
            fine_water_raster_block = CostRasterCreatorHelper.get_all_block(
                fine_water_raster)
        else:
            fine_water_raster_block = None

        if soil_raster is not None:
            soil_raster_block = CostRasterCreatorHelper.get_all_block(
                soil_raster)
        else:
            soil_raster_block = None

        if special_raster is not None:
            special_raster_block = CostRasterCreatorHelper.get_all_block(
                special_raster)
        else:
            special_raster_block = None

        feedback.pushInfo(self.tr("Preparing output..."))
        # We set the output to be ready : It is a QgsDataProvider
        outputFile = self.parameterAsOutputLayer(parameters, self.OUTPUT,
                                                 context)
        outputFormat = QgsRasterFileWriter.driverForExtension(
            os.path.splitext(outputFile)[1])

        crs = listOfRastersToCheck[0].crs()
        extent = listOfRastersToCheck[0].extent()
        rows = max([
            math.ceil(extent.height() /
                      listOfRastersToCheck[0].rasterUnitsPerPixelY()), 1.0
        ])
        cols = max([
            math.ceil(extent.width() /
                      listOfRastersToCheck[0].rasterUnitsPerPixelX()), 1.0
        ])
        # We will need this value for the fine water computation later
        pixelSide = (listOfRastersToCheck[0].rasterUnitsPerPixelY() +
                     listOfRastersToCheck[0].rasterUnitsPerPixelX()) / 2

        writer = QgsRasterFileWriter(outputFile)
        writer.setOutputProviderKey('gdal')
        writer.setOutputFormat(outputFormat)
        provider = writer.createOneBandRaster(Qgis.Float32, cols, rows, extent,
                                              crs)

        if provider is None:
            raise QgsProcessingException(
                self.tr("Could not create raster output: {}").format(
                    outputFile))
        if not provider.isValid():
            raise QgsProcessingException(
                self.tr("Could not create raster output {}").format(
                    outputFile))

        provider.setNoDataValue(1, -9999)

        # We create the data block for the output raster, and we fill it with the values we need
        dataBlock = QgsRasterBlock(Qgis.Float32, cols, rows)
        # i = float(1.0)

        feedback.pushInfo(self.tr("Calculating cost raster..."))
        progress = 0
        feedback.setProgress(0)
        errorMessages = list()
        for y in range(dataBlock.height()):
            for x in range(dataBlock.width()):
                if feedback.isCanceled():
                    raise QgsProcessingException(
                        self.tr("ERROR: Operation was cancelled."))

                    # If there is a road already on this pixel, then the cost is 0.
                if initial_road_network_raster_block is not None and \
                     (initial_road_network_raster_block.value(y,
                                                              x) != 0 and not initial_road_network_raster_block.isNoData(
                         y, x)):
                    finalValue = 0

                # If there is a water body on this pixel, we stop everything :
                # The cost will be the construction of a bridge
                elif coarse_water_raster_block is not None and coarse_water_raster_block.value(
                        y, x) != 0:
                    if coarse_water_cost is not None:
                        finalValue = coarse_water_cost
                    else:
                        raise QgsProcessingException(
                            self.
                            tr("A coarse water raster has been given, but no coarse "
                               +
                               "water cost. Please input a coarse water cost.")
                        )
                    # feedback.pushInfo("Seems like there was a road on this pixel. Final value is " + str(finalValue))

                # Else, if we are not on a road or on a body of water...
                else:
                    # We start with the base cost of crossing the pixel
                    finalValue = basic_distance_cost
                    # feedback.pushInfo("No road on this pixel, we put basic distance cost. Final value is " + str(finalValue))
                    # Then, if we have it, we add the soil cost
                    if soil_raster_block is not None:
                        finalValue += soil_raster_block.value(y, x)
                        # feedback.pushInfo("After soils, final value is " + str(finalValue))
                    if special_raster_block is not None:
                        finalValue += special_raster_block.value(y, x)
                    # Then the coarse elevation value
                    if coarse_elevation_raster_block is not None:
                        additionalValue, errorMessage = CostRasterCreatorHelper.CalculateCoarseElevationCost(
                            y, x, coarse_elevation_raster_block,
                            coarse_elevation_costs, pixelSide)
                        finalValue += additionalValue
                        if errorMessage is not None:
                            errorMessages.append(errorMessage)
                        # feedback.pushInfo("After coarse elevation, final value is " + str(finalValue))
                    # Then the fine water value
                    if fine_water_raster_block is not None:
                        finalValue += CostRasterCreatorHelper.CalculateFineWaterCost(
                            y, x, fine_water_raster_block, fine_water_cost,
                            pixelSide)
                        # feedback.pushInfo("After fine water, final value is " + str(finalValue))
                    # Then, we multiply everything with the fine elevation cost.
                    if fine_elevation_raster_block is not None:
                        finalValue, errorMessage = CostRasterCreatorHelper.CalculateFineElevationCost(
                            y, x, fine_elevation_raster_block,
                            fine_elevation_costs, finalValue)
                        if errorMessage is not None:
                            errorMessages.append(errorMessage)
                        # feedback.pushInfo("After fine elevation, final value is " + str(finalValue))
                dataBlock.setValue(y, x, float(finalValue))

                progress += 1
                feedback.setProgress(
                    100 * (progress /
                           (dataBlock.height() * dataBlock.width())))

        # We write the values in the provider of our files
        provider.writeBlock(dataBlock, 1)

        # We stop the edition of the output raster
        provider.setEditable(False)

        # We display the warning messages about the thresholds
        if len(errorMessages) > 0:
            above = 0
            below = 0
            for errorMessage in errorMessages:
                if errorMessage == "Above":
                    above += 1
                elif errorMessage == "Below":
                    below += 1
            feedback.pushInfo(
                self.
                tr("WARNING : There were " + str(below) +
                   " situations where the value of a pixel was under"
                   " the lowest threshold given as a parameter; and " +
                   str(above) + " when it was above the"
                   " highest. In those cases, the lowest or highest value of the parameter range was used."
                   " To avoid that, please make sure to use thresholds that cover all of the range of values in"
                   " your rasters."))

        # We make the output
        return {self.OUTPUT: outputFile}