Chapter 4

Lab Docs

Find out how to create and organize your content quickly and intuitively.

Subsections of Lab Docs

Laboratory etiquette

  1. Safety – The principal investigator of the study and his/her designated users are responsible to make sure the laboratory is a safe environment. Please review your experimental protocol and make sure it is approved by your PI. Never leave a participant alone in the laboratory.

  2. Courtesy – Do not remove any equipment or cables from the laboratory that do not belong to you. Return any equipment changes to their original state (e.g., moving monitors or chairs, etc.). Do not leave used equipment in the rooms (e.g., cables or monitors), as they can cause artifacts (e.g., with EEG) and accidents.

  3. Cleanliness – Keep the laboratory clean (ex: throw away garbage). Pick up any loose cables or equipment (return to where you found them) when you are finished using them. Keep the shelves organized and neat. When you are finished with your experiment, the laboratory suite should look like you were never there.

  4. Do not go over your allotted time – The rooms should be turned over to the next user group at the beginning of their session. This means you should leave time at the end of your slot to remove your participant and tidy the areas you used for the next user. Even if you get started late, your session must end on time.

  5. Food and drinks – No Food is allowed in the laboratory, unless they are dry snacks provided to the study participants or if this will be part of your experimental protocol. Hot food is never allowed because it is smelly and the laboratory is an enclosed space! Drinks are okay only if they are covered containers!

  6. Responsibilities – As well as what is mentioned above, responsibilities also include filling out the log book, backing up your data such that it is not stored on the computers in the laboratory. Please report any issues or broken equipment to the principal investigator right away.

Reproducibility: recipes for science

Reproducibility

Replicability in is vital for science, but we may get it every time.

Reproducibility ensures that using the obtained data anyone can achieve the same results.This is not as easy as it seems because it necessitates (1) methodological procedures and analytic pipeline to be explicitly documented in their entirety (like a recipe), and (2) the use of a fully reproducible environment.

To give you an example, here we will reproduce the hexagonal logo (sometimes refereed to as hex-stickers) of our course. Keep in mind that this example is only partial computational reproducibility, as we employ only package management. R version, system packages, operating system can vary and bias our results.

Full computational reproducibility, achievable with Docker containers or NixOS derivations, is beyond the scope of this demo.

Managing packages

For simplicity, we just store package versions within the .Rmd file and use renv for package management and taking care of all other dependencies.

Take note that renv is more powerful then this and should typically be used in a project-centric (i.e. .prj) workflow.

if (!require("renv")) install.packages("renv", dependencies = TRUE)

renv::use(
  "renv@1.0.3",
  "here@1.0.1",
  "dplyr@1.1.4",
  "tidyr@1.3.0",
  "ggseg3d@1.6.3",
  "ggseg@1.6.5",
  "plotly@4.10.3",
  "RColorBrewer@1.1-3",
  "reticulate@1.34.0",
  "magick@2.8.2",
  "cropcircles@0.2.4",
  "hexSticker@0.4.9"
)

Loading packages and setting up

# Packages
library(renv)
library(here)
library(dplyr)
library(tidyr)
library(ggseg)
library(ggseg3d)
library(plotly)
library(RColorBrewer)
library(reticulate)
library(magick)
library(cropcircles)
library(hexSticker)

As we are doing everything within a single .Rmd file. Here we use an unusual way of setting up an working directory for the .Rmd file that can be reproduced on any other system. Nevertheless, the usual way would be to use knitr options to set a root directory.

# Settings 
# If working in .prj directory and not using RStudio
here::set_here()
## File .here already exists in C:\Users\User\c\Github\ns101-website\content\lab_docs\2024-01-20-reproducibility
unloadNamespace("here")   # need new R session or unload namespace for .here file to take precedence over .Rproj
script_path <- file.path(here::here())

# If using RStudio
# script_path <- dirname(rstudioapi::getActiveDocumentContext()$path) 

# Create output folder if it doesn't exist
setwd(script_path)
folder_name <- "output"
if(!exists(folder_name)) {dir.create(folder_name)} 
## Warning in dir.create(folder_name): 'output' already exists
setwd(file.path(script_path, folder_name))

Making an interactive plot

The package aseg_3d helps us build a plotly interactive plot using a brain atlas.

# Make the Brain plot -------------------------------------------------------------------------
scene <- list(eye = list(x = -1.5, y = 0.3, z = 0))

my_aseg <- aseg_3d %>% 
  unnest(cols = ggseg_3d) %>% 
  select(label, colour) %>% 
  mutate(coln = as.integer(as.factor(colour))) %>% 
  mutate(coln = if_else(grepl("Cerebellum|Ventricle|Vent", label), NA_integer_, coln)) %>% 
  mutate(coln = if_else(grepl("CC_", label), 1L, coln)) %>% 
  mutate(col = RColorBrewer::brewer.pal(11, "Paired")[12 - as.integer(as.factor(coln))]) %>% 
  mutate(col = if_else(grepl("Cerebellum", label), "#012169", col))  # UB color

brain_plotly <- 
  ggseg3d(.data = my_aseg, atlas = aseg_3d, 
    colour = "col", 
    na.colour = "#A6CEE3",
    show.legend = TRUE
  ) %>% 
  add_glassbrain(
    hemisphere = "left",  
    colour = "#A6CEE3", # "#cecece"
    opacity = 0.3
  ) %>% 
  remove_axes() %>% 
  pan_camera(camera = scene) %>% 
  hide_colorbar()

You can interact with this visualization of a glass brain showing its subcortical structures.

brain_plotly
# Export to html
# htmlwidgets::saveWidget(brain_plotly, "brain_plotly.html")

Exporting the plot

Exporting plotly graphics is a bit of a hassle, as we need to spawn a python environment in order to use the kaleido library.

## Error : Miniconda is already installed at path "C:/Users/User/AppData/Local/r-miniconda".
## - Use `reticulate::install_miniconda(force = TRUE)` to overwrite the previous installation.

Now we have a .png of our glass brain!

# file.show(here::here("output", "brain_img.png"))
knitr::include_graphics(here::here("output", "brain_img.png"))

Let’s crop around it so we can then fit it inside a hexagonal shape.

# Make the hex sticker -------------------------------------------------------------------------
brain_img <- magick::image_read(here::here("output", "brain_img.png"))

cropcircles::circle_crop(
  images = brain_img,
  border_colour = "#ffffff",
  border_size = 10,
  to = here::here("output", "brain_img_cropped.png")
)
## [1] "C:/Users/User/c/Github/ns101-website/content/lab_docs/2024-01-20-reproducibility/output/brain_img_cropped.png"
brain_img_cropped <- magick::image_read(here::here("output", "brain_img_cropped.png"))
# brain_img_cropped
knitr::include_graphics(here::here("output", "brain_img_cropped.png"))

Now we hexSticker package to make out image into a hex sticker!

hexSticker::sticker(
  brain_img_cropped, 
  package = "UniBuc NS101", p_color="#012169", p_family = "sans",     # don't use: p_fontface = "bold"
  p_size = 14, p_y = 1.5,  
  s_x = 1, s_y = 0.9, s_width = 2, s_height = 1.5,
  h_fill="#ffffff", h_color="#012169", 
  url = "ns101.psychlab.eu", u_color = "#012169", u_size	= 8,
  filename = here::here("output", "brain_hex_bg.png")
)

brain_hex_bg <- magick::image_read(here::here("output", "brain_hex_bg.png"))
knitr::include_graphics(here::here("output", "brain_hex_bg.png"))

A little bit more styling and we are done - we really want the background to be transparent, not white.

fuzz <- 50

brain_hex <- brain_hex_bg %>%             # make background transparent
  magick::image_fill(color = "transparent", refcolor = "white", fuzz = fuzz, point = "+1+1") %>%
  magick::image_fill(color = "transparent", refcolor = "white", fuzz = fuzz, 
             point = paste0("+", image_info(brain_hex_bg)$width-1, "+1")) %>%
  magick::image_fill(color = "transparent", refcolor = "white", fuzz = fuzz, 
             point = paste0("+1", "+", image_info(brain_hex_bg)$height-1)) %>%
  magick::image_fill(color = "transparent", refcolor = "white", fuzz = fuzz, 
             point = paste0("+", image_info(brain_hex_bg)$width-1, "+", image_info(brain_hex_bg)$height-1))
magick::image_write(image = brain_hex, path = here::here("output", "brain_hex.png"))
# file.show(here::here("output", "brain_hex.png"))
knitr::include_graphics(here::here("output", "brain_hex.png"))

If we documented everything well enough and if you have a similar system, there should be a very high probability that by running this .Rmd file, you will re-construct our brain hex logo.