MODIS fire
R-bloggers 2025-11-16
[This article was first published on r.iresmi.net, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
Day 15 of 30DayMapChallenge: « Fire » (previously).
An animation of global fires in 2024 using MODIS data.
library(dggridR)library(dplyr)library(readr)library(ggplot2)library(purrr)library(sf)library(rnaturalearth)library(glue)library(classInt)
Data
See the docs. You can use a client like Filezilla to download the data.
- SFTP:
fuoco.geog.umd.edu - Login / Password (as of time of writing):
fire/burnt
Get all year 2024 files available in /data/MODIS/C61/MCD14ML.
We’ll use binning on a 250 km discrete global grid.
# countries backgroundworld <- ne_countries(scale = 10) |> st_make_valid() |> st_wrap_dateline()# build the griddggs <- dgconstruct(spacing = 250) hex <- dggs |> dgshptogrid(world, cellsize = 0.5) |> st_make_valid() |> st_wrap_dateline() |> st_filter(world) |> select(seqnum)# read all MODIS files and find their grid cell IDmodis <- dir("~/data/modis/", full.names = TRUE) |> read_fwf( skip = 1, col_types = cols("YYYYMMDD" = col_date(format = "%Y%m%d")), fwf_positions( c(1, 10, 15, 17, 26, 36, 42, 48, 53, 61, 65, 68), c(9, 14, 16, 25, 35, 41, 47, 52, 60, 64, 67, 69), c("YYYYMMDD", "HHMM", "sat", "lat", "lon", "T21", "T31", "sample", "FRP", "conf", "type", "dn")), num_threads = 10) |> mutate(seqnum = dgGEO_to_SEQNUM(dggs, lon, lat)$seqnum)Map
We generate one PNG file per day and create the video with a call to a system-installed ffmpeg.
# compute the number of fires for each cell and each daymodis_cells <- modis |> count(seqnum, YYYYMMDD) |> left_join(hex, join_by(seqnum)) # prepare the breaksbreaks <- classIntervals(modis_cells$n, n = 4, style = "kmeans")# create a PNG map for one daycreate_map <- function(d) { p <- modis_cells |> filter(YYYYMMDD == d) |> left_join(hex, join_by(seqnum)) |> st_sf() |> ggplot() + geom_sf(data = world, fill = "#1a3853", color = "#002240") + geom_sf(aes(fill = n, color = n)) + scale_fill_viridis_c(aesthetics = c("colour", "fill"), breaks = round(breaks$brks), transform = "log", name = "Fires\nper cell\n(log\nscale)", option = "B", limits = c(1, max(modis_cells$seqnum))) + coord_sf(crs = "EPSG:8857") + labs(title = "MODIS fire detection", subtitle = d, caption = glue("MODIS - Global Monthly Fire Location \\ Product (MCD14ML) https://r.iresmi.net/ - {Sys.Date()}")) + theme_void() + theme(text = element_text(family = "Ubuntu", color = "white"), plot.margin = margin(2, 2, 2, 5, unit = "mm"), plot.caption = element_text(size = 7, color = "#777")) ggsave(glue("img/fire_{d}.png"), p, bg = "#002240", width = 9, height = 5)}# Iteratemodis |> distinct(YYYYMMDD) |> pull(YYYYMMDD) |> walk(create_map, .progress = TRUE)# generate the videosystem(glue('ffmpeg -framerate 24 -pattern_type glob -i "img/fire*.png" \\ -c:v libx264 -pix_fmt yuv420p modis.mp4'))Figure 1: Animation of global fires in 2024 using MODIS data
To leave a comment for the author, please follow the link and comment on their blog: r.iresmi.net.
R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
