Skip to content

Commit

Permalink
Use tidyverse style with styler
Browse files Browse the repository at this point in the history
  • Loading branch information
Mikkel Roald-Arbøl committed Sep 15, 2024
1 parent 6888cc5 commit 98caf83
Show file tree
Hide file tree
Showing 29 changed files with 284 additions and 258 deletions.
50 changes: 26 additions & 24 deletions R/calculate_kinematics.R
Original file line number Diff line number Diff line change
Expand Up @@ -14,35 +14,36 @@
#' @importFrom rlang .data
#'
calculate_kinematics <- function(
data
) {
data) {
# We first temporarily back-calculate from our xy coordinates to the distances (dx, dy) covered between each observation (which is what we got from the sensors initially)
data <- data |>
dplyr::mutate(dx = .data$x - lag(.data$x),
dy = .data$y - lag(.data$y),
# dt = .data$time - lag(.data$time)
)
dplyr::mutate(
dx = .data$x - lag(.data$x),
dy = .data$y - lag(.data$y),
# dt = .data$time - lag(.data$time)
)

# Find the sampling rate
# sampling_rate <- round(1 / stats::median(data$dt, na.rm = TRUE))

# Calculate kinematics
data <- data |>
dplyr::mutate(distance = calculate_distance(.data$dx, .data$dy),
v_translation = calculate_derivative(.data$distance, 0, .data$time, lag(.data$time)),
a_translation = calculate_derivative(.data$v_translation, lag(.data$v_translation), .data$time, lag(.data$time)),
direction = calculate_direction(.data$dx, .data$dy),
rotation = calculate_angular_difference(.data$direction, lag(.data$direction)),
v_rotation = calculate_derivative(0, .data$rotation, .data$time, lag(.data$time)),
a_rotation = calculate_derivative(.data$v_rotation, lag(.data$v_rotation), .data$time, lag(.data$time)),
# We change the directions to stay within 2pi only here, otherwise rotation becomes harder to alculate
direction = adjust_direction(.data$direction) # Keep direction between 0 and 2*pi
dplyr::mutate(
distance = calculate_distance(.data$dx, .data$dy),
v_translation = calculate_derivative(.data$distance, 0, .data$time, lag(.data$time)),
a_translation = calculate_derivative(.data$v_translation, lag(.data$v_translation), .data$time, lag(.data$time)),
direction = calculate_direction(.data$dx, .data$dy),
rotation = calculate_angular_difference(.data$direction, lag(.data$direction)),
v_rotation = calculate_derivative(0, .data$rotation, .data$time, lag(.data$time)),
a_rotation = calculate_derivative(.data$v_rotation, lag(.data$v_rotation), .data$time, lag(.data$time)),
# We change the directions to stay within 2pi only here, otherwise rotation becomes harder to alculate
direction = adjust_direction(.data$direction) # Keep direction between 0 and 2*pi
)

# Remove leftover columns
data <- data |>
select(-c("dx", "dy"))
# select(-c("dx", "dy", "dt"))
# select(-c("dx", "dy", "dt"))

return(data)
}
Expand All @@ -52,7 +53,7 @@ calculate_kinematics <- function(
#' @param dx dx
#' @param dy dy
#' @keywords internal
calculate_distance <- function(dx, dy){
calculate_distance <- function(dx, dy) {
sqrt(dx^2 + dy^2)
}

Expand All @@ -61,21 +62,22 @@ calculate_distance <- function(dx, dy){
#' @inheritParams calculate_distance
#' @importFrom circular circular
#' @keywords internal
calculate_direction <- function(dx, dy){
calculate_direction <- function(dx, dy) {
if_else(dx == 0 & dy == 0, NA, circular::circular(atan2(dy, dx), modulo = "asis"))
}

#' Calculate angular difference
#' @param from_angle From angle
#' @param to_angle To angle
#' @keywords internal
calculate_angular_difference <- function(from_angle, to_angle){
calculate_angular_difference <- function(from_angle, to_angle) {
ensure_circular(from_angle)
ensure_circular(to_angle)
diff_angle <- from_angle - to_angle
case_when(diff_angle > pi ~ diff_angle - 2*pi,
diff_angle < -pi ~ diff_angle + 2*pi,
.default = diff_angle)
case_when(diff_angle > pi ~ diff_angle - 2 * pi,
diff_angle < -pi ~ diff_angle + 2 * pi,
.default = diff_angle
)
}

#' Calculate the derivative (dx/dt)
Expand All @@ -85,7 +87,7 @@ calculate_angular_difference <- function(from_angle, to_angle){
#' @param from_t Current timestamp
#' @param to_t Lagging timestamp
#' @keywords internal
calculate_derivative <- function(from_x, to_x, from_t, to_t){
calculate_derivative <- function(from_x, to_x, from_t, to_t) {
(from_x - to_x) / (from_t - to_t)
}

Expand All @@ -94,6 +96,6 @@ calculate_derivative <- function(from_x, to_x, from_t, to_t){
#' @param direction Direction
#' @importFrom circular circular
#' @keywords internal
adjust_direction <- function(direction){
adjust_direction <- function(direction) {
circular::circular(direction, modulo = "2pi")
}
31 changes: 15 additions & 16 deletions R/calculate_statistics.R
Original file line number Diff line number Diff line change
Expand Up @@ -19,40 +19,39 @@
calculate_statistics <- function(
data,
measures = "median_mad",
straightness = c("A", "B", "C", "D")
) {
straightness = c("A", "B", "C", "D")) {
validate_statistics()

# Calculate translational and rotational separately (maybe?) and gather at the end
totals <- data |>
dplyr::summarise(across(c(.data$distance, .data$rotation), ~ collapse::fsum(abs(.x)), .names = "total_{.col}"),
across(c(.data$x, .data$y), ~ dplyr::last(.x, na_rm = TRUE), .names = "last_{.col}"),
.by = .data$uid)
across(c(.data$x, .data$y), ~ dplyr::last(.x, na_rm = TRUE), .names = "last_{.col}"),
.by = .data$uid
)

totals <- totals |>
calculate_straightness(straightness)
# dplyr::mutate("straightness_{{ A }} = calculate_straightness(.data$last_x, .data$last_y, .data$total_distance, method = straightness))
# dplyr::mutate("straightness_{{ A }} = calculate_straightness(.data$last_x, .data$last_y, .data$total_distance, method = straightness))


if (measures == "median_mad"){
if (measures == "median_mad") {
data <- data |>
dplyr::summarise(across(c(.data$direction), ~ collapse::fmean(circular::circular(.x, modulo = "2pi")), .names = "median_{.col}"),
across(c(.data$direction), ~ calculate_circular_mad(circular::circular(.x, modulo = "2pi")), .names = "mad_{.col}"),
across(c(.data$v_translation, .data$a_translation, .data$v_rotation, .data$a_rotation), ~ collapse::fmedian(abs(.x)), .names = "median_{.col}"),
across(c(.data$v_translation, .data$a_translation, .data$v_rotation, .data$a_rotation), ~ stats::mad(abs(.x), na.rm = TRUE), .names = "mad_{.col}"),
.by = .data$uid
across(c(.data$direction), ~ calculate_circular_mad(circular::circular(.x, modulo = "2pi")), .names = "mad_{.col}"),
across(c(.data$v_translation, .data$a_translation, .data$v_rotation, .data$a_rotation), ~ collapse::fmedian(abs(.x)), .names = "median_{.col}"),
across(c(.data$v_translation, .data$a_translation, .data$v_rotation, .data$a_rotation), ~ stats::mad(abs(.x), na.rm = TRUE), .names = "mad_{.col}"),
.by = .data$uid
) |>
left_join(totals) |>
select(-c(.data$last_x, .data$last_y)) |>
suppressMessages()

} else if (measures == "mean_sd"){
} else if (measures == "mean_sd") {
data <- data |>
dplyr::summarise(across(c(.data$direction), ~ collapse::fmean(circular::circular(.x)), .names = "mean_{.col}"),
across(c(.data$direction), ~ circular::sd(circular::circular(.x)), .names = "sd_{.col}"),
across(c(.data$v_translation, .data$a_translation, .data$v_rotation, .data$a_rotation), ~ collapse::fmean(abs(.x)), .names = "mean_{.col}"),
across(c(.data$v_translation, .data$a_translation, .data$v_rotation, .data$a_rotation), ~ collapse::fsd(abs(.x)), .names = "sd_{.col}"),
.by = .data$uid
across(c(.data$direction), ~ circular::sd(circular::circular(.x)), .names = "sd_{.col}"),
across(c(.data$v_translation, .data$a_translation, .data$v_rotation, .data$a_rotation), ~ collapse::fmean(abs(.x)), .names = "mean_{.col}"),
across(c(.data$v_translation, .data$a_translation, .data$v_rotation, .data$a_rotation), ~ collapse::fsd(abs(.x)), .names = "sd_{.col}"),
.by = .data$uid
) |>
left_join(totals) |>
select(-c(.data$last_x, .data$last_y)) |>
Expand Down
29 changes: 17 additions & 12 deletions R/calculate_straightness.R
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,29 @@
#'
#' @keywords internal
#' @export
calculate_straightness <- function(data, straightness = c("A", "B", "C", "D")){
calculate_straightness <- function(data, straightness = c("A", "B", "C", "D")) {
# Make validator to ensure that x,y,total_translation and total_rotation is present

data <- data |>
dplyr::mutate(straightness_A = calculate_straightness_A(
.data$last_x,
.data$last_y,
.data$total_distance),
dplyr::mutate(
straightness_A = calculate_straightness_A(
.data$last_x,
.data$last_y,
.data$total_distance
),
straightness_B = calculate_straightness_B(
.data$last_x,
.data$last_y,
.data$total_distance),
.data$total_distance
),
straightness_C = calculate_straightness_C(
.data$total_distance,
.data$total_rotation),
.data$total_rotation
),
straightness_D = calculate_straightness_D(
.data$total_distance,
.data$total_rotation)
.data$total_rotation
)
)

# Only select the methods chosen by the user
Expand All @@ -37,21 +42,21 @@ calculate_straightness <- function(data, straightness = c("A", "B", "C", "D")){
}

#' @keywords internal
calculate_straightness_A <- function(x, y, distance){
calculate_straightness_A <- function(x, y, distance) {
calculate_distance(x, y) / distance
}

#' @keywords internal
calculate_straightness_B <- function(x, y, distance){
calculate_straightness_B <- function(x, y, distance) {
distance / calculate_distance(x, y)
}

#' @keywords internal
calculate_straightness_C <- function(distance, rotation){
calculate_straightness_C <- function(distance, rotation) {
distance / as.numeric(rotation)
}

#' @keywords internal
calculate_straightness_D <- function(distance, rotation){
calculate_straightness_D <- function(distance, rotation) {
as.numeric(rotation) / distance
}
4 changes: 2 additions & 2 deletions R/clean_kinematics.R
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@
#'
#' @return a clean kinematics data frame
#' @export
clean_kinematics <- function(data){
clean_kinematics <- function(data) {
# Place validators here

# Proceed to make the cleaning
data <- data |>
dplyr::filter(.data$direction != atan2(1,0) & .data$direction != atan2(0,1)) |>
dplyr::filter(.data$direction != atan2(1, 0) & .data$direction != atan2(0, 1)) |>
dplyr::filter(.data$v_translation > 0)
return(data)
}
28 changes: 15 additions & 13 deletions R/clean_movement.R
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,22 @@
smooth_track <- function(
data,
method = c("rolling_median"),
window_width = 5
) {

window_width = 5) {
# Back-transform to dx and dy
data <- data |>
dplyr::mutate(dx = .data$x - lag(.data$x),
dy = .data$y - lag(.data$y))
dplyr::mutate(
dx = .data$x - lag(.data$x),
dy = .data$y - lag(.data$y)
)

# Filter the dx/dy values
if (method == "rolling_mean"){
if (method == "rolling_mean") {
data <- data |>
dplyr::mutate(
dx = zoo::rollmean(.data$dx, k = window_width, fill = NA),
dy = zoo::rollmean(.data$dy, k = window_width, fill = NA)
)
} else if (method == "rolling_median"){
dplyr::mutate(
dx = zoo::rollmean(.data$dx, k = window_width, fill = NA),
dy = zoo::rollmean(.data$dy, k = window_width, fill = NA)
)
} else if (method == "rolling_median") {
data <- data |>
dplyr::mutate(
dx = zoo::rollmedian(.data$dx, k = window_width, fill = NA),
Expand All @@ -46,8 +46,10 @@ smooth_track <- function(

# Re-compute xy-coordinates
data <- data |>
dplyr::mutate(x = cumsum(coalesce(.data$dx, 0)) + .data$dx*0,
y = cumsum(coalesce(.data$dy, 0)) + .data$dy*0) |>
dplyr::mutate(
x = cumsum(coalesce(.data$dx, 0)) + .data$dx * 0,
y = cumsum(coalesce(.data$dy, 0)) + .data$dy * 0
) |>
select(-.data$dx, -.data$dy)
return(data)
}
2 changes: 1 addition & 1 deletion R/read_animalta.R
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
#'
#' @return a movement dataframe
#' @export
read_animalta <- function(path){
read_animalta <- function(path) {
cli::cli_abort("`read_animalta` has not yet been implemented. Coming soon!")
}
2 changes: 1 addition & 1 deletion R/read_deeplabcut.R
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
#'
#' @return a movement dataframe
#' @export
read_deeplabcut <- function(data){
read_deeplabcut <- function(data) {
cli::cli_abort("`read_deeplabcut` has not yet been implemented. Coming soon!")
}
2 changes: 1 addition & 1 deletion R/read_idtracker.R
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
#'
#' @return a movement dataframe
#' @export
read_idtracker <- function(data){
read_idtracker <- function(data) {
cli::cli_abort("`read_idtracker` has not yet been implemented. Coming soon!")
}
2 changes: 1 addition & 1 deletion R/read_movement.R
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#'
#' @return a movement dataframe
#' @export
read_movement <- function(data){
read_movement <- function(data) {
cli::cli_abort("`read_movement` has not yet been implemented. Coming soon!")
# Make validators - otherwise straightforward, as the movement export should put them in the correct format
}
2 changes: 1 addition & 1 deletion R/read_sleap.R
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
#'
#' @return a movement dataframe
#' @export
read_sleap <- function(data){
read_sleap <- function(data) {
cli::cli_abort("`read_sleap` has not yet been implemented. Coming soon!")
}
Loading

0 comments on commit 98caf83

Please sign in to comment.