Total Biomass Production (TBP)
Total Biomass Production (TBP) is defined as the sum of the above-ground dry matter produced for a given year. TBP is calculated from Net Primary Production (NPP). TBP is expressed in kgDM/ha/day, and has thus different biomass units compared to NPP, with 1 gC/m2/day (NPP) = 22.222 kgDM/ha/day (DMP).
For further information on the methodology read the WaPOR documentation available at: https://bitbucket.org/cioapps/wapor-et-look/wiki/Home
Dataset Overview
- Source: WaPOR L1 v3
- Period of Use: 2018βpresent
- Spatial Resolution: 300m
- Temporal Resolution: Monthly
- Output Format Used in EQIPA: Monthly GeoTIFF
π Data Processing Summary
- Monthly WaPOR L1 v3 NPP (300m) maps have been downloaded from WaPOR.
- Monthly TBP maps are calculated as = Monthly NPP Γ Scale Factor (0.001) Γ Unit Conversion Factor (22.222). See the scale factor for each WaPOR product here: https://data.apps.fao.org/wapor
- Annual TBP maps is computed for all crop years by aggregating monthly TBP maps from June to May, covering crop years 2018-19 to 2022-23.
Download Clipped Monthly NPP Raster, Apply Scale Factor and convert to Monthly TBP
This script downloads monthly WaPOR v3 NPP raster files from FAO's WaPOR Google Cloud Bucket URLs, clips them to the India boundary (using GDAL), and applies a scale factor and unit conversion and produce Monthly TBP Rasters.
π India Boundary file: Link
import os
import numpy as np
import rasterio
from osgeo import gdal
firstyear = 2023
lastyear = 2024
output_folder = "tbp_wapor_v3_monthly_ind"
geojson_boundary = "IndiaBoundary.geojson"
os.makedirs(output_folder, exist_ok=True)
for year in range(firstyear, lastyear + 1):
for month in range(1, 13):
filename = f"WAPOR-3.L1-NPP-M.{year}-{month:02d}.tif"
output_filename = f"wapor_tbp_m_{year}_{month:02d}.tif"
output_path = os.path.join(output_folder, output_filename)
if os.path.exists(output_path):
print(f"β
{output_filename} already exists, skipping...")
continue
url = f"https://gismgr.fao.org/DATA/WAPOR-3/MAPSET/L1-NPP-M/{filename}"
vsicurl_url = f"/vsicurl/{url}"
temp_clip = os.path.join(output_folder, f"temp_{output_filename}")
print(f"Downloading...{filename}")
try:
warp_options = gdal.WarpOptions(
cutlineDSName=geojson_boundary,
cropToCutline=True,
dstNodata=-9999
)
gdal.Warp(destNameOrDestDS=temp_clip, srcDSOrSrcDSTab=vsicurl_url, options=warp_options)
except Exception as e:
print(f"β GDAL warp failed for {filename}: {e}")
continue
try:
with rasterio.open(temp_clip) as src:
profile = src.profile
data = src.read(1)
nodata = src.nodata
data = np.where(data == nodata, -9999, data)
scaled_data = np.where(data != -9999, data * 0.001 * 22.222, -9999)
profile.update(
dtype=rasterio.float32,
nodata=-9999,
compress="LZW"
)
with rasterio.open(output_path, "w", **profile) as dst:
dst.write(scaled_data.astype(rasterio.float32), 1)
os.remove(temp_clip)
print(f"β
Processed and saved: {output_filename}")
except Exception as e:
print(f"β Failed to scale/write {filename}: {e}")
if os.path.exists(temp_clip):
os.remove(temp_clip)