# data schema periods = list() periods[[1]] = c(0, 120) periods[[2]] = c(120, 300) periods[[3]] = c(300, 480) periods[[4]] = c(480, 660) periods[[5]] = c(660, 840) periods[[6]] = c(840, 1020) periods[[7]] = c(1020, 1200) periods[[8]] = c(1200, 1380) periods[[9]] = c(1200, 1380) periods[[10]] = c(1380, 1560) periods[[11]] = c(1560, 1740) actionNames <- c("dynamic_lever_pressing", "cage_exploring", "lying_down", "grooming", "laser", "freezing", "akinesia", "slow_lever_pressing", "presence_next_to_feeder", "scratching", "chewing", "yawning") # utility functions decorateAction <- function(action) { trimmedAction = trimws(action) if(trimmedAction == "time_on_lever_pressing_exploredisspan") { return(actionNames[1]) } else if (trimmedAction == "time_on_exploring_cage") { return(actionNames[2]) } else if (trimmedAction == "nap") { return(actionNames[3]) } else if (trimmedAction == "grooming") { return(actionNames[4]) } else if (trimmedAction == "laser") { return(actionNames[5]) } else if (trimmedAction == "freezing") { return(actionNames[6]) } else if (trimmedAction == "catatonic") { return(actionNames[7]) } else if (trimmedAction == "slowly_lever_presing") { return(actionNames[8]) } else if (trimmedAction == "exloring_and_time_disspa") { return(actionNames[9]) } else if (trimmedAction == "scratching") { return(actionNames[10]) } else if (trimmedAction == "zucie") { return(actionNames[11]) } else if (trimmedAction == "ziewanie") { return(actionNames[12]) } else { print(action) } } decoratePeriod <- function(period) { return(paste(period[1], "_", period[2], sep = "")) } indexNameForPeriod <- function(period) { return(paste(period[1], "-", period[2], sep = "")) } map <- function(collection, fun) { res <- list() counter <- 1 for (el in collection) { res[[counter]] <- fun(el) counter <- counter+1 } return(res) } select <- function(collection, fun) { res <- list() counter <- 1 for (el in collection) { if (fun(el)) { res[[counter]] <- el counter <- counter+1 } } return(res) } sum <- function(collection, attr) { amount <- 0 for (el in collection) { amount <- amount + el[[attr]] } amount } generateVectorFromCollection <- function(collection) { vec <- c() for (el in collection) { vec <- c(vec, el) } return(vec) } # business logic getTimeRowsFromFile <- function(filename) { lines <- readLines(filename) return(lines[2:length(lines)]) } timeStrToSeconds <- function(str) { numbers <- strsplit(str, ":")[[1]] amount = (as.numeric(numbers[1]) * 3600) + (as.numeric(numbers[2]) * 60) + as.numeric(numbers[3]) + (as.numeric(numbers[4]) / 100) return(amount) } parseRow <- function(row) { res <- list() parts <- strsplit(row, " - ")[[1]] res[["time_in_sec"]] <- timeStrToSeconds(parts[1]) res[["action"]] <- parts[2] return(res) } getActionPairsFromFile <- function(filename) { parsedRows <- map(getTimeRowsFromFile(filename), function(row) { return(parseRow(row)) }) startTimeInSeconds <- parsedRows[[1]][["time_in_sec"]] rowActionsCache <- list() result <- list() counter <- 1 for(row in parsedRows[2:(length(parsedRows)-1)]) { calculatedTime <- row[["time_in_sec"]] - startTimeInSeconds action <- row[["action"]] cacheValue <- rowActionsCache[[action]] if (is.null(cacheValue)) { rowActionsCache[[action]] <- calculatedTime } else { previousTime <- cacheValue entry <- list() entry[["action"]] <- decorateAction(row[["action"]]) entry[["start_time"]] <- previousTime entry[["end_time"]] <- calculatedTime entry[["duration"]] <- (calculatedTime - previousTime) result[[counter]] <- entry counter <- counter+1 rowActionsCache[[action]] <- NULL } } return(result) } getActionPairsPerDuration <- function(pairs, start, end) { matchingPairs <- select(pairs, function(pair) { startedInPeriod <- pair[["start_time"]] > start & pair[["start_time"]] <= end endedInPeriod <- pair[["end_time"]] > start & pair[["end_time"]] <= end return(startedInPeriod | endedInPeriod) }) withTimesAlignedToPeriod <- map(matchingPairs, function(pair) { entry <- pair if (entry[["start_time"]] < start) { entry["start_time"] <- start } if (entry[["end_time"]] > end) { entry["end_time"] <- end } entry[["duration"]] <- (entry[["end_time"]] - entry[["start_time"]]) return(entry) }) return(withTimesAlignedToPeriod) } scopeDownPairsToAction <- function(pairs, action) { return(select(pairs, function(pair) { pair[["action"]] == action })) } calculateAmountPerAction <- function(pairs, action) { return(length(scopeDownPairsToAction(pairs, action))) } calculateTotalDurationPerAction <- function(pairs, action) { return(sum(scopeDownPairsToAction(pairs, action), "duration")) } calculateAverageDurationPerAction <- function(pairs, action) { amountPerAction <- calculateAmountPerAction(pairs, action) totalDuration <- calculateTotalDurationPerAction(pairs, action) if (amountPerAction == 0) { return(0) } else { return(totalDuration / amountPerAction) } } filenames <- list.files("data/", "*.bvs") # procedure finalData <- list() for (actionName in actionNames) { finalData[[actionName]] <- list() for (filename in filenames) { finalData[[actionName]][[filename]] <- list() fullPath = paste("data", filename, sep="/") pairsFromFile = getActionPairsFromFile(fullPath) for(period in periods) { periodIndex = paste(period[1], "-", period[2], sep = "") finalData[[actionName]][[filename]][[periodIndex]] <- list() pairsFromPeriod = getActionPairsPerDuration(pairsFromFile, period[1], period[2]) finalData[[actionName]][[filename]][[periodIndex]][["n"]] = calculateAmountPerAction(pairsFromPeriod, actionName) finalData[[actionName]][[filename]][[periodIndex]][["total"]] = calculateTotalDurationPerAction(pairsFromPeriod, actionName) finalData[[actionName]][[filename]][[periodIndex]][["average"]] = calculateAverageDurationPerAction(pairsFromPeriod, actionName) } } } generateCsvDataForAction <- function(actionName, data) { props <- c("n", "total", "average") csvData <- list() csvData[["Filenames"]] <- generateVectorFromCollection(filenames) for(period in periods) { for(prop in props) { numbers <- generateVectorFromCollection(map(filenames, function(filename) { return(round(data[[actionName]][[filename]][[indexNameForPeriod(period)]][[prop]], 2)) })) header <- paste(prop, decoratePeriod(period), sep=" ") csvData[[header]] <- numbers } } return(csvData) } outputFileName = "output.csv" for(actionName in actionNames) { write(actionName, file=outputFileName, append=T) write("", file=outputFileName, append=T) data <- generateCsvDataForAction(actionName, finalData) write.table(data, file=outputFileName, append=T, row.names=F) write("", file=outputFileName, append=T) write("", file=outputFileName, append=T) }