library(scanr)5 SWaT PIT-502 Pressure Sensor: A Real-World Example
This example applies change-point detection to the PIT-502 pressure sensor in the Secure Water Treatment (SWaT) dataset.
5.1 Load the Data
Load the dataset and resample it at one-minute intervals for change-point detection.
head(swat) Timestamp PIT502 Normal/Attack
1 28/12/2015 10:00:00 AM 1.649953 Normal
2 28/12/2015 10:01:00 AM 1.649953 Normal
3 28/12/2015 10:02:00 AM 1.665972 Normal
4 28/12/2015 10:03:00 AM 1.681991 Normal
5 28/12/2015 10:04:00 AM 1.746067 Normal
6 28/12/2015 10:05:00 AM 1.681991 Normal
5.2 Choose Window Sizes
The largest candidate window is \(\lfloor n^{2/3}\rfloor\). The package helper selects 15 default window sizes between 20 minutes and that upper bound.
n <- nrow(swat)
window_sizes <- scanr::default_window_sizes(
n,
min_window = 100,
max_window = floor(n^(2 / 3)),
n_windows = 10,
seed = 400
)
window_sizes [1] 201 255 426 442 519 587 607 624 625 652
The PIT-502 measurements are standardized before detection. Standardization changes their units but preserves the locations of mean shifts.
x <- as.numeric(scale(swat[["PIT502"]]))5.3 Detect change-points
The R interface uses n_boot and random_state for bootstrap calibration and reproducibility.
fit_swat <- scan_cpd(
x,
window_sizes = window_sizes,
n_boot = 400,
vote_threshold = 0.15,
random_state = 100,
change_type = "mean",
n_jobs = -1
)
fit_swatscanr change-point result
observations: 17477
change points: 517, 1222, 1901, 2596, 3311, 4232, 4952, 5610, 6643, 7542, 8291, 8972, 9799, 10689, 11277, 12063, 12741, 13588, 13960, 14718, 15131, 15792, 16541, 17201
The fitted object stores change points as positions in the one-minute series. We can map those positions back to timestamps, observed pressures, and the dataset’s operating-state labels.
detected_changes <- swat[
fit_swat$change_points,
c("Timestamp", "PIT502", "Normal/Attack"),
drop = FALSE
]
cat("Number of change-points:", nrow(detected_changes), "\n")Number of change-points: 24
5.4 Visualize the Result
vis_change_points(
x,
fit_swat,
index = seq_along(x),
x_label = "Time",
y_label = "Standardized PIT-502 pressure",
title = "Mean changes in the SWaT PIT-502 pressure sensor"
)
5.5 Inspect the Vote Scree
The vote scree shows how much support each candidate location receives across the selected window sizes. The horizontal threshold corresponds to the vote_threshold = 0.15 used above.
vis_vote_scree(fit_swat)