6  jsPsychR Admins


jsPsychAdmin: Functions to help with common administrative tasks for jsPsychR protocols. The goal is to minimize issues and make sure tasks behave in a consistent and reproducible manner.


if (!require('pak')) utils::install.packages('pak'); pak::pkg_install("gorkang/jsPsychAdmin")

You will need a .vault folder with .credentials, data_encrypted.rds and data_public_key.txt.

6.0.1 Common tasks

6.0.1.1 Debug functions

Prints usage and examples, shows help, and loads usage parameters to Global environment.

get_parameters_of_function(name_function = "jsPsychMaker::create_protocol()", 
                           load_parameters = TRUE)

6.0.1.2 Sync and Check all protocols

  # Syncs and checks all
  jsPsychAdmin::download_check_all_protocols(gmail_account = "XYZ@gmail.com",
                                             # Overwrites existing files that changed
                                             ignore_existing = FALSE, 
                                             dont_ask = TRUE,
                                             show_all_messages = TRUE)


  # Just syncs the protocols
  jsPsychHelpeR::sync_server_local(server_folder = "",
                                   local_folder = here::here(paste0("..", "/CSCN-server/protocols/")),
                                   direction = "server_to_local",
                                   only_test = FALSE,
                                   exclude_csv = TRUE, # DO NOT INCLUDE DATA
                                   delete_nonexistent = TRUE,
                                   # If a file already exists, ignore it. Good for data, bad for protocols.
                                   ignore_existing = FALSE, 
                                   dont_ask = TRUE
                                   )

6.0.1.3 CHECK participants all protocols

  # Uses the .credentials file + the public key to unlock the encrypted data_encrypted.rds
  jsPsychAdmin::check_status_participants_protocol()

6.0.1.4 Clean up a DEV protocol

  # Clean up DB and csv files for a test/protocols_DEV/ protocol # Useful when testing
  # rstudioapi::navigateToFile(".vault/.credentials")
  # Asks for server password
  jsPsychAdmin::clean_up_dev_protocol(protocol_id = "test/protocols_DEV/31") 

6.0.1.5 Check missing scripts

  #  Downloads all the protocols to CSCN-server
  #  Then checks:
  # - for which ones we do not have preparation scripts
  # - for which ones we do not have googledoc details in
  # + https://docs.google.com/spreadsheets/d/1Eo0F4GcmqWZ1cghTpQlA4aHsc8kTABss-HAeimE2IqA/edit#gid=0
  # + https://docs.google.com/spreadsheets/d/1LAsyTZ2ZRP_xLiUBkqmawwnKWgy8OCwq4mmWrrc_rpQ/edit#gid=0

  jsPsychAdmin::check_missing_prepare_TASK(sync_protocols = TRUE, 
                                           check_trialids = TRUE, 
                                           check_new_task_tabs = TRUE, 
                                           delete_nonexistent = FALSE,
                                           gmail_account = "myemail@gmail.com")

  # Will sync all protocols on server to the LOCAL folder ../CSCN-server
  # Then, will CHECK:
  # - Tasks with no prepare_TASK() script!
  # - Tasks NOT in Google Doc
  # - Check trialid's are OK
  # - Check no missing info in Google doc of NEW tasks
  jsPsychAdmin::download_check_all_protocols(gmail_account = "myemail@gmail.com")

6.0.1.6 Download/Upload specific protocol

  # UPLOAD
jsPsychHelpeR::sync_server_local(
  direction = "local_to_server",
  local_folder = "protocols_DEV/999/",
  server_folder = "test/protocols_DEV/999/",
  only_test = TRUE,
  delete_nonexistent = FALSE
)

  # DOWNLOAD
jsPsychHelpeR::sync_server_local(
  direction = "server_to_local",
  server_folder = "test/protocols_DEV/999/",
  local_folder = "protocols_DEV/999/",
  only_test = TRUE,
  delete_nonexistent = FALSE
)

6.0.1.7 Build jsPsychHelpeR and jsPsychMonkeys packages

Scripts to build the template projects for jsPsychHelpeR and jsPsychMonkeys

jsPsychAdmin::create_jsPsychHelpeR_zip()
jsPsychAdmin::create_jsPsychMonkeys_zip()

6.0.1.8 Create & Simulate & Prepare

  # Extract example tasks to a folder
  jsPsychMaker::copy_example_tasks(destination_folder = "~/Downloads/example_tasks/")

  # Create a protocol with the example tasks
  jsPsychMaker::create_protocol(
    folder_tasks = "~/Downloads/example_tasks/",
    folder_output = "~/Downloads/protocolALL999",
    launch_browser = FALSE,
    options_separator = ";"
  )

  # AUTOMATICALLY run Monkeys and prepare data

  # Only prints in console the code
  jsPsychAdmin::simulate_prepare(folder_protocol = "~/Downloads/protocolALL999", 
                                 n_participants = 3, 
                                 print_watch_run = "print")

  # Runs everything
  jsPsychAdmin::simulate_prepare(folder_protocol = "~/Downloads/protocolALL999", 
                                 n_participants = 3, 
                                 print_watch_run = "run")

  # Run a single Monkey and open VNC to see how it goes
  jsPsychAdmin::simulate_prepare(folder_protocol = "~/Downloads/protocolALL999", 
                                 print_watch_run = "watch")

6.1 Docker containers

We can create a fully reproducible docker image with the data preparation and analysis for a specific project using jsPsychHelpeR::create_docker_container()

Afterwards, you can use the image to run a docker container that will reproduce the analysis and results of your project.

The current version is a first attempt at this, so there is a lot to improve.

6.1.1 Install Docker

First, we need to install docker.

6.1.2 Create image for a project

When a project is ready to share, you can create a self-contained docker image:

# Clean environment -------------------------------------------------------

  # DELETE ALL CACHE
  system("docker builder prune --all -f")
  
  # Clean renv cache libraries
  renv::clean()

  # Clean extra versions of libraries
  source("R/helper_functions_extra.R")
  clean_renv_cache()


# Create docker image -----------------------------------------------------  
  
  PID = 999
  jsPsychHelpeR::create_docker_container(PID = PID)

6.1.3 Store image

You can create a tar file with the image or directly share it through dockerhub:

  1. Store image creating a pid[PID].tar.zip file TO SHARE
  PID = 999
  system(paste0("docker save gorkang/jspsychhelper:pid", PID, " | zip > pid", PID, ".tar.zip"))
  1. Push image to Dockerhub
  PID = 999
  system(paste0("docker push gorkang/jspsychhelper:pid", PID))

6.1.4 Load image

You can load the image in your computer in two ways:

  1. Using a pid[PID].tar.zip:

On linux:

  PID = 999
  utils::unzip(zipfile = paste0("pid", PID, ".tar.zip"), files = paste0("-"))
  system(paste0("docker load --input -"))

On windows:

tar -xf pid999.tar.zip & docker load input - 
  1. Pull image from Dockerhub
  PID = 999
  system(paste0("docker pull gorkang/jspsychhelper:pid", PID))

6.1.5 Run container

Once the docker image is loaded in your system, you will be able to run the data preparation and analysis for your project inside a docker container, ensuring reproducibility. The output will be in Downloads/jsPsychHelpeR[PID]/outputs after a couple of minutes.

  • Linux
  # Make sure ~/Downloads/jsPsychHelpeR999 is empty
  file.remove(list.files(paste0("~/Downloads/jsPsychHelpeR", PID, "/outputs"), recursive = TRUE, full.names = TRUE))
  
  # Run docker
  system(paste0("docker run --rm -d --name pid", PID, " -v ~/Downloads/jsPsychHelpeR", PID, "/outputs:/home/project/jsPsychHelpeR/outputs:rw gorkang/jspsychhelper:pid", PID))
  • Windows
docker run --rm -d --name jspsychhelper -v %USERPROFILE%\Downloads\jsPsychHelpeR\outputs:/home/project/jsPsychHelpeR/outputs:rw gorkang/jspsychhelper:pid999

6.1.6 DEBUG Container

You can DEBUG a container with the following command:

docker run --rm -ti -v ~/Downloads/jsPsychHelpeR999/outputs:/home/project/jsPsychHelpeR/outputs:rw gorkang/jspsychhelper:pid999 /bin/bash

Inside the container, you can acces R and debug as you would locally.

# See last CMD line in Dockerfile_TEMPLATE:
# $ R
source('renv/activate.R')
invisible(lapply(list.files('./R', full.names = TRUE, pattern = '.R$'), source))
setup_folders(pid = 999, folder = '.')
targets::tar_destroy(ask = FALSE)
targets::tar_make()

# Check size folders
du -had1 renv/ | sort -h
du -had1 * | sort -h

6.2 Google Docs

We have a few Google Documents with information about available tasks, protocols, etc.

6.3 Folders and how to work

We have two main locations, the Github jsPsychMaker project and the server.

Github jsPsychMaker project

  • canonical_protocol:
    • machinery: last stable version
    • tasks: all available tasks
    • server: protocols/999/
  • canonical_protocol_DEV
    • machinery: development version
    • tasks: all available tasks
    • server: protocols/test/canonical_protocol_DEV/
  • canonical_protocol_clean
    • machinery: last stable version
    • tasks: Consent and Goodbye
    • server: protocols/test/canonical_protocol_clean/
  • protocols_DEV
    • machinery: last stable version
    • should only contain tasks in development
    • server: protocols/test/protocols_DEV/

In protocols_DEV we prepare the new protocolos:

  • Create a copy in test/protocols_DEV of canonical_protocol_clean and rename to the number of the new protocol, test/protocols_DEV/NumberOfProtocol

  • Once the protocol is ready:

    • Copy protocol to root folder: protocols/NumberOfProtocol
    • ZIP subfolder and move zip to protocols/test/protocols_DEV/OLD_TESTS/
    • Delete folder test/protocols_DEV/NumberOfProtocol
    • If there are new tasks:
      • CHECK with: check_missing_prepare_TASK()
      • TEST with create_protocol_with_NEW_tasks.R
      • Copy tasks, images, videos, specific plugins, etc. to protocols/999/
      • TEST in canonical protocol protocols/999/ just in case there is a weird interaction

6.4 Helper functions

There are a number of helper functions to make some of the jsPsychR admins tasks easier.

6.4.1 Check all protocols

For example, we can use check_missing_prepare_TASK() to:

  • Download all the protocols (without data) to a local folder (sync_protocols = TRUE)

  • Check the trialid’s of all the tests are OK (check_trialids = TRUE)

  • Check there are no duplicate short_name of tasks in the tareas jsPsychR and NUEVAS tareas

  • Check which tasks do not have a prepare_TASK.R script

  • Check tasks with no info on the tareas jsPsychR Google doc

  • Check tasks with missing info on NUEVAS tareas

# Open jsPsychHelpeR RStudio project

  # Load check_missing_prepare_TASK() function
  # cli::cli_alert_info(getwd())

  WD = getwd()
  setwd("../../jsPsychHelpeR/")
  source("R/check_missing_prepare_TASK.R")
  # source("../../jsPsychHelpeR/R/check_missing_prepare_TASK.R")
  setwd(WD)
  
  # If sync_protocols = TRUE, will download to ../CSCN-server/protocols all the protocols from the server
  DF_missing = check_missing_prepare_TASK(sync_protocols = FALSE,
                                          check_trialids = TRUE,
                                          delete_nonexistent = TRUE,
                                          check_new_task_tabs = TRUE,
                                          helper_folder = "../../jsPsychHelpeR",
                                          CSCN_server_folder = "../../CSCN-server/")

  # - Tasks with no prepare_TASK() script!
  # - Tasks NOT in Google Doc
  # - Check trialid's are OK
  DF_missing

  DF_missing$DF_FINAL %>% tidyr::replace_na(list(missing_script = "",
                                                 missing_googledoc = "",
                                                 missing_task = ""))


  # Tasks ready to create prepare_*.R script
  DF_missing$DF_FINAL %>% filter(!is.na(missing_script) & is.na(missing_gdoc))
  DF_missing$DF_FINAL %>% filter(!is.na(missing_script) | !is.na(missing_gdoc)) %>%
    filter(!task %in% c("DEMOGR24", "DEMOGRfondecyt2022E1", "ITC", "fauxPasEv")) %>%  # "MDDF_respaldo", "mic_test", "faux_pas",
    select(-matches("missing"), -Nombre, -Descripcion)

6.4.2 Create protocol with NEW tasks

With create_protocol_with_NEW_tasks.R we can create a protocol with the tasks for which we do not yet have a control snapshot (no .csv’s in the 999.zip data).

This is a necessary step before the task can be moved to the canonical protocol.

The function find_missing_tasks_in_999() will read all the csv in jsPsychHelpeR/data/999/999.zip and depending on the value of the parameter search_where (“prepare_TASK” or “js”):

  • all .js tasks in jsPsychMaker/protocols_DEV/

  • all prepare_TASK.R in jsPSychHelpeR/R_tasks/

Comparing both sources, will look for tasks for which we do not have a .csv in the 999 protocol yet (remember the 999 protocol is the canonical_protocol in the server).

Then, it prepares a NEW_TASKS protocol using the tasks.js files found in the server (after downloading all the server protocols to jsPsychR/CSCN-server/). A couple important points:

  • This is a bit tricky, as it will use all the tasks in the server that it can found, across all the protocols, and will select the newest one.

  • Sometimes there are multiple copies, with different dates and sizes…

  • It is important that the server is as clean as possible. With all the OLD non-updated protocols zipped.

To make sure the Github jsPsychMaker/protocols_DEV/NEW_TASKS/ is up to date, create_protocol_with_NEW_tasks.R will UPLOAD CSCN-server/.../NEW_TASKS to the server, and then DOWNLOAD NEW_TASKS to ../jsPsychMaker/protocols_DEV/NEW_TASKS/

6.4.3 Check canonical protocol DEV

With 000_CHECK_CANONICAL.R we can check that the canonical protocol in development works and expected.

In the script you can:

  • sync canonical_protocol_DEV/ folder in jsPsychMaker to 999/ in the server
  • launch 5 monkeys
  • rename the csv files to a fixed date, etc.
  • prepare data
  • compare with snaphot (WIP)