Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Facilitate research on comparing self-reported nap/nonwear with acc-based daytime rest detection #900

Merged
merged 48 commits into from
Sep 13, 2023
Merged
Changes from 42 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
8069dba
progress on mapping overlap selfreported nonwear, nap and sibs #687
vincentvanhees Oct 19, 2022
64c02fc
splitting nap classification from sibreport analyses, first draft of …
vincentvanhees Oct 19, 2022
e527e45
limit sibanalyses to waking hours only
vincentvanhees Oct 19, 2022
39d23a2
#687 updating var names, addressing timestamp issue and including ext…
vincentvanhees Oct 21, 2022
632c5df
Merge branch 'master' into issue687_nap_enhancement2
vincentvanhees Oct 24, 2022
409670f
#687 sibreport now has duration for selfreported naps and nonwear and…
vincentvanhees Oct 26, 2022
06aeeb7
#687 move code to separate function and add unit test
vincentvanhees Oct 26, 2022
d2fedee
merge master
vincentvanhees Nov 3, 2022
8090dfc
Merge branch 'master' into issue687_nap_enhancement2
vincentvanhees Dec 5, 2022
9b82e13
merge master branch
vincentvanhees Dec 7, 2022
9f5a278
merge master
vincentvanhees Feb 27, 2023
502f153
Merge branch 'master' into issue687_nap_enhancement2
vincentvanhees Mar 16, 2023
0f83af1
Merge branch 'master' into issue687_nap_enhancement2
vincentvanhees Mar 24, 2023
1e17a81
Merge branch 'master' into issue687_nap_enhancement2
vincentvanhees Mar 24, 2023
59719fa
Merge branch 'master' into issue687_nap_enhancement2
vincentvanhees Mar 24, 2023
d6c924e
merge master
vincentvanhees Mar 24, 2023
852bad1
Merge branch 'master' into issue687_nap_enhancement2
vincentvanhees Apr 28, 2023
d57721d
Merge branch 'master' into issue687_nap_enhancement2
vincentvanhees Apr 29, 2023
d4b12ca
Merge branch 'master' into issue687_nap_enhancement2
vincentvanhees May 1, 2023
09563b7
merge master
vincentvanhees May 9, 2023
ac8f05b
Merge branch 'master' into issue687_nap_enhancement2
vincentvanhees May 10, 2023
1730e5c
Merge branch 'master' into issue687_nap_enhancement2
vincentvanhees May 11, 2023
db73f8f
Merge branch 'master' into issue687_nap_enhancement2
vincentvanhees Jun 6, 2023
adeeab4
Merge branch 'master' into issue687_nap_enhancement2
vincentvanhees Jun 6, 2023
37c165e
merge master
vincentvanhees Jun 18, 2023
d8b79c0
Merge branch 'master' into issue687_nap_enhancement2
vincentvanhees Jun 18, 2023
e220dc1
Merge branch 'master' into issue687_nap_enhancement2
vincentvanhees Jun 18, 2023
65e5cf3
Merge branch 'master' into issue687_nap_enhancement2
vincentvanhees Jun 22, 2023
6e4b828
Merge branch 'master' into issue687_nap_enhancement2_test_merge_master
vincentvanhees Aug 2, 2023
59887b0
Merge branch 'master' into issue687_nap_test_merge_master
vincentvanhees Aug 31, 2023
b6e61da
Moving rest analyses to new g.part5_analyseSegment function #687
vincentvanhees Sep 1, 2023
9158f57
update documentation for previous commit
vincentvanhees Sep 1, 2023
b235928
make indentation align with rest of repo
vincentvanhees Sep 1, 2023
99501e7
Merge branch 'master' into issue687_nap_enhancement2
vincentvanhees Sep 1, 2023
17e35e8
Merge branch 'master' into issue687_nap_enhancement2
vincentvanhees Sep 12, 2023
129c5bc
making sure rest analysis is not run when no sibreport object is avai…
vincentvanhees Sep 12, 2023
4ddaebe
Improving documentation for #687 and updating changelog
vincentvanhees Sep 12, 2023
6bfcc41
making sure code can run when nap_model is not specified
vincentvanhees Sep 12, 2023
fef0bd0
reusing argument possible_nap_duration to specify minimum sib duratio…
vincentvanhees Sep 12, 2023
848ebd5
Adding filter options for sibreport anlaysis #687
vincentvanhees Sep 12, 2023
ebbe8fa
Update NEWS.md
vincentvanhees Sep 12, 2023
cf90d60
fix typo in documentation
vincentvanhees Sep 12, 2023
c80331e
transform time in g.part5.analyseRest if needed
jhmigueles Sep 13, 2023
ee01f80
fix issue introduced in previous commit, make sure time is character …
jhmigueles Sep 13, 2023
708cfff
improve code comments
vincentvanhees Sep 13, 2023
00561e7
update to master
jhmigueles Sep 13, 2023
c21adc4
add check that input is character and condense code
vincentvanhees Sep 13, 2023
3c36304
Merge branch 'issue687_nap_enhancement2' of https://github.com/wadpac…
vincentvanhees Sep 13, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion NAMESPACE
Original file line number Diff line number Diff line change
@@ -39,7 +39,9 @@ export(g.analyse, g.calibrate,
ShellDoc2Vignette, parametersVignette,
correctOlderMilestoneData,
convertEpochData, appendRecords, extractID,
g.part5_analyseSegment, g.part5_initialise_ts)
g.part5_analyseSegment, g.part5_initialise_ts,
g.part5.analyseRest)

importFrom("grDevices", "colors", "dev.off", "pdf","rainbow","rgb")
importFrom("graphics", "abline", "axis", "par", "plot", "plot.new",
"rect","axis.POSIXct", "barplot", "box", "legend",
3 changes: 3 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# CHANGES IN GGIR VERSION 2.10-3

- Part 5: Now able to assess overlap between self-reported naps and nonwear
with sustained inactivity bouts in order to facilitate research on nap detection. Fixes #687

- Visualreport: Bug fixed extracting the numeric value of the days to exclude in g.plot5 #879

- Part 1: Fixed minor bug to keep calibration data in the data quality report after re-running parts 1 and 2 with overwrite = TRUE and backup.cal.coef = "retrieve" #896
2 changes: 1 addition & 1 deletion R/check_params.R
Original file line number Diff line number Diff line change
@@ -30,7 +30,7 @@ check_params = function(params_sleep = c(), params_metrics = c(),
#-----------------------------------------------------------------------------------------
if (length(params_sleep) > 0) { # Check class of sleep parameters
numeric_params = c("anglethreshold", "timethreshold", "longitudinal_axis", "possible_nap_window", "possible_nap_dur",
"colid", "coln1", "def.noc.sleep", "nnights", "sleepefficiency.metric")
"colid", "coln1", "def.noc.sleep", "nnights", "sleepefficiency.metric", "possible_nap_edge_acc")
boolean_params = c("ignorenonwear", "constrain2range", "HASPT.ignore.invalid",
"relyonguider", "sleeplogidnum")
character_params = c("HASPT.algo", "HASIB.algo", "Sadeh_axis", "nap_model",
113 changes: 63 additions & 50 deletions R/g.part5.R
Original file line number Diff line number Diff line change
@@ -227,6 +227,7 @@ g.part5 = function(datadir = c(), metadatadir = c(), f0=c(), f1=c(),
}

for (sibDef in def) { # loop through sleep definitions (defined by angle and time threshold in g.part3)

ws3new = ws3 # reset wse3new, because if part5_agg2_60seconds is TRUE then this will have been change in the previous iteration of the loop
if (params_general[["part5_agg2_60seconds"]] == TRUE) {
ts = ts_backup
@@ -314,7 +315,7 @@ g.part5 = function(datadir = c(), metadatadir = c(), f0=c(), f1=c(),
#===============================================
# Use sib.report to classify naps, non-wear and integrate these in time series
# does not depend on bout detection criteria or window definitions.
if (params_output[["do.sibreport"]] == TRUE & length(params_sleep[["nap_model"]]) > 0) {
if (params_output[["do.sibreport"]] == TRUE) {
IDtmp = as.character(ID)
sibreport = g.sibreport(ts, ID = IDtmp, epochlength = ws3new, logs_diaries,
desiredtz = params_general[["desiredtz"]])
@@ -324,66 +325,66 @@ g.part5 = function(datadir = c(), metadatadir = c(), f0=c(), f1=c(),
dir.create(file.path(metadatadir, ms5.sibreport))
}
shortendFname = gsub(pattern = "[.]|RData|csv|cwa|bin", replacement = "", x = fnames.ms3[i], ignore.case = TRUE)

sibreport_fname = paste0(metadatadir,ms5.sibreport,"/sib_report_", shortendFname, "_",sibDef,".csv")
data.table::fwrite(x = sibreport, file = sibreport_fname, row.names = FALSE,
sep = params_output[["sep_reports"]])
# nap/sib/nonwear overlap analysis

# TO DO

# nap detection
if (params_general[["acc.metric"]] != "ENMO" |
params_sleep[["HASIB.algo"]] != "vanHees2015") {
warning("\nNap classification currently assumes acc.metric = ENMO and HASIB.algo = vanHees2015, so output may not be meaningful")
}
naps_nonwear = g.part5.classifyNaps(sibreport = sibreport,
desiredtz = params_general[["desiredtz"]],
possible_nap_window = params_sleep[["possible_nap_window"]],
possible_nap_dur = params_sleep[["possible_nap_dur"]],
nap_model = params_sleep[["nap_model"]],
HASIB.algo = params_sleep[["HASIB.algo"]])
# store in ts object, such that it is exported in as time series
ts$nap1_nonwear2 = 0
# napsindices = which(naps_nonwear$probability_nap == 1)
# if (length(napsindices) > 0) {
if (length(naps_nonwear) > 0) {
for (nni in 1:nrow(naps_nonwear)) {
nnc_window = which(time_POSIX >= naps_nonwear$start[nni] & time_POSIX <= naps_nonwear$end[nni] & ts$diur == 0)
if (length(nnc_window) > 0) {
if (naps_nonwear$probability_nap[nni] == 1) {
ts$nap1_nonwear2[nnc_window] = 1 # nap
} else if (naps_nonwear$probability_nap[nni] == 0) {
ts$nap1_nonwear2[nnc_window] = 2 # nonwear
if (length(params_sleep[["nap_model"]]) > 0) {
# nap detection
if (params_general[["acc.metric"]] != "ENMO" |
params_sleep[["HASIB.algo"]] != "vanHees2015") {
warning("\nNap classification currently assumes acc.metric = ENMO and HASIB.algo = vanHees2015, so output may not be meaningful")
}
naps_nonwear = g.part5.classifyNaps(sibreport = sibreport,
desiredtz = params_general[["desiredtz"]],
possible_nap_window = params_sleep[["possible_nap_window"]],
possible_nap_dur = params_sleep[["possible_nap_dur"]],
nap_model = params_sleep[["nap_model"]],
HASIB.algo = params_sleep[["HASIB.algo"]])
# store in ts object, such that it is exported in as time series
ts$nap1_nonwear2 = 0
# napsindices = which(naps_nonwear$probability_nap == 1)
# if (length(napsindices) > 0) {
if (length(naps_nonwear) > 0) {
for (nni in 1:nrow(naps_nonwear)) {
nnc_window = which(time_POSIX >= naps_nonwear$start[nni] & time_POSIX <= naps_nonwear$end[nni] & ts$diur == 0)
if (length(nnc_window) > 0) {
if (naps_nonwear$probability_nap[nni] == 1) {
ts$nap1_nonwear2[nnc_window] = 1 # nap
} else if (naps_nonwear$probability_nap[nni] == 0) {
ts$nap1_nonwear2[nnc_window] = 2 # nonwear
}
}
}
}
}
# impute non-naps episodes (non-wear)
nonwearindices = which(naps_nonwear$probability_nap == 0)
if (length(nonwearindices) > 0) {
for (nni in nonwearindices) {
nwwindow_start = which(time_POSIX >= naps_nonwear$start[nni] & time_POSIX <= naps_nonwear$end[nni] & ts$diur == 0)
if (length(nwwindow_start) > 0) {
Nepochsin24Hours = (60/ws3new) * 60 * 24
if (nwwindow_start[1] > Nepochsin24Hours) {
nwwindow = nwwindow_start - Nepochsin24Hours # impute time series with preceding day
if (length(which(ts$nap1_nonwear2[nwwindow] == 2)) / length(nwwindow) > 0.5) {
# if there is also a lot of overlap with non-wear there then do next day
nwwindow = nwwindow_start + Nepochsin24Hours
# impute non-naps episodes (non-wear)
nonwearindices = which(naps_nonwear$probability_nap == 0)
if (length(nonwearindices) > 0) {
for (nni in nonwearindices) {
nwwindow_start = which(time_POSIX >= naps_nonwear$start[nni] & time_POSIX <= naps_nonwear$end[nni] & ts$diur == 0)
if (length(nwwindow_start) > 0) {
Nepochsin24Hours = (60/ws3new) * 60 * 24
if (nwwindow_start[1] > Nepochsin24Hours) {
nwwindow = nwwindow_start - Nepochsin24Hours # impute time series with preceding day
if (length(which(ts$nap1_nonwear2[nwwindow] == 2)) / length(nwwindow) > 0.5) {
# if there is also a lot of overlap with non-wear there then do next day
nwwindow = nwwindow_start + Nepochsin24Hours
}
} else {
nwwindow = nwwindow_start + Nepochsin24Hours # if there is not preceding day use next day
}
} else {
nwwindow = nwwindow_start + Nepochsin24Hours # if there is not preceding day use next day
}
if (max(nwwindow) <= nrow(ts)) { # only attempt imputation if possible
# check again that there is not a lot of overlap with non-wear
if (length(which(ts$nap1_nonwear2[nwwindow] == 2)) / length(nwwindow) > 0.5) {
ts$ACC[nwwindow_start] = ts$ACC[nwwindow] # impute
if (max(nwwindow) <= nrow(ts)) { # only attempt imputation if possible
# check again that there is not a lot of overlap with non-wear
if (length(which(ts$nap1_nonwear2[nwwindow] == 2)) / length(nwwindow) > 0.5) {
ts$ACC[nwwindow_start] = ts$ACC[nwwindow] # impute
}
}
}
}
}
}
} else {
sibreport = NULL
}
ts$window = 0
# backup of nightsi outside threshold defintions to avoid
@@ -394,7 +395,7 @@ g.part5 = function(datadir = c(), metadatadir = c(), f0=c(), f1=c(),
for (TRVi in params_phyact[["threshold.vig"]]) {
# derive behavioral levels (class), e.g. MVPA, inactivity bouts, etc.
levelList = identify_levels(ts = ts, TRLi = TRLi, TRMi = TRMi, TRVi = TRVi,
ws3 = ws3new, params_phyact = params_phyact)
ws3 = ws3new, params_phyact = params_phyact)
LEVELS = levelList$LEVELS
OLEVELS = levelList$OLEVELS
Lnames = levelList$Lnames
@@ -503,7 +504,8 @@ g.part5 = function(datadir = c(), metadatadir = c(), f0=c(), f1=c(),
fullFilename = fullfilenames[i],
add_one_day_to_next_date,
lightpeak_available, tail_expansion_log,
foldernamei = foldername[i])
foldernamei = foldername[i],
sibreport = sibreport)
# Extract essential object to be used as input for the next
# segment
indexlog = gas$indexlog
@@ -523,6 +525,17 @@ g.part5 = function(datadir = c(), metadatadir = c(), f0=c(), f1=c(),
ws3new = timeList$epochSize
if (doNext == TRUE) next
}
#===============================================
# FOLDER STRUCTURE
if (params_output[["storefolderstructure"]] == TRUE) {
if ("filename_dir" %in% ds_names) fi = which( ds_names == "filename_dir")
dsummary[di,fi] = fullfilenames[i] #full filename structure
ds_names[fi] = "filename_dir"; fi = fi + 1
dsummary[di,fi] = foldername[i] #store the lowest foldername
if ("foldername" %in% ds_names) fi = which( ds_names == "foldername")
ds_names[fi] = "foldername"; fi = fi + 1
}
di = di + 1
}
}
di = di + 1
Loading