Skip to content

Commit

Permalink
Merge pull request #1031 from wadpac/combined_PR_for_issues_1026_1029…
Browse files Browse the repository at this point in the history
…_1030

Fixes three smaller issues 1026 1029 1030
  • Loading branch information
vincentvanhees authored Feb 2, 2024
2 parents cf962fe + 2c12251 commit 48e8cf9
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 31 deletions.
8 changes: 8 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# CHANGES IN GGIR VERSION 3.0-5

- Part 5: Fix bug in functionality for Sensewear data (externally derived epoch data) #1030

- Part 1: For externally derived epoch data in dataFormat actiwatch_csv, actiwatch_awd, actigraph_csv, and sensewear_xls the non-wear detection is no longer done based on a hard-coded 60 minute rolling window but the window length is now modifiable with the third value of argument windowsizes (in seconds) as also used for raw data. #1026

- Part 5: Fix issue with defining days specific to when timewindow is MM, recordings starts at midnight and both first and last days are incomplete #1029

# CHANGES IN GGIR VERSION 3.0-4

- Part 5: Improved handling of inconsistent number of columns in part 5 milestone data #1002
Expand Down
7 changes: 5 additions & 2 deletions R/HASPT.R
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ HASPT = function(angle, perc = 10, spt_threshold = 15,
ma <- function(x, n = 300 / ws3){stats::filter(x, rep(1 / n, n), sides = 2, circular = TRUE)}
x = ma(x)
activityThreshold = sd(x, na.rm = TRUE) * 0.2
# For sensewear external data this will not work as it mostly has values of 1 and up.
if (activityThreshold < min(activity)) {
activityThreshold = quantile(x, probs = 0.1)
}
if (HASPT.ignore.invalid == TRUE) {
invalid = adjustlength(x, invalid)
zeroMovement = which(x <= activityThreshold & invalid == 0)
Expand Down Expand Up @@ -121,6 +125,5 @@ HASPT = function(angle, perc = 10, spt_threshold = 15,
}
tib.threshold = pp
}
invisible(list(SPTE_start=SPTE_start,
SPTE_end=SPTE_end, tib.threshold=tib.threshold))
invisible(list(SPTE_start = SPTE_start, SPTE_end = SPTE_end, tib.threshold = tib.threshold))
}
3 changes: 2 additions & 1 deletion R/convertEpochData.R
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ convertEpochData = function(datadir = c(), metadatadir = c(),
tz = params_general[["desiredtz"]]
epSizeShort = params_general[["windowsizes"]][1]
epSizeLong = params_general[["windowsizes"]][2]
epSizeNonWear = params_general[["windowsizes"]][3]
myfun = NULL
# Identify input data file extensions
if (dir.exists(datadir) == FALSE) {
Expand Down Expand Up @@ -557,7 +558,7 @@ convertEpochData = function(datadir = c(), metadatadir = c(),
params_general[["dataFormat"]] == "actigraph_csv" |
params_general[["dataFormat"]] == "sensewear_xls") {
# Using rolling 60 minute sum to indicate whether it is nonwear
imp2 = zoo::rollapply(imp, width = (1*3600) / epSizeShort, FUN = sum, fill = 0)
imp2 = zoo::rollapply(imp, width = ceiling(epSizeNonWear / epSizeShort), FUN = sum, fill = 0)
imp4 = imp2
imp4[which(imp2 > 0)] = 0
imp4[which(imp2 == 0)] = 3 # If rolling average is zero then consider it nonwear
Expand Down
6 changes: 2 additions & 4 deletions R/g.part4.R
Original file line number Diff line number Diff line change
Expand Up @@ -292,14 +292,12 @@ g.part4 = function(datadir = c(), metadatadir = c(), f0 = f0, f1 = f1,
} else if ((length(params_sleep[["def.noc.sleep"]]) == 1 ||
length(params_sleep[["loglocation"]]) != 0) &&
length(SPTE_start) != 0) {

# use SPTE algorithm (inside the g.sib.det function) as backup for sleeplog OR if user
# explicitely asks for it
defaultSptOnset = SPTE_start[j]
defaultSptWake = SPTE_end[j]
guider = "HDCZA"
if (params_sleep[["sleepwindowType"]] == "TimeInBed" & params_general[["sensor.location"]] == "hip") {
guider = "HorAngle"
}
guider = params_sleep[["HASPT.algo"]] # HDCZA, NotWorn, HorAngle
if (is.na(defaultSptOnset) == TRUE) {
# If SPTE was not derived for this night, use average estimate for other nights
availableestimate = which(is.na(SPTE_start) == FALSE)
Expand Down
39 changes: 19 additions & 20 deletions R/g.part5.definedays.R
Original file line number Diff line number Diff line change
Expand Up @@ -46,28 +46,26 @@ g.part5.definedays = function(nightsi, wi, indjump, nightsi_bu,
qqq_backup = qqq
} else if (wi > length(nightsi)) {
qqq[1] = qqq_backup[2] + 1
if (wi <= length(nightsi)) {
qqq[2] = nightsi[wi] - 1
} else {
if (wi - indjump <= length(nightsi)) {
tmp1 = which(nightsi_bu == nightsi[wi - indjump])
qqq[2] = nightsi_bu[tmp1 + indjump] - 1
indjump = indjump + 1 # in case there are multiple days beyond nightsi
if (is.na(qqq[2])) { # if that does not work use last midnight and add 24 hours
index_lastmidn = which(nightsi_bu == nightsi[wi - (indjump - 1)]) + (indjump - 1)
if (length(index_lastmidn) > 0) {
qqq[2] = nightsi_bu[index_lastmidn] + (24*(60/epochSize) * 60) - 1
} else {
qqq[2] = NA
}
}
} else {
qqq[2] = NA
}
if (wi - indjump <= length(nightsi)) {
tmp1 = which(nightsi_bu == nightsi[wi - indjump])
qqq[2] = nightsi_bu[tmp1 + indjump] - 1
indjump = indjump + 1 # in case there are multiple days beyond nightsi
if (is.na(qqq[2])) { # if that does not work use last midnight and add 24 hours
qqq[2] = qqq_backup[2] + (24*(60/epochSize) * 60) - 1
index_lastmidn = which(nightsi_bu == nightsi[wi - (indjump - 1)]) + (indjump - 1)
if (length(index_lastmidn) > 0) {
qqq[2] = nightsi_bu[index_lastmidn] + (24*(60/epochSize) * 60) - 1
} else {
qqq[2] = NA
}
}
if (qqq[1] == qqq[2]) qqq[2] = qqq[2] + (24*(60/epochSize) * 60) - 1
} else {
qqq[2] = NA
}
if (is.na(qqq[2])) { # if that does not work use last midnight and add 24 hours
qqq[2] = qqq_backup[2] + (24*(60/epochSize) * 60) - 1
}
if (qqq[1] == qqq[2]) {
qqq[2] = qqq[2] + (24*(60/epochSize) * 60) - 1
}
if (is.na(qqq[2]) == TRUE | Nts < qqq[2]) {
qqq[2] = Nts
Expand All @@ -88,6 +86,7 @@ g.part5.definedays = function(nightsi, wi, indjump, nightsi_bu,
}
# in MM, also define segments of the day based on qwindow
if (!is.na(qqq[1]) & !is.na(qqq[2])) {
if (qqq[2] > Nts) qqq[2] = Nts
fullQqq = qqq[1]:qqq[2]
firstepoch = format(ts$time[qqq[1]], "%H:%M:%S")
lastepoch = format(ts$time[qqq[2]], "%H:%M:%S")
Expand Down
4 changes: 3 additions & 1 deletion R/g.part5_initialise_ts.R
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ g.part5_initialise_ts = function(IMP, M, params_247, params_general, longitudina
angleName = "angley"
} else if (longitudinal_axis == 3 && "anglex" %in% names(IMP$metashort)) {
angleName = "anglez"
} else {
angleName = NULL
}
if (angleName %in% names(IMP$metashort)) {
if (!is.null(angleName) && angleName %in% names(IMP$metashort)) {
ts = data.frame(time = IMP$metashort[,1], ACC = IMP$metashort[,params_general[["acc.metric"]]] * scale,
guider = rep("unknown", nrow(IMP$metashort)),
angle = as.numeric(as.matrix(IMP$metashort[,which(names(IMP$metashort) == angleName)])))
Expand Down
10 changes: 7 additions & 3 deletions man/GGIR.Rd
Original file line number Diff line number Diff line change
Expand Up @@ -245,17 +245,21 @@ GGIR(mode = 1:5,
\item{dataFormat}{
Character (default = "raw").
To indicate what the format is of the data in datadir.
Current alternatives: ukbiobank_csv, actiwatch_csv, actiwatch_awd,
Alternatives: ukbiobank_csv, actiwatch_csv, actiwatch_awd,
actigraph_csv, and sensewear_xls, which correspond to epoch level data
files from, respecitively, UK Biobank in csv format, Actiwatch in csv
files from, respecitively, UK Biobank in csv format, Actiwatch in csv
format, Actiwatch in awd format, ActiGraph csv format, and Sensewear in
xls format (also works with xlsx). Here, the assumed epoch size for
UK Biobank csvdata is 5 seconds.
The epoch size for the other non-raw data formats is
flexible, but make sure that you set first value of argument
\code{windowsizes} accordingly. Also when working with
non-raw data formats specify argument \code{extEpochData_timeformat} as
documented below.}
documented below. For ukbiobank_csv nonwear is a column in the data itself,
for actiwatch_csv, actiwatch_awd, actigraph_csv, and sensewear_xls non-wear
is detected as 60 minute rolling zeros. The length of this window can be
modified with the third value of argument \code{windowsizes} expressed in
seconds.}

\item{maxRecordingInterval}{
Numeric (default = NULL).
Expand Down

0 comments on commit 48e8cf9

Please sign in to comment.