Skip to content

Commit

Permalink
Merge 0069997 into 0e67881
Browse files Browse the repository at this point in the history
  • Loading branch information
jhmigueles authored Oct 11, 2023
2 parents 0e67881 + 0069997 commit 050d549
Show file tree
Hide file tree
Showing 7 changed files with 45 additions and 12 deletions.
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ relative to start and end of the most active time window as identified. #905

- Fix recently introduced bug where GGIR environment was not exported to cluster in GGIR part 1, 2, 3, and 5 #910

- Part 5: Implemented sleep onset to sleep onset timewindow ("OO") #931

# CHANGES IN GGIR VERSION 2.10-3

- Part 1: Fixed minor bug in ismovisens that failed when datadir started with "./" #897
Expand Down
11 changes: 9 additions & 2 deletions R/g.part5.R
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,7 @@ g.part5 = function(datadir = c(), metadatadir = c(), f0=c(), f1=c(),
#-------------------------------
# ignore all nights in 'inights' before the first waking up and after the last waking up
FM = which(diff(ts$diur) == -1)
SO = which(diff(ts$diur) == 1)
# now 0.5+6+0.5 midnights and 7 days
for (timewindowi in params_output[["timewindow"]]) {
nightsi = nightsi_bu
Expand All @@ -419,6 +420,11 @@ g.part5 = function(datadir = c(), metadatadir = c(), f0=c(), f1=c(),
# ignore first and last midnight because we did not do sleep detection on it
nightsi = nightsi[nightsi > FM[1] & nightsi < FM[length(FM)]]
}
} else if (timewindowi == "OO") {
if (length(SO) > 0) {
# ignore data before the first sleep onset and after the last sleep onset
nightsi = nightsi[nightsi > SO[1] & nightsi < SO[length(SO)]]
}
} else {
# if first night is missing then nights needs to align with diur
startend_sleep = which(abs(diff(ts$diur)) == 1)
Expand All @@ -428,8 +434,10 @@ g.part5 = function(datadir = c(), metadatadir = c(), f0=c(), f1=c(),
}
if (timewindowi == "MM") {
Nwindows = length(nightsi) + 1
} else {
} else if (timewindowi == "WW") {
Nwindows = length(which(diff(ts$diur) == -1))
} else if (timewindowi == "OO") {
Nwindows = length(which(diff(ts$diur) == 1))
}
indjump = 1
qqq_backup = c()
Expand All @@ -442,7 +450,6 @@ g.part5 = function(datadir = c(), metadatadir = c(), f0=c(), f1=c(),
}
for (wi in 1:Nwindows) { #loop through 7 windows (+1 to include the data after last awakening)
# Define indices of start and end of the day window (e.g. midnight-midnight, or waking-up or wakingup

defdays = g.part5.definedays(nightsi, wi, indjump,
nightsi_bu, epochSize = ws3new, qqq_backup, ts,
timewindowi, Nwindows, qwindow = params_247[["qwindow"]],
Expand Down
19 changes: 19 additions & 0 deletions R/g.part5.definedays.R
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,25 @@ g.part5.definedays = function(nightsi, wi, indjump, nightsi_bu,
names(segments) = paste(start, end, sep = "-")
segments_names = "WW"
}
} else if (timewindowi == "OO") {
if (wi <= (Nwindows - 1)) { # all full wake to wake days
qqq[1] = which(diff(ts$diur) == 1)[wi] + 1
qqq[2] = which(diff(ts$diur) == 1)[wi + 1]
} else {
# time after last reliable waking up (this can be more than 24 hours)
# ignore this day, because if the night was ignored for sleep analysis
# then the description of the day in part 5 including that night is
# not informative.
qqq = c(NA, NA)
}
# build up segments
if (!is.na(qqq[1]) & !is.na(qqq[2])) {
segments = list(qqq)
start = substr(ts$time[qqq[1]], 12, 19)
end = substr(ts$time[qqq[2]], 12, 19)
names(segments) = paste(start, end, sep = "-")
segments_names = "OO"
}
}
return(invisible(list(qqq = qqq, qqq_backup = qqq_backup,
segments = segments, segments_names = segments_names)))
Expand Down
8 changes: 4 additions & 4 deletions R/g.report.part5.R
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ g.report.part5 = function(metadatadir = c(), f0 = c(), f1 = c(), loglocation = c
}
# Note: Below we intentionally only sets a criteria on daytime, because for
# the night time we only need start and end of the SPT window.
if (window == "WW") {
if (window == "WW" | window == "OO") {
indices = which(x$nonwear_perc_day <= maxpernwday &
x$dur_spt_min > 0 & x$dur_day_min > 0 & include_window == TRUE)
} else if (window == "MM") {
Expand Down Expand Up @@ -153,8 +153,8 @@ g.report.part5 = function(metadatadir = c(), f0 = c(), f1 = c(), loglocation = c
# split results to different spreadsheets in order to minimize individual
# filesize and to ease organising dataset
uwi = as.character(unique(outputfinal$window))
if (!all(uwi %in% c("MM", "WW"))) {
uwi = c(uwi[uwi %in% c("MM", "WW")], "Segments")
if (!all(uwi %in% c("MM", "WW", "OO"))) {
uwi = c(uwi[uwi %in% c("MM", "WW", "OO")], "Segments")
}
uTRLi = as.character(unique(outputfinal$TRLi))
uTRMi = as.character(unique(outputfinal$TRMi))
Expand Down Expand Up @@ -197,7 +197,7 @@ g.report.part5 = function(metadatadir = c(), f0 = c(), f1 = c(), loglocation = c
"-", uTRVi[h3], "-", usleepparam[h4]))
}
select_window = as.character(outputfinal$window) == uwi[j]
if (!(uwi[j] %in% c("MM", "WW"))) select_window = !(as.character(outputfinal$window) %in% c("MM", "WW"))
if (!(uwi[j] %in% c("MM", "WW", "OO"))) select_window = !(as.character(outputfinal$window) %in% c("MM", "WW", "OO"))
seluwi = which(select_window &
as.character(outputfinal$TRLi) == uTRLi[h1] &
as.character(outputfinal$TRMi) == uTRMi[h2] &
Expand Down
2 changes: 1 addition & 1 deletion man/GGIR.Rd
Original file line number Diff line number Diff line change
Expand Up @@ -1278,7 +1278,7 @@ GGIR(mode = 1:5,
Character (default = c("MM", "WW")).
In \link{g.part5}: Timewindow over which summary statistics are derived.
Value can be "MM" (midnight to midnight), "WW" (waking time to waking time),
or both c("MM","WW").}
"OO" (sleep onset to sleep onset), or any combination of them.}
\item{save_ms5rawlevels}{
Boolean (default = FALSE).
Expand Down
9 changes: 7 additions & 2 deletions tests/testthat/test_chainof5parts.R
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ test_that("chainof5parts", {
overwrite = TRUE, excludefirstlast = FALSE, do.parallel = do.parallel,
frag.metrics = "all", save_ms5rawlevels = TRUE,
part5_agg2_60seconds = TRUE, do.sibreport = TRUE, nap_model = "hip3yr",
iglevels = 1)
iglevels = 1, timewindow = c("MM", "WW", "OO"))
sibreport_dirname = "output_test/meta/ms5.outraw/sib.reports"
expect_true(dir.exists(sibreport_dirname))
expect_true(file.exists(paste0(sibreport_dirname, "/sib_report_123A_testaccfile_T5A5.csv")))
Expand All @@ -214,9 +214,11 @@ test_that("chainof5parts", {

expect_true(dir.exists(dirname))
expect_true(file.exists(rn[1]))
expect_that(nrow(output),equals(4))
expect_that(nrow(output),equals(5)) # changed because OO window is exported
expect_that(ncol(output),equals(197))
expect_that(round(as.numeric(output$wakeup[2]), digits = 4), equals(36))
expect_that(as.numeric(output$dur_day_spt_min[4]), equals(1150)) # WW window duration
expect_that(as.numeric(output$dur_day_spt_min[5]), equals(1680)) # OO window duration
dirname_raw = "output_test/meta/ms5.outraw/40_100_400"
rn2 = dir(dirname_raw,full.names = TRUE, recursive = T)
expect_true(file.exists(rn2[1]))
Expand All @@ -240,6 +242,9 @@ test_that("chainof5parts", {
expect_true(file.exists("output_test/results/part4_nightsummary_sleep_cleaned.csv"))
expect_true(file.exists("output_test/results/part4_summary_sleep_cleaned.csv"))
expect_true(file.exists("output_test/results/file summary reports/Report_123A_testaccfile.csv.pdf"))
expect_true(file.exists("output_test/results/part5_daysummary_MM_L40M100V400_T5A5.csv"))
expect_true(file.exists("output_test/results/part5_daysummary_WW_L40M100V400_T5A5.csv"))
expect_true(file.exists("output_test/results/part5_daysummary_OO_L40M100V400_T5A5.csv"))
dn = "output_test"

#=======================
Expand Down
6 changes: 3 additions & 3 deletions vignettes/GGIR.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -482,8 +482,8 @@ For an explanation on how time use analysis is performed see section
Here, the full 25 minutes would count towards the duration of
the MVPA bout.
- `timewindow` to specify whether days should be defined from midnight
to midnight `"MM"`, from waking-up to waking-up `"WW"`, or both
`c("MM","WW")`.
to midnight `"MM"`, from waking-up to waking-up `"WW"`, from sleep onset
to sleep onset `"OO"`, or any combination of them.
- Configure durations of bouts: `boutdur.mvpa`, `boutdur.in`, and
`boutdur.lig`. Note that this can be a vector of multiple values
indicating the minimum and maximum duration of subsequent bout
Expand Down Expand Up @@ -1618,7 +1618,7 @@ correspond to the date of analysis.
| SleepPeriodTime | Is 1 if SPT is detected, 0 if not. Note that this refers to the combined usage of guider and detected sustained inactivity bouts (rest periods).|
| invalidepoch | Is 1 if epoch was detect as invalid (e.g. non-wear), 0 if not. |
| guider | Is 1 if guider method detect epoch as SPT (e.g. sleeplog, HDCZA), 0 if not. You will not find here which guider is used, for this see other GGIR output. |
| window | Numeric indicator of the analysis window in the recording. If timewindow = "MM" then these correspond to calendar days, if timewindow = "WW" then these correspond to which wakingup-wakingup window in the recording. So, in a recording of one week you may find window numbers 1, 2, 3, 4, 5 and 6.|
| window | Numeric indicator of the analysis window in the recording. If timewindow = "MM" then these correspond to calendar days, if timewindow = "WW" then these correspond to which wakingup-wakingup window in the recording, if timewindow = "OO" then these correspond to which sleeponset-sleeponset window in the recording. So, in a recording of one week you may find window numbers 1, 2, 3, 4, 5 and 6.|
| class_id | The behavioural class codes are documented in the exported csv file meta/ms5outraw/behaviouralcodes.csv. Class codes above class 8 will be analysis specific, because it depends on the number time variants of the bouts used. For example, if you look at MVPA lasting 1-10, 10-20, 30-40 then all of them will have their own class_id. |
| invalid_fullwindow | Fraction of the window (see above) that represents invalid data. I added this to make it easier to filter the timeseries based on whether days are valid or not. |
| invalid_sleepperiod | Fraction of SPT within the current window that represents invalid data. |
Expand Down

0 comments on commit 050d549

Please sign in to comment.