Quadrants

When reformatting 96 well plates into 384 with fixed tip 96 channel liquid handling robot, the layouts of the destination plate is predetermined and matches the source layout, only replicated four times. Each source plate is deposited into a “quadrant” of the destination plate, such that a quadrant is defined as the wells across the destination plate that accomodate the samples from one source plate.

In the image below, quadrants are indicated for wells A01, A02, B01, and B02. Additional wells that belong to quadrant 1 are indicated. Note that quadrant 1 wells extend across the 384 well plate down to well O23.

The following images explicitly define the indicated quadrant with a filled in square:

Q1

Q2

Q3

Q4

A simplifying assumption made by LIMS*Nucleus is that during a reformatting operation, source plates are added sequentialy in a Z pattern such that plate 1 is deposited into quadrant 1, plate 2 into quadrant 2, etc.:

The process of transferring four 384 well plates into a 1536 well plate is analogous to what is described above.

Rearray

Rearraying is the process of transferring hits from one or more plates into a new plate set. Hits are transferred in sample id order, into plates by column. In the example below, hits are the black wells across 3 plates, being transferred into a single plate:

To initiate a rearray operation start by navigating into a hit list by clicking on the hit list URL. Scroll down to see the list of plate sets that contain the hits of interest. Here I am looking at HL-1:

Note there are 10 hits total. Two plate sets are suggested, but the 384 well plate set is a transient assay plate that contains the hits in duplicate. Use the plate type as a guicde as to which plates might contain the samples. The master plate set PS-1 is selected. Under the tools icon select ‘Rearray’:

The rearray form will appear, with an auto-generated description which you can edit. Fill in the required information and click ‘Submit’.

Confirm the information and select the controls layout. You are then directed to the plate set page where you can see the new plate set PS-20 of hits:

Field Description
Name freeform text, a descriptive name
Description auto-populated but editable
Format 96, 384 well plates are possible destination formats
Type Rearray suggested but user selected
Sample Layout Choose a layout; layout “description” appears in this dropdown

In the plate set view, the newly created PS-20 in PRJ-1 is visible with its informative description. There is also a worklist associated with the plate set because it was created using a rearray operation.

Generate a view of the worklist:

Now to physically transfer the samples from PS-1 to the new plates of PS-20, export the worklist to Excel and import into a liquid handling robot to run the transfer:

Split plate sets

Only plate sets can be split. You can think of splitting a plate set as a regrouping of plates within a plate set. Navigate into the plate set of interest containing the plates to be grouped and highlight the plates. Select Utilities/Group from the menu bar:

A dialog will open. Fill in the name and description for the new plate set. The plates must be of the same format and layout, which will be indicated in the dialog box. Select a plate type and press OK.

Tutorial 1 - Canonical workflow

Using the demonstration data, work through a cononical workflow. This tutorial is available as a video

Create a new plate set by reformating

Using the demonstration data, reformat Project 10, Plate Set 6, 10 96 well plates, into 384 well assay plates with a replication of 1. Navigate into Project 10 and select plate set 6:

Select reformat to be presented with the reformat form. The top panel provides information about the source plate set, and the bottom panels requests information on the design of the destination plate set. I will use sample replicates of 1 and target replicates of 4 i.e. all 4 quadrants of the 384 well plate coated with the same target. This requires that I define the layout as 1S4T.

Pressing Submit brings you to the confirmation page where you have the opportunity to select the target layout. I will get a new Plate Set #8, assuming no earlier modifications were made to the demo data. Navigate into PS-8 and note that there are 3 plates, 30-32, with 32 only half filled. I am ready to load data.

Apply barcode IDs to plates, Accession IDs to samples

Applying barcode and accession IDs is optional. The purpose of these identifiers is to allow you to associate LIMS*Nucleus data with data in other systems. Start by selecting the Plate Set of interest, PS-8 in this case, and follow the directions for importing accession ids and barcode ids. Use the following data:

ID type File
accession ps8-accessions.txt
barcode ps8-barcodes.txt

Note that empty wells in the third plate do not have an entry in the acessions file. A template for loading the accession IDs can be generated by exporting the underlying plate set data. The columns of interest are “Order” and “Well” which must be relabeled “plate” and “well”. Also include the accession as “accs.id”.

Load assay data.

Download the demonstration tab delimitted data set plates384x3_1S4T.txt to your local drive. The plate layout looks like:

and the response values look like:

This might be an ELISA assay showing a majority of responses less than 0.5. There is good reproducibility amongst the controls, with a good assay window. With the destination plate set highlighted, select Utilities/Import assay data:

Fill in the dialog, substituting the path name with the path to the file on your computer. Note that the import form provides a sample of what the import data should look like. Column order, spelling and capitalization are critical. After file selection the first few rows of data are displayed for confirmation:

I want hits automatically identified using a built in algorithm so I select the option mean +3SD in the algorithm dropdown so that all responses greater than the mean of the background wells + 3 standard deviation units are considered a hit. Because I am auto-identifiying hits, the add hit list name and description fields become active giving me the opportunity to name and describe the hit list. I did NOT select Top N as the selection algorithm so the number of desired hits field remains inactive:

Click import data. Not that the import button changes to ‘Loading…’. Do not reclick. Depending on the size of the data, import could take many seconds. Once complete you will be presented with the list of plates for the current plate set. Scroll down to see assaciated hit lists - HL-7 being the just created hit list:

View the Assay Run

Click on the assay run hyperlink AR-6, to view the data under default conditions - normalized with a threshold of mean of the negative controls plus 3 standard deviations. Controls are color coded:

Below the plot is a form for replotting under different conditions of normalization and thresholding. After replot, the tools menu allows for the viewing of hits above the selected threshold and the creation of a hit list if desired.

View the Hit List

To view a hit list, select the menu item under the tools icon. In the hit list view you can inspect the hits and are given the opportunity to save the list. Enter and name and description, and select ‘Add New Hit List’ from the tools menu:

Upon successful creation of the hit list you are presented with its parent assay run. Scroll to the bottom to see the newly created hit list:

Rearray

At this point you are ready to rearry your hits into a new plate set for secondary assay or further processing. Note that HL-7 contains 162 samples. Click on the ‘HL-7’ hyperlink to view the hit list. Scroll to the bottom to see the availability of hits in various plate sets:

In our simplistic demonstration data set, it is obvious that the parental samples for our assay plate set are in plate set 6. In real life processing, samples may get distributed across many plate sets. Use the type and count fields to help determine an appropriate source of samples for rearray. Assay plates are typically transient and not a source of material for rearraying. You must establish type naming conventions for your plate set, for example archive plates or master/daughter/rearry plates contain samples while assay plates are transient. In the demo data PS-6 is labeled “master”, which helps identify a plate that contains the parent samples. Assay plates are typically transient and not a source for sample recovery.

The count field is to confirm that a particular plate set contains (or not) all the hits of interest. If no single plate set contains all hits, you may have to group plate sets.

Select the plate set that will serve as the rearry source and select “Rearry” using the tools button. This will initiate the production of a new plate set that will contain hits only:

Provide the requested information and press “Submit”. You will then have the opportunity to select the layout of controls. The number of plates required will be automatically calculated and hits will be distributed in numerical order by column into the plates. Since this is a rearray plate, and not an assay plate, the target is auto-assigned to DefaultQuadruplicates, which is inconsequential. To achieve the physical rearry in the lab a worklist is generated and associated with the plate set. Indication that a plate set was generated by a worklist is the presence of the worklist ID in the “worklist” column in the plate set view. Only plate sets generated by a rearray have an integer in the “worklist” column. The worklist is permanently stored in the database and can be recalled by selecting the plate set and using the tools icon select ‘Worklist’.

The worklist will be displayed:

The worklist can be exported to e.g. Microsoft Excel or LibreOffice Calc, depending on what your computer has associated with the .CSV extension:

This worklist can be used with a liquid handling robot such as a Beckman Biomek, to perform the physical rearry.

Tutorial 2 is a repeat of the canonical workflow, this time using an assay plate layout that allows for duplicate samples.

Artanis modifications needed for Guix packaging

Note: These modifications are incorporated into Artanis v1.0.0 (2025)

This page discusses modification to the Artanis web server softare required for packaging an Artanis application. Guidelines for writing a Guix compatible Artanis application can be found here.

Artanis

GNU Artanis is a web server written in Guile (a scheme dialect). Artanis -the web server software - has been packaged for Guix. The packaging recipe can be found in …/gnu/packages/guile-xyz.scm. Artanis applications such as LIMS*Nucleus are not by default packageable by guix due to the presence of a writeable ../tmp directory in the application folder. Here is the partial directory structure of LIMS*Nucleus:

The directory ../limsn/limsn/tmp holds temporary files created while users are navigating the application. Since the Guix store is immutable, a temporary folder is not allowed and must be moved outside of the application. Artanis defines a variable ‘current-toplevel’ which, in the above example would be ../limsn/limsn. In the labsolns modified artanis all references to ‘current-toplevel’ are divided into two groups:

variable description
1 current-toplevel redirected to /tmp/limsn i.e. references that create a temporary file
2 immutable-toplevel references that point to the original ‘current-toplevel’ i.e. references that do not create files and can reside in the immutable /gnu/store… directory

Source Code Modifications

To allow for Guix packaging of Artanis applications the following modifications to the Artanis source code are introduced during packaging:

File line Modified source code
utils.scm 279 (if (immutable-toplevel)
280 (format #f “~a/pub/~a” (immutable-toplevel) path)
833 (let* ((toplevel (immutable-toplevel))
1309 (immutable-toplevel) file)))
tpl/parser.scm 40 (format #f “~a/~a/~a” (immutable-toplevel) pub args))))
52 (mfile (format #f “~a/~a/manifest.json” (immutable-toplevel) path))
commands/work.scm 77 (let ((entry (string-append (immutable-toplevel) “/” *artanis-entry*)))
126 (add-to-load-path (immutable-toplevel))
mvc/controller.scm 45 (immutable-toplevel) ’name method)))
62 (define toplevel (immutable-toplevel))
webapi/restful.scm 58 (load (format #f “~a/app/api/~a.scm” (immutable-toplevel) s)))

Recipe File Modifications

The above changes are introduced during the installation of Artanis. Recipe file additions are:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
	  ;;============START forguix mods=========================================================================
;;immutable-toplevel is the original current-toplevel in /gnu/store
;;current-toplevel is the mutable toplevel in /tmp/<appname>/tmp/cache

(substitute* "artanis/commands/work.scm"
(("\\(let \\(\\(entry \\(string-append \\(current-toplevel\\) \"/\" \\*artanis-entry\\*\\)\\)\\)")
"(let ((entry (string-append (immutable-toplevel) \"/\" *artanis-entry*)))")
(("\\(add-to-load-path \\(current-toplevel\\)\\)")
"(add-to-load-path (immutable-toplevel))")
(("\\(add-to-load-path \\(string-append \\(current-toplevel\\) \"/lib\"\\)\\)")
"(add-to-load-path (string-append (immutable-toplevel) \"/lib\"))"))
(substitute* '("artanis/tpl/parser.scm"
"artanis/mvc/controller.scm"
"artanis/webapi/restful.scm")
(("current-toplevel")
"immutable-toplevel"))
(substitute* "artanis/utils.scm"
(("\\(let\\* \\(\\(toplevel \\(current-toplevel\\)\\)")
"(let* ((toplevel (immutable-toplevel))")
(("\\(current-toplevel\\) file\\)\\)\\)")
"(immutable-toplevel) file)))")
(("\\(if \\(current-toplevel\\)")
"(if (immutable-toplevel)")
((" \\(let \\(\\(p \\(-> path\\)\\)\\)")
" (let ((p (-> path))(dummy (format (artanis-current-output) \"current-appname: ~a\" (current-appname) )))")
(("\\(format \\#f \"~a/pub/~a\" \\(current-toplevel\\) path\\)")
"(format #f \"~a/pub/~a\" (immutable-toplevel) path)")
)
(substitute* "artanis/env.scm"
((" current-toplevel\n")
" current-toplevel\n %immutable-toplevel\n immutable-toplevel\n")
(("\\(define \\(current-toplevel\\)\n")
"(define %immutable-toplevel (make-parameter #f))\n")
((" \\(or \\(%current-toplevel\\)\n")
" (define (immutable-toplevel)\n")
((" \\(find-ENTRY-path identity #t\\)\\)\\)\n")
" (or (%immutable-toplevel)\n (find-ENTRY-path identity #t)))\n\n(define (current-toplevel) (string-append \"/tmp/\" (and=> (string-match \".+/(.+)$\" (getcwd)) (lambda (m) (match:substring m 1))))) ")

) ;;use of (current-appname) causes disk thrashing and freezing
;; (find-ENTRY-path identity #t) evaluates to #f and so can't be used

;;============END forguix mods=========================================================================

Get the modified Artanis software

  1. Set up your system so that you can utilize the labsolns channel
  2. guix pull
  3. guix edit artanis (to see the recipe)
  4. guix package -i artanis (to install or upgrade to the modified Artanis)

Caution

Note that the Guix modified Artanis is labeled as v0.5.2 and so (Sept 2022) will “upgrade” your copy of Artanis.

Guix modified Artanis has been tested with LIMS*Nucleus. Modifications may have broken Artanis features that are not used by LIMS*Nucleus.

Request for Invoice

Thank you for your request.

An invoice in the amount of $5000 for a LIMS*Nucleus license key will be emailed to:

info@labsolns.com

Table of Contents

Group plate sets

Only plate sets can be grouped. Navigate into the project of interest containing the plate sets to be grouped and highlight the plate sets. Select Utilities/Group from the menu bar:

A dialog will open. Fill in the name and description for the new plate sets. The source plate sets must be of the same format and layout, which will be indicated in the dialog box. Select a plate type and press OK.

hitlist

A list of samples of interest Must have a header road named “name” One sample per line, no separator Primarily used to cherry pick samples from plate to plate

Next:

LIMS*Nucleus - Multi-Well Plate Management Software

LIMS*Nucleus is a software program used to manage multi-well plates in an academic or industrial environment. Functionality includes:

  • Generate 96, 384 or 1536 well plates with or without samples
  • Collect plates into plate sets
  • Group or split plate sets
  • Reformat plates - four 96 well plates into a 384 well plate; four 384 well plates into a 1536 well plate
  • Associate assay data with plate sets
  • Identify hits scoring in assays using included algorithms - or write your own
  • Export annotated data
  • Generate worklists for liquid handling robots
  • Rearray hits into a smaller collection of plates
  • Prototype algorithms, visualization with R/Shiny
  • Evaluate an online instance
  • Video overviews of features and capabilities

LIMS*Nucleus has a restricted set of features - multi-well plate management, hit identification, rearraying - and serves as the core of a larger system. Source code is available for modification. The architecture is simple client/server with no middleware or ORM. The client utilizes Bootstrap/Datatables and the database is PostgreSQL The software is packaged as a Guix pack for easy installation/configuration. R/Shiny dashboards can be used to extend functionality.

Next: Monoliths vs Systems

Mutation Visualization

Compare parental and mutant sequences

After perfoming error prone PCR (random) or oligonucleotide (directed) mutagenesis you will want to visualize your sequences and determine the rate of mutation incorporation. A typical visualization is the stacked bar chart as in this figure from Finlay et al. JMB (2009) 388, 541-558:

To decode this graphic you must:

  • estimate the percentage of each amino acid by comparison to the Y axis
  • compare relative amino acid abundance by comparing the area of boxes
  • correlate color with amino acid identity
  • compare to the reference sequence at the bottom of the graph

An easier to interpret graphic would be a scatter plot of sequence index (i.e. nucleotide position) on the X axis vs frequency on the Y. The data points are the single letter amino acid code. Highlight the reference sequence with a red letter.

The first step is to align all sequences. Start with a multi-fasta file of all sequences:


$cat ./myseqs.fasta

>ref
GLVQXGGSXRLSCAASGFTFSSYAMSWVRQAPGKGLEWVSAISGSGGSTYY
ADSVKGRFTISRDNSKNTLYLQMNSLRAEDTAVYYCAKDHRRPKGAFDIWGQGTMVTVSS
GGGGSGGGGSGGGGSGQSALTQPASVSGSPGQSITISCTGTSSDVGAYNYVSWYQQYPGK
APKLMIYEVTNRPSGVSDRFSGSKSGNTASLTISGLQTGDEADYYCGTWDSSLSAVV
>BSA130618a-A01
glvxxggxxrlscasgftfssyamswvrqapgklewvsaisgsggstyysdsvkgrftissdnskntlylqmnslraedt
avyycakdhrrpkgafdiwgqgtmvtvssggggsggggsggggsgqsaltqprsvsgtpgqsviisctgtssdvggskyv
swyqqhpgnapkliiydvserpsgvsnrfsgsksgtsaslaitglqaedeadyycqsydsslvvf
>BSA130618a-A02
glvqpggxxrlscasgftfssyamswvrqapgkglewvsaisgsggstyyadsvkgrftisrdnskntlylqmnslraed
tavyycakdhrrpngafdiwgqgtmvtvssggggsggggsggggsgqsvvtqppsmsaapgqkvtiscsgsssnignnyv
swyqqlpgtapklliydnnkrpsxipdrfsgsksgtsatlitglqtgdeadyycgtwdsslsagvf
>BSA130618a-A03
glvqxggxxrlscasgftfssyamswvrqapgkglewvsaisgsggstyyadsvkgrftisrdnskntlylqmnslraed
tavyycakdhrrpkgafdiwgqgtmvtvssggggsggggsggggsgsyeltqppsvsvspgqtasitcsgsssniginyv
swyqqvpgtapklliyddtnrpsgisdrfsgsksgtsatlgitglqtgdeadyycgtwdsslsvvvf

Above I have labeled my parental reference sequence “ref”. Use clustalo to perform the alignment and request the output in “clustal” format. The clustalo command can be run from within R using the system command. Read the alignment file into a matrix:

  input.file <- paste( getwd(), "/out.fasta", sep="")
  output.file <-  paste( getwd(), "/out.aln", sep="")
  system( paste("c:/progra~1/clustalo/clustalo.exe -infile=", input.file, " -o ", output.file, ".aln --outfmt=clustal", sep=""))   
 
 in.file <- paste(getwd(), "/out.aln", sep="")  
 seqs.aln <- as.matrix(read.alignment(file = in.file, format="clustal"))

At each position determine the frequency of all 20 amino acids. Set up a second matrix that has one dimension as the length of the sequence and the other as 20 for each amino acid. This is the matrix that will hold the amino acid frequencies.

The R package “seqinr” provides a constant containing all single character amino acids as well as asterisk for the stop codon. Use this to name the rows of the frequency matrix.

    library(seqinr)
levels(SEQINR.UTIL$CODON.AA$L)

[1] "*" "A" "C" "D" "E" "F" "G" "H" "I" "K" "L" "M" "N" "P" "Q" "R" "S" "T" "V"
[20] "W" "Y"

aas <- c(levels(SEQINR.UTIL$CODON.AA$L), 'X')
freqs <- matrix(  ncol=dim(seqs.aln)[2], nrow=length(aas))
rownames(freqs) <- aas

#Process through the matrix, calculating the frequency for each amino acid.
for( col in 1:dim(aligns)[2]){
     for( row in 1:length(aas)){
          freqs[row, col] <- length(which(toupper(seqs.aln[,col])==aas[row]))/dim(seqs.aln)[1]
      }
}

Set up an empty plot for Frequency (Y axis) vs nucleotide index (X axis). Y range is 0 to 1, X range is one to the length of the sequence i.e. the number of columns in the frequency matrix. Plot frequencies >0 in black, using the single letter amino acid code as the plot character.

    plot(1, type="n", xlab="Sequence Index", ylab="Frequency", xlim=c(1, dim(freqs)[2]), ylim=c(0, 1))
for( i in 1:length(aas)){
       points( which(freqs[i,]>0), freqs[i, freqs[i,]>0], pch=rownames(freqs)[i], cex=0.5)
       }

Overlay the reference sequence in red.

ref <-seqs.aln[rownames(seqs.aln)=="ref",]
for(i in 1:length(ref)){
     if(  length( freqs[rownames(freqs)[rownames(freqs)==toupper(ref[i])],i] ) > 0){
    if(freqs[rownames(freqs)[rownames(freqs)==toupper(ref[i])],i] > 0){
                  points( i,freqs[rownames(freqs)[rownames(freqs)==toupper(ref[i])],i]  , pch=toupper(ref[i]), cex=0.5, col="red")
              }
            }
    }

This is what it looks like (open in a new tab to see detail):

It’s easy to see which amino acid is parental, and its relative abundance to other amino acids is clear.
Consider position 61: N is the parental amino acid but T is now more abundant in the panel of mutants. K and S are the next most abundant amino acids.

Should multiple amino acids have the same or close to the same frequency, the graph can get cluttered and difficult to interpret. Adjusting the Y axis can help clarify amino acid identity. At each position percentages may not add up to 100 depending on the number of gaps. Consider the sequence “RFSGS” at positions 69-73 which is in a region containing gaps for some of the clones:

Installation

Edit your channels.scm file to include the labsolns channel

Once edited:


$guix pull
$guix package -i mutvis
$source $HOME/.guix-profile/etc/profile

##run the bash script

$mutvis.sh