diff --git a/NEWS.md b/NEWS.md index 1a2b78442..204a4918d 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,7 @@ +# CHANGES IN GGIR VERSION 2.10-3 + +- Part 4: Added parameter sleepefficiency.metric to decide if in-bed time (denominator) should be guider_spt or acc_spt + latency #811 + # CHANGES IN GGIR VERSION 2.10-2 - Part 1: Revision to readability of code (credits: Lena Kushleyeva) diff --git a/R/check_params.R b/R/check_params.R index 503fe9753..af67978f3 100644 --- a/R/check_params.R +++ b/R/check_params.R @@ -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") + "colid", "coln1", "def.noc.sleep", "nnights", "sleepefficiency.metric") boolean_params = c("ignorenonwear", "constrain2range", "HASPT.ignore.invalid", "relyonguider", "sleeplogidnum") character_params = c("HASPT.algo", "HASIB.algo", "Sadeh_axis", "nap_model", diff --git a/R/g.part4.R b/R/g.part4.R index 7ca5ac310..957380a39 100644 --- a/R/g.part4.R +++ b/R/g.part4.R @@ -888,14 +888,18 @@ g.part4 = function(datadir = c(), metadatadir = c(), f0 = f0, f1 = f1, nightsummary[sumi, 22] = acc_wakeTS #---------------------------------------------- nightsummary[sumi, 23] = tmp1 #guider_onset_ts - nightsummary[sumi, 24] = tmp4 #guider_onset_ts + nightsummary[sumi, 24] = tmp4 #guider_wake_ts if (params_sleep[["sleepwindowType"]] == "TimeInBed") { - # If guider isa sleeplog and if the sleeplog recorded time in bed then + # If guider is a sleeplog and if the sleeplog recorded time in bed then # calculate: sleep latency: nightsummary[sumi, 25] = round(nightsummary[sumi, 3] - nightsummary[sumi, 7], digits = 7) #sleeponset - guider_onset # sleep efficiency: - nightsummary[sumi, 26] = round(nightsummary[sumi, 14]/nightsummary[sumi, 9], digits = 5) #accumulated nocturnal sleep / guider + if (params_sleep[["sleepefficiency.metric"]] == 1) { + nightsummary[sumi, 26] = round(nightsummary[sumi, 14]/nightsummary[sumi, 9], digits = 5) #accumulated nocturnal sleep / guider + } else if (params_sleep[["sleepefficiency.metric"]] == 2) { + nightsummary[sumi, 26] = round(nightsummary[sumi, 14]/(nightsummary[sumi, 5] + nightsummary[sumi, 25]), digits = 5) #accumulated nocturnal sleep / detected spt + latency + } } nightsummary[sumi, 27] = pagei nightsummary[sumi, 28] = daysleeper[j] diff --git a/R/load_params.R b/R/load_params.R index 1c2697a27..5dfa437c1 100644 --- a/R/load_params.R +++ b/R/load_params.R @@ -26,7 +26,7 @@ load_params = function(group = c("sleep", "metrics", "rawdata", sleeplogsep = NULL, sleepwindowType = "SPT", possible_nap_window = c(9, 18), possible_nap_dur = c(15, 240), - nap_model = c()) + nap_model = c(), sleepefficiency.metric = 1) } if ("metrics" %in% group) { params_metrics = list(do.anglex = FALSE, do.angley = FALSE, do.anglez = TRUE, diff --git a/man/GGIR.Rd b/man/GGIR.Rd index b2e8c35d7..8ee4a5f05 100755 --- a/man/GGIR.Rd +++ b/man/GGIR.Rd @@ -1096,6 +1096,16 @@ GGIR(mode = 1:5, e.g., \code{possible_nap_dur = c(15, 240)}. Currently used in the context of an explorative nap classification algortihm that was trained in 3.5 year olds.} + + \item{sleepefficiency.metric}{ + Numeric (default = 1). + If 1 (default), sleep efficiency is calculated as detected nocturnal sleep time divided by + log-derived duration in sleep period time (considering user-reported sleep onset and + wake times). If 2, sleep efficiency is calculated as detected nocturnal + sleep time divided by detected duration in sleep period time plus sleep latency (where + sleep latency refers to the difference between log-derived sleep onset and + accelerometer-detected sleep onset). + } } } diff --git a/tests/testthat/test_chainof5parts.R b/tests/testthat/test_chainof5parts.R index 8bf831942..c42c01faa 100644 --- a/tests/testthat/test_chainof5parts.R +++ b/tests/testthat/test_chainof5parts.R @@ -139,7 +139,7 @@ test_that("chainof5parts", { expect_that(round(nightsummary$number_sib_wakinghours[1], digits = 4), equals(6)) expect_true(as.logical(nightsummary$acc_available[1])) expect_true(as.logical(nightsummary$sleeplog_used[1])) - + #-------------------------------------------- #part 5 g.part5(datadir = fn, metadatadir = metadatadir, f0 = 1, f1 = 1, desiredtz = desiredtz, @@ -191,6 +191,38 @@ test_that("chainof5parts", { #======================= # Different variations on part 4: + #-------------------------------------------- + #-------------------------------------------- + # part 4 with sleepwindowType = TimeInBed and sleepefficiency.metric = 2 + g.part4(datadir = fn, metadatadir = metadatadir, f0 = 1, f1 = 1, + idloc = 2, loglocation = sleeplog_fn, do.visual = TRUE, outliers.only = FALSE, + excludefirstlast = FALSE, criterror = 1, includenightcrit = 0, #nnights = 7, + colid = 1, coln1 = 2, relyonguider = FALSE, desiredtz = desiredtz, + storefolderstructure = FALSE, overwrite = TRUE, + sleepwindowType = "TimeInBed", sleepefficiency.metric = 2) + dirname = "output_test/meta/ms4.out/" + rn = dir(dirname,full.names = TRUE) + load(rn[1]) + expect_true("sleeplatency" %in% colnames(nightsummary)) + expect_true("sleepefficiency" %in% colnames(nightsummary)) + expect_equal(round(nightsummary$sleeplatency[1], 3), 0.171) + expect_equal(round(nightsummary$sleepefficiency[1], 3), 0.951) + + #-------------------------------------------- + # part 4 with sleepwindowType = TimeInBed and sleepefficiency.metric = 1 + g.part4(datadir = fn, metadatadir = metadatadir, f0 = 1, f1 = 1, + idloc = 2, loglocation = sleeplog_fn, do.visual = TRUE, outliers.only = FALSE, + excludefirstlast = FALSE, criterror = 1, includenightcrit = 0, #nnights = 7, + colid = 1, coln1 = 2, relyonguider = FALSE, desiredtz = desiredtz, + storefolderstructure = FALSE, overwrite = TRUE, + sleepwindowType = "TimeInBed", sleepefficiency.metric = 1) + dirname = "output_test/meta/ms4.out/" + rn = dir(dirname,full.names = TRUE) + load(rn[1]) + expect_true("sleeplatency" %in% colnames(nightsummary)) + expect_true("sleepefficiency" %in% colnames(nightsummary)) + expect_equal(round(nightsummary$sleepefficiency[1], 3), 0.851) + #-------------------------------------------- # part 4 without sleeplog g.part4(datadir = fn, metadatadir = metadatadir, f0 = 1, f1 = 1, @@ -198,7 +230,8 @@ test_that("chainof5parts", { excludefirstlast = FALSE, criterror = 1, includenightcrit = 0, nnights = 7, colid = 1, coln1 = 2, relyonguider = FALSE, desiredtz = desiredtz, - storefolderstructure = TRUE, overwrite = TRUE, verbose = FALSE) + storefolderstructure = TRUE, overwrite = TRUE, verbose = FALSE, + sleepwindowType = "SPT") dirname = "output_test/meta/ms4.out/" rn = dir(dirname,full.names = TRUE) diff --git a/tests/testthat/test_load_check_params.R b/tests/testthat/test_load_check_params.R index 28c87c9c6..4ee135ad1 100644 --- a/tests/testthat/test_load_check_params.R +++ b/tests/testthat/test_load_check_params.R @@ -10,7 +10,7 @@ test_that("load_params can load parameters", { # Test length of objects expect_equal(length(params), 8) - expect_equal(length(params$params_sleep), 20) + expect_equal(length(params$params_sleep), 21) expect_equal(length(params$params_metrics), 41) expect_equal(length(params$params_rawdata), 37) expect_equal(length(params$params_247), 20) diff --git a/vignettes/GGIR.Rmd b/vignettes/GGIR.Rmd index 7253c1375..15a213d22 100644 --- a/vignettes/GGIR.Rmd +++ b/vignettes/GGIR.Rmd @@ -830,7 +830,7 @@ data. If either of these applies set argument `sleepwindowType` to | guider_guider_inbedStart | Time of getting in bed | | guider_guider_inbedEnd | Time of getting out of bed| | guider_inbedDuration | Time in Bed: guider_inbedEnd - guider_inbedStart | -| sleepefficiency | Sleep efficiency, calculated as: SleepDurationInSpt / guider_inbedDuration | +| sleepefficiency | Sleep efficiency, calculated as: SleepDurationInSpt / guider_inbedDuration or SleepDurationInSpt / (Spt + latency) as defined with `relyonguider_SleepEfficiency`| | sleeplatency | Sleep latency, calculated as: sleeponset - guider_inbedStart | ### Person level summaries @@ -852,7 +852,7 @@ may not be obvious: | `_WE`| Weekend days | | `_WD`| Week days | | sleeplog_used | Whether a sleeplog was available (TRUE) or not (FALSE)| -| sleep_efficiency | Accelerometer detrive sleep efficiency within the sleep period time calculated as the ratio between acc_SleepDurationInSpt and acc_SptDuration (denominator). Only available at person level, because at night level the user can calculate this from existing variables. | +| sleep_efficiency | Accelerometer derived sleep efficiency within the sleep period time calculated as the ratio between acc_SleepDurationInSpt and guider_SptDuration (denominator) or acc_SleepDurationInSpt and acc_SptDuration + latency (denominator), as defined with relyonguider_SleepEfficiency. Only available at person level, because at night level the user can calculate this from existing variables. | | n_nights_acc | Number of nights of accelerometer data | | n_nights_sleeplog | Number of nights of sleeplog data. | | n\_WE_nights_complete | Number of weekend nights complete which means both accelerometer and estimate from guider. | diff --git a/vignettes/GGIRParameters.Rmd b/vignettes/GGIRParameters.Rmd index d6b28604e..4ed1f2992 100644 --- a/vignettes/GGIRParameters.Rmd +++ b/vignettes/GGIRParameters.Rmd @@ -184,6 +184,7 @@ find a description and default value for all the arguments. | includenightcrit | 4 | params_cleaning | | relyonguider | 4 | params_sleep | | relyonsleeplog | 4 | not in parameter objects | +| relyonguider_SleepEfficiency| 4 | params_sleep | | def.noc.sleep | 4 | params_sleep | | data_cleaning_file | 4, 5 | params_cleaning | | excludefirst.part4 | 4 | params_cleaning |