Skip to content

Plots by Sensors

This example demonstrates how to retrieve and plot data from selected sensors at specific plots using R.

ICP Documentation

In this example, we request plots (code_plot) by the types of sensor types (code_variable) definied.

After fetching the data from the mm_mem table in the icp_download schema, we create a line chart showing daily mean values over time for the selected plot and sensor type. The line chart is saved as a PNG file in the same directory as the R script.

Script

Running the script you will be prompted to enter two values:

  1. Enter plot code (e.g. 1203 for Kienhorst, 1204, ...)
  2. Enter the sensor type of the sensor (e.g. AT for Air Temperature, NR, TF)

In this example, the start date is hard coded set to '2000-01-01' to fetch all available data from that date to today.

Environment Variable

Do not forget to create a .env file in the same directory as the R script including your API key.

If you do not have an API key yet, please see Getting Started

R
# Load necessary libraries
library(dotenv) # Load dotenv package
library(httr)
library(ggplot2)

# Get the directory of the current R script
script_dir <- dirname(sys.frames()[[1]]$ofile)

# Load environment variables from .env file
dotenv::load_dot_env(file = file.path(script_dir, ".env"))

# Configuration
data_schema <- 'icp_download'
dictionaries_schema <- 'icp_dictionaries'

table <- 'mm_mem'
host <- 'https://db.forstliche-umweltkontrolle.de/' # Supabase host
apikey <- Sys.getenv("API_KEY") # Get apikey from .env

# Check if apikey is available
if (apikey == "") {
    stop("API_KEY is not set in the .env file")
}

start_date_observation <- '2000-01-01'

# Function to fetch data by plot, variable, and date range
fetch_data <- function(schema, table, host, apikey, code_plot, code_variable, start_date) {
    url <- paste0(host, "rest/v1/", table,
        "?date_observation=gte.", start_date,
        "&code_variable=eq.", code_variable,
        "&code_plot=eq.", code_plot,
        "&select=daily_mean,date_observation,code_variable,code_plot,daily_min,daily_max,instrument_seq_nr"
    )
    # Accept-Profile header to specify schema

    response <- httr::GET(url, httr::add_headers(
        apikey = apikey,
        Authorization = paste("Bearer", apikey),
        `Accept-Profile` = schema,
        `Accept` = 'text/csv'
    ))
  
    if (response$status_code != 200) {
        stop("Failed to fetch data: ", response$status_code, " - ", httr::content(response, as = "text"))
    }
    data <- httr::content(response, as = "parsed", type = "text/csv", encoding = "UTF-8")
    return(data)
}

# Ask for code plot
# https://forstliche-umweltkontrolle.de/dauerbeobachtung/level-ii/
code_plot <- readline(prompt = "Enter the code_plot (e.g. 1203 for Kienhorst, 1204, ): ")

# Ask for sensor type
# https://icp-forests.org/documentation/Dictionaries/d_variable.html
code_variable <- readline(prompt = "Enter the code_variable (e.g. AT, NR, TF): ")

# Fetch data
data <- fetch_data(data_schema, table, host, apikey, code_plot, code_variable, start_date_observation)


# Get description and unit from icp_dictionaries.d_variable by code_variable
fetch_variable_info <- function(schema, host, apikey, code_variable) {

    url <- paste0(host, "rest/v1/d_variable?code=eq.", code_variable, "&select=description,unit")

    response <- httr::GET(url, httr::add_headers(
        apikey = apikey,
        Authorization = paste("Bearer", apikey),
        `Accept-Profile` = schema,
        `Accept` = 'application/json'
    ))
  
    if (response$status_code != 200) {
        stop("Failed to fetch variable info: ", response$status_code, " - ", httr::content(response, as = "text"))
    }
    info <- httr::content(response, as = "parsed", type = "application/json", encoding = "UTF-8")
    return(info[[1]])
}
variable_info <- fetch_variable_info(dictionaries_schema, host, apikey, code_variable)
variable_description <- variable_info$description # e.g., "Air Temperature"

# Might be null
variable_unit <- variable_info$unit # e.g., "°C"

## Plot linechart comparing daily mean values from both sensors
data$code_plot <- as.factor(data$code_plot)

# Create the plot
ggplot() +
    geom_line(data = data, aes(x = as.Date(date_observation), y = daily_mean, color = code_plot), linewidth = 1) +
    labs(title = paste("Plot:", code_plot, "- Variable:", variable_description),
         x = "Date",
         y = paste("Daily Mean", variable_description, ifelse(variable_unit == "", "", paste("(", variable_unit, ")")) ),
         color = "Plot Number") +
    scale_color_manual(values = c("1203" = "blue")) +
    theme_minimal() +
    theme(text = element_text(size = 16))

# Get the directory of the current R script
script_dir <- dirname(sys.frames()[[1]]$ofile)

# Save the plot in the same directory as the R script
ggsave(file.path(script_dir, paste0("sensor-by-range_", code_plot, "_", code_variable, ".png")), width = 16, height = 9, units = "in")

# Print a message indicating where the plot was saved
cat("Plot saved to:", file.path(script_dir, paste0("sensor-by-range_", code_plot, "_", code_variable, ".png")), "\n")

# End of script
bash
API_KEY=[your_api_key]

Output

After running the script, the line chart will be saved as a PNG file in the same directory as the R script. Below are some example outputs for different plot codes and sensor types.