Skip to content

Commit c63ddd5

Browse files
move new code to new function markerButtonForRest + documentation + unit test #1267
1 parent 76ec1d5 commit c63ddd5

6 files changed

+264
-111
lines changed

NAMESPACE

+2-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ export(g.analyse, g.calibrate,
4343
g.part5.analyseRest, part6AlignIndividuals,
4444
part6PairwiseAggregation, g.part6, g.report.part6,
4545
check_log, g.report.part5_dictionary, DFA, ABI, SSP, visualReport,
46-
splitRecords, getSplitNames, addSplitNames)
46+
splitRecords, getSplitNames, addSplitNames,
47+
markerButtonForRest)
4748

4849
importFrom("grDevices", "colors", "dev.off", "pdf",
4950
"rgb", "rainbow", "palette", "adjustcolor", "gray.colors")

R/g.part5.analyseRest.R

+1-110
Original file line numberDiff line numberDiff line change
@@ -94,117 +94,8 @@ g.part5.analyseRest = function(sibreport = NULL, dsummary = NULL,
9494
}
9595
#-----------------------------------------------------------
9696
# Consider using marker button data to aid nap detection
97+
sibreport = markerButtonForRest(sibreport, params_sleep, ts)
9798

98-
# nap_markerbutton_method:
99-
# 0 do not use marker button (default)
100-
# 1 do not require it and copy timing => use marker button to improve definition of nap
101-
# 2 require it and do not copy timing => use marker button as a condition for nap detection
102-
# 3 require it and copy timing => use marker button to improve definition and as a condition for nap detection
103-
104-
# Explanation objects as used below
105-
# nap_copy_timing_mb: rely on marker for final timing of the nap?
106-
# if TRUE, only consider marker buttons before midtime of sib for start
107-
# and only consider marker buttons after midtime of sib for end
108-
# if FALSE, then consider any mark button, this uses the marker solely as
109-
# a confirmation that nap nearby
110-
111-
# nap_require_mb: require availability of marker to consider
112-
# detection of a nap
113-
# if TRUE, only keep sibs that had marker button nearby
114-
# if FALSE, also keep sibs that may not have marker button but meet
115-
# criteria for another reason
116-
#
117-
sibreport$ignore = FALSE # if no marker button than keep sibs
118-
if (params_sleep[["nap_markerbutton_method"]] > 0) {
119-
if (params_sleep[["nap_markerbutton_method"]] > 1) {
120-
sibreport$ignore = TRUE # if no marker button then ignore all sibs
121-
}
122-
# maximum gap allowed between sib edge and marker
123-
nap_mb_max_dist = params_sleep[["nap_markerbutton_max_distance"]]
124-
125-
# If marker button data available
126-
if ("marker" %in% colnames(ts)) {
127-
if (1 %in% ts$marker) {
128-
if (params_sleep[["nap_markerbutton_method"]] == 1) {
129-
nap_require_mb = FALSE
130-
nap_copy_timing_mb = TRUE
131-
} else if (params_sleep[["nap_markerbutton_method"]] == 2) {
132-
nap_require_mb = TRUE
133-
nap_copy_timing_mb = FALSE
134-
} else if (params_sleep[["nap_markerbutton_method"]] == 3) {
135-
nap_require_mb = TRUE
136-
nap_copy_timing_mb = TRUE
137-
}
138-
# Calculate time in minutes to nearest button press
139-
# that starts before and after midway the sib, for start and end respectively
140-
sibreport$midtime = sibreport$start + (sibreport$end - sibreport$start) / 2
141-
marker_times = ts$time[which(ts$marker == 1)]
142-
sibreport$start_to_marker = NA
143-
sibreport$end_to_marker = NA
144-
145-
for (hi in 1:nrow(sibreport)) {
146-
# assess duration marker buttons relative to sib midtime
147-
delta_times = as.numeric(sibreport$midtime[hi]) - as.numeric(marker_times)
148-
if (nap_copy_timing_mb == TRUE) {
149-
# Plan is to use marker button timing, so only consider
150-
# for start the marker buttons that start before midtime
151-
end_delta_times = delta_times[which(delta_times < 0)]
152-
# Plan is to use marker button timing, so only consider
153-
# for end the marker buttons that start after midtime
154-
start_delta_times = delta_times[which(delta_times > 0)]
155-
} else {
156-
# Plan is NOT to use marker button timing, so any nearby
157-
# marker button is sufficient
158-
start_delta_times = end_delta_times = delta_times
159-
}
160-
nap_start_found = nap_end_found = FALSE
161-
half_sib_dur = sibreport$duration[hi] / 2
162-
# find marker for start nap
163-
if (length(start_delta_times) > 0) {
164-
sibreport$start_to_marker[hi] = min(abs(start_delta_times)) / 60 - half_sib_dur
165-
if (any(sibreport$start_to_marker[hi] < nap_mb_max_dist)) {
166-
# marker button nearby
167-
if (nap_copy_timing_mb == TRUE) {
168-
# use nearby marker button to overwrite sib start
169-
tmp_start = sibreport$midtime[hi] - start_delta_times[which.min(abs(start_delta_times))]
170-
}
171-
nap_start_found = TRUE
172-
}
173-
}
174-
# find marker for end nap
175-
if (length(end_delta_times) > 0) {
176-
sibreport$end_to_marker[hi] = min(abs(end_delta_times)) / 60 - half_sib_dur
177-
if (any(abs(sibreport$end_to_marker[hi]) < nap_mb_max_dist)) {
178-
# marker button nearby
179-
if (nap_copy_timing_mb == TRUE) {
180-
# use nearby marker button to overwrite sib end
181-
tmp_end = sibreport$midtime[hi] + abs(end_delta_times[which.min(abs(end_delta_times))])
182-
}
183-
nap_end_found = TRUE
184-
}
185-
}
186-
if (nap_require_mb == TRUE && (nap_start_found == FALSE || nap_end_found == FALSE)) {
187-
# if nearby marker button is required but none was available
188-
# ignore this sib
189-
sibreport$ignore[hi] = TRUE
190-
} else {
191-
# enable nap detection further down becaue marker button was found
192-
sibreport$ignore[hi] = FALSE
193-
# overwrite all other sibs that overlap such that they form duplicated rows
194-
sibreport$start[hi] = tmp_start
195-
sibreport$start[which(sibreport$start < sibreport$midtime[hi] & sibreport$start >= tmp_start)] = sibreport$start[hi]
196-
sibreport$end[hi] = tmp_end
197-
sibreport$end[which(sibreport$end < sibreport$midtime[hi] & sibreport$end >= tmp_end)] = sibreport$end[hi]
198-
# recalculate midtime
199-
sibreport$midtime = sibreport$start + (sibreport$end - sibreport$start) / 2
200-
}
201-
}
202-
}
203-
}
204-
}
205-
# remove duplicate rows
206-
sibreport = sibreport[!duplicated(sibreport[, c("start", "end")]), ]
207-
20899
sibreport$startHour = as.numeric(format(sibreport$start, "%H"))
209100
sibreport$endHour = as.numeric(format(sibreport$end, "%H"))
210101

R/markerButtonForRest.R

+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
markerButtonForRest = function(sibreport, params_sleep, ts) {
2+
#-----------------------------------------------------------
3+
# Consider using marker button data to aid nap detection
4+
5+
# nap_markerbutton_method:
6+
# 0 do not use marker button (default)
7+
# 1 do not require it and copy timing => use marker button to improve definition of nap
8+
# 2 require it and do not copy timing => use marker button as a condition for nap detection
9+
# 3 require it and copy timing => use marker button to improve definition and as a condition for nap detection
10+
11+
# Explanation objects as used below
12+
# nap_copy_timing_mb: rely on marker for final timing of the nap?
13+
# if TRUE, only consider marker buttons before midtime of sib for start
14+
# and only consider marker buttons after midtime of sib for end
15+
# if FALSE, then consider any mark button, this uses the marker solely as
16+
# a confirmation that nap nearby
17+
18+
# nap_require_mb: require availability of marker to consider
19+
# detection of a nap
20+
# if TRUE, only keep sibs that had marker button nearby
21+
# if FALSE, also keep sibs that may not have marker button but meet
22+
# criteria for another reason
23+
#
24+
sibreport$ignore = FALSE # if no marker button than keep sibs
25+
if (params_sleep[["nap_markerbutton_method"]] > 0) {
26+
if (params_sleep[["nap_markerbutton_method"]] > 1) {
27+
sibreport$ignore = TRUE # if no marker button then ignore all sibs
28+
}
29+
# maximum gap allowed between sib edge and marker
30+
nap_mb_max_dist = params_sleep[["nap_markerbutton_max_distance"]]
31+
32+
# If marker button data available
33+
if ("marker" %in% colnames(ts)) {
34+
if (1 %in% ts$marker) {
35+
if (params_sleep[["nap_markerbutton_method"]] == 1) {
36+
nap_require_mb = FALSE
37+
nap_copy_timing_mb = TRUE
38+
} else if (params_sleep[["nap_markerbutton_method"]] == 2) {
39+
nap_require_mb = TRUE
40+
nap_copy_timing_mb = FALSE
41+
} else if (params_sleep[["nap_markerbutton_method"]] == 3) {
42+
nap_require_mb = TRUE
43+
nap_copy_timing_mb = TRUE
44+
}
45+
# Calculate time in minutes to nearest button press
46+
# that starts before and after midway the sib, for start and end respectively
47+
sibreport$midtime = sibreport$start + (sibreport$end - sibreport$start) / 2
48+
marker_times = ts$time[which(ts$marker == 1)]
49+
sibreport$start_to_marker = NA
50+
sibreport$end_to_marker = NA
51+
52+
for (hi in 1:nrow(sibreport)) {
53+
# assess duration marker buttons relative to sib midtime
54+
delta_times = as.numeric(sibreport$midtime[hi]) - as.numeric(marker_times)
55+
if (nap_copy_timing_mb == TRUE) {
56+
# Plan is to use marker button timing, so only consider
57+
# for start the marker buttons that start before midtime
58+
end_delta_times = delta_times[which(delta_times < 0)]
59+
# Plan is to use marker button timing, so only consider
60+
# for end the marker buttons that start after midtime
61+
start_delta_times = delta_times[which(delta_times > 0)]
62+
} else {
63+
# Plan is NOT to use marker button timing, so any nearby
64+
# marker button is sufficient
65+
start_delta_times = end_delta_times = delta_times
66+
}
67+
nap_start_found = nap_end_found = FALSE
68+
half_sib_dur = sibreport$duration[hi] / 2
69+
tmp_start = tmp_end = NULL
70+
# find marker for start nap
71+
if (length(start_delta_times) > 0) {
72+
sibreport$start_to_marker[hi] = min(abs(start_delta_times)) / 60 - half_sib_dur
73+
if (any(sibreport$start_to_marker[hi] < nap_mb_max_dist)) {
74+
# marker button nearby
75+
if (nap_copy_timing_mb == TRUE) {
76+
# use nearby marker button to overwrite sib start
77+
tmp_start = sibreport$midtime[hi] - start_delta_times[which.min(abs(start_delta_times))]
78+
}
79+
nap_start_found = TRUE
80+
}
81+
}
82+
# find marker for end nap
83+
if (length(end_delta_times) > 0) {
84+
sibreport$end_to_marker[hi] = min(abs(end_delta_times)) / 60 - half_sib_dur
85+
if (any(sibreport$end_to_marker[hi] < nap_mb_max_dist)) {
86+
# marker button nearby
87+
if (nap_copy_timing_mb == TRUE) {
88+
# use nearby marker button to overwrite sib end
89+
tmp_end = sibreport$midtime[hi] + abs(end_delta_times[which.min(abs(end_delta_times))])
90+
}
91+
nap_end_found = TRUE
92+
}
93+
}
94+
if (nap_require_mb == TRUE && (nap_start_found == FALSE || nap_end_found == FALSE)) {
95+
# if nearby marker button is required but none was available
96+
# ignore this sib
97+
sibreport$ignore[hi] = TRUE
98+
} else {
99+
# enable nap detection further down becaue marker button was found
100+
sibreport$ignore[hi] = FALSE
101+
# overwrite all other sibs that overlap such that they form duplicated rows
102+
if (length(tmp_start) > 0) {
103+
sibreport$start[hi] = tmp_start
104+
sibreport$start[which(sibreport$start < sibreport$midtime[hi] & sibreport$start >= tmp_start)] = sibreport$start[hi]
105+
}
106+
if (length(tmp_end) > 0) {
107+
sibreport$end[hi] = tmp_end
108+
sibreport$end[which(sibreport$end < sibreport$midtime[hi] & sibreport$end >= tmp_end)] = sibreport$end[hi]
109+
}
110+
# recalculate midtime
111+
sibreport$midtime = sibreport$start + (sibreport$end - sibreport$start) / 2
112+
}
113+
}
114+
}
115+
}
116+
}
117+
# remove duplicate rows
118+
sibreport = sibreport[!duplicated(sibreport[, c("start", "end")]), ]
119+
return(sibreport)
120+
}

man/g.part5.analyseRest.Rd

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
\value{
4444
List with updated objects dsummary, ds_names, fi, and di
4545
}
46+
\keyword{internal}
4647
\author{
4748
Vincent T van Hees <v.vanhees@accelting.com>
4849
}

man/markerButtonForRest.Rd

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
\name{markerButtonForRest}
2+
\alias{markerButtonForRest}
3+
\title{
4+
Improve the labelling of rest with marker button data
5+
}
6+
\description{
7+
Improve the labelling of rest with marker button data.
8+
Currently only functional for Actiwatch and Philips Healthband.
9+
}
10+
\usage{
11+
markerButtonForRest(sibreport = NULL, ts = NULL, params_sleep = NULL)
12+
}
13+
\arguments{
14+
\item{sibreport}{
15+
sibreport data.frame produced by \link{g.sibreport}
16+
}
17+
\item{ts}{
18+
Data.frame with time series object passed on from \link{g.part5_analyseSegment} and \link{g.part5}.
19+
}
20+
\item{params_sleep}{
21+
See \link{GGIR}
22+
}
23+
}
24+
\value{
25+
Updated sibreport
26+
}
27+
\keyword{internal}
28+
\author{
29+
Vincent T van Hees <v.vanhees@accelting.com>
30+
}

0 commit comments

Comments
 (0)