Code Monkey home page Code Monkey logo

pathviewr's Introduction

pathviewr

Project Status: Active – The project has reached a stable, usable state and is being actively developed. R build status Codecov test coverage
DOI CRAN status

pathviewr offers tools to import, clean, and visualize movement data, particularly from motion capture systems such as Optitrack’s Motive, the Straw Lab’s Flydra, or other sources. We provide functions to remove artifacts, standardize tunnel position and tunnel axes, select a region of interest, isolate specific trajectories, fill gaps in trajectory data, and calculate 3D and per-axis velocity. For experiments of visual guidance, we also provide functions that use subject position to estimate perception of visual stimuli.

Installation

You can install pathviewr from CRAN via:

install.packages("pathviewr")

Or to get the latest (developmental) version through GitHub, use:

devtools::install_github("ropensci/pathviewr")

Example

Data import and cleaning via pathviewr

We’ll also load two tidyverse packages for wrangling & plotting in this readme.

library(pathviewr)
library(ggplot2)
library(magrittr)

We will import and clean a sample data set from .csv files exported by Optitrack’s Motive software. For examples of how to import and clean other types of data, see the Basics of data import and cleaning vignette.

## Import the Motive example data included in 
## the package

motive_data <-
  read_motive_csv(
    system.file("extdata", "pathviewr_motive_example_data.csv",
                package = 'pathviewr')
  )

Several functions to clean and wrangle data are available, and we have a suggested pipeline for how these steps should be handled. For this example, we will use one of two “all-in-one” functions: clean_viewr(). See the Basics of data import and cleaning vignette for the full pipeline and the other “all-in-one” function.

motive_allinone <-
  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.

## Quick plot
## Colors correspond to unique trajectories (file_sub_traj)
motive_allinone %>%
  ggplot(aes(x = position_length, y = position_width, 
             fill = file_sub_traj)) +
  geom_point(pch = 21) +
  coord_fixed() +
  theme_classic() +
  theme(
    legend.position = "none"
  )

To get a sense of what we’ve done, compare the data before and after it has passed through the pipeline.

## Check out the data's structure before cleaning and wrangling:
str(motive_data)
#> tibble [934 × 26] (S3: tbl_df/tbl/data.frame)
#>  $ frame                     : int [1:934] 72210 72211 72212 72213 72214 72215 72216 72217 72218 72219 ...
#>  $ time_sec                  : num [1:934] 722 722 722 722 722 ...
#>  $ device02_rotation_x       : num [1:934] 0.1346 0.0819 0.2106 0.1961 0.1305 ...
#>  $ device02_rotation_y       : num [1:934] -0.977 -0.978 -0.973 -0.972 -0.975 ...
#>  $ device02_rotation_z       : num [1:934] -0.1117 -0.0991 -0.0939 -0.1275 -0.1213 ...
#>  $ device02_rotation_w       : num [1:934] 0.1215 0.1654 0.0311 0.0351 0.1315 ...
#>  $ device02_position_x       : num [1:934] 0.142 0.137 0.125 0.118 0.113 ...
#>  $ device02_position_y       : num [1:934] 0.16 0.164 0.166 0.168 0.173 ...
#>  $ device02_position_z       : num [1:934] 2 1.97 1.95 1.92 1.89 ...
#>  $ device02_mean_marker_error: num [1:934] 0.000113 0.000105 0.000115 0.000202 0.000106 0.000095 0.000114 0.000117 0.000121 0.000131 ...
#>  $ device03_rotation_x       : num [1:934] 0.107 0.111 0.109 0.109 0.108 ...
#>  $ device03_rotation_y       : num [1:934] -0.295 -0.295 -0.295 -0.295 -0.295 ...
#>  $ device03_rotation_z       : num [1:934] -0.088 -0.0866 -0.0853 -0.0853 -0.0879 ...
#>  $ device03_rotation_w       : num [1:934] 0.945 0.945 0.945 0.945 0.945 ...
#>  $ device03_position_x       : num [1:934] 0.222 0.222 0.222 0.222 0.222 ...
#>  $ device03_position_y       : num [1:934] 0.245 0.245 0.245 0.245 0.245 ...
#>  $ device03_position_z       : num [1:934] 0.0597 0.0597 0.0598 0.0598 0.0598 ...
#>  $ device03_mean_marker_error: num [1:934] 0.000166 0.000172 0.000164 0.000163 0.000162 0.000162 0.000169 0.00017 0.00017 0.000213 ...
#>  $ device05_rotation_x       : num [1:934] 0.00672 0.00714 0.00709 0.00742 0.00826 ...
#>  $ device05_rotation_y       : num [1:934] 0.944 0.944 0.944 0.944 0.944 ...
#>  $ device05_rotation_z       : num [1:934] -0.117 -0.116 -0.118 -0.118 -0.117 ...
#>  $ device05_rotation_w       : num [1:934] 0.308 0.308 0.309 0.31 0.308 ...
#>  $ device05_position_x       : num [1:934] 0.173 0.173 0.173 0.173 0.173 ...
#>  $ device05_position_y       : num [1:934] 0.243 0.243 0.243 0.243 0.243 ...
#>  $ device05_position_z       : num [1:934] 2.66 2.66 2.66 2.66 2.66 ...
#>  $ device05_mean_marker_error: num [1:934] 0.000241 0.000247 0.000255 0.000244 0.00023 0.000226 0.000231 0.000236 0.000242 0.000263 ...
#>  - attr(*, ".internal.selfref")=<externalptr> 
#>  - attr(*, "pathviewr_steps")= chr "viewr"
#>  - attr(*, "file_id")= chr "pathviewr_motive_example_data.csv"
#>  - attr(*, "file_mtime")= POSIXct[1:1], format: "2023-03-07 11:12:49"
#>  - attr(*, "frame_rate")= num 100
#>  - attr(*, "header")='data.frame':   11 obs. of  2 variables:
#>   ..$ metadata: chr [1:11] "Format Version" "Take Name" "Take Notes" "Capture Frame Rate" ...
#>   ..$ value   : chr [1:11] "1.23" "sept-18_mixed-group_16-30" "" "100.000000" ...
#>  - attr(*, "Motive_IDs")= chr [1:24] "\"9E207518D8A311E969D7AB6B1FACE49B\"" "\"9E207518D8A311E969D7AB6B1FACE49B\"" "\"9E207518D8A311E969D7AB6B1FACE49B\"" "\"9E207518D8A311E969D7AB6B1FACE49B\"" ...
#>  - attr(*, "subject_names_full")= chr [1:24] "device02" "device02" "device02" "device02" ...
#>  - attr(*, "subject_names_simple")= chr [1:3] "device02" "device03" "device05"
#>  - attr(*, "data_names")= chr [1:26] "frame" "time_sec" "device02_rotation_x" "device02_rotation_y" ...
#>  - attr(*, "data_types_full")= chr [1:24] "Rigid Body" "Rigid Body" "Rigid Body" "Rigid Body" ...
#>  - attr(*, "data_types_simple")= chr "Rigid Body"
#>  - attr(*, "d1")= chr [1:26] "" "" "Rotation" "Rotation" ...
#>  - attr(*, "d2")= chr [1:26] "Frame" "Time (Seconds)" "X" "Y" ...
#>  - attr(*, "import_method")= chr "motive"

## Check out the data's structure after cleaning and wrangling:
str(motive_allinone)
#> tibble [449 × 24] (S3: tbl_df/tbl/data.frame)
#>  $ frame            : int [1:449] 72213 72214 72215 72216 72217 72218 72219 72220 72221 72222 ...
#>  $ time_sec         : num [1:449] 722 722 722 722 722 ...
#>  $ subject          : chr [1:449] "device02" "device02" "device02" "device02" ...
#>  $ position_length  : num [1:449] 0.647 0.62 0.593 0.567 0.541 ...
#>  $ position_width   : num [1:449] -0.112 -0.116 -0.122 -0.134 -0.141 ...
#>  $ position_height  : num [1:449] -0.0371 -0.0324 -0.0273 -0.0235 -0.0209 ...
#>  $ rotation_length  : num [1:449] -0.128 -0.121 -0.105 -0.106 -0.149 ...
#>  $ rotation_width   : num [1:449] 0.1961 0.1305 0.0935 0.1798 0.164 ...
#>  $ rotation_height  : num [1:449] -0.972 -0.975 -0.975 -0.975 -0.972 ...
#>  $ rotation_real    : num [1:449] 0.0351 0.1315 0.1734 0.0807 0.0824 ...
#>  $ mean_marker_error: num [1:449] 0.000202 0.000106 0.000095 0.000114 0.000117 0.000121 0.000131 0.00014 0.000113 0.000114 ...
#>  $ velocity         : num [1:449] 2.73 2.78 2.84 2.85 2.68 ...
#>  $ length_inst_vel  : num [1:449] -2.65 -2.72 -2.74 -2.58 -2.56 ...
#>  $ width_inst_vel   : num [1:449] -0.642 -0.387 -0.58 -1.139 -0.75 ...
#>  $ height_inst_vel  : num [1:449] 0.184 0.475 0.508 0.379 0.258 ...
#>  $ traj_id          : int [1:449] 0 0 0 0 0 0 0 0 0 0 ...
#>  $ file_sub_traj    : chr [1:449] "pathviewr_motive_example_data.csv_device02_0" "pathviewr_motive_example_data.csv_device02_0" "pathviewr_motive_example_data.csv_device02_0" "pathviewr_motive_example_data.csv_device02_0" ...
#>  $ traj_length      : int [1:449] 63 63 63 63 63 63 63 63 63 63 ...
#>  $ start_length     : num [1:449] 0.647 0.647 0.647 0.647 0.647 ...
#>  $ end_length       : num [1:449] -0.656 -0.656 -0.656 -0.656 -0.656 ...
#>  $ length_diff      : num [1:449] 1.3 1.3 1.3 1.3 1.3 ...
#>  $ start_length_sign: num [1:449] 1 1 1 1 1 1 1 1 1 1 ...
#>  $ end_length_sign  : num [1:449] -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 ...
#>  $ direction        : chr [1:449] "leftwards" "leftwards" "leftwards" "leftwards" ...
#>  - attr(*, "file_id")= chr "pathviewr_motive_example_data.csv"
#>  - attr(*, "file_mtime")= POSIXct[1:1], format: "2023-03-07 11:12:49"
#>  - attr(*, "frame_rate")= num 100
#>  - attr(*, "header")='data.frame':   11 obs. of  2 variables:
#>   ..$ metadata: chr [1:11] "Format Version" "Take Name" "Take Notes" "Capture Frame Rate" ...
#>   ..$ value   : chr [1:11] "1.23" "sept-18_mixed-group_16-30" "" "100.000000" ...
#>  - attr(*, "Motive_IDs")= chr [1:24] "\"9E207518D8A311E969D7AB6B1FACE49B\"" "\"9E207518D8A311E969D7AB6B1FACE49B\"" "\"9E207518D8A311E969D7AB6B1FACE49B\"" "\"9E207518D8A311E969D7AB6B1FACE49B\"" ...
#>  - attr(*, "subject_names_full")= chr [1:24] "device02" "device02" "device02" "device02" ...
#>  - attr(*, "subject_names_simple")= chr [1:3] "device02" "device03" "device05"
#>  - attr(*, "data_names")= chr [1:26] "frame" "time_sec" "device02_rotation_x" "device02_rotation_y" ...
#>  - attr(*, "data_types_full")= chr [1:24] "Rigid Body" "Rigid Body" "Rigid Body" "Rigid Body" ...
#>  - attr(*, "data_types_simple")= chr "Rigid Body"
#>  - attr(*, "d1")= chr [1:26] "" "" "Rotation" "Rotation" ...
#>  - attr(*, "d2")= chr [1:26] "Frame" "Time (Seconds)" "X" "Y" ...
#>  - attr(*, "import_method")= chr "motive"
#>  - attr(*, "pathviewr_steps")= chr [1:10] "viewr" "renamed_tunnel" "gathered_tunnel" "artifacts_removed" ...
#>  - attr(*, "perch1_midpoint_original")= num [1:3] 0 0.2 0.205
#>  - attr(*, "perch2_midpoint_original")= num [1:3] 2.54 0.24 0.205
#>  - attr(*, "tunnel_centerpoint_original")= num [1:3] 1.27 0.22 0.205
#>  - attr(*, "rotation_degrees")= num 0.902
#>  - attr(*, "rotation_radians")= num 0.0157
#>  - attr(*, "perch1_midpoint_current")= num [1:3] -1.27 4.65e-15 2.05e-01
#>  - attr(*, "perch2_midpoint_current")= num [1:3] 1.27 -4.65e-15 2.05e-01
#>  - attr(*, "percent_selected")= num 50
#>  - attr(*, "full_tunnel_length")= num 2.64
#>  - attr(*, "selected_tunnel_length")= num 1.32
#>  - attr(*, "max_frame_gap")= int [1:3] 1 1 2
#>  - attr(*, "span")= num 0.95
#>  - attr(*, "trajectories_removed")= int 5

An important aspect of how pathviewr defines trajectories is by managing gaps in the data. See the vignette on Managing frame gaps for more information on trajectory definition and frame gaps.

Now that the data is cleaned, 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. For a complete description of these functions, see the vignette on Estimating visual perceptions from tracking data.

Add more info about experiments

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 from this example were recorded in a V-shaped tunnel. Accordingly, the vertex angle and vertex height of the tunnel, along with information about the visual stimuli used during the experiment, will be added to the data to inform calculations of visual perception (next section).

motive_V <- 
  motive_allinone %>%
  insert_treatments(
    tunnel_config = "v",
    perch_2_vertex = 0.4,
    vertex_angle = 90,
    tunnel_length = 2,
    stim_param_lat_pos = 0.1,
    stim_param_lat_neg = 0.1,
    stim_param_end_pos = 0.3,
    stim_param_end_neg = 0.3,
    treatment = "lat10_end_30"
  ) 

Estimate perception of visual stimuli

To calculate the spatial frequency of the visual stimuli as perceived by the subject some distance from the stimuli, we will use get_sf().

This will require two intermediate steps: 1) calculating the minimum distance between a subject and each wall (via calc_min_dist_v()) and 2) estimating the visual angles from the subject’s perspective (get_vis_angle()).

motive_V_sf <- 
  motive_V %>%
  calc_min_dist_v(simplify_output = TRUE) %>%
  get_vis_angle() %>%
  get_sf()

Visualizing the calculations provides an more intuitive understanding of how these visual perceptions change as the subject moves throughout the tunnel. Please see the vignette on Estimating visual perceptions from tracking data for more examples of visualizing calculations.

ggplot(motive_V_sf, aes(x = position_width, y = position_height)) +
  geom_point(aes(color = sf_pos), shape=1, size=3) +
  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)) +
  coord_fixed() +
  theme_classic() +
  theme(
    legend.position = "none"
  )

Contributing and/or raising Issues

We welcome feedback on bugs, improvements, and/or feature requests. Please see our Issues templates on GitHub to make a bug fix request or feature request.

To contribute code via a pull request, please consult our Contributing Guide first.

Citation

The preferred way to cite pathviewr (but subject to change) is:

Baliga VB, Armstrong MS, Press ER (2021). pathviewr: Tools to import, clean, and visualize animal movement data in R. R package version 1.1.7, https://github.com/ropensci/pathviewr. doi: 10.5281/zenodo.4270187

License

GPL (>= 3) + file LICENSE

🐢

pathviewr's People

Contributors

actions-user avatar epress12 avatar scienceisfiction avatar vbaliga avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

Forkers

epress12 lab-star

pathviewr's Issues

Package writing guidelines & resources

Formerly stored in our README, now here for reference:

Some notes on organization

  • The /R folder is for function scripts (and accompanying roxygen2 documentation) only. Please do not add example scripts or any other files in this folder
  • The /example_scripts is meant to house scripts that we write to not only showcase our functions to each other but also have examples we can run through to make sure things are working properly. This will be taken to an advanced level via the testthat package later on.

Guidelines for writing code

These are informed by the rOpenSci guide as well as my personal opinion

  • Always spell out TRUE and FALSE entirely, e.g. use argument = TRUE instead of argument = T
  • Limit line lengths to no more than 80 characters
    • In RStudio, I recommend going to Tools -> Global Options -> Code -> Display, then check the box next to Show margin and set Margin column to 80. This will generate a vertical guide line to point out where 80 characters is in your scripts.
  • Use snake_case for naming all functions, arguments, and variables
    • Try to go with object_verb() or verb_object() naming schemes for functions when possible, e.g. stri_join() or read_csv()
    • Try to avoid using function names that appear in other packages, esp those in popular packages like ggplot2 or dplyr, e.g. don't make a read_csv()
  • To auto-generate the Help file (and other useful stuff) we will rely on the roxygen2 package. This will entail adding roxygen-style comments above each of our functions. Here is a useful vignette on the topic.
  • Anywhere you rely on a function from another package, you must use explicit naming in a package_name::function() format, e.g. readxl::read_excel()
  • Avoid acronyms whenever possible unless something is more commonly known by its acronym (e.g. "csv")
  • For functions, make the object/data the first argument whenever possible to allow it to be pipeable (%>%)
  • rOpenSci advises against using <- for assignment and prefers = instead. That said, it's not a big deal so long as you are generally consistent with your choice
  • spelling::spell_check_package() is your best friend

Package writing resources

🐢

`calc_vis_angle()` development and bug fixes

https://github.com/vbaliga/pathviewR/blob/21fded1eaac9da0300abd7a52dfcf44e382b72c1/R/analytical_functions.R#L416

I think I have identified a couple minor bugs in the calculations inside calc_vis_angle(). Take a look at the pdf I have attached here: 2020-07-18_vbb_calc_vis_angle.pdf

Assuming that I have correctly interpreted each object name and then done the math correctly, we might need to revise how certain objects like height_2_screen are being computed. I also think min_dist may not be correct. But it's very possible I am missing something, so I think meeting and going over this stuff together would very much help.

The other thing I am unsure about is how to deal with situations where the stimulus is not perfectly centered around the min_dist. I suspect I am missing something fundamental here though -- would be good to talk to you about this too. But as I say in the pdf, maybe the thing to do ultimately (or in addition) is to use min_dist to calculate how spatial frequency information is modulated overall.

In 21fded1, I inserted some comments within example_calc_vis_angle.R as I was going through the script. Most of these are relatively minor and it might be better to ignore this stuff until we're solid on all the calculations.

Issues with next version of ggplot2

Hi

We preparing the next release of ggplot2 and our reverse dependency checks show that your package is failing with the new version. Looking into it we see that your package reaches into the internal structure of ggplot2 and those have changed in the new version.

You can install the release candidate of ggplot2 using devtools::install_github('tidyverse/[email protected]') to test this out.

We plan to submit ggplot2 by the end of October and hope you can have a fix ready before then

Kind regards
Thomas

roxygen example

https://github.com/vbaliga/pathviewR/blob/51906db8a39b86fef38913872431fed33ddd9c32/R/utility_functions.R#L6

In my two most recent commits (here and here), I added an example of a roxygen block to our relabel_motiv_axes() function. Picked that function because it was one for which it was relatively easy to write a Help file.

As you look at this roxygen block, it may help you to look at the auto-generated Help file that corresponds to it. To access this, run the following:

library(devtools)
install()
library(pathviewR)
?relabel_motiv_axes

What you'll then see is how each subsection within the roxygen block corresponds to a section within the Help file.

If you'd like detailed guides on how this all works, check out the following:
http://r-pkgs.had.co.nz/man.html
https://cran.r-project.org/web/packages/roxygen2/vignettes/rd.html
There are more advanced features, but we can deal with those later.

Let me know if you have any questions/issues!

🐢

The dreaded R 4.0 update & packages we'll need

To ultimately submit this, we'll need the package to work in R 4.0 (and beyond). This new version also changes a lot about R itself (looking at you stringsAsFactors), so it's probably a good idea to update for your own sake. This likely means reinstalling packages, too.

It is also a good time to mention that there are several packages that aid in package writing and ideally we'll be using the same versions of these. To that end, I'll paste below the code I use to install these packages.

Note 1: I tend to prefer the developmental (github) versions over the CRAN versions -- it often helps to get the new features as they roll out. The danger is that a "developmental" version of a package (usually styled as version X.Y.Z.9000) may be buggy or broken. That said, the authors of the packages below tend to recognize what a dick move it would be to push a buggy version of their package to github -- most of these packages are used by thousands of people. So it's (hopefully) unlikely we'll encounter these types of issues.

install.packages("devtools")

## if any of the below fails, just go with the CRAN version via 
## install.packages()

## First restart R (Ctrl + Shift + F10 on Windows or CMD + Shift + F10 on Mac)

remotes::install_github("r-lib/rlang")
devtools::install_github("hadley/tidyverse")
devtools::install_github("r-lib/devtools")

## Again, restart R (Ctrl + Shift + F10 on Windows or CMD + Shift + F10 on Mac)

remotes::install_github("r-lib/remotes")
devtools::install_github("r-lib/usethis")
devtools::install_github("ropenscilabs/available")

## Restart R (Ctrl + Shift + F10 on Windows or CMD + Shift + F10 on Mac)

devtools::install_github("r-lib/testthat")
devtools::install_github("r-lib/pkgdown")
devtools::install_github("klutometis/roxygen")
devtools::install_github("r-lib/roxygen2", force = TRUE)
remotes::install_github('rstudio/rmarkdown')
devtools::install_github("r-lib/usethis")

## Restart R (Ctrl + Shift + F10 on Windows or CMD + Shift + F10 on Mac)

devtools::install_github("mangothecat/goodpractice")
devtools::install_github("ropensci/codemetar")
devtools::install_github("ropensci/spelling")

Note 2: The code below is an excerpt from a larger script I run each time I update R. The full script contains all the other packages I commonly use. I'll attach it to this Issue in case you'd like the whole thing. Gonna attach it as a .txt file because github doesn't support attaching .R files for some reason...

FOR_NEW_R_INSTALLS.txt

Object classes in pathviewR

So I had previously been naming & classifying imported objects as motiv objects, e.g. read_motiv_csv() makes an object of class motiv. Going forward, we might want to drop this convention, especially if we end up integrating data import capabilities from other sources (e.g. Flydra)

One option is to use pathviewR, but perhaps style it as pathviewr. So once data are imported, the resultant object would have class pathviewr. But this convention is a bit more difficult for re-naming our functions like read_motiv_csv() -- I don't think we want to rename that as read_pathviewr_csv().

It would be great to use this Issue thread to brainstorm these naming conventions and come to a consensus

Resources & tutorials on quaternions

At present, it looks like further incorporating rotation data into our functions or analyses is something we'd benefit from doing. To that end, I think this "Issue" would be a good place to stash any resources or tutorials we find on how quaternions work, since Motive exports rotation data in that notation.

This site (and the youtube videos included therein) seem to be a great resource for understanding quaternions:
https://eater.net/quaternions

We need to pick a license

This is a pretty important decision and also one for which I don't claim to have a lot of insight.

When you get a chance, please take a look at our options which can be accessed via: ?usethis::use_gpl3_license() (all the use_x_license() functions seem to point to the same "License a package" help file).

I used GPL (>= 3) for workloopR but that decision was based on: 1) lots of other R packages using that license, and 2) it seemed pretty reasonable.

We should definitely figure this step out together -- curious to see what you think

Automation of `max_frame_gap` argument

https://github.com/vbaliga/pathviewR/blob/f4a043e75cb22e993aebc82790ecd730604b5439/R/utility_functions.R#L1029

I made some changes to how the max_frame_gap argument of separate_trajectories() behaves. The gist:

  • numeric values (e.g. max_frame_gap = 1) can be used and the function basically behaves as it always has. One minor thing: if this value is set too high (e.g. max_frame_gap = 10000000000), then the function internally resets it to the actual maximum frame gap found within the data.
  • alternatively, you can set max_frame_gap = "autodetect" to ask the function to guesstimate this for you.
    • The autodetect procedure, right now, is to generate a list of all frame gaps (on a per-subject basis; I can explain why later) and then filter out all cases where the frame gap is 1 (i.e. things are working normally). From the remaining frame gaps, we then take the median value as a rough estimate of what a max_frame_gap value could be.

That said, I am not sold on the idea of the median observed frame gap being the best value to use.

I'm very enthusiastic about keeping Melissa's determine_fg_M() function in pathviewR (if she's cool with that). At the very least, it is a very useful function for a user to be able to visualize how things change with frame gap choice and not need to blindly trust what we may automate within separate_trajectories().

But I also think that in addition to keeping this standalone plotting function, some of determine_fg_M()'s internals can be added into separate_trajectories(). Automating the max_frame_gap value to be where the "elbow" of the plot is seems like a better way to go vs. choosing the median as I mentioned above.

To that end, I think something like changepoint detection could work. There's even a changepoint package that could be useful here. I have a little experience playing around with this; I'll leave this piece as an example.

Curious to see what you guys think. Also please scream if any changes I made today break stuff for you!

Potential submission venues

Let's keep updating this list as we think of possibilities. I suggest we try to get peer review of code in addition to a "software paper". But depending on how we develop this package, we may try other options. Ideally, it would be good to avoid a publication cost.

Some ideas we've had so far, not necessarily in order:

  • rOpenSci (code peer-review)
  • rOpenSci + Journal of Open Source Software paper
  • rOpenSci + Methods in Ecology and Evolution paper
  • Behavior Research Methods
  • Source Code for Biology and Medicine ($$$)
  • Journal of Neuroscience Methods
  • PLOS Computational Biology ($$$)

Ellipises (...) in functions are improperly passing arguments

https://github.com/vbaliga/pathviewR/blob/76e5d1cded3bf43fee8ff5e54a17d40140cd71ac/example_scripts/pathviewR_pancakes.R#L288

Just noticed this when I ran through pathviewR_pancakes.R. For some reason, the behavior of ellipsis arguments in functions (...) has now changed. The idea behind ... is to allow arguments to be passed to previous steps in our analytical pipeline. For example:

jul_29_percent74 <-
  jul_29_path %>% import_and_clean_viewr(desired_percent = 74)

had previously allowed the desired_percent argument to be changed from its default within the select_x_percent() function (the 6th of the 8 functions in the full pipeline).

Instead, we now get the following error:

Error in data.table::fread(text = readLines(file_con), header = FALSE,  : 
  unused argument (desired_percent = 74)

This could stem from the R 4.0 update, but I haven't seen it explicitly documented anywhere. Or I could just be misunderstanding the situation. Not sure what's up...

[general_feature_request]

Please describe the nature of your feature request.
Is the request to improve the tool(s) currently within pathviewR or to provide a tool that adds to the package's capabilities?

Please explain the feature you would like to use in pathviewR.
Briefly describe the goal of the feature and/or which current aspects of pathviewR relate to your request.

Can you provide an example file to help explain your request?
Data on public repositories are preferred. If that is not an option, please contact one of the pathviewR authors directly.

Are you interested in contributing a function and/or code yourself?
If so, please feel free to make a pull request for us to review.

Additional context
Add any other context or screenshots about the feature request here.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.