Skip to content

Commit

Permalink
add functionality for Actical csv format #68
Browse files Browse the repository at this point in the history
  • Loading branch information
vincentvanhees committed Sep 27, 2024
1 parent 859ac7d commit c32837b
Show file tree
Hide file tree
Showing 8 changed files with 704 additions and 9 deletions.
3 changes: 2 additions & 1 deletion NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export(readGenea, readAxivity, readGENEActiv,
GENEActivReader, resample, readWav,
readActiGraphCount, readActiwatchCount)
readActiGraphCount, readActiwatchCount,
readActicalCount)
useDynLib(GGIRread, .registration = TRUE)
importFrom(Rcpp, sourceCpp)
importFrom(data.table, fread)
Expand Down
2 changes: 1 addition & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
- Added a `NEWS.md` file to track changes to the package.
- Stops interactive calling of `chooseCRANmirror` on `.onAttach` if interactive and CRAN mirror not set GGIR #1141.
- Migrate read function for ActiGraph (csv) and Actiwatch (csv/awd) count data to GGIRread #68.

- Add read function for Actical (csv) count data #68.

# Changes in version 1.0.1 (release date:03-06-2024)

Expand Down
90 changes: 90 additions & 0 deletions R/readActicalCount.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
readActicalCount = function(filename = file, desiredEpochSize = NULL,
timeformat = "%m/%d/%Y %H:%M:%S", tz = "", timeformatName = "timeformat") {
# In GGIR set timeformatName to extEpochData_timeformat


# ! Assumptions that timeseries start before line 1000
index = 300
while (index > 0) {
quote = detectQuote(fn = filename, index = index)
testraw = data.table::fread(input = filename,
header = FALSE, sep = ",", skip = index,
nrows = 2, data.table = FALSE, quote = quote)
if (length(testraw) > 0) {
if (nrow(testraw) == 2) {
if (testraw$V1[2] == testraw$V1[1] + 1) {
break
}
}
}
index = index - 100
}
# ! Assumption that first column are the epoch numbers
delta = 1 - testraw$V1[1]
index = index + delta
startFound = FALSE
while (startFound == FALSE) {
Dtest = data.table::fread(input = filename, sep = ",", skip = index, quote = quote, nrows = 1)
if (Dtest$V1[1] == 1) {
startFound = TRUE
} else {
# This happens when file is has an empty row between each measurement point is stored
index = index - 1
if (index < 1) stop("Could not find start of recording", call. = FALSE)
}
}
D = data.table::fread(input = filename, sep = ",", skip = index, quote = quote, data.table = FALSE)
# ! Assumption that column names are present 2 lines prior to timeseries
dashedlineFound = FALSE
dashedLineIndex = index
while (dashedlineFound == FALSE) {
linedata = data.table::fread(input = filename, data.table = FALSE,
header = FALSE, sep = ",",
skip = dashedLineIndex, nrows = 1, quote = quote)
if (length(grep(pattern = "------", x = linedata[1])) == 1) {
dashedlineFound = TRUE
} else {
dashedLineIndex = dashedLineIndex - 1
}
}
colnames = data.table::fread(input = filename, data.table = FALSE,
header = FALSE, sep = ",",
skip = dashedLineIndex + 1, nrows = (index - dashedLineIndex) - 2, quote = quote)

collapse = function(x) {
return(paste0(x, collapse = "_"))
}
colnames = tolower(as.character(apply(colnames, MARGIN = 2, FUN = collapse)))
colnames(D) = colnames
# ! Assumptions about columns names
colnames(D)[grep(pattern = "time", x = colnames(D))] = "time"
colnames(D)[grep(pattern = "date", x = colnames(D))] = "date"
colnames(D)[grep(pattern = "activity_counts", x = colnames(D))] = "counts"
colnames(D)[grep(pattern = "steps", x = colnames(D))] = "steps"
D = D[, grep(pattern = "time|date|counts|steps", x = colnames(D))]
timestamp_POSIX = as.POSIXct(x = paste(D$date[1:4], D$time[1:4], sep = " "),
format = timeformat,
tz = tz)
checkTimeFormat(timestamp_POSIX[1],
rawValue = paste(D$date[1], D$time[1], sep = " "),
timeformat = timeformat,
timeformatName = timeformatName)
epSizeShort = mean(diff(as.numeric(timestamp_POSIX)))
timestamp_POSIX = timestamp_POSIX[1]
D = D[, -which(colnames(D) %in% c("date", "time"))]
D = as.matrix(D, drop = FALSE)

# If requested, aggregate data to lower resolution to match desired
# epoch size in argument windowsizes
if (!is.null(desiredEpochSize)) {
if (desiredEpochSize > epSizeShort) {
step = desiredEpochSize %/% epSizeShort
D = sumAggregate(D, step)
epSizeShort = epSizeShort * step
}
checkEpochMatch(desiredEpochSize, epSizeShort)
}
if (quote == "") D = apply(D, 2, as.numeric)
invisible(list(data = D, epochSize = epSizeShort,
startTime = timestamp_POSIX))
}
13 changes: 8 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@

Functions for reading accelerometer data from the following file formats:

Brand | Device name | File extension | GGIRread function
------ | ------- | ------- | ----------------
Axivity Ltd https://axivity.com/ | AX3 and AX6 | .cwa | readAxivity
ActivInsights Ltd https://activinsights.com/ | GENEActiv Original and Sleep | .bin | readGENEActiv
Unilever Discover Ltd | Genea (no longer manufactured) | .bin | readGenea
Brand | Device name | File extension | Data type | GGIRread function
------ | ------- | ------- | ---------------- | ---------------------
Axivity Ltd https://axivity.com/ | AX3 and AX6 | .cwa | raw gravitational units |readAxivity
ActivInsights Ltd https://activinsights.com/ | GENEActiv Original and Sleep | .bin | raw gravitational units | readGENEActiv
Unilever Discover Ltd | Genea (no longer manufactured) | .bin | raw gravitational units | readGenea
ActiGraph | ??? | .csv | count data | readActigraph
Actiwatch | ??? | .csv and .awd | count data | readActiwatch
Actical | ??? | .csv | count data | readActical
Loading

0 comments on commit c32837b

Please sign in to comment.