Skip to content

Commit

Permalink
Started developing the benchmark model
Browse files Browse the repository at this point in the history
  • Loading branch information
ghislainv committed Jun 4, 2024
1 parent d717be7 commit d9ca9e3
Show file tree
Hide file tree
Showing 8 changed files with 500 additions and 18 deletions.
8 changes: 8 additions & 0 deletions riskmapjnr/benchmark/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
"""Benchmark functions."""

from .download_gadm import download_gadm
from .rasterize_subjurisdictions import rasterize_subjurisdictions
from .vulnerability_classes import vulnerability_classes
from .defrate_per_class import defrate_per_class

# End
169 changes: 169 additions & 0 deletions riskmapjnr/benchmark/defrate_per_class.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
"""Compute deforestation rates per vulnerability class."""

import numpy as np
from osgeo import gdal
import pandas as pd

from ..misc import progress_bar, makeblock


def defrate_per_class(
fcc_file,
vulnerability_file,
time_interval,
period="calibration",
tab_file_defrate="defrate_per_class.csv",
blk_rows=128,
verbose=True):
"""Compute deforestation rates per vulnerability class.
This function computes the historical deforestation rates for each
vulnerability class.
A ``.csv`` file with deforestation rates for each vulnerability
class is created (see ``tab_file_defrate``).
:param fcc_file: Input raster file of forest cover change at three
dates (123). 1: first period deforestation, 2: second period
deforestation, 3: remaining forest at the end of the second
period. No data value must be 0 (zero).
:param vulnerability_file: Input file with vulnerability classes.
:param time_interval: Time interval (in years) for forest cover
change observations.
:param period: Either "calibration" (from t1 to t2), "validation"
(or "confirmation" from t2 to t3), or "historical" (full
historical period from t1 to t3). Default to "calibration".
:param tab_file_defrate: Path to the ``.csv`` output file with
estimates of deforestation rates for each vulnerability class.
:param blk_rows: If > 0, number of rows for computation by block.
:param verbose: Logical. Whether to print messages or not. Default
to ``True``.
"""

# ==============================================================
# Input rasters
# ==============================================================

# Get fcc raster data
fcc_ds = gdal.Open(fcc_file)
fcc_band = fcc_ds.GetRasterBand(1)

# Landscape variables
gt = fcc_ds.GetGeoTransform()
xres = gt[1]
yres = -gt[5]

# Get defor_cat raster data
defor_cat_ds = gdal.Open(vulnerability_file)
defor_cat_band = defor_cat_ds.GetRasterBand(1)

# Make blocks
blockinfo = makeblock(fcc_file, blk_rows=blk_rows)
nblock = blockinfo[0]
nblock_x = blockinfo[1]
x = blockinfo[3]
y = blockinfo[4]
nx = blockinfo[5]
ny = blockinfo[6]

# ==============================================
# Compute deforestation rates per cat
# ==============================================

# Number of deforestation categories
n_cat_max = 30999
cat = [c + 1 for c in range(n_cat_max)]

# Create a table to save the results
data = {"cat": cat, "nfor": 0, "ndefor": 0,
"rate_obs": 0.0, "rate_mod": 0.0}
df = pd.DataFrame(data)

# Loop on blocks of data
for b in range(nblock):
# Progress bar
if verbose:
progress_bar(nblock, b + 1)
# Position
px = b % nblock_x
py = b // nblock_x
# Data
fcc_data = fcc_band.ReadAsArray(x[px], y[py], nx[px], ny[py])
defor_cat_data = defor_cat_band.ReadAsArray(
x[px], y[py], nx[px], ny[py])
# Defor data on period
if period == "calibration":
data_for = defor_cat_data[fcc_data > 0]
data_defor = defor_cat_data[fcc_data == 1]
elif period in ["validation", "confirmation"]:
data_for = defor_cat_data[fcc_data > 1]
data_defor = defor_cat_data[fcc_data == 2]
elif period == "historical":
data_for = defor_cat_data[fcc_data > 0]
data_defor = defor_cat_data[np.isin(fcc_data, [1, 2])]
# nfor_per_cat
cat_for = pd.Categorical(data_for.flatten(), categories=cat)
df["nfor"] += cat_for.value_counts().values
# ndefor_per_cat
cat_defor = pd.Categorical(data_defor.flatten(), categories=cat)
df["ndefor"] += cat_defor.value_counts().values

# Remove classes with no forest
df = df[df["nfor"] != 0]

# Annual deforestation rates per category
df["rate_obs"] = 1 - (1 - df["ndefor"] / df["nfor"]) ** (1 / time_interval)

# Relative spatial deforestation probability from model
df["rate_mod"] = df["rate_obs"]
# df["rate_mod"] = ((df["cat"] - 1) * 999999 / 65534 + 1) * 1e-6
# # Set proba of deforestation to 0 for category 1
# df.loc[df["cat"] == 1, "rate_mod"] = 0

# Correction factor, either ndefor / sum_i p_i
# or theta * nfor / sum_i p_i
sum_ndefor = df["ndefor"].sum()
sum_pi = (df["nfor"] * df["rate_mod"]).sum()
correction_factor = sum_ndefor / sum_pi

# Absolute deforestation probability
df["rate_abs"] = df["rate_mod"] * correction_factor

# Time interval
df["time_interval"] = time_interval

# Pixel area
pixel_area = xres * yres / 10000
df["pixel_area"] = pixel_area

# Deforestation density (ha/pixel/yr)
df["defor_dens"] = df["rate_abs"] * pixel_area / time_interval

# Export the table of results
df.to_csv(tab_file_defrate, sep=",", header=True,
index=False, index_label=False)

# Dereference drivers
del fcc_ds, defor_cat_ds


# # Test
# import os
# os.chdir("/home/ghislain/deforisk/MTQ_2000_2010_2020_jrc_7221/")
# defrate_per_class(
# fcc_file="data/forest/fcc123.tif",
# vulnerability_file="outputs/benchmark_model/vulnerability_classes.tif",
# time_interval=10,
# period="calibration",
# tab_file_defrate="outputs/benchmark_model/defrate_per_class.csv",
# blk_rows=128,
# verbose=True)

# End
28 changes: 28 additions & 0 deletions riskmapjnr/benchmark/download_gadm.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""Download GADM data."""

import os
from urllib.request import urlretrieve


def download_gadm(iso3, output_file):
"""Download GADM data for a country.
Download GADM (Global Administrative Areas) for a specific
country. See `<https://gadm.org>`_\\ .
:param iso3: Country ISO 3166-1 alpha-3 code.
:param output_file: Path to output GPKG file.
"""

# Check for existing file
if not os.path.isfile(output_file):

# Download the file from gadm.org
url = ("https://geodata.ucdavis.edu/gadm/gadm4.1/"
f"gpkg/gadm41_{iso3}.gpkg")
urlretrieve(url, output_file)


# End
69 changes: 69 additions & 0 deletions riskmapjnr/benchmark/rasterize_subjurisdictions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
"""Resterizing subjurisdictions."""

import os

from osgeo import gdal


def rasterize_subjurisdictions(input_file, fcc_file, output_file,
verbose=False):
"""Rasterizing subjurisdictions.
:param input_file: Input GPKG vector file with subjurisdictions.
:param fcc_file: Input fcc file for resolution and extent.
:param output_file: Output raster file with integer id for
subjurisdictions.
:param verbose: Logical. Whether to print messages or not. Default
to ``False``.
"""

# Output dir
out_dir = os.path.dirname(output_file)

# Callback
cback = gdal.TermProgress if verbose else 0

# Raster info: extent, resolution, proj
fcc_ds = gdal.Open(fcc_file, gdal.GA_ReadOnly)
gt = fcc_ds.GetGeoTransform()
xmin = gt[0]
xres = gt[1]
ymax = gt[3]
yres = -gt[5]
xmax = xmin + xres * fcc_ds.RasterXSize
ymin = ymax - yres * fcc_ds.RasterYSize
extent = (xmin, ymin, xmax, ymax)
proj = fcc_ds.GetProjectionRef()

# SQL statement to get id
sql_statement = ("select *, row_number() over () "
"as id from adm_adm_1")

# Rasterize
param = gdal.RasterizeOptions(
outputBounds=extent,
targetAlignedPixels=True,
attribute="id",
outputSRS=proj,
noData=0,
xRes=xres,
yRes=yres,
SQLStatement=sql_statement,
SQLDialect="SQLite",
outputType=gdal.GDT_Byte,
creationOptions=["COMPRESS=DEFLATE", "BIGTIFF=YES"],
callback=cback)
gdal.Rasterize(output_file, input_file, options=param, callback=cback)


# # Test
# import os
# os.chdir("/home/ghislain/deforisk/MTQ_2000_2010_2020_jrc_7221/")
# rasterize_subjurisdictions(
# input_file="data_raw/gadm41_MTQ_0.gpkg",
# fcc_file="data/fcc.tif",
# output_file="outputs/benchmark_model/subj.tif",
# verbose=True)

# End
Loading

0 comments on commit d9ca9e3

Please sign in to comment.