Calculated sum of 2023 monthly net primary production (NPP) from VIIRS data.
Community guidance for developing this website was to provide a single productivity product as a Standard product. For this, we initially chose the original Vertically Generalized Production Model (VGPM) (Behrenfeld and Falkowski, 1997a) as the standard algorithm. The VGPM is a “chlorophyll-based” model that estimate net primary production from chlorophyll using a temperature-dependent description of chlorophyll-specific photosynthetic efficiency. For the VGPM, net primary production is a function of chlorophyll, available light, and the photosynthetic efficiency.
Standard products are based on chlorophyll, temperature and PAR data from SeaWiFS, MODIS and VIIRS satellites, along with estimates of euphotic zone depth from a model developed by Morel and Berthon (1989) and based on chlorophyll concentration.
if (!file.exists(vgpm_tif)) {if(!file.exists(file_tar))download.file(url_tar, file_tar) dir_untar <-path_ext_remove(file_tar)dir.create(dir_untar, showWarnings = F)untar(file_tar, exdir = dir_untar)# Get list of compressed files files_gz <-dir_ls(dir_untar, glob ="*.gz") dir_unzip <-file.path(dir_untar, "unzipped")dir.create(dir_unzip, showWarnings = F)# Unzip all filesfor (file_gz in files_gz) { # file_gz = files_gz[1] file_hdf <-file.path(dir_unzip, sub("\\.gz$", "", basename(file_gz)))if (!file.exists(file_hdf))gunzip(file_gz, destname = file_hdf) }# Get list of unzipped HDF files files_hdf <-dir_ls(dir_unzip, glob ="*.hdf") # length(files_hdf) = 12# Function to read VGPM data from HDF file read_vgpm_hdf <-function(file_hdf) { # file_hdf <- files_hdf[1]# First, query the HDF file to see the subdatasets sds_info <- terra::describe(file_hdf)if (verbose)print(sds_info)tryCatch({ r <- terra::rast(file_hdf, noflip=T)# Standard VGPM product is typically 1/6 degree global grid (-180 to 180, -90 to 90)ext(r) <-c(-180, 180, -90, 90)crs(r) <-"EPSG:4326" r[r==-9999] <-NA# plot(r)return(r) }, error =function(e) {warning("Error reading", file_hdf, ":", e$message, "\n")return(NULL) }) }# Initialize a list to store all monthly rasters monthly_rasters <-list()# Read all monthly filesfor (i inseq_along(files_hdf)) {if (verbose)message("Processing file", i, "of", length(files_hdf), ":", files_hdf[i], "\n") r <-read_vgpm_hdf(files_hdf[i])if (!is.null(r)) { monthly_rasters[[i]] <- r } }# Create a SpatRaster collection from all the monthly rasters s_vgpm <-rast(monthly_rasters) r <-app(s_vgpm, mean, na.rm =TRUE)names(r) <-"npp_daily_avg"writeRaster(r, vgpm_tif, overwrite =TRUE)message(glue("Annual products created and saved. - daily avg for {yr}: {vgpm_tif}"))}r <-rast(vgpm_tif) # |> # rotate(left=F) # -180 to 180 -> 0 to 360# shift(dx = 0.0001) # problem with -180 extentmapView( r, maxpixels =2332800, col.regions =cmocean("algae"), layer.name ="raster: daily avg NPP") |>slot("map") |>addFullscreenControl() |>addControl(tags$div(HTML("units: mg C / m<sup>2</sup> / day")), position ="topright")