Skip to content

Commit

Permalink
Merge pull request #6 from jhmigueles/issue4_nonIntegerSF
Browse files Browse the repository at this point in the history
Issue4 non integer sf
  • Loading branch information
jhmigueles authored Mar 11, 2023
2 parents a808eb0 + 492848f commit 5f96010
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 37 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/r.yml
Original file line number Diff line number Diff line change
Expand Up @@ -110,4 +110,4 @@ jobs:
uses: actions/upload-artifact@main
with:
name: ${{ runner.os }}-r${{ matrix.config.r }}-results
path: check
path: check
3 changes: 2 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ Description: A tool to obtain activity counts, originally a translation of the
'python' package 'agcounts' <https://github.com/actigraph/agcounts>. This tool
allows the processing of data from any accelerometer brand, with a more flexible
approach to handle different sampling frequencies.
URL: https://github.com/jhmigueles/actilifecounts
Encoding: UTF-8
LazyData: true
Depends: R (>= 2.10)
Imports: gsignal, pracma
Imports: gsignal, pracma, GGIRread
RoxygenNote: 7.2.1
License: LGPL (>= 3)
Suggests:
Expand Down
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export(resample_10hz)
export(resample_30hz)
export(sum_counts)
export(trim_data)
importFrom(GGIRread,resample)
importFrom(gsignal,filter)
importFrom(gsignal,filter_zi)
importFrom(pracma,Lcm)
79 changes: 44 additions & 35 deletions R/resample_30hz.R
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#'
#' @return resampled_data
#' @importFrom pracma Lcm
#' @importFrom GGIRread resample
#' @author Jairo Hidalgo Migueles
#' @references Ali Neishabouri et al. DOI: https://doi.org/10.21203/rs.3.rs-1370418/v1
#' @export
Expand All @@ -17,44 +18,52 @@ resample_30hz = function(raw = c(), sf = 30, verbose = FALSE) {

# make sure it is a matrix
raw = as.matrix(raw)

# define factors using the least common multiple so that any sf can be converted.
upsample_factor = pracma::Lcm(sf, 30) / sf
downsample_factor = pracma::Lcm(sf, 30) / 30

# upsample by factor
n = nrow(raw); m = ncol(raw)
upsample_data = matrix(rep(0, upsample_factor*n*m), ncol = m)
fill_i = seq(1, nrow(upsample_data), by = upsample_factor)
upsample_data[fill_i, ] = raw

# other variables
a_fp = pi / (pi + 2 * upsample_factor)
b_fp = (pi - 2 * upsample_factor) / (pi + 2 * upsample_factor)
up_factor_fp = upsample_factor

# Allocate memory and then LPF. LPF is only done at non
# integer multiples of 30 Hz. This LPF is garbage and does a
# poor job of attenuating higher frequencies that need to be
# rejected. This is the reason why there is aliasing which
# causes the "tail" on the epochs.
if (sf %% 30 != 0) {
upsample_data_roll = upsample_data[c(nrow(upsample_data), 1:(nrow(upsample_data) - 1)),]
upsample_data = (a_fp * up_factor_fp) * (upsample_data + upsample_data_roll)
for (i in 2:nrow(upsample_data)) upsample_data[i,] = upsample_data[i,] - b_fp * upsample_data[i - 1,]

if (sf %% 1 == 0) { # sf is integer
# define factors using the least common multiple so that any sf can be converted.
upsample_factor = pracma::Lcm(sf, 30) / sf
downsample_factor = pracma::Lcm(sf, 30) / 30

# upsample by factor
n = nrow(raw); m = ncol(raw)
upsample_data = matrix(rep(0, upsample_factor*n*m), ncol = m)
fill_i = seq(1, nrow(upsample_data), by = upsample_factor)
upsample_data[fill_i, ] = raw

# other variables
a_fp = pi / (pi + 2 * upsample_factor)
b_fp = (pi - 2 * upsample_factor) / (pi + 2 * upsample_factor)
up_factor_fp = upsample_factor

# Allocate memory and then LPF. LPF is only done at non
# integer multiples of 30 Hz. This LPF is garbage and does a
# poor job of attenuating higher frequencies that need to be
# rejected. This is the reason why there is aliasing which
# causes the "tail" on the epochs.
if (sf %% 30 != 0) {
upsample_data_roll = upsample_data[c(nrow(upsample_data), 1:(nrow(upsample_data) - 1)),]
upsample_data = (a_fp * up_factor_fp) * (upsample_data + upsample_data_roll)
for (i in 2:nrow(upsample_data)) upsample_data[i,] = upsample_data[i,] - b_fp * upsample_data[i - 1,]
}
if (sf == 30) downsample_data = raw
if (sf != 30) downsample_data = upsample_data[seq(1, nrow(upsample_data), by = downsample_factor),]

if (verbose) cat(" Done!\n")
downsample_data = matrix(round(downsample_data, 3), ncol = m)
colnames(downsample_data) = colnames(raw)
} else { # sf is not integer
downsample_data = GGIRread::resample(raw = raw,
rawTime = 1:nrow(raw),
time = 1:(nrow(raw)/sf*30),
stop = nrow(raw),
type = 1)
colnames(downsample_data) = colnames(raw)
}
if (sf == 30) downsample_data = raw
if (sf != 30) downsample_data = upsample_data[seq(1, nrow(upsample_data), by = downsample_factor),]

if (verbose) cat(" Done!\n")
downsample_data = matrix(round(downsample_data, 3), ncol = m)
colnames(downsample_data) = colnames(raw)


# free memory
rm(raw, upsample_data)
if (exists("upsample_data_roll")) rm(upsample_data_roll)
rm(list = setdiff(ls(), c("downsample_data")))
gc()

# return
return(downsample_data)
}

0 comments on commit 5f96010

Please sign in to comment.