diff --git a/bin/induction-instructions.R b/bin/induction-instructions.R new file mode 100755 index 0000000..77b245b --- /dev/null +++ b/bin/induction-instructions.R @@ -0,0 +1,91 @@ +#!/usr/bin/env Rscript + +library(rjson) +library(gridExtra) +library(grid) +library(png) + +insert_overview <- function(data, x_margin, y_initial, y_spacing, font_size) { + grid.text("Induction of protein expression in OT-2", x = x_margin, y = y_initial, just = "left", gp = gpar(fontsize = font_size + 4, fontface = "bold")) + overview <- c("Quick Overview", + paste("Once the cultures have reached the desired growth phase, the robot transfers cells to appropriate plates."), + paste("The robot adds an inducer to the cultures."), + paste("After induction, cultures are incubated to allow for protein expression.")) + overview_y_lines <- (y_initial - 2*y_spacing) - seq(0, length(overview) - 1) * y_spacing + text_style <- gpar(fontsize = font_size, fontface = c("bold", rep("plain", length(overview) - 1))) + grid.text(overview, x = x_margin, y = overview_y_lines, just = "left", gp = text_style) + return(overview_y_lines[length(overview_y_lines)]-y_spacing) +} + +insert_preparation <- function(x_margin, y_initial, y_spacing) { + preparation <- c("Preparation", + "Prepare the reagents and labware according to the below diagrams.", + "Volumes (uL) indicate how much of reagents will be used, so add additional volume.") + + preparation_y_lines <- y_initial - y_spacing * (1:length(preparation)) + text_style <- gpar(fontsize = 12, fontface = c("bold", rep("plain", length(preparation) - 1))) + grid.text(preparation, x = x_margin, y = preparation_y_lines, just = "left", gp = text_style) + return(preparation_y_lines[length(preparation_y_lines)]-y_spacing) +} + +insert_labware <- function(visualised_labware, width, height, x_margin, y_initial, y_spacing) { + image_files <- list.files(visualised_labware, pattern = "^0", full.names = TRUE) + num_images <- length(image_files) + + positions <- list() + # Generate positions + for (i in 1:num_images) { + # Calculate position based on index + x <- x_margin + width/2 + ((i - 1) %% 2) * width + y <- y_initial - height/2 + floor((i - 1) / 2) * - height + positions[[i]] <- list(x = x, y = y) + } + # Insert each image into the PDF + for (i in seq_along(image_files)) { + if (file.exists(image_files[i])) { + image <- readPNG(image_files[i]) + position <- positions[[i]] + grid.raster(image, x = position$x, y = position$y, width = width, height = height) + } + } + + return(positions[[num_images]]$y - height/2 - y_spacing) +} + +insert_deck_loading <- function(data, x_margin, y_initial, font_size, y_spacing) { + deck <- c("Deck Loading Instructions", + paste("Check that", data$right_pipette_name, "is in the right mount, and", data$left_pipette_name, "is in the left mount." ), + paste("Slot", paste(data$right_pipette_tiprack_slot, collapse = ", "), ": load", data$right_pipette_tiprack_name, "for the", data$right_pipette_name, "pipette."), + paste("Slot", paste(data$left_pipette_tiprack_slot, collapse = ", "), ": load", data$left_pipette_tiprack_name, "for the", data$left_pipette_name, "pipette."), + paste("Slot", data$blank_plate_slot, ": load", data$blank_plate_name, "containing blank for the plate reader."), + paste("Slot", data$culture_plate_slot, ": load", data$culture_plate_name, "containing the cell culture."), + paste("Slot", data$inducer_plate_slot, ": load", data$inducer_plate_name, "containing the inducer."), + paste("Slot", data$destination_plate_slot, ": load", data$destination_plate_name, " where the induction occurs.")) + deck_y_lines <- y_initial - seq(0, length(deck) - 1) * y_spacing + text_style <- gpar(fontsize = font_size, fontface = c("bold", rep("plain", length(deck) - 1))) + grid.text(deck, x = x_margin, y = deck_y_lines, just = "left", gp = text_style) +} + +instructions <- function(json_file_path, visualised_labware, output_file, x_margin = 0.05, y_spacing = 0.02, labware_width = 0.45, labware_height = 0.27, font_size = 12, y_initial = 0.98) { + pdf(output_file, width = 8.5, height = 11) + par(mar = c(5, 4, 4, 2) + 0.1) + json_data <- fromJSON(file = json_file_path) + + overview <- insert_overview(json_data, x_margin, y_initial, y_spacing, font_size) # Title and Overview + preparation <- insert_preparation(x_margin, overview, y_spacing) # Reagents preparation + + labware <- insert_labware(visualised_labware, labware_width, labware_height, x_margin, preparation, y_spacing) # # Insert images and get coordinates + deck_loading <- insert_deck_loading(json_data, x_margin, labware, font_size, y_spacing) + + dev.off() + +} + +# Command-line arguments +args <- commandArgs(trailingOnly = TRUE) +json_file_path <- args[1] +visualised_labware <- args[2] +output_file <- args[3] + +# Generateinstructions +instructions(json_file_path, visualised_labware, output_file) diff --git a/bin/picking-instructions.R b/bin/picking-instructions.R new file mode 100755 index 0000000..746de44 --- /dev/null +++ b/bin/picking-instructions.R @@ -0,0 +1,91 @@ +#!/usr/bin/env Rscript + +library(rjson) +library(gridExtra) +library(grid) +library(png) + +insert_overview <- function(data, x_margin, y_initial, y_spacing, font_size) { + grid.text("Colony picking in OT-2", x = x_margin, y = y_initial, just = "left", gp = gpar(fontsize = font_size + 4, fontface = "bold")) + overview <- c("Quick Overview", + paste("The colonies were picked using a pipette tip and transferred to destination plate containing fresh media."), + paste("The plate is then incubated under the required conditions for further growth."), + paste("The robot picked colonies from total of", length(data$agar_plate_slot), "agar plates."), + paste("The picking height into the agar is set at ", data$agar_stab_depth, "mm."), + paste("The agar height is calculated automatically per plate based on:"), + paste("its shape (", data$agar_plate_shape, ") and dimensions (", paste(data$agar_plate_dimensions, collapse=", "), "in mm),"), + paste("the plate weight without agar (", data$plate_weight_without_agar, "g) and with agar (g),"), + paste("and agar density of ", data$agar_density,"(g/mm3).")) + overview_y_lines <- (y_initial - 2*y_spacing) - seq(0, length(overview) - 1) * y_spacing + text_style <- gpar(fontsize = font_size, fontface = c("bold", rep("plain", length(overview) - 1))) + grid.text(overview, x = x_margin, y = overview_y_lines, just = "left", gp = text_style) + return(overview_y_lines[length(overview_y_lines)]-y_spacing) +} +insert_preparation <- function(x_margin, y_initial, y_spacing) { + preparation <- c("Preparation", + "The colonies are picked in accordance to the plate layout below.") + preparation_y_lines <- y_initial - y_spacing * (1:length(preparation)) + text_style <- gpar(fontsize = 12, fontface = c("bold", rep("plain", length(preparation) - 1))) + grid.text(preparation, x = x_margin, y = preparation_y_lines, just = "left", gp = text_style) + return(preparation_y_lines[length(preparation_y_lines)]-y_spacing) +} + +insert_labware <- function(visualised_labware, width, height, x_margin, y_initial, y_spacing) { + image_files <- list.files(visualised_labware, pattern = "^0", full.names = TRUE) + num_images <- length(image_files) + + positions <- list() + # Generate positions + for (i in 1:num_images) { + # Calculate position based on index + x <- x_margin + width/2 + ((i - 1) %% 2) * width + y <- y_initial - height/2 + floor((i - 1) / 2) * - height + positions[[i]] <- list(x = x, y = y) + } + # Insert each image into the PDF + for (i in seq_along(image_files)) { + if (file.exists(image_files[i])) { + image <- readPNG(image_files[i]) + position <- positions[[i]] + grid.raster(image, x = position$x, y = position$y, width = width, height = height) + } + } + + return(positions[[num_images]]$y - height/2 - y_spacing) +} + +insert_deck_loading <- function(data, x_margin, y_initial, font_size, y_spacing) { + deck <- c("Deck Loading Instructions", + paste("Check that", data$pipette_name, "is in the", data$pipette_mount, "mount"), + paste("Slot", paste(data$pipette_tiprack_slot, collapse = ", "), ": load", data$pipette_tiprack_name, "for the", data$pipette_name, "pipette."), + paste("Slot", data$agar_plate_slot, ": load", data$agar_plate_name, "with agar."), + paste("Slot", data$media_plate_slot, ": load", data$media_plate_name, "containing fresh media.")) + deck_y_lines <- y_initial - seq(0, length(deck) - 1) * y_spacing + text_style <- gpar(fontsize = font_size, fontface = c("bold", rep("plain", length(deck) - 1))) + grid.text(deck, x = x_margin, y = deck_y_lines, just = "left", gp = text_style) +} + +instructions <- function(json_file_path, visualised_labware, output_file, x_margin = 0.05, y_spacing = 0.02, labware_width = 0.45, labware_height = 0.27, font_size = 12, y_initial = 0.98) { + pdf(output_file, width = 8.5, height = 11) + par(mar = c(5, 4, 4, 2) + 0.1) + json_data <- fromJSON(file = json_file_path) + + overview <- insert_overview(json_data, x_margin, y_initial, y_spacing, font_size) # Title and Overview + preparation <- insert_preparation(x_margin, overview, y_spacing) # Reagents preparation + + + labware <- insert_labware(visualised_labware, labware_width, labware_height, x_margin, preparation, y_spacing) # # Insert images and get coordinates + deck_loading <- insert_deck_loading(json_data, x_margin, labware, font_size, y_spacing) + + dev.off() + +} + +# Command-line arguments +args <- commandArgs(trailingOnly = TRUE) +json_file_path <- args[1] +visualised_labware <- args[2] +output_file <- args[3] + +# Generateinstructions +instructions(json_file_path, visualised_labware, output_file) diff --git a/bin/spotting-instructions.R b/bin/spotting-instructions.R new file mode 100755 index 0000000..4513f84 --- /dev/null +++ b/bin/spotting-instructions.R @@ -0,0 +1,96 @@ +#!/usr/bin/env Rscript + +library(rjson) +library(gridExtra) +library(grid) +library(png) + +insert_overview <- function(data, x_margin, y_initial, y_spacing, font_size) { + grid.text("Spotting in OT-2", x = x_margin, y = y_initial, just = "left", gp = gpar(fontsize = font_size + 4, fontface = "bold")) + overview <- c("Quick Overview", + paste("The robot spots transformed cells on the total of", length(data$agar_plate_slot), "agar plates."), + paste("The pipette aspirates additional", data$dead_volume, "uL of transfromed cells."), + paste("The spotting height above the agar is set at ", data$spotting_height, "mm."), + paste("The agar height is calculated automatically per plate based on:"), + paste("its shape (", data$agar_plate_shape, ") and dimensions (", paste(data$agar_plate_dimensions, collapse=", "), "in mm),"), + paste("the plate weight without agar (", data$plate_weight_without_agar, "g) and with agar (g),"), + paste("and agar density of ", data$agar_density,"(g/mm3).")) + overview_y_lines <- (y_initial - 2*y_spacing) - seq(0, length(overview) - 1) * y_spacing + text_style <- gpar(fontsize = font_size, fontface = c("bold", rep("plain", length(overview) - 1))) + grid.text(overview, x = x_margin, y = overview_y_lines, just = "left", gp = text_style) + return(overview_y_lines[length(overview_y_lines)]-y_spacing) +} +insert_preparation <- function(x_margin, y_initial, y_spacing) { + preparation <- c("Preparation", + "The plates are spotted in uL according to the layout below.") + preparation_y_lines <- y_initial - y_spacing * (1:length(preparation)) + text_style <- gpar(fontsize = 12, fontface = c("bold", rep("plain", length(preparation) - 1))) + grid.text(preparation, x = x_margin, y = preparation_y_lines, just = "left", gp = text_style) + return(preparation_y_lines[length(preparation_y_lines)]-y_spacing) +} + +insert_labware <- function(visualised_labware, width, height, x_margin, y_initial, y_spacing) { + # List all files that start with a number, ensuring full names are returned + image_files <- list.files(visualised_labware, pattern = "^\\d+", full.names = TRUE) + + # Sort the files numerically based on their prefix + image_files <- sort(image_files, method = "radix") + + num_images <- length(image_files) + + positions <- list() + # Generate positions + for (i in 1:num_images) { + # Calculate position based on index + x <- x_margin + width/2 + ((i - 1) %% 2) * width + y <- y_initial - height/2 - floor((i - 1) / 2) * height # Adjusted calculation + positions[[i]] <- list(x = x, y = y) + } + + # Insert each image into the PDF + for (i in seq_along(image_files)) { + if (file.exists(image_files[i])) { + image <- readPNG(image_files[i]) + position <- positions[[i]] + grid.raster(image, x = position$x, y = position$y, width = width, height = height) + } + } + + return(positions[[num_images]]$y - height/2 - y_spacing) +} + +insert_deck_loading <- function(data, x_margin, y_initial, font_size, y_spacing) { + deck <- c("Deck Loading Instructions", + paste("Check that", data$pipette_name, "is in the", data$pipette_mount,"mount."), + paste("Slot", paste(data$pipette_tiprack_slots, collapse = ", "), ": load", data$pipette_tiprack_name, "for the", data$pipette_name, "pipette."), + paste("Slot", data$agar_plate_slot, ": load", data$agar_plate_name, "with agar."), + paste("Slot", data$transformation_plate_slot, ": load", data$transformation_plate_name, "containing transformed cells.")) + deck_y_lines <- y_initial - seq(0, length(deck) - 1) * y_spacing + text_style <- gpar(fontsize = font_size, fontface = c("bold", rep("plain", length(deck) - 1))) + grid.text(deck, x = x_margin, y = deck_y_lines, just = "left", gp = text_style) +} + +instructions <- function(json_file_path, visualised_labware, output_file, x_margin = 0.05, y_spacing = 0.02, labware_width = 0.45, labware_height = 0.27, font_size = 12, y_initial = 0.98) { + pdf(output_file, width = 8.5, height = 11) + par(mar = c(5, 4, 4, 2) + 0.1) + json_data <- fromJSON(file = json_file_path) + + overview <- insert_overview(json_data, x_margin, y_initial, y_spacing, font_size) # Title and Overview + preparation <- insert_preparation(x_margin, overview, y_spacing) # Reagents preparation + + + labware <- insert_labware(visualised_labware, labware_width, labware_height, x_margin, preparation, y_spacing) # # Insert images and get coordinates + deck_loading <- insert_deck_loading(json_data, x_margin, labware, font_size, y_spacing) + + dev.off() + +} + +# Command-line arguments +args <- commandArgs(trailingOnly = TRUE) +json_file_path <- args[1] +visualised_labware <- args[2] +output_file <- args[3] + +# Generateinstructions +instructions(json_file_path, visualised_labware, output_file) diff --git a/bin/transfer-instructions.R b/bin/transfer-instructions.R new file mode 100755 index 0000000..38b0082 --- /dev/null +++ b/bin/transfer-instructions.R @@ -0,0 +1,84 @@ +#!/usr/bin/env Rscript + +library(rjson) +library(gridExtra) +library(grid) +library(png) + +insert_overview <- function(data, x_margin, y_initial, y_spacing, font_size) { + grid.text("Simple liquid transfer in OT-2", x = x_margin, y = y_initial, just = "left", gp = gpar(fontsize = font_size + 4, fontface = "bold")) + overview <- c("Quick Overview", + paste("The transfer of liquids.")) + overview_y_lines <- (y_initial - 2*y_spacing) - seq(0, length(overview) - 1) * y_spacing + text_style <- gpar(fontsize = font_size, fontface = c("bold", rep("plain", length(overview) - 1))) + grid.text(overview, x = x_margin, y = overview_y_lines, just = "left", gp = text_style) + return(overview_y_lines[length(overview_y_lines)]-y_spacing) +} +insert_preparation <- function(x_margin, y_initial, y_spacing) { + preparation <- c("Preparation", + "The liquids are transferred according to the layout below (uL).") + preparation_y_lines <- y_initial - y_spacing * (1:length(preparation)) + text_style <- gpar(fontsize = 12, fontface = c("bold", rep("plain", length(preparation) - 1))) + grid.text(preparation, x = x_margin, y = preparation_y_lines, just = "left", gp = text_style) + return(preparation_y_lines[length(preparation_y_lines)]-y_spacing) +} + +insert_labware <- function(visualised_labware, width, height, x_margin, y_initial, y_spacing) { + image_files <- list.files(visualised_labware, pattern = "^0", full.names = TRUE) + num_images <- length(image_files) + + positions <- list() + # Generate positions + for (i in 1:num_images) { + # Calculate position based on index + x <- x_margin + width/2 + ((i - 1) %% 2) * width + y <- y_initial - height/2 + floor((i - 1) / 2) * - height + positions[[i]] <- list(x = x, y = y) + } + # Insert each image into the PDF + for (i in seq_along(image_files)) { + if (file.exists(image_files[i])) { + image <- readPNG(image_files[i]) + position <- positions[[i]] + grid.raster(image, x = position$x, y = position$y, width = width, height = height) + } + } + + return(positions[[num_images]]$y - height/2 - y_spacing) +} + +insert_deck_loading <- function(data, x_margin, y_initial, font_size, y_spacing) { + deck <- c("Deck Loading Instructions", + paste("Check that", data$pipette_name, "is in the", data$pipette_mount, "mount"), + paste("Slot", paste(data$pipette_tiprack_slot, collapse = ", "), ": load", data$pipette_tiprack_name, "for the", data$pipette_name, "pipette."), + paste("Slot", data$source_plate_slot, ": load", data$source_plate_name, "with source reagents."), + paste("Slot", data$destination_plate_slot, ": load", data$destination_plate_name, "as a destination plate.")) + deck_y_lines <- y_initial - seq(0, length(deck) - 1) * y_spacing + text_style <- gpar(fontsize = font_size, fontface = c("bold", rep("plain", length(deck) - 1))) + grid.text(deck, x = x_margin, y = deck_y_lines, just = "left", gp = text_style) +} + +instructions <- function(json_file_path, visualised_labware, output_file, x_margin = 0.05, y_spacing = 0.02, labware_width = 0.45, labware_height = 0.27, font_size = 12, y_initial = 0.98) { + pdf(output_file, width = 8.5, height = 11) + par(mar = c(5, 4, 4, 2) + 0.1) + json_data <- fromJSON(file = json_file_path) + + overview <- insert_overview(json_data, x_margin, y_initial, y_spacing, font_size) # Title and Overview + preparation <- insert_preparation(x_margin, overview, y_spacing) # Reagents preparation + + + labware <- insert_labware(visualised_labware, labware_width, labware_height, x_margin, preparation, y_spacing) # # Insert images and get coordinates + deck_loading <- insert_deck_loading(json_data, x_margin, labware, font_size, y_spacing) + + dev.off() + +} + +# Command-line arguments +args <- commandArgs(trailingOnly = TRUE) +json_file_path <- args[1] +visualised_labware <- args[2] +output_file <- args[3] + +# Generateinstructions +instructions(json_file_path, visualised_labware, output_file) diff --git a/bin/transformation-instructions.R b/bin/transformation-instructions.R new file mode 100755 index 0000000..dee8cd7 --- /dev/null +++ b/bin/transformation-instructions.R @@ -0,0 +1,94 @@ +#!/usr/bin/env Rscript + +library(rjson) +library(gridExtra) +library(grid) +library(png) + +insert_overview <- function(data, x_margin, y_initial, y_spacing, font_size) { + grid.text("E. coli Transformation in OT-2", x = x_margin, y = y_initial, just = "left", gp = gpar(fontsize = font_size + 4, fontface = "bold")) + overview <- c("Quick Overview", + paste("Add DNA into competent cells in thermocycler."), + paste("Incubate the cells at", data$init_temp, "°C for", data$init_time, "minutes."), + paste("Heat-shock the cells at", data$heat_temp, "°C for", data$heat_time, "seconds."), + paste("Incubate the cells at", data$cool_temp, "°C for", data$cool_time, "minutes."), + paste("Add the recovery medium and incubate cells at", data$inc_temp, "°C for", data$inc_time, "minutes.")) + overview_y_lines <- (y_initial - 2*y_spacing) - seq(0, length(overview) - 1) * y_spacing + text_style <- gpar(fontsize = font_size, fontface = c("bold", rep("plain", length(overview) - 1))) + grid.text(overview, x = x_margin, y = overview_y_lines, just = "left", gp = text_style) + return(overview_y_lines[length(overview_y_lines)]-y_spacing) +} + +insert_preparation <- function(x_margin, y_initial, y_spacing) { + preparation <- c("Preparation", + "Prepare the reagents and labware according to the below diagrams.", + "Volumes (uL) indicate how much of reagents will be used, so add additional volume.") + preparation_y_lines <- y_initial - y_spacing * (1:length(preparation)) + text_style <- gpar(fontsize = 12, fontface = c("bold", rep("plain", length(preparation) - 1))) + grid.text(preparation, x = x_margin, y = preparation_y_lines, just = "left", gp = text_style) + return(preparation_y_lines[length(preparation_y_lines)]-y_spacing) +} + +insert_labware <- function(visualised_labware, width, height, x_margin, y_initial, y_spacing) { + image_files <- list.files(visualised_labware, pattern = "^0", full.names = TRUE) + num_images <- length(image_files) + + positions <- list() + # Generate positions + for (i in 1:num_images) { + # Calculate position based on index + x <- x_margin + width/2 + ((i - 1) %% 2) * width + y <- y_initial - height/2 + floor((i - 1) / 2) * - height + positions[[i]] <- list(x = x, y = y) + } + # Insert each image into the PDF + for (i in seq_along(image_files)) { + if (file.exists(image_files[i])) { + image <- readPNG(image_files[i]) + position <- positions[[i]] + grid.raster(image, x = position$x, y = position$y, width = width, height = height) + } + } + + return(positions[[num_images]]$y - height/2 - y_spacing) +} + +insert_deck_loading <- function(data, x_margin, y_initial, font_size, y_spacing) { + deck <- c("Deck Loading Instructions", + paste("Check that", data$right_pipette_name, "is in the right mount, and", data$left_pipette_name, "is in the left mount." ), + paste("Slot", paste(data$right_pipette_tiprack_slot, collapse = ", "), ": load", data$right_pipette_tiprack_name, "for the", data$right_pipette_name, "pipette."), + paste("Slot", paste(data$left_pipette_tiprack_slot, collapse = ", "), ": load", data$left_pipette_tiprack_name, "for the", data$left_pipette_name, "pipette."), + paste("Slot", data$dna_plate_slot, ": load", data$dna_plate_name, " containing DNA."), + paste("Slot", data$cells_plate_slot, ": load", data$cells_plate_name, " containing cells."), + paste("Slot", data$media_plate_slot, ": load", data$media_plate_name, " containing SOC."), + paste("Slot 7,8,10,11: load a thermocycler and turn it on."), + paste("Thermocycler: load", data$transformation_plate_name, "when instructed on the screen.")) + deck_y_lines <- y_initial - seq(0, length(deck) - 1) * y_spacing + text_style <- gpar(fontsize = font_size, fontface = c("bold", rep("plain", length(deck) - 1))) + grid.text(deck, x = x_margin, y = deck_y_lines, just = "left", gp = text_style) +} + +instructions <- function(json_file_path = "data/transformation-parameters.json", visualised_labware, output_file = "Instructions.pdf", x_margin = 0.05, y_spacing = 0.02, labware_width = 0.45, labware_height = 0.27, font_size = 12, y_initial = 0.98) { + pdf(output_file, width = 8.5, height = 11) + par(mar = c(5, 4, 4, 2) + 0.1) + json_data <- fromJSON(file = json_file_path) + + overview <- insert_overview(json_data, x_margin, y_initial, y_spacing, font_size) # Title and Overview + preparation <- insert_preparation(x_margin, overview, y_spacing) # Reagents preparation + + + labware <- insert_labware(visualised_labware, labware_width, labware_height, x_margin, preparation, y_spacing) # # Insert images and get coordinates + deck_loading <- insert_deck_loading(json_data, x_margin, labware, font_size, y_spacing) + + dev.off() + +} + +# Command-line arguments +args <- commandArgs(trailingOnly = TRUE) +json_file_path <- args[1] +visualised_labware <- args[2] +output_file <- args[3] + +# Generateinstructions +instructions(json_file_path, visualised_labware, output_file)