Skip to contents

Background

One measurement chain consists of six sensors that are placed in one production well, but at different filter depths. In total, three measurement chains will be installed in three different production wells.

Table 1 below lists all individual sensors. The number of the sensor within the well is given in column sensor_endnummer. The identifier of the production well that the sensor is located in is given in column brunnen_nummer.

Each sensor (type: WLF05, TODO: add-link-to-factsheet-on-kwb-cloud) measures two parameters with the following characteristics:

  • electrical conductivity:
    • measurement range: 0 - 20 mS
    • measurement range detection: automatic
    • typical accuracy: +/- 1.5 % of measurement value
  • temperature:
    • measurement range: 0 - 50 degree Celsius
    • measurement resolution: 0.1 Kelvin
    • typical accuracy: <= 0.1 Kelvin

The maximum temporal resolution that a sensor can provide is “every second”. Within the GeoSalz project, measurements are taken every 5 minutes. This should be sufficient to detect potential salinity shifts that are caused by changes in the pumping regime.

Data Management

Define Paths

# Define paths to directories, using <placeholder> replacements
paths <- kwb.utils::resolve(list(
  
  # Local temporary directory
  local_dir = kwb.geosalz:::temp_dir(),
  
  # Target directory for downloaded measurement chain files (.csv)
  download_dir = "<local_dir>/download", 
 
  # Local directory for aggregated data (.csv and .zip)
  export_dir = "<local_dir>/export", 
 
  # KWB cloud directory to which data in "export_dir" is uploaded
  upload_dir = "projects/GeoSalz/Monitoring/messketten",
  
  # KWB cloud directory with latest BWB well operation data
  well_operation = "<upload_dir>/BWB_Brunnen_Prozessdaten"
))
#> The directory "C:\Users\RUNNER~1\AppData\Local\Temp/R_kwb.geosalz" was created.

# Print all paths
paths
#> $local_dir
#> [1] "C:\\Users\\RUNNER~1\\AppData\\Local\\Temp/R_kwb.geosalz"
#> 
#> $download_dir
#> [1] "C:\\Users\\RUNNER~1\\AppData\\Local\\Temp/R_kwb.geosalz/download"
#> 
#> $export_dir
#> [1] "C:\\Users\\RUNNER~1\\AppData\\Local\\Temp/R_kwb.geosalz/export"
#> 
#> $upload_dir
#> [1] "projects/GeoSalz/Monitoring/messketten"
#> 
#> $well_operation
#> [1] "projects/GeoSalz/Monitoring/messketten/BWB_Brunnen_Prozessdaten"

Define SFTP Login

Run usethis::edit_r_environ() to edit the .Renviron file. The file defines environment variables that are to be made accessible during an R session. Add the following three rows, defining three more environment variables, to the file. The environment variables are required to log in to the SFTP server from which input data are downloaded.

MESSKETTEN_SERVER=<sftp_url>
MESSKETTEN_USER=<sftp_username>
MESSKETTEN_PASSWORD=<sftp_userpassword>

Replace the placeholders <sftp_url>, <sftp_username>, <sftp_userpassword> with the URL, the user name, and the password, respectively, that are required to get access to the SFTP server.

Save the .Renviron file and restart the R session (e.g. with “Session/Restart R” from the menu in RStudio) to make the environment variables available in R.

In case that the SFTP login credentials are correct, the code below should work. It downloads the measurement chains data (i.e. parameters electrical conductivity and temperature) from the SFTP server to a user-defined directory on your local device.

Data Download

What files are available on the SFTP server?

# Metadata of measurement chains (see also Table 1 above)
metadata <- kwb.geosalz::get_measurementchains_metadata()
str(metadata)
#> spc_tbl_ [18 × 10] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
#>  $ galerie               : chr [1:18] "K" "K" "K" "K" ...
#>  $ brunnen_nummer        : int [1:18] 9 9 9 9 9 9 10 10 10 10 ...
#>  $ dn                    : int [1:18] 400 400 400 400 400 400 600 600 600 600 ...
#>  $ einbau_pumpe          : chr [1:18] "über Filter" "über Filter" "über Filter" "über Filter" ...
#>  $ einbau_messkette      : chr [1:18] "unter Pumpe" "unter Pumpe" "unter Pumpe" "unter Pumpe" ...
#>  $ filteroberkante_muGOK : num [1:18] 21 21 21 21 21 21 11 11 11 11 ...
#>  $ filterunterkante_muGOK: num [1:18] 27 27 27 27 27 27 18 18 18 18 ...
#>  $ sensor_id             : int [1:18] 4182018 4182017 4182016 4182015 4182014 4182013 4182006 4182005 4182004 4182003 ...
#>  $ sensor_endnummer      : int [1:18] 8 7 6 5 4 3 6 5 4 3 ...
#>  $ einbau_sensor_muGOK   : num [1:18] 21.5 22.5 23.5 24.5 25.5 26.5 11.5 12.7 13.9 15.1 ...
#>  - attr(*, "spec")=
#>   .. cols(
#>   ..   galerie = col_character(),
#>   ..   brunnen_nummer = col_integer(),
#>   ..   dn = col_integer(),
#>   ..   einbau_pumpe = col_character(),
#>   ..   einbau_messkette = col_character(),
#>   ..   filteroberkante_muGOK = col_double(),
#>   ..   filterunterkante_muGOK = col_double(),
#>   ..   sensor_id = col_integer(),
#>   ..   sensor_endnummer = col_integer(),
#>   ..   einbau_sensor_muGOK = col_double()
#>   .. )
#>  - attr(*, "problems")=<externalptr>

# Information on available measurement chain files on SFTP server
mc_files <- kwb.geosalz::get_measurementchains_files()

str(mc_files)
#> 'data.frame':    13553 obs. of  16 variables:
#>  $ rights          : chr  "-rw-r--r--" "-rw-r--r--" "-rw-r--r--" "-rw-r--r--" ...
#>  $ links           : chr  "1" "1" "1" "1" ...
#>  $ ownername       : chr  "1011" "1011" "1011" "1011" ...
#>  $ ownergroup      : chr  "1002" "1002" "1002" "1002" ...
#>  $ filesize        : chr  "4559" "4559" "4559" "4559" ...
#>  $ t1              : chr  "Oct" "Oct" "Oct" "Oct" ...
#>  $ t2              : chr  "24" "24" "24" "25" ...
#>  $ t3              : chr  "2022" "2022" "2022" "2022" ...
#>  $ sftp_path       : chr  "K09/4182013-2022-10-22-0606.csv" "K09/4182013-2022-10-23-0606.csv" "K09/4182013-2022-10-24-0606.csv" "K09/4182013-2022-10-25-0606.csv" ...
#>  $ type            : chr  "file" "file" "file" "file" ...
#>  $ galerie         : chr  "K" "K" "K" "K" ...
#>  $ brunnen_nummer  : int  9 9 9 9 9 9 9 9 9 9 ...
#>  $ prefix          : chr  "" "" "" "" ...
#>  $ sensor_id       : int  4182013 4182013 4182013 4182013 4182013 4182013 4182013 4182013 4182013 4182013 ...
#>  $ sensor_endnummer: int  3 3 3 3 3 3 3 3 3 3 ...
#>  $ datum_uhrzeit   : POSIXct, format: "2022-10-22 06:06:00" "2022-10-23 06:06:00" ...
head(mc_files)
#>       rights links ownername ownergroup filesize  t1 t2   t3
#> 1 -rw-r--r--     1      1011       1002     4559 Oct 24 2022
#> 2 -rw-r--r--     1      1011       1002     4559 Oct 24 2022
#> 3 -rw-r--r--     1      1011       1002     4559 Oct 24 2022
#> 4 -rw-r--r--     1      1011       1002     4559 Oct 25 2022
#> 5 -rw-r--r--     1      1011       1002     4559 Oct 26 2022
#> 6 -rw-r--r--     1      1011       1002     4559 Oct 27 2022
#>                         sftp_path type galerie brunnen_nummer prefix sensor_id
#> 1 K09/4182013-2022-10-22-0606.csv file       K              9          4182013
#> 2 K09/4182013-2022-10-23-0606.csv file       K              9          4182013
#> 3 K09/4182013-2022-10-24-0606.csv file       K              9          4182013
#> 4 K09/4182013-2022-10-25-0606.csv file       K              9          4182013
#> 5 K09/4182013-2022-10-26-0606.csv file       K              9          4182013
#> 6 K09/4182013-2022-10-27-0606.csv file       K              9          4182013
#>   sensor_endnummer       datum_uhrzeit
#> 1                3 2022-10-22 06:06:00
#> 2                3 2022-10-23 06:06:00
#> 3                3 2022-10-24 06:06:00
#> 4                3 2022-10-25 06:06:00
#> 5                3 2022-10-26 06:06:00
#> 6                3 2022-10-27 06:06:00

# All paths to files on the SFTP server
all_paths <- kwb.utils::selectColumns(mc_files, "sftp_path")

What data are already available on the Nextcloud server?

# Download existing data from the Nextcloud server. NULL is returned if there is
# no file "mc_data.zip" in the Nextcloud folder 
# "projects/GeoSalz/Monitoring/messketten"
old_data <- kwb.geosalz::get_measurement_chain_data_on_cloud()
#> The directory "~/../Downloads/nextcloud_4f419401d28" was created.
#> Downloading remote.php/dav/files/hsonne/projects/GeoSalz/Monitoring/messketten/mc_data.zip ... ok. (1.23 secs)
#old_data <- NULL

What files need to be downloaded from the SFTP server?

# Determine the SFTP paths of the files to be downloaded. Download all available
# files if there was no data on the Nextcloud yet. Otherwise, download only
# those files that have been added to the SFTP server since when this script was
# run the last time.
new_paths <- if (is.null(old_data)) {
  
  all_paths
  
} else {
  
  # Get SFTP paths from which data were originally retrieved
  old_paths <- unique(kwb.utils::selectColumns(old_data, "file"))
  
  # Determine the paths to the new files that need to be downloaded
  setdiff(all_paths, old_paths)
}

Download the new files from the SFTP server

# If there are new files to download, download them.
csv_files <- if (length(new_paths)) {
  
  # Download only the new measurement chain files (.csv) from the SFTP server
  kwb.geosalz::download_measurementchains_data(
    sftp_paths = new_paths,
    target_directory = paths$download_dir,
    debug = TRUE
  )
  
} # else NULL implicitly
#> The directory "C:\Users\RUNNER~1\AppData\Local\Temp/R_kwb.geosalz/download" was created.
#> Download 18 measurement chains files (using 3 CPU cores) to C:\Users\RUNNER~1\AppData\Local\Temp/R_kwb.geosalz/download ... ok. (24.65 secs)

str(csv_files)
#>  chr [1:18] "C:\\Users\\RUNNER~1\\AppData\\Local\\Temp/R_kwb.geosalz/download/K09/4182013-2024-11-22-0507.csv" ...

Data Import

The following code imports the downloaded measurement chains files (.csv) into R:

# Set the current data to the old data (may be NULL)
mc_data <- old_data

# If new files have been downloaded, import them into R
if (length(csv_files)) {
  
  # Import csv files using multiple CPU cores
  new_data <- kwb.geosalz::read_measurementchains_data(
    csv_files,
    run_parallel = TRUE,
    debug = TRUE
  )
  
  # Combine the new data with the existing data and reorder
  mc_data <- mc_data %>%
    rbind(new_data) %>%
    kwb.geosalz::order_measurement_chain_data()
}
#> Importing 18 measurement chains files (using 3 CPU cores) ... ok. (2.29 secs) 
#> Filtering out 'lab' measurements before '2022-09-27 11:00:00' (installation in K10) ... ok. (0.00 secs)

The following datasets were imported into R or already available in R:

mc_data_stats <- mc_data %>%
  kwb.geosalz::get_measurmentchains_data_stats() %>% 
  dplyr::arrange(
    .data$parameter, 
    dplyr::desc(.data$sensor_id)
  )

These cover the time period from 2022-09-27 11:00:00 to 2024-11-21 23:00:00 with a total of 195504 samples.

Data Export

debug <- TRUE

# Export "mc_data" to csv file
data_csv_path <- kwb.geosalz::write_measurementchains_data(
  mc_data,
  target_directory = paths$export_dir,
  to_zip = FALSE,
  debug = debug
)
#> Exporting provided dataset 'mc_data' to 'C:/Users/RUNNER~1/AppData/Local/Temp/R_kwb.geosalz/export/mc_data_20220927-110000TZ+01_20241121-230000TZ+01.csv' ... ok. (2.68 secs)

size_data_csv <- fs::file_size(data_csv_path)

# Export "mc_data" to zip file (~10x less disk space for test dataset)
data_zip_path <- kwb.geosalz::write_measurementchains_data(
  mc_data,
  target_directory = paths$export_dir,
  to_zip = TRUE,
  debug = debug
)
#> Exporting provided dataset 'mc_data' to 'C:/Users/RUNNER~1/AppData/Local/Temp/R_kwb.geosalz/export/mc_data_20220927-110000TZ+01_20241121-230000TZ+01.csv' ... ok. (2.67 secs) 
#> Exporting provided dataset 'mc_data' to 'C:\Users\RUNNER~1\AppData\Local\Temp/R_kwb.geosalz/export/mc_data.zip' and delete intermediate 'C:/Users/RUNNER~1/AppData/Local/Temp/R_kwb.geosalz/export/mc_data_20220927-110000TZ+01_20241121-230000TZ+01.csv' ... ok. (0.20 secs)

size_data_zip <- fs::file_size(data_zip_path)
size_data_csv / size_data_zip
#> 19.9

extract_data_timeperiod <- function(file) {
  basename(file) %>% 
    kwb.utils::replaceFileExtension("") %>%  
    stringr::str_remove("^mc[-|_]data")
}

# Define helper function to write a csv file in a target directory
write_csv <- function(df, postfix = "", target_dir) {
  fs::dir_create(target_dir)
  name <- deparse(substitute(df))
  file <- file.path(target_dir, paste0(name, postfix,  ".csv"))
  readr::write_csv(df, file)
  file
}

postfix <- extract_data_timeperiod(data_zip_path)
target_dir <- paths$export_dir

# Export data and metadata to csv files
stats_path <- write_csv(mc_data_stats, postfix, target_dir)
metadata_path <- write_csv(metadata, postfix, target_dir)
files_path <- write_csv(mc_files, postfix, target_dir)

# Define function that plots data to a pdf file
plot_to_pdf <- function(mc_data, para, target_dir = ".", debug = TRUE) {
  
  plots <- kwb.geosalz::plot_measurementchains(mc_data, para)
  
  sapply(names(plots), function(name) {
    path <-  file.path(target_dir, sprintf("mc_data_%s.pdf", name))
    kwb.utils::catAndRun(
      sprintf("Writting '%s' to '%s'", name, path),
      expr = {
        kwb.utils::preparePdf(path, width.cm = 25, height.cm = 15)
        on.exit(dev.off())
        print(plots[[name]])
        path
      }, 
      dbg = debug
    )
  })
}

pdf_files <- c(
  plot_to_pdf(mc_data, "Leitfaehigkeit", paths$export_dir), 
  plot_to_pdf(mc_data, "Temperatur", paths$export_dir)
)
#> Writting 'Leitfaehigkeit_K10' to 'C:\Users\RUNNER~1\AppData\Local\Temp/R_kwb.geosalz/export/mc_data_Leitfaehigkeit_K10.pdf' ...
#> ok. (0.86 secs) 
#> Writting 'Leitfaehigkeit_K13' to 'C:\Users\RUNNER~1\AppData\Local\Temp/R_kwb.geosalz/export/mc_data_Leitfaehigkeit_K13.pdf' ...
#> ok. (0.73 secs) 
#> Writting 'Leitfaehigkeit_K09' to 'C:\Users\RUNNER~1\AppData\Local\Temp/R_kwb.geosalz/export/mc_data_Leitfaehigkeit_K09.pdf' ...
#> ok. (0.60 secs) 
#> Writting 'Temperatur_K10' to 'C:\Users\RUNNER~1\AppData\Local\Temp/R_kwb.geosalz/export/mc_data_Temperatur_K10.pdf' ...
#> ok. (0.89 secs) 
#> Writting 'Temperatur_K13' to 'C:\Users\RUNNER~1\AppData\Local\Temp/R_kwb.geosalz/export/mc_data_Temperatur_K13.pdf' ...
#> ok. (0.57 secs) 
#> Writting 'Temperatur_K09' to 'C:\Users\RUNNER~1\AppData\Local\Temp/R_kwb.geosalz/export/mc_data_Temperatur_K09.pdf' ...
#> ok. (0.61 secs)

data_zip_path
#> [1] "C:\\Users\\RUNNER~1\\AppData\\Local\\Temp/R_kwb.geosalz/export/mc_data.zip"

The file size of the mc_data_20220927-110000TZ+01_20241121-230000TZ+01.csv file is 19.9 times larger compared to compressing it into mc_data.zip.

Data Upload

In order to automate the data management process the exported data these data will be uploaded to a restricted shared folder on the KWB cloud. For doing so the following environment variables need to be defined in case the code below should be run from a client computer. However, as these variables are defined in a GitHub actions workflow there is no need to do this locally.

NEXTCLOUD_URL = "https://<replace-with-kwb-cloud-url>"
NEXTCLOUD_USER = "<your-kwb-cloud-username>" # your username
NEXTCLOUD_PASSWORD = "your-nextcloud-app-password" ### see details below

Subsequently the following code is run for uploading the data:

# List paths of files to upload explicitly
upload_files <- kwb.geosalz:::exclude_missing_files(c(
  stats_path, 
  pdf_files,
  metadata_path, 
  files_path,
  data_zip_path
))

for (file in upload_files) {
  
  kwb.utils::catAndRun(
    messageText = paste("Uploading file", file),
    expr = try(kwb.nextcloud::upload_file(
      file = file, 
      target_path = paths$upload_dir
    )),
    dbg = TRUE
  )
}
#> Uploading file C:\Users\RUNNER~1\AppData\Local\Temp/R_kwb.geosalz/export/mc_data_stats.csv ... Uploading
#>   C:\Users\RUNNER~1\AppData\Local\Temp/R_kwb.geosalz/export/mc_data_stats.csv
#> to
#>   projects/GeoSalz/Monitoring/messketten ... ok. (1.38 secs) 
#> ok. (1.82 secs) 
#> Uploading file C:\Users\RUNNER~1\AppData\Local\Temp/R_kwb.geosalz/export/mc_data_Leitfaehigkeit_K10.pdf ... Uploading
#>   C:\Users\RUNNER~1\AppData\Local\Temp/R_kwb.geosalz/export/mc_data_Leitfaehigkeit_K10.pdf
#> to
#>   projects/GeoSalz/Monitoring/messketten ... ok. (3.65 secs) 
#> ok. (4.10 secs) 
#> Uploading file C:\Users\RUNNER~1\AppData\Local\Temp/R_kwb.geosalz/export/mc_data_Leitfaehigkeit_K13.pdf ... Uploading
#>   C:\Users\RUNNER~1\AppData\Local\Temp/R_kwb.geosalz/export/mc_data_Leitfaehigkeit_K13.pdf
#> to
#>   projects/GeoSalz/Monitoring/messketten ... ok. (1.55 secs) 
#> ok. (1.94 secs) 
#> Uploading file C:\Users\RUNNER~1\AppData\Local\Temp/R_kwb.geosalz/export/mc_data_Leitfaehigkeit_K09.pdf ... Uploading
#>   C:\Users\RUNNER~1\AppData\Local\Temp/R_kwb.geosalz/export/mc_data_Leitfaehigkeit_K09.pdf
#> to
#>   projects/GeoSalz/Monitoring/messketten ... ok. (1.51 secs) 
#> ok. (1.90 secs) 
#> Uploading file C:\Users\RUNNER~1\AppData\Local\Temp/R_kwb.geosalz/export/mc_data_Temperatur_K10.pdf ... Uploading
#>   C:\Users\RUNNER~1\AppData\Local\Temp/R_kwb.geosalz/export/mc_data_Temperatur_K10.pdf
#> to
#>   projects/GeoSalz/Monitoring/messketten ... ok. (1.60 secs) 
#> ok. (2.00 secs) 
#> Uploading file C:\Users\RUNNER~1\AppData\Local\Temp/R_kwb.geosalz/export/mc_data_Temperatur_K13.pdf ... Uploading
#>   C:\Users\RUNNER~1\AppData\Local\Temp/R_kwb.geosalz/export/mc_data_Temperatur_K13.pdf
#> to
#>   projects/GeoSalz/Monitoring/messketten ... ok. (1.27 secs) 
#> ok. (1.65 secs) 
#> Uploading file C:\Users\RUNNER~1\AppData\Local\Temp/R_kwb.geosalz/export/mc_data_Temperatur_K09.pdf ... Uploading
#>   C:\Users\RUNNER~1\AppData\Local\Temp/R_kwb.geosalz/export/mc_data_Temperatur_K09.pdf
#> to
#>   projects/GeoSalz/Monitoring/messketten ... ok. (1.38 secs) 
#> ok. (1.76 secs) 
#> Uploading file C:\Users\RUNNER~1\AppData\Local\Temp/R_kwb.geosalz/export/metadata.csv ... Uploading
#>   C:\Users\RUNNER~1\AppData\Local\Temp/R_kwb.geosalz/export/metadata.csv
#> to
#>   projects/GeoSalz/Monitoring/messketten ... ok. (0.79 secs) 
#> ok. (1.18 secs) 
#> Uploading file C:\Users\RUNNER~1\AppData\Local\Temp/R_kwb.geosalz/export/mc_files.csv ... Uploading
#>   C:\Users\RUNNER~1\AppData\Local\Temp/R_kwb.geosalz/export/mc_files.csv
#> to
#>   projects/GeoSalz/Monitoring/messketten ... ok. (1.49 secs) 
#> ok. (1.87 secs) 
#> Uploading file C:\Users\RUNNER~1\AppData\Local\Temp/R_kwb.geosalz/export/mc_data.zip ... Uploading
#>   C:\Users\RUNNER~1\AppData\Local\Temp/R_kwb.geosalz/export/mc_data.zip
#> to
#>   projects/GeoSalz/Monitoring/messketten ... ok. (1.32 secs) 
#> ok. (1.71 secs)

Download Well Operation Data from Cloud


mc_dat <- mc_data %>%  
  dplyr::left_join(metadata[,c("sensor_id", "einbau_sensor_muGOK")], by = "sensor_id") %>% 
  dplyr::left_join(mc_files %>% dplyr::select(sftp_path, galerie, brunnen_nummer),
                   by = c(file = "sftp_path"))


well_op_file <- kwb.nextcloud::list_files(path = paths$well_operation,
                                          full_info = TRUE) %>% 
  dplyr::filter(lastmodified == max(lastmodified))
#> Listing projects/GeoSalz/Monitoring/messketten/BWB_Brunnen_Prozessdaten


xlsx_file <- kwb.nextcloud::download_files(hrefs = well_op_file$href,
                                           target_dir = paths$export_dir)
#> Downloading /remote.php/dav/files/hsonne/projects/GeoSalz/Monitoring/messketten/BWB_Brunnen_Prozessdaten/FRI%20-%20K%20-%20Brunnenlaufzeiten%20und%20Q%20(Export%20f%c3%bcr%20KWB)2024-11-18.xlsx ... ok. (1.09 secs)

well_op_data <- readxl::read_xlsx(path = xlsx_file) %>% 
  janitor::clean_names() %>%
  dplyr::filter(.data$menge_summe_m3 < 2000)



separate_name_der_messstelle_gms <- function(string) {
  
tibble::tibble(
  wasserwerk = stringr::str_sub(string, 1L, 3L),
  galerie = stringr::str_sub(string, 4L, 4L) %>% toupper(),
  brunnen_nummer = stringr::str_sub(string, 5L, 9L) %>%
    stringr::str_remove_all(pattern = "-") %>% 
    as.integer(),
  unbekannter_buchstabe = stringr::str_sub(string, 10L, 10L) %>%
    stringr::str_remove_all(pattern = "-") %>% 
    as.character(),
  brunnen_baujahr = stringr::str_sub(string, 12L, 15L) %>%
    stringr::str_remove_all(pattern = "-") %>% 
    as.integer(),
  brunnen_bauart = stringr::str_sub(string, 16L, 16L) %>%
    stringr::str_remove_all(pattern = "-") %>% 
    as.character()
  )
}


well_op_data_meta <- well_op_data %>% 
  dplyr::bind_cols(separate_name_der_messstelle_gms(well_op_data$name_der_messstelle_gms))

Make combined EC and well operation plot

and upload on cloud.

well_ids <- c(9,10,13)

pdf_names <- sprintf("mc_and_q_well-%02d.pdf", well_ids)

target_dir <- "."
para <- "Leitfaehigkeit"
debug <- TRUE

### Make pdf for each well  
pdf_files <- sapply(well_ids, function(well_id) {
    path <-  file.path(target_dir, sprintf("mc-%s_and_abstraction_well-%02d.pdf", 
                                           para,
                                           well_id))
    kwb.utils::catAndRun(
      sprintf("Writting '%s' to '%s'", well_id, path),
      expr = {
        kwb.utils::preparePdf(path, landscape = TRUE)
        on.exit(dev.off())
        print(
          kwb.geosalz::plot_measurementchain_and_well_operation(
            mc_dat = mc_dat,
            well_op_data_meta = well_op_data_meta,
            brunnen_nr = well_id,
            para = para,
            date_min = as.Date("2023-05-10")))
        path
      }, 
      dbg = debug
    )
  })
#> Writting '9' to './mc-Leitfaehigkeit_and_abstraction_well-09.pdf' ...
#> Warning: Removed 16530 rows containing missing values or values outside the scale range
#> (`geom_line()`).
#> ok. (0.89 secs) 
#> Writting '10' to './mc-Leitfaehigkeit_and_abstraction_well-10.pdf' ...
#> Warning: Removed 26112 rows containing missing values or values outside the scale range
#> (`geom_line()`).
#> ok. (0.71 secs) 
#> Writting '13' to './mc-Leitfaehigkeit_and_abstraction_well-13.pdf' ...
#> Warning: Removed 14226 rows containing missing values or values outside the scale range
#> (`geom_line()`).
#> ok. (0.67 secs)
  
### Upload pdf files on cloud 
  
  for (file in  pdf_files) {
  
  kwb.utils::catAndRun(
    messageText = paste("Uploading file", file),
    expr = try(kwb.nextcloud::upload_file(
      file = file, 
      target_path = paths$upload_dir
    )),
    dbg = TRUE
  )}
#> Uploading file ./mc-Leitfaehigkeit_and_abstraction_well-09.pdf ... Uploading
#>   ./mc-Leitfaehigkeit_and_abstraction_well-09.pdf
#> to
#>   projects/GeoSalz/Monitoring/messketten ... ok. (1.11 secs) 
#> ok. (1.52 secs) 
#> Uploading file ./mc-Leitfaehigkeit_and_abstraction_well-10.pdf ... Uploading
#>   ./mc-Leitfaehigkeit_and_abstraction_well-10.pdf
#> to
#>   projects/GeoSalz/Monitoring/messketten ... ok. (0.91 secs) 
#> ok. (1.32 secs) 
#> Uploading file ./mc-Leitfaehigkeit_and_abstraction_well-13.pdf ... Uploading
#>   ./mc-Leitfaehigkeit_and_abstraction_well-13.pdf
#> to
#>   projects/GeoSalz/Monitoring/messketten ... ok. (0.81 secs) 
#> ok. (1.20 secs)