Compare Sensors
This example demonstrates how to compare daily mean values from two different sensors (plots) using R. It retrieves data for a specified variable and date range, processes it, and generates a line chart comparing the two sensors.
ICP Documentation
In this example, we will compare air temperature (code_variable = 'AT') data from two different plots (code_plot = '1203' and '1204') over the year 2023.
You can request data from the mm_mem table in the icp_download schema. The data is filtered by the date_observation column, which is a date type representing the date (YYYY-MM-DD) of the observation.
Script
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
# Compare data from two sensors by charting daily mean values over time
# Load necessary libraries
library(httr)
library(ggplot2)
# Configuration
data_schema <- 'icp_download'
dictionaries_schema <- 'icp_dictionaries'
table <- 'mm_mem'
host <- 'https://db.forstliche-umweltkontrolle.de/' # Supabase host
apikey <- '[apikey]'
start_date_observation <- '2023-01-01'
end_date_observation <- '2023-12-31'
code_variable <- 'AT' # e.g. AT, NR, TF https://icp-forests.org/documentation/Dictionaries/d_variable.html
code_plot_1 <- '1203' # Plot number 1
code_plot_2 <- '1204' # Plot number 2
# Function to fetch data by plot, variable, and date range
fetch_data <- function(schema, table, host, apikey, code_plot, code_variable, start_date, end_date) {
url <- paste0(host, "rest/v1/", table,
"?date_observation=gte.", start_date,
"&date_observation=lte.", end_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)
}
# Fetch data
data_1 <- fetch_data(data_schema, table, host, apikey, code_plot_1, code_variable, start_date_observation, end_date_observation)
data_2 <- fetch_data(data_schema, table, host, apikey, code_plot_2, code_variable, start_date_observation, end_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"
variable_unit <- variable_info$unit # e.g., "°C"
## Plot linechart comparing daily mean values from both sensors
data_1$code_plot <- as.factor(data_1$code_plot)
data_2$code_plot <- as.factor(data_2$code_plot)
# Create the plot
ggplot() +
geom_line(data = data_1, aes(x = as.Date(date_observation), y = daily_mean, color = code_plot), size = 1) +
geom_line(data = data_2, aes(x = as.Date(date_observation), y = daily_mean, color = code_plot), size = 1) +
labs(title = paste("Comparison of sensors example"),
x = "Date",
y = paste("Daily Mean", variable_description, "(", variable_unit, ")"),
color = "Plot Number") +
scale_color_manual(values = c("1203" = "blue", "1204" = "red")) +
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, "compare_sensors.png"), width = 16, height = 9, units = "in")import requests
import pandas as pd
import matplotlib.pyplot as plt
from datetime import datetime
import os
import io
# Configuration
data_schema = "icp_download"
dictionaries_schema = "icp_dictionaries"
table = "mm_mem"
host = "https://db.forstliche-umweltkontrolle.de/" # Supabase host
apikey = "[apikey]"
start_date_observation = "2023-01-01"
end_date_observation = "2023-12-31"
code_variable = "AT" # e.g., AT, NR, TF
code_plot_1 = "1203" # Plot number 1
code_plot_2 = "1204" # Plot number 2
# Function to fetch data by plot, variable, and date range
def fetch_data(schema, table, host, apikey, code_plot, code_variable, start_date, end_date):
url = f"{host}rest/v1/{table}"
# Postgrest query parameters
params = {
("date_observation", f"gte.{start_date}"),
("date_observation", f"lte.{end_date}"),
("code_variable", f"eq.{code_variable}"),
("code_plot", f"eq.{code_plot}"),
("select", "daily_mean,date_observation,code_variable,code_plot,daily_min,daily_max,instrument_seq_nr")
}
headers = {
"apikey": apikey,
"Authorization": f"Bearer {apikey}",
"Accept-Profile": schema,
"Accept": "text/csv"
}
response = requests.get(url, headers=headers, params=params)
if response.status_code != 200:
raise Exception(f"Failed to fetch data: {response.status_code} - {response.text}")
data = pd.read_csv(io.StringIO(response.text)) # Use io.StringIO here
return data
# Fetch data
data_1 = fetch_data(data_schema, table, host, apikey, code_plot_1, code_variable, start_date_observation, end_date_observation)
data_2 = fetch_data(data_schema, table, host, apikey, code_plot_2, code_variable, start_date_observation, end_date_observation)
# Sort data by date_observation
data_1 = data_1.sort_values(by="date_observation")
data_2 = data_2.sort_values(by="date_observation")
# Function to fetch variable info
def fetch_variable_info(schema, host, apikey, code_variable):
url = f"{host}rest/v1/d_variable"
params = {
"code": f"eq.{code_variable}",
"select": "description,unit"
}
headers = {
"apikey": apikey,
"Authorization": f"Bearer {apikey}",
"Accept-Profile": schema,
"Accept": "application/json"
}
response = requests.get(url, headers=headers, params=params)
if response.status_code != 200:
raise Exception(f"Failed to fetch variable info: {response.status_code} - {response.text}")
info = response.json()
return info[0]
variable_info = fetch_variable_info(dictionaries_schema, host, apikey, code_variable)
variable_description = variable_info["description"] # e.g., "Air Temperature"
variable_unit = variable_info["unit"] # e.g., "°C"
# Convert date_observation to datetime
data_1["date_observation"] = pd.to_datetime(data_1["date_observation"])
data_2["date_observation"] = pd.to_datetime(data_2["date_observation"])
# Plot line chart comparing daily mean values from both sensors
plt.figure(figsize=(16, 9))
plt.plot(data_1["date_observation"], data_1["daily_mean"], label="Plot 1203", color="blue", linewidth=2)
plt.plot(data_2["date_observation"], data_2["daily_mean"], label="Plot 1204", color="red", linewidth=2)
plt.title("Comparison of Sensors Example", fontsize=16)
plt.xlabel("Date", fontsize=14)
plt.ylabel(f"Daily Mean {variable_description} ({variable_unit})", fontsize=14)
plt.legend(title="Plot Number", fontsize=12)
plt.grid(True)
# Save the plot in the same directory as the script
script_dir = os.path.dirname(os.path.abspath(__file__))
plt.savefig(os.path.join(script_dir, "compare_sensors_py.png"), dpi=300)
#plt.show()API_KEY=[your_api_key]Output
The output is a line chart comparing the daily mean values of the specified variable from two different sensors (plots) over the selected date range. The chart includes a title, labeled axes, and a legend indicating the plot numbers.