diff --git a/.Rbuildignore b/.Rbuildignore
new file mode 100644
index 0000000..d71c833
--- /dev/null
+++ b/.Rbuildignore
@@ -0,0 +1,5 @@
+R/main.R
+^renv$
+^renv\.lock$
+^packrat/
+^\.Rprofile$
diff --git a/.Rprofile b/.Rprofile
new file mode 100644
index 0000000..33877b4
--- /dev/null
+++ b/.Rprofile
@@ -0,0 +1,4 @@
+source("renv/activate.R")
+options(languageserver.formatting_style = function(options) {
+ styler::tidyverse_style()
+})
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..1d4e2cf
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+*.swp
+results/
+renv/library/
+renv/staging/
+.DS_Store
diff --git a/.renv.locl b/.renv.locl
new file mode 100644
index 0000000..3ec462a
--- /dev/null
+++ b/.renv.locl
@@ -0,0 +1,1230 @@
+{
+ "R": {
+ "Version": "3.6.2",
+ "Repositories": [
+ {
+ "Name": "CRAN",
+ "URL": "https://cloud.r-project.org"
+ }
+ ]
+ },
+ "Bioconductor": {
+ "Version": "3.10"
+ },
+ "Packages": {
+ "BH": {
+ "Package": "BH",
+ "Version": "1.72.0-3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "8f9ce74c6417d61f0782cbae5fd2b7b0"
+ },
+ "Biobase": {
+ "Package": "Biobase",
+ "Version": "2.46.0",
+ "Source": "Bioconductor",
+ "Hash": "ddbfe185296ede75aadb84a51724ac88"
+ },
+ "BiocGenerics": {
+ "Package": "BiocGenerics",
+ "Version": "0.32.0",
+ "Source": "Bioconductor",
+ "Hash": "b2dabf833cc349c2cd9cba38de7af085"
+ },
+ "BiocManager": {
+ "Package": "BiocManager",
+ "Version": "1.30.10",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "db75371846625725e221470b310da1d5"
+ },
+ "BiocVersion": {
+ "Package": "BiocVersion",
+ "Version": "3.10.1",
+ "Source": "Bioconductor",
+ "Hash": "b69e4e634db423b8e6c58103d579ec95"
+ },
+ "DBI": {
+ "Package": "DBI",
+ "Version": "1.1.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "4744be45519d675af66c28478720fce5"
+ },
+ "FNN": {
+ "Package": "FNN",
+ "Version": "1.1.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "b56998fff55e4a4b4860ad6e8c67e0f9"
+ },
+ "KernSmooth": {
+ "Package": "KernSmooth",
+ "Version": "2.23-16",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "997471f25a7ed6c782f0090ce52cc63a"
+ },
+ "MASS": {
+ "Package": "MASS",
+ "Version": "7.3-51.4",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "a94714e63996bc284b8795ec50defc07"
+ },
+ "Matrix": {
+ "Package": "Matrix",
+ "Version": "1.2-18",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "08588806cba69f04797dab50627428ed"
+ },
+ "MatrixModels": {
+ "Package": "MatrixModels",
+ "Version": "0.4-1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "d57ac35220b39c591388ab3a080f9cbe"
+ },
+ "R6": {
+ "Package": "R6",
+ "Version": "2.4.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "292b54f8f4b94669b08f94e5acce6be2"
+ },
+ "RANN": {
+ "Package": "RANN",
+ "Version": "2.6.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "d128ea05a972d3e67c6f39de52c72bd7"
+ },
+ "RColorBrewer": {
+ "Package": "RColorBrewer",
+ "Version": "1.1-2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "e031418365a7f7a766181ab5a41a5716"
+ },
+ "ROCR": {
+ "Package": "ROCR",
+ "Version": "1.0-7",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "fd202bb77d2b1b19fb9dcc393d489ef0"
+ },
+ "RSpectra": {
+ "Package": "RSpectra",
+ "Version": "0.16-0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "a41329d24d5a98eaed2bd0159adb1b5f"
+ },
+ "Rcpp": {
+ "Package": "Rcpp",
+ "Version": "1.0.4",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "5ef9c463e30f8aea49c293e4b8d9d7be"
+ },
+ "RcppAnnoy": {
+ "Package": "RcppAnnoy",
+ "Version": "0.0.16",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "076352082c0cd6e24e87649d4e656e2f"
+ },
+ "RcppEigen": {
+ "Package": "RcppEigen",
+ "Version": "0.3.3.7.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "c6faf038ba4346b1de19ad7c99b8f94a"
+ },
+ "RcppProgress": {
+ "Package": "RcppProgress",
+ "Version": "0.4.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "1c0aa18b97e6aaa17f93b8b866c0ace5"
+ },
+ "Rdpack": {
+ "Package": "Rdpack",
+ "Version": "0.11-1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "41999a971efe596c3715f2601030cd79"
+ },
+ "Rtsne": {
+ "Package": "Rtsne",
+ "Version": "0.15",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "f153432c4ca15b937ccfaa40f167c892"
+ },
+ "Seurat": {
+ "Package": "Seurat",
+ "Version": "3.1.4",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "687418116139a0eddade5f43aa85db2f"
+ },
+ "SparseM": {
+ "Package": "SparseM",
+ "Version": "1.78",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "fbe4ac267bf42a91e495cc68ad3f8b63"
+ },
+ "TFisher": {
+ "Package": "TFisher",
+ "Version": "0.2.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "e6b216a490aaae020d2ac09e1e0988b5"
+ },
+ "TH.data": {
+ "Package": "TH.data",
+ "Version": "1.0-10",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "84dffc44f23c419537c1c79cc46347a5"
+ },
+ "ape": {
+ "Package": "ape",
+ "Version": "5.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "35b0c2165569c94550d5e28b5a792b2f"
+ },
+ "askpass": {
+ "Package": "askpass",
+ "Version": "1.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "e8a22846fff485f0be3770c2da758713"
+ },
+ "assertthat": {
+ "Package": "assertthat",
+ "Version": "0.2.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "50c838a310445e954bc13f26f26a6ecf"
+ },
+ "backports": {
+ "Package": "backports",
+ "Version": "1.1.5",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "e9f705633dc932bfd5b02b17a5053a06"
+ },
+ "base64enc": {
+ "Package": "base64enc",
+ "Version": "0.1-3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "543776ae6848fde2f48ff3816d0628bc"
+ },
+ "bibtex": {
+ "Package": "bibtex",
+ "Version": "0.4.2.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "8d96f3da9e7ec851e14e39c0872ad1ab"
+ },
+ "bitops": {
+ "Package": "bitops",
+ "Version": "1.0-6",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "0b118d5900596bae6c4d4865374536a6"
+ },
+ "boot": {
+ "Package": "boot",
+ "Version": "1.3-23",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "f7c819deb39929db5af6c6299f7eb0b5"
+ },
+ "broom": {
+ "Package": "broom",
+ "Version": "0.5.5",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "70ec3aef8a0df13661bf6cc2ff877d61"
+ },
+ "caTools": {
+ "Package": "caTools",
+ "Version": "1.18.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "6f7c1405e500ef25a7c147e860b5fe32"
+ },
+ "callr": {
+ "Package": "callr",
+ "Version": "3.4.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "643163a00cb536454c624883a10ae0bc"
+ },
+ "cellranger": {
+ "Package": "cellranger",
+ "Version": "1.1.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "f61dbaec772ccd2e17705c1e872e9e7c"
+ },
+ "cli": {
+ "Package": "cli",
+ "Version": "2.0.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "ff0becff7bfdfe3f75d29aff8f3172dd"
+ },
+ "clipr": {
+ "Package": "clipr",
+ "Version": "0.7.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "08cf4045c149a0f0eaf405324c7495bd"
+ },
+ "cluster": {
+ "Package": "cluster",
+ "Version": "2.1.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "db63a44aab5aadcb6bf2f129751d129a"
+ },
+ "codetools": {
+ "Package": "codetools",
+ "Version": "0.2-16",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "89cf4b8207269ccf82fbeb6473fd662b"
+ },
+ "colorspace": {
+ "Package": "colorspace",
+ "Version": "1.4-1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "6b436e95723d1f0e861224dd9b094dfb"
+ },
+ "cowplot": {
+ "Package": "cowplot",
+ "Version": "1.0.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "82bae0172ae9d4c4f88a440ad01f73bb"
+ },
+ "crayon": {
+ "Package": "crayon",
+ "Version": "1.3.4",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "0d57bc8e27b7ba9e45dba825ebc0de6b"
+ },
+ "crosstalk": {
+ "Package": "crosstalk",
+ "Version": "1.1.0.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "ae55f5d7c02f0ab43c58dd050694f2b4"
+ },
+ "curl": {
+ "Package": "curl",
+ "Version": "4.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "2b7d10581cc730804e9ed178c8374bd6"
+ },
+ "data.table": {
+ "Package": "data.table",
+ "Version": "1.12.8",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "cd711af60c47207a776213a368626369"
+ },
+ "dbplyr": {
+ "Package": "dbplyr",
+ "Version": "1.4.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "022c8630abecb00f22740d021ab89595"
+ },
+ "desc": {
+ "Package": "desc",
+ "Version": "1.2.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "6c8fe8fa26a23b79949375d372c7b395"
+ },
+ "digest": {
+ "Package": "digest",
+ "Version": "0.6.25",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "f697db7d92b7028c4b3436e9603fb636"
+ },
+ "dplyr": {
+ "Package": "dplyr",
+ "Version": "0.8.5",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "57a42ddf80f429764ff7987128c3fd0a"
+ },
+ "dqrng": {
+ "Package": "dqrng",
+ "Version": "0.2.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "cc0d03e8383d407e9568855f8efbc07d"
+ },
+ "ellipsis": {
+ "Package": "ellipsis",
+ "Version": "0.3.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "7067d90c1c780bfe80c0d497e3d7b49d"
+ },
+ "evaluate": {
+ "Package": "evaluate",
+ "Version": "0.14",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "ec8ca05cffcc70569eaaad8469d2a3a7"
+ },
+ "fansi": {
+ "Package": "fansi",
+ "Version": "0.4.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "7fce217eaaf8016e72065e85c73027b5"
+ },
+ "farver": {
+ "Package": "farver",
+ "Version": "2.0.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "dad6793a5a1f73c8e91f1a1e3e834b05"
+ },
+ "fitdistrplus": {
+ "Package": "fitdistrplus",
+ "Version": "1.0-14",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "690f753a275a336022edcffcec5f9aea"
+ },
+ "forcats": {
+ "Package": "forcats",
+ "Version": "0.5.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "1cb4279e697650f0bd78cd3601ee7576"
+ },
+ "fs": {
+ "Package": "fs",
+ "Version": "1.4.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "0486d00e8a929da0311e01ddc9a3b6c5"
+ },
+ "future": {
+ "Package": "future",
+ "Version": "1.16.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "20c20385da360f28c07364f2d099a6d7"
+ },
+ "future.apply": {
+ "Package": "future.apply",
+ "Version": "1.4.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "a690d4bb5e287dc499229617a944dc39"
+ },
+ "gbRd": {
+ "Package": "gbRd",
+ "Version": "0.4-11",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "dd324973735626ce23e950a5f2d3d8ee"
+ },
+ "gdata": {
+ "Package": "gdata",
+ "Version": "2.18.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "465ccb84427f5fe2c54f8620666db131"
+ },
+ "generics": {
+ "Package": "generics",
+ "Version": "0.0.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "b8cff1d1391fd1ad8b65877f4c7f2e53"
+ },
+ "ggplot2": {
+ "Package": "ggplot2",
+ "Version": "3.3.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "911561e07da928345f1ae2d69f97f3ea"
+ },
+ "ggrepel": {
+ "Package": "ggrepel",
+ "Version": "0.8.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "c013a50b19695daf04853679e1bc105a"
+ },
+ "ggridges": {
+ "Package": "ggridges",
+ "Version": "0.5.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "b5c4e55a3856dff3c05595630a40edfc"
+ },
+ "globals": {
+ "Package": "globals",
+ "Version": "0.12.5",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "e9e529fb7a579ad4b4ff65e052e76ed8"
+ },
+ "glue": {
+ "Package": "glue",
+ "Version": "1.3.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "af1f47b63d1aa2206c1fe4d3db1d9366"
+ },
+ "gplots": {
+ "Package": "gplots",
+ "Version": "3.0.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "8c9dd0fe4766504762688b9f1de3139e"
+ },
+ "gridExtra": {
+ "Package": "gridExtra",
+ "Version": "2.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "7d7f283939f563670a697165b2cf5560"
+ },
+ "gtable": {
+ "Package": "gtable",
+ "Version": "0.3.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "ac5c6baf7822ce8732b343f14c072c4d"
+ },
+ "gtools": {
+ "Package": "gtools",
+ "Version": "3.8.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "0a749b4458d19a54acae93c64e3e7c85"
+ },
+ "haven": {
+ "Package": "haven",
+ "Version": "2.2.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "e3f662e125e9fdffd1ee4e94baea3451"
+ },
+ "hexbin": {
+ "Package": "hexbin",
+ "Version": "1.28.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "3d59212f2814d65dff517e6899813c58"
+ },
+ "highr": {
+ "Package": "highr",
+ "Version": "0.8",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "4dc5bb88961e347a0f4d8aad597cbfac"
+ },
+ "hms": {
+ "Package": "hms",
+ "Version": "0.5.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "726671f634529d470545f9fd1a9d1869"
+ },
+ "htmltools": {
+ "Package": "htmltools",
+ "Version": "0.4.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "2d7691222f82f41e93f6d30f169bd5e1"
+ },
+ "htmlwidgets": {
+ "Package": "htmlwidgets",
+ "Version": "1.5.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "41bace23583fbc25089edae324de2dc3"
+ },
+ "httr": {
+ "Package": "httr",
+ "Version": "1.4.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "7146fea4685b4252ebf478978c75f597"
+ },
+ "ica": {
+ "Package": "ica",
+ "Version": "1.0-2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "95ba9b882bb834ecbdad37338a11f3f8"
+ },
+ "igraph": {
+ "Package": "igraph",
+ "Version": "1.2.5",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "3878c30ce67cdb7f2d7f72554e37f476"
+ },
+ "irlba": {
+ "Package": "irlba",
+ "Version": "2.3.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "a9ad517358000d57022401ef18ee657a"
+ },
+ "isoband": {
+ "Package": "isoband",
+ "Version": "0.2.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "15f6d57a664cd953a31ae4ea61e5e60e"
+ },
+ "jsonlite": {
+ "Package": "jsonlite",
+ "Version": "1.6.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "84b0ee361e2f78d6b7d670db9471c0c5"
+ },
+ "knitr": {
+ "Package": "knitr",
+ "Version": "1.28",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "915a6f0134cdbdf016d7778bc80b2eda"
+ },
+ "labeling": {
+ "Package": "labeling",
+ "Version": "0.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "73832978c1de350df58108c745ed0e3e"
+ },
+ "later": {
+ "Package": "later",
+ "Version": "1.0.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "6d927978fc658d24175ce37db635f9e5"
+ },
+ "lattice": {
+ "Package": "lattice",
+ "Version": "0.20-38",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "848f8c593fd1050371042d18d152e3d7"
+ },
+ "lazyeval": {
+ "Package": "lazyeval",
+ "Version": "0.2.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "d908914ae53b04d4c0c0fd72ecc35370"
+ },
+ "leiden": {
+ "Package": "leiden",
+ "Version": "0.3.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "b558ae02ba3ad5a3f015de3e8208c0a4"
+ },
+ "lifecycle": {
+ "Package": "lifecycle",
+ "Version": "0.2.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "361811f31f71f8a617a9a68bf63f1f42"
+ },
+ "listenv": {
+ "Package": "listenv",
+ "Version": "0.8.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "0bde42ee282efb18c7c4e63822f5b4f7"
+ },
+ "lmtest": {
+ "Package": "lmtest",
+ "Version": "0.9-37",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "c108129ded5ffdb129064ec1d7ba77d0"
+ },
+ "lsei": {
+ "Package": "lsei",
+ "Version": "1.2-0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "75f28bb3d161432f11a63a7a56b1ffdc"
+ },
+ "lubridate": {
+ "Package": "lubridate",
+ "Version": "1.7.4",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "796afeea047cda6bdb308d374a33eeb6"
+ },
+ "magrittr": {
+ "Package": "magrittr",
+ "Version": "1.5",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "1bb58822a20301cee84a41678e25d9b7"
+ },
+ "markdown": {
+ "Package": "markdown",
+ "Version": "1.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "61e4a10781dd00d7d81dd06ca9b94e95"
+ },
+ "metap": {
+ "Package": "metap",
+ "Version": "1.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "618d4f26eaf3cde5b5bb7c40387154e3"
+ },
+ "mgcv": {
+ "Package": "mgcv",
+ "Version": "1.8-31",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "4bb7e0c4f3557583e1e8d3c9ffb8ba5c"
+ },
+ "mime": {
+ "Package": "mime",
+ "Version": "0.9",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "e87a35ec73b157552814869f45a63aa3"
+ },
+ "mnormt": {
+ "Package": "mnormt",
+ "Version": "1.5-6",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "f4c908c3d498f2ed076cb1746dc8b0db"
+ },
+ "modelr": {
+ "Package": "modelr",
+ "Version": "0.1.6",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "30a2db10e829133fa0a1e6eaed25bc73"
+ },
+ "multcomp": {
+ "Package": "multcomp",
+ "Version": "1.4-12",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "0e521fe0d3dac4a951dc927595bf29f6"
+ },
+ "multtest": {
+ "Package": "multtest",
+ "Version": "2.42.0",
+ "Source": "Bioconductor",
+ "Hash": "8dbb186639bbb7580d90f44a1776639f"
+ },
+ "munsell": {
+ "Package": "munsell",
+ "Version": "0.5.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "6dfe8bf774944bd5595785e3229d8771"
+ },
+ "mutoss": {
+ "Package": "mutoss",
+ "Version": "0.1-12",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "0aa141265a2f405ac251e8fb58c0971b"
+ },
+ "mvtnorm": {
+ "Package": "mvtnorm",
+ "Version": "1.1-0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "b4467e29ec60b2d05e361c9141e4fc59"
+ },
+ "nlme": {
+ "Package": "nlme",
+ "Version": "3.1-142",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "557d78d7eac2c1090ee58647a6274142"
+ },
+ "npsurv": {
+ "Package": "npsurv",
+ "Version": "0.4-0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "63576bc6d9730443164d9108c7c05044"
+ },
+ "numDeriv": {
+ "Package": "numDeriv",
+ "Version": "2016.8-1.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "df58958f293b166e4ab885ebcad90e02"
+ },
+ "openssl": {
+ "Package": "openssl",
+ "Version": "1.4.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "49f7258fd86ebeaea1df24d9ded00478"
+ },
+ "patchwork": {
+ "Package": "patchwork",
+ "Version": "1.0.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "16eee5b5edc41eec5af1149ccdc6b2c9"
+ },
+ "pbapply": {
+ "Package": "pbapply",
+ "Version": "1.4-2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "ee90507ce37987b22470fae76325f370"
+ },
+ "pillar": {
+ "Package": "pillar",
+ "Version": "1.4.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "fa3ed60396b6998d0427c57dab90fba4"
+ },
+ "pkgbuild": {
+ "Package": "pkgbuild",
+ "Version": "1.0.6",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "899835dfe286963471cbdb9591f8f94f"
+ },
+ "pkgconfig": {
+ "Package": "pkgconfig",
+ "Version": "2.0.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "01f28d4278f15c76cddbea05899c5d6f"
+ },
+ "pkgload": {
+ "Package": "pkgload",
+ "Version": "1.0.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "5e655fb54cceead0f095f22d7be33da3"
+ },
+ "plogr": {
+ "Package": "plogr",
+ "Version": "0.2.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "09eb987710984fc2905c7129c7d85e65"
+ },
+ "plotly": {
+ "Package": "plotly",
+ "Version": "4.9.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "bee8fe8f97d10023ed3740a9c3e9eb02"
+ },
+ "plotrix": {
+ "Package": "plotrix",
+ "Version": "3.7-7",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "f273659b57b53ead904028360b93ba68"
+ },
+ "plyr": {
+ "Package": "plyr",
+ "Version": "1.8.6",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "ec0e5ab4e5f851f6ef32cd1d1984957f"
+ },
+ "png": {
+ "Package": "png",
+ "Version": "0.1-7",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "03b7076c234cb3331288919983326c55"
+ },
+ "praise": {
+ "Package": "praise",
+ "Version": "1.0.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "a555924add98c99d2f411e37e7d25e9f"
+ },
+ "prettyunits": {
+ "Package": "prettyunits",
+ "Version": "1.1.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "95ef9167b75dde9d2ccc3c7528393e7e"
+ },
+ "processx": {
+ "Package": "processx",
+ "Version": "3.4.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "20a082f2bde0ffcd8755779fd476a274"
+ },
+ "progress": {
+ "Package": "progress",
+ "Version": "1.2.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "14dc9f7a3c91ebb14ec5bb9208a07061"
+ },
+ "promises": {
+ "Package": "promises",
+ "Version": "1.1.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "efbbe62da4709f7040a380c702bc7103"
+ },
+ "ps": {
+ "Package": "ps",
+ "Version": "1.3.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "98777535b61c57d1749344345e2a4ccd"
+ },
+ "purrr": {
+ "Package": "purrr",
+ "Version": "0.3.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "22aca7d1181718e927d403a8c2d69d62"
+ },
+ "quantreg": {
+ "Package": "quantreg",
+ "Version": "5.55",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "dc0f41e5f60efc5fdbdb35a51a4028c5"
+ },
+ "rappdirs": {
+ "Package": "rappdirs",
+ "Version": "0.3.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "8c8298583adbbe76f3c2220eef71bebc"
+ },
+ "readr": {
+ "Package": "readr",
+ "Version": "1.3.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "af8ab99cd936773a148963905736907b"
+ },
+ "readxl": {
+ "Package": "readxl",
+ "Version": "1.3.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "63537c483c2dbec8d9e3183b3735254a"
+ },
+ "rematch": {
+ "Package": "rematch",
+ "Version": "1.0.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "c66b930d20bb6d858cd18e1cebcfae5c"
+ },
+ "renv": {
+ "Package": "renv",
+ "Version": "0.9.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "c1a367437d8a8a44bec4b9d4974cb20c"
+ },
+ "reprex": {
+ "Package": "reprex",
+ "Version": "0.3.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "b06bfb3504cc8a4579fd5567646f745b"
+ },
+ "reshape2": {
+ "Package": "reshape2",
+ "Version": "1.4.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "15a23ad30f51789188e439599559815c"
+ },
+ "reticulate": {
+ "Package": "reticulate",
+ "Version": "1.15",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "ba447f1ad910156609e8e37b52e752e3"
+ },
+ "rlang": {
+ "Package": "rlang",
+ "Version": "0.4.5",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "1cc1b38e4db40ea6eb19ab8080bbed3b"
+ },
+ "rmarkdown": {
+ "Package": "rmarkdown",
+ "Version": "2.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "9d1c61d476c448350c482d6664e1b28b"
+ },
+ "rprojroot": {
+ "Package": "rprojroot",
+ "Version": "1.3-2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "f6a407ae5dd21f6f80a6708bbb6eb3ae"
+ },
+ "rstudioapi": {
+ "Package": "rstudioapi",
+ "Version": "0.11",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "33a5b27a03da82ac4b1d43268f80088a"
+ },
+ "rsvd": {
+ "Package": "rsvd",
+ "Version": "1.0.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "3a6b30449282b6a4b19ce267142c3299"
+ },
+ "rvest": {
+ "Package": "rvest",
+ "Version": "0.3.5",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "6a20c2cdf133ebc7ac45888c9ccc052b"
+ },
+ "sandwich": {
+ "Package": "sandwich",
+ "Version": "2.5-1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "510d1f864cd565d8119801a49db4fd85"
+ },
+ "scales": {
+ "Package": "scales",
+ "Version": "1.1.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "a1c68369c629ea3188d0676e37069c65"
+ },
+ "sctransform": {
+ "Package": "sctransform",
+ "Version": "0.2.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "61f43457038016e2aa1f0fce3867718f"
+ },
+ "selectr": {
+ "Package": "selectr",
+ "Version": "0.4-2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "3838071b66e0c566d55cc26bd6e27bf4"
+ },
+ "sitmo": {
+ "Package": "sitmo",
+ "Version": "2.0.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "0f9ba299f2385e686745b066c6d7a7c4"
+ },
+ "sn": {
+ "Package": "sn",
+ "Version": "1.6-1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "79ba68cf0b686c9f7d24825cd5a8493e"
+ },
+ "stringi": {
+ "Package": "stringi",
+ "Version": "1.4.6",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "e99d8d656980d2dd416a962ae55aec90"
+ },
+ "stringr": {
+ "Package": "stringr",
+ "Version": "1.4.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "0759e6b6c0957edb1311028a49a35e76"
+ },
+ "survival": {
+ "Package": "survival",
+ "Version": "3.1-8",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "ad25122f95d04988f6f79d69aaadd53d"
+ },
+ "sys": {
+ "Package": "sys",
+ "Version": "3.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "507f3116a38d37ad330a038b3be07b66"
+ },
+ "testthat": {
+ "Package": "testthat",
+ "Version": "2.3.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "0829b987b8961fb07f3b1b64a2fbc495"
+ },
+ "tibble": {
+ "Package": "tibble",
+ "Version": "3.0.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "e742bc8d72071ef9aba29f71f132d773"
+ },
+ "tidyr": {
+ "Package": "tidyr",
+ "Version": "1.0.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "fb73a010ace00d6c584c2b53a21b969c"
+ },
+ "tidyselect": {
+ "Package": "tidyselect",
+ "Version": "1.0.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "7d4b0f1ab542d8cb7a40c593a4de2f36"
+ },
+ "tidyverse": {
+ "Package": "tidyverse",
+ "Version": "1.3.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "bd51be662f359fa99021f3d51e911490"
+ },
+ "tinytex": {
+ "Package": "tinytex",
+ "Version": "0.21",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "02e11a2e5d05f1d5ab19394f19ab2999"
+ },
+ "tsne": {
+ "Package": "tsne",
+ "Version": "0.1-3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "7a6f77f5bdfa8a876f4995b8accfa68b"
+ },
+ "utf8": {
+ "Package": "utf8",
+ "Version": "1.1.4",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "4a5081acfb7b81a572e4384a7aaf2af1"
+ },
+ "uwot": {
+ "Package": "uwot",
+ "Version": "0.1.8",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "094c1c4b1dad5a5aa84adafe5cd6d076"
+ },
+ "vctrs": {
+ "Package": "vctrs",
+ "Version": "0.2.4",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "6c839a149a30cb4ffc70443efa74c197"
+ },
+ "viridisLite": {
+ "Package": "viridisLite",
+ "Version": "0.3.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "ce4f6271baa94776db692f1cb2055bee"
+ },
+ "whisker": {
+ "Package": "whisker",
+ "Version": "0.4",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "ca970b96d894e90397ed20637a0c1bbe"
+ },
+ "withr": {
+ "Package": "withr",
+ "Version": "2.1.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "aa57ed55ff2df4bea697a07df528993d"
+ },
+ "writexl": {
+ "Package": "writexl",
+ "Version": "1.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "a012c4b3bbd4e2ef837f045db2ffd2ec"
+ },
+ "xfun": {
+ "Package": "xfun",
+ "Version": "0.12",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "ccd8453a7b9e380628f6cd2862e46cad"
+ },
+ "xml2": {
+ "Package": "xml2",
+ "Version": "1.3.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "415db5714ce4d3f7aa46e0320213a2cb"
+ },
+ "yaml": {
+ "Package": "yaml",
+ "Version": "2.2.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "2826c5d9efb0a88f657c7a679c7106db"
+ },
+ "zoo": {
+ "Package": "zoo",
+ "Version": "1.8-7",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "157e0e442de69a5b00ee5c7066d6184d"
+ }
+ }
+}
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..f288702
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/R/helper_functions.R b/R/helper_functions.R
new file mode 100644
index 0000000..895334c
--- /dev/null
+++ b/R/helper_functions.R
@@ -0,0 +1,99 @@
+#' Find clusters in Seurat object
+#'
+#' This function combines the necessary and sequential calls
+#' to Seurat::FindNeighbors and Seurat::FindClusters
+#'
+#' @param obj Seurat object
+#' @param reduction String naming the reduction for \code{Seurat::FindNeighbors}
+#' @param npcs Integer of number of dimensions for \code{Seurat::FindNeighbors}
+#' @param assay String naming the assay for \code{Seurat::FindNeighbors}
+#' This assay is also used to define features in the default settings
+#' @param features Character vector containing features for \code{Seurat::FindNeighbors}
+#' @param resolution Numeric of resolution to use for \code{Seurat::FindClusters}
+#' @param verbose Boolean controlling verbosity
+#' If \code{TRUE}, print updates to terminal
+#'
+#' @return A Seurat object with the new clusters stored in Idents and the
+#' old clusters stored in \code{seurat_clusters}
+#'
+#' @section Warning:
+#' Each call to this function overwrites \code{seurat_clusters}
+#'
+#' @seealso \url{https://www.rdocumentation.org/packages/Seurat/versions/3.1.0/topics/FindClusters}
+#' and\url{https://www.rdocumentation.org/packages/Seurat/versions/3.1.0/topics/FindNeighbors}
+#' for further documentation on the component functions.
+#'
+#' @examples
+#' data <- find_clusters(obj)
+#' data <- find_clusters(obj, npcs = 30, verbose = TRUE)
+#' \dontrun{
+#' data <- find_clusters()
+#' }
+#' @export
+find_clusters <- function(
+ obj,
+ reduction = "pca",
+ npcs = 100,
+ assay = "integrated",
+ features = NULL,
+ resolution = 0.8,
+ verbose = FALSE) {
+ obj <- Seurat::FindNeighbors(
+ obj,
+ reduction = reduction,
+ dims = 1:npcs,
+ assay = integtrated,
+ features = features,
+ verbose = verbose,
+ graph.name = paste(reduction, assay, sep = ".")
+ )
+ obj <- Seurat::FindClusters(
+ obj,
+ resolution = resolution,
+ graph.name = paste(reduction, assay, sep = "."),
+ verbose = verbose
+ )
+ return(obj)
+}
+
+#' Generate n sub-samples
+#'
+#' Wrapper function around rplicate and split to generate
+#' \code{n} subsamples of size \code{size} from \code{input}
+#'
+#' @param n Integer number of replicates
+#' @param input Vector to be subset
+#' @param size Numeric fraction of input to take for subsample
+#' @param replace Boolean whether to sample with or without replacement
+#' @param simplify Whether to simplify output to array or matrix, if possible
+#'
+#' @return A list of subsamples of \code{input}.
+#' If \code{simplify}, then in a simplfied array or matrix
+#'
+#' @seealso \code{\link[base]{replicate}} and \code{\link[base]{sample}}
+#' for documentation on the component functions.
+#
+#' @examples
+#' n_samples(3, c(1, 3, 5, 2))
+#' n_samples(5, c('a', 'b', 'c'), size = 0.5, replace = TRUE)
+#'
+#' \dontrun{
+#' n_samples(c(1, 2, 3))
+#' }
+#' @export
+n_samples <- function(
+ n,
+ input,
+ size = 0.8,
+ replace = FALSE,
+ simplify = FALSE) {
+ splits <- replicate(
+ n,
+ sample(
+ input,
+ as.integer(length(input) * size),
+ replace = replace
+ ),
+ simplify = simplify
+ )
+}
diff --git a/R/pipeline.R b/R/pipeline.R
new file mode 100644
index 0000000..4b672d7
--- /dev/null
+++ b/R/pipeline.R
@@ -0,0 +1,211 @@
+# Functions used directly in the analysis and example script
+
+source("R/helper_functions.R")
+`%>%` <- magrittr::`%>%`
+
+#' Run multiple clusters on the same Seurat Object
+#'
+#' Given a Seurat object, cluster a random subset of the object n times
+#' This assumes that the object has already been apropriately
+#' normalised, scaled, and reduced.
+#'
+#' @param obj Seurat object containing apropriately preprocessed cells
+#' @param n Integer number of clusterings to perform
+#' @param size Numeric fraction of obj to use for random subset
+#' @param npcs Integer number of dimensions from the reduction to use
+#' @param res Numeric resolution to use for clustering
+#' @param reduction String reduction slot of obj to use for clustering
+#' @param assay String assay slot of obj to use for clustering
+#'
+#' @return clusters dplyr::tibble with cells in first column and clustering
+#' results in consecutive columns
+#'
+#' @examples
+#' results <- multiple_clusters(obj)
+#' results <- multiple_clusters(obj, n = 10, res = 4, reduction = "my_pca")
+#' \dontrun{
+#' multiple_cluster()
+#' }
+#' @export
+multiple_cluster <- function(
+ obj,
+ n = 100,
+ size = 0.8,
+ npcs = 100,
+ res = 1.2,
+ reduction = "pca",
+ assay = "SCT") {
+
+ # Initialise tibble for data
+ clusters <- dplyr::as_tibble(Seurat::Cells(obj))
+ clusters <- dplyr::rename(clusters, "cell" = value)
+
+ # Get samples
+ samples <- n_samples(n, Seurat::Cells(obj), size = size)
+
+ # Repeated clusters
+ j <- 1
+ for (idx in samples) {
+ message(paste0("\tClustering ", j, "..."))
+ small_obj <- obj[, idx]
+ small_obj <- find_clusters(
+ small_obj,
+ reduction = reduction,
+ npcs = npcs,
+ resolution = res,
+ assay = assay
+ )
+ clusters <- dplyr::left_join(
+ clusters,
+ dplyr::as_tibble(Seurat::Idents(small_obj), rownames = "cell"),
+ by = "cell"
+ )
+ j <- j + 1
+ }
+ return(clusters)
+}
+
+#' Find matches for a given clustering resolution
+#'
+#' Given a dataframe where clustering results are stored in columns,
+#' find which cells were included in the same cluster.
+#' This function scores matches as 1 (TRUE), mis-matches as 0 (FALSE)
+#' and drops as 1i (imaginary). This allows further calcualtions to
+#' distinguish between mismatches and drops.
+#'
+#' @param col String column name containing results
+#' @param df Dataframe where each row is a cell and each column is the
+#' results of a clustering
+#'
+#' @return dgCMatrix of dimension \code{n_cells x n_cells} encoding matches
+#'
+#' @examples
+#' find_matches("first_cluster", data)
+#' \dontrun{
+#' find_matches(first_cluster, data)
+#' }
+#' @export
+find_matches <- function(col, df) {
+ mtchs <- outer(df[[col]], df[[col]], "==")
+ # Records drops as imaginary, mtchs as 1, not mtchs as 0
+ mtchs[is.na(mtchs)] <- 1i
+ return(mtchs)
+}
+
+#' Score the number of matches
+#'
+#' Given a complex number x, calculate the fraction of time that it was a match
+#' Assuming the reall part represents matches, the imaginary part represents
+#' drops, and that there were \code{n} repeats
+#'
+#' @param x Complex number encoding the number of matches and drops
+#' @param n Integer number of repeats
+#'
+#' @return Float fraction of times that a match occurred
+#'
+#' @examples
+#' percent_match(5 + 3i, 10)
+#' \dontrun{
+#' percent_match("abc")
+#' }
+#' @export
+percent_match <- function(x, n = 100) {
+ return(Re(x) / (n - Im(x)))
+}
+
+#' Compute group average frequencies
+#'
+#' Given a tibble of pairwise colcustering frequencies, compute the average
+#' pairwise co-clustering frequency for each cluster.
+#'
+#' @param tbl Tibble with pairwise co-clustering frequency per cell
+#' @param clusters Vector of cluster labels. This should be for each
+#' cell. That is, if there are 100 cells, this should have
+#' \code{length(clusters) == 100}
+#'
+#' @return Tibble with clusters in both column and rows.
+#' This format makes it ideal for plotting heatmaps
+#'
+#' @examples
+#' group_scores(data, Seurat::Idents(data))
+#' \dontrun{
+#' group_scores(data, unique(Seurat::Idents(data)))
+#' }
+#' @export
+group_scores <- function(tbl, clusters) {
+ colnames(tbl) <- clusters
+ data <- tbl %>%
+ tibble::add_column("cell_1" = clusters) %>%
+ tidyr::pivot_longer(-cell_1, names_to = "cell_2", values_to = "percent") %>%
+ dplyr::group_by(cell_1, cell_2) %>%
+ dplyr::summarise("avg_percent" = mean(percent)) %>%
+ dplyr::ungroup()
+ return(data)
+}
+
+#' Compute group average silhouette scores
+#'
+#' Given a path to an RDS object containing silhouette scores, calculate the
+#' cluster-wise average silhouette score
+#'
+#' @param sil Silhouette score output
+#' @param res Numeric resolution at which the silhouette score was calculated
+#'
+#' @return Tibble with 3 columns: cluster, avg_sil, and res
+#'
+#' @examples
+#' scores <- group_sil("/path/to/my/silhouette.rds", 0.8)
+#' \dontrun{
+#' group_scores(sil_scores, 1.0)
+#' }
+#' @export
+group_sil <- function(sil, res) {
+ sil <- tibble::as_tibble(sil[, ]) %>%
+ dplyr::group_by(cluster) %>%
+ dplyr::summarise("avg_sil" = mean(sil_width)) %>%
+ tibble::add_column("res" = res)
+ return(sil)
+}
+
+#' Compute confidence intervals on the median
+#'
+#' Given a numeric vector, calculate confidence intervals on the median
+#' The user may specify the interval, number of replicates used for
+#' bootstrapping, and the type of bootstrap to use
+#'
+#' @param x Numeric vector containing distribution of values to analysed
+#' @param interval Numeric confidence interval to calculate. 0 < interval < 1
+#' @param R Integer number of bootstrap replicates to use
+#' @param type String type of confidence interval to calculate
+#'
+#' @return Tibble with clusters in both column and rows.
+#' This format makes it ideal for plotting heatmaps
+#'
+#' @seealso \code{\link[boot]{boot}} and \code{\link[boot]{boot.ci}}
+#' for more information on their parameters and meanings
+#'
+#' @examples
+#' ci <- boot_median(c(1, 2, 3, 4, 5), interval = 0.9)
+#' \dontrun{
+#' group_scores(1, 2, 3, 4, 5)
+#' }
+#' @export
+boot_median <- function(x, interval = 0.95, R = 25000, type = "bca") {
+ # Define median to take data and indices for use with boot::
+ med <- function(data, indices) {
+ resample <- data[indices]
+ return(median(resample))
+ }
+
+ # Calculate intervals
+ boot_data <- boot::boot(data = x, statistic = med, R = R)
+ boot_ci <- boot::boot.ci(boot_data, conf = interval, type = type)
+
+ # Extract desired statistics
+ ci <- list(
+ low_med = boot_ci$bca[4],
+ med = boot_ci$t0,
+ high_med = boot_ci$bca[5]
+ )
+ return(ci)
+}
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..4ca0668
--- /dev/null
+++ b/README.md
@@ -0,0 +1,41 @@
+# Guided selection of single cell clustering parameters through sub-sampling cluster robustness metrics
+
+This repository contains an example implementation in `R` using `Seurat` of the framework outlined in:
+
+> Patterson-Cross, R.B., Levin, A.J. & Menon, V. Guided selection of single cell clustering parameters through sub-sampling cluster robustness metrics. (2020).
+
+## Installation
+
+To use the code and examples in the repository, first clone the repository to your computer:
+
+```bash
+git clone https://github.com/rbpatt2019/cluster.stability.git
+```
+
+The code is implemeted in R, and the dependencies are pinned in the `renv.lock` file. To install dependencies, open an R terminal, then proceed as follows:
+
+```R
+install.packages("renv") # Not necessary if already installed
+renv::init()
+```
+
+This will create a local project and install the dependencies there, rather than into your global `R` installation.
+
+## Usage
+
+Two example scripts are included in this repo. The [first](./examples/1_seurat_pipeline.R) runs through the main analysis framework and covers the key steps, including iterative, sub-sampled clustering, calculating the co-clustering frequency matrix, determining the silhouette scores, and creating the silhouette distribution plots.
+The [second](./examples/2_seurat_further_visuaisations.R) covers several additionaly visualisations that we used in the paper and find useful for understanding the patterns and clusters within your data.
+Both these files can be run as stand-alone scripts, as so:
+
+```R
+Rscript examples/1_seurat_pipeline.R
+Rscript examples/2_seurat_further_visuaisations.R
+```
+
+If used this way, they are meant to be run sequentially. Alternatively, they can be opened with any modern IDE or editor for interactive execution.
+
+Additionally, the interested user may directly source the scripts in the `R` directory to create analyses that suit individual needs.
+
+## Data
+
+An example data set is included with this repo. It contains ~500 human PBMCs sequenced with Smart-Seq from [Ding, et al. _Nature Biotechnology_, 2020](https://www.nature.com/articles/s41587-020-0465-8) and is one the datasets detailed in our paper. The RDS included in the `data` directory has already been normalised and had PCAs calculated using Seurat's `SCTransform` and `RunPCA` functions. If you are using your own data, be sure to normalise and calculate PCAs first.
diff --git a/data/ding_smartseq_pbmc_preprocessed.rds b/data/ding_smartseq_pbmc_preprocessed.rds
new file mode 100644
index 0000000..78ba9cd
Binary files /dev/null and b/data/ding_smartseq_pbmc_preprocessed.rds differ
diff --git a/examples/1_seurat_pipeline.R b/examples/1_seurat_pipeline.R
new file mode 100644
index 0000000..4c6216e
--- /dev/null
+++ b/examples/1_seurat_pipeline.R
@@ -0,0 +1,181 @@
+source("R/pipeline.R")
+library(Seurat)
+library(ggplot2)
+`%>%` <- magrittr::`%>%`
+
+# Load Seurat object
+# Make sure this has already been normalised and that PCA has been performed
+# The data included here is the Ding, et al., Nature Biotechnology, 2020
+# human PBMC Smart-Seq data from our manuscript
+obj <- readRDS("data/ding_smartseq_pbmc_preprocessed.rds")
+
+# Define the number of PCs to use, and which assay and reduction to use.
+# We recommend testing a broad range of resolutions
+# For more on picking the correct number of PCs, see:
+# https://satijalab.org/seurat/v3.1/pbmc3k_tutorial.html
+npcs <- 100
+resolutions <- c(0.8, 1, 1.2, 1.6, 2, 4, 6, 8, 12, 16)
+assay <- "SCT"
+reduction <- "pca"
+results_path <- "results/"
+
+# Run pipeline
+for (res in resolutions) {
+ message(paste0("Clustering ", res, "..."))
+ message("\tFinding ground truth...")
+
+ # "Truths" will be stored at glue::glue("{reduction}.{assay}_res.{res}")
+ obj <- find_clusters(
+ obj,
+ reduction = reduction,
+ assay = assay,
+ resolution = res
+ )
+ clusters <- obj[[glue::glue("{reduction}.{assay}_res.{res}")]]
+
+ # Now perform iterative, sub-sampled clusters
+ results <- multiple_cluster(
+ obj,
+ n = 100,
+ size = 0.8,
+ npcs = npcs,
+ res = res,
+ reduction = reduction,
+ assay = assay
+ )
+
+ # Now calculate the co-clustering frequencies
+ message(paste0("Tallying ", res, "..."))
+ # This is the more time efficient vectorisation
+ # However, it exhausts vector memory for (nearly) all datasets
+ # matches <- purrr::map(columns, find_matches, df = results)
+ # matches <- purrr::reduce(matches, `+`)
+ columns <- colnames(dplyr::select(results, -cell))
+ mtchs <- matrix(0, nrow = dim(results)[1], ncol = dim(results)[1])
+ i <- 1 # Counter
+ for (col in columns) {
+ message(paste0("\tRound ", i, "..."))
+ mtchs <- Reduce("+", list(
+ mtchs,
+ find_matches(col, df = results)
+ ))
+ i <- i + 1
+ }
+
+ message(paste0("Scoring ", res, "..."))
+ mtchs <- dplyr::mutate_all(
+ dplyr::as_tibble(mtchs),
+ function(x) dplyr::if_else(Re(x) > 0, percent_match(x), 0)
+ )
+
+ # Now calculate silhouette scores
+ message(paste0("Silhouette ", res, "..."))
+ sil <- cluster::silhouette(
+ x = as.numeric(as.character(unlist(clusters))),
+ dmatrix = (1 - as.matrix(mtchs))
+ )
+ saveRDS(sil, paste0(results_path, "silhouette_", res, ".rds"))
+
+ # Finally, calculate grouped metrics
+ message(paste0("Grouping ", res, "..."))
+ grp <- group_scores(mtchs, unlist(clusters))
+ saveRDS(grp, paste0(results_path, "frequency_grouped_", res, ".rds"))
+ sil <- group_sil(sil, res)
+ saveRDS(sil, paste0(results_path, "silhouette_grouped_", res, ".rds"))
+}
+
+# Save original data, with ground truth labels
+saveRDS(obj, paste0(results_path, "clustered_data.rds"))
+
+# Create silhouette plot
+# Read in scores and calculate CIs
+scores <- purrr::map(
+ paste0(results_path, "silhouette_grouped_", resolutions, ".rds"),
+ readRDS
+)
+scores <- dplyr::bind_rows(scores)
+meds <- scores %>%
+ dplyr::group_by(res) %>%
+ dplyr::summarise("boot" = list(boot_median(avg_sil))) %>%
+ tidyr::unnest_wider(boot)
+
+writexl::write_xlsx(meds, paste0(results_path, "median_ci.xlsx"))
+
+# Find thresholds
+threshold <- max(meds$low_med)
+choice <- as.character(
+ meds %>% dplyr::filter(med >= threshold) %>% tail(n = 1) %>% dplyr::pull(res)
+)
+
+# And plot!
+ggplot(meds, aes(factor(res), med)) +
+ geom_crossbar(
+ aes(ymin = low_med, ymax = high_med),
+ fill = "grey",
+ size = 0.25
+ ) +
+ geom_hline(aes(yintercept = threshold), colour = "blue") +
+ geom_vline(aes(xintercept = choice), colour = "red") +
+ geom_jitter(
+ data = scores,
+ aes(factor(res), avg_sil),
+ size = 0.35,
+ width = 0.15
+ ) +
+ scale_x_discrete("Resolution") +
+ scale_y_continuous(
+ "Silhouette Score",
+ expand = c(0, 0),
+ limits = c(-1, 1),
+ breaks = seq(-1, 1, 0.25),
+ oob = scales::squish
+ ) +
+ cowplot::theme_minimal_hgrid() +
+ theme(
+ axis.title = element_text(size = 8),
+ axis.text = element_text(size = 7),
+ axis.line.x = element_line(colour = "black"),
+ axis.line.y = element_line(colour = "black"),
+ axis.ticks = element_line(colour = "black"),
+ )
+
+ggsave(
+ filename = paste0(results_path, "silhouette_distribution_plot.png"),
+ dpi = 300,
+ height = 3.5,
+ width = 3.5,
+ units = "in"
+)
+
+# Finally, a dot plot of silhouette scores to help identify less robust clusters
+# The initial pipe is to order the clusters by silhouette score
+scores %>%
+ dplyr::filter(res == choice) %>%
+ dplyr::arrange(dplyr::desc(avg_sil)) %>%
+ dplyr::mutate_at("cluster", ordered, levels = .$cluster) %>%
+ ggplot(aes(factor(cluster), avg_sil)) +
+ geom_point() +
+ scale_x_discrete("Cluster") +
+ scale_y_continuous(
+ "Silhouette Score",
+ expand = c(0, 0),
+ limits = c(-1, 1),
+ breaks = seq(-1, 1, 0.25),
+ oob = scales::squish
+ ) +
+ cowplot::theme_minimal_grid() +
+ theme(
+ axis.title = element_text(size = 8),
+ axis.text = element_text(size = 7),
+ axis.line.x = element_line(colour = "black"),
+ axis.line.y = element_line(colour = "black"),
+ axis.ticks = element_line(colour = "black"),
+ )
+
+ggsave(
+ filename = paste0(results_path, "silhouette_point_plot_", choice, ".png"),
+ dpi = 300,
+ height = 3.5,
+ width = 3.5,
+ units = "in"
+)
diff --git a/examples/2_seurat_further_visuaisations.R b/examples/2_seurat_further_visuaisations.R
new file mode 100644
index 0000000..05af74e
--- /dev/null
+++ b/examples/2_seurat_further_visuaisations.R
@@ -0,0 +1,189 @@
+library(Seurat)
+library(tidyverse)
+
+# Currently, running ggsave with Rscript produces spurious pdfs.
+# To prevent this, all plots are caught and saved directly
+# Call print(plot) at any point to see your plot!
+
+# Define sommon common variables
+# choice is the res elected by the pipeline in examples/1_seurat_pipeline.R
+# Be sure to change your path as necessary!
+reduction <- "pca"
+assay <- "SCT"
+choice <- 1.6
+results_path <- "results/"
+
+# Load in the object containing the clustered results
+obj <- readRDS(paste0(results_path, "clustered_data.rds"))
+
+# First is a cluster average co-clustering heatmap
+# Read the data
+grp <- readRDS(paste0(results_path, "frequency_grouped_", choice, ".rds"))
+
+# As the data is symmetrical, we do not need the upper triangle
+grp <- grp %>%
+ pivot_wider(names_from = "cell_2", values_from = "avg_percent") %>%
+ select(str_sort(colnames(.), numeric = T)) %>%
+ column_to_rownames("cell_1")
+grp[lower.tri(grp)] <- NA
+grp <- grp %>%
+ as_tibble(rownames = "cell_1") %>%
+ pivot_longer(-cell_1, names_to = "cell_2", values_to = "avg_percent") %>%
+ mutate_at("cell_2", ordered, levels = unique(.$cell_1)) %>%
+ mutate_at("cell_1", ordered, levels = unique(.$cell_1))
+
+# And plot!
+plot <- ggplot(grp, aes(factor(cell_1), cell_2, fill = avg_percent)) +
+ geom_tile() +
+ scale_x_discrete("Cluster", expand = c(0, 0)) +
+ scale_y_discrete(
+ "Cluster",
+ limits = rev(levels(grp$cell_2)),
+ expand = c(0, 0)
+ ) +
+ scale_fill_distiller(
+ " ",
+ limits = c(0, 1),
+ breaks = c(0, 0.5, 1),
+ palette = "RdYlBu",
+ na.value = "white"
+ ) +
+ coord_fixed() +
+ theme(
+ axis.ticks = element_line(colour = "black"),
+ axis.text = element_text(size = 6),
+ axis.title = element_text(size = 8),
+ legend.text = element_text(size = 7),
+ legend.position = c(0.9, 0.9)
+ ) +
+ guides(fill = guide_colorbar(barheight = 3, barwidth = 1))
+
+ggsave(
+ plot = plot,
+ filename = paste0(results_path, "coclustering_heatmap_", choice, ".png"),
+ dpi = 300,
+ height = 3.5,
+ width = 3.5,
+ units = "in"
+)
+
+# Let's add the silhouette scores to the Seurat object!
+sil_scores <- readRDS(paste0(results_path, "silhouette_", choice, ".rds"))
+sil_scores <- as.data.frame(sil_scores[, 3], row.names = Seurat::Cells(obj))
+colnames(sil_scores) <- c("sil_score")
+obj <- AddMetaData(obj, metadata = sil_scores)
+
+# Let's visualise the selected cluster
+# If your data has known clusters, you could also visualise those!
+# Remember, truths are in "glue({reduction}.{assay}_res.{choice})"
+# Seurat Changes color scheme if you order your data, so we provide
+# the following helper function to restore defaults
+gg_color <- function(n) {
+ hues <- seq(15, 375, length = n + 1)
+ colours <- hcl(h = hues, c = 100, l = 65)[1:n]
+ return(colours)
+}
+
+plot <- DimPlot(
+ obj,
+ reduction = "umap",
+ group.by = glue::glue("{reduction}.{assay}_res.{choice}"),
+ pt.size = 0.5,
+ # cols = gg_color(6) # Only necessary if you have ordered your clusters
+)
+
+ggsave(
+ plot = plot,
+ filename = paste0(results_path, choice, "_cluster_umap.png"),
+ dpi = 300,
+ height = 5,
+ width = 5,
+ units = "in"
+)
+
+# We also find it useful to visualise the silhouette scores on the UMAP!
+plot <- FeaturePlot(
+ obj,
+ "sil_score",
+ reduction = "umap",
+ pt.size = 0.5,
+ min.cutoff = -1,
+ max.cutoff = 1
+) +
+ scale_colour_distiller(
+ palette = "RdYlBu",
+ labels = c(-1, 0, 1),
+ breaks = c(-1, 0, 1),
+ limits = c(-1, 1)
+ )
+
+ggsave(
+ plot = plot,
+ filename = paste0(results_path, choice, "_silhouette_umap.png"),
+ dpi = 300,
+ height = 5,
+ width = 5,
+ units = "in"
+)
+
+# This dataset does have annotated cell types, so we can create a heatmap
+# to see how well they line up. Remember, "truths" will always be in
+# glue::glue("{reduction}.{assay}_res.{choice}"), but annotated cell types
+# might be in different locations. Be sure to change the names as needed.
+ids <- as_tibble(
+ obj[[c(glue::glue("{reduction}.{assay}_res.{choice}"), "CellType")]]
+ ) %>%
+ mutate_at(
+ c(glue::glue("{reduction}.{assay}_res.{choice}"), "CellType"),
+ as.factor
+ ) %>%
+ group_by(pca.SCT_res.1.6, CellType) %>%
+ summarise("count" = n()) %>%
+ ungroup() %>%
+ complete(pca.SCT_res.1.6, CellType, fill = list("count" = 0)) %>%
+ # Count suggested clusters
+ group_by(pca.SCT_res.1.6) %>%
+ mutate("n_suggested" = sum(count)) %>%
+ ungroup() %>%
+ # Count known clusters
+ group_by(CellType) %>%
+ mutate("n_known" = sum(count)) %>%
+ ungroup() %>%
+ # Calculate statistics
+ mutate("dice" = (2 * count) / (n_suggested + n_known)) %>%
+ mutate(
+ "pca.SCT_res.1.6" = fct_reorder(pca.SCT_res.1.6, dice, max, .desc = TRUE),
+ "CellType" = fct_reorder(CellType, dice, max, .desc = TRUE)
+ )
+
+plot <- ggplot(ids, aes(pca.SCT_res.1.6, CellType, fill = dice)) +
+ geom_tile() +
+ scale_x_discrete("Suggested Clusters", expand = c(0, 0)) +
+ scale_y_discrete(
+ "Known Clusters",
+ limits = rev(levels(ids$CellType)),
+ expand = c(0, 0)
+ ) +
+ coord_fixed() +
+ scale_fill_distiller(
+ NULL,
+ limits = c(0, 1),
+ breaks = c(0, 0.5, 1),
+ palette = "RdYlBu"
+ ) +
+ theme(
+ axis.ticks = element_line(colour = "black"),
+ axis.text = element_text(size = 6),
+ axis.title = element_text(size = 8),
+ legend.text = element_text(size = 7),
+ ) +
+ guides(fill = guide_colorbar(barheight = 3, barwidth = 0.5))
+
+ggsave(
+ plot = plot,
+ filename = paste0(results_path, "cluster_relation_heatmap.png"),
+ dpi = 300,
+ height = 3.5,
+ width = 3.5,
+ units = "in"
+)
diff --git a/renv.lock b/renv.lock
new file mode 100644
index 0000000..e7540b8
--- /dev/null
+++ b/renv.lock
@@ -0,0 +1,1028 @@
+{
+ "R": {
+ "Version": "3.6.2",
+ "Repositories": [
+ {
+ "Name": "CRAN",
+ "URL": "https://cloud.r-project.org"
+ }
+ ]
+ },
+ "Bioconductor": {
+ "Version": "3.10"
+ },
+ "Packages": {
+ "BH": {
+ "Package": "BH",
+ "Version": "1.72.0-3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "8f9ce74c6417d61f0782cbae5fd2b7b0"
+ },
+ "Biobase": {
+ "Package": "Biobase",
+ "Version": "2.46.0",
+ "Source": "Bioconductor",
+ "Hash": "ddbfe185296ede75aadb84a51724ac88"
+ },
+ "BiocGenerics": {
+ "Package": "BiocGenerics",
+ "Version": "0.32.0",
+ "Source": "Bioconductor",
+ "Hash": "b2dabf833cc349c2cd9cba38de7af085"
+ },
+ "BiocManager": {
+ "Package": "BiocManager",
+ "Version": "1.30.10",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "db75371846625725e221470b310da1d5"
+ },
+ "FNN": {
+ "Package": "FNN",
+ "Version": "1.1.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "b56998fff55e4a4b4860ad6e8c67e0f9"
+ },
+ "KernSmooth": {
+ "Package": "KernSmooth",
+ "Version": "2.23-16",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "997471f25a7ed6c782f0090ce52cc63a"
+ },
+ "MASS": {
+ "Package": "MASS",
+ "Version": "7.3-51.4",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "a94714e63996bc284b8795ec50defc07"
+ },
+ "Matrix": {
+ "Package": "Matrix",
+ "Version": "1.2-18",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "08588806cba69f04797dab50627428ed"
+ },
+ "MatrixModels": {
+ "Package": "MatrixModels",
+ "Version": "0.4-1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "d57ac35220b39c591388ab3a080f9cbe"
+ },
+ "R6": {
+ "Package": "R6",
+ "Version": "2.4.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "292b54f8f4b94669b08f94e5acce6be2"
+ },
+ "RANN": {
+ "Package": "RANN",
+ "Version": "2.6.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "d128ea05a972d3e67c6f39de52c72bd7"
+ },
+ "RColorBrewer": {
+ "Package": "RColorBrewer",
+ "Version": "1.1-2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "e031418365a7f7a766181ab5a41a5716"
+ },
+ "ROCR": {
+ "Package": "ROCR",
+ "Version": "1.0-7",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "fd202bb77d2b1b19fb9dcc393d489ef0"
+ },
+ "RSpectra": {
+ "Package": "RSpectra",
+ "Version": "0.16-0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "a41329d24d5a98eaed2bd0159adb1b5f"
+ },
+ "Rcpp": {
+ "Package": "Rcpp",
+ "Version": "1.0.4",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "5ef9c463e30f8aea49c293e4b8d9d7be"
+ },
+ "RcppAnnoy": {
+ "Package": "RcppAnnoy",
+ "Version": "0.0.16",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "076352082c0cd6e24e87649d4e656e2f"
+ },
+ "RcppEigen": {
+ "Package": "RcppEigen",
+ "Version": "0.3.3.7.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "c6faf038ba4346b1de19ad7c99b8f94a"
+ },
+ "RcppProgress": {
+ "Package": "RcppProgress",
+ "Version": "0.4.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "1c0aa18b97e6aaa17f93b8b866c0ace5"
+ },
+ "Rdpack": {
+ "Package": "Rdpack",
+ "Version": "0.11-1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "41999a971efe596c3715f2601030cd79"
+ },
+ "Rtsne": {
+ "Package": "Rtsne",
+ "Version": "0.15",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "f153432c4ca15b937ccfaa40f167c892"
+ },
+ "Seurat": {
+ "Package": "Seurat",
+ "Version": "3.1.4",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "687418116139a0eddade5f43aa85db2f"
+ },
+ "SparseM": {
+ "Package": "SparseM",
+ "Version": "1.78",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "fbe4ac267bf42a91e495cc68ad3f8b63"
+ },
+ "TFisher": {
+ "Package": "TFisher",
+ "Version": "0.2.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "e6b216a490aaae020d2ac09e1e0988b5"
+ },
+ "TH.data": {
+ "Package": "TH.data",
+ "Version": "1.0-10",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "84dffc44f23c419537c1c79cc46347a5"
+ },
+ "ape": {
+ "Package": "ape",
+ "Version": "5.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "35b0c2165569c94550d5e28b5a792b2f"
+ },
+ "askpass": {
+ "Package": "askpass",
+ "Version": "1.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "e8a22846fff485f0be3770c2da758713"
+ },
+ "assertthat": {
+ "Package": "assertthat",
+ "Version": "0.2.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "50c838a310445e954bc13f26f26a6ecf"
+ },
+ "backports": {
+ "Package": "backports",
+ "Version": "1.1.5",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "e9f705633dc932bfd5b02b17a5053a06"
+ },
+ "base64enc": {
+ "Package": "base64enc",
+ "Version": "0.1-3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "543776ae6848fde2f48ff3816d0628bc"
+ },
+ "bibtex": {
+ "Package": "bibtex",
+ "Version": "0.4.2.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "8d96f3da9e7ec851e14e39c0872ad1ab"
+ },
+ "bitops": {
+ "Package": "bitops",
+ "Version": "1.0-6",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "0b118d5900596bae6c4d4865374536a6"
+ },
+ "boot": {
+ "Package": "boot",
+ "Version": "1.3-23",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "f7c819deb39929db5af6c6299f7eb0b5"
+ },
+ "caTools": {
+ "Package": "caTools",
+ "Version": "1.18.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "6f7c1405e500ef25a7c147e860b5fe32"
+ },
+ "callr": {
+ "Package": "callr",
+ "Version": "3.4.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "643163a00cb536454c624883a10ae0bc"
+ },
+ "cli": {
+ "Package": "cli",
+ "Version": "2.0.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "ff0becff7bfdfe3f75d29aff8f3172dd"
+ },
+ "cluster": {
+ "Package": "cluster",
+ "Version": "2.1.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "db63a44aab5aadcb6bf2f129751d129a"
+ },
+ "codetools": {
+ "Package": "codetools",
+ "Version": "0.2-16",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "89cf4b8207269ccf82fbeb6473fd662b"
+ },
+ "colorspace": {
+ "Package": "colorspace",
+ "Version": "1.4-1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "6b436e95723d1f0e861224dd9b094dfb"
+ },
+ "cowplot": {
+ "Package": "cowplot",
+ "Version": "1.0.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "82bae0172ae9d4c4f88a440ad01f73bb"
+ },
+ "crayon": {
+ "Package": "crayon",
+ "Version": "1.3.4",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "0d57bc8e27b7ba9e45dba825ebc0de6b"
+ },
+ "crosstalk": {
+ "Package": "crosstalk",
+ "Version": "1.1.0.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "ae55f5d7c02f0ab43c58dd050694f2b4"
+ },
+ "curl": {
+ "Package": "curl",
+ "Version": "4.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "2b7d10581cc730804e9ed178c8374bd6"
+ },
+ "data.table": {
+ "Package": "data.table",
+ "Version": "1.12.8",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "cd711af60c47207a776213a368626369"
+ },
+ "desc": {
+ "Package": "desc",
+ "Version": "1.2.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "6c8fe8fa26a23b79949375d372c7b395"
+ },
+ "digest": {
+ "Package": "digest",
+ "Version": "0.6.25",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "f697db7d92b7028c4b3436e9603fb636"
+ },
+ "dplyr": {
+ "Package": "dplyr",
+ "Version": "0.8.5",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "57a42ddf80f429764ff7987128c3fd0a"
+ },
+ "dqrng": {
+ "Package": "dqrng",
+ "Version": "0.2.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "cc0d03e8383d407e9568855f8efbc07d"
+ },
+ "ellipsis": {
+ "Package": "ellipsis",
+ "Version": "0.3.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "7067d90c1c780bfe80c0d497e3d7b49d"
+ },
+ "evaluate": {
+ "Package": "evaluate",
+ "Version": "0.14",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "ec8ca05cffcc70569eaaad8469d2a3a7"
+ },
+ "fansi": {
+ "Package": "fansi",
+ "Version": "0.4.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "7fce217eaaf8016e72065e85c73027b5"
+ },
+ "farver": {
+ "Package": "farver",
+ "Version": "2.0.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "dad6793a5a1f73c8e91f1a1e3e834b05"
+ },
+ "fitdistrplus": {
+ "Package": "fitdistrplus",
+ "Version": "1.0-14",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "690f753a275a336022edcffcec5f9aea"
+ },
+ "future": {
+ "Package": "future",
+ "Version": "1.16.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "20c20385da360f28c07364f2d099a6d7"
+ },
+ "future.apply": {
+ "Package": "future.apply",
+ "Version": "1.4.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "a690d4bb5e287dc499229617a944dc39"
+ },
+ "gbRd": {
+ "Package": "gbRd",
+ "Version": "0.4-11",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "dd324973735626ce23e950a5f2d3d8ee"
+ },
+ "gdata": {
+ "Package": "gdata",
+ "Version": "2.18.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "465ccb84427f5fe2c54f8620666db131"
+ },
+ "ggplot2": {
+ "Package": "ggplot2",
+ "Version": "3.3.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "911561e07da928345f1ae2d69f97f3ea"
+ },
+ "ggrepel": {
+ "Package": "ggrepel",
+ "Version": "0.8.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "c013a50b19695daf04853679e1bc105a"
+ },
+ "ggridges": {
+ "Package": "ggridges",
+ "Version": "0.5.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "b5c4e55a3856dff3c05595630a40edfc"
+ },
+ "globals": {
+ "Package": "globals",
+ "Version": "0.12.5",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "e9e529fb7a579ad4b4ff65e052e76ed8"
+ },
+ "glue": {
+ "Package": "glue",
+ "Version": "1.3.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "af1f47b63d1aa2206c1fe4d3db1d9366"
+ },
+ "gplots": {
+ "Package": "gplots",
+ "Version": "3.0.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "8c9dd0fe4766504762688b9f1de3139e"
+ },
+ "gridExtra": {
+ "Package": "gridExtra",
+ "Version": "2.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "7d7f283939f563670a697165b2cf5560"
+ },
+ "gtable": {
+ "Package": "gtable",
+ "Version": "0.3.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "ac5c6baf7822ce8732b343f14c072c4d"
+ },
+ "gtools": {
+ "Package": "gtools",
+ "Version": "3.8.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "0a749b4458d19a54acae93c64e3e7c85"
+ },
+ "hexbin": {
+ "Package": "hexbin",
+ "Version": "1.28.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "3d59212f2814d65dff517e6899813c58"
+ },
+ "htmltools": {
+ "Package": "htmltools",
+ "Version": "0.4.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "2d7691222f82f41e93f6d30f169bd5e1"
+ },
+ "htmlwidgets": {
+ "Package": "htmlwidgets",
+ "Version": "1.5.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "41bace23583fbc25089edae324de2dc3"
+ },
+ "httr": {
+ "Package": "httr",
+ "Version": "1.4.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "7146fea4685b4252ebf478978c75f597"
+ },
+ "ica": {
+ "Package": "ica",
+ "Version": "1.0-2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "95ba9b882bb834ecbdad37338a11f3f8"
+ },
+ "igraph": {
+ "Package": "igraph",
+ "Version": "1.2.5",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "3878c30ce67cdb7f2d7f72554e37f476"
+ },
+ "irlba": {
+ "Package": "irlba",
+ "Version": "2.3.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "a9ad517358000d57022401ef18ee657a"
+ },
+ "isoband": {
+ "Package": "isoband",
+ "Version": "0.2.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "15f6d57a664cd953a31ae4ea61e5e60e"
+ },
+ "jsonlite": {
+ "Package": "jsonlite",
+ "Version": "1.6.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "84b0ee361e2f78d6b7d670db9471c0c5"
+ },
+ "labeling": {
+ "Package": "labeling",
+ "Version": "0.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "73832978c1de350df58108c745ed0e3e"
+ },
+ "later": {
+ "Package": "later",
+ "Version": "1.0.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "6d927978fc658d24175ce37db635f9e5"
+ },
+ "lattice": {
+ "Package": "lattice",
+ "Version": "0.20-38",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "848f8c593fd1050371042d18d152e3d7"
+ },
+ "lazyeval": {
+ "Package": "lazyeval",
+ "Version": "0.2.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "d908914ae53b04d4c0c0fd72ecc35370"
+ },
+ "leiden": {
+ "Package": "leiden",
+ "Version": "0.3.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "b558ae02ba3ad5a3f015de3e8208c0a4"
+ },
+ "lifecycle": {
+ "Package": "lifecycle",
+ "Version": "0.2.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "361811f31f71f8a617a9a68bf63f1f42"
+ },
+ "listenv": {
+ "Package": "listenv",
+ "Version": "0.8.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "0bde42ee282efb18c7c4e63822f5b4f7"
+ },
+ "lmtest": {
+ "Package": "lmtest",
+ "Version": "0.9-37",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "c108129ded5ffdb129064ec1d7ba77d0"
+ },
+ "lsei": {
+ "Package": "lsei",
+ "Version": "1.2-0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "75f28bb3d161432f11a63a7a56b1ffdc"
+ },
+ "magrittr": {
+ "Package": "magrittr",
+ "Version": "1.5",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "1bb58822a20301cee84a41678e25d9b7"
+ },
+ "metap": {
+ "Package": "metap",
+ "Version": "1.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "618d4f26eaf3cde5b5bb7c40387154e3"
+ },
+ "mgcv": {
+ "Package": "mgcv",
+ "Version": "1.8-31",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "4bb7e0c4f3557583e1e8d3c9ffb8ba5c"
+ },
+ "mime": {
+ "Package": "mime",
+ "Version": "0.9",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "e87a35ec73b157552814869f45a63aa3"
+ },
+ "mnormt": {
+ "Package": "mnormt",
+ "Version": "1.5-6",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "f4c908c3d498f2ed076cb1746dc8b0db"
+ },
+ "multcomp": {
+ "Package": "multcomp",
+ "Version": "1.4-12",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "0e521fe0d3dac4a951dc927595bf29f6"
+ },
+ "multtest": {
+ "Package": "multtest",
+ "Version": "2.42.0",
+ "Source": "Bioconductor",
+ "Hash": "8dbb186639bbb7580d90f44a1776639f"
+ },
+ "munsell": {
+ "Package": "munsell",
+ "Version": "0.5.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "6dfe8bf774944bd5595785e3229d8771"
+ },
+ "mutoss": {
+ "Package": "mutoss",
+ "Version": "0.1-12",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "0aa141265a2f405ac251e8fb58c0971b"
+ },
+ "mvtnorm": {
+ "Package": "mvtnorm",
+ "Version": "1.1-0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "b4467e29ec60b2d05e361c9141e4fc59"
+ },
+ "nlme": {
+ "Package": "nlme",
+ "Version": "3.1-142",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "557d78d7eac2c1090ee58647a6274142"
+ },
+ "npsurv": {
+ "Package": "npsurv",
+ "Version": "0.4-0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "63576bc6d9730443164d9108c7c05044"
+ },
+ "numDeriv": {
+ "Package": "numDeriv",
+ "Version": "2016.8-1.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "df58958f293b166e4ab885ebcad90e02"
+ },
+ "openssl": {
+ "Package": "openssl",
+ "Version": "1.4.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "49f7258fd86ebeaea1df24d9ded00478"
+ },
+ "patchwork": {
+ "Package": "patchwork",
+ "Version": "1.0.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "16eee5b5edc41eec5af1149ccdc6b2c9"
+ },
+ "pbapply": {
+ "Package": "pbapply",
+ "Version": "1.4-2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "ee90507ce37987b22470fae76325f370"
+ },
+ "pillar": {
+ "Package": "pillar",
+ "Version": "1.4.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "fa3ed60396b6998d0427c57dab90fba4"
+ },
+ "pkgbuild": {
+ "Package": "pkgbuild",
+ "Version": "1.0.6",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "899835dfe286963471cbdb9591f8f94f"
+ },
+ "pkgconfig": {
+ "Package": "pkgconfig",
+ "Version": "2.0.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "01f28d4278f15c76cddbea05899c5d6f"
+ },
+ "pkgload": {
+ "Package": "pkgload",
+ "Version": "1.0.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "5e655fb54cceead0f095f22d7be33da3"
+ },
+ "plogr": {
+ "Package": "plogr",
+ "Version": "0.2.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "09eb987710984fc2905c7129c7d85e65"
+ },
+ "plotly": {
+ "Package": "plotly",
+ "Version": "4.9.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "bee8fe8f97d10023ed3740a9c3e9eb02"
+ },
+ "plotrix": {
+ "Package": "plotrix",
+ "Version": "3.7-7",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "f273659b57b53ead904028360b93ba68"
+ },
+ "plyr": {
+ "Package": "plyr",
+ "Version": "1.8.6",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "ec0e5ab4e5f851f6ef32cd1d1984957f"
+ },
+ "png": {
+ "Package": "png",
+ "Version": "0.1-7",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "03b7076c234cb3331288919983326c55"
+ },
+ "praise": {
+ "Package": "praise",
+ "Version": "1.0.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "a555924add98c99d2f411e37e7d25e9f"
+ },
+ "prettyunits": {
+ "Package": "prettyunits",
+ "Version": "1.1.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "95ef9167b75dde9d2ccc3c7528393e7e"
+ },
+ "processx": {
+ "Package": "processx",
+ "Version": "3.4.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "20a082f2bde0ffcd8755779fd476a274"
+ },
+ "promises": {
+ "Package": "promises",
+ "Version": "1.1.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "efbbe62da4709f7040a380c702bc7103"
+ },
+ "ps": {
+ "Package": "ps",
+ "Version": "1.3.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "98777535b61c57d1749344345e2a4ccd"
+ },
+ "purrr": {
+ "Package": "purrr",
+ "Version": "0.3.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "22aca7d1181718e927d403a8c2d69d62"
+ },
+ "quantreg": {
+ "Package": "quantreg",
+ "Version": "5.55",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "dc0f41e5f60efc5fdbdb35a51a4028c5"
+ },
+ "rappdirs": {
+ "Package": "rappdirs",
+ "Version": "0.3.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "8c8298583adbbe76f3c2220eef71bebc"
+ },
+ "renv": {
+ "Package": "renv",
+ "Version": "0.9.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "c1a367437d8a8a44bec4b9d4974cb20c"
+ },
+ "reshape2": {
+ "Package": "reshape2",
+ "Version": "1.4.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "15a23ad30f51789188e439599559815c"
+ },
+ "reticulate": {
+ "Package": "reticulate",
+ "Version": "1.15",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "ba447f1ad910156609e8e37b52e752e3"
+ },
+ "rlang": {
+ "Package": "rlang",
+ "Version": "0.4.5",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "1cc1b38e4db40ea6eb19ab8080bbed3b"
+ },
+ "rprojroot": {
+ "Package": "rprojroot",
+ "Version": "1.3-2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "f6a407ae5dd21f6f80a6708bbb6eb3ae"
+ },
+ "rstudioapi": {
+ "Package": "rstudioapi",
+ "Version": "0.11",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "33a5b27a03da82ac4b1d43268f80088a"
+ },
+ "rsvd": {
+ "Package": "rsvd",
+ "Version": "1.0.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "3a6b30449282b6a4b19ce267142c3299"
+ },
+ "sandwich": {
+ "Package": "sandwich",
+ "Version": "2.5-1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "510d1f864cd565d8119801a49db4fd85"
+ },
+ "scales": {
+ "Package": "scales",
+ "Version": "1.1.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "a1c68369c629ea3188d0676e37069c65"
+ },
+ "sctransform": {
+ "Package": "sctransform",
+ "Version": "0.2.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "61f43457038016e2aa1f0fce3867718f"
+ },
+ "sitmo": {
+ "Package": "sitmo",
+ "Version": "2.0.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "0f9ba299f2385e686745b066c6d7a7c4"
+ },
+ "sn": {
+ "Package": "sn",
+ "Version": "1.6-1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "79ba68cf0b686c9f7d24825cd5a8493e"
+ },
+ "stringi": {
+ "Package": "stringi",
+ "Version": "1.4.6",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "e99d8d656980d2dd416a962ae55aec90"
+ },
+ "stringr": {
+ "Package": "stringr",
+ "Version": "1.4.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "0759e6b6c0957edb1311028a49a35e76"
+ },
+ "survival": {
+ "Package": "survival",
+ "Version": "3.1-8",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "ad25122f95d04988f6f79d69aaadd53d"
+ },
+ "sys": {
+ "Package": "sys",
+ "Version": "3.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "507f3116a38d37ad330a038b3be07b66"
+ },
+ "testthat": {
+ "Package": "testthat",
+ "Version": "2.3.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "0829b987b8961fb07f3b1b64a2fbc495"
+ },
+ "tibble": {
+ "Package": "tibble",
+ "Version": "3.0.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "e742bc8d72071ef9aba29f71f132d773"
+ },
+ "tidyr": {
+ "Package": "tidyr",
+ "Version": "1.0.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "fb73a010ace00d6c584c2b53a21b969c"
+ },
+ "tidyselect": {
+ "Package": "tidyselect",
+ "Version": "1.0.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "7d4b0f1ab542d8cb7a40c593a4de2f36"
+ },
+ "tsne": {
+ "Package": "tsne",
+ "Version": "0.1-3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "7a6f77f5bdfa8a876f4995b8accfa68b"
+ },
+ "utf8": {
+ "Package": "utf8",
+ "Version": "1.1.4",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "4a5081acfb7b81a572e4384a7aaf2af1"
+ },
+ "uwot": {
+ "Package": "uwot",
+ "Version": "0.1.8",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "094c1c4b1dad5a5aa84adafe5cd6d076"
+ },
+ "vctrs": {
+ "Package": "vctrs",
+ "Version": "0.2.4",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "6c839a149a30cb4ffc70443efa74c197"
+ },
+ "viridisLite": {
+ "Package": "viridisLite",
+ "Version": "0.3.0",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "ce4f6271baa94776db692f1cb2055bee"
+ },
+ "withr": {
+ "Package": "withr",
+ "Version": "2.1.2",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "aa57ed55ff2df4bea697a07df528993d"
+ },
+ "writexl": {
+ "Package": "writexl",
+ "Version": "1.3",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "c23be94422411c9ff161c11db8499840"
+ },
+ "yaml": {
+ "Package": "yaml",
+ "Version": "2.2.1",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "2826c5d9efb0a88f657c7a679c7106db"
+ },
+ "zoo": {
+ "Package": "zoo",
+ "Version": "1.8-7",
+ "Source": "Repository",
+ "Repository": "CRAN",
+ "Hash": "157e0e442de69a5b00ee5c7066d6184d"
+ }
+ }
+}
diff --git a/renv/activate.R b/renv/activate.R
new file mode 100644
index 0000000..4baa934
--- /dev/null
+++ b/renv/activate.R
@@ -0,0 +1,185 @@
+
+local({
+
+ # the requested version of renv
+ version <- "0.9.3"
+
+ # avoid recursion
+ if (!is.na(Sys.getenv("RENV_R_INITIALIZING", unset = NA)))
+ return(invisible(TRUE))
+
+ # signal that we're loading renv during R startup
+ Sys.setenv("RENV_R_INITIALIZING" = "true")
+ on.exit(Sys.unsetenv("RENV_R_INITIALIZING"), add = TRUE)
+
+ # signal that we've consented to use renv
+ options(renv.consent = TRUE)
+
+ # load the 'utils' package eagerly -- this ensures that renv shims, which
+ # mask 'utils' packages, will come first on the search path
+ library(utils, lib.loc = .Library)
+
+ # check to see if renv has already been loaded
+ if ("renv" %in% loadedNamespaces()) {
+
+ # if renv has already been loaded, and it's the requested version of renv,
+ # nothing to do
+ spec <- .getNamespaceInfo(.getNamespace("renv"), "spec")
+ if (identical(spec[["version"]], version))
+ return(invisible(TRUE))
+
+ # otherwise, unload and attempt to load the correct version of renv
+ unloadNamespace("renv")
+
+ }
+
+ # construct path to renv in library
+ libpath <- local({
+
+ root <- Sys.getenv("RENV_PATHS_LIBRARY", unset = "renv/library")
+ prefix <- paste("R", getRversion()[1, 1:2], sep = "-")
+
+ # include SVN revision for development versions of R
+ # (to avoid sharing platform-specific artefacts with released versions of R)
+ devel <-
+ identical(R.version[["status"]], "Under development (unstable)") ||
+ identical(R.version[["nickname"]], "Unsuffered Consequences")
+
+ if (devel)
+ prefix <- paste(prefix, R.version[["svn rev"]], sep = "-r")
+
+ file.path(root, prefix, R.version$platform)
+
+ })
+
+ # try to load renv from the project library
+ if (requireNamespace("renv", lib.loc = libpath, quietly = TRUE)) {
+
+ # warn if the version of renv loaded does not match
+ loadedversion <- utils::packageDescription("renv", fields = "Version")
+ if (version != loadedversion) {
+
+ # assume four-component versions are from GitHub; three-component
+ # versions are from CRAN
+ components <- strsplit(loadedversion, "[.-]")[[1]]
+ remote <- if (length(components) == 4L)
+ paste("rstudio/renv", loadedversion, sep = "@")
+ else
+ paste("renv", loadedversion, sep = "@")
+
+ fmt <- paste(
+ "renv %1$s was loaded from project library, but renv %2$s is recorded in lockfile.",
+ "Use `renv::record(\"%3$s\")` to record this version in the lockfile.",
+ "Use `renv::restore(packages = \"renv\")` to install renv %2$s into the project library.",
+ sep = "\n"
+ )
+
+ msg <- sprintf(fmt, loadedversion, version, remote)
+ warning(msg, call. = FALSE)
+
+ }
+
+ # load the project
+ return(renv::load())
+
+ }
+
+ # failed to find renv locally; we'll try to install from GitHub.
+ # first, set up download options as appropriate (try to use GITHUB_PAT)
+ install_renv <- function() {
+
+ message("Failed to find installation of renv -- attempting to bootstrap...")
+
+ # ensure .Rprofile doesn't get executed
+ rpu <- Sys.getenv("R_PROFILE_USER", unset = NA)
+ Sys.setenv(R_PROFILE_USER = "")
+ on.exit({
+ if (is.na(rpu))
+ Sys.unsetenv("R_PROFILE_USER")
+ else
+ Sys.setenv(R_PROFILE_USER = rpu)
+ }, add = TRUE)
+
+ # prepare download options
+ pat <- Sys.getenv("GITHUB_PAT")
+ if (nzchar(Sys.which("curl")) && nzchar(pat)) {
+ fmt <- "--location --fail --header \"Authorization: token %s\""
+ extra <- sprintf(fmt, pat)
+ saved <- options("download.file.method", "download.file.extra")
+ options(download.file.method = "curl", download.file.extra = extra)
+ on.exit(do.call(base::options, saved), add = TRUE)
+ } else if (nzchar(Sys.which("wget")) && nzchar(pat)) {
+ fmt <- "--header=\"Authorization: token %s\""
+ extra <- sprintf(fmt, pat)
+ saved <- options("download.file.method", "download.file.extra")
+ options(download.file.method = "wget", download.file.extra = extra)
+ on.exit(do.call(base::options, saved), add = TRUE)
+ }
+
+ # fix up repos
+ repos <- getOption("repos")
+ on.exit(options(repos = repos), add = TRUE)
+ repos[repos == "@CRAN@"] <- "https://cloud.r-project.org"
+ options(repos = repos)
+
+ # check for renv on CRAN matching this version
+ db <- as.data.frame(available.packages(), stringsAsFactors = FALSE)
+ if ("renv" %in% rownames(db)) {
+ entry <- db["renv", ]
+ if (identical(entry$Version, version)) {
+ message("* Installing renv ", version, " ... ", appendLF = FALSE)
+ dir.create(libpath, showWarnings = FALSE, recursive = TRUE)
+ utils::install.packages("renv", lib = libpath, quiet = TRUE)
+ message("Done!")
+ return(TRUE)
+ }
+ }
+
+ # try to download renv
+ message("* Downloading renv ", version, " ... ", appendLF = FALSE)
+ prefix <- "https://api.github.com"
+ url <- file.path(prefix, "repos/rstudio/renv/tarball", version)
+ destfile <- tempfile("renv-", fileext = ".tar.gz")
+ on.exit(unlink(destfile), add = TRUE)
+ utils::download.file(url, destfile = destfile, mode = "wb", quiet = TRUE)
+ message("Done!")
+
+ # attempt to install it into project library
+ message("* Installing renv ", version, " ... ", appendLF = FALSE)
+ dir.create(libpath, showWarnings = FALSE, recursive = TRUE)
+
+ # invoke using system2 so we can capture and report output
+ bin <- R.home("bin")
+ exe <- if (Sys.info()[["sysname"]] == "Windows") "R.exe" else "R"
+ r <- file.path(bin, exe)
+ args <- c("--vanilla", "CMD", "INSTALL", "-l", shQuote(libpath), shQuote(destfile))
+ output <- system2(r, args, stdout = TRUE, stderr = TRUE)
+ message("Done!")
+
+ # check for successful install
+ status <- attr(output, "status")
+ if (is.numeric(status) && !identical(status, 0L)) {
+ text <- c("Error installing renv", "=====================", output)
+ writeLines(text, con = stderr())
+ }
+
+
+ }
+
+ try(install_renv())
+
+ # try again to load
+ if (requireNamespace("renv", lib.loc = libpath, quietly = TRUE)) {
+ message("Successfully installed and loaded renv ", version, ".")
+ return(renv::load())
+ }
+
+ # failed to download or load renv; warn the user
+ msg <- c(
+ "Failed to find an renv installation: the project will not be loaded.",
+ "Use `renv::activate()` to re-initialize the project."
+ )
+
+ warning(paste(msg, collapse = "\n"), call. = FALSE)
+
+})
diff --git a/renv/settings.dcf b/renv/settings.dcf
new file mode 100644
index 0000000..bba46f4
--- /dev/null
+++ b/renv/settings.dcf
@@ -0,0 +1,6 @@
+external.libraries:
+ignored.packages:
+package.dependency.fields: Imports, Depends, LinkingTo
+snapshot.type: packrat
+use.cache: TRUE
+vcs.ignore.library: TRUE