Modified Post: 2018-09-06


Tags: fMRI R


These motion variables can be used as control variables (as seen in resting-state and task-based functional connectivity analyses).



6-Rigid Body Motion Regressors

The first six motion parameters are the standard motion parameters and include:

  1. \(translation_X\), translation in the x-direction
  2. \(translation_Y\), translation in the y-direction
  3. \(translation_Z\), translation in the z-direction
  4. \(rotation_X\), rotation around the x-axis
  5. \(rotation_Y\), rotation around the y-axis
  6. \(rotation_Z\), rotation around the z-axis
# load 6-rigidy body motion parameters
motion_demeaned <- read.csv("blog_Calculate_Motion_Regressors_files/example_motion_demeand.csv", header = FALSE)

# rename columns
motion_variables <- c("translation_x", "translation_y", "translation_z", "rotation_x", "rotation_y", "rotation_z")

colnames(motion_demeaned) <- motion_variables

# add duration for graphs
motion_demeaned$duration <- c(1:780)

# plot translation x
motion_translation_x <- ggplot(motion_demeaned, mapping = aes(x = duration, y = translation_x)) +
  geom_line(color = "#106a8c") +
  theme_classic() +
  theme(
    plot.title = element_text(hjust = .5),
    plot.subtitle = element_text(hjust = .5)
  ) +
  ggtitle("Translation X") +
  xlab("Duration") +
  ylab("mm")

# plot translation y
motion_translation_y <- ggplot(motion_demeaned, mapping = aes(x = duration, y = translation_y)) +
  geom_line(color = "#106a8c") +
  theme_classic() +
  theme(
    plot.title = element_text(hjust = .5),
    plot.subtitle = element_text(hjust = .5)
  ) +
  ggtitle("Translation Y") +
  xlab("Duration") +
  ylab("mm")

# plot translation z
motion_translation_z <- ggplot(motion_demeaned, mapping = aes(x = duration, y = translation_z)) +
  geom_line(color = "#106a8c") +
  theme_classic() +
  theme(
    plot.title = element_text(hjust = .5),
    plot.subtitle = element_text(hjust = .5)
  ) +
  ggtitle("Translation Z") +
  xlab("Duration") +
  ylab("mm")

# plot rotation x
motion_rotation_x <- ggplot(motion_demeaned, mapping = aes(x = duration, y = rotation_x)) +
  geom_line(color = "#106a8c") +
  theme_classic() +
  theme(
    plot.title = element_text(hjust = .5),
    plot.subtitle = element_text(hjust = .5)
  ) +
  ggtitle("Rotation X") +
  xlab("Duration") +
  ylab("Degrees")

# plot rotation y
motion_rotation_y <- ggplot(motion_demeaned, mapping = aes(x = duration, y = rotation_y)) +
  geom_line(color = "#106a8c") +
  theme_classic() +
  theme(
    plot.title = element_text(hjust = .5),
    plot.subtitle = element_text(hjust = .5)
  ) +
  ggtitle("Rotation Y") +
  xlab("Duration") +
  ylab("Degrees")

# plot yaw
motion_rotation_z <- ggplot(motion_demeaned, mapping = aes(x = duration, y = rotation_z)) +
  geom_line(color = "#106a8c") +
  theme_classic() +
  theme(
    plot.title = element_text(hjust = .5),
    plot.subtitle = element_text(hjust = .5)
  ) +
  ggtitle("Rotation Z") +
  xlab("Duration") +
  ylab("Degrees")

# plot 6-rigid body motion parameters into one figure
grid.arrange(motion_translation_x, motion_translation_y, motion_translation_z, motion_rotation_x, motion_rotation_y, motion_rotation_z, nrow = 2, ncol = 3, top = "6-Rigid Body Motion Parameters")



12-Motion Regressors

The next six motion parameters are the first temporal derivates of the original six rigid body motion parameters. Specifically, it is the motion minus the motion from the previous time point.

  1. \(translation_{X_{T-1}}\), first temporal derivative of the translation in the x-direction
  2. \(translation_{Y_{T-1}}\), first temporal derivative of the translation in the y-direction
  3. \(translation_{Z_{T-1}}\), first temporal derivative of the translation in the z-direction
  4. \(rotation_{X_{T-1}}\) first temporal derivative of the rotation around the x-axis
  5. \(rotation_{Y_{T-1}}\), first temporal derivative of the rotation around the y-axis
  6. \(rotation_{Z_{T-1}}\), first temporal derivative of the rotation around the z-axis
# calculate first temporal derivative
motion_demeaned.td1 <- sapply(motion_demeaned, FUN = function(x) c(NA, diff(x)))

# save as dataframe
motion_demeaned.td1 <- as.data.frame(motion_demeaned.td1)

# rename columns
colnames(motion_demeaned.td1) <- paste0(motion_variables, "_td1")

# add duration for graphs
motion_demeaned.td1$duration <- c(1:780)

# plot translation x td1
motion_translation_x_td1 <- ggplot(motion_demeaned.td1, mapping = aes(x = duration, y = translation_x_td1)) +
  geom_line(color = "#106a8c") +
  theme_classic() +
  theme(
    plot.title = element_text(hjust = .5),
    plot.subtitle = element_text(hjust = .5)
  ) +
  ggtitle("Translation X") +
  xlab("Duration") +
  ylab("mm")

# plot translation y td1
motion_translation_y_td1 <- ggplot(motion_demeaned.td1, mapping = aes(x = duration, y = translation_y_td1)) +
  geom_line(color = "#106a8c") +
  theme_classic() +
  theme(
    plot.title = element_text(hjust = .5),
    plot.subtitle = element_text(hjust = .5)
  ) +
  ggtitle("Translation Y") +
  xlab("Duration") +
  ylab("mm")

# plot translation z td1
motion_translation_z_td1 <- ggplot(motion_demeaned.td1, mapping = aes(x = duration, y = translation_z_td1)) +
  geom_line(color = "#106a8c") +
  theme_classic() +
  theme(
    plot.title = element_text(hjust = .5),
    plot.subtitle = element_text(hjust = .5)
  ) +
  ggtitle("Translation Z") +
  xlab("Duration") +
  ylab("mm")

# plot rotation x td1
motion_rotation_x_td1 <- ggplot(motion_demeaned.td1, mapping = aes(x = duration, y = rotation_x_td1)) +
  geom_line(color = "#106a8c") +
  theme_classic() +
  theme(
    plot.title = element_text(hjust = .5),
    plot.subtitle = element_text(hjust = .5)
  ) +
  ggtitle("Rotation X") +
  xlab("Duration") +
  ylab("Degrees")

# plot rotation y td1
motion_rotation_y_td1 <- ggplot(motion_demeaned.td1, mapping = aes(x = duration, y = rotation_y_td1)) +
  geom_line(color = "#106a8c") +
  theme_classic() +
  theme(
    plot.title = element_text(hjust = .5),
    plot.subtitle = element_text(hjust = .5)
  ) +
  ggtitle("Rotation Y") +
  xlab("Duration") +
  ylab("Degrees")

# plot rotation z td1
motion_rotation_z_td1 <- ggplot(motion_demeaned.td1, mapping = aes(x = duration, y = rotation_z_td1)) +
  geom_line(color = "#106a8c") +
  theme_classic() +
  theme(
    plot.title = element_text(hjust = .5),
    plot.subtitle = element_text(hjust = .5)
  ) +
  ggtitle("Rotation Z") +
  xlab("Duration") +
  ylab("Degrees")

# plot motion.td1 into one figure
grid.arrange(motion_translation_x_td1, motion_translation_y_td1, motion_translation_z_td1, motion_rotation_x_td1, motion_rotation_y_td1, motion_rotation_z_td1, nrow = 2, ncol = 3, top = "First Temporal Derivatives of the 6-Rigid Body Motion Parameters")



18-Motion Regressors

The next six motion parameters are the original six rigid body motion parameters squared:

  1. \(translation_X^2\), translation in the x-direction squared
  2. \(translation_Y^2\), translation in the y-direction squared
  3. \(translation_Z^2\), translation in the z-direction squared
  4. \(rotation_X^2\), rotation around the x-axis squared
  5. \(rotation_Y^2\), rotation around the y-axis squared
  6. \(rotation_Z^2\), rotation around the z-axis squared
# square 6-rigid body motion parameters
motion_demeaned.sq <- motion_demeaned^2

# save as data frame
motion_demeaned.sq <- as.data.frame(motion_demeaned.sq)

# rename columns
colnames(motion_demeaned.sq) <- paste0(motion_variables, "_squared")

# add duration for graphs
motion_demeaned.sq$duration <- c(1:780)

# plot translation x squared
motion_translation_x_squared <- ggplot(motion_demeaned.sq, mapping = aes(x = duration, y = translation_x_squared)) +
  geom_line(color = "#106a8c") +
  theme_classic() +
  theme(
    plot.title = element_text(hjust = .5),
    plot.subtitle = element_text(hjust = .5)
  ) +
  ggtitle("Translation X") +
  xlab("Duration") +
  ylab("mm")

# plot translation y squared
motion_translation_y_squared <- ggplot(motion_demeaned.sq, mapping = aes(x = duration, y = translation_y_squared)) +
  geom_line(color = "#106a8c") +
  theme_classic() +
  theme(
    plot.title = element_text(hjust = .5),
    plot.subtitle = element_text(hjust = .5)
  ) +
  ggtitle("Translation Y") +
  xlab("Duration") +
  ylab("mm")

# plot translation z squared
motion_translation_z_squared <- ggplot(motion_demeaned.sq, mapping = aes(x = duration, y = translation_z_squared)) +
  geom_line(color = "#106a8c") +
  theme_classic() +
  theme(
    plot.title = element_text(hjust = .5),
    plot.subtitle = element_text(hjust = .5)
  ) +
  ggtitle("Translation Z") +
  xlab("Duration") +
  ylab("mm")

# plot rotation x squared
motion_rotation_x_squared <- ggplot(motion_demeaned.sq, mapping = aes(x = duration, y = rotation_x_squared)) +
  geom_line(color = "#106a8c") +
  theme_classic() +
  theme(
    plot.title = element_text(hjust = .5),
    plot.subtitle = element_text(hjust = .5)
  ) +
  ggtitle("Rotation X") +
  xlab("Duration") +
  ylab("Degrees")

# plot rotation y squared
motion_rotation_y_squared <- ggplot(motion_demeaned.sq, mapping = aes(x = duration, y = rotation_y_squared)) +
  geom_line(color = "#106a8c") +
  theme_classic() +
  theme(
    plot.title = element_text(hjust = .5),
    plot.subtitle = element_text(hjust = .5)
  ) +
  ggtitle("Rotation Y") +
  xlab("Duration") +
  ylab("Degrees")

# plot rotation z squared
motion_rotation_z_squared <- ggplot(motion_demeaned.sq, mapping = aes(x = duration, y = rotation_z_squared)) +
  geom_line(color = "#106a8c") +
  theme_classic() +
  theme(
    plot.title = element_text(hjust = .5),
    plot.subtitle = element_text(hjust = .5)
  ) +
  ggtitle("Rotation Z") +
  xlab("Duration") +
  ylab("Degrees")

# plot motion.sq into one figure
grid.arrange(motion_translation_x_squared, motion_translation_y_squared, motion_translation_z_squared, motion_rotation_x_squared, motion_rotation_y_squared, motion_rotation_z_squared, nrow = 2, ncol = 3, top = "6-Rigid Body Motion Parameters Squared")



24-Motion Regressors

The next six motion parameters are the first temporal derivatives squared.

  1. \(translation_{X_{T-1}}^2\), first temporal derivative of the translation in the x-direction squared
  2. \(translation_{Y_{T-1}}^2\), first temporal derivative of the translation in the y-direction squared
  3. \(translation_{Z_{T-1}}^2\), first temporal derivative of the translation in the z-direction squared
  4. \(rotation_{X_{T-1}}^2\), first temporal derivative of the rotation around the x-axis squared
  5. \(rotation_{Y_{T-1}}^2\) first temporal derivative of the rotation around the y-axis squared
  6. \(rotation_{Z_{T-1}}^2\), first temporal derivative of the rotation around the z-axis squared
# square the first temporal derivative
motion_demeaned.td1.sq <- motion_demeaned.td1^2 # first temporal derivative squared

# save as dataframe
motion_demeaned.td1.sq <- as.data.frame(motion_demeaned.td1.sq)

# rename columns
colnames(motion_demeaned.td1.sq) <- paste0(motion_variables, "_td1_squared") # rename columns

# add duration for graphs
motion_demeaned.td1.sq$duration <- c(1:780)

# plot translation x td1 squared
motion_translation_x_td1_squared <- ggplot(motion_demeaned.td1.sq, mapping = aes(x = duration, y = translation_x_td1_squared)) +
  geom_line(color = "#106a8c") +
  theme_classic() +
  theme(
    plot.title = element_text(hjust = .5),
    plot.subtitle = element_text(hjust = .5)
  ) +
  ggtitle("Translation X") +
  xlab("Duration") +
  ylab("mm")

# plot translation y td1 squared
motion_translation_y_td1_squared <- ggplot(motion_demeaned.td1.sq, mapping = aes(x = duration, y = translation_y_td1_squared)) +
  geom_line(color = "#106a8c") +
  theme_classic() +
  theme(
    plot.title = element_text(hjust = .5),
    plot.subtitle = element_text(hjust = .5)
  ) +
  ggtitle("Translation Y") +
  xlab("Duration") +
  ylab("mm")

# plot translation z td1 squared
motion_translation_z_td1_squared <- ggplot(motion_demeaned.td1.sq, mapping = aes(x = duration, y = translation_z_td1_squared)) +
  geom_line(color = "#106a8c") +
  theme_classic() +
  theme(
    plot.title = element_text(hjust = .5),
    plot.subtitle = element_text(hjust = .5)
  ) +
  ggtitle("Translation Z") +
  xlab("Duration") +
  ylab("mm")

# plot rotation x td1 squared
motion_rotation_x_td1_squared <- ggplot(motion_demeaned.td1.sq, mapping = aes(x = duration, y = rotation_x_td1_squared)) +
  geom_line(color = "#106a8c") +
  theme_classic() +
  theme(
    plot.title = element_text(hjust = .5),
    plot.subtitle = element_text(hjust = .5)
  ) +
  ggtitle("Rotation X") +
  xlab("Duration") +
  ylab("Degrees")

# plot rotation y td1 squared
motion_rotation_y_td1_squared <- ggplot(motion_demeaned.td1.sq, mapping = aes(x = duration, y = rotation_y_td1_squared)) +
  geom_line(color = "#106a8c") +
  theme_classic() +
  theme(
    plot.title = element_text(hjust = .5),
    plot.subtitle = element_text(hjust = .5)
  ) +
  ggtitle("Rotation Y") +
  xlab("Duration") +
  ylab("Degrees")

# plot rotation z td1 squared
motion_rotation_z_td1_squared <- ggplot(motion_demeaned.td1.sq, mapping = aes(x = duration, y = rotation_z_td1_squared)) +
  geom_line(color = "#106a8c") +
  theme_classic() +
  theme(
    plot.title = element_text(hjust = .5),
    plot.subtitle = element_text(hjust = .5)
  ) +
  ggtitle("Rotation Z") +
  xlab("Duration") +
  ylab("Degrees")

# plot motion.td1.sq into one figure
grid.arrange(motion_translation_x_td1_squared, motion_translation_y_td1_squared, motion_translation_z_td1_squared, motion_rotation_x_td1_squared, motion_rotation_y_td1_squared, motion_rotation_z_td1_squared, nrow = 2, ncol = 3, top = "First Temporal Derivatives of the 6-Rigid Body Motion Parameters Squared")



R Code Example

# function to create 24 motion variables =======================================
create_24_motion_variables <- function(dataset) {
  # mean-center (demean) ----
  # subtract each score from its respective column mean
  dataset_motion_demeaned <- scale(x = dataset, center = T, scale = F)

  # first temporal derivatives ----
  # subtract motion from prior motion time point
  dataset_motion_td1 <- sapply(dataset_motion_demeaned, FUN = function(x) c(NA, diff(x)))

  # combine the variables into one dataset
  dataset_motion <- data.frame(dataset_motion_demeaned, dataset_motion_td1)

  # squares ----
  # square 6-rigid body motion parameters and its temporal derivatives
  dataset_motion_squared <- dataset_motion^2

  # combine the variables into one dataset
  dataset_motion <- data.frame(dataset_motion, dataset_motion_squared)

  return(dataset_motion)
}

# load 6-rigid body motion parameters file =====================================
# assign to dataset_motion
dataset_motion <- read.csv(file.choose())

# create 24 motion variables using function ====================================
# assign output to dataset_motion_24
dataset_motion_24 <- create_24_motion_variables(dataset = dataset_motion)

# rename columns ===============================================================
# assign original motion variables
motion_variables <- c(
  "translation_x", "translation_y", "translation_z",
  "rotation_x", "rotation_y", "rotation_z"
)

# rename columns
colnames(dataset_motion_24) <- c(
  motion_variables,
  paste0(motion_variables, "_td1"),
  paste0(motion_variables, "_squared"),
  paste0(motion_variables, "_td1_squared")
)

# export 24-motion variables ===================================================
write.csv(x = dataset_motion_24, file = "dataset-motion-24.csv")



References

Friston, K. J., Williams, S., Howard, R., Frackowiak, R. S. J., & Turner, R. (1996). Movement-related effects in fMRI time-series. Magnetic Resonance in Medicine, 35(3), 346–355. http://doi.org/10.1002/mrm.1910350312

Yan, C.-G., Cheung, B., Kelly, C., Colcombe, S., Craddock, R. C., Di Martino, A., … Milham, M. P. (2013). A comprehensive assessment of regional variation in the impact of head micromovements on functional connectomics. NeuroImage, 76, 183–201. http://doi.org/10.1016/j.neuroimage.2013.03.004