df_monitor_spec <- tibble::tribble(~`Decision Type`, ~`Decision`,"Event Type", "Primera (MJJA) seasonal rainfall deficit","Geographic level of analysis", "Admin 1 level","Forecast Lead Time", "Up to 4 months (March onwards)","Activation thresholds", "1 in 4 year return period rainfall deficit. Measured per lead time, per admin unit","Forecast to use", "March/April: National (INSIVUMEH)\nMay: ECMWF SEAS5" )gt(df_monitor_spec) |>tab_header("StartNetwork Monitoring Specs" ) |>tab_options(heading.background.color ="#00ad78ff",column_labels.background.color =hdx_hex("mint-ultra-light") )
StartNetwork Monitoring Specs
Decision Type
Decision
Event Type
Primera (MJJA) seasonal rainfall deficit
Geographic level of analysis
Admin 1 level
Forecast Lead Time
Up to 4 months (March onwards)
Activation thresholds
1 in 4 year return period rainfall deficit. Measured per lead time, per admin unit
Forecast to use
March/April: National (INSIVUMEH) May: ECMWF SEAS5
Code
df_combined_thresholds <- cumulus$blob_read(container ="projects",name ="ds-aa-lac-dry-corridor/framework_update_2025/df_thresholds_seas5_insivumeh_startnetwork_guatemela.parquet" )# insivumeh zonal stats from parquet on blob - - not ecmwf comes from postgres in code belowdf_insivumeh_zonal <- cumulus$blob_read(container ="projects",name ="ds-aa-lac-dry-corridor/df_startnetwork_historical_zonal_primera.parquet")df_aoi <- utils$load_aoi_df(version ="startnetwork")
Area of Interest
Below we see the area of interest as a table and a map.
# the below doesn't need to be evaluated on render - as I save the outputs of this # chunk to blob and load later. Nonetheless, we can keep the code in the notebook.lgdf_nic <- cumulus$download_fieldmaps_sf(iso3="nic",layer =c("nic_adm1","nic_adm0"))lgdf_hnd <- cumulus$download_fieldmaps_sf(iso3="hnd",layer=c("hnd_adm1","hnd_adm0"))lgdf_slv <- cumulus$download_fieldmaps_sf(iso3="slv",layer=c("slv_adm1","slv_adm0"))lgdf_gtm <- cumulus$download_fieldmaps_sf(iso3="gtm",layer=c("gtm_adm1","gtm_adm0"))gdf_adm1_cadc <-list_rbind(list( lgdf_nic$nic_adm1, lgdf_hnd$hnd_adm1, lgdf_slv$slv_adm1, lgdf_gtm$gtm_adm1 )) |>rename(geometry=geom )gdf_adm0_cadc <-list_rbind(list( lgdf_nic$nic_adm0, lgdf_hnd$hnd_adm0, lgdf_slv$slv_adm0, lgdf_gtm$gtm_adm0 )) |>rename(geometry=geom )cumulus$blob_write( gdf_adm1_cadc,container ="projects",name ="ds-aa-lac-dry-corridor/framework_update_2025/gdf_cadc_adm1.parquet" )cumulus$blob_write( gdf_adm0_cadc,container ="projects",name ="ds-aa-lac-dry-corridor/framework_update_2025/gdf_cadc_adm0.parquet" )
# First we just look at ECMWF - here we actually consider all leadtimes -- not just those considered for monitoring and we see no activation present in historical record. If we did see activation we would want to check on what lead times those occured.# quick func to filter historical data based on conditions of frameworkfilter_historical_to_moments <-function(df,window_col){ df |>filter(!(month(issued_date)==2&!!sym(window_col)=="primera"),!(month(issued_date) %in%c(5,9) &!!sym(window_col)=="postrera") )}# Prep Seas5 --------------------------------------------------------------df_seas5 <-tbl(con,"seas5") |>filter( adm_level ==1, pcode %in% df_aoi$pcode,month(valid_date)%in%c(5:11) # just grabbing all relevant months (including postrera) for both windows ) |>collect() # this actually loads data into memory so can take a 10s or so.df_seas5 <- df_seas5 |>mutate(precipitation =days_in_month(valid_date) * mean )df_primera <- cumulus$seas5_aggregate_forecast( df_seas5,value ="precipitation",valid_months =c(5:8),by =c("iso3", "pcode","issued_date")) |>mutate(window ="primera" )df_postrera <- cumulus$seas5_aggregate_forecast( df_seas5,valid_months =c(9:11),value ="precipitation",by =c("iso3", "pcode","issued_date") ) |>mutate(window ="postrera" )df_historical <-bind_rows( df_primera, df_postrera)df_historical_aa <- df_historical |>filter_historical_to_moments(window_col ="window" )# startNetwork is monitoring adm1s independent - so no weighted avgdf_historical_aa_adm0 <- df_historical_aa |>left_join( df_new_aoi_meta |>select( pcode, iso3, adm1_es = name ) )
INSIVUMEH
Here we look at the historical forecasts from insivumeh. Years that are highlighted indicate that an activation would have occured in either March or April.
Code
df_insivumeh_thresholds <- df_combined_thresholds |>filter(forecast_source =="INSIVUMEH")df_insivumeh_aa <- df_insivumeh_zonal |>mutate(season ="primera" ) |># already done in parquet file -- but not bad to leav herefilter_historical_to_moments(window_col ="season") |># rename to use same plotting code aboverename(window ="season" )df_insivumeh_zonal_min_per_year <- df_insivumeh_aa |>left_join( df_insivumeh_thresholds |>filter(window =="primera"),by =c("adm0_es", "adm1_es","adm1_pcode","leadtime","window") ) |>mutate(yr_issued =year(issued_date),mm_flag = value<=value_empirical,priority =if_else(mm_flag, 1, 2) # trick for plotting ) |>group_by(adm0_es,adm1_es,window,yr_issued) |>slice_min(order_by =tibble(priority,value) )df_insivumeh_zonal_min_per_year |>ggplot(aes(x=year(issued_date),y=value, group =1) )+geom_point(aes(color = mm_flag), alpha=0.7, size=4)+geom_line(color ="black")+facet_wrap(~adm1_es, ncol=1)+scale_color_manual(values =c(hdx_hex("sapphire-hdx"),hdx_hex("tomato-hdx")))+labs(title ="CADC Guatemala: Primera Season (MJJA) Forecast",subtitle ="INSIVUMEH March + April Publication",caption ="Points represent minimum rainfall across both leadtimes monitoried in" ) +geom_text_repel(data=filter(df_insivumeh_zonal_min_per_year,mm_flag),aes(label =year(issued_date)), color =hdx_hex("tomato-hdx"),size= txt_label_size )+theme(axis.title =element_blank(),legend.position ="none" )
ECMWF
To capture the May activation moment we use ECMWF global seasonal forecast.
Code
df_seas5_thresholds <- df_combined_thresholds |>filter( forecast_source =="SEAS5" )df_classified_2024_seas5_thresholds <- df_historical_aa_adm0 |>left_join(df_seas5_thresholds, by =c("iso3","pcode","adm1_es"="name","leadtime","window")) |>mutate(precipitation_flag = precipitation <= value_empirical )df_classified_2024_seas5_thresholds |>filter( window =="primera", leadtime ==0 ) |>ggplot(aes(x=year(issued_date),y=precipitation, group =1) )+geom_point(aes(color = precipitation_flag), alpha=0.7, size=4)+geom_line(color ="black")+facet_wrap(~adm1_es, ncol =1)+scale_color_manual(values =c(hdx_hex("sapphire-hdx"),hdx_hex("tomato-hdx")))+labs(title ="CADC Guatemala: Primera Season (MJJA) Forecast",subtitle ="Global ECMWF SEAS5 May Publication",caption ="Plotting minimum rainfall at any leadtime monitoried in AA Framework Analysis performed at sub-national levelbased on area-weighted average of admins of interest per country" ) +geom_text_repel(data=filter(df_classified_2024_seas5_thresholds,precipitation_flag, window =="primera", leadtime ==0),aes(label =year(issued_date)), color =hdx_hex("tomato-hdx"), size=txt_label_size )+theme(axis.title =element_blank(),legend.position ="none" )
Threshold Tables
Code
df_thresholds_aa <- df_combined_thresholds |>filter(# do not use SEAS5 for Guatemala -- only for leadtime 0!(iso3 =="GTM"& leadtime %in%c(1:4) & forecast_source =="SEAS5"),# these 2 months not being moniored!(issued_month_label %in%c("Feb","Sep")),!(issued_month_label =="May"& window =="postrera") ) |>mutate(# pull over from seas5 colsadm1_es =if_else(is.na(adm1_es),name, adm1_es),adm1_pcode =if_else(is.na(adm1_pcode),pcode, adm1_pcode) ) df_thresholds_formatted <- df_thresholds_aa %>%mutate(# pull over from seas5 colsadm1_es =if_else(is.na(adm1_es),name, adm1_es),adm1_pcode =if_else(is.na(adm1_pcode),pcode, adm1_pcode) ) |>arrange( iso3, window ) |># print(n=15) |> mutate(pub_month_int =ifelse(window =="primera",5- leadtime,9-leadtime),pub_month_chr =month(pub_month_int, label =T, abb=T),pub_month_lt =paste0(pub_month_chr," (", leadtime,")"), ) %>%select( adm0_es, adm1_es, pub_month_lt,threshold = value_empirical, window, forecast_source ) ldf_thresholds_wide <-split(df_thresholds_formatted,df_thresholds_formatted$window) %>%map(\(dft){ dft |>arrange(adm0_es) %>%select(-forecast_source,-window) |>filter(!str_detect(pub_month_lt, "^Feb") ) %>%pivot_wider(names_from = adm1_es,values_from =threshold ) |>select( pub_month_lt,"Baja Verapaz","Quiché" ) %>%arrange(desc(parse_number(pub_month_lt)) ) })txt_footnote <-"Threshold calculations are made based on analysis of historical forecast data (1981-2022) to approximate a 1 in 4 year return period drought levels for rainfall over the entire season for each administrative 1 unit respectively. Thresholds are calculated per country, leadtime,admin 1 unit, and forecast data source to minimize potential biases. Where possible national forecasts were used for this analysis and monitoring. Where no national forecasts were readily available, ECMWF seasonal forecasts/historical forecasts were used. <br><br><b> Note:</b> The national forecast provided by INSIVUMEH in Guatemala does not provide a forecast estimate for the month of publication, therefore when that month is included as an activation moment, ECMWF is used."# set colors for table/legend# ecmwf_cols <- c("El Salvador","Honduras","Nicaragua")ecmwf_color <-hdx_hex("mint-light")insuv_color <-hdx_hex("sapphire-light")# make legend for table MARS datagt_legend <-data.frame(`Forecast Data Source`="Forecast Data Source",ecmwf ="ECMWF SEAS5" ,insuv="INSIVUMEH") %>%gt(rowname_col ="Forecast Data Source") %>%data_color(columns ="ecmwf", direction ="column",color=ecmwf_color) %>%data_color(columns ="insuv", direction ="column",color=insuv_color) %>%tab_options(column_labels.hidden = T ) %>%as_raw_html()
Primera (MJJA 2025) Rainfall (mm) Monitoring Thresholds
Forecast Data Source
ECMWF SEAS5
INSIVUMEH
Publication Month
(leadtime)
Baja Verapaz
Quiché
Mar (2)
755
1,039
Apr (1)
721
1,018
May (0)
803
905
Threshold calculations are made based on analysis of historical forecast data (1981-2022) to approximate a 1 in 4 year return period drought levels for rainfall over the entire season for each administrative 1 unit respectively. Thresholds are calculated per country, leadtime,admin 1 unit, and forecast data source to minimize potential biases. Where possible national forecasts were used for this analysis and monitoring. Where no national forecasts were readily available, ECMWF seasonal forecasts/historical forecasts were used.
Note: The national forecast provided by INSIVUMEH in Guatemala does not provide a forecast estimate for the month of publication, therefore when that month is included as an activation moment, ECMWF is used.
Joint RPs
StartNetwork has expressed that we should implement a 4 year return period based threshold for each administrative unite and lead time separately. Therefore, it is also useful to look at the overall joint return period/activation rate for an activation occurring in any of the lead times and either admin1 area.