Segment pattern from a time-series x
via Adaptive Empirical Pattern
Transformation (ADEPT).
segmentPattern( x, x.fs, template, pattern.dur.seq, similarity.measure = "cov", similarity.measure.thresh = 0, x.adept.ma.W = NULL, finetune = NULL, finetune.maxima.ma.W = NULL, finetune.maxima.nbh.W = NULL, run.parallel = FALSE, run.parallel.cores = 1L, x.cut = TRUE, x.cut.vl = 6000, compute.template.idx = FALSE )
x | A numeric vector. A time-series to segment pattern from. |
---|---|
x.fs | A numeric scalar. Frequency at which a time-series |
template | A list of numeric vectors, or a numeric vector. Each vector represents a distinct pattern template used in segmentation. |
pattern.dur.seq | A numeric vector. A grid of potential pattern durations used in segmentation. Expressed in seconds. See: Details. |
similarity.measure | A character scalar. Statistic used to compute similarity
between a time-series
Default is |
similarity.measure.thresh | A numeric scalar. Threshold of minimal similarity
value between a time-series |
x.adept.ma.W | A numeric scalar.
A length of a window used in moving average smoothing of a time-series |
finetune | A character scalar. A type of fine-tuning procedure employed in
segmentation. Defaults to
|
finetune.maxima.ma.W | A numeric scalar.
A length of a window used in moving average smoothing of a time-series |
finetune.maxima.nbh.W | A numeric scalar.
A length of the two neighborhoods centered at preliminarily identified
beginning and end of a pattern
within which we search for local maxima of |
run.parallel | A logical scalar. Whether or not to use parallel execution in the algorithm
with |
run.parallel.cores | An integer scalar. The number of cores to use for parallel execution. Defaults to 1L (no parallel). DOES NOT WORK ON WINDOWS. |
x.cut | A logical scalar. Whether or not to use time optimization procedure in
which a time-series |
x.cut.vl | An integer scalar.
Defines a vector length of parts that |
compute.template.idx | A logical scalar. Whether or not to compute and return information about
which of the provided pattern templates yielded a similarity matrix value
that corresponds to an identified pattern occurrence.
Setting to |
A data.frame
with segmentation results. Each row
describes one identified pattern occurrence:
tau_i
- index of x
where pattern starts,
T_i
- pattern duration, expressed in x
vector length,
sim_i
- similarity between a pattern and x
;
note: if "maxima"
fine-tune and/or x
smoothing is employed,
the similarity value between the final segmented pattern and a template
may differ from the value in this table,
template_i
- if compute.template.idx
equals TRUE
:
index of a template best matched to x
;
if compute.template.idx
equals FALSE
: NA
.
Function implements Adaptive Empirical Pattern Transformation (ADEPT) method for pattern segmentation
from a time-series x
.
ADEPT is optimized to perform fast, accurate walking strides segmentation from
high-density data collected with a wearable accelerometer during walking.
ADEPT identifies patterns in a time-series x
via maximization of chosen
similarity statistic (correlation, covariance, etc.) between a time-series x
and a pattern template(s). It accounts for variability in both
(1) pattern duration and (2) pattern shape.
Karas, M., Straczkiewicz, M., Fadel, W., Harezlak, J., Crainiceanu, C.M., Urbanek, J.K. (2019). Adaptive empirical pattern transformation (ADEPT) with application to walking stride segmentation. Biostatistics. https://doi.org/10.1093/biostatistics/kxz033
## Example 1: Simulate a time-series `x`. Assume that ## - `x` is collected at a frequency of 100 Hz, ## - there is one shape of pattern present within `x`, ## - each pattern lasts 1 second, ## - there is no noise in the collected data. true.pattern <- cos(seq(0, 2 * pi, length.out = 100)) x <- c(true.pattern[1], replicate(10, true.pattern[-1])) ## Segment pattern from x. out <- segmentPattern( x = x, x.fs = 100, template = true.pattern, pattern.dur.seq = c(0.9, 0.95, 1.03, 1.1), similarity.measure = "cor", compute.template.idx = TRUE) out#> tau_i T_i sim_i template_i #> 1 4 95 0.9987941 1 #> 2 98 103 0.9992482 1 #> 3 202 95 0.9987941 1 #> 4 296 103 0.9992482 1 #> 5 400 95 0.9987941 1 #> 6 494 103 0.9992482 1 #> 7 598 95 0.9987941 1 #> 8 692 103 0.9992482 1 #> 9 796 95 0.9987941 1 #> 10 895 95 0.9987941 1## Segment pattern from x. Now assume a grid of potential pattern duratios ## contains true pattern duration out <- segmentPattern( x = x, x.fs = 100, template = true.pattern, pattern.dur.seq = c(0.9, 0.95, 1, 1.03, 1.1), similarity.measure = "cor", compute.template.idx = TRUE) out#> tau_i T_i sim_i template_i #> 1 1 100 1 1 #> 2 100 100 1 1 #> 3 199 100 1 1 #> 4 298 100 1 1 #> 5 397 100 1 1 #> 6 496 100 1 1 #> 7 595 100 1 1 #> 8 694 100 1 1 #> 9 793 100 1 1 #> 10 892 100 1 1## Example 2: Simulate a time-series `x`. Assume that ## - `x` is collected at a frequency of 100 Hz, ## - there are two shapes of pattern present within `x`, ## - patterns have various duration, ## - there is no noise in the collected data. true.pattern.1 <- cos(seq(0, 2 * pi, length.out = 200)) true.pattern.2 <- true.pattern.1 true.pattern.2[70:130] <- 2 * true.pattern.2[min(70:130)] + abs(true.pattern.2[70:130]) x <- numeric() for (vl in seq(70, 130, by = 10)){ true.pattern.1.s <- approx( seq(0, 1, length.out = 200), true.pattern.1, xout = seq(0, 1, length.out = vl))$y true.pattern.2.s <- approx( seq(0, 1, length.out = 200), true.pattern.2, xout = seq(0, 1, length.out = vl))$y x <- c(x, true.pattern.1.s[-1], true.pattern.2.s[-1]) if (vl == 70) x <- c(true.pattern.1.s[1], x) } ## Segment pattern from x. Use a `template` object consisting of both ## true patterns used in `x` simulation. out <- segmentPattern( x = x, x.fs = 100, template = list(true.pattern.1, true.pattern.2), pattern.dur.seq = 60:130 * 0.01, similarity.measure = "cor", compute.template.idx = TRUE) out#> tau_i T_i sim_i template_i #> 1 1 70 1 1 #> 2 70 70 1 2 #> 3 139 80 1 1 #> 4 218 80 1 2 #> 5 297 90 1 1 #> 6 386 90 1 2 #> 7 475 100 1 1 #> 8 574 100 1 2 #> 9 673 110 1 1 #> 10 782 110 1 2 #> 11 891 120 1 1 #> 12 1010 120 1 2 #> 13 1129 130 1 1 #> 14 1258 130 1 2## Example 3: Simulate a time-series `x`. Assume that ## - `x` is collected at a frequency of 100 Hz, ## - there are two shapes of a pattern present within `x`, ## - patterns have various duration, ## - there is noise in the collected data. set.seed(1) x <- x + rnorm(length(x), sd = 0.5) ## Segment pattern from x. out <- segmentPattern( x = x, x.fs = 100, template = list(true.pattern.1, true.pattern.2), pattern.dur.seq = 60:130 * 0.01, similarity.measure = "cor", compute.template.idx = TRUE) out#> tau_i T_i sim_i template_i #> 1 4 63 0.8615665 1 #> 2 76 62 0.7351057 2 #> 3 137 84 0.7708233 1 #> 4 220 76 0.6768561 2 #> 5 295 92 0.8507212 1 #> 6 391 83 0.7404364 2 #> 7 473 106 0.8300020 1 #> 8 582 87 0.6515298 2 #> 9 668 118 0.8047385 1 #> 10 785 106 0.6958617 2 #> 11 890 123 0.7927484 1 #> 12 1015 113 0.6789908 1 #> 13 1129 130 0.7938183 1 #> 14 1265 123 0.7686607 2## Segment pattern from x. Use `x.adept.ma.W` to define a length of a smoothing ## window to smooth `x` for similarity matrix computation. out <- segmentPattern( x = x, x.fs = 100, template = list(true.pattern.1, true.pattern.2), pattern.dur.seq = 60:130 * 0.01, similarity.measure = "cor", x.adept.ma.W = 0.1, compute.template.idx = TRUE) out#> tau_i T_i sim_i template_i #> 1 4 63 0.9931174 1 #> 2 75 63 0.9683646 2 #> 3 139 79 0.9683054 1 #> 4 217 80 0.9748040 2 #> 5 296 94 0.9802473 1 #> 6 391 82 0.9462213 2 #> 7 472 106 0.9855837 1 #> 8 578 93 0.9608881 2 #> 9 670 115 0.9887225 1 #> 10 784 107 0.9562694 2 #> 11 896 113 0.9734575 1 #> 12 1008 127 0.9703118 1 #> 13 1134 116 0.9606235 1 #> 14 1266 122 0.9593345 2## Segment pattern from x. Use `x.adept.ma.W` to define a length of a smoothing ## window to smooth `x` for similarity matrix computation. Employ a fine-tuning ## procedure for stride identification. out <- segmentPattern( x = x, x.fs = 100, template = list(true.pattern.1, true.pattern.2), pattern.dur.seq = 60:130 * 0.01, similarity.measure = "cor", x.adept.ma.W = 0.1, finetune = "maxima", finetune.maxima.nbh.W = 0.3, compute.template.idx = TRUE) out#> tau_i T_i sim_i template_i #> 1 4 67 0.9931174 1 #> 2 70 78 0.9683646 2 #> 3 147 60 0.9060130 2 #> 4 206 98 0.9785617 2 #> 5 303 78 0.9802473 1 #> 6 380 107 0.9666486 2 #> 7 486 93 0.9855837 1 #> 8 578 93 0.9608881 2 #> 9 670 105 0.9887225 1 #> 10 774 113 0.9786236 2 #> 11 893 128 0.9734575 1 #> 12 1020 112 0.9453138 1 #> 13 1131 123 0.9661650 1 #> 14 1253 125 0.9593345 2## Segment pattern from x. Employ a fine-tuning procedure for stride ## identification. Smooth `x` for both similarity matrix computation ## (set `x.adept.ma.W = 0.1`) and for fine-tune peak detection procedure ## (set `finetune.maxima.nbh.W = 0.3`). out <- segmentPattern( x = x, x.fs = 100, template = list(true.pattern.1, true.pattern.2), pattern.dur.seq = 60:130 * 0.01, similarity.measure = "cor", x.adept.ma.W = 0.1, finetune = "maxima", finetune.maxima.nbh.W = 0.3, compute.template.idx = TRUE) out#> tau_i T_i sim_i template_i #> 1 4 67 0.9931174 1 #> 2 70 78 0.9683646 2 #> 3 147 60 0.9060130 2 #> 4 206 98 0.9785617 2 #> 5 303 78 0.9802473 1 #> 6 380 107 0.9666486 2 #> 7 486 93 0.9855837 1 #> 8 578 93 0.9608881 2 #> 9 670 105 0.9887225 1 #> 10 774 113 0.9786236 2 #> 11 893 128 0.9734575 1 #> 12 1020 112 0.9453138 1 #> 13 1131 123 0.9661650 1 #> 14 1253 125 0.9593345 2