| Type: | Package |
| Title: | Advanced Continuous Glucose Monitoring Analysis with High-Performance C++ Backend |
| Version: | 0.2.0 |
| Maintainer: | Sang Ho Park <shstat1729@gmail.com> |
| Description: | Tools for advanced analysis of continuous glucose monitoring (CGM) time-series, implementing GRID (Glucose Rate Increase Detector) and GRID-based algorithms for postprandial peak detection, and detection of hypoglycemic and hyperglycemic episodes (Levels 1/2/Extended) aligned with international consensus CGM metrics. Core algorithms are implemented in optimized C++ using 'Rcpp' to provide accurate and fast analysis on large datasets. |
| License: | MIT + file LICENSE |
| Encoding: | UTF-8 |
| RoxygenNote: | 7.3.3 |
| LinkingTo: | Rcpp |
| Imports: | Rcpp |
| Suggests: | testthat (≥ 3.0.0), knitr, rmarkdown, iglu, dplyr, covr, ggplot2, microbenchmark |
| VignetteBuilder: | knitr |
| URL: | https://github.com/shstat1729/cgmguru |
| BugReports: | https://github.com/shstat1729/cgmguru/issues |
| Config/testthat/edition: | 3 |
| NeedsCompilation: | yes |
| Packaged: | 2026-05-07 05:49:21 UTC; bagsangho |
| Author: | Sang Ho Park [aut, cre], Rosa Oh [aut, ctb], Sang-Man Jin [aut, ctb] |
| Repository: | CRAN |
| Date/Publication: | 2026-05-07 06:20:02 UTC |
Advanced Continuous Glucose Monitoring Analysis and GRID-Based Event Detection
Description
A high-performance R package for comprehensive Continuous Glucose Monitoring (CGM) data analysis with optimized C++ implementations. The package provides advanced tools for CGM data analysis with two primary capabilities: GRID and postprandial peak detection, and extended glycemic events detection aligned with international consensus CGM metrics.
Details
The package implements several key algorithms for CGM analysis:
-
GRID Algorithm: Detects rapid glucose rate increases (commonly
\geq90-95 mg/dL/hour) with configurable thresholds and gaps for postprandial peak detection -
Postprandial Peak Detection: Finds peak glucose after GRID points using local maxima and configurable time windows
-
Consensus CGM Metrics Event Detection: Level 1/2 hypo- and hyperglycemia detection with duration validation (default minimum 15 minutes) aligned with Battelino et al. (2023) international consensus
-
Advanced Analysis Tools: Local maxima finding, excursion analysis, and robust episode validation utilities
Core algorithms are implemented in optimized C++ via 'Rcpp' for accurate and fast analysis on large datasets, making the package suitable for both research and clinical applications.
Main Functions
gridGRID algorithm for detecting rapid glucose rate increases
maxima_gridCombined maxima detection and GRID analysis for postprandial peaks
detect_hyperglycemic_eventsHyperglycemic event detection (Level 1/2/Extended)
detect_hypoglycemic_eventsHypoglycemic event detection (Level 1/2/Extended)
detect_all_eventsComprehensive detection of all glycemic event types
find_local_maximaLocal maxima identification in glucose time series
orderfastFast dataframe ordering utility
Data Requirements
Input dataframes should contain:
-
id: Patient identifier (character or factor) -
time: POSIXct timestamps -
gl: Glucose values in mg/dL
All function arguments and return values are expected to be in tibble format. For convenience, single-column parameters can be passed as vectors in R, which will be automatically converted to single-column tibbles.
Examples
# Basic GRID analysis result <- grid(cgm_data, gap = 15, threshold = 130) # Postprandial peak detection (GRID-based) maxima <- maxima_grid(cgm_data, threshold = 130, gap = 60, hours = 2) # Level 1 Hyperglycemic event detection events <- detect_hyperglycemic_events(cgm_data, type = "lv1") # Comprehensive event detection all_events <- detect_all_events(cgm_data, reading_minutes = 5)
Author(s)
Sang Ho Park shstat1729@gmail.com
References
Battelino, T., et al. "Continuous glucose monitoring and metrics for clinical trials: an international consensus statement." *The Lancet Diabetes & Endocrinology* 11.1 (2023): 42-57.
Harvey, Rebecca A., et al. "Design of the glucose rate increase detector: a meal detection module for the health monitoring system." *Journal of diabetes science and technology* 8.2 (2014): 307-320.
Adolfsson, Peter, et al. "Increased time in range and fewer missed bolus injections after introduction of a smart connected insulin pen." Diabetes Technology & Therapeutics 22.10 (2020): 709-718.
Chun, E., et al. "iglu: interpreting glucose data from continuous glucose monitors." R package version 3.0 (2023).
Park, Sang Ho, et al. "Identification of clinically meaningful automatically detected postprandial glucose excursions in individuals with type 1 diabetes using personal continuous glucose monitoring." Diabetes Research and Clinical Practice (2025): 112951.
Park, Soojin, et al. "High-Amplitude and Prolonged Glucose Excursions as a Key Determinant of Discordance Between Glucose Management Indicator and Glycated Hemoglobin in Type 1 Diabetes." Diabetes Care (2026): dc252820. https://doi.org/10.2337/dc25-2820
Edwards, Stephanie, et al. "Use of connected pen as a diagnostic tool to evaluate missed bolus dosing behavior in people with type 1 and type 2 diabetes." Diabetes Technology & Therapeutics 24.1 (2022): 61-66.
For more information about the GRID algorithm and CGM analysis methodologies,
see the package vignette: vignette("intro", package = "cgmguru")
See Also
grid, maxima_grid, detect_hyperglycemic_events, detect_all_events
Detect All Glycemic Events
Description
Comprehensive function to detect all types of glycemic events aligned with international consensus CGM metrics (Battelino et al., 2023). This function provides a unified interface for detecting multiple event types including Level 1/2/Extended hypo- and hyperglycemia, and Level 1 excluded events. Events are counted only after the required recovery condition is confirmed; duration summaries use the event boundary immediately before recovery starts.
Usage
detect_all_events(df, reading_minutes = NULL)
Arguments
df |
A dataframe containing continuous glucose monitoring (CGM) data. Must include columns:
|
reading_minutes |
Time interval between readings in minutes (optional). Can be a single integer/numeric value (applied to all subjects) or a vector matching data length (different intervals per subject) |
Value
A tibble containing comprehensive event analysis with columns:
-
id: Subject identifier -
type: Event type (hypo/hyper) -
level: Event level (lv1/lv2/extended/lv1_excl) -
total_episodes: Total number of episodes -
avg_ep_per_day: Average episodes per day -
avg_episode_duration_below_54: Average episode duration below 54 mg/dL in minutes (hypoglycemic events only)
Event types
- Hypoglycemia: lv1 (< 70 mg/dL, \geq 15 min), lv2 (< 54 mg/dL, \geq 15 min), extended (< 70 mg/dL, \geq 120 min).
- Hyperglycemia: lv1 (> 180 mg/dL, \geq 15 min), lv2 (> 250 mg/dL, \geq 15 min), extended (> 250 mg/dL, \geq 90 min in 120 min, end \leq 180 mg/dL for \geq 15 min).
References
Battelino, T., et al. (2023). Continuous glucose monitoring and metrics for clinical trials: an international consensus statement. The Lancet Diabetes & Endocrinology, 11(1), 42-57.
See Also
detect_hyperglycemic_events, detect_hypoglycemic_events
Examples
# Load sample data
library(iglu)
data(example_data_5_subject)
data(example_data_hall)
# Detect all glycemic events with 5-minute reading intervals
all_events <- detect_all_events(example_data_5_subject, reading_minutes = 5)
print(all_events)
# Detect all events on larger dataset
large_all_events <- detect_all_events(example_data_hall, reading_minutes = 5)
print(paste("Total event types analyzed:", nrow(large_all_events)))
# Filter for specific event types
hyperglycemia_events <- all_events[all_events$type == "hyper", ]
hypoglycemia_events <- all_events[all_events$type == "hypo", ]
print("Hyperglycemia events:")
print(hyperglycemia_events)
print("Hypoglycemia events:")
print(hypoglycemia_events)
Detect Events Between Maxima
Description
Identifies and analyzes events occurring between detected maxima points, providing detailed episode information for GRID analysis. This function helps characterize the glucose dynamics between identified peaks.
Usage
detect_between_maxima(df, transform_df)
Arguments
df |
A dataframe containing continuous glucose monitoring (CGM) data. Must include columns:
|
transform_df |
A dataframe containing summary information from previous transformations |
Value
A list containing:
-
results: Tibble with events between maxima (id,grid_time,grid_gl,maxima_time,maxima_glucose,time_to_peak) -
episode_counts: Tibble with episode counts per subject (id,episode_counts)
See Also
grid, mod_grid, find_new_maxima, transform_df
Other GRID pipeline:
find_local_maxima(),
find_max_after_hours(),
find_max_before_hours(),
find_min_after_hours(),
find_min_before_hours(),
find_new_maxima(),
grid(),
maxima_grid(),
mod_grid(),
start_finder(),
transform_df()
Examples
# Load sample data
library(iglu)
data(example_data_5_subject)
data(example_data_hall)
# Complete pipeline to get transform_df
grid_result <- grid(example_data_5_subject, gap = 60, threshold = 130)
maxima_result <- find_local_maxima(example_data_5_subject)
mod_result <- mod_grid(example_data_5_subject, grid_result$grid_vector, hours = 2, gap = 60)
max_after <- find_max_after_hours(example_data_5_subject, mod_result$mod_grid_vector, hours = 2)
new_maxima <- find_new_maxima(example_data_5_subject,
max_after$max_index,
maxima_result$local_maxima_vector)
transformed <- transform_df(grid_result$episode_start, new_maxima)
# Detect events between maxima
between_events <- detect_between_maxima(example_data_5_subject, transformed)
print(paste("Events between maxima:", length(between_events)))
# Analysis on larger dataset
large_grid <- grid(example_data_hall, gap = 60, threshold = 130)
large_maxima <- find_local_maxima(example_data_hall)
large_mod <- mod_grid(example_data_hall, large_grid$grid_vector, hours = 2, gap = 60)
large_max_after <- find_max_after_hours(example_data_hall, large_mod$mod_grid_vector, hours = 2)
large_new_maxima <- find_new_maxima(example_data_hall,
large_max_after$max_index,
large_maxima$local_maxima_vector)
large_transformed <- transform_df(large_grid$episode_start, large_new_maxima)
large_between <- detect_between_maxima(example_data_hall, large_transformed)
print(paste("Events between maxima in larger dataset:", length(large_between)))
Detect Hyperglycemic Events
Description
Identifies and segments hyperglycemic events in CGM data based on international consensus
CGM metrics (Battelino et al., 2023). Use type to select one of
three event definitions:
-
Level 1:
\geq15 consecutive min of>180 mg/dL, ends with\geq15 consecutive min\leq180 mg/dL -
Level 2:
\geq15 consecutive min of>250 mg/dL, ends with\geq15 consecutive min\leq250 mg/dL -
Extended:
>250 mg/dL lasting\geq90 cumulative min within a 120-min period, ends when glucose returns to\leq180 mg/dL for\geq15 consecutive min after
Events are counted only after glucose remains at or below the end threshold
for the specified end length. In events_detailed, end_time,
end_glucose, and end_index report the last hyperglycemic
reading immediately before that confirmed recovery period starts.
Usage
detect_hyperglycemic_events(df, ..., type = "extended",
reading_minutes = NULL)
Arguments
df |
A dataframe containing continuous glucose monitoring (CGM) data. Must include columns:
|
... |
Custom event criteria supplied by name. Prefer
|
type |
Hyperglycemia event definition. One of |
reading_minutes |
Time interval between readings in minutes (optional) |
Value
A list containing:
-
events_total: Tibble with summary statistics per subject (id, total_events, avg_ep_per_day) -
events_detailed: Tibble with detailed event information (id, start_time, start_glucose, end_time, end_glucose, start_index, end_index). End fields report the last dysglycemic reading before confirmed recovery starts.
Methods
Hyperglycemic events can be detected using either the recommended
type argument or named custom threshold and duration criteria.
1. Preset method using type (recommended):
Use type when you want the standard Level 1, Level 2, or Extended
hyperglycemia definitions without manually entering thresholds.
-
type = "lv1"usesstart_gl = 180,dur_length = 15,end_length = 15, andend_gl = 180. -
type = "lv2"usesstart_gl = 250,dur_length = 15,end_length = 15, andend_gl = 250. -
type = "extended"usesstart_gl = 250,dur_length = 120,end_length = 15, andend_gl = 180.
2. Custom criteria method:
Supply start_gl, dur_length, end_length, and
end_gl directly when using a custom definition, for example
detect_hyperglycemic_events(df, start_gl = 180, dur_length = 15,
end_length = 15, end_gl = 180) for Level 1 hyperglycemia. If an explicit
type is supplied together with custom numeric criteria, the function
returns results based on type; the custom criteria are ignored and a
warning is issued.
Units and sampling
- reading_minutes can be a scalar (all rows) or a vector per-row.
- If reading_minutes is NULL, duration is computed from time deltas.
References
Battelino, T., et al. (2023). Continuous glucose monitoring and metrics for clinical trials: an international consensus statement. The Lancet Diabetes & Endocrinology, 11(1), 42-57.
See Also
Examples
# Load sample data
library(iglu)
data(example_data_5_subject)
data(example_data_hall)
# Level 1 Hyperglycemia Event (>=15 consecutive min of >180 mg/dL and event
# ends when there is >=15 consecutive min with a CGM sensor value of <=180 mg/dL)
hyper_lv1 <- detect_hyperglycemic_events(example_data_5_subject, type = "lv1")
print(hyper_lv1$events_total)
# Level 2 Hyperglycemia Event (>=15 consecutive min of >250 mg/dL and event
# ends when there is >=15 consecutive min with a CGM sensor value of <=250 mg/dL)
hyper_lv2 <- detect_hyperglycemic_events(example_data_5_subject, type = "lv2")
print(hyper_lv2$events_total)
# Extended Hyperglycemia Event (>250 mg/dL lasting >=90 cumulative min within a
# 120-min period, ends when glucose returns to <=180 mg/dL for >=15 consecutive
# min after)
hyper_extended <- detect_hyperglycemic_events(example_data_5_subject, type = "extended")
print(hyper_extended$events_total)
# Custom criteria method for the same standard definitions
hyper_lv1_custom <- detect_hyperglycemic_events(
example_data_5_subject,
start_gl = 180,
dur_length = 15,
end_length = 15,
end_gl = 180
)
hyper_lv2_custom <- detect_hyperglycemic_events(
example_data_5_subject,
start_gl = 250,
dur_length = 15,
end_length = 15,
end_gl = 250
)
hyper_extended_custom <- detect_hyperglycemic_events(
example_data_5_subject,
start_gl = 250,
dur_length = 120,
end_length = 15,
end_gl = 180
)
# Compare event rates across levels
cat("Level 1 events:", sum(hyper_lv1$events_total$total_events), "\n")
cat("Level 2 events:", sum(hyper_lv2$events_total$total_events), "\n")
cat("Extended events:", sum(hyper_extended$events_total$total_events), "\n")
# Analysis on larger dataset with Level 1 criteria
large_hyper <- detect_hyperglycemic_events(example_data_hall, type = "lv1")
print(large_hyper$events_total)
# Analysis on larger dataset with Level 2 criteria
large_hyper_lv2 <- detect_hyperglycemic_events(example_data_hall, type = "lv2")
print(large_hyper_lv2$events_total)
# Analysis on larger dataset with Extended criteria
large_hyper_extended <- detect_hyperglycemic_events(example_data_hall, type = "extended")
print(large_hyper_extended$events_total)
# View detailed events for specific subject
if(nrow(hyper_lv1$events_detailed) > 0) {
first_subject <- hyper_lv1$events_detailed$id[1]
subject_events <- hyper_lv1$events_detailed[hyper_lv1$events_detailed$id == first_subject, ]
head(subject_events)
}
Detect Hypoglycemic Events
Description
Identifies and segments hypoglycemic events in CGM data based on international consensus
CGM metrics (Battelino et al., 2023). Use type to select one of
three event definitions:
-
Level 1:
\geq15 consecutive min of<70 mg/dL, ends with\geq15 consecutive min\geq70 mg/dL -
Level 2:
\geq15 consecutive min of<54 mg/dL, ends with\geq15 consecutive min\geq54 mg/dL -
Extended:
>120 consecutive min of<70 mg/dL, ends with\geq15 consecutive min\geq70 mg/dL
Events are counted only after glucose remains at or above the recovery
threshold for the specified end length. In events_detailed,
end_time, end_glucose, and end_index report the last
hypoglycemic reading immediately before that confirmed recovery period starts.
Usage
detect_hypoglycemic_events(df, ..., type = "extended",
reading_minutes = NULL)
Arguments
df |
A dataframe containing continuous glucose monitoring (CGM) data. Must include columns:
|
... |
Custom event criteria supplied by name. Prefer
|
type |
Hypoglycemia event definition. One of |
reading_minutes |
Time interval between readings in minutes (optional) |
Value
A list containing:
-
events_total: Tibble with summary statistics per subject (id, total_events, avg_ep_per_day) -
events_detailed: Tibble with detailed event information (id, start_time, start_glucose, end_time, end_glucose, start_index, end_index, duration_below_54_minutes). End fields report the last dysglycemic reading before confirmed recovery starts.
Methods
Hypoglycemic events can be detected using either the recommended
type argument or named custom threshold and duration criteria.
1. Preset method using type (recommended):
Use type when you want the standard Level 1, Level 2, or Extended
hypoglycemia definitions without manually entering thresholds.
-
type = "lv1"usesstart_gl = 70,dur_length = 15, andend_length = 15. -
type = "lv2"usesstart_gl = 54,dur_length = 15, andend_length = 15. -
type = "extended"usesstart_gl = 70,dur_length = 120, andend_length = 15.
2. Custom criteria method:
Supply start_gl, dur_length, and end_length directly
when using a custom definition, for example
detect_hypoglycemic_events(df, start_gl = 70, dur_length = 15,
end_length = 15) for Level 1 hypoglycemia. If an explicit type is
supplied together with custom numeric criteria, the function returns results
based on type; the custom criteria are ignored and a warning is
issued.
Units and sampling
- reading_minutes can be a scalar (all rows) or a vector per-row.
- If reading_minutes is NULL, duration is computed from time deltas.
References
Battelino, T., et al. (2023). Continuous glucose monitoring and metrics for clinical trials: an international consensus statement. The Lancet Diabetes & Endocrinology, 11(1), 42-57.
See Also
Examples
# Load sample data
library(iglu)
data(example_data_5_subject)
data(example_data_hall)
# Level 1 Hypoglycemia Event (>=15 consecutive min of <70 mg/dL and event
# ends when there is >=15 consecutive min with a CGM sensor value of >=70 mg/dL)
hypo_lv1 <- detect_hypoglycemic_events(example_data_5_subject, type = "lv1")
print(hypo_lv1$events_total)
# Level 2 Hypoglycemia Event (>=15 consecutive min of <54 mg/dL and event
# ends when there is >=15 consecutive min with a CGM sensor value of >=54 mg/dL)
hypo_lv2 <- detect_hypoglycemic_events(example_data_5_subject, type = "lv2")
# Extended Hypoglycemia Event (>120 consecutive min of <70 mg/dL and event
# ends when there is >=15 consecutive min with a CGM sensor value of >=70 mg/dL)
hypo_extended <- detect_hypoglycemic_events(example_data_5_subject, type = "extended")
print(hypo_extended$events_total)
# Custom criteria method for the same standard definitions
hypo_lv1_custom <- detect_hypoglycemic_events(
example_data_5_subject,
start_gl = 70,
dur_length = 15,
end_length = 15
)
hypo_lv2_custom <- detect_hypoglycemic_events(
example_data_5_subject,
start_gl = 54,
dur_length = 15,
end_length = 15
)
hypo_extended_custom <- detect_hypoglycemic_events(
example_data_5_subject,
start_gl = 70,
dur_length = 120,
end_length = 15
)
# Compare event rates across levels
cat("Level 1 events:", sum(hypo_lv1$events_total$total_events), "\n")
cat("Level 2 events:", sum(hypo_lv2$events_total$total_events), "\n")
cat("Extended events:", sum(hypo_extended$events_total$total_events), "\n")
# Analysis on larger dataset with Level 1 criteria
large_hypo <- detect_hypoglycemic_events(example_data_hall, type = "lv1")
print(large_hypo$events_total)
# Analysis on larger dataset with Level 2 criteria
large_hypo_lv2 <- detect_hypoglycemic_events(example_data_hall, type = "lv2")
print(large_hypo_lv2$events_total)
# Analysis on larger dataset with Extended criteria
large_hypo_extended <- detect_hypoglycemic_events(example_data_hall, type = "extended")
print(large_hypo_extended$events_total)
Calculate Glucose Excursions
Description
Calculates glucose excursions in CGM data. An excursion is defined as
a > 70 mg/dL (> 3.9 mmol/L) rise within 2 hours, not preceded by a value
< 70 mg/dL (< 3.9 mmol/L).
Usage
excursion(df, gap = 15)
Arguments
df |
A dataframe containing continuous glucose monitoring (CGM) data. Must include columns:
|
gap |
Gap threshold in minutes for excursion calculation (default: 15). This parameter defines the minimum time interval between consecutive GRID events. |
Value
A list containing:
-
excursion_vector: Tibble with excursion results (excursion) -
episode_counts: Tibble with episode counts per subject (id,episode_counts) -
episode_start: Tibble with all episode starts with columns:-
id: Subject identifier -
time: Timestamp at which the event occurs; equivalent todf$time[index] -
gl: Glucose value at the event; equivalent todf$gl[index] -
index: R-based (1-indexed) row number(s) indfdenoting where the event occurs
-
Notes
- gap is minutes; change to enforce minimum separation between excursions.
References
Edwards, S., et al. (2022). Use of connected pen as a diagnostic tool to evaluate missed bolus dosing behavior in people with type 1 and type 2 diabetes. Diabetes Technology & Therapeutics, 24(1), 61-66.
See Also
Examples
# Load sample data
library(iglu)
data(example_data_5_subject)
data(example_data_hall)
# Calculate glucose excursions
excursion_result <- excursion(example_data_5_subject, gap = 15)
print(paste("Excursion vector length:", length(excursion_result$excursion_vector)))
print(excursion_result$episode_counts)
# Excursion analysis with different gap
excursion_30min <- excursion(example_data_5_subject, gap = 30)
# Analysis on larger dataset
large_excursion <- excursion(example_data_hall, gap = 15)
print(paste("Excursion vector length in larger dataset:", length(large_excursion$excursion_vector)))
print(paste("Total episodes:", sum(large_excursion$episode_counts$episode_counts)))
Find Local Maxima in Glucose Time Series
Description
Identifies local maxima (peaks) in glucose concentration time series data. Uses a difference-based algorithm to detect peaks where glucose values increase or remain constant for two consecutive points before the peak point, and decrease or remain constant for two consecutive points after the peak point.
Usage
find_local_maxima(df)
Arguments
df |
A dataframe containing continuous glucose monitoring (CGM) data. Must include columns:
|
Value
A list containing:
-
local_maxima_vector: Tibble with R-based (1-indexed) row numbers of local maxima (local_maxima). The corresponding occurrence time isdf$time[local_maxima]and glucose isdf$gl[local_maxima]. -
merged_results: Tibble with local maxima details (id,time,gl)
See Also
grid, mod_grid, find_new_maxima
Other GRID pipeline:
detect_between_maxima(),
find_max_after_hours(),
find_max_before_hours(),
find_min_after_hours(),
find_min_before_hours(),
find_new_maxima(),
grid(),
maxima_grid(),
mod_grid(),
start_finder(),
transform_df()
Examples
# Load sample data
library(iglu)
data(example_data_5_subject)
data(example_data_hall)
# Find local maxima
maxima_result <- find_local_maxima(example_data_5_subject)
print(paste("Found", nrow(maxima_result$local_maxima_vector), "local maxima"))
# Find maxima on larger dataset
large_maxima <- find_local_maxima(example_data_hall)
print(paste("Found", nrow(large_maxima$local_maxima_vector), "local maxima in larger dataset"))
# View first few maxima
head(maxima_result$local_maxima_vector)
# View merged results
head(maxima_result$merged_results)
Find Maximum Glucose After Specified Hours
Description
Identifies the maximum glucose value occurring within a specified time window after a given start point. This function is useful for analyzing glucose patterns following specific events or time points.
Usage
find_max_after_hours(df, start_point_df, hours)
Arguments
df |
A dataframe containing continuous glucose monitoring (CGM) data. Must include columns:
|
start_point_df |
A dataframe with column |
hours |
Number of hours to look ahead from the start point |
Value
A list containing:
-
max_index: Tibble with R-based (1-indexed) row numbers of maximum glucose (max_index). The corresponding occurrence time isdf$time[max_index]and glucose isdf$gl[max_index]. -
episode_counts: Tibble with episode counts per subject (id,episode_counts) -
episode_start: Tibble with all episode starts with columns:-
id: Subject identifier -
time: Timestamp at which the maximum occurs; equivalent todf$time[index] -
gl: Glucose value at the maximum; equivalent todf$gl[index] -
index: R-based (1-indexed) row number(s) indfdenoting where the maximum occurs
-
Notes
- start_index must be valid row numbers in df (1-indexed).
- The search window is (0, hours] hours after each start index.
See Also
mod_grid, find_local_maxima, find_new_maxima, transform_df
Other GRID pipeline:
detect_between_maxima(),
find_local_maxima(),
find_max_before_hours(),
find_min_after_hours(),
find_min_before_hours(),
find_new_maxima(),
grid(),
maxima_grid(),
mod_grid(),
start_finder(),
transform_df()
Examples
# Load sample data
library(iglu)
data(example_data_5_subject)
data(example_data_hall)
# Create start points for demonstration (using row index)
start_index <- seq(1, nrow(example_data_5_subject), by = 100)
start_points <- data.frame(start_index = start_index)
# Find maximum glucose in next 2 hours
max_after <- find_max_after_hours(example_data_5_subject, start_points, hours = 2)
print(paste("Found", length(max_after$max_index), "maximum points"))
# Find maximum glucose in next 1 hour
max_after_1h <- find_max_after_hours(example_data_5_subject, start_points, hours = 1)
# Analysis on larger dataset
large_start_index <- seq(1, nrow(example_data_hall), by = 200)
large_start_points <- data.frame(start_index = large_start_index)
large_max_after <- find_max_after_hours(example_data_hall, large_start_points, hours = 2)
print(paste("Found", length(large_max_after$max_index), "maximum points in larger dataset"))
Find Maximum Glucose Before Specified Hours
Description
Identifies the maximum glucose value occurring within a specified time window before a given start point. This function is useful for analyzing glucose patterns preceding specific events or time points.
Usage
find_max_before_hours(df, start_point_df, hours)
Arguments
df |
A dataframe containing continuous glucose monitoring (CGM) data. Must include columns:
|
start_point_df |
A dataframe with column |
hours |
Number of hours to look back from the start point |
Value
A list containing:
-
max_index: Tibble with R-based (1-indexed) row numbers of maximum glucose (max_index). The corresponding occurrence time isdf$time[max_index]and glucose isdf$gl[max_index]. -
episode_counts: Tibble with episode counts per subject (id,episode_counts) -
episode_start: Tibble with all episode starts with columns:-
id: Subject identifier -
time: Timestamp at which the maximum occurs; equivalent todf$time[index] -
gl: Glucose value at the maximum; equivalent todf$gl[index] -
index: R-based (1-indexed) row number(s) indfdenoting where the maximum occurs
-
Notes
- The search window is [hours, 0) hours before each start index.
See Also
mod_grid, find_local_maxima, find_new_maxima
Other GRID pipeline:
detect_between_maxima(),
find_local_maxima(),
find_max_after_hours(),
find_min_after_hours(),
find_min_before_hours(),
find_new_maxima(),
grid(),
maxima_grid(),
mod_grid(),
start_finder(),
transform_df()
Examples
# Load sample data
library(iglu)
data(example_data_5_subject)
data(example_data_hall)
# Create start points for demonstration (using row index)
start_index <- seq(1, nrow(example_data_5_subject), by = 100)
start_points <- data.frame(start_index = start_index)
# Find maximum glucose in previous 2 hours
max_before <- find_max_before_hours(example_data_5_subject, start_points, hours = 2)
print(paste("Found", length(max_before$max_index), "maximum points"))
# Find maximum glucose in previous 1 hour
max_before_1h <- find_max_before_hours(example_data_5_subject, start_points, hours = 1)
# Analysis on larger dataset
large_start_index <- seq(1, nrow(example_data_hall), by = 200)
large_start_points <- data.frame(start_index = large_start_index)
large_max_before <- find_max_before_hours(example_data_hall, large_start_points, hours = 2)
print(paste("Found", length(large_max_before$max_index), "maximum points in larger dataset"))
Find Minimum Glucose After Specified Hours
Description
Identifies the minimum glucose value occurring within a specified time window after a given start point. This function is useful for analyzing glucose patterns following specific events or time points.
Usage
find_min_after_hours(df, start_point_df, hours)
Arguments
df |
A dataframe containing continuous glucose monitoring (CGM) data. Must include columns:
|
start_point_df |
A dataframe with column |
hours |
Number of hours to look ahead from the start point |
Value
A list containing:
-
min_index: Tibble with R-based (1-indexed) row numbers of minimum glucose (min_index). The corresponding occurrence time isdf$time[min_index]and glucose isdf$gl[min_index]. -
episode_counts: Tibble with episode counts per subject (id,episode_counts) -
episode_start: Tibble with all episode starts with columns:-
id: Subject identifier -
time: Timestamp at which the minimum occurs; equivalent todf$time[index] -
gl: Glucose value at the minimum; equivalent todf$gl[index] -
index: R-based (1-indexed) row number(s) indfdenoting where the minimum occurs
-
See Also
Other GRID pipeline:
detect_between_maxima(),
find_local_maxima(),
find_max_after_hours(),
find_max_before_hours(),
find_min_before_hours(),
find_new_maxima(),
grid(),
maxima_grid(),
mod_grid(),
start_finder(),
transform_df()
Examples
# Load sample data
library(iglu)
data(example_data_5_subject)
data(example_data_hall)
# Create start points for demonstration (using row index)
start_index <- seq(1, nrow(example_data_5_subject), by = 100)
start_points <- data.frame(start_index = start_index)
# Find minimum glucose in next 2 hours
min_after <- find_min_after_hours(example_data_5_subject, start_points, hours = 2)
print(paste("Found", length(min_after$min_index), "minimum points"))
# Find minimum glucose in next 1 hour
min_after_1h <- find_min_after_hours(example_data_5_subject, start_points, hours = 1)
# Analysis on larger dataset
large_start_index <- seq(1, nrow(example_data_hall), by = 200)
large_start_points <- data.frame(start_index = large_start_index)
large_min_after <- find_min_after_hours(example_data_hall, large_start_points, hours = 2)
print(paste("Found", length(large_min_after$min_index), "minimum points in larger dataset"))
Find Minimum Glucose Before Specified Hours
Description
Identifies the minimum glucose value occurring within a specified time window before a given start point. This function is useful for analyzing glucose patterns preceding specific events or time points.
Usage
find_min_before_hours(df, start_point_df, hours)
Arguments
df |
A dataframe containing continuous glucose monitoring (CGM) data. Must include columns:
|
start_point_df |
A dataframe with column |
hours |
Number of hours to look back from the start point |
Value
A list containing:
-
min_index: Tibble with R-based (1-indexed) row numbers of minimum glucose (min_index). The corresponding occurrence time isdf$time[min_index]and glucose isdf$gl[min_index]. -
episode_counts: Tibble with episode counts per subject (id,episode_counts) -
episode_start: Tibble with all episode starts with columns:-
id: Subject identifier -
time: Timestamp at which the minimum occurs; equivalent todf$time[index] -
gl: Glucose value at the minimum; equivalent todf$gl[index] -
index: R-based (1-indexed) row number(s) indfdenoting where the minimum occurs
-
See Also
Other GRID pipeline:
detect_between_maxima(),
find_local_maxima(),
find_max_after_hours(),
find_max_before_hours(),
find_min_after_hours(),
find_new_maxima(),
grid(),
maxima_grid(),
mod_grid(),
start_finder(),
transform_df()
Examples
# Load sample data
library(iglu)
data(example_data_5_subject)
data(example_data_hall)
# Create start points for demonstration (using row index)
start_index <- seq(1, nrow(example_data_5_subject), by = 100)
start_points <- data.frame(start_index = start_index)
# Find minimum glucose in previous 2 hours
min_before <- find_min_before_hours(example_data_5_subject, start_points, hours = 2)
print(paste("Found", length(min_before$min_index), "minimum points"))
# Find minimum glucose in previous 1 hour
min_before_1h <- find_min_before_hours(example_data_5_subject, start_points, hours = 1)
# Analysis on larger dataset
large_start_index <- seq(1, nrow(example_data_hall), by = 200)
large_start_points <- data.frame(start_index = large_start_index)
large_min_before <- find_min_before_hours(example_data_hall, large_start_points, hours = 2)
print(paste("Found", length(large_min_before$min_index), "minimum points in larger dataset"))
Find New Maxima Around Grid Points
Description
Identifies new maxima in the vicinity of previously identified grid points, useful for refining maxima detection in GRID analysis. This function helps improve the accuracy of peak detection by searching around known event points.
Usage
find_new_maxima(df, mod_grid_max_point_df, local_maxima_df)
Arguments
df |
A dataframe containing continuous glucose monitoring (CGM) data. Must include columns:
|
mod_grid_max_point_df |
A dataframe with column |
local_maxima_df |
A dataframe with column |
Value
A tibble with updated maxima information containing columns (id, time, gl, index)
The index column contains R-based (1-indexed) row number(s) in df; thus, time == df$time[index] and gl == df$gl[index].
See Also
find_local_maxima, find_max_after_hours, transform_df
Other GRID pipeline:
detect_between_maxima(),
find_local_maxima(),
find_max_after_hours(),
find_max_before_hours(),
find_min_after_hours(),
find_min_before_hours(),
grid(),
maxima_grid(),
mod_grid(),
start_finder(),
transform_df()
Examples
# Load sample data
library(iglu)
data(example_data_5_subject)
data(example_data_hall)
# First, get grid points and local maxima
grid_result <- grid(example_data_5_subject, gap = 15, threshold = 130)
maxima_result <- find_local_maxima(example_data_5_subject)
# Create modified grid points (simplified for example)
mod_grid_indices <- data.frame(index = grid_result$episode_start$index[1:10])
# Find new maxima around grid points
new_maxima <- find_new_maxima(example_data_5_subject,
mod_grid_indices,
maxima_result$local_maxima_vector)
print(paste("Found", nrow(new_maxima), "new maxima"))
# Analysis on larger dataset
large_grid <- grid(example_data_hall, gap = 15, threshold = 130)
large_maxima <- find_local_maxima(example_data_hall)
large_mod_grid <- data.frame(index = large_grid$episode_start$index[1:20])
large_new_maxima <- find_new_maxima(example_data_hall,
large_mod_grid,
large_maxima$local_maxima_vector)
print(paste("Found", nrow(large_new_maxima), "new maxima in larger dataset"))
GRID Algorithm for Glycemic Event Detection
Description
Implements the GRID (Glucose Rate Increase Detector) algorithm for detecting rapid glucose rate increases in continuous glucose monitoring (CGM) data.
This algorithm identifies rapid glucose changes using specific rate-based criteria, and is commonly applied for meal detection.
Meals are detected when the CGM value is \geq 7.2 mmol/L (\geq 130 mg/dL) and the rate-of-change is \geq 5.3 mmol/L/h [\geq 95 mg/dL/h] for the last two consecutive readings, or \geq 5.0 mmol/L/h [\geq 90 mg/dL/h] for two of the last three readings.
Usage
grid(df, gap = 15, threshold = 130)
Arguments
df |
A dataframe containing continuous glucose monitoring (CGM) data. Must include columns:
|
gap |
Gap threshold in minutes for event detection (default: 15). This parameter defines the minimum time interval between consecutive GRID events. For example, if gap is set to 60, only one GRID event can be detected within any one-hour window; subsequent events within the gap interval are not counted as new events. |
threshold |
GRID slope threshold in mg/dL/hour for event classification (default: 130) |
Value
A list containing:
-
grid_vector: A tibble with the results of the GRID analysis. Contains agridcolumn (0/1 values; 1 denotes a detected GRID event) and all relevant input columns. -
episode_counts: A tibble summarizing the number of GRID events per subject (id) asepisode_counts. -
episode_start: A tibble listing the start of each GRID episode, with columns:-
id: Subject ID. -
time: The timestamp (POSIXct) at which the GRID event was detected. -
gl: The glucose value (mg/dL; integer or numeric) at the GRID event. -
index: R-based (1-indexed) row number(s) in the original dataframe where the GRID event occurs. The occurrence time equalsdf$time[index]and glucose equalsdf$gl[index].
-
Algorithm
- Flags points where gl >= 130 mg/dL and rate-of-change meets the GRID criteria (see references).
- Enforces a minimum gap in minutes between detected events to avoid duplicates.
Units and sampling
- gl is mg/dL; time is POSIXct; gap is minutes.
- The effective sampling interval is derived from time deltas.
References
Harvey, R. A., et al. (2014). Design of the glucose rate increase detector: a meal detection module for the health monitoring system. Journal of Diabetes Science and Technology, 8(2), 307-320.
Adolfsson, Peter, et al. "Increased time in range and fewer missed bolus injections after introduction of a smart connected insulin pen." Diabetes technology & therapeutics 22.10 (2020): 709-718.
See Also
mod_grid, maxima_grid, find_local_maxima, detect_between_maxima
Other GRID pipeline:
detect_between_maxima(),
find_local_maxima(),
find_max_after_hours(),
find_max_before_hours(),
find_min_after_hours(),
find_min_before_hours(),
find_new_maxima(),
maxima_grid(),
mod_grid(),
start_finder(),
transform_df()
Examples
# Load sample data
library(iglu)
data(example_data_5_subject)
data(example_data_hall)
# Basic GRID analysis on smaller dataset
grid_result <- grid(example_data_5_subject, gap = 15, threshold = 130)
print(grid_result$episode_counts)
print(grid_result$episode_start)
print(grid_result$grid_vector)
# More sensitive GRID analysis
sensitive_result <- grid(example_data_5_subject, gap = 10, threshold = 120)
# GRID analysis on larger dataset
large_grid <- grid(example_data_hall, gap = 15, threshold = 130)
print(paste("Detected", sum(large_grid$episode_counts$episode_counts), "episodes"))
print(large_grid$episode_start)
print(large_grid$grid_vector)
Combined Maxima Detection and GRID Analysis
Description
Fast method for postprandial glucose peak detection combining GRID algorithm with local maxima analysis. Detects meal-induced glucose peaks by identifying GRID events (rapid glucose increases) and mapping them to corresponding local maxima within a search window. Local maxima are defined as points where glucose values increase or remain constant for two consecutive points before the peak, and decrease or remain constant for two consecutive points after the peak.
The 7-step algorithm: (1) finds GRID points indicating meal starts (2) identifies modified GRID points after minimum duration (3) locates maximum glucose within the subsequent time window (4) detects all local maxima using the two-consecutive-point criteria (5) refines peaks from local maxima candidates (6) maps GRID points to peaks within 4-hour constraint (7) redistributes overlapping peaks.
Usage
maxima_grid(df, threshold = 130, gap = 60, hours = 2)
Arguments
df |
A dataframe containing continuous glucose monitoring (CGM) data. Must include columns:
|
threshold |
GRID slope threshold in mg/dL/hour for event classification (default: 130) |
gap |
Gap threshold in minutes for event detection (default: 60). This parameter defines the minimum time interval between consecutive GRID events. |
hours |
Time window in hours for maxima analysis (default: 2) |
Value
A list containing:
-
results: Tibble with combined maxima and GRID analysis results, with columns:-
id: Subject identifier -
grid_time: Timestamp of GRID event detection (POSIXct) -
grid_gl: Glucose value at GRID event (mg/dL) -
maxima_time: Timestamp of peak glucose (POSIXct) -
maxima_glucose: Peak glucose value (mg/dL) -
time_to_peak_min: Time from GRID event to peak in minutes -
grid_index: R-based (1-indexed) row number of GRID event;grid_time == df$time[grid_index],grid_gl == df$gl[grid_index] -
maxima_index: R-based (1-indexed) row number of peak;maxima_time == df$time[maxima_index],maxima_glucose == df$gl[maxima_index]
-
-
episode_counts: Tibble with episode counts per subject (id,episode_counts)
Algorithm (7 steps)
1) GRID -> 2) modified GRID -> 3) window maxima -> 4) local maxima -> 5) refine peaks ->
6) map GRID to peaks (\leq 4h) -> 7) redistribute overlapping peaks.
References
Park, Sang Ho, et al. "Identification of clinically meaningful automatically detected postprandial glucose excursions in individuals with type 1 diabetes using personal continuous glucose monitoring." Diabetes Research and Clinical Practice (2025): 112951.
Park, Soojin, et al. "High-Amplitude and Prolonged Glucose Excursions as a Key Determinant of Discordance Between Glucose Management Indicator and Glycated Hemoglobin in Type 1 Diabetes." Diabetes Care (2026): dc252820. https://doi.org/10.2337/dc25-2820
See Also
grid, mod_grid, find_local_maxima, find_new_maxima, transform_df
Other GRID pipeline:
detect_between_maxima(),
find_local_maxima(),
find_max_after_hours(),
find_max_before_hours(),
find_min_after_hours(),
find_min_before_hours(),
find_new_maxima(),
grid(),
mod_grid(),
start_finder(),
transform_df()
Examples
# Load sample data
library(iglu)
data(example_data_5_subject)
data(example_data_hall)
# Combined analysis on smaller dataset
maxima_result <- maxima_grid(example_data_5_subject, threshold = 130, gap = 60, hours = 2)
print(maxima_result$episode_counts)
print(maxima_result$results)
# More sensitive analysis
sensitive_maxima <- maxima_grid(example_data_5_subject, threshold = 120, gap = 30, hours = 1)
print(sensitive_maxima$episode_counts)
print(sensitive_maxima$results)
# Analysis on larger dataset
large_maxima <- maxima_grid(example_data_hall, threshold = 130, gap = 60, hours = 2)
print(large_maxima$episode_counts)
print(large_maxima$results)
Modified GRID Analysis
Description
Constructs a modified GRID series by reapplying the GRID logic with a designated gap (e.g., 60 minutes) and analysis window in hours (e.g., 2 hours). It reassigns GRID events under these constraints to produce a modified grid suitable for downstream maxima mapping and episode analysis.
Usage
mod_grid(df, grid_point_df, hours = 2, gap = 15)
Arguments
df |
A dataframe containing continuous glucose monitoring (CGM) data. Must include columns:
|
grid_point_df |
A dataframe with column |
hours |
Time window in hours for analysis (default: 2) |
gap |
Gap threshold in minutes for event detection (default: 15). This parameter defines the minimum time interval between consecutive GRID events. |
Value
A list containing:
-
mod_grid_vector: Tibble with modified GRID results (mod_grid) -
episode_counts: Tibble with episode counts per subject (id,episode_counts) -
episode_start: Tibble with all episode starts with columns:-
id: Subject identifier -
time: Timestamp at which the event occurs; equivalent todf$time[index] -
gl: Glucose value at the event; equivalent todf$gl[index] -
index: R-based (1-indexed) row number(s) indfdenoting where the event occurs
-
Units and sampling
- gap is minutes; hours is hours; time is POSIXct.
References
Park, Sang Ho, et al. "Identification of clinically meaningful automatically detected postprandial glucose excursions in individuals with type 1 diabetes using personal continuous glucose monitoring." Diabetes Research and Clinical Practice (2025): 112951.
Park, Soojin, et al. "High-Amplitude and Prolonged Glucose Excursions as a Key Determinant of Discordance Between Glucose Management Indicator and Glycated Hemoglobin in Type 1 Diabetes." Diabetes Care (2026): dc252820. https://doi.org/10.2337/dc25-2820
See Also
grid, find_max_after_hours, find_new_maxima
Other GRID pipeline:
detect_between_maxima(),
find_local_maxima(),
find_max_after_hours(),
find_max_before_hours(),
find_min_after_hours(),
find_min_before_hours(),
find_new_maxima(),
grid(),
maxima_grid(),
start_finder(),
transform_df()
Examples
# Load sample data
library(iglu)
data(example_data_5_subject)
data(example_data_hall)
# First, get grid points
grid_result <- grid(example_data_5_subject, gap = 60, threshold = 130)
# Perform modified GRID analysis
mod_result <- mod_grid(example_data_5_subject, grid_result$grid_vector, hours = 2, gap = 60)
print(paste("Modified grid points:", nrow(mod_result$mod_grid_vector)))
# Modified analysis with different parameters
mod_result_1h <- mod_grid(example_data_5_subject, grid_result$grid_vector, hours = 1, gap = 40)
# Analysis on larger dataset
large_grid <- grid(example_data_hall, gap = 60, threshold = 130)
large_mod_result <- mod_grid(example_data_hall, large_grid$grid_vector, hours = 2, gap = 60)
print(paste("Modified grid points in larger dataset:", nrow(large_mod_result$mod_grid_vector)))
Fast Ordering Function
Description
Orders a dataframe by id and time columns efficiently using base R's
order. Optimized for large CGM datasets, it returns the input with rows
sorted by subject then timestamp while preserving all columns.
Orders a dataframe by id and time columns
Usage
orderfast(df)
Arguments
df |
A dataframe with 'id' and 'time' columns |
Value
A dataframe ordered by id and time
A dataframe ordered by id and time
Examples
# Load sample data
library(iglu)
data(example_data_5_subject)
data(example_data_hall)
# Shuffle without replacement, then order and compare to baseline
set.seed(123)
shuffled <- example_data_5_subject[sample(seq_len(nrow(example_data_5_subject)),
replace = FALSE), ]
baseline <- orderfast(example_data_5_subject)
ordered_shuffled <- orderfast(shuffled)
# Compare results
print(paste("Identical after ordering:", identical(baseline, ordered_shuffled)))
head(baseline[, c("id", "time", "gl")])
head(ordered_shuffled[, c("id", "time", "gl")])
# Order larger dataset
ordered_large <- orderfast(example_data_hall)
print(paste("Ordered", nrow(ordered_large), "rows in larger dataset"))
df <- data.frame(id = c("b", "a", "a"), time = as.POSIXct(
c("2024-01-01 01:00:00", "2024-01-01 00:00:00", "2024-01-01 01:00:00"), tz = "UTC"
))
orderfast(df)
Find Start Points for Event Analysis
Description
Finds R-based (1-indexed) positions where the value is 1 in an integer vector of 0s and 1s, specifically identifying episode start points. This function looks for positions where a 1 follows a 0 or is at the beginning of the vector, which is useful for identifying the start of glycemic events or episodes.
Usage
start_finder(df)
Arguments
df |
A dataframe with the first column containing an integer vector of 0s and 1s |
Value
A tibble containing start_index with R-based (1-indexed) positions where episodes start
Note: These index refer to positions in the provided input vector/dataframe, not necessarily rows of the original CGM df unless that vector was derived directly from df in row order.
Notes
- Returns R-based start_index positions relative to the provided input vector/dataframe.
- If used on vectors derived from a CGM df, index map directly to df rows.
See Also
Other GRID pipeline:
detect_between_maxima(),
find_local_maxima(),
find_max_after_hours(),
find_max_before_hours(),
find_min_after_hours(),
find_min_before_hours(),
find_new_maxima(),
grid(),
maxima_grid(),
mod_grid(),
transform_df()
Examples
# Load sample data
library(iglu)
data(example_data_5_subject)
data(example_data_hall)
# Create a binary vector indicating episode starts
binary_vector <- c(0, 0, 1, 1, 0, 1, 0, 0, 1, 1)
df <- data.frame(episode_starts = binary_vector)
# Find R-based index where episodes start
start_points <- start_finder(df)
print(paste("Start index:", paste(start_points$start_index, collapse = ", ")))
# Use with actual GRID results
grid_result <- grid(example_data_5_subject, gap = 15, threshold = 130)
grid_starts <- start_finder(grid_result$grid_vector)
print(paste("GRID episode starts:", length(grid_starts$start_index)))
# Analysis on larger dataset
large_grid <- grid(example_data_hall, gap = 15, threshold = 130)
large_starts <- start_finder(large_grid$grid_vector)
print(paste("GRID episode starts in larger dataset:", length(large_starts$start_index)))
Transform Dataframe for Analysis
Description
Performs data transformations required for GRID analysis, including mapping GRID episode starts to maxima within a 4-hour window and merging grid and maxima information. This function prepares data for downstream analysis by combining these results.
Usage
transform_df(grid_df, maxima_df)
Arguments
grid_df |
A dataframe containing grid analysis results |
maxima_df |
A dataframe containing maxima detection results |
Value
A tibble with transformed data containing columns (id, grid_time, grid_gl, maxima_time, maxima_gl)
See Also
grid, find_new_maxima, detect_between_maxima
Other GRID pipeline:
detect_between_maxima(),
find_local_maxima(),
find_max_after_hours(),
find_max_before_hours(),
find_min_after_hours(),
find_min_before_hours(),
find_new_maxima(),
grid(),
maxima_grid(),
mod_grid(),
start_finder()
Examples
# Load sample data
library(iglu)
data(example_data_5_subject)
data(example_data_hall)
# Complete pipeline example with smaller dataset
threshold <- 130
gap <- 60
hours <- 2
# 1) Find GRID points
grid_result <- grid(example_data_5_subject, gap = gap, threshold = threshold)
# 2) Find modified GRID points before 2 hours minimum
mod_grid <- mod_grid(example_data_5_subject,
start_finder(grid_result$grid_vector),
hours = hours,
gap = gap)
# 3) Find maximum point 2 hours after mod_grid point
mod_grid_maxima <- find_max_after_hours(example_data_5_subject,
start_finder(mod_grid$mod_grid_vector),
hours = hours)
# 4) Identify local maxima around episodes/windows
local_maxima <- find_local_maxima(example_data_5_subject)
# 5) Among local maxima, find maximum point after two hours
final_maxima <- find_new_maxima(example_data_5_subject,
mod_grid_maxima$max_index,
local_maxima$local_maxima_vector)
# 6) Map GRID points to maximum points (within 4 hours)
transform_maxima <- transform_df(grid_result$episode_start, final_maxima)
# 7) Redistribute overlapping maxima between GRID points
final_between_maxima <- detect_between_maxima(example_data_5_subject, transform_maxima)
# Complete pipeline example with larger dataset (example_data_hall)
# This demonstrates the same workflow on a more comprehensive dataset
hall_threshold <- 130
hall_gap <- 60
hall_hours <- 2
# 1) Find GRID points on larger dataset
hall_grid_result <- grid(example_data_hall, gap = hall_gap, threshold = hall_threshold)
# 2) Find modified GRID points
hall_mod_grid <- mod_grid(example_data_hall,
start_finder(hall_grid_result$grid_vector),
hours = hall_hours,
gap = hall_gap)
# 3) Find maximum points after mod_grid
hall_mod_grid_maxima <- find_max_after_hours(example_data_hall,
start_finder(hall_mod_grid$mod_grid_vector),
hours = hall_hours)
# 4) Identify local maxima
hall_local_maxima <- find_local_maxima(example_data_hall)
# 5) Find new maxima
hall_final_maxima <- find_new_maxima(example_data_hall,
hall_mod_grid_maxima$max_index,
hall_local_maxima$local_maxima_vector)
# 6) Transform data
hall_transform_maxima <- transform_df(hall_grid_result$episode_start, hall_final_maxima)
# 7) Detect between maxima
hall_final_between_maxima <- detect_between_maxima(example_data_hall, hall_transform_maxima)