vignettes/visual-perception-functions.Rmd
visual-perception-functions.Rmd
pathviewR
includes functions that estimate visual perceptions based on the distance between the subject/observer and visual stimuli on the walls of the experimental tunnel.
We’ll need to start by loading pathviewR
as well as a couple tidyverse
packages for visualizing the data.
Data objects must be prepared as described in the Data Import and Cleaning vignette pipeline prior to their use in these functions. For a detailed description of these functions, please see the linked vignette.
Let’s work with a few example datasets included in pathviewR
. pathviewR_motive_example_data.csv
is a .csv file exported from Motive
. pathviewR_flydra_example_data.mat
is a .mat file exported from Flydra
. pathviewR
contains an all-in-one cleaning function clean_viewr
for more coarse-grained data cleaning tasks. We will use this function in the examples below.
## motive data set motive_data <- # import read_motive_csv( system.file("extdata", "pathviewR_motive_example_data.csv", package = 'pathviewR') ) motive_full <- motive_data %>% clean_viewr( relabel_viewr_axes = TRUE, gather_tunnel_data = TRUE, trim_tunnel_outliers = TRUE, standardization_option = "rotate_tunnel", select_x_percent = TRUE, desired_percent = 50, rename_viewr_characters = FALSE, separate_trajectories = TRUE, max_frame_gap = "autodetect", get_full_trajectories = TRUE, span = 0.95 ) #> autodetect is an experimental feature -- please report issues.
## flydra data set flydra_data <- # import read_flydra_mat( system.file("extdata", "pathviewR_flydra_example_data.mat", package = 'pathviewR'), subject_name = "birdie_wooster") flydra_full <- # clean flydra_data %>% clean_viewr( relabel_viewr_axes = FALSE, gather_tunnel_data = FALSE, trim_tunnel_outliers = FALSE, standardization_option = "redefine_tunnel_center", length_method = "middle", height_method = "user-defined", height_zero = 1.44, get_velocity = FALSE, select_x_percent = TRUE, rename_viewr_characters = FALSE, separate_trajectories = TRUE, get_full_trajectories = TRUE )
insert_treatments()
Now that our objects have been cleaned, we will use insert_treatments()
to add information about the experiments that are necessary for calculating visual perceptions.
The data within motive_full
were collected from birds flying through a V-shaped tunnel in which the origin (0,0,0)
was set to the height of the perches that sit 0.3855m above the height of the vertex. The lateral walls were angled ±45˚ from the vertical axis. The visual stimulus on the positive side of the tunnel (where position_width
values > 0) were horizontal sine wave gratings with a cycle length of 0.1m on the screen. The visual stimulus on the negative side of the tunnel (where position_width
values < 0) were vertical sine wave gratings with a cycle length of 0.2m on the screen.
Therefore we will use the following code:
motive_V <- motive_full %>% insert_treatments(vertex_height = -0.3855, vertex_angle = 45, stim_param_pos = 0.1, stim_param_neg = 0.2, treatment = "latB")
Our object now has the variables, vertex_height
, vertex_angle
, stim_param_pos
, and stim_param_neg
which are needed to calculate visual perceptions. The variable treatment
has also been included and this information has been stored in the object’s metadata.
motive_V #> # A tibble: 449 x 29 #> vertex_height vertex_angle stim_param_pos stim_param_neg treatment frame #> <dbl> <dbl> <dbl> <dbl> <chr> <int> #> 1 -0.386 0.785 0.1 0.2 latB 72213 #> 2 -0.386 0.785 0.1 0.2 latB 72214 #> 3 -0.386 0.785 0.1 0.2 latB 72215 #> 4 -0.386 0.785 0.1 0.2 latB 72216 #> 5 -0.386 0.785 0.1 0.2 latB 72217 #> 6 -0.386 0.785 0.1 0.2 latB 72218 #> 7 -0.386 0.785 0.1 0.2 latB 72219 #> 8 -0.386 0.785 0.1 0.2 latB 72220 #> 9 -0.386 0.785 0.1 0.2 latB 72221 #> 10 -0.386 0.785 0.1 0.2 latB 72222 #> # … with 439 more rows, and 23 more variables: time_sec <dbl>, subject <chr>, #> # position_length <dbl>, position_width <dbl>, position_height <dbl>, #> # rotation_length <dbl>, rotation_width <dbl>, rotation_height <dbl>, #> # rotation_real <dbl>, mean_marker_error <dbl>, velocity <dbl>, #> # length_inst_vel <dbl>, width_inst_vel <dbl>, height_inst_vel <dbl>, #> # traj_id <int>, file_sub_traj <chr>, traj_length <int>, start_length <dbl>, #> # end_length <dbl>, length_diff <dbl>, start_length_sign <dbl>, #> # end_length_sign <dbl>, direction <chr>
The data within flydra_full
were collected from birds flying in a rectangular tunnel i.e. a box where the positive, negative, and front walls were 0.5m from the origin. The visual stimuli were the same as in the motive example, though now with a stimulus on the front wall of 0.2m cycle length.
flydra_box <- # prep for calculations flydra_full %>% insert_treatments(pos_wall = 0.5, neg_wall = 0.5, front_wall = 0.5, stim_param_pos = 0.1, stim_param_neg = 0.2, stim_param_front = 0.2, treatment = "latB")
To calculate the spatial frequency of the visual stimuli as perceived by the subject some distance from the stimuli, we will use calc_sf_V()
and calc_sf_box
depending on the configuration of the tunnel for each experiment.
motive_V_sf <- motive_V %>% calc_sf_V(simplify_output = FALSE) ## The resulting object contains 10 new variables which are values involved in ## the calculation of spatial frequency. motive_V_sf #> # A tibble: 449 x 39 #> vertex_height vertex_angle stim_param_pos stim_param_neg treatment frame #> <dbl> <dbl> <dbl> <dbl> <chr> <int> #> 1 -0.386 0.785 0.1 0.2 latB 72213 #> 2 -0.386 0.785 0.1 0.2 latB 72214 #> 3 -0.386 0.785 0.1 0.2 latB 72215 #> 4 -0.386 0.785 0.1 0.2 latB 72216 #> 5 -0.386 0.785 0.1 0.2 latB 72217 #> 6 -0.386 0.785 0.1 0.2 latB 72218 #> 7 -0.386 0.785 0.1 0.2 latB 72219 #> 8 -0.386 0.785 0.1 0.2 latB 72220 #> 9 -0.386 0.785 0.1 0.2 latB 72221 #> 10 -0.386 0.785 0.1 0.2 latB 72222 #> # … with 439 more rows, and 33 more variables: time_sec <dbl>, subject <chr>, #> # position_length <dbl>, position_width <dbl>, position_height <dbl>, #> # rotation_length <dbl>, rotation_width <dbl>, rotation_height <dbl>, #> # rotation_real <dbl>, mean_marker_error <dbl>, velocity <dbl>, #> # length_inst_vel <dbl>, width_inst_vel <dbl>, height_inst_vel <dbl>, #> # traj_id <int>, file_sub_traj <chr>, traj_length <int>, start_length <dbl>, #> # end_length <dbl>, length_diff <dbl>, start_length_sign <dbl>, #> # end_length_sign <dbl>, direction <chr>, height_2_vertex <dbl>, #> # height_2_screen <dbl>, width_2_screen_pos <dbl>, width_2_screen_neg <dbl>, #> # bound_pos <dbl>, bound_neg <dbl>, min_dist_pos <dbl>, min_dist_neg <dbl>, #> # sf_pos <dbl>, sf_neg <dbl>
flydra_box_sf <- flydra_box %>% calc_sf_box() flydra_box_sf #> # A tibble: 133 x 26 #> pos_wall neg_wall front_wall stim_param_pos stim_param_neg stim_param_front #> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> #> 1 0.5 0.5 0.5 0.1 0.2 0.2 #> 2 0.5 0.5 0.5 0.1 0.2 0.2 #> 3 0.5 0.5 0.5 0.1 0.2 0.2 #> 4 0.5 0.5 0.5 0.1 0.2 0.2 #> 5 0.5 0.5 0.5 0.1 0.2 0.2 #> 6 0.5 0.5 0.5 0.1 0.2 0.2 #> 7 0.5 0.5 0.5 0.1 0.2 0.2 #> 8 0.5 0.5 0.5 0.1 0.2 0.2 #> 9 0.5 0.5 0.5 0.1 0.2 0.2 #> 10 0.5 0.5 0.5 0.1 0.2 0.2 #> # … with 123 more rows, and 20 more variables: treatment <chr>, frame <dbl>, #> # time_sec <dbl>, subject <chr>, position_length <dbl>, position_width <dbl>, #> # position_height <dbl>, traj_id <int>, file_sub_traj <chr>, #> # traj_length <int>, start_length <dbl>, end_length <dbl>, length_diff <dbl>, #> # start_length_sign <dbl>, end_length_sign <dbl>, direction <chr>, #> # min_dist_pos <dbl>, min_dist_neg <dbl>, sf_pos <dbl>, sf_neg <dbl>
simplify_output = TRUE
returns an object containing the 4 new variables min_dist_pos
, mind_dist_neg
, sf_pos
, sf_neg
. Note for calc_sf_box
, there is no need for a simplify_output argument.
To calculate an estimation of the visual angles perceived by the subject, we will use calc_vis_angle_V
and not calc_vis_angle_box
because the data was collected in a V-shaped tunnel.
motive_V_angle <- motive_V %>% calc_vis_angle_V(simplify_output=FALSE) ## The resulting object contains 12 new variables which are values involved in the calculation of visual angles. motive_V_angle #> # A tibble: 449 x 41 #> vertex_height vertex_angle stim_param_pos stim_param_neg treatment frame #> <dbl> <dbl> <dbl> <dbl> <chr> <int> #> 1 -0.386 0.785 0.1 0.2 latB 72213 #> 2 -0.386 0.785 0.1 0.2 latB 72214 #> 3 -0.386 0.785 0.1 0.2 latB 72215 #> 4 -0.386 0.785 0.1 0.2 latB 72216 #> 5 -0.386 0.785 0.1 0.2 latB 72217 #> 6 -0.386 0.785 0.1 0.2 latB 72218 #> 7 -0.386 0.785 0.1 0.2 latB 72219 #> 8 -0.386 0.785 0.1 0.2 latB 72220 #> 9 -0.386 0.785 0.1 0.2 latB 72221 #> 10 -0.386 0.785 0.1 0.2 latB 72222 #> # … with 439 more rows, and 35 more variables: time_sec <dbl>, subject <chr>, #> # position_length <dbl>, position_width <dbl>, position_height <dbl>, #> # rotation_length <dbl>, rotation_width <dbl>, rotation_height <dbl>, #> # rotation_real <dbl>, mean_marker_error <dbl>, velocity <dbl>, #> # length_inst_vel <dbl>, width_inst_vel <dbl>, height_inst_vel <dbl>, #> # traj_id <int>, file_sub_traj <chr>, traj_length <int>, start_length <dbl>, #> # end_length <dbl>, length_diff <dbl>, start_length_sign <dbl>, #> # end_length_sign <dbl>, direction <chr>, height_2_vertex <dbl>, #> # height_2_screen <dbl>, width_2_screen_pos <dbl>, width_2_screen_neg <dbl>, #> # min_dist_pos <dbl>, min_dist_neg <dbl>, bound_pos <dbl>, bound_neg <dbl>, #> # vis_angle_pos_rad <dbl>, vis_angle_neg_rad <dbl>, vis_angle_pos_deg <dbl>, #> # vis_angle_neg_deg <dbl>
flydra_box_angle <- flydra_box %>% calc_vis_angle_box()
simplify_output=TRUE
returns an object containing the 4 new variables min_dist_pos
, min_dist_neg
, vis_angle_pos_deg
, and vis_angle_neg_deg
.
Visualizing the calculations provides an more intuitive understanding of how these visual perceptions change as the subject moves throughout the tunnel. Note: The axes of the following examples differ between the motive and flydra data sets. These plots were generated to best visualize the perceptual calculations
Motive
ggplot(motive_V_sf, aes(x = position_width, y = position_height)) + geom_point(aes(color = sf_pos), shape=1, size=3) + coord_fixed() + geom_segment(aes(x = 0, # dimensions of the positive wall y = -0.3855, xend = 0.5869, yend = 0.2014)) + geom_segment(aes(x = 0, # dimensions of the negative wall y = -0.3855, xend = -0.5869, yend = 0.2014))
We can see that as the position of the subject is closer to the right (positive) wall, the perception of that stimulus is with smaller spatial frequency.
ggplot(motive_V_sf, aes(x = position_width, y = position_height)) + geom_point(aes(color = sf_neg), shape=1, size=3) + coord_fixed() + geom_segment(aes(x = 0, # dimensions of the positive wall y = -0.3855, xend = 0.5869, yend = 0.2014)) + geom_segment(aes(x = 0, # dimensions of the negative wall y = -0.3855, xend = -0.5869, yend = 0.2014))
A different pattern is found by visualizing the spatial frequencies observed from the left (negative) wall.
Flydra
ggplot(flydra_box_sf, aes(x = position_width, y = position_length)) + geom_point(aes(colour = sf_pos), size = 2) + coord_fixed() + geom_segment(aes(x = -0.5, # negative wall y = -0.5, xend = -0.5, yend = 0.5)) + geom_segment(aes(x = 0.5, # positive wall y = -0.5, xend = 0.5, yend = 0.5))
ggplot(flydra_box_sf, aes(x = position_width, y = position_length)) + geom_point(aes(colour = sf_neg), size = 2) + coord_fixed() + geom_segment(aes(x = -0.5, # negative wall y = -0.5, xend = -0.5, yend = 0.5)) + geom_segment(aes(x = 0.5, # positive wall y = -0.5, xend = 0.5, yend = 0.5))
Motive
ggplot(motive_V_angle, aes(x = position_width, y = position_height)) + geom_point(aes(color = vis_angle_pos_deg), shape=1, size=3) + coord_fixed() + geom_segment(aes(x = 0, # dimensions of the positive wall y = -0.3855, xend = 0.5869, yend = 0.2014)) + geom_segment(aes(x = 0, # dimensions of the negative wall y = -0.3855, xend = -0.5869, yend = 0.2014))
By displaying the visual angles (in degrees) created by the stimulus on the positive wall, we can see that the subject perceives larger visual angles the closer it gets to the positive wall.
Now displaying visual angles perceived on the negative wall.
ggplot(motive_V_angle, aes(x = position_width, y = position_height)) + geom_point(aes(color = vis_angle_neg_deg), shape=1, size=3) + coord_fixed() + geom_segment(aes(x = 0, # dimensions of the positive wall y = -0.3855, xend = 0.5869, yend = 0.2014)) + geom_segment(aes(x = 0, # dimensions of the negative wall y = -0.3855, xend = -0.5869, yend = 0.2014))
This shows that the subject perceives larger visual angles the closer it gets to the negative wall.
Flydra
ggplot(flydra_box_angle, aes(x = position_width, y = position_length)) + geom_point(aes(colour = vis_angle_pos_deg), size = 2) + coord_fixed() + geom_segment(aes(x = -0.5, # negative wall y = -0.5, xend = -0.5, yend = 0.5)) + geom_segment(aes(x = 0.5, # positive wall y = -0.5, xend = 0.5, yend = 0.5))
ggplot(flydra_box_angle, aes(x = position_width, y = position_length)) + geom_point(aes(colour = vis_angle_neg_deg), size = 2) + coord_fixed() + geom_segment(aes(x = -0.5, # negative wall y = -0.5, xend = -0.5, yend = 0.5)) + geom_segment(aes(x = 0.5, # positive wall y = -0.5, xend = 0.5, yend = 0.5))