#' Plot long profile for a DRV
#' @param Name Name of the DRV
#' @param case.list List of cases to plot, default is all
#' @param case.desc Standard naming of case.list
#' @param sobek.project Path to sobek project
#' @param param dicharge/waterlevel
#' @param lt.by Linetype defining by this value
#' @param color.by Coloring by this value
#' @param facet.by Facetting by this value
#' @param compare.by Calculating delta by this value. Default 'zustand'
#' @param cmp.sort Should comparing parameter be sorted. Default is FALSE
#' @param group.by Groupping for delta calculation
#' @param color.name Name of color in the legend
#' @param lt.name Name of linetype in the legend
#' @param delta Should delta line also be plotted?
#' @param delta.lt Linetype discretization for Delta lines (vgf, zustand, hwe...)
#' @param reverse.x Logical. If TRUE the x-axis will be reversed
#' @param x.lab x-axis label
#' @param y.lab y-axis label
#' @param to.upstream distance (km) to upstream of the DRV to be included in the graphic
#' @param to.downstream distance (km) to downstream of the DRV to be included in the graphic
#' @param y2.scale scale of y2-axis. Default value will be automatic calculated.
#' @param y2.tick1 The value of the first tick on the y2-axis. Using this and y2.scale to make y2-axis looks nice.
#' @param plot.title Title of the graphic
#' @param text.size Size of text
#' @param text.x.top.angle Angle of text at top
#' @param text.x.bottom.angle Angle of text at bottom
#' @param ntick.x Minimum number of ticks on x-axis. Default = 10
#' @param a.fill Fill color of the highlight area
#' @param a.alpha Transparent ratio (alpha blending) of the highlight area
#' @param overlap List of overlap labels should be avoid
#' @param master.tbl Master table
#' @param man.colors Using for scale_color_manual. Default is NULL (auto coloring)
#' @param hqs Adding HQ Statistic points to the graphic
#' @param verbose Print some messages if TRUE
#' @param do.par If TRUE, parallel computing will be executed
#' @param ts.trim.left Default NULL. Number of days from the begining of simulation time to remove from timeseries (useful to remove "cold start period")
#' @return a ggplot2 graphic
#' @export
plot_drv <- function(
name = NULL,
case.list = NULL,
case.desc = case.list,
sobek.project = NULL,
param = 'discharge',
lt.by = 'zustand',
color.by = 'vgf',
facet.by = NULL,
compare.by = NULL,
cmp.sort = FALSE,
group.by = compare.by,
color.name = 'Farbe',
lt.name = 'Linienart',
delta = FALSE,
delta.lt = compare.by,
reverse.x = FALSE,
x.lab = 'Lage (KM)',
y.lab = ifelse(param == 'discharge',
'Abfluss [m³/s]', 'Wasserstand [m+NHN]'),
to.upstream = 0,
to.downstream = 0,
y2.scale = NULL,
y2.tick1 = NULL,
plot.title = NULL,
text.size = 12,
text.x.top.angle = 90L,
text.x.top.size = 8L,
text.x.bottom.angle = 0L,
line.size = 1.0,
ntick.x = 10L,
ntick.y = 7L,
a.fill = exl_std[3],
a.alpha = 0.1,
overlap = NULL,
master.tbl = NULL,
man.colors = NULL,
hqs = NULL,
verbose = TRUE,
do.par = FALSE,
ts.trim.left = NULL
){
if (!is.null(ts.trim.left)) stopifnot(is.numeric(ts.trim.left))
# preparing parameters--------------------------------------------------------
param <- tolower(param)
stopifnot(is.numeric(to.upstream) & is.numeric(to.downstream))
case_tbl <- parse_case(case.desc = case.desc, orig.name = case.list)
if (!is.null(compare.by)) {
if (!compare.by %in% c('zustand', 'vgf', 'notiz', 'zielpegel', 'hwe')) {
stop("compare.by must be one of ('zustand', 'vgf', 'notiz', 'zielpegel', 'hwe')")
}
cmp_vars <- unique(case_tbl[, get(compare.by)])
if (cmp.sort) cmp_vars <- sort(cmp_vars)
if (length(cmp_vars) != 2 & delta) {
stop('compare.by must have two values not: ',
str_flatten(cmp_vars, collapse = ", " ))
}
}
if (!is.null(group.by)) {
if (length(group.by) == 1) {
if (!group.by %in% c('hwe', 'zustand', 'vgf', 'notiz', 'zielpegel')) {
stop("group.by must be one of ('hwe', 'zustand', 'vgf', 'notiz', 'zielpegel')")
}
} else {
case_tbl[, group__by := paste(get(group.by[1]),
get(group.by[2]),
sep = "_"
)
]
group.by <- "group__by"
}
grp_vars <- unique(case_tbl[, get(group.by)])
}
if (delta) {
if (is.null(compare.by) | is.null(group.by)) {
stop('For caculating delta, compare.by and group.by must be specified!')
}
total_case <-
unique(as.vector(outer(cmp_vars, grp_vars, paste, sep = "_")))
if (compare.by != group.by) {
if (length(total_case) != length(case.list)) {
stop("Combination of compare.by and group.by is not distinct
for calculating delta")
}
} else{
if (!near(length(total_case) / 2, length(case.list), 0.1)) {
stop("Combination of compare.by and group.by is not distinct
for calculating delta")
}
}
}
if (is.null(plot.title)) {
plot.title <- paste('Längsschnitt',
str_extract(y.lab, 'Abfluss|Wasserstand'),
'entlang DRV:', name
)
}
#----get data----
if (verbose) cat('Reading data...\n')
data_tbl <- get_drv_data(name = name,
case.list = case.list,
case.desc = case.desc,
sobek.project = sobek.project,
param = param,
master.tbl = master.tbl,
to.upstream = to.upstream,
to.downstream = to.downstream,
get.max = TRUE,
do.par = do.par,
verbose = verbose,
ts.trim.left = ts.trim.left)
data_tbl <- merge(data_tbl, case_tbl, by = 'case', sort = FALSE)
# data_tbl[, besonderheit := gsub('DRV_', '', besonderheit)]
drv_begin_tick <- master.tbl[
grepl(
pattern = paste("DRV", name, 'Begin', sep = "_"),
x = besonderheit
),
km
]
drv_end_tick <- master.tbl[
grepl(
pattern = paste("DRV", name, 'End', sep = "_"),
x = besonderheit
),
km
]
b_tick <- data_tbl[case == case.list[[1]] &
nchar(besonderheit) > 0,
c("km", "besonderheit")
]
# processing overlap labels
if (!is.null(overlap)) {
for (i in seq_along(overlap)) {
# overlap_i <- b_tick[grepl(overlap[[i]], besonderheit), besonderheit][[1]]
overlap_i_pos <- b_tick[grepl(overlap[[i]], besonderheit), which = TRUE]
if (isTRUE(overlap_i_pos > 1)) {
overlap_nchar <- nchar(b_tick[overlap_i_pos - 1, besonderheit])
b_tick[overlap_i_pos,
besonderheit := str_replace(besonderheit, 'Polder_|DRV_', '')]
b_tick[overlap_i_pos, besonderheit := paste(str_dup(' ', 2 * overlap_nchar),
'--', besonderheit)]
}
}
}
x_min <- data_tbl[, min(km, na.rm = TRUE)]
x_max <- data_tbl[, max(km, na.rm = TRUE)]
y1_min <- data_tbl[, min(scheitel, na.rm = TRUE)]
y1_max <- data_tbl[, max(scheitel, na.rm = TRUE)]
# procesisng HQS points
hqs_point <- FALSE
if (!is.null(hqs)) {
hqs <- melt(hqs, id.vars = c('Pegel', 'km'),
variable.name = 'HQ_Statistik', value.name = 'HQS') %>%
as.data.table()
hqs <- hqs[km >= from.km & km <= to.km]
hqs[, c('vgf', 'hwe', 'zustand', 'notiz', 'zielpegel') :=
list(NA, NA, NA, NA, NA)]
# check if there is a mistake to give HQS of Q to 'waterlevel'
if (min(hqs$HQS, na.rm = TRUE) > 5 * y1_max & param == 'waterlevel') {
warning('Check if HQ Statistik for Discharge was given for a graphic of waterlevel')
cat('HQ Statistik points have not been plotted.\n')
} else {
hqs_point <- TRUE
y1_min <- min(min(hqs$HQS, na.rm = TRUE), y1_min)
y1_max <- max(max(hqs$HQS, na.rm = TRUE), y1_max)
}
}
y1_length <- y1_max - y1_min
x_pretty <- pretty(x_min:x_max, ntick.x, ntick.x)
y1_pretty <- pretty(y1_min:y1_max, ntick.y, ntick.y)
#----delta == TRUE----
if (delta) {
# searching for KM that delta calculation is possible
km_4_delta <- unique(data_tbl[!is.na(scheitel)]$km)
y2_name <- paste('Delta',
ifelse(param == 'discharge', '[m³/s]', '(m)')
)
if (compare.by != group.by) {
lt.by <- compare.by
color.by <- group.by
data_tbl_delta <-
dcast.data.table(data_tbl[km %in% km_4_delta],
km ~ get(compare.by) + get(group.by),
value.var = 'scheitel')
for (i in grp_vars) {
col_i <- paste('Delta', i, sep = '_')
col_1 <- paste(cmp_vars[1], i, sep = '_')
col_2 <- paste(cmp_vars[2], i, sep = '_')
data_tbl_delta[, eval(col_i) := get(col_2) - get(col_1)]
data_tbl_delta[, eval(col_1) := NULL]
data_tbl_delta[, eval(col_2) := NULL]
}
data_tbl_delta <- melt(data_tbl_delta, id.vars = 'km',
variable.name = group.by,
value.name = 'delta',
sort = FALSE)
data_tbl_delta[, delta_color := get(group.by)]
data_tbl_delta[, eval(group.by) := str_replace(
get(group.by), 'Delta_', '')
]
data_tbl <- merge(data_tbl, data_tbl_delta, by = c('km', group.by),
all = TRUE,
sort = FALSE)
} else{
data_tbl_delta <-
dcast(data_tbl[km %in% km_4_delta], km ~ get(compare.by),
value.var = 'scheitel')
col_1 <- cmp_vars[1]
col_2 <- cmp_vars[2]
data_tbl_delta[, delta := get(col_1) - get(col_2)]
data_tbl_delta[, eval(col_1) := NULL]
data_tbl_delta[, eval(col_2) := NULL]
data_tbl_delta[, delta_color := paste('Delta',
str_to_sentence(compare.by))
]
data_tbl <-
merge(data_tbl, data_tbl_delta, by = 'km', all = TRUE, sort = FALSE,)
}
data_tbl[, delta := round(delta, 3)]
data_tbl[, Linienart := paste('Delta', get(delta.lt))]
y2_min <- min(data_tbl$delta, na.rm = TRUE)
y2_max <- max(data_tbl$delta, na.rm = TRUE)
y2_length <- y2_max - y2_min
if (y2_max - y2_min > 10) {
y2_min <- round(y2_min, -1)
} else {
if (abs(y2_min) > 1) y2_min <- floor(y2_min)
}
if (is.null(y2.scale)) {
y2.scale <- y1_length * 0.5 / y2_length
for (i in 0:3) {
if (abs(y2.scale) > 10 ** i)
y2.scale <- round(y2.scale, -i)
}
if (verbose) cat('tried with y2.scale =', y2.scale, '\n')
}
y2_shift <- y1_min - y2_min * y2.scale
y1_max <- max(y1_max, y2_max * y2.scale + y2_shift)
y1_min <- min(y1_min, y2_min * y2.scale + y2_shift)
y1_length <- y1_max - y1_min
if (y1_length < 10) {
y1_max_1 <- y1_max * 100
y1_min_1 <- y1_min * 100
y1_pretty <- pretty(y1_min_1:y1_max_1, ntick.y, ntick.y)
y1_pretty <- y1_pretty / 100
} else{
y1_pretty <- pretty(y1_min:y1_max, ntick.y, ntick.y)
}
check_y1_pretty <- (max(y1_pretty) - min(y1_pretty)) / (y1_max - y1_min)
if (length(y1_pretty) < 5 | check_y1_pretty > 1) {
y1_min_1 <- y1_min * 10
y1_max_1 <- y1_max * 10
y1_pretty <- pretty(y1_min_1:y1_max_1, ntick.y, ntick.y)
y1_pretty <- y1_pretty / 10
}
if (!is.null(y2.tick1)) {
y2_shift = y1_pretty[2] - y2.tick1 * y2.scale
}
y2_pretty <- (y1_pretty - y2_shift) / y2.scale
y2_pmin <- min(y2_pretty)
y2_pmax <- max(y2_pretty)
if (0 %between% c(y2_pmin, y2_pmax)) {
pos_y2_zero <- ceiling(abs(y2_pmax / (y2_pmax - y2_pmin)))
if (pos_y2_zero > length(y1_pretty)) pos_y2_zero <- length(y1_pretty)
y2_shift <- y1_pretty[pos_y2_zero]
y1_max <- max(y1_max, y2_max * y2.scale + y2_shift)
y1_min <- min(y1_min, y2_min * y2.scale + y2_shift)
y1_pretty <- pretty(y1_min:y1_max, 5, 5)
check_y1_pretty <- (max(y1_pretty) - min(y1_pretty)) / (y1_max - y1_min)
if (length(y1_pretty) < 5 | check_y1_pretty > 1) {
y1_min_1 <- y1_min * 10
y1_max_1 <- y1_max * 10
y1_pretty <- pretty(y1_min_1:y1_max_1, ntick.y, ntick.y)
y1_pretty <- y1_pretty/10
}
if (!is.null(y2.tick1)) {
y2_shift = y1_pretty[2] - y2.tick1 * y2.scale
}
y2_pretty <- (y1_pretty - y2_shift) / y2.scale
y2_pretty <- unique(sort(c(y2_pretty, 0)))
}
data_tbl[get(compare.by) == cmp_vars[2], delta := NA]
data_tbl[get(compare.by) == cmp_vars[2], delta_color := NA]
data_tbl[is.na(scheitel), delta := NA]
}
#----add graphic----
if (verbose) cat('Preparing graphic...\n')
# preparing data for highlighting DRV
setorderv(b_tick, cols = 'km', order = ifelse(reverse.x, -1, 1))
b_tick[grepl('DRV_([^,;]*)_Begin', besonderheit), drv_start := km]
b_tick[grepl('DRV_([^,;]*)_End', besonderheit), drv_end := km]
b_tick[grepl('DRV_([^,;]*)_Begin', besonderheit), drv_nr := .I]
data_tbl <- merge(data_tbl, b_tick, by = c('km', 'besonderheit'), all.x = TRUE,
sort = FALSE)
# finding DRV list for highlighting them correctly, due to overlapping
drv_list <- b_tick[grepl('DRV_([^,;]*)_Begin|DRV_([^,;]*)_End', besonderheit),
besonderheit] %>%
str_replace('DRV_', '') %>%
str_replace('_Beginn', '') %>%
str_replace('_Ende', '') %>%
unique()
# data_tbl <- merge(data_tbl, b_tick, by = c('km', 'besonderheit'), sort = FALSE)
g <- ggplot(data = data_tbl,
aes(x = km,
linetype = !!ensym(lt.by),
color = !!ensym(color.by),
y = scheitel)
) +
theme_bw(base_size = text.size) +
theme(legend.position = 'bottom',
legend.key.width = unit(2, "cm"),
axis.text.x.top =
element_text(angle = text.x.top.angle,
hjust = 0,
vjust = 0.5,
size = text.x.top.size),
axis.text.x.bottom =
element_text(angle = text.x.bottom.angle,
hjust = 0.5,
size = text.size)
) +
labs(title = plot.title) +
ylab(y.lab) +
scale_y_continuous(
breaks = y1_pretty,
labels = function(x) stri_replace_all_fixed(as.character(x), ".", ",")
)
if (reverse.x) {
g <- g +
scale_x_reverse(
name = x.lab,
breaks = x_pretty,
sec.axis = dup_axis(
breaks = b_tick$km,
labels = b_tick$besonderheit,
name = 'Station'
)
)
} else{
g <- g +
scale_x_continuous(
name = x.lab,
breaks = x_pretty,
sec.axis = dup_axis(
breaks = b_tick$km,
labels = b_tick$besonderheit,
name = 'Station'
)
)
}
g <- g + geom_line(size = line.size)
if (!is.null(man.colors)) {
g <- g + scale_color_manual(values = c(man.colors, man.colors, 'black'))
}
g$labels$colour <- color.name
g$labels$linetype <- lt.name
if (delta) {
g <- g + geom_line(
data = data_tbl,
aes(
y = delta * y2.scale + y2_shift,
color = delta_color,
linetype = 'Delta'
),
size = line.size
) +
scale_y_continuous(
breaks = y1_pretty,
labels = function(x) stri_replace_all_fixed(as.character(x), ".", ","),
sec.axis =
sec_axis(
trans = ~ (. - y2_shift) / y2.scale,
breaks = y2_pretty,
labels = function(x) stri_replace_all_fixed(as.character(x), ".", ","),
name = y2_name
)
)
}
for (i in seq_along(drv_list)) {
x_min <-
b_tick[grepl(paste('DRV', drv_list[i], 'Begin', sep = "_"), besonderheit),
drv_start]
x_max <-
b_tick[grepl(paste('DRV', drv_list[i], 'End', sep = "_"), besonderheit),
drv_end]
if (length(x_min) == 0 | length(x_max) == 0) next
g <- g + annotate(
'rect',
xmin = x_min,
xmax = x_max,
ymin = -Inf,
ymax = Inf,
fill = a.fill,
alpha = a.alpha
)
}
if (!is.null(facet.by)) {
g <- g + facet_grid(rows = ensym(facet.by))
}
# adding HQS Points
if (hqs_point) {
g <- g + geom_point(
mapping = aes(y = HQS, shape = HQ_Statistik),
color = 'black',
data = hqs,
size = 2
)
}
if (verbose) {
if (delta) cat('y2_shift =', y2_shift, 'and y2.scale =', y2.scale, '\n')
cat("done.")
}
return(g)
}
#' Plot long profile for a river segment
#'
#'
#' @param river Name of the river
#' @param from.km Start location (km)
#' @param to.km End location (km)
#' @param case.list List of cases to plot, default is all
#' @param case.desc Standard naming of case.list
#' @param sobek.project Path to sobek project
#' @param param dicharge/waterlevel
#' @param lt.by Linetype defining by this value
#' @param color.by Coloring by this value
#' @param compare.by Calculating delta by this value
#' @param cmp.sort Should comparing parameter be sorted. Default is FALSE
#' @param group.by Groupping for delta calculation
#' @param color.name Name of color in the legend
#' @param lt.name Name of linetype in the legend
#' @param color.nrow Number of rows for color legend
#' @param lt.nrow Number of rows for linetype legend
#' @param shape.nrow Number of rows for point shape legend
#' @param pt.size Point size
#' @param delta Should delta also plotted?
#' @param delta.lt Linetype discretization for Delta lines (vgf, zustand, hwe...)
#' @param dband Display max-min band of the delta
#' @param dband.label Display value of max-min band on second y-axis
#' @param reverse.x Logical. If TRUE the x-axis will be reversed
#' @param x.lab x-axis label
#' @param y.lab y-axis label
#' @param to.upstream distance (km) to upstream of the DRV to be included in the graphic
#' @param to.downstream distance (km) to downstream of the DRV to be included in the graphic
#' @param y2.scale scale of y2-axis. Default value will be automatic calculated
#' @param y2.tick1 The value of the first tick on the y2-axis. Using this and y2.scale to make y2-axis looks nice.
#' @param y2.shift Manually set y2.shift (This will overwrite y2.tick1)
#' @param y2.zero if TRUE, a horizotal line at y2.zero will be plotted
#' @param y2.round Decimal place for y2.scale
#' @param plot.title Title of the graphic
#' @param text.size Base size for text
#' @param text.x.top.angle Angle of text at top
#' @param text.x.bottom.angle Angle of text at bottom
#' @param line.size Size for lines
#' @param ntick.x Minimum number of ticks on x-axis. Default = 10
#' @param highlight A vector of two locations (km), ex. c(4, 10) to be highlighted
#' @param a.fill Fill color of the highlight area
#' @param a.alpha Transparent ratio (alpha blending) of the highlight area
#' @param overlap List of overlap labels should be avoid
#' @param talweg If TRUE, and param = waterlevel then the talweg line will be added
#' @param master.tbl Master table
#' @param man.colors Using for scale_color_manual. Default is NULL (auto coloring)
#' @param hqs Adding HQ Statistic points to the graphic
#' @param keep.data Output the original data table
#' @param input.data Take the input.data instead of reading it from sobek.project
#' @param verbose Print some messages if TRUE
#' @param do.par If TRUE, parallel computing will be executed
#' @param ts.trim.left Default NULL. Number of days from the begining of simulation time to remove from timeseries (useful to remove "cold start period")
#' @param remove.inf Remove segment without data
#' @return a ggplot2 graphic
#' @export
plot_longprofile_old <- function(
river = NULL,
from.km = -Inf,
to.km = Inf,
case.list,
case.desc = case.list,
sobek.project,
param = 'discharge',
compare.by = 'zustand',
group.by = compare.by,
lt.by = compare.by,
color.by = group.by,
delta.lt = compare.by,
color.name = 'Farbe',
lt.name = 'Linienart',
cmp.sort = FALSE,
color.nrow = 3,
lt.nrow = 3,
shape.nrow = 2,
pt.size = 2.5,
delta = FALSE,
dband = TRUE,
dband.label = FALSE,
reverse.x = FALSE,
x.lab = 'Lage (KM)',
y.lab = ifelse(param == 'discharge',
'Abfluss [m³/s]', 'Wasserstand [m+NHN]'),
y2.scale = NULL,
y2.tick1 = NULL,
y2.shift = NULL,
y2.zero = FALSE,
y2.round = 2L,
plot.title = NULL,
text.size = 12L,
text.x.top.angle = 90L,
text.x.top.size = 8L,
text.x.bottom.angle = 0L,
line.size = 1.0,
ntick.x = 10L,
ntick.y = 7L,
highlight = NULL,
highlight.text = NULL,
a.fill = 'grey',
a.alpha = 0.5,
overlap = NULL,
talweg = FALSE,
master.tbl,
man.colors = NULL,
hqs = NULL,
keep.data = FALSE,
input.data = NULL,
verbose = TRUE,
do.par = FALSE,
ts.trim.left = NULL,
fav = TRUE,
remove.inf = FALSE
){
# must evaluate lt.by and color.by to avoid problem with ggplot
eval(lt.by)
eval(color.by)
if (!delta) dband <- FALSE
# preparing parameters--------------------------------------------------------
param <- tolower(param)
stopifnot(length(unique(case.list)) == length(case.list))
stopifnot(is.numeric(from.km) & is.numeric(to.km))
stopifnot(to.km > from.km)
if (!is.null(highlight)) {
stopifnot(is.numeric(highlight) & length(highlight) > 1)
if (!is.null(highlight.text)) {
stopifnot(length(highlight.text) > 1)
}
}
case_tbl <- parse_case(case.desc = case.desc, orig.name = case.list)
if (!is.null(compare.by)) {
if (!compare.by %in% c('zustand', 'vgf', 'notiz', 'hwe', 'zielpegel')) {
stop("compare.by must be one of ('zustand', 'hwe', 'vgf', 'notiz', 'zielpegel')")
}
cmp_vars <- unique(case_tbl[, get(compare.by)])
if (cmp.sort) cmp_vars <- sort(cmp_vars)
if (length(cmp_vars) != 2 & delta) {
if (length(case.list) != 1) stop('compare.by must have two values not: ',
str_flatten(cmp_vars, collapse = ", " ))
}
}
if (!is.null(group.by)) {
if (length(group.by) == 1) {
if (!group.by %in% c('hwe', 'zustand', 'vgf', 'notiz', 'zielpegel')) {
stop("group.by must be one of ('hwe', 'zustand', 'vgf', 'notiz', 'zielpegel')")
}
} else {
case_tbl[, group__by := paste(get(group.by[1]),
get(group.by[2]),
sep = "_"
)
]
group.by <- "group__by"
}
grp_vars <- unique(case_tbl[, get(group.by)])
}
if (delta) {
if (is.null(compare.by) | is.null(group.by)) {
stop('For caculating delta, compare.by and group.by must be specified!')
}
if (compare.by != group.by) {
total_case <- unique(as.vector(outer(cmp_vars, grp_vars, paste, sep = "_")))
if (length(total_case) != length(case.list)) {
cat("Combination of compare.by and group.by does not have the same length as case.list\n")
cat('Hint: notiz can be modified and used as a groupping parameter\n')
stop('Groupping by ', group.by,
' is not unique for calculating delta between ', compare.by)
}
}
}
river_ids <- master.tbl[, .N, by = river]
if (is.null(river)) {
setorder(river_ids, -N)
river <- river_ids$river[[1]]
} else{
stopifnot(river %in% river_ids$river)
}
#----get data----
if (is.null(input.data)) {
if (verbose) cat('Reading data...\n')
data_tbl <- get_segment_data(
river = river,
from.km = from.km,
to.km = to.km,
case.list = case.list,
case.desc = case.desc,
param = param,
get.max = TRUE,
sobek.project = sobek.project,
master.tbl = master.tbl,
verbose = verbose,
do.par = do.par,
ts.trim.left = ts.trim.left,
remove.inf = remove.inf
)
if (keep.data) {
dta <- copy(data_tbl)
}
} else {
keep.data <- FALSE
data_tbl <- input.data[km >= from.km & km <= to.km]
}
from.km <- max(min(data_tbl$km, na.rm = TRUE), from.km)
to.km <- min(max(data_tbl$km, na.rm = TRUE), to.km)
if (is.null(plot.title)) {
plot.title <- paste('Längsschnitt ',
str_extract(y.lab, 'Abfluss|Wasserstand'),
' entlang ', river, ' von KM ',
format(from.km, nsmall = 2, decimal.mark = ","),
' bis KM ',
format(to.km, nsmall = 2, decimal.mark = ","),
sep = ''
)
}
data_tbl <- merge(data_tbl, case_tbl, by = 'case', sort = FALSE)
x_min <- data_tbl[, min(km, na.rm = TRUE)]
x_max <- data_tbl[, max(km, na.rm = TRUE)]
y1_min <- data_tbl[, min(scheitel, na.rm = TRUE)]
y1_max <- data_tbl[, max(scheitel, na.rm = TRUE)]
# procesisng HQS points
hqs_point <- FALSE
if (!is.null(hqs)) {
hqs <- melt(hqs, id.vars = c('Pegel', 'km'),
variable.name = 'HQ_Statistik', value.name = 'HQS') %>%
as.data.table()
hqs <- hqs[km >= from.km & km <= to.km]
hqs[, c('vgf', 'hwe', 'zustand', 'notiz', 'zielpegel') :=
list(NA, NA, NA, NA, NA)]
# check if there is a mistake to give HQS of Q to 'waterlevel'
if (min(hqs$HQS, na.rm = TRUE) > 5 * y1_max & param == 'waterlevel') {
warning('Check if HQ Statistik for Discharge was given for a graphic of waterlevel')
cat('HQ Statistik points have not been plotted.\n')
} else {
hqs_point <- TRUE
y1_min <- min(min(hqs$HQS, na.rm = TRUE), y1_min)
y1_max <- max(max(hqs$HQS, na.rm = TRUE), y1_max)
}
}
y1_length <- y1_max - y1_min
x_pretty <- pretty(x_min:x_max, ntick.x, ntick.x)
y1_pretty <- pretty(y1_min:y1_max, ntick.y, ntick.y)
#----delta == TRUE----
if (delta) {
# searching for KM that delta calculation is possible
km_4_delta <- unique(data_tbl[!is.na(scheitel)]$km)
y2_name <- paste('Delta',
ifelse(param == 'discharge', '[m³/s]', '(m)')
)
if (compare.by != group.by) {
lt.by <- compare.by
color.by <- group.by
data_tbl_delta <-
dcast(data_tbl[!is.na(scheitel) & km %in% km_4_delta],
km ~ get(compare.by) + get(group.by),
value.var = 'scheitel')
for (i in grp_vars) {
col_i <- paste('Delta', i, sep = '_')
col_1 <- paste(cmp_vars[1], i, sep = '_')
col_2 <- paste(cmp_vars[2], i, sep = '_')
data_tbl_delta[, eval(col_i) := get(col_2) - get(col_1)]
data_tbl_delta[, eval(col_1) := NULL]
data_tbl_delta[, eval(col_2) := NULL]
}
data_tbl_delta <- melt(data_tbl_delta, id.vars = 'km',
variable.name = group.by,
value.name = 'delta',
sort = FALSE)
data_tbl_delta[, delta_color := get(group.by)]
data_tbl_delta[, eval(group.by) := str_replace(
get(group.by), 'Delta_', '')
]
data_tbl <- merge(data_tbl, data_tbl_delta, by = c('km', group.by),
all = TRUE,
sort = FALSE)
} else{
data_tbl_delta <-
dcast(data_tbl[!is.na(scheitel) & km %in% km_4_delta],
km ~ get(compare.by),
value.var = 'scheitel'
)
col_1 <- cmp_vars[1]
col_2 <- cmp_vars[2]
data_tbl_delta[, delta := get(col_1) - get(col_2)]
data_tbl_delta[, eval(col_1) := NULL]
data_tbl_delta[, eval(col_2) := NULL]
data_tbl_delta[, delta_color := paste('Delta',
str_to_sentence(compare.by))
]
data_tbl <-
merge(data_tbl, data_tbl_delta, by = 'km', all = TRUE, sort = FALSE,)
}
data_tbl[, delta := round(delta, 3)]
data_tbl[, Linienart := paste('Delta', get(delta.lt))]
y2_min <- min(data_tbl$delta, na.rm = TRUE)
y2_max <- max(data_tbl$delta, na.rm = TRUE)
y2_length <- y2_max - y2_min
if (y2_max - y2_min > 10) {
y2_min <- round(y2_min, -1)
} else {
if (abs(y2_min) > 1) y2_min <- floor(y2_min)
}
if (is.null(y2.scale)) {
y2.scale <- y1_length * 0.5 / y2_length
for (i in 0:3) {
if (abs(y2.scale) > 10 ** i)
y2.scale <- round(y2.scale, -i)
}
}
y2_shift <- y1_min - y2_min * y2.scale
y1_max <- max(y1_max, y2_max * y2.scale + y2_shift)
y1_min <- min(y1_min, y2_min * y2.scale + y2_shift)
y1_length <- y1_max - y1_min
if (y1_length < 10) {
y1_max_1 <- y1_max * 100
y1_min_1 <- y1_min * 100
y1_pretty <- pretty(y1_min_1:y1_max_1, ntick.y, ntick.y)
y1_pretty <- y1_pretty / 100
} else{
y1_pretty <- pretty(y1_min:y1_max, ntick.y, ntick.y)
}
check_y1_pretty <- (max(y1_pretty) - min(y1_pretty)) / (y1_max - y1_min)
if (length(y1_pretty) < 5 | check_y1_pretty > 1) {
y1_min_1 <- y1_min * 10
y1_max_1 <- y1_max * 10
y1_pretty <- pretty(y1_min_1:y1_max_1, ntick.y, ntick.y)
y1_pretty <- y1_pretty / 10
}
if (!is.null(y2.tick1)) {
y2_shift = y1_pretty[2] - y2.tick1 * y2.scale
}
y2_pretty <- (y1_pretty - y2_shift) / y2.scale
y2_pmin <- min(y2_pretty)
y2_pmax <- max(y2_pretty)
if (0 %between% c(y2_pmin, y2_pmax)) {
pos_y2_zero <- ceiling(abs(y2_pmax / (y2_pmax - y2_pmin)))
if (pos_y2_zero > length(y1_pretty)) pos_y2_zero <- length(y1_pretty)
y2_shift <- y1_pretty[pos_y2_zero]
y1_max <- max(y1_max, y2_max * y2.scale + y2_shift)
y1_min <- min(y1_min, y2_min * y2.scale + y2_shift)
y1_pretty <- pretty(y1_min:y1_max, ntick.y, ntick.y)
check_y1_pretty <- (max(y1_pretty) - min(y1_pretty)) / (y1_max - y1_min)
if (length(y1_pretty) < 5 | check_y1_pretty > 1) {
y1_min_1 <- y1_min * 10
y1_max_1 <- y1_max * 10
y1_pretty <- pretty(y1_min_1:y1_max_1, ntick.y, ntick.y)
y1_pretty <- y1_pretty/10
}
if (!is.null(y2.tick1)) {
y2_shift = y1_pretty[2] - y2.tick1 * y2.scale
}
y2_pretty <- (y1_pretty - y2_shift) / y2.scale
y2_pretty <- unique(sort(c(y2_pretty, 0)))
}
data_tbl[get(compare.by) == cmp_vars[2], delta := NA]
data_tbl[get(compare.by) == cmp_vars[2], delta_color := NA]
data_tbl[is.na(scheitel), delta := NA]
if (dband) {
round_nr <- ifelse(param == 'discharge', 0, y2.round)
d_min <- round(min(data_tbl$delta, na.rm = TRUE), round_nr)
d_max <- round(max(data_tbl$delta, na.rm = TRUE), round_nr)
data_tbl[, dband_min := min(delta, na.rm = TRUE), by = km]
data_tbl[, dband_max := max(delta, na.rm = TRUE), by = km]
data_tbl[is.infinite(dband_min), dband_min := NA]
data_tbl[is.infinite(dband_max), dband_max := NA]
}
}
#----add graphic----
b_tick <- data_tbl[case == case.list[[1]] &
nchar(besonderheit) > 0,
c("km", "besonderheit")
]
b_tick_river <- b_tick[grepl('Lat_|M_|Zufluss', besonderheit)]
b_tick <- b_tick[!besonderheit %in% b_tick_river$besonderheit]
b_tick_measure <- b_tick[grepl('RHR_|Polder_|DRV_|RRE_|Flutpolder', besonderheit)]
# processing overlap labels
if (!is.null(overlap)) {
for (i in seq_along(overlap)) {
overlap_i_pos <- b_tick[grepl(overlap[[i]], besonderheit), which = TRUE]
if (isTRUE(overlap_i_pos > 1)) {
overlap_nchar <- nchar(b_tick[overlap_i_pos - 1, besonderheit])
b_tick[overlap_i_pos,
besonderheit := str_replace(besonderheit, 'Polder_|DRV_', '')]
b_tick[overlap_i_pos, besonderheit := paste(str_dup(' ', 2 * overlap_nchar),
'--', besonderheit)]
}
}
}
if (verbose) cat('Preparing graphic...\n')
if (!is.null(compare.by)) {
data_tbl[[compare.by]] <- factor(data_tbl[[compare.by]],
levels = c(cmp_vars)
)
}
b_tick[, label := str_remove(besonderheit, 'M_|Lat_|Polder_|RHR_|RRE_|DRV_')]
b_tick_measure[, label := str_remove(besonderheit, 'Polder_|RHR_|RRE_|DRV_')]
b_tick_river[, label := str_remove(besonderheit, 'Polder_|RHR_|RRE_|DRV_')]
g_base <- ggplot(data = data_tbl,
aes(x = km,
linetype = !!ensym(lt.by),
color = !!ensym(color.by),
y = scheitel)
) +
theme_bw(base_size = text.size) +
theme(legend.position = 'bottom',
legend.key.width = unit(2, "cm"),
axis.text.x.top =
element_text(angle = text.x.top.angle,
hjust = 0,
vjust = 0.5,
size = text.x.top.size),
axis.text.x.bottom =
element_text(angle = text.x.bottom.angle,
hjust = 0.5,
size = text.size)
) +
labs(title = plot.title) +
ylab(y.lab)
if (nrow(b_tick_river) > 0) {
x_above_breaks <- b_tick[!besonderheit %in% b_tick_river$besonderheit, km]
x_above_labels <- b_tick[!besonderheit %in% b_tick_river$besonderheit, label]
} else {
x_above_breaks <- b_tick$km
x_above_labels <- b_tick$besonderheit
}
if (fav) {
sec_x_axis <- dup_axis(
breaks = x_above_breaks,
labels = x_above_labels,
name = 'Station'
)
} else {
sec_x_axis <- waiver()
}
if (reverse.x) {
g <- g_base +
scale_x_reverse(
name = x.lab,
breaks = x_pretty,
sec.axis = sec_x_axis
)
} else {
g <- g_base +
scale_x_continuous(
name = x.lab,
breaks = x_pretty,
sec.axis = sec_x_axis
)
}
g <- g + geom_line(size = line.size)
if (talweg & param == 'waterlevel') {
if (verbose) cat('Reading profile...\n')
pf_tbl <- get_profile_tbl(
case = case.list[[1]],
sobek.project = sobek.project
)[, c('def_id', 'zb')]
data_tbl <- merge(data_tbl, pf_tbl, by.x = 'ID_F', by.y = 'def_id',
sort = FALSE)
y1_min <- min(y1_min, data_tbl$zb, na.rm = TRUE)
y1_max <- max(y1_max, data_tbl$zb, na.rm = TRUE)
y1_pretty <- pretty(y1_min:y1_max, ntick.y, ntick.y)
if (delta) y2_pretty <- (y1_pretty - y2_shift) / y2.scale
g <- g + geom_line(data = data_tbl,
aes(
y = zb,
color = 'Talweg',
linetype = 'Talweg'
),
size = line.size)
}
if (!delta) g <- g + scale_y_continuous(
breaks = y1_pretty,
labels = function(x) stri_replace_all_fixed(as.character(x), ".", ",")
)
if (!is.null(man.colors)) {
g <- g + scale_color_manual(values = c(man.colors, man.colors))
}
if (delta) {
# manual setting for y2 axis
if (!is.null(y2.shift)) {
if (verbose) cat('Manual y2-axis setting with y2.scale and y2.shift, y2.tick1 was ignored!\n')
y2_shift <- y2.shift
y1_min <- min(y1_min, data_tbl$scheitel, na.rm = TRUE)
y1_max <- max(y1_max, data_tbl$scheitel, na.rm = TRUE)
if (hqs_point) {
y1_min <- min(min(hqs$HQS, na.rm = TRUE), y1_min)
y1_max <- max(max(hqs$HQS, na.rm = TRUE), y1_max)
}
y2_min <- (y1_min - y2_shift) / y2.scale
y2_max <- (y1_max - y2_shift) / y2.scale
if (dband.label) {
y2_min <- min(y2_min, d_min)
y2_max <- max(y2_max, d_max)
}
y1_min <- min(y2_min * y2.scale + y2_shift, y1_min)
y1_max <- max(y2_max * y2.scale + y2_shift, y1_max)
y1_pretty <- pretty(y1_min:y1_max, ntick.y, ntick.y)
y2_pretty <- (y1_pretty - y2_shift) / y2.scale
}
if (dband.label) {
y2_pretty <- sort(c(d_min, d_max, y2_pretty))
}
if (y2.zero) {
g <- g + geom_hline(yintercept = y2_shift,
color = 'black',
size = 0.5,
linetype = 'solid'
)
y2_pretty <- unique(sort(c(y2_pretty, 0)))
}
g <- g + geom_line(
data = data_tbl,
aes(
x = km,
y = delta * y2.scale + y2_shift,
color = delta_color,
linetype = Linienart
),
size = line.size
) +
scale_y_continuous(
breaks = y1_pretty,
labels = function(x) stri_replace_all_fixed(as.character(x), ".", ","),
sec.axis =
sec_axis(
trans = ~ (. - y2_shift) / y2.scale,
breaks = y2_pretty,
labels = function(x) stri_replace_all_fixed(as.character(x), ".", ","),
name = y2_name
)
)
}
#----adding highlight area----
# Consider to remove this
if (!is.null(highlight)) {
g <- g + annotate('rect',
xmin = highlight[[1]],
xmax = highlight[[2]],
ymin = -Inf, ymax = Inf,
fill = a.fill,
alpha = a.alpha
)
if (!is.null(highlight.text)) {
g <- g + annotate(
'text',
x = highlight[[1]],
y = y1_min + abs(y1_max - y1_min) / 2,
label = highlight.text[[1]],
angle = 90, vjust = 0, hjust = 0.5
) +
annotate(
'text',
x = highlight[[2]],
y = y1_min + abs(y1_max - y1_min) / 2,
label = highlight.text[[2]],
angle = 90, vjust = 0, hjust = 0.5
)
}
}
# adding HQS Points
if (hqs_point) {
g <- g + geom_point(
mapping = aes(y = HQS, shape = HQ_Statistik),
color = 'black',
data = hqs,
size = pt.size
)
}
g <- g + guides(
colour = guide_legend(nrow = color.nrow),
shape = guide_legend(nrow = shape.nrow),
linetype = guide_legend(nrow = lt.nrow)
)
if (dband) {
g <- g +
geom_ribbon(
aes(
x = km,
ymax = y2.scale * dband_min + y2_shift,
ymin = y2.scale * dband_max + y2_shift
),
color = NA,
linetype = 'dashed',
fill = a.fill,
alpha = a.alpha
)
}
# ----adding besonderheit symbol----
y_lims <- ggplot_build(g)$layout$panel_params[[1]]$y.range
if (nrow(b_tick_river) > 0 & fav) {
g <- g + geom_point(
data = data_tbl[km %in% b_tick_river$km],
aes(x = km, y = -Inf),
color = 'blue',
shape = '\u2191',
show.legend = FALSE,
size = 8
) +
geom_text(
data = data_tbl[km %in% b_tick_river$km][,
besonderheit := str_remove_all(besonderheit, "M_|Lat_")],
aes(x = km, y = y_lims[1], label = besonderheit),
color = 'blue',
size = 4,
angle = 45,
hjust = 0.5,
vjust = 0.5,
show.legend = FALSE
)
}
if (verbose) {
if (delta) cat('y2_shift =', y2_shift, 'and y2.scale =', y2.scale, '\n')
cat("done.")
}
g$labels$colour <- color.name
g$labels$linetype <- lt.name
if (keep.data) {
ret <- list(data_tbl = dta, g = g)
} else {
ret <- g
}
return(ret)
}
#' Plot long profile for a river segment
#'
#'
#' @param river Name of the river
#' @param from.km Start location (km)
#' @param to.km End location (km)
#' @param case.list List of cases to plot, default is all
#' @param case.desc Standard naming of case.list
#' @param sobek.project Path to sobek project
#' @param param dicharge/waterlevel
#' @param lt.by Linetype defining by this value
#' @param color.by Coloring by this value
#' @param compare.by Calculating delta by this value
#' @param cmp.sort Should comparing parameter be sorted. Default is FALSE
#' @param group.by Groupping for delta calculation
#' @param color.name Name of color in the legend
#' @param lt.name Name of linetype in the legend
#' @param color.nrow Number of rows for color legend
#' @param lt.nrow Number of rows for linetype legend
#' @param shape.nrow Number of rows for point shape legend
#' @param pt.size Point size
#' @param delta Should delta also plotted?
#' @param delta.lt Linetype discretization for Delta lines (vgf, zustand, hwe...)
#' @param dband Display max-min band of the delta
#' @param reverse.x Logical. If TRUE the x-axis will be reversed
#' @param x.lab x-axis label
#' @param y.lab y-axis label
#' @param to.upstream distance (km) to upstream of the DRV to be included in the graphic
#' @param to.downstream distance (km) to downstream of the DRV to be included in the graphic
#' @param y2.scale scale of y2-axis. Default value will be automatic calculated
#' @param y2.shift This value is to align the y2-Zero (at position y2.shift) to the main y-axis
#' @param y2.zero if TRUE, a horizotal line at y2.zero will be plotted
#' @param y2.round Decimal place for y2.scale
#' @param plot.title Title of the graphic
#' @param txt.size Base size for text
#' @param txt.top element_text() for the x-top
#' @param txt.bottom element_text() for the x-bottom
#' @param line.size Size for lines
#' @param delta.size Size for delta lines
#' @param ntick.x Minimum number of ticks on x-axis. Default = 10
#' @param a.fill Fill color of the highlight area
#' @param a.alpha Transparent ratio (alpha blending) of the highlight area
#' @param master.tbl Master table
#' @param man.colors Using for scale_color_manual. Default is NULL (auto coloring)
#' @param hqs Adding HQ Statistic points to the graphic
#' @param keep.data Output the original data table
#' @param input.data Take the input.data instead of reading it from sobek.project
#' @param verbose Print some messages if TRUE
#' @param do.par If TRUE, parallel computing will be executed
#' @param ts.trim.left Default NULL. Number of days from the begining of simulation time to remove from timeseries (useful to remove "cold start period")
#' @param remove.inf Remove segment without data
#' @return a ggplot2 graphic
#' @export
plot_longprofile <- function(
river = NULL,
from.km = -Inf,
to.km = Inf,
case.list,
case.desc = case.list,
sobek.project,
master.tbl,
param = 'discharge',
compare.by = 'zustand',
group.by = compare.by,
lt.by = 'zustand',
delta.lt = 'vgf',
color.name = 'Farbe',
lt.name = 'Linienart',
cmp.sort = FALSE,
color.nrow = 3,
lt.nrow = 3,
shape.nrow = 2,
pt.size = 2.5,
delta = FALSE,
dband = delta,
reverse.x = FALSE,
x.lab = NULL,
y.lab = ifelse(param == 'discharge',
'Abfluss [m³/s]', 'Wasserstand [m+NHN]'),
y2.scale = NULL,
y2.shift = NULL,
y2.zero = FALSE,
y2.round = 2L,
y2.name = "Scheitelreduktion",
plot.title = NULL,
txt.size = 12L,
txt.top = element_text(angle = 90, size = txt.size),
txt.bottom = element_text(angle = 0, size = txt.size),
line.size = 1.0,
delta.size = line.size,
ntick.x = 10L,
ntick.y = 7L,
a.fill = 'grey',
a.alpha = 0.5,
x.expand = expansion(0.02),
man.colors = six_colors,
hqs = NULL,
keep.data = FALSE,
input.data = NULL,
verbose = TRUE,
do.par = FALSE,
ts.trim.left = NULL,
fav = TRUE,
agg.fun = NULL,
get.max = TRUE,
talweg = FALSE,
remove.inf = TRUE
) {
# processing parameters ---------------------------------------------------
if (!delta) dband <- FALSE
param <- tolower(param)
stopifnot(length(unique(case.desc)) == length(case.desc))
stopifnot(is.numeric(from.km) && is.numeric(to.km))
stopifnot(to.km > from.km)
case_tbl <- parse_case(case.desc = case.desc, orig.name = case.list)
if (!is.null(compare.by)) {
for (a_cmp in compare.by) {
if (!a_cmp %in% c('hwe', 'zustand', 'vgf', 'notiz', 'zielpegel')) {
stop("group.by & compare.by must be a combination of ('hwe', 'zustand', 'vgf', 'notiz', 'zielpegel')")
}
}
case_tbl[, compare__by := do.call(paste, .SD), .SDcols = compare.by]
cmp_vars <- unique(case_tbl[, get(compare.by)])
if (!is.null(cmp.sort)) cmp_vars <- sort(cmp_vars, decreasing = cmp.sort)
if (length(cmp_vars) != 2 & delta) {
if (length(case.list) != 1) stop('compare.by must have two values not: ',
str_flatten(cmp_vars, collapse = ", " ))
}
}
if (!is.null(group.by)) {
for (a_grp in group.by) {
if (!a_grp %in% c('hwe', 'zustand', 'vgf', 'notiz', 'zielpegel')) {
stop("group.by & compare.by must be a combination of ('hwe', 'zustand', 'vgf', 'notiz', 'zielpegel')")
}
}
case_tbl[, group__by := do.call(paste, .SD), .SDcols = group.by
]
grp_vars <- unique(case_tbl[, group__by])
}
if (delta) {
if (is.null(compare.by) || is.null(group.by)) {
stop('For caculating delta, compare.by and group.by must be specified!')
}
total_case <- length(unique(as.vector(outer(cmp_vars, grp_vars, paste)))) / 2
if (total_case != length(case.desc)) {
cat("Combination of compare.by and group.by does not have the same length as case.desc\n")
cat('Hint: notiz can be modified and used as a groupping parameter\n')
stop('Groupping by ', paste(group.by, collapse = ' & '),
' is not unique for calculating delta between ',
paste(compare.by, collapse = ' & ')
)
}
}
river_ids <- master.tbl[, .N, by = river]
if (is.null(river)) {
river <- river_ids[N == max(N), river]
} else{
stopifnot(river %in% river_ids$river)
}
if (missing(x.lab)) x.lab <- paste(river, 'km', sep = '-')
#----processing data----
if (is.null(input.data)) {
if (verbose) cat('Reading data...\n')
data_tbl <- get_segment_data(
river = river,
from.km = from.km,
to.km = to.km,
case.list = case.list,
case.desc = case.desc,
param = param,
get.max = get.max,
agg.fun = agg.fun,
sobek.project = sobek.project,
master.tbl = master.tbl,
verbose = verbose,
do.par = do.par,
ts.trim.left = ts.trim.left,
remove.inf = remove.inf
)
if (keep.data) {
dta <- copy(data_tbl)
}
} else {
keep.data <- FALSE
data_tbl <- input.data[km >= from.km & km <= to.km]
}
from.km <- max(min(data_tbl$km, na.rm = TRUE), from.km)
to.km <- min(max(data_tbl$km, na.rm = TRUE), to.km)
y1_range <- range(data_tbl$scheitel)
data_tbl <- merge(data_tbl, case_tbl, by = 'case', sort = FALSE)
if (delta) {
# searching for KM that delta calculation is possible
km_4_delta <- unique(data_tbl[!is.na(scheitel)]$km)
if (!identical(compare.by, group.by)) {
data_tbl_delta <-
dcast.data.table(data_tbl[!is.na(scheitel) & km %in% km_4_delta],
km ~ compare__by + group__by,
value.var = 'scheitel')
for (i in grp_vars) {
col_1 <- paste(cmp_vars[1], i, sep = '_')
col_2 <- paste(cmp_vars[2], i, sep = '_')
data_tbl_delta[, eval(i) := get(col_2) - get(col_1)]
data_tbl_delta[, eval(col_1) := NULL]
data_tbl_delta[, eval(col_2) := NULL]
}
data_tbl_delta <- melt(data_tbl_delta, id.vars = 'km',
variable.name = 'group__by',
value.name = 'delta',
sort = FALSE)
round_digit <- ifelse(param == "discharge", 1, 3)
data_tbl_delta[, delta := round(delta, round_digit)]
data_tbl <- merge(data_tbl, data_tbl_delta, by = c('km', 'group__by'),
all = TRUE,
sort = FALSE)
} else{
data_tbl_delta <-
dcast(data_tbl[!is.na(scheitel) & km %in% km_4_delta],
km ~ compare__by,
value.var = 'scheitel'
)
col_1 <- cmp_vars[1]
col_2 <- cmp_vars[2]
data_tbl_delta[, delta := get(col_1) - get(col_2)]
data_tbl_delta[, eval(col_1) := NULL]
data_tbl_delta[, eval(col_2) := NULL]
data_tbl <-
merge(data_tbl, data_tbl_delta, by = 'km', all = TRUE, sort = FALSE)
}
data_tbl[, delta := round(delta, 3)]
y2_range <- range(data_tbl_delta$delta, na.rm = TRUE)
if (y2_range[2] - y2_range[1] == 0) y2_range[2] <- y2_range[1] + 1
if (dband) {
round_nr <- ifelse(param == 'discharge', 0, y2.round)
d_min <- round(min(data_tbl$delta, na.rm = TRUE), round_nr)
d_max <- round(max(data_tbl$delta, na.rm = TRUE), round_nr)
data_tbl[, dband_min := min(delta, na.rm = TRUE), by = km]
data_tbl[, dband_max := max(delta, na.rm = TRUE), by = km]
data_tbl[is.infinite(dband_min), dband_min := NA]
data_tbl[is.infinite(dband_max), dband_max := NA]
}
}
if (!is.null(delta.lt)) {
data_tbl[, delta_lt := paste('Delta', get(delta.lt))]
} else {
data_tbl[, delta_lt := "Delta"]
}
#----add graphic----
if (verbose) cat('Preparing graphic...\n')
g_base <- ggplot(data = data_tbl,
aes(x = km,
linetype = compare__by,
color = group__by,
y = scheitel)
) +
theme_bw(base_size = txt.size) +
theme(legend.position = 'bottom',
legend.key.width = unit(1.5, "cm"),
axis.text.x.top = txt.top,
axis.text.x.bottom = txt.bottom
) +
labs(title = plot.title) +
ylab(y.lab)
if (reverse.x) {
g <- g_base +
scale_x_reverse(
name = x.lab,
expand = x.expand,
breaks = pretty(from.km:to.km, ntick.x, ntick.x)
)
} else {
g <- g_base +
scale_x_continuous(
name = x.lab,
expand = x.expand,
breaks = pretty(from.km:to.km, ntick.x, ntick.x)
)
}
# +++add main lines -------------------------------------------------------
g <- g + geom_line(size = line.size)
# +++add hqs -------------------------------------------------------
if (!is.null(hqs) & param == 'discharge') {
hqs <- melt(hqs, id.vars = c('Pegel', 'km'),
variable.name = 'HQ Statistik', value.name = 'HQS') %>%
as.data.table()
hqs <- hqs[km >= from.km & km <= to.km]
y1_range <- range(y1_range, hqs$HQS, na.rm = TRUE)
hqs[, c('compare__by', 'group__by') := list(NA, NA)]
g <- g + geom_point(
mapping = aes(y = HQS, shape = `HQ Statistik`),
color = 'black',
data = hqs,
size = pt.size
)
}
# +++add manual colors -------------------------------------------------------
# create manual color vector
if (!is.null(man.colors)) {
mcolor_v <- vector(mode = 'character')
for (i in seq_along(grp_vars)) {
mcolor_v[[grp_vars[i]]] <- man.colors[i]
}
g <- g + scale_color_manual(
name = color.name,
values = mcolor_v
)
}
y1_range <- range(data_tbl[!is.infinite(scheitel), scheitel], na.rm = TRUE)
y1_breaks <- pretty(y1_range[1]:y1_range[2], ntick.y, ntick.y)
if (talweg & param == 'waterlevel') {
if (verbose) cat('Reading profile...\n')
pf_tbl <- get_profile_tbl(
case = case.list[[1]],
sobek.project = sobek.project
)[, c('def_id', 'zb')]
data_tbl <- merge(data_tbl, pf_tbl, by.x = 'ID_F', by.y = 'def_id',
sort = FALSE)
y1_range <- range(y1_range, data_tbl$zb, na.rm = TRUE)
y1_pretty <- pretty(y1_range[1]:y1_range[2], ntick.y, ntick.y)
# if (delta) y2_pretty <- (y1_pretty - y2_shift) / y2.scale
g <- g + geom_line(data = data_tbl,
aes(
y = zb,
color = 'Talweg',
linetype = 'Talweg'
),
size = line.size)
}
# +++add delta lines -------------------------------------------------------
# processing y2 scale
if (delta) {
if (!is.null(delta.lt)) {
delta_lt_vars <- paste('Delta', case_tbl[, unique(get(delta.lt))])
} else {
delta_lt_vars <- 'Delta'
}
y1_length <- abs(y1_range[2] - y1_range[1])
y2_length <- abs(y2_range[2] - y2_range[1])
y2_scale <- ifelse(is.null(y2.scale),
pretty(y1_length / y2_length)[1], y2.scale)
y2_shift <- ifelse(is.null(y2.shift), y1_breaks[1], y2.shift)
y1_range <- range(y1_range, y2_range * y2_scale + y2_shift)
y1_breaks <- pretty(y1_range[1]:y1_range[2], ntick.y, ntick.y)
y2_breaks <- (y1_breaks - y2_shift) / y2_scale
y2_breaks <- unique(c(0, y2_breaks))
y2_name <- paste0(y2.name, ' [',
ifelse(param == 'discharge', 'm³/s', 'm'),
']'
)
g <- g +
geom_line(
aes(y = delta * y2_scale + y2_shift, linetype = delta_lt),
data = data_tbl[compare__by == cmp_vars[1]],
size = delta.size
) +
scale_y_continuous(
name = y.lab,
breaks = y1_breaks,
labels = function(x) stri_replace_all_fixed(as.character(x), ".", ","),
sec.axis = sec_axis(
name = y2_name,
labels = function(x) stri_replace_all_fixed(as.character(x), ".", ","),
trans = ~(. - y2_shift) / y2_scale,
breaks = y2_breaks
)
) +
scale_linetype_discrete(
name = lt.name,
breaks = c(cmp_vars, delta_lt_vars)
)
# +++add dband -------------------------------------------------------
if (dband) {
data_tbl[, dband_min := min(delta, na.rm = TRUE), by = km]
data_tbl[, dband_max := max(delta, na.rm = TRUE), by = km]
data_tbl[is.infinite(dband_min), dband_min := NA]
data_tbl[is.infinite(dband_max), dband_max := NA]
g <- g +
geom_ribbon(
aes(
x = km,
ymax = y2_scale * dband_min + y2_shift,
ymin = y2_scale * dband_max + y2_shift
),
color = NA,
linetype = 'dashed',
fill = a.fill,
alpha = a.alpha
)
}
if (y2.zero) {
g <- g + geom_hline(yintercept = y2_shift,
size = 0.5, color = 'grey20')
}
} else {
g <- g + scale_y_continuous(
name = y.lab,
labels = function(x) stri_replace_all_fixed(as.character(x), ".", ","),
breaks = y1_breaks
)
}
g$labels$linetype <- lt.name
g$labels$colour <- color.name
g <- g + guides(
color = guide_legend(
nrow = color.nrow
),
linetype = guide_legend(
nrow = lt.nrow
),
shape = guide_legend(
nrow = shape.nrow
)
)
if (verbose & delta) cat("tried with y2_scale = ", y2_scale, " y2_shift = ",
y2_shift, "\n")
if (keep.data) {
return(list(g = g, data_tbl = dta))
} else {
return(g)
}
}
#' Add favorites to long profile graphic
#'
#'
#' @param g the long profile graphic
#' @param fav table of favorites
#' @param p_pos Symbol position for pegel, in percentage of y_limit
#' @param p_txt Text position for pegel
#' @param d_color Color for DRV
#' @param d_size Line size for DRV
#' @param d_angle Text angle for DRV
#' @param d_txt Text position for DRV
#' @param gs_color Color for polders
#' @param gs_size Point size for polders
#' @param gs_angle Text angle for polders
#' @param gs_txt Text position for polders
#' @return a ggplot
#' @export
add_station <- function(g,
fav,
p_pos = 1,
p_txt = 0.97,
p_color = 'blue',
p_size = 3,
p_angle = 0,
d_color = 'magenta',
d_size = 5,
d_angle = 0,
d_txt = Inf,
gs_txt = d_txt,
gs_color = 'black',
gs_size = 4,
gs_angle = 0) {
y_lims <- ggplot_build(g)$layout$panel_params[[1]]$y.range
# add NA columns to avoid "missing" variable warnings
fav[, compare__by := NA][, group__by := NA][, delta_lt := NA]
riv_fav <- fav[type == 'm']
riv_chk <- nrow(riv_fav) > 0
p_fav <- fav[type == 'p']
p_chk <- nrow(p_fav) > 0
gs_fav <- fav[type == 'gs']
gs_chk <- nrow(gs_fav) > 0
drv_fav <- fav[type == 'd']
drv_chk <- nrow(gs_fav) > 0
# add river
if (riv_chk) {
g <- g + geom_point(
aes(x = km, y = -Inf),
data = riv_fav,
color = 'blue',
shape = '\u2191',
show.legend = FALSE,
size = 8
) +
geom_text(
data = riv_fav,
aes(x = km, y = y_lims[1], label = akz),
color = 'blue',
size = 4,
angle = 90,
hjust = 0,
vjust = 0.5,
show.legend = FALSE
)
}
# add Pegel
if (p_chk) {
g <- g + geom_point(
aes(x = km, y = y_lims[2] * p_pos),
data = p_fav,
color = p_color,
shape = 'diamond',
show.legend = FALSE,
size = p_size
) +
geom_text(
data = p_fav,
aes(
x = km,
y = y_lims[2] * p_txt,
label = akz
),
color = p_color,
size = p_size,
angle = p_angle,
hjust = 0.5,
vjust = 1,
show.legend = FALSE
)
}
# add DRV
if (drv_chk) {
drv_fav[, x_end := max(km, na.rm = TRUE), by = label]
drv_fav[, akz := paste0('\n', akz)]
g <- g +
geom_segment(
aes(y = Inf,
yend = Inf,
xend = x_end),
color = d_color,
linetype = "solid",
data = drv_fav,
size = d_size
) +
geom_text(
aes(
x = (km + x_end) / 2,
y = y_lims[2] * d_txt,
label = akz
),
data = drv_fav,
check_overlap = TRUE,
color = d_color,
angle = d_angle,
vjust = 1,
hjust = 0.5
)
}
# add Polders
if (gs_chk) {
gs_fav[, akz := paste0('\n', akz)]
g <- g +
geom_point(
aes(y = Inf),
color = gs_color,
data = gs_fav,
size = gs_size
) +
geom_text(
aes(y = y_lims[2] * gs_txt, label = akz),
data = gs_fav,
check_overlap = TRUE,
color = gs_color,
angle = gs_angle,
vjust = 1,
hjust = 0.5
)
}
g
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.