Start by loading harp
library(harp)
library(here)
The data are from 15 August 2022 over southern Norway - forecasts from MEPS determinisitic (member 0 of the ensemble) and observations from MET Norway Nordic analysis (a blend of radar, in situ observations and model data where there are no observations - lead time unkonwn?)
Set some paths and stuff
obs_dir <- here("..", "data", "met_analysis")
obs_template <- "met_analysis_1_0km_nordic_{YYYY}{MM}{DD}T{HH}Z.nc"
obs_opts <- netcdf_opts(proj4_var = "projection_lcc", lon_var = NULL, lat_var = NULL)
fcst_dir <- here("..", "data", "meps")
fcst_template <- "meps_det_2_5km_{YYYY}{MM}{DD}T{HH}Z.nc"
fcst_opts <- netcdf_opts(ref_time_var = NA, z_var = "height0")
start_date <- 2022081501
end_date <- 2022081700
Define verification domain
dom <- read_forecast(
date_times = 2022081500,
fcst_model = "meps",
parameter = "Pcp",
lead_time = 0,
file_path = fcst_dir,
file_template = fcst_template,
file_format_opts = fcst_opts,
transformation = "subgrid",
transformation_opts = subgrid_opts(172, 472, 180, 480),
return_data = TRUE
) %>%
get_domain(meps_det)
Plot the domain to check it’s right
plot(dom)
Read observations
obs <- read_analysis(
date_times = seq_dates(start_date, end_date),
analysis_model = "met_analysis",
parameter = "precipitation_amount",
file_path = obs_dir,
file_template = obs_template,
file_format_opts = obs_opts,
transformation = "regrid",
transformation_opts = regrid_opts(dom)
)
Error : None of the requested parameters found in file: /home/andrewts/harpSpatial_ww/harp-ww-feb2023/harphub/../data/met_analysis/met_analysis_1_0km_nordic_20220815T01Z.nc
Plot observations
countries <- get_map(dom = dom, poly = FALSE)
ggplot() +
geom_georaster(aes(geofield = met_analysis), obs$met_analysis) +
geom_path(aes(x, y), countries) +
scico::scale_fill_scico(
"mm", palette = "oslo", direction = -1, limits = c(0.125, NA),
trans = "log", breaks = c(0.125, 0.25, 0.5, 1, 2, 4, 8, 16, 32),
na.value = "transparent"
) +
coord_equal(expand = FALSE) +
facet_wrap(vars(validdate)) +
theme_harp_map()
Read forecast
fcst <- read_forecast(
date_times = 2022081500,
fcst_model = "meps",
parameter = "Pcp",
lead_time = seq(0, 48),
file_path = fcst_dir,
file_template = fcst_template,
file_format_opts = fcst_opts,
transformation = "regrid",
transformation_opts = regrid_opts(dom),
return_data = TRUE
)
Error : None of the requested parameters found in file: /home/andrewts/harpSpatial_ww/harp-ww-feb2023/harphub/../data/meps/meps_det_2_5km_20220815T00Z.nc
Plot forecast
ggplot() +
geom_georaster(aes(geofield = meps_det), accumulate(fcst$meps, 1)) +
geom_path(aes(x, y), countries) +
scico::scale_fill_scico(
"mm", palette = "oslo", direction = -1, limits = c(0.125, NA),
trans = "log", breaks = c(0.125, 0.25, 0.5, 1, 2, 4, 8, 16, 32),
na.value = "transparent"
) +
coord_equal(expand = FALSE) +
facet_wrap(vars(validdate)) +
theme_harp_map()
Just for fun… use verify_fuzzy for in memory calculation of FSS - this will become much easier soon(ish)
fcst <- accumulate(fcst, 1) # Make sure the forecasts are 1h precip
fss <- mapply(
verify_fuzzy,
fcst$meps$meps_det,
obs$met_analysis$met_analysis,
MoreArgs = list(thresholds = c(0.5, 1), window_sizes = c(3, 5, 7)),
SIMPLIFY = FALSE
) %>%
dplyr::bind_rows()
fss
Now use the main verify_spatial function (Note that for netcdf, the parameter name needs to be mapped to the variable name in the file as they are different for the forecast and observation files):
verif1h <- verify_spatial(
start_date = 2022081500,
end_date = 2022081500,
det_model = "meps_det",
parameter = "AccPcp1h",
lead_time = seq(0, 48),
fc_file_path = fcst_dir,
fc_file_template = fcst_template,
fc_file_format = "netcdf",
fc_options = modify_opts(
fcst_opts,
param_find = list(AccPcp1h = "precipitation_amount_acc")
),
ob_file_path = obs_dir,
ob_file_template = obs_template,
ob_file_format = "netcdf",
ob_options = modify_opts(
obs_opts,
param_find = list(AccPcp1h = "precipitation_amount")
),
ob_accumulation = "1h",
verif_domain = dom
)
Currently the accumulation is done via the parameter name (e.g. AccPcp1h for 1h precipitation), which requires care in setting the mapping to the variable in the netcdf files, so if we want to do 3-hour accumualtions we need to change the parameter name and the mapping:
verif3h <- verify_spatial(
start_date = 2022081500,
end_date = 2022081500,
det_model = "meps_det",
parameter = "AccPcp3h",
lead_time = seq(0, 48),
fc_file_path = fcst_dir,
fc_file_template = fcst_template,
fc_file_format = "netcdf",
fc_options = modify_opts(
fcst_opts,
param_find = list(AccPcp3h = "precipitation_amount_acc")
),
ob_file_path = obs_dir,
ob_file_template = obs_template,
ob_file_format = "netcdf",
ob_options = modify_opts(
obs_opts,
param_find = list(AccPcp3h = "precipitation_amount")
),
ob_accumulation = "1h",
verif_domain = dom
)
Now we can make some plots:
plot_spatial_verif(verif1h, fss)
This gives the FSS aggregated over all times in the verification data. We can filter the data with filter_by
plot_spatial_verif(verif1h, fss, filter_by = vars(leadtime == 12))
To facet the plot for individual lead times requires going back to ggplot
ggplot(
verif1h$fuzzy,
aes(factor(threshold), factor(scale), fill = fss, label = sprintf("%1.2f", fss))
) +
geom_raster() +
geom_text(size = 3) +
scico::scale_fill_scico("FSS", palette = "cork", limits = c(0, 1)) +
coord_equal(expand = FALSE) +
facet_wrap(vars(leadtime)) +
labs(x = "Threshold [mm]", y = "Neighbourhood Length (grid squares)")
Plot the SAL:
plot_spatial_verif(verif1h, SAL) +
coord_equal()
LS0tCnRpdGxlOiAiaGFycFNwYXRpYWwgVGVzdDogaGFycGh1YiB2ZXJzaW9uIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKZWRpdG9yX29wdGlvbnM6IAogIGNodW5rX291dHB1dF90eXBlOiBpbmxpbmUKLS0tCgpTdGFydCBieSBsb2FkaW5nIGhhcnAKYGBge3IgbG9hZC1oYXJwLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBlcnJvcj1GQUxTRX0KbGlicmFyeShoYXJwKQpsaWJyYXJ5KGhlcmUpCmBgYAoKVGhlIGRhdGEgYXJlIGZyb20gMTUgQXVndXN0IDIwMjIgb3ZlciBzb3V0aGVybiBOb3J3YXkgLSBmb3JlY2FzdHMgZnJvbSBNRVBTIGRldGVybWluaXNpdGljIChtZW1iZXIgMCBvZiB0aGUgZW5zZW1ibGUpIGFuZCBvYnNlcnZhdGlvbnMgZnJvbSBNRVQgTm9yd2F5IE5vcmRpYyBhbmFseXNpcyAoYSBibGVuZCBvZiByYWRhciwgaW4gc2l0dSBvYnNlcnZhdGlvbnMgYW5kIG1vZGVsIGRhdGEgd2hlcmUgdGhlcmUgYXJlIG5vIG9ic2VydmF0aW9ucyAtIGxlYWQgdGltZSB1bmtvbnduPykKClNldCBzb21lIHBhdGhzIGFuZCBzdHVmZgpgYGB7ciBzZXQtcGF0aHN9Cm9ic19kaXIgPC0gaGVyZSgiLi4iLCAiZGF0YSIsICJtZXRfYW5hbHlzaXMiKQpvYnNfdGVtcGxhdGUgPC0gIm1ldF9hbmFseXNpc18xXzBrbV9ub3JkaWNfe1lZWVl9e01NfXtERH1Ue0hIfVoubmMiCm9ic19vcHRzIDwtIG5ldGNkZl9vcHRzKHByb2o0X3ZhciA9ICJwcm9qZWN0aW9uX2xjYyIsIGxvbl92YXIgPSBOVUxMLCBsYXRfdmFyID0gTlVMTCkKCmZjc3RfZGlyIDwtIGhlcmUoIi4uIiwgImRhdGEiLCAibWVwcyIpCmZjc3RfdGVtcGxhdGUgPC0gIm1lcHNfZGV0XzJfNWttX3tZWVlZfXtNTX17RER9VHtISH1aLm5jIgpmY3N0X29wdHMgPC0gbmV0Y2RmX29wdHMocmVmX3RpbWVfdmFyID0gTkEsIHpfdmFyID0gImhlaWdodDAiKQoKc3RhcnRfZGF0ZSA8LSAyMDIyMDgxNTAxCmVuZF9kYXRlIDwtIDIwMjIwODE3MDAKYGBgCgpEZWZpbmUgdmVyaWZpY2F0aW9uIGRvbWFpbgpgYGB7ciB2ZXJpZi1kb21haW4sIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGVycm9yPUZBTFNFfQpkb20gPC0gcmVhZF9mb3JlY2FzdCgKICBkYXRlX3RpbWVzICAgICAgICAgID0gMjAyMjA4MTUwMCwKICBmY3N0X21vZGVsICAgICAgICAgID0gIm1lcHMiLCAKICBwYXJhbWV0ZXIgICAgICAgICAgID0gIlBjcCIsCiAgbGVhZF90aW1lICAgICAgICAgICA9IDAsCiAgZmlsZV9wYXRoICAgICAgICAgICA9IGZjc3RfZGlyLAogIGZpbGVfdGVtcGxhdGUgICAgICAgPSBmY3N0X3RlbXBsYXRlLAogIGZpbGVfZm9ybWF0X29wdHMgICAgPSBmY3N0X29wdHMsCiAgdHJhbnNmb3JtYXRpb24gICAgICA9ICJzdWJncmlkIiwKICB0cmFuc2Zvcm1hdGlvbl9vcHRzID0gc3ViZ3JpZF9vcHRzKDE3MiwgNDcyLCAxODAsIDQ4MCksCiAgcmV0dXJuX2RhdGEgICAgICAgICA9IFRSVUUgCikgJT4lIAogIGdldF9kb21haW4obWVwc19kZXQpCmBgYAoKUGxvdCB0aGUgZG9tYWluIHRvIGNoZWNrIGl0J3MgcmlnaHQKYGBge3IgcGxvdC1kb219CnBsb3QoZG9tKQpgYGAKCgpSZWFkIG9ic2VydmF0aW9ucwpgYGB7ciByZWFkLW9icywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZXJyb3I9RkFMU0V9Cm9icyA8LSByZWFkX2FuYWx5c2lzKAogIGRhdGVfdGltZXMgICAgICAgICAgPSBzZXFfZGF0ZXMoc3RhcnRfZGF0ZSwgZW5kX2RhdGUpLAogIGFuYWx5c2lzX21vZGVsICAgICAgPSAibWV0X2FuYWx5c2lzIiwKICBwYXJhbWV0ZXIgICAgICAgICAgID0gInByZWNpcGl0YXRpb25fYW1vdW50IiwKICBmaWxlX3BhdGggICAgICAgICAgID0gb2JzX2RpciwKICBmaWxlX3RlbXBsYXRlICAgICAgID0gb2JzX3RlbXBsYXRlLAogIGZpbGVfZm9ybWF0X29wdHMgICAgPSBvYnNfb3B0cywKICB0cmFuc2Zvcm1hdGlvbiAgICAgID0gInJlZ3JpZCIsCiAgdHJhbnNmb3JtYXRpb25fb3B0cyA9IHJlZ3JpZF9vcHRzKGRvbSkKKQpgYGAKClBsb3Qgb2JzZXJ2YXRpb25zCmBgYHtyIHBsb3Qtb2JzLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBlcnJvcj1GQUxTRSwgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTEyLCBmaWcuYWxpZ249J2NlbnRlcid9CmNvdW50cmllcyA8LSBnZXRfbWFwKGRvbSA9IGRvbSwgcG9seSA9IEZBTFNFKQpnZ3Bsb3QoKSArIAogIGdlb21fZ2VvcmFzdGVyKGFlcyhnZW9maWVsZCA9IG1ldF9hbmFseXNpcyksIG9icyRtZXRfYW5hbHlzaXMpICsKICBnZW9tX3BhdGgoYWVzKHgsIHkpLCBjb3VudHJpZXMpICsgCiAgc2NpY286OnNjYWxlX2ZpbGxfc2NpY28oCiAgICAibW0iLCBwYWxldHRlID0gIm9zbG8iLCBkaXJlY3Rpb24gPSAtMSwgbGltaXRzID0gYygwLjEyNSwgTkEpLAogICAgdHJhbnMgPSAibG9nIiwgYnJlYWtzID0gYygwLjEyNSwgMC4yNSwgMC41LCAxLCAyLCA0LCA4LCAxNiwgMzIpLAogICAgbmEudmFsdWUgPSAidHJhbnNwYXJlbnQiCiAgKSArCiAgY29vcmRfZXF1YWwoZXhwYW5kID0gRkFMU0UpICsKICBmYWNldF93cmFwKHZhcnModmFsaWRkYXRlKSkgKwogIHRoZW1lX2hhcnBfbWFwKCkKICAKYGBgCgpSZWFkIGZvcmVjYXN0CmBgYHtyIHJlYWQtZmNzdCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZXJyb3I9RkFMU0V9CmZjc3QgPC0gcmVhZF9mb3JlY2FzdCgKICBkYXRlX3RpbWVzICAgICAgICAgID0gMjAyMjA4MTUwMCwKICBmY3N0X21vZGVsICAgICAgICAgID0gIm1lcHMiLAogIHBhcmFtZXRlciAgICAgICAgICAgPSAiUGNwIiwKICBsZWFkX3RpbWUgICAgICAgICAgID0gc2VxKDAsIDQ4KSwKICBmaWxlX3BhdGggICAgICAgICAgID0gZmNzdF9kaXIsCiAgZmlsZV90ZW1wbGF0ZSAgICAgICA9IGZjc3RfdGVtcGxhdGUsCiAgZmlsZV9mb3JtYXRfb3B0cyAgICA9IGZjc3Rfb3B0cywKICB0cmFuc2Zvcm1hdGlvbiAgICAgID0gInJlZ3JpZCIsCiAgdHJhbnNmb3JtYXRpb25fb3B0cyA9IHJlZ3JpZF9vcHRzKGRvbSksCiAgcmV0dXJuX2RhdGEgICAgICAgICA9IFRSVUUgCikKCmBgYAoKUGxvdCBmb3JlY2FzdApgYGB7ciBwbG90LWZjc3QsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGVycm9yPUZBTFNFLCBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9MTIsIGZpZy5hbGlnbj0nY2VudGVyJ30KZ2dwbG90KCkgKyAKICBnZW9tX2dlb3Jhc3RlcihhZXMoZ2VvZmllbGQgPSBtZXBzX2RldCksIGFjY3VtdWxhdGUoZmNzdCRtZXBzLCAxKSkgKwogIGdlb21fcGF0aChhZXMoeCwgeSksIGNvdW50cmllcykgKyAKICBzY2ljbzo6c2NhbGVfZmlsbF9zY2ljbygKICAgICJtbSIsIHBhbGV0dGUgPSAib3NsbyIsIGRpcmVjdGlvbiA9IC0xLCBsaW1pdHMgPSBjKDAuMTI1LCBOQSksCiAgICB0cmFucyA9ICJsb2ciLCBicmVha3MgPSBjKDAuMTI1LCAwLjI1LCAwLjUsIDEsIDIsIDQsIDgsIDE2LCAzMiksCiAgICBuYS52YWx1ZSA9ICJ0cmFuc3BhcmVudCIKICApICsKICBjb29yZF9lcXVhbChleHBhbmQgPSBGQUxTRSkgKwogIGZhY2V0X3dyYXAodmFycyh2YWxpZGRhdGUpKSArCiAgdGhlbWVfaGFycF9tYXAoKQogIApgYGAKCkp1c3QgZm9yIGZ1bi4uLiB1c2UgdmVyaWZ5X2Z1enp5IGZvciBpbiBtZW1vcnkgY2FsY3VsYXRpb24gb2YgRlNTIC0gdGhpcyB3aWxsIGJlY29tZSBtdWNoIGVhc2llciBzb29uKGlzaCkKYGBge3IgdmVyaWZ5LXdpdGgtbWFwcGx5LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBlcnJvcj1GQUxTRX0KZmNzdCA8LSBhY2N1bXVsYXRlKGZjc3QsIDEpICMgTWFrZSBzdXJlIHRoZSBmb3JlY2FzdHMgYXJlIDFoIHByZWNpcApmc3MgPC0gbWFwcGx5KAogIHZlcmlmeV9mdXp6eSwKICBmY3N0JG1lcHMkbWVwc19kZXQsCiAgb2JzJG1ldF9hbmFseXNpcyRtZXRfYW5hbHlzaXMsCiAgTW9yZUFyZ3MgPSBsaXN0KHRocmVzaG9sZHMgPSBjKDAuNSwgMSksIHdpbmRvd19zaXplcyA9IGMoMywgNSwgNykpLAogIFNJTVBMSUZZID0gRkFMU0UKKSAlPiUgCiAgZHBseXI6OmJpbmRfcm93cygpCmBgYAoKYGBge3IgZnNzLWFzLXRhYmxlfQpmc3MKYGBgCgpOb3cgdXNlIHRoZSBtYWluIHZlcmlmeV9zcGF0aWFsIGZ1bmN0aW9uIChOb3RlIHRoYXQgZm9yIG5ldGNkZiwgdGhlIHBhcmFtZXRlciBuYW1lIG5lZWRzIHRvIGJlIG1hcHBlZCB0byB0aGUgdmFyaWFibGUgbmFtZSBpbiB0aGUgZmlsZSBhcyB0aGV5IGFyZSBkaWZmZXJlbnQgZm9yIHRoZSBmb3JlY2FzdCBhbmQgb2JzZXJ2YXRpb24gZmlsZXMpOgpgYGB7ciB2ZXJpZi1zcGF0aWFsLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBlcnJvcj1GQUxTRX0KdmVyaWYxaCA8LSB2ZXJpZnlfc3BhdGlhbCgKICBzdGFydF9kYXRlICAgICAgICA9IDIwMjIwODE1MDAsCiAgZW5kX2RhdGUgICAgICAgICAgPSAyMDIyMDgxNTAwLAogIGRldF9tb2RlbCAgICAgICAgID0gIm1lcHNfZGV0IiwKICBwYXJhbWV0ZXIgICAgICAgICA9ICJBY2NQY3AxaCIsCiAgbGVhZF90aW1lICAgICAgICAgPSBzZXEoMCwgNDgpLAogIGZjX2ZpbGVfcGF0aCAgICAgID0gZmNzdF9kaXIsCiAgZmNfZmlsZV90ZW1wbGF0ZSAgPSBmY3N0X3RlbXBsYXRlLAogIGZjX2ZpbGVfZm9ybWF0ICAgID0gIm5ldGNkZiIsCiAgZmNfb3B0aW9ucyAgICAgICAgPSBtb2RpZnlfb3B0cygKICAgIGZjc3Rfb3B0cywgCiAgICBwYXJhbV9maW5kID0gbGlzdChBY2NQY3AxaCA9ICJwcmVjaXBpdGF0aW9uX2Ftb3VudF9hY2MiKQogICksCiAgb2JfZmlsZV9wYXRoICAgICAgPSBvYnNfZGlyLCAKICBvYl9maWxlX3RlbXBsYXRlICA9IG9ic190ZW1wbGF0ZSwKICBvYl9maWxlX2Zvcm1hdCAgICA9ICJuZXRjZGYiLAogIG9iX29wdGlvbnMgICAgICAgID0gbW9kaWZ5X29wdHMoCiAgICBvYnNfb3B0cywgCiAgICBwYXJhbV9maW5kID0gbGlzdChBY2NQY3AxaCA9ICJwcmVjaXBpdGF0aW9uX2Ftb3VudCIpCiAgKSwKICBvYl9hY2N1bXVsYXRpb24gICA9ICIxaCIsCiAgdmVyaWZfZG9tYWluICAgICAgPSBkb20KKQoKYGBgCgpDdXJyZW50bHkgdGhlIGFjY3VtdWxhdGlvbiBpcyBkb25lIHZpYSB0aGUgcGFyYW1ldGVyIG5hbWUgKGUuZy4gQWNjUGNwMWggZm9yIDFoIHByZWNpcGl0YXRpb24pLCB3aGljaCByZXF1aXJlcyBjYXJlIGluIHNldHRpbmcgdGhlIG1hcHBpbmcgdG8gdGhlIHZhcmlhYmxlIGluIHRoZSBuZXRjZGYgZmlsZXMsIHNvIGlmIHdlIHdhbnQgdG8gZG8gMy1ob3VyIGFjY3VtdWFsdGlvbnMgd2UgbmVlZCB0byBjaGFuZ2UgdGhlIHBhcmFtZXRlciBuYW1lIGFuZCB0aGUgbWFwcGluZzoKYGBge3IgdmVyaWYtc3BhdGlhbC0zaCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZXJyb3I9RkFMU0V9CnZlcmlmM2ggPC0gdmVyaWZ5X3NwYXRpYWwoCiAgc3RhcnRfZGF0ZSAgICAgICAgPSAyMDIyMDgxNTAwLAogIGVuZF9kYXRlICAgICAgICAgID0gMjAyMjA4MTUwMCwKICBkZXRfbW9kZWwgICAgICAgICA9ICJtZXBzX2RldCIsCiAgcGFyYW1ldGVyICAgICAgICAgPSAiQWNjUGNwM2giLAogIGxlYWRfdGltZSAgICAgICAgID0gc2VxKDAsIDQ4KSwKICBmY19maWxlX3BhdGggICAgICA9IGZjc3RfZGlyLAogIGZjX2ZpbGVfdGVtcGxhdGUgID0gZmNzdF90ZW1wbGF0ZSwKICBmY19maWxlX2Zvcm1hdCAgICA9ICJuZXRjZGYiLAogIGZjX29wdGlvbnMgICAgICAgID0gbW9kaWZ5X29wdHMoCiAgICBmY3N0X29wdHMsIAogICAgcGFyYW1fZmluZCA9IGxpc3QoQWNjUGNwM2ggPSAicHJlY2lwaXRhdGlvbl9hbW91bnRfYWNjIikKICApLAogIG9iX2ZpbGVfcGF0aCAgICAgID0gb2JzX2RpciwgCiAgb2JfZmlsZV90ZW1wbGF0ZSAgPSBvYnNfdGVtcGxhdGUsCiAgb2JfZmlsZV9mb3JtYXQgICAgPSAibmV0Y2RmIiwKICBvYl9vcHRpb25zICAgICAgICA9IG1vZGlmeV9vcHRzKAogICAgb2JzX29wdHMsIAogICAgcGFyYW1fZmluZCA9IGxpc3QoQWNjUGNwM2ggPSAicHJlY2lwaXRhdGlvbl9hbW91bnQiKQogICksCiAgb2JfYWNjdW11bGF0aW9uICAgPSAiMWgiLAogIHZlcmlmX2RvbWFpbiAgICAgID0gZG9tCikKYGBgCgpOb3cgd2UgY2FuIG1ha2Ugc29tZSBwbG90czoKYGBge3IgcGxvdC1mc3N9CnBsb3Rfc3BhdGlhbF92ZXJpZih2ZXJpZjFoLCBmc3MpCmBgYAoKVGhpcyBnaXZlcyB0aGUgRlNTIGFnZ3JlZ2F0ZWQgb3ZlciBhbGwgdGltZXMgaW4gdGhlIHZlcmlmaWNhdGlvbiBkYXRhLiBXZSBjYW4gZmlsdGVyIHRoZSBkYXRhIHdpdGggYGZpbHRlcl9ieWAKYGBge3IgcGxvdC1mc3MtZmlsdGVyfQpwbG90X3NwYXRpYWxfdmVyaWYodmVyaWYxaCwgZnNzLCBmaWx0ZXJfYnkgPSB2YXJzKGxlYWR0aW1lID09IDEyKSkKYGBgCgpUbyBmYWNldCB0aGUgcGxvdCBmb3IgaW5kaXZpZHVhbCBsZWFkIHRpbWVzIHJlcXVpcmVzIGdvaW5nIGJhY2sgdG8gZ2dwbG90CmBgYHtyIHBsb3QtZnNzLWZhY2V0LCBmaWcuaGVpZ2h0PTEyLCBmaWcud2lkdGg9MTIsIGZpZy5hbGlnbj0nY2VudGVyJ30KZ2dwbG90KAogIHZlcmlmMWgkZnV6enksIAogIGFlcyhmYWN0b3IodGhyZXNob2xkKSwgZmFjdG9yKHNjYWxlKSwgZmlsbCA9IGZzcywgbGFiZWwgPSBzcHJpbnRmKCIlMS4yZiIsIGZzcykpCikgKwogIGdlb21fcmFzdGVyKCkgKwogIGdlb21fdGV4dChzaXplID0gMykgKwogIHNjaWNvOjpzY2FsZV9maWxsX3NjaWNvKCJGU1MiLCBwYWxldHRlID0gImNvcmsiLCBsaW1pdHMgPSBjKDAsIDEpKSArCiAgY29vcmRfZXF1YWwoZXhwYW5kID0gRkFMU0UpICsgCiAgZmFjZXRfd3JhcCh2YXJzKGxlYWR0aW1lKSkgKyAKICBsYWJzKHggPSAiVGhyZXNob2xkIFttbV0iLCB5ID0gIk5laWdoYm91cmhvb2QgTGVuZ3RoIChncmlkIHNxdWFyZXMpIikKYGBgCgpQbG90IHRoZSBTQUw6CmBgYHtyIHBsb3Qtc2FsLCB3YXJuaW5nPUZBTFNFfQpwbG90X3NwYXRpYWxfdmVyaWYodmVyaWYxaCwgU0FMKSArCiAgY29vcmRfZXF1YWwoKQoKYGBgCgo=