Source code for forestatrisk.validate.map_accuracy

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# ==============================================================================
# author          :Ghislain Vieilledent
# email           :ghislain.vieilledent@cirad.fr, ghislainv@gmail.com
# web             :https://ecology.ghislainv.fr
# python_version  :>=2.7
# license         :GPLv3
# ==============================================================================

# Standard library imports
from __future__ import division, print_function  # Python 3 compatibility

# Third party imports
import numpy as np
from osgeo import gdal

# Local application imports
from ..misc import progress_bar, makeblock


# Percentage_correct
[docs] def map_confmat(r_obs0, r_obs1, r_pred0, r_pred1, blk_rows=0): """Compute a confusion matrix. This function computes a confusion matrix at a given resolution. Number of pixels in each category (0, 1) and in each spatial cell are given by r_obs\\* and r_pred\\* rasters. :param r_obs0: Raster counting the number of 0 for observations. :param r_obs1: Raster counting the number of 1 for observations. :param r_pred0: Raster counting the number of 0 for predictions. :param r_pred1: Raster counting the number of 1 for predictions. :param blk_rows: If > 0, number of lines per block. :return: A numpy array of shape (2,2). """ # Landscape variables from raster of observations obsR = gdal.Open(r_obs0) gt = obsR.GetGeoTransform() ncol_r = obsR.RasterXSize nrow_r = obsR.RasterYSize del obsR Xmin = gt[0] Xmax = gt[0] + gt[1] * ncol_r Ymin = gt[3] + gt[5] * nrow_r Ymax = gt[3] # Raster list raster_list = [r_obs0, r_obs1, r_pred0, r_pred1] # Make vrt with gdal.BuildVRT # Note: Extent and resolution from forest raster! print("Make virtual raster") param = gdal.BuildVRTOptions( resolution="user", outputBounds=(Xmin, Ymin, Xmax, Ymax), xRes=gt[1], yRes=-gt[5], separate=True, ) gdal.BuildVRT("/vsimem/temp.vrt", raster_list, options=param) stack = gdal.Open("/vsimem/temp.vrt") # Make blocks blockinfo = makeblock(r_obs0, blk_rows=blk_rows) nblock = blockinfo[0] nblock_x = blockinfo[1] x = blockinfo[3] y = blockinfo[4] nx = blockinfo[5] ny = blockinfo[6] print("Divide region in {} blocks".format(nblock)) # Confusion matrix conf_mat = np.zeros((2, 2), dtype=int) # Loop on blocks of data for b in range(nblock): # Progress bar progress_bar(nblock, b + 1) # Position in 1D-arrays px = b % nblock_x py = b // nblock_x # Read the data data = stack.ReadAsArray(x[px], y[py], nx[px], ny[py]).astype(np.int32) # Local confusion matrix n00 = np.sum(np.min(data[(0, 2), :, :], axis=0)) n11 = np.sum(np.min(data[(1, 3), :, :], axis=0)) n01 = np.sum(np.maximum(0, data[2, :, :] - data[0, :, :])) n10 = np.sum(np.maximum(0, data[3, :, :] - data[1, :, :])) mat = np.array([n00, n01, n10, n11]).reshape(2, 2) conf_mat += mat # Close stack del stack # Return confusion matrix return conf_mat
# map_accuracy
[docs] def map_accuracy(mat): """Compute accuracy indices from a confusion matrix. Compute Overall Accuracy, Expected Accuracy, Figure of Merit, Specificity, Sensitivity, True Skill Statistics and Cohen's Kappa from a confusion matrix. :param mat: Confusion matrix. Format: [[n00, n01], [n10, n11]] with pred on lines and obs on columns. :return: A dictionnary of accuracy indices. """ # Confusion matrix n00 = mat[0, 0] n01 = mat[0, 1] n10 = mat[1, 0] n11 = mat[1, 1] # Accuracy indices N = n11 + n10 + n00 + n01 OA = (n11 + n00) / N FOM = n00 / (n00 + n10 + n01) Specificity = n11 / (n11 + n01) Sensitivity = n00 / (n00 + n10) TSS = Sensitivity + Specificity - 1 Prob_1and1 = ((n11 + n10) / N) * ((n11 + n01) / N) Prob_0and0 = ((n00 + n01) / N) * ((n00 + n10) / N) EA = Prob_1and1 + Prob_0and0 Kappa = (OA - EA) / (1 - EA) r = { "OA": OA, "EA": EA, "FOM": FOM, "Sen": Sensitivity, "Spe": Specificity, "TSS": TSS, "K": Kappa, } return r
# End