Source code for forestatrisk.validate.map_validation
#!/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 :>=3
# license :GPLv3
# ==============================================================================
# Third party imports
import numpy as np
from osgeo import gdal
import pandas as pd
# Local application imports
from ..misc import progress_bar, makeblock
# map_validation
[docs]
def map_validation(pred, obs, blk_rows=128):
"""Compute accuracy indices based on predicted and observed
forest-cover change (fcc) maps.
Compute the Overall Accuracy, the Figure of Merit, the
Specificity, the Sensitivity, the True Skill Statistics and the
Cohen's Kappa from a confusion matrix built on predictions
vs. observations.
:param pred: Raster of predicted fcc.
:param obs: Raster of observed fcc.
:param blk_rows: If > 0, number of rows for block (else 256x256).
:return: A dictionnary of accuracy indices.
"""
# Load raster and band
predR = gdal.Open(pred)
predB = predR.GetRasterBand(1)
obsR = gdal.Open(obs)
obsB = obsR.GetRasterBand(1)
# Make blocks
blockinfo = makeblock(pred, 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))
# Initialize the confusion matrix
n00 = 0.0
n10 = 0.0
n01 = 0.0
n11 = 0.0
# Compute the confusion matrix
print("Compute the confusion matrix")
# 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
# Data for one block
df_pred = predB.ReadAsArray(x[px], y[py], nx[px], ny[py])
df_pred = 1 - df_pred
df_obs = obsB.ReadAsArray(x[px], y[py], nx[px], ny[py])
df_obs = 1 - df_obs
# Update confusion matrix
n00 = n00 + np.sum((df_pred == 0) & (df_obs == 0))
n10 = n10 + np.sum((df_pred == 1) & (df_obs == 0))
n01 = n01 + np.sum((df_pred == 0) & (df_obs == 1))
n11 = n11 + np.sum((df_pred == 1) & (df_obs == 1))
# Dereference driver
predB = None
del predR
obsB = None
del obsR
# Print confusion matrix
mat = pd.DataFrame(
{
"obs0": pd.Series([n00, n10], index=["pred0", "pred1"]),
"obs1": pd.Series([n01, n11], index=["pred0", "pred1"]),
}
)
print(mat)
# Accuracy indices
print("Compute accuracy indices")
OA = (n11 + n00) / (n11 + n10 + n00 + n01)
FOM = n11 / (n11 + n10 + n01)
Sensitivity = n11 / (n11 + n01)
Specificity = n00 / (n00 + n10)
TSS = Sensitivity + Specificity - 1
N = n11 + n10 + n00 + n01
Observed_accuracy = (n11 + n00) / N
Expected_accuracy = (
(n11 + n10) * ((n11 + n01) / N) + (n00 + n01) * ((n00 + n10) / N)
) / N
Kappa = (Observed_accuracy - Expected_accuracy) / (1 - Expected_accuracy)
r = {
"OA": round(OA, 2),
"FOM": round(FOM, 2),
"Sen": round(Sensitivity, 2),
"Spe": round(Specificity, 2),
"TSS": round(TSS, 2),
"K": round(Kappa, 2),
}
return r
# End