1 Introduction

To generate plate maps, WPM uses an algorithm inspired from the backtracking algorithm. More precisely, WPM loops on the following actions until all of the samples are given a correct location:

  1. randomly choose a well on the plate
  2. Randomly selects a sample;
  3. Check whether all the specified location constraints are met. If yes, place the sample accordingly.

This process allows for an experimental design by block randomization.

There are two ways using the wpm package:

  • through a shiny application for users who do not have sufficient R programming skills.
  • using R commands for users who want to work with their own R scripts.

Important: Even in case of command line use, we strongly recommend to read the section about the shiny app section, as this is where all terms and concepts are explained in detail.

1.1 Supported input formats

Input Format Command line WPM app
CSV yes yes
ExpressionSet yes no
SummarizedExperiment yes no
MSnSet yes no

2 Getting started

2.1 Prerequisites

This tutorial explains how to use the Well Plate Maker package. Make sure you are using a recent R version (\(\geq 4.0.0\)). For Windows users who do not have the Edge browser, we recommend using the Chrome browser rather than Internet Explorer.

2.2 Installation from BioConductor:

if (!requireNamespace("BiocManager", quietly = TRUE))
    install.packages("BiocManager")

BiocManager::install("wpm")

3 How to use the WPM shiny application

3.1 Launch the shiny application

Whether you use RStudio or simply work with an R console, the procedure remains the same to launch the shiny app:

library(wpm)
wpm()

If everything is in order, a new window will open in your default browser. If not, find the line written in the R console: Listening on http://127.0.0.1:8000, and paste the URL in your web browser.

WPM has 4 main tabs: Home, Parameters, Results ans Help.

3.2 The Home tab

Briefly presents the aim of the app, shows the last package version, explains how to cite us to support our work and gives the contact information.

The Home page when wpm is started

The Home page when wpm is started

3.3 The Parameters tab

Overall the page is organized in two sections.

The one on the left contains all the configuration steps. It is divided into 6 main steps, detailed below. It is of the utmost importance to correctly specify all the constraints for generating the desired plate maps.

The one on the right summarizes the input parameters (tuned along the 6 steps of the left panel) as well as the chosen (empty) plate layout. The right section is automatically updated each time a parameter is changed in the left section.

Parameters Panel

Parameters Panel

3.3.1 Upload dataset

First, you must upload a Comma-separated values (.CSV) or a text (.txt) file. This file contains at least one kind of information: the sample names.

Sample
s1
s2
s3
s4

It is also possible to provide a file containing several variables describing the data, as in the example below:

Sample Type Treatment
s1 A trt1
s2 A tr1
s3 B Ctrl
s4 C Ctrl

IMPORTANT Please respect this ORDER of columns for the data in the CSV file: Sample names in the first column, and other variables in the other columns, like the example below (if there are rownames, then the Samples’ Column must be the second in the file.):

Sample;Type;Treatment
s1;A;trt1
s2;A;trt1
s3;B;Ctrl
s4;C;Ctrl

Second, you have to specify if there are quotes in your file or not. The Default is none, meaning that there is no __*“*__ or characters in your file. If you select the appropriate quote, then you will be able to:

  • check if your file does have a header and row names.
  • select the appropriate separator field. Default is semicolon (“;”)

Then you can select one of the variables that you want to use as the grouping factor for WPM.
This column will be renamed “Group” in the final dataset.

Choose the grouping factor

Choose the grouping factor

The names you give to columns in your CSV do not matter, because WPM will create a new dataset having 3 fields: “Sample” , “Group” and “ID”.

You will see your dataset on the right side of the window, and another dataset which will be used by WPM to generate the map(s).
Each sample is assigned a unique ID, which will be used to name the samples onto the plate maps (for more details on the ID see the Results section ).

Dataset vizualisation

Dataset vizualisation

IMPORTANT Please ensure that the dataset is correctly displayed in the right window and that the number of samples / groups is correct.
If you see that the total number of samples is wrong, this means that you have not chosen the appropriate options among those described above and you need to set the correct ones.

3.3.2 Choose a Project name

This step is optional. If you provide one, it will be used in the plots titles and in the name of the final dataset.

3.3.3 Plate(s) dimensions

Here you have to specify the plate dimensions and their number. Currently, WPM supports plate dimensions of 6,24, 48, 96, 386, 1534 wells and a custom option (where you specify the number of lines and columns by hand).

To the right of step 2 you can see an information box, warning you that WPM will distribute the samples in a balanced manner within the plates (if there are several).

balanced way message

balanced way message

If you select a plate size compatible with the total number of samples, you will see two blues boxes and a plate plan appear on the right summarizing all of your configuration. In the example below, we selected the pre-defined dimension of 96 wells and only one plate:

plate dimensions example

plate dimensions example

The right side of the panel will summarize all these parameters:

parameters summary

parameters summary

This plot updates with each modification of the parameters, thus making it possible to see if one has made an error.

IMPORTANT: If WPM detects a problem or incompatibility between parameters, you will see an error message instead of the plate map, explaining you what could be the problem.

Example of error message

Example of error message

3.3.4 Forbidden wells

In this step are listed the Forbidden wells if any (optional):

A Forbidden well will not be filled with any kind of sample. We simply do not want to fill them (e.g. the coins of the plate), or in case of dirty wells, broken pipettes, etc.

You fill the text input with the coordinates of the wells (a combination of letters and numbers like in the example below):

Example of forbidden wells listed in the text input

Example of forbidden wells listed in the text input

You will see the plot updated in the right section:

Updated plot with forbidden wells

Updated plot with forbidden wells

The wells filled with forbidden wells will have the “forbidden” ID in the final dataset.

3.3.5 Buffers

At this stage you can specify the wells which correspond to buffers, if there are any.

A buffer well corresponds to wells filled in with solution but without biological material (e.g. to avoid cross-contamination).

Five patterns are available for placing the buffers:

1) no buffers: there will be no buffer on the plate(s).

2) Per line: Automatically places buffers every other line. You can choose to start placing in even or odd line.

Per line mode example with even option

Per line mode example with even option

3) Per column: Automatically places buffers every other column. You can choose to start placing in even or odd column.

Per Column mode example with even option

Per Column mode example with even option

4) Checkerboard: Automatically places buffers like a checkerboard.

Checkerboard mode

Checkerboard mode

5) Choose by hand: It is the same procedure as for specifying forbidden wells.

3.3.5.1 Specify the neighborhood constraints

These are the spatial constraints that WPM needs to create the plates. Currently, 4 types of them are proposed. Note that the patterns are available only if they are compatible with the chosen buffer pattern. The question here is: Should samples from the same group be found side by side?

Schematically, the spatial constraints can be summarized as follows (the blue well is the current well evaluated by WPM; The wells in green are those assessed for compliance with the chosen constraint. The blue well therefore has the possibility (but not the obligation since the filling of the plate is done randomly) to be filled with a sample belonging to the same group as the samples in the wells evaluated.

No constraint

No constraint

North-South constraint

North-South constraint

East-West constraint

East-West constraint

North-South-East-West constraint

North-South-East-West constraint

The wells filled with buffer wells will have the “buffer” ID in the final dataset.

3.3.6 Fixed wells

At this stage you can specify the wells which correspond to fixed wells, if there are any.

A fixed well corresponds to quality control samples or standards, the precise location of which must be controlled by the experimenter.

This step works in exactly the same way as the forbidden well step. The only difference is that the fixed will appear in black on the plot.

The wells filled with fixed wells will have the “fixed” ID in the final dataset.

3.3.7 Number of iterations

Here you choose a maximum number of iterations that WPM is authorized to find a solution (the default value is 20, but if your configuration is somewhat complex, then it is advisable to increase this number). Afterwards, start WPM by clicking the “start WPM” button. An iteration corresponds to an attempt by WPM to find a solution. The algorithm used is not “fully” backtracked: WPM stops as soon as there are no more possibilities to finalize the current solution, and starts from scratch the plate map, until providing a solution that complements all the constraints. With this approach, not all possible combinations are explored, but it does reduce execution time.

When you start WPM, a progress bar shows which iteration WPM is at.

If WPM finds a solution, you will see this pop in the browser, inviting you to go to the Result Panel:

WPM succeeded

WPM succeeded

If WPM fails, an error message will appear, prompting you to try again:

WPM failed

WPM failed

IMPORTANT If after launching WPM and generating the results, you realize that one or more parameters do not work, you can always return to the “Parameters” tab and modify them. The data displayed in the “Results” tab will not be automatically changed, you will have to click again on the “start WPM” button to take into account the new changes.

NOTE If you want to create a new plate plan for another project, press ctrl + f5, this will reset the application.


3.4 The Results tab

This tab allows you to look after the final dataset containing the wells chosen for each sample:

Final dataframe

Final dataframe

The dataset contains 7 columns giving all the information needed to run the experiment: The sample name with its corresponding group; its ID for the plot; the well chosen; the row and the column to which the well corresponds and the number of the plate on which the sample must be placed during the experiment.

This tab also shows you the generated plot(s) of your final well-plate map(s). One color corresponds to one group level. The numbers are the IDs used in place of the sample names which could be too long and make the plot unreadable.

Below is an example of 80 samples distributed in 10 groups and placed on a 96 well-plate, with the North-South-East-West neighborhood constraint:

Plate map

Plate map

Dataset and plots are downloadable separately.

4 How to use WPM using command lines

As explained before, WPM can also be used through R command lines by following these steps:

  1. Create the dataset for WPM
  2. Run WPM
  3. Visualize the final plate plan(s)

4.1 Prepare the dataset

The user can work with CSV files, ExpressionSet, MSnSet or SummarizedExperimentobjects. The first step is to create a dataframe containing all the data needed by wpm to work properly. To do so:

4.1.1 Starting from a CSV file, then run:

imported_csv <- wpm::convertCSV("path-to-CSV-file")

4.1.2 Starting from an ExpressionSet or MSnSet object

sample_names <- c("s1","s2","s3","s4", "s5")
M <- matrix(NA, nrow = 4, ncol = 5)
colnames(M) <- sample_names
rownames(M) <- paste0("id", LETTERS[1:4])
pd <- data.frame(Environment = rep_len(LETTERS[1:3], 5),
                 Category = rep_len(1:2, 5), row.names = sample_names)
rownames(pd) <- colnames(M)
my_MSnSet_object <- MSnbase::MSnSet(exprs = M,pData =  pd)

then run convertESet by specifying the object and the variable to use as grouping factor for samples:

df <- wpm::convertESet(my_MSnSet_object, "Environment")

4.1.3 Starting from a SummarizedExperiment

nrows <- 200
ncols <- 6
counts <- matrix(runif(nrows * ncols, 1, 1e4), nrows)
colData <- data.frame(Treatment=rep(c("ChIP", "Input"), 3),
                      row.names=LETTERS[1:6])
se <- SummarizedExperiment::SummarizedExperiment(assays=list(counts=counts),
                                                 colData=colData)
df <- wpm::convertSE(se, "Treatment")

4.2 Run WPM

The next step is to run the wpm wrapper function by giving it all the parameters needed. For more details on the parameters, please see the sections about plate dimensions, forbidden wells, buffers, Quality Control wells and Spatial constraints.

In this toy example, we do not specify any buffer well.

4.2.1 After importing a CSV file

wpm_result <- wpm::wrapperWPM(user_df = imported_csv$df_wpm,
            plate_dims = list(8,12),
            nb_plates = 1,
            forbidden_wells = "A1,A2,A3",
            fixed_wells = "B1,B2",
            spatial_constraint = "NS")

4.2.2 after importing an ExpressionSet, MSnSet or SummarizedExperiment

wpm_result <- wpm::wrapperWPM(user_df = df,
            plate_dims = list(8,12),
            nb_plates = 1,
            forbidden_wells = "A1,A2,A3",
            fixed_wells = "B1,B2",
            spatial_constraint = "NS")
##   Sample     Group ID Well    Status Row Column
## 1   <NA> forbidden NA   A1 forbidden   1      1
## 2   <NA> forbidden NA   A2 forbidden   1      2
## 3   <NA> forbidden NA   A3 forbidden   1      3
## 4   <NA>     fixed NA   B1     fixed   2      1
## 5   <NA>     fixed NA   B2     fixed   2      2
## 2020-10-28 00:16:40 INFO::max_iteration: 20
## 2020-10-28 00:16:40 INFO:backtrack/map:nrow(c): 6
## 2020-10-28 00:16:40 INFO::plate number 1
## 2020-10-28 00:16:40 WARNING:fonctions.generateMapPlate:number of attempts: 1
## 2020-10-28 00:16:40 INFO:backtracking:class(new_df): data.frame

4.3 Plate map visualization

The last step is to plot the plate map(s) using:

drawned_map <- wpm::drawMap(df = wpm_result,
        sample_gps = length(levels(as.factor(colData$Treatment))),
        gp_levels = gp_lvl <- levels(as.factor(colData$Treatment)),
        plate_lines = 8,
        plate_cols = 12,
        project_title = "my Project Title")
drawned_map

Plots can be saved with:

ggplot2::ggsave(
    filename = "my file name",
    plot = drawned_map,
    width = 10,
    height = 7,
    units = "in"
)

IMPORTANT If multiple plates where specified, then wpm_result will be a list containing a dataset for each generated plate. Concretely, if 2 plates are generated, each of them can be accessed with wpm_result[[numberOfThePlate]]:

numberOfThePlate <- 1
drawned_map <- wpm::drawMap(df = wpm_result[[numberOfThePlate]],
        sample_gps = length(levels(as.factor(pd$Environment))),
        gp_levels = gp_lvl <- levels(as.factor(pd$Environment)),
        plate_lines = 8,
        plate_cols = 12,
        project_title = "my Project Title")

5 Citing Our work

The published article of the project will be linked here.

6 SessionInfo

sessionInfo()
## R version 4.0.3 (2020-10-10)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Ubuntu 18.04.5 LTS
## 
## Matrix products: default
## BLAS:   /home/biocbuild/bbs-3.12-bioc/R/lib/libRblas.so
## LAPACK: /home/biocbuild/bbs-3.12-bioc/R/lib/libRlapack.so
## 
## locale:
##  [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
##  [3] LC_TIME=en_US.UTF-8        LC_COLLATE=C              
##  [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
##  [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                 
##  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
## [1] BiocStyle_2.18.0
## 
## loaded via a namespace (and not attached):
##  [1] Rcpp_1.0.5                  lattice_0.20-41            
##  [3] digest_0.6.27               foreach_1.5.1              
##  [5] R6_2.4.1                    GenomeInfoDb_1.26.0        
##  [7] plyr_1.8.6                  mzID_1.28.0                
##  [9] stats4_4.0.3                evaluate_0.14              
## [11] ggplot2_3.3.2               highr_0.8                  
## [13] pillar_1.4.6                zlibbioc_1.36.0            
## [15] rlang_0.4.8                 magick_2.5.0               
## [17] S4Vectors_0.28.0            Matrix_1.2-18              
## [19] preprocessCore_1.52.0       rmarkdown_2.5              
## [21] mzR_2.24.0                  BiocParallel_1.24.0        
## [23] stringr_1.4.0               ProtGenerics_1.22.0        
## [25] RCurl_1.98-1.2              munsell_0.5.0              
## [27] DelayedArray_0.16.0         compiler_4.0.3             
## [29] xfun_0.18                   pkgconfig_2.0.3            
## [31] BiocGenerics_0.36.0         pcaMethods_1.82.0          
## [33] htmltools_0.5.0             tidyselect_1.1.0           
## [35] SummarizedExperiment_1.20.0 GenomeInfoDbData_1.2.4     
## [37] tibble_3.0.4                bookdown_0.21              
## [39] logging_0.10-108            IRanges_2.24.0             
## [41] codetools_0.2-16            matrixStats_0.57.0         
## [43] XML_3.99-0.5                crayon_1.3.4               
## [45] dplyr_1.0.2                 MASS_7.3-53                
## [47] bitops_1.0-6                grid_4.0.3                 
## [49] gtable_0.3.0                lifecycle_0.2.0            
## [51] affy_1.68.0                 magrittr_1.5               
## [53] scales_1.1.1                ncdf4_1.17                 
## [55] stringi_1.5.3               impute_1.64.0              
## [57] farver_2.0.3                XVector_0.30.0             
## [59] affyio_1.60.0               doParallel_1.0.16          
## [61] limma_3.46.0                ellipsis_0.3.1             
## [63] generics_0.0.2              vctrs_0.3.4                
## [65] RColorBrewer_1.1-2          iterators_1.0.13           
## [67] tools_4.0.3                 Biobase_2.50.0             
## [69] MSnbase_2.16.0              glue_1.4.2                 
## [71] purrr_0.3.4                 MatrixGenerics_1.2.0       
## [73] parallel_4.0.3              yaml_2.2.1                 
## [75] colorspace_1.4-1            BiocManager_1.30.10        
## [77] vsn_3.58.0                  GenomicRanges_1.42.0       
## [79] MALDIquant_1.19.3           wpm_1.0.0                  
## [81] knitr_1.30