From 7fb1cd3587d845d81cf160fba69610b4731b7a75 Mon Sep 17 00:00:00 2001 From: Vincent van Hees Date: Thu, 21 Dec 2023 17:19:13 +0100 Subject: [PATCH 1/8] Fixes #1006 and corrects ordering and time windows as displayed in output --- R/g.part5.definedays.R | 5 +++-- R/g.report.part5.R | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/R/g.part5.definedays.R b/R/g.part5.definedays.R index b1fcce462..759917c2c 100644 --- a/R/g.part5.definedays.R +++ b/R/g.part5.definedays.R @@ -34,7 +34,7 @@ g.part5.definedays = function(nightsi, wi, indjump, nightsi_bu, if (nightsi[1] == 1) { wi = wi + 1 # add extra nightsi to get the last day processed (as wi has been increased by 1) - nightsi = c(nightsi, nightsi + (24*(60/epochSize) * 60) - 1) + nightsi = c(nightsi, nightsi[length(nightsi)] + (24*(60/epochSize) * 60) - 1) } if (length(nightsi) >= wi) { if (wi == 1) { @@ -89,6 +89,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])) { fullQqq = qqq[1]:qqq[2] + firstepoch = format(ts$time[qqq[1]], "%H:%M:%S") lastepoch = format(ts$time[qqq[2]], "%H:%M:%S") qnames = NULL if (is.data.frame(qwindow)) { @@ -108,7 +109,7 @@ g.part5.definedays = function(nightsi, wi, indjump, nightsi_bu, } # build up segments segments = list(qqq) - segments_timing = paste("00:00:00", lastepoch, sep = "-") + segments_timing = paste(firstepoch, lastepoch, sep = "-") segments_names = "MM" si = 2 do.segments = TRUE diff --git a/R/g.report.part5.R b/R/g.report.part5.R index 810e0e6b0..ca32c7c0f 100644 --- a/R/g.report.part5.R +++ b/R/g.report.part5.R @@ -148,8 +148,8 @@ g.report.part5 = function(metadatadir = c(), f0 = c(), f1 = c(), loglocation = c outputfinal$window_number = as.numeric(gsub(" ", "", outputfinal$window_number)) # outputfinal_segments = outputfinal[which(!outputfinal$window %in% c("MM", "WW")),] # outputfinal = outputfinal[which(outputfinal$window %in% c("MM", "WW")),] - outputfinal = outputfinal[order(outputfinal$filename, outputfinal$window, outputfinal$window_number),] - + outputfinal = outputfinal[order(outputfinal$window_number, outputfinal$window, outputfinal$filename), ] + # split results to different spreadsheets in order to minimize individual # filesize and to ease organising dataset uwi = as.character(unique(outputfinal$window)) @@ -475,7 +475,7 @@ g.report.part5 = function(metadatadir = c(), f0 = c(), f1 = c(), loglocation = c } OF3tmp = OF3[, columns2keep] foo34 = function(df,aggPerIndividual,nameold,namenew,cval,window) { - # function to help with calculating additinal variables + # function to help with calculating additional variables # related to counting how many days of measurement there are # that meet a certain criteria # cval is a vector with 0 and 1, indicating whether the criteria is met From 370ad7989699784475489607e09d4bf9923c5553 Mon Sep 17 00:00:00 2001 From: Vincent van Hees Date: Thu, 21 Dec 2023 17:20:13 +0100 Subject: [PATCH 2/8] Update NEWS.md --- NEWS.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS.md b/NEWS.md index ec6d2bbc8..1833360b1 100644 --- a/NEWS.md +++ b/NEWS.md @@ -4,6 +4,8 @@ - Part 1: Fix bug where on machines with GMT timezone and R >= 4.3.0, for GENEActiv .bin files, the starting timestamps of M$metalong and M$metashort were truncated to midninght #1000 +- Part 5: Fix bug where part5 output showed duplicate rows when argument dayborder is set to nondefault value #1006 + # CHANGES IN GGIR VERSION 3.0-2 - Part 2: Fix bug that caused part 2 to struggle with corrupt ActiGraph .gt3x files #972 From 162c9e6adc41c2105163f87affd86f3a7fe1e7e2 Mon Sep 17 00:00:00 2001 From: Vincent van Hees Date: Thu, 21 Dec 2023 17:36:22 +0100 Subject: [PATCH 3/8] correct unit-test #1006 --- tests/testthat/test_recording.starts.at.midnight.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/testthat/test_recording.starts.at.midnight.R b/tests/testthat/test_recording.starts.at.midnight.R index c604d46fa..524fd22c8 100644 --- a/tests/testthat/test_recording.starts.at.midnight.R +++ b/tests/testthat/test_recording.starts.at.midnight.R @@ -37,7 +37,7 @@ test_that("Test recordings that start at midnight", { rn = "output_test/results/part5_daysummary_MM_L40M100V400_T5A5.csv" out5 = read.csv(rn) expect_equal(nrow(out5), 2) - expect_true(all(out5$dur_day_spt_min == 1440)) + expect_equal(out5$dur_day_spt_min, c(1440, 1439.917)) if (dir.exists(dn)) unlink(dn, recursive = TRUE) if (file.exists(fn)) unlink(fn) From 03f8444029d8f178241886c6e1f5b47fc16c4ec9 Mon Sep 17 00:00:00 2001 From: Vincent van Hees Date: Thu, 21 Dec 2023 17:36:48 +0100 Subject: [PATCH 4/8] make code less verbose --- R/g.analyse.R | 12 ++++++------ R/g.analyse.perday.R | 4 +--- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/R/g.analyse.R b/R/g.analyse.R index 24ba307d1..f69d3f0cc 100644 --- a/R/g.analyse.R +++ b/R/g.analyse.R @@ -67,7 +67,7 @@ g.analyse = function(I, C, M, IMP, params_247 = c(), params_phyact = c(), n_ws2_perday = (1440*60) / ws2 n_ws3_perday = (1440*60) / ws3 if (((nrow(metalong)/((1440*60)/ws2)*10) - (nrow(metashort)/((60/ws3)*1440)) * 10) > 1) { - cat("Matrices 'metalong' and 'metashort' are not compatible") + warning("Matrices 'metalong' and 'metashort' are not compatible") } #---------------------- # Extract ID centrally @@ -168,9 +168,9 @@ g.analyse = function(I, C, M, IMP, params_247 = c(), params_phyact = c(), # LW = length(which(as.numeric(qcheck) != 1)) / (60/ws3) #number of minutes wear time between first and last midnights nfulldays = (lastmidnighti - firstmidnighti) / ((3600/ws2)*24) ndays = length(midnights) + 1 #ceiling(nfulldays + 2) # ceiling to cope with days with 23 hours - if (ndays != round(ndays)) { #day saving time causing trouble? - cat("One day in this measurement is longer or shorter than 24 hours (probably related to day saving time)") - } + # if (ndays != round(ndays)) { #day saving time causing trouble? + # cat("One day in this measurement is longer or shorter than 24 hours (probably related to day saving time)") + # } #------------------------------------- # Detect orientation (at the moment only desighned for hip with accelerometer): # assess which angle per axis is most strongly 24 hour correlated: @@ -279,8 +279,8 @@ g.analyse = function(I, C, M, IMP, params_247 = c(), params_phyact = c(), average24h = average24h / average24hc AveAccAve24hr[h] = mean(average24h) #average acceleration in an average 24 hour cycle } - } else { - cat("file skipped for general average caculation because not enough data") + # } else { + # cat("file skipped for general average caculation because not enough data") } rm(metalong); rm(metashort) dataqual_summary = data.frame(clipping_score = LC2 / ((LD/1440)*96), diff --git a/R/g.analyse.perday.R b/R/g.analyse.perday.R index bf5ad50bd..a9389c636 100644 --- a/R/g.analyse.perday.R +++ b/R/g.analyse.perday.R @@ -30,12 +30,10 @@ g.analyse.perday = function(ndays, firstmidnighti, time, nfeatures, if (firstmidnighti == 1) { #if measurement starts at midnight ndays = ndays - 1 startatmidnight = 1 - cat("measurement starts at midnight or there is no midnight") } if (lastmidnight == time[length(time)] & nrow(metashort) < ((60/ws3) * 1440)) { #if measurement ends at midnight ndays = ndays - 1 endatmidnight = 1 - cat("measurement ends at midnight or there is no midnight") } } @@ -141,7 +139,7 @@ g.analyse.perday = function(ndays, firstmidnighti, time, nfeatures, if (length(params_247[["qwindow"]]) < 2) params_247[["qwindow"]] = c() if (length(params_247[["qwindow"]]) > 0) { if (length(qwindow_names) == 1) { - cat("Argument to qwindow is invalid, requires a vector of at least length 2") + warning("Argument to qwindow is invalid, requires a vector of at least length 2") } if (length(qwindow_names) == 2) { if (params_247[["qwindow"]][1] != 0 | params_247[["qwindow"]][2] != 24) { From 4ad580cf5d253a3e713744d98656bd23ae5913d4 Mon Sep 17 00:00:00 2001 From: Vincent van Hees Date: Thu, 21 Dec 2023 17:53:47 +0100 Subject: [PATCH 5/8] correct ordering part 5 segment report --- R/g.report.part5.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/g.report.part5.R b/R/g.report.part5.R index ca32c7c0f..d70738e6e 100644 --- a/R/g.report.part5.R +++ b/R/g.report.part5.R @@ -148,7 +148,7 @@ g.report.part5 = function(metadatadir = c(), f0 = c(), f1 = c(), loglocation = c outputfinal$window_number = as.numeric(gsub(" ", "", outputfinal$window_number)) # outputfinal_segments = outputfinal[which(!outputfinal$window %in% c("MM", "WW")),] # outputfinal = outputfinal[which(outputfinal$window %in% c("MM", "WW")),] - outputfinal = outputfinal[order(outputfinal$window_number, outputfinal$window, outputfinal$filename), ] + outputfinal = outputfinal[order(outputfinal$filename, outputfinal$window_number, outputfinal$window), ] # split results to different spreadsheets in order to minimize individual # filesize and to ease organising dataset From b25676fa66921e8570464b10cb4e0a017f59ff73 Mon Sep 17 00:00:00 2001 From: Vincent van Hees Date: Thu, 21 Dec 2023 18:06:06 +0100 Subject: [PATCH 6/8] undo change to unit test and fix issue in code --- R/g.part5.definedays.R | 2 +- tests/testthat/test_recording.starts.at.midnight.R | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/R/g.part5.definedays.R b/R/g.part5.definedays.R index 759917c2c..ccbe97200 100644 --- a/R/g.part5.definedays.R +++ b/R/g.part5.definedays.R @@ -34,7 +34,7 @@ g.part5.definedays = function(nightsi, wi, indjump, nightsi_bu, if (nightsi[1] == 1) { wi = wi + 1 # add extra nightsi to get the last day processed (as wi has been increased by 1) - nightsi = c(nightsi, nightsi[length(nightsi)] + (24*(60/epochSize) * 60) - 1) + nightsi = c(nightsi, nightsi[length(nightsi)] + (24*(60/epochSize) * 60)) } if (length(nightsi) >= wi) { if (wi == 1) { diff --git a/tests/testthat/test_recording.starts.at.midnight.R b/tests/testthat/test_recording.starts.at.midnight.R index 524fd22c8..c604d46fa 100644 --- a/tests/testthat/test_recording.starts.at.midnight.R +++ b/tests/testthat/test_recording.starts.at.midnight.R @@ -37,7 +37,7 @@ test_that("Test recordings that start at midnight", { rn = "output_test/results/part5_daysummary_MM_L40M100V400_T5A5.csv" out5 = read.csv(rn) expect_equal(nrow(out5), 2) - expect_equal(out5$dur_day_spt_min, c(1440, 1439.917)) + expect_true(all(out5$dur_day_spt_min == 1440)) if (dir.exists(dn)) unlink(dn, recursive = TRUE) if (file.exists(fn)) unlink(fn) From 93a09b8129aa11cf96a76225c18326797d21fadc Mon Sep 17 00:00:00 2001 From: Vincent van Hees Date: Thu, 21 Dec 2023 18:08:29 +0100 Subject: [PATCH 7/8] tidy up code --- R/g.analyse.R | 7 +------ R/g.report.part5.R | 4 ---- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/R/g.analyse.R b/R/g.analyse.R index f69d3f0cc..05cec5be6 100644 --- a/R/g.analyse.R +++ b/R/g.analyse.R @@ -67,7 +67,7 @@ g.analyse = function(I, C, M, IMP, params_247 = c(), params_phyact = c(), n_ws2_perday = (1440*60) / ws2 n_ws3_perday = (1440*60) / ws3 if (((nrow(metalong)/((1440*60)/ws2)*10) - (nrow(metashort)/((60/ws3)*1440)) * 10) > 1) { - warning("Matrices 'metalong' and 'metashort' are not compatible") + stop("Matrices 'metalong' and 'metashort' are not compatible") } #---------------------- # Extract ID centrally @@ -168,9 +168,6 @@ g.analyse = function(I, C, M, IMP, params_247 = c(), params_phyact = c(), # LW = length(which(as.numeric(qcheck) != 1)) / (60/ws3) #number of minutes wear time between first and last midnights nfulldays = (lastmidnighti - firstmidnighti) / ((3600/ws2)*24) ndays = length(midnights) + 1 #ceiling(nfulldays + 2) # ceiling to cope with days with 23 hours - # if (ndays != round(ndays)) { #day saving time causing trouble? - # cat("One day in this measurement is longer or shorter than 24 hours (probably related to day saving time)") - # } #------------------------------------- # Detect orientation (at the moment only desighned for hip with accelerometer): # assess which angle per axis is most strongly 24 hour correlated: @@ -279,8 +276,6 @@ g.analyse = function(I, C, M, IMP, params_247 = c(), params_phyact = c(), average24h = average24h / average24hc AveAccAve24hr[h] = mean(average24h) #average acceleration in an average 24 hour cycle } - # } else { - # cat("file skipped for general average caculation because not enough data") } rm(metalong); rm(metashort) dataqual_summary = data.frame(clipping_score = LC2 / ((LD/1440)*96), diff --git a/R/g.report.part5.R b/R/g.report.part5.R index d70738e6e..53f1aac18 100644 --- a/R/g.report.part5.R +++ b/R/g.report.part5.R @@ -119,8 +119,6 @@ g.report.part5 = function(metadatadir = c(), f0 = c(), f1 = c(), loglocation = c out = base::merge(tmp, out, all = TRUE) } if (length(tail_expansion_log) != 0) { - # col2na = grep(pattern = "spt|sleeplog_used", - # x = names(out), value = FALSE) col2na = grep(pattern = paste0("sleep_efficiency|N_atleast5minwakenight|daysleeper|", "daysleeper|sleeplog_used|_spt_sleep|_spt_wake"), x = names(out), value = FALSE) @@ -146,8 +144,6 @@ g.report.part5 = function(metadatadir = c(), f0 = c(), f1 = c(), loglocation = c # order data.frame outputfinal$window_number = as.numeric(gsub(" ", "", outputfinal$window_number)) - # outputfinal_segments = outputfinal[which(!outputfinal$window %in% c("MM", "WW")),] - # outputfinal = outputfinal[which(outputfinal$window %in% c("MM", "WW")),] outputfinal = outputfinal[order(outputfinal$filename, outputfinal$window_number, outputfinal$window), ] # split results to different spreadsheets in order to minimize individual From 047e101a733302ade0c9591e8a4c97db185e6420 Mon Sep 17 00:00:00 2001 From: Jairo H Migueles Date: Thu, 11 Jan 2024 11:30:07 +0100 Subject: [PATCH 8/8] prevent error when ID/date cannot be matched with activity log --- R/g.part5.definedays.R | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/R/g.part5.definedays.R b/R/g.part5.definedays.R index ccbe97200..39ca9befb 100644 --- a/R/g.part5.definedays.R +++ b/R/g.part5.definedays.R @@ -95,8 +95,12 @@ g.part5.definedays = function(nightsi, wi, indjump, nightsi_bu, if (is.data.frame(qwindow)) { date_of_interest = substr(ts$time[qqq[1]], 1, 10) qdate = which(qwindow$ID == ID & qwindow$date == date_of_interest) - qnames = unlist(qwindow$qwindow_names[qdate]) - qwindow = unlist(qwindow$qwindow_values[qdate]) + if (length(qdate) == 1) { # if ID/date matched with activity log + qnames = unlist(qwindow$qwindow_names[qdate]) + qwindow = unlist(qwindow$qwindow_values[qdate]) + } else { # if ID/date not correctly matched with activity log + qwindow = c(0, 24) + } } breaks = qwindow2timestamp(qwindow, lastepoch = lastepoch) breaks_i = c()