Skip to content

Commit 8cfca7d

Browse files
Merge pull request #1279 from wadpac/issue1278_split_recordings
Add option to split recordings into multiple recordings
2 parents a175e51 + c542b39 commit 8cfca7d

28 files changed

+560
-76
lines changed

NAMESPACE

+2-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ export(g.analyse, g.calibrate,
4242
g.part5_analyseSegment, g.part5_initialise_ts,
4343
g.part5.analyseRest, part6AlignIndividuals,
4444
part6PairwiseAggregation, g.part6, g.report.part6,
45-
check_log, g.report.part5_dictionary, DFA, ABI, SSP, visualReport)
45+
check_log, g.report.part5_dictionary, DFA, ABI, SSP, visualReport,
46+
splitRecords, getSplitNames, addSplitNames)
4647

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

NEWS.md

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
- Part 5 and visualreport: When wake up time at start of recording is added in part 5 no log was kept of the guider and bedend column was not recognised, this is now fixed. #1273
88

9+
- General: Add functionality to split recordings based on recording specific timestamps or dates, for example useful when studying effect of interventions. This new functionality comes with new parameters recording_split_times, recording_split_overlap, recording_split_timeformat #1278.
10+
911
# CHANGES IN GGIR VERSION 3.2-0
1012

1113
- Part 2:

R/GGIR.R

+6
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,12 @@ GGIR = function(mode = 1:5, datadir = c(), outputdir = c(),
269269
params_general = params_general,
270270
verbose = verbose)
271271
}
272+
if (!is.null(params_general[["recording_split_times"]])) {
273+
# Split recordings based on user specified time points
274+
splitRecords(metadatadir = metadatadir,
275+
params_general = params_general)
276+
}
277+
272278
if (!is.null(params_general[["maxRecordingInterval"]])) {
273279
# Append recordings when ID and brand match and gap between
274280
# recordings does not exceed maxRecordingInterval,

R/addSplitNames.R

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
addSplitNames = function(x) {
2+
if (nrow(x) != 0) {
3+
x$filename = as.character(x$filename)
4+
for (spi in 1:nrow(x)) {
5+
splitnames = getSplitNames(as.character(x$filename[spi]))
6+
segment_names = splitnames$segment_names
7+
filename = splitnames$filename
8+
if (!is.null(segment_names)) {
9+
x$filename[spi] = filename
10+
if ("split1_name" %in% colnames(x) == FALSE) {
11+
x$split1_name = NA
12+
x$split2_name = NA
13+
col_index_filename = which(colnames(x) == "filename")
14+
15+
x = x[,c(1:col_index_filename,
16+
which(colnames(x) %in% c("split1_name", "split2_name")),
17+
(col_index_filename + 1):(ncol(x) - 2))]
18+
}
19+
x$split1_name[spi] = segment_names[2]
20+
x$split2_name[spi] = segment_names[3]
21+
}
22+
}
23+
x$filename = as.factor(x$filename)
24+
}
25+
return(x)
26+
}

R/appendRecords.R

+1-15
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,6 @@
11
appendRecords = function(metadatadir, desiredtz = "", idloc = 1, maxRecordingInterval = NULL) {
22

33
# Declare local functions:
4-
getInfo = function(fn, idloc, tz) {
5-
load(fn)
6-
if (is.null(M$metashort)) return()
7-
hvars = g.extractheadervars(I)
8-
if (exists("Clist")) {
9-
ID = NA # If Clist exists then ignore this file as it was previously appended
10-
} else {
11-
ID = extractID(hvars, idloc, fname = I$filename)
12-
}
13-
start = as.POSIXct(x = M$metashort$timestamp[1], format = "%Y-%m-%dT%H:%M:%S%z", tz = tz)
14-
end = as.POSIXct(x = M$metashort$timestamp[nrow(M$metashort)], format = "%Y-%m-%dT%H:%M:%S%z", tz = tz)
15-
info = data.frame(ID = ID, start = start, end = end, filename = fn, brand = I$monn)
16-
return(info)
17-
}
184
mergePair = function(M1, M2, overlap, tz) {
195
# overlap in epochs
206
if (overlap < 0) {
@@ -77,7 +63,7 @@ appendRecords = function(metadatadir, desiredtz = "", idloc = 1, maxRecordingInt
7763
# Create overview of all recordings ID, start time, end time, and filename
7864
fns = dir(paste0(metadatadir, "/meta/basic"), full.names = TRUE)
7965

80-
S = do.call("rbind", lapply(X = fns, FUN = getInfo, idloc = idloc, tz = desiredtz))
66+
S = do.call("rbind", lapply(X = fns, FUN = getPart1BasicInfo, idloc = idloc, tz = desiredtz))
8167
if (length(S) > 0 & !is.null(maxRecordingInterval)) {
8268
S = S[!is.na(S$ID),]
8369
S = S[order(S$ID, S$start), ]

R/check_params.R

+18-6
Original file line numberDiff line numberDiff line change
@@ -131,10 +131,12 @@ check_params = function(params_sleep = c(), params_metrics = c(),
131131
}
132132
if (length(params_general) > 0) {
133133
numeric_params = c("maxNcores", "windowsizes", "idloc", "dayborder",
134-
"expand_tail_max_hours", "maxRecordingInterval")
134+
"expand_tail_max_hours", "maxRecordingInterval",
135+
"recording_split_overlap")
135136
boolean_params = c("overwrite", "print.filename", "do.parallel", "part5_agg2_60seconds")
136137
character_params = c("acc.metric", "desiredtz", "configtz", "sensor.location",
137-
"dataFormat", "extEpochData_timeformat")
138+
"dataFormat", "extEpochData_timeformat", "recording_split_times",
139+
"recording_split_timeformat")
138140
check_class("general", params = params_general, parnames = numeric_params, parclass = "numeric")
139141
check_class("general", params = params_general, parnames = boolean_params, parclass = "boolean")
140142
check_class("general", params = params_general, parnames = character_params, parclass = "character")
@@ -557,10 +559,20 @@ check_params = function(params_sleep = c(), params_metrics = c(),
557559
}
558560
}
559561

560-
if (!is.null(params_general[["maxRecordingInterval"]])) {
561-
if (params_general[["maxRecordingInterval"]] > 24 * 21) {
562-
stop(paste0("A maxRecordingInterval value higher than 21 days (504 hours) is permitted,",
563-
" please specify a lower value."), call. = FALSE)
562+
if (length(params_general) > 0) {
563+
if (!is.null(params_general[["maxRecordingInterval"]])) {
564+
if (params_general[["maxRecordingInterval"]] > 24 * 21) {
565+
stop(paste0("A maxRecordingInterval value higher than 21 days (504 hours) is not permitted,",
566+
" please specify a lower value."), call. = FALSE)
567+
}
568+
}
569+
if (!is.null(params_general[["recording_split_times"]])) {
570+
if (!file.exists(params_general[["recording_split_times"]])) {
571+
stop(paste0("File .../", basename(params_general[["recording_split_times"]]),
572+
" as specified with parameter recording_split_times does not exist, ",
573+
" please fix."), call. = FALSE)
574+
575+
}
564576
}
565577
}
566578

R/g.analyse.R

+4-3
Original file line numberDiff line numberDiff line change
@@ -220,16 +220,17 @@ g.analyse = function(I, C, M, IMP, params_247 = c(), params_phyact = c(),
220220
doiglevels = doiglevels, nfulldays = nfulldays,
221221
lastmidnight = lastmidnight,
222222
ws3 = ws3, ws2 = ws2, qcheck = qcheck, fname = fname,
223-
idloc = idloc, sensor.location = sensor.location,
223+
sensor.location = sensor.location,
224224
wdayname = wdayname,
225225
tooshort = tooshort, includedaycrit = includedaycrit,
226226
quantiletype = quantiletype, doilevels = doilevels,
227227
domvpa = domvpa,
228228
mvpanames = mvpanames, wdaycode = wdaycode, ID = ID,
229229
deviceSerialNumber = deviceSerialNumber,
230230
doquan = doquan, ExtFunColsi = ExtFunColsi,
231-
myfun = myfun, desiredtz = desiredtz,
232-
params_247 = params_247, params_phyact = params_phyact)
231+
myfun = myfun,
232+
params_247 = params_247, params_phyact = params_phyact,
233+
params_general = params_general)
233234
}
234235
#metashort is shortened from midgnight to midnight if requested (data_masking_strategy 2)
235236
if (data_masking_strategy == 2) {

R/g.analyse.perday.R

+24-7
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
g.analyse.perday = function(ndays, firstmidnighti, time, nfeatures,
22
midnightsi, metashort, averageday,
33
doiglevels, nfulldays,lastmidnight, ws3, ws2, qcheck,
4-
fname, idloc, sensor.location, wdayname, tooshort, includedaycrit,
4+
fname, sensor.location, wdayname, tooshort, includedaycrit,
55
doquan, quantiletype, doilevels, domvpa,
66
mvpanames, wdaycode, ID,
7-
deviceSerialNumber, ExtFunColsi, myfun, desiredtz = "",
7+
deviceSerialNumber, ExtFunColsi, myfun,
88
params_247 = c(), params_phyact = c(),
9+
params_general = c(),
910
...) {
11+
1012
#get input variables
1113
input = list(...)
1214

@@ -50,7 +52,7 @@ g.analyse.perday = function(ndays, firstmidnighti, time, nfeatures,
5052
}
5153
unique_dates_recording = unique(as.Date(iso8601chartime2POSIX(time[c(seq(1, length(time),
5254
by = (3600/ws2) * 12),
53-
length(time))], tz = desiredtz)))
55+
length(time))], tz = params_general[["desiredtz"]])))
5456
ExtFunColsi = ExtFunColsi - 1 # subtract 1 because code ignores timestamp
5557

5658
for (di in 1:ndays) { #run through days
@@ -198,8 +200,23 @@ g.analyse.perday = function(ndays, firstmidnighti, time, nfeatures,
198200
daysummary[di,fi] = ID
199201
idremember = daysummary[di,fi]
200202
ds_names[fi] = "ID"; fi = fi + 1
201-
daysummary[di,fi] = fname
203+
if (!is.null(params_general[["recording_split_times"]])) {
204+
filename = fname
205+
splitnames = getSplitNames(filename)
206+
segment_names = splitnames$segment_names
207+
filename = splitnames$filename
208+
} else {
209+
segment_names = NULL
210+
filename = fname
211+
}
212+
daysummary[di,fi] = filename
202213
ds_names[fi] = "filename"; fi = fi + 1
214+
if (!is.null(params_general[["recording_split_times"]]) && !is.null(segment_names)) {
215+
daysummary[di,fi] = segment_names[2]
216+
daysummary[di,fi + 1] = segment_names[3]
217+
ds_names[fi:(fi + 1)] = c("split1_name","split2_name")
218+
fi = fi + 2
219+
}
203220
calendardate = unlist(strsplit(as.character(vari[1,1])," "))[1]
204221
daysummary[di,fi] = calendardate
205222
daysummary[di,(fi + 1)] = sensor.location
@@ -342,17 +359,17 @@ g.analyse.perday = function(ndays, firstmidnighti, time, nfeatures,
342359
}
343360
} else {
344361
# When it is not the first day of recording
345-
if (NRV == 23) { # day has 23 hours (assuming DST)
362+
if (NRV == 23 * 60 * (60/ws3)) { # day has 23 hours (assuming DST)
346363
# Append data after 2nd hour
347364
startMissingHour = 2 * 60 * (60/ws3) + 1
348365
enMissingHour = 3 * 60 * (60/ws3)
349366
vari = rbind(vari[1:(startMissingHour - 1)], averageday[startMissingHour:enMissingHour, ],
350-
vari[startMissingHour:nrow(vari),])
367+
vari[startMissingHour:nrow(vari), , drop = FALSE])
351368
} else { # day has less than 24 hours for another reason
352369
# Append the average day to the end
353370
a56 = nrow(averageday) - abs(deltaLength) + 1
354371
a57 = nrow(averageday)
355-
vari = rbind(vari,averageday[a56:a57,])
372+
vari = rbind(vari, averageday[a56:a57, , drop = FALSE])
356373
}
357374
}
358375
} else if (deltaLength > 0) { # 25 hour days, assuming DST

R/g.analyse.perfile.R

+17-1
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,26 @@ g.analyse.perfile = function(I, C, metrics_nav,
3737
vi = vi + 2
3838
# starttime of measurement, body location, filename
3939
filesummary[vi] = file_summary$sensor.location
40-
filesummary[(vi + 1)] = file_summary$fname
40+
if (!is.null(params_general[["recording_split_times"]])) {
41+
filename = file_summary$fname
42+
splitnames = getSplitNames(filename)
43+
segment_names = splitnames$segment_names
44+
filename = splitnames$filename
45+
} else {
46+
segment_names = NULL
47+
filename = file_summary$fname
48+
}
49+
filesummary[(vi + 1)] = filename
4150
filesummary[(vi + 2)] = file_summary$startt # starttime of measurement
4251
s_names[vi:(vi + 2)] = c("bodylocation","filename","start_time")
4352
vi = vi + 3
53+
54+
if (!is.null(params_general[["recording_split_times"]]) && !is.null(segment_names)) {
55+
filesummary[vi] = segment_names[2]
56+
filesummary[vi + 1] = segment_names[3]
57+
s_names[vi:(vi + 1)] = c("split1_name","split2_name")
58+
vi = vi + 2
59+
}
4460
# weekday on which measurement started, sample frequency and device
4561
filesummary[vi] = file_summary$wdayname
4662
filesummary[(vi + 1)] = I$sf

R/g.report.part2.R

+1-1
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ g.report.part2 = function(metadatadir = c(), f0 = c(), f1 = c(), maxdur = 0,
309309
# reorder to have starttime next to calendar_date
310310
old_vars = which(colnames(daySUMMARY_clean) != "start_time")
311311
new_var = which(colnames(daySUMMARY_clean) == "start_time")
312-
daySUMMARY_clean = daySUMMARY_clean[, c(old_vars[1:3], new_var, old_vars[4:length(old_vars)])]
312+
daySUMMARY_clean = daySUMMARY_clean[, c(old_vars[1:2], new_var, old_vars[3:length(old_vars)])]
313313
# format calendar dates
314314
dd = iso8601chartime2POSIX(daySUMMARY_clean$calendar_date, tz = desiredtz)
315315
daySUMMARY_clean$calendar_date = format(dd, format = "%Y-%m-%d")

0 commit comments

Comments
 (0)