{"id":30117194,"url":"https://github.com/pabrod/kinematics","last_synced_at":"2025-08-10T10:38:20.868Z","repository":{"id":48480502,"uuid":"386349057","full_name":"PabRod/kinematics","owner":"PabRod","description":"Trajectory analyzer","archived":false,"fork":false,"pushed_at":"2024-08-27T13:57:12.000Z","size":2374,"stargazers_count":1,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-11T23:37:50.432Z","etag":null,"topics":["biology","ethology","kinematics","r"],"latest_commit_sha":null,"homepage":"https://pabrod.github.io/kinematics/","language":"R","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/PabRod.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":"CITATION.cff","codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-07-15T16:03:16.000Z","updated_at":"2024-11-13T15:18:29.000Z","dependencies_parsed_at":"2023-01-20T05:16:02.530Z","dependency_job_id":"4ee910f3-ca65-4be0-a7b0-1f7a94fe5938","html_url":"https://github.com/PabRod/kinematics","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/PabRod/kinematics","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PabRod%2Fkinematics","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PabRod%2Fkinematics/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PabRod%2Fkinematics/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PabRod%2Fkinematics/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/PabRod","download_url":"https://codeload.github.com/PabRod/kinematics/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PabRod%2Fkinematics/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":269712747,"owners_count":24463210,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-10T02:00:08.965Z","response_time":71,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["biology","ethology","kinematics","r"],"created_at":"2025-08-10T10:38:16.445Z","updated_at":"2025-08-10T10:38:20.860Z","avatar_url":"https://github.com/PabRod.png","language":"R","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![CRAN](https://www.r-pkg.org/badges/version/kinematics)](https://cran.r-project.org/web/packages/kinematics/index.html)\n[![Build Status](https://github.com/PabRod/kinematics/workflows/R-CMD-check/badge.svg?branch=main)](https://github.com/PabRod/kinematics/actions)\n[![codecov](https://codecov.io/gh/PabRod/kinematics/graph/badge.svg)](https://codecov.io/gh/PabRod/kinematics)\n[![codecov](https://img.shields.io/badge/lifecycle-stable-brightgreen.svg)](https://lifecycle.r-lib.org/articles/stages.html)\n[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.5107804.svg)](https://doi.org/10.5281/zenodo.5107804)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![fair-software.eu](https://img.shields.io/badge/fair--software.eu-%E2%97%8F%20%20%E2%97%8F%20%20%E2%97%8F%20%20%E2%97%8F%20%20%E2%97%8B-yellow)](https://fair-software.eu)\n[![Downloads](https://cranlogs.r-pkg.org/badges/kinematics)](https://cran.r-project.org/web/packages/kinematics/index.html)\n\n# Kinematics \u003cimg src=\"man/figures/logo.png\" width=\"120\" align=\"right\" /\u003e\n\nAllows analyzing time series representing two-dimensional movements.\nIt accepts a data frame with a time (t), horizontal (x) and vertical (y) \ncoordinate as columns, and returns several dynamical properties such as speed, \nacceleration or curvature.\n\n## Motivation and purpose\n\nThis package was born as a collaboration between a physicist and an\nexperimental biologist. Everything started when our department bought a\nfancy device for tracking the positions of a small organism on a Petri\ndish.\n\nLong story short, the device captured several images per second, and\nmanaged to identify the horizontal and vertical positions of the\norganism under study. The output produced by the software contained time\nseries with values of the sampling times *t*, and the corresponding\ntwo-dimensional positions (*x*, *y*). Unfortunately, this output also\ncontained some obscure and difficult to manage processed data.\n\nWe decided to write our own analysis software for these sampled\ntrajectories, using only the fundamental information about movement\n(that is: *t*, *x* and *y*, see more on section below). This type of\ndata, although inspired by the particular problem of the organism’s\ntracker, is completely general and applicable to any object moving in\ntwo dimensions.\n\nOur package returns different properties of that movement, such as the\ninstantaneous speeds, accelerations and curvatures.\n\n## Impact and citation\n\nThis package has been used in the following research papers:\n\n- Among-individual variation in the swimming behaviour of the amphipod _Gammarus pulex_ under dark and light conditions, [Science of The Total Environment, 2023](https://doi.org/10.1016/j.scitotenv.2023.162177).\n- Effects of the antidepressant fluoxetine on the swimming behaviour of the amphipod _Gammarus pulex_: Comparison of short-term and long-term toxicity in the laboratory and the semi-field, [Science of The Total Environment,\n2023](https://doi.org/10.1016/j.scitotenv.2023.162173).\n\nPlease cite if you use it. You can do this easily with one of these options:\n\n- The `cite this repository` menu in the right tab.\n- The [citation file](./CITATION.cff).\n- If you prefer to copypaste, here you have the APA and BibTex strings:\n\n`Rodríguez-Sánchez, P., \u0026 van den Berg, S. kinematics [Computer software]. https://github.com/PabRod/kinematics`\n\n---\n\n`@software{Rodriguez-Sanchez_kinematics,author = {Rodríguez-Sánchez, Pablo and van den Berg, Sanne},license = {MIT},title = {{kinematics}},url = {https://github.com/PabRod/kinematics}}`\n\n## Installation\n\nThis is an *R* package. [*R*](https://www.r-project.org/) is required,\n[*RStudio*](https://www.rstudio.com/) is recommended.\n\nIn order to use the package, we have to install it. The package is in CRAN, so \nwe can install it easily by typing:\n\n```r\ninstall.packages(\"kinematics\")\n```\n\nAfter installing, we have to attach the package as usual:\n\n```r\nlibrary(kinematics)\n```\n\nAnd we are ready to go!\n\n## In a nutshell\n\nThis package takes trajectories and returns a whole set of kinematical features.\n### Input\n\nThe input is a data frame like the one below (see subsection _Movement and how to store it_ below):\n\n| t     | x         | y         |\n|-------|-----------|-----------|\n| $t_0$ | `\u003cfloat\u003e` | `\u003cfloat\u003e` |\n| $t_1$ | `\u003cfloat\u003e` | `\u003cfloat\u003e` |\n| $t_2$ | `\u003cfloat\u003e` | `\u003cfloat\u003e` |\n| $t_3$ | `\u003cfloat\u003e` | `\u003cfloat\u003e` |\n| ...   | ...       | ...       |\n\n### Output\n\nWhen the input is fed to the `append_dynamics` function, the output extends the original data frame with all the extra dynamical information available in the package:\n\n| t     | x         | y         |  | Velocity   | Acceleration | Curvature | Displacement |\n|-------|-----------|-----------|--|------------|--------------|-----------|:-------------|\n| $t_0$ | `\u003cfloat\u003e` | `\u003cfloat\u003e` |  | `\u003cvector\u003e` | `\u003cvector\u003e`   | `\u003cfloat\u003e` | `\u003cvector\u003e`   |\n| $t_1$ | `\u003cfloat\u003e` | `\u003cfloat\u003e` |  | `\u003cvector\u003e` | `\u003cvector\u003e`   | `\u003cfloat\u003e` | `\u003cvector\u003e`   |\n| $t_2$ | `\u003cfloat\u003e` | `\u003cfloat\u003e` |  | `\u003cvector\u003e` | `\u003cvector\u003e`   | `\u003cfloat\u003e` | `\u003cvector\u003e`   |\n| $t_3$ | `\u003cfloat\u003e` | `\u003cfloat\u003e` |  | `\u003cvector\u003e` | `\u003cvector\u003e`   | `\u003cfloat\u003e` | `\u003cvector\u003e`   |\n| ...   | ...       | ...       |  | ...        | ...          | ...       | ...          |\n\n## Detailed tutorial\n### Movement and how to store it\n\nThis is a package for studying movement. So we need a way of coding\nmovement into an object. This is R, so you guessed it! We’ll code\nmovement in the form of a data frame.\n\nIf you ask a kid to describe what movement is, probably he will trace a\ncurve in the air with the tips of his fingers. And he will be right,\nthat’s movement indeed! The apparently simple idea of “tracing a curve\nwith the tips of your fingers” can be abstracted to the idea of a\nposition that changes on time. One possible way of representing this is\nby a **list of times and their corresponding positions**.\n\nParticularly, our data frames representing movement will have three\ncolumns:\n\n-   The *t* column: representing time\n-   The *x* column: representing the horizontal position at the time *t*\n-   The *y* column: representing the vertical position at the time *t*\n\nA minimal example could be:\n\n```r\nmov \u003c- data.frame(t = c(0, 1, 2, 3, 4), \n                  x = c(0, 1, 2, 3, 4), \n                  y = c(0, 1, 4, 9, 16))\n```\n\nthat represents five steps of what seems to be a parabolic movement:\n\n```r\nplot(mov$x, mov$y, xlab = \"x\", ylab = \"y\")\n```\n\n![](man/figures/parabolic-plot-1.png)\n\nNotice that the insides of the data frame look like below:\n\n```r\n#\u003e   t x  y\n#\u003e 1 0 0  0\n#\u003e 2 1 1  1\n#\u003e 3 2 2  4\n#\u003e 4 3 3  9\n#\u003e 5 4 4 16\n```\n\nwhere each row represents one “footprint”, that is, one snapshot of the\nmovement. For instance, we see that at *t*=2, the position of the\norganism was (x, y) = (2,4).\n\n### Extracting movement properties\n\nMovement has much more properties than just position. Some examples are\nspeed, acceleration, curvature and displacement. The branch of physics\nthat deals with this kind of problems is known as\n[kinematics](https://en.wikipedia.org/wiki/Kinematics). In this package,\nwe implemented some of the classical algorithms of kinematics. We did it\nin what we think is a practical and easy-to-use fashion.\n\n**The function `append_dynamics` is a way of extracting as much movement\nproperties as possible**. If we apply it to `mov`, the resulting data\nframe contains much more columns:\n\n```r\nmov_analyzed \u003c- append_dynamics(mov)\n\n#\u003e   t x  y vx vy   aspeed            ax ay aaccel        curv curv_radius disp_x\n#\u003e 1 0 0  0  1  0 1.000000 -3.420544e-12  2      2 2.000000000     0.50000     NA\n#\u003e 2 1 1  1  1  2 2.236068 -6.539938e-14  2      2 0.178885438     5.59017      1\n#\u003e 3 2 2  4  1  4 4.123106  3.250388e-14  2      2 0.028533603    35.04640      1\n#\u003e 4 3 3  9  1  6 6.082763  2.179979e-14  2      2 0.008886432   112.53111      1\n#\u003e 5 4 4 16  1  8 8.062258 -1.726720e-12  2      2 0.003816453   262.02338      1\n#\u003e   disp_y    adisp\n#\u003e 1     NA       NA\n#\u003e 2      1 1.414214\n#\u003e 3      3 3.162278\n#\u003e 4      5 5.099020\n#\u003e 5      7 7.071068\n```\n\nThese new columns are:\n\n- `vx`, `vy` and `aspeed`: horizontal, vertical and absolute speed.\n- `ax`, `ay`, and `aaccel`: horizontal, vertical and absolute\n  acceleration.\n- `curv` and `curv_radius`: curvature and curvature radius.\n- `disp_x`, `disp_y` and `adisp`: horizontal, vertical and absolute\n  displacement (since previous time step).\n\n#### A note about units\n\nThe units of *x* and *y* are expected to be the same (say, meters). All\nthe new columns derive their units from thse of *t* and *x* that is:\n\n- Speeds’ units are: *x* unit divided by *t* unit.\n- Acceleration’s units are: *x* unit divided by *t* unit squared.\n- Curvature unit is 1 divided by *x* unit.\n- Curvature radius’ unit is the same as *x*.\n- Displacements’ units are the same as *x*.\n\nThe new columns are ready to be analyzed. For example, we can visualize\ncurvature and absolute speed using `ggplot2`:\n\n```r\nlibrary(ggplot2)\nggplot(data = mov_analyzed, \n       mapping = aes(x = x, y = y, col = curv_radius, size = aspeed)) +\n       geom_point() +\n       scale_color_gradient(low=\"blue\", high=\"red\")\n```\n\n![](man/figures/ggplot-1.png)\n\n## More realistic examples\n\n### Parametric equation of movement\n\nA common way of describing movement in physics is by assigning a\nfunction of time to *x* and *y*. For instance, an Archimedean spiral is\nknown to follow the equations below:\n\n$$\nx(t) = t \\cos(t)\n$$\n\n$$\ny(t) = t \\sin(t)\n$$\n\nWe can encode it, and sample at intervals of 0.05 units of time, using\nthe snippet below:\n\n```r\n# Generate the times\nts \u003c- seq(0, 10, by = 0.05)\n\n# Calculate the positions using a function\nxs \u003c- ts * cos(ts)\nys \u003c- ts * sin(ts)\n\n# Store as data frame\nmov \u003c- data.frame(t = ts, \n                  x = xs, \n                  y = ys)\n```\n\nThe data looks like this:\n\n```r\nplot(mov$x, mov$y, xlab = \"x\", ylab = \"y\", asp = 1)\n```\n\n![](man/figures/spiral-plot-1.png)\n\nAnd repeating the analysis shown in the previous example, we can\nsignificantly enrich the features we can see on the data. For instance,\nonce again, we use color to plot curvature radii and size to plot\nabsolute speed.\n\n```r\nmov_analyzed \u003c- append_dynamics(mov)\n\nggplot(data = mov_analyzed, \n       mapping = aes(x = x, y = y, col = curv_radius, size = aspeed)) +\n       geom_point(alpha = 0.5) +\n       coord_fixed() +\n       scale_color_gradient(low=\"blue\", high=\"red\")\n```\n\n![](man/figures/spiral-ggplot-1.png)\n\n### Sampled curve\n\nMuch more interesting examples will come from actual **sampled** data,\nsuch as the ones that our device produced. In that case, we’ll have to\nload the data from whatever external source we used, and transform it to\nthe (t, x, y) data frame format. Sometimes, we’ll also need to clean the\ndata a bit (for instance, removing NAs, artifacts, … you know [the\ndrill](https://cengel.github.io/R-data-wrangling/)).\n\nFor pedagogical purposes, we include an example data set in this\npackage. The curve was traced by a macroinvertebrate called *Asella*\ninside a Petri dish (no animals were harmed in the making of this\npackage).\n\nThis is how it looks after importing and cleaning:\n\n```r\nmov \u003c- kinematics::example_mov\n\nplot(mov$x, mov$y, xlab = \"x\", ylab = \"y\", asp = 1)\n```\n![](man/figures/load-data-1.png)\n\nUsing `append_dynamics` we can extract a lot of significant information:\nAnd this is an example of how our analysis enriches the information\ncontained on it:\n\n```r\nmov_analyzed \u003c- append_dynamics(mov)\n```\nAnd use the power of R to, for instance, make nice plots. Such as this\none that maps acceleration to color and speed to marker size.\n\n```r\nggplot(data = mov_analyzed, \n       mapping = aes(x = x, y = y, col = aaccel, size = aspeed)) +\n       geom_point(alpha = 0.1) +\n       coord_fixed() +\n       scale_color_gradient(low=\"blue\", high=\"red\")\n```\n\n![](man/figures/plot-data-1.png)\n\nOr a histogram about accelerations:\n\n```r\nhist(mov_analyzed$aaccel, \n     breaks = 500, \n     xlab = 'Accelerations', \n     main = 'Acceleration histogram')\n```\n\n![](man/figures/hist-data-1.png)\n\n## Citation\n\nPlease use the information below to compose your citation of this software.\n\n```\nPablo Rodríguez-Sánchez, \u0026 Sanne J.P. van den Berg.\n(2021, July 15). \nPabRod/kinematics \nZenodo. \nhttp://doi.org/10.5281/zenodo.5107804\n```\n\nDifferent citation formats can be automatically generated from [Zenodo](https://doi.org/10.5281/zenodo.5107804).\n\n## Authors\n\n- [Pablo Rodríguez-Sánchez](https://pabrod.github.io)\n- [Sanne J.P. van den Berg](https://www.wur.nl/en/Persons/Sanne-dr.-SJP-Sanne-van-den-Berg.htm)\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE.md](LICENSE) file for details\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpabrod%2Fkinematics","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpabrod%2Fkinematics","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpabrod%2Fkinematics/lists"}