CardiacDP can automatically read and collate heart rate data, and then employing the autocorrelation function (ACF) with a genetic algorithm framework to locate periodic sub-sequences within each sequence. From the candidate heart rates of these sub-sequences, the final results are either evaluated based on the autocorrelation value or a tracking index (TI).
install.packages("CardiacDP")
# Or from GitHub
devtools::install_github("Vicellken/CardiacDP")
# Or the source package from GitHub:
# Vector of package names
packages <- c("data.table", "doParallel", "dplyr", "foreach", "ggplot2", "purrr", "RColorBrewer", "stringr")
lapply(packages, function(pkg) {
if (!require(pkg, character.only = TRUE)) {
install.packages(pkg)
}
})
# Install the source package
install.packages("CardiacDP_0.4.0.tar.gz", repos = NULL, type = "source")This is an example shows the complete analysis pipeline:
library(CardiacDP)
zip_path <- "" # PATH_TO_ZIP_FILE
# use collatedata() to generate a single collated data table
collated <- collatedata(
file_path = zip_path,
output_file = NULL, # PATH_TO_SAVE_COLLATED_CSV
verbose = TRUE)
# csv_path <- "" # PATH_TO_COLLATED_CSV
# run computeHR() (no files are written by default)
output <- computeHR(
file_path = zip_path, # csv_path
save_outputs = TRUE,
output_dir = "", # PATH_TO_STORE_OUTPUTS
verbose = TRUE)The user can then access the output by the channel name. finalsubseq is a list showing the positions and durations of the final sub-sequences determined for each sequence. They are presented as data tables (s = start index of the sub-sequence; e = end index of the sub-sequence; p = which of the initial population the sub-sequence is derived from; and f = duration of the sub-sequence), the rows of which represent separate final sub-sequences. The example below shows the first five sequences (e.g. [[4]] indicates at the 4th minute there are three final sub-sequences).
# positions (in indices) and durations of the final sub-sequences
# NOTE: the results are not included to ease the reading, please refer to Appendix S4
# output[["finalsubseq"]][["Channel A"]]The corresponding candidate heart rates per sub-sequences can be found in candidateHR (ACF = autocorrelation value; lag = time lag; and hr = heart rate). Taking the 4th minute again as an example, there are two candidate heart rates for the first sub-sequence (as shown in [[4]][[1]]), and only one candidate heart rate for the other two sub-sequences (as shown in [[4]][[2]]and [[4]][[3]]).
# candidate heart rates of the final sub-sequences
# NOTE: the results are not included to ease the reading, please refer to Appendix S4
# output[["candidateHR"]][["Channel A"]]The final results after evaluating the candidate heart rates, checking for resolution and weighing for durations can eventually be obtained from results_ACF and results_TI. These results referred to evaluating the candidate heart rates by autocorrelation values (i.e. the “ACF + GA” approach) and the tracking index (i.e. the “ACF + GA +TI” approach) respectively. Each of them consists of 1) the details of the sub-sequences (subseqHR); 2) the weighted heart rate per sequence (weightedHR); and 3) a plot of weighted heart rate against time (plot).
## results obtained from evaluating the candidate heart rates by autocorrelation values
# output[["results_ACF"]][["Channel A"]]
# results obtained from evaluating the candidate heart rates by the tracking index
# output[["results_TI"]][["Channel A"]]| Variable | Content |
|---|---|
| finalsubseq | A list of positions and durations of the final periodic sub-sequences |
| candidateHR | A list of candidate heart rates extracted from ACF for each sub-sequence |
| results_ACF | Results obtained from evaluating the candidate heart rates of each sub-sequence based on autocorrelation values (i.e. following the “ACF + GA” approach as described in the main manuscript). Consisted of three items: 1) subseqHR: a list of sub-sequences and the corresponding heart rates and durations; 2) weightedHR: a list of final heart rates per sequence after weighing; and 3) plot: a plot of final heart rates against time |
| results_TI | Results obtained from evaluating the candidate heart rates of each sub-sequence using a tracking index (i.e. following the “ACF + GA + TI” approach as described in the main manuscript). Consisted of three items: 1) subseqHR: a list of sub-sequences and the corresponding heart rates and durations; 2) weightedHR: a list of final heart rates per sequence after weighing; and 3) plot: a plot of final heart rates against time |
By default, computeHR() does not write any files. If you want
CSV/PNG outputs, set save_outputs = TRUE and optionally provide
output_dir (if output_dir is NULL, it defaults to tempdir()):
csv_path <- system.file("extdata", "example.csv", package = "CardiacDP")
output <- computeHR(
file_path = csv_path,
reduce_res = 0.1,
save_outputs = TRUE,
output_dir = tempdir()
)For each channel and method (ACF and TI), the following CSV files are saved:
{Channel}_ACF_subseqHR.csv- Details of sub-sequences with heart rates (ACF method){Channel}_ACF_weightedHR.csv- Weighted heart rates per analysis interval (ACF method){Channel}_TI_subseqHR.csv- Details of sub-sequences with heart rates (TI method){Channel}_TI_weightedHR.csv- Weighted heart rates per analysis interval (TI method)
Note: Channel names with spaces (e.g., “Channel A”) are converted to underscores (e.g., “Channel_A”) in filenames.
For each channel and method, heart rate plots are saved:
{Channel}_ACF_plot.png- Heart rate plot (ACF method){Channel}_TI_plot.png- Heart rate plot (TI method)
weightedHR CSV files contain:
ix- Sequence index (1, 2, 3, …)Time_min- Time in minutes (midpoint of analysis interval = (ix - 0.5) × analysis_interval)wACF- Weighted autocorrelation valuewhr- Weighted heart rate in beats per minute (can be NA)
subseqHR CSV files contain:
ix- Sequence indexwin- Sub-sequence window number within the sequences,e,p,f- Sub-sequence parameters (start, end, population, fitness)ACF- Autocorrelation valuelag- Time laghr- Heart rate in beats per minute (can be NA)res- Resolution usedTime_min- Time in minutes (start of analysis interval = (ix - 1) × analysis_interval)
The saved CSV files contain all the data needed to reproduce the heart rate plots. Use the weightedHR CSV files for plotting:
library(ggplot2)
library(RColorBrewer)
library(data.table)
# Read the saved weighted heart rate data (example; assumes you ran computeHR(save_outputs=TRUE))
data <- fread(output$files[["Channel A"]][["TI_weightedHR"]])
# Create the plot (matching the package output)
palette <- brewer.pal(n = 11, name = "RdYlBu")
names(palette) <- seq(0, 10, 1) / 10
ggplot() +
geom_point(
data = data,
aes(x = Time_min, y = whr, fill = factor(floor(wACF * 10) / 10)),
colour = "black", shape = 21, size = 4, alpha = 0.8
) +
scale_fill_manual(
name = "ACF", values = palette, na.value = NA,
na.translate = FALSE, guide = "legend"
) +
scale_y_continuous(
name = "Heart rate (bpm)",
breaks = seq(0, ceiling(max(data$whr, na.rm = TRUE) / 50) * 50, 50),
limits = c(0, ceiling(max(data$whr, na.rm = TRUE) / 50) * 50),
expand = c(0, 0)
) +
scale_x_continuous(
name = "Time (min)",
breaks = seq(0, ceiling(max(data$Time_min, na.rm = TRUE) / 30) * 30, 30),
limits = c(0, ceiling(max(data$Time_min, na.rm = TRUE) / 30) * 30),
expand = c(0, 0)
) +
theme_linedraw() +
theme(
text = element_text(size = 12, colour = "black"),
panel.grid.minor = element_blank(),
panel.border = element_rect(fill = NA, colour = "black", linewidth = 1)
)Key columns for plotting:
- X-axis:
Time_min- Time in minutes - Y-axis:
whr- Weighted heart rate (bpm) - Fill color:
wACF- Weighted autocorrelation value (colored by discrete bins)
