library(data.table)
library(tidyverse)
library(jsonlite)
library(wx)
dir.data <- file.path(dirs$meta, "stn", "mch")
dir.obs <- "~/Temp/smn"
dir.out <- "inst/smn"
## ----------------------------- Contents ------------------------------------
#' dt.stat: basic station info
#' dt.oscar: station history (by sensor)
## ----------------------------- Def ------------------------------------
server <- "https://data.geo.admin.ch"
server.oscar <- "https://oscar.wmo.int/surface/rest/api/stations/station?"
api.oscar <- "https://oscar.wmo.int/surface/rest/api/stations/observation/grouping"
vars <- list(
list(mch = "lufttemperatur-10min", values = "value", code_var = "tt"),
list(mch = "luftfeuchtigkeit-10min", values = "value", code_var = "rh"),
list(mch = "niederschlag-10min", values = "value", code_var = "pp"),
list(mch = "niederschlag-1d", values = "value", code_var = "pp_1d"),
list(mch = "gesamtschnee-1d", values = "value", code_var = "snow"),
list(mch = "neuschnee-1d", values = "value", code_var = "snow_new"),
list(mch = "luftdruck-qfe-10min", values = "value", code_var = "p_qfe"),
list(mch = "luftdruck-qnh-10min", values = "value", code_var = "p_qnh"),
list(mch = "luftdruck-qff-10min", values = "value", code_var = "p_qff"),
list(mch = "windgeschwindigkeit-kmh-10min", values = c("value", "wind_direction"), code_var = c("ff", "dir")),
list(mch = "wind-boeenspitze-kmh-10min", values = c("value"), code_var = "fx"),
list(mch = "sonnenscheindauer-10min", values = "value", code_var = "sun"),
list(mch = "globalstrahlung-10min", values = "value", code_var = "rad")
)
def.network <- list(
smn = "messnetz-automatisch",
climate = "messnetz-klima",
atmos = "messnetz-atmosphaere",
pp_manual = "messnetz-manuell",
synop = "messnetz-beobachtungen",
aero = "messnetz-flugwetter"
)
fn <- sprintf("%s/ch.meteoschweiz.%s_de.json", dir.data, "messwerte-niederschlag-10min")
dt <- jsonlite::fromJSON(fn, flatten = F)
str(dt)
dt <- dt$features %>%
tidyr::unnest(geometry)
dt$properties.description[1]
## ----------------------------- Networks ------------------------------------
list.stat <- mapply(names(def.network), def.network, SIMPLIFY = F, FUN = function(nw, url){
# url = "messnetz-automatisch"; nw = "smn"
url.1 <- sprintf("%s/ch.meteoschweiz.%s_de.csv", dir.data, url)
dt <- fread(url.1, encoding = "Latin-1")
dt[, network := nw]
dt
})
dt.stat <- rbindlist(list.stat, fill = T)
smn.stn <- dt.stat %>%
dplyr::select(
stn = `Abk.`,
id_wigos = `WIGOS-ID`,
name = Station,
from = `Daten seit`,
z = `Stationshöhe m. ü. M.`,
z_baro = `Barometerhöhe m. ü. Boden`,
lon = KoordinatenE,
lat = KoordinatenN,
x = Längengrad,
y = Breitengrad,
canton = Kanton,
network,
airport = Flugplatz
) %>%
group_by(stn, id_wigos, name, z, lon, lat, x, y, canton) %>%
summarise(z_baro = median(z_baro, na.rm = T), from = min(from, na.rm = T), network = paste(network, collapse = ","), airport = max(airport, na.rm = T)) %>%
mutate(
from = as.Date(strptime(from, "%d.%m.%Y")),
id_wmo = str_extract(id_wigos, "[0-9]{5}$"),
id_wigos = case_when(id_wigos == "" ~ NA_character_, TRUE ~id_wigos)
) %>%
ungroup() %>%
arrange(stn) %>%
as.data.table()
which(duplicated(smn.stn$stn))
## ----------------------------- WIGOS ------------------------------------
dt.oscar.vars.lut <- rbindlist(list(
p = list(titleName = "Atmosphere > Pressure", observationTitle = "Atmospheric pressure - [Geometry: Point]"),
pp = list(titleName = "Atmosphere > Precipitation", observationTitle = "Amount of precipitation - [Geometry: Point]"),
tt = list(titleName = "Atmosphere > Temperature", observationTitle = "Air temperature (at specified distance from reference surface) - [Geometry: Point]"),
rh = list(titleName = "Atmosphere > Temperature", observationTitle = "Humidity (at specified distance from reference surface) - [Geometry: Point]"),
rad = list(titleName = "Atmosphere > Radiation", observationTitle = "Solar > Global solar radiation (downwelling) - [Geometry: Point]"),
dir = list(titleName = "Atmosphere > Wind", observationTitle = "Horizontal wind direction at specified distance from reference surface - [Geometry: Point]"),
ff = list(titleName = "Atmosphere > Wind", observationTitle = "Horizontal wind speed at specified distance from reference surface - [Geometry: Point]"),
fx = list(titleName = "Atmosphere > Wind", observationTitle = "Horizontal wind speed at specified distance from reference surface - [Geometry: Point]"),
snow = list(titleName = "Terrestrial > Cryosphere_", observationTitle = "Snow > Snow depth - [Geometry: Point]"),
snow_new = list(titleName = "Terrestrial > Cryosphere_", observationTitle = "Snow > Depth of snowfall - [Geometry: Point]")
), idcol = "code_var")
dt.wigos <- smn.stat %>% filter(!is.na(id_wigos)) #%>% dplyr::slice(1:5)
list.oscar <- mapply(dt.wigos$stn, dt.wigos$id_wigos, SIMPLIFY = F, FUN = function(id.sma, id.wigos){
# id.sma = "ABO"; id.wigos = "0-20000-0-06735"
cat(id.sma)
def <- try(fromJSON(sprintf("%swmoIndex=%s", server.oscar, id.wigos)))
if(inherits(def, "try-error")) return(NULL)
oscar.vars <- fromJSON(sprintf("%s/%s", api.oscar, def$stationId), simplifyDataFrame = F)
dt.oscar.vars <- simplify(oscar.vars) %>% rbindlist() %>% unnest_wider(observationTitle) %>% as.data.table
dt.vars <- merge(dt.oscar.vars, dt.oscar.vars.lut, by = c("titleName", "observationTitle"))
list.res <- mapply(dt.vars$observationId, dt.vars$code_var, SIMPLIFY = F, FUN = function(id.obs, code.var){
# id.obs <- 171591; code.var = "tt"
cat(" ", code.var)
j1 <- fromJSON(sprintf("https://oscar.wmo.int/surface/rest/api/stations/deployments/%s", id.obs), flatten = T, simplifyDataFrame = F, simplifyVector = F)
j <- map(j1, ~simplify(.x)) #jj <- map(j, ~as.data.table(enframe(unlist(.x))))
data.table(
stn = id.sma,
id_wigos = id.wigos,
para = code.var,
from = map(j, ~ .x$dataGenerations[[1]]$observationSince) %>% replace_na(NA_character_) %>% unlist(),
to = map(j, ~ .x$dataGenerations[[1]]$observationTill) %>% replace_na(NA_character_) %>% unlist(),
h = map(j, ~ as.numeric(.x$distanceFromRefSurface)) %>% replace_na(NA_real_) %>% unlist(),
x = map(j, ~ .x$instrument$locations[[1]]$longitude) %>% replace_na(NA_real_) %>% unlist(),
y = map(j, ~ .x$instrument$locations[[1]]$latitude) %>% replace_na(NA_real_) %>% unlist(),
z = map(j, ~ .x$instrument$locations[[1]]$elevation) %>% replace_na(NA_real_) %>% unlist()
)
})
dt <- rbindlist(list.res)
cat("\n")
dt
})
smn.stn.sensor.hist <- rbindlist(list.oscar)
setorder(smn.stn.sensor.hist, stn, para, from)
# Fix missing z
smn.stn.sensor.hist[, `:=`(
z = fifelse(z == -99, NA_real_, z),
h = fifelse(z == -99, NA_real_, h),
from = as.Date(from),
to = as.Date(to)
)]
# Omit soil temp
smn.stn.sensor.hist <- smn.stn.sensor.hist[!(para == "tt" & h == 0.05)]
smn.stn.sensor.hist[stn == "SMA" & para == "snow"]
## ----------------------------- Sensors ------------------------------------
load_smn_variable <- function(var, server){
path <- sprintf("ch.meteoschweiz.messwerte-%s", var)
file <- sprintf("ch.meteoschweiz.messwerte-%s_de.json", var)
fromJSON(file.path(dir.obs, file), simplifyDataFrame = T, flatten = F)
}
list.meta <- lapply(seq_along(vars), function(i){
# i = 1
def <- vars[[i]]
print(def$code_var)
j <- load_smn_variable(def$mch, server)
data.table(
para = def$code_var,
stn = j$features$id,
#j$features$properties$station_name,
z_str = j$features$properties$altitude,
h_str = j$features$properties$measurement_height,
lon = do.call(rbind, j$features$geometry$coordinates)[,1],
lat = do.call(rbind, j$features$geometry$coordinates)[,2],
descr = gsub("<.*?>", "", j$features$properties$description)
)
})
dt.meta <- rbindlist(list.meta, fill = T)
smn.stn.sensor <- dt.meta %>%
tidyr::separate(h_str, into = c("h", "h_obj_str"), sep = "\\(", remove = F) %>%
mutate(
z_para = as.numeric(str_extract(z_str, "[0-9\\.]+")),
h = as.numeric(str_extract(h_str, "[0-9\\.]+")),
obj = str_extract(h_obj_str, "[A-Z][a-z]+"),
h_obj = as.numeric(str_extract(h_obj_str, "[0-9\\.]+"))
) %>%
dplyr::select(stn, para, lon, lat, z_para, h, h_obj, obj) %>%
as.data.table()
smn.stn.sensor[stn == "HIW"]
## --------------------------- Merge ------------------------------
smn.stn.name <- fread(file.path(dir.out, "smn_stn_name.csv"))
smn.stn <- merge(smn.stn, smn.stn.name, by = "stn", all = TRUE)
smn.stn <- merge(smn.stn, smn.stn.sensor[, .(para_list = paste(para, collapse = ","), para_count = .N), .(stn)], by = "stn", all = TRUE)
smn.stn[, short_name := fifelse(is.na(short_name), name, short_name)]
# Filter
smn.stn[is.na(para_list)]
smn.stn <- smn.stn[!is.na(para_list)]
## ----------------------------- Classes/Tags ------------------------------------
def.class <- list(
clim = c("GSB", "JUN", "CDF", "GRH", "PAY", "RAG", "ANT", "ELM", "OTL", "LUG", "SAM", "SIA", "DAV", "SMA", "CHM", "ENG", "CHD", "SIO", "BAS",
"STG", "GVE", "SAE", "BER", "MER", "ALT", "NEU", "SBE", "GRC", "LUZ"),
city = c("SMA", "LUG", "BAS", "BER", "GVE", "NEU", "STG", "LUZ", "SIO", "PUY"),
mountain = c("SAE", "JUN", "PIL", "TIT", "WFJ", "PMA", "COV", "MTR", "GEN", "GUE", "EGH", "NAP", "HOE",
"ATT", "DIA", "MLS", "DOL", "CHM", "CHA", "LAE", "UEB", "STC", "BAN"),
tower = c("UEB", "STC", "BAN", "MSK"),
airport = smn.stn[!is.na(airport), stn]
)
dt.class <- rbindlist(lapply(def.class, function(i) data.table(stn = i)), idcol = "class")
smn.stn[, stn_type := dplyr::case_when(
stn %in% def.class$city ~ "city",
stn %in% def.class$tower ~ "tower",
stn %in% def.class$mountain ~ "mountain",
stn %in% def.class$airport ~ "airport",
grepl("H|Q", para_list) ~ "hydro",
grepl("tt|ff|fx", para_list) ~ "weather",
grepl("\\bpp\\b", para_list) ~ "pp",
grepl("pp_1d", para_list) ~ "pp_1d",
grepl("snow", para_list) ~ "snow",
TRUE ~ NA_character_
)]
smn.stn[stn == "ZOF"]
smn.stn[, .N, para_list]
smn.stn[, .N, stn_type]
smn.stn[is.na(stn_type)]
smn.stn.class <- merge(smn.stn[, .(stn, stn_type)], dt.class, by = "stn", allow.cartesian = T, all = T)
smn.stn.class <- smn.stn.class[, .(class = paste(na.omit(unique(c(stn_type, class))), collapse=",")), .(stn, stn_type)]
smn.stn.class[stn == "BIZ"]
smn.stn.class[class == "pp"]
smn.stn.class[, .N, class]
## --------------------------- Register ------------------------------
write.table(smn.stn, file.path("inst", "smn", "smn_stn.csv"),
sep = ",", na = "", row.names = F, append = F, fileEncoding = "UTF-8")
write.table(smn.stn.sensor.hist, file.path("inst", "smn", "smn_stn_sensor_hist.csv"),
sep = ",", na = "", row.names = F, append = F, fileEncoding = "UTF-8")
write.table(smn.stn.sensor, file.path("inst", "smn", "smn_stn_sensor.csv"),
sep = ",", na = "", row.names = F, append = F, fileEncoding = "UTF-8")
write.table(smn.stn.class, file.path("inst", "smn", "smn_stn_class.csv"),
sep = ",", na = "", row.names = F, append = F, fileEncoding = "UTF-8")
smn.stn <- data.table::fread("inst/smn/smn_stn.csv")
smn.stn.name <- data.table::fread("inst/smn/smn_stn_name.csv")
smn.stn.sensor <- data.table::fread("inst/smn/smn_stn_sensor.csv")
smn.stn.sensor.hist <- data.table::fread("inst/smn/smn_stn_sensor_hist.csv")
smn.stn.class <- data.table::fread("inst/smn/smn_stn_class.csv")
usethis::use_data(
smn.stn,
smn.stn.name,
smn.stn.sensor,
smn.stn.sensor.hist,
smn.stn.class,
overwrite = TRUE, internal = FALSE
)
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.