LIMS*Nucleus Client Installation

The LIMS*Nucleus client is distributed and installed as a Guix Package. The name of the LIMS*Nucleus package is ‘limsn’. For the package to be available to your system, you must first modify your channels.scm file to include the labsolns channel. You can then issue the install command:

1
guix package -i limsn

This will install not only LIMS*Nucleus but also all of its dependencies, as well as configuration scripts and sql scripts for setting up the database. You may have already set up the database in which case you only need to configure artanis.conf. The sequence of scripts that need to be run are:

Sequence Script Name Function
1 init-limsn.sh create directories that hold temp files and the configuration file; modify .bashrc
2 install-pg-aws.sh install the Postgres database; install-pg-aws.sh is designed for AWS, there are other options
3 start-limsn.sh start the client; run in background mode if desired with ‘nohup’

Other options, such as the AWS installation script will automatically run the init-limsn.sh and install-pg-aws.sh scripts for you.

Artanis applications suitable for Guix packaging

This page discusses the guidelines for writing an Artanis application such as LIMS*Nucleus that is suitable for Guix packaging. If you are looking for modifications needed in the Artanis source code, look here.

Write a Guix packageable Artanis application

First read the discussion on modifications required to the Artanis source code so you are aware that all temporary files created by your application must be moved to a directory outside the application directory. In addition, Artanis’ cache must be move outside the application directory, as well as artanis.conf so it remains editable. These activities can be handled with a post installation initialization file.

One time initialization

Because your artanis app needs some directories outside of the application directory to work with temporary files, configuration files etc., a one time initialization script can be run to set up your server. The overall process would look like:

  1. guix package -i limsn
  2. init-limsn.sh
  3. install-pg-aws.sh
  4. start-limsn.sh

The initialization file would create required directories and copy over the artanis.conf file. Note that the placeholder PATH_INTO_STORE is replaced on installation by the path into the store.

init-limsn-channel.sh
1
2
3
4
5
6
7
8
9
10
#! /bin/bash
export LC_ALL="C"
echo export LC_ALL=\"C\" >> $HOME/.bashrc
echo export GUIX_PROFILE=$HOME/.guix-profile >> $HOME/.bashrc
echo . $HOME/.guix-profile/etc/profile >> $HOME/.bashrc
echo export GUIX_LOCPATH=$HOME/.guix-profile/lib/locale >> $HOME/.bashrc

sudo mkdir -p $HOME/.config/limsn
sudo cp PATH_INTO_STORE/share/guile/site/3.0/limsn/conf/artanis.conf $HOME/.config/limsn

artanis.conf

Because a configuration file outside the project directory is being used, you can use a startup script to launch your application:

start-limsn.sh
1
2
3
4
5
6
#!/bin/bash
!#
export LC_ALL="C"
mkdir -p /var/tmp/limsn/tmp/cache
cd PATH_INTO_STORE/share/guile/site/3.0/limsn
art work -h0.0.0.0 --config=$HOME/.config/limsn/artanis.conf

In this example -h0.0.0.0 is needed for running on Amazon Web Services

GNUPLOT

With regular Artanis Gnuplot can be run on the server and generate *.png files in the ../pub directory that are accessible to the .html.tpl file via:

page1.html.tpl
1
<image src= <%= myplot %>>

Where in the above snippet the variable myplot == “../pub/myplot.png”. With guix modified Artanis, the .png file would have to go into /tmp/limsn and would become inaccessible due to security restrictions. To get around this, load the myplot variable with svg commands. This is accomplished by first creating the gnuplot script with the following commands:

my-gnuplot-script.txt
1
2
3
4
5
6
reset session
set terminal svg size 800,500
save '-'
set key box ins vert right top
set grid
...etc.

The ‘save’-’’ statement will save to standard output so that you can pipe into your variable. Here is a helper function that will collect the svg commands:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
(use-modules (ice-9 regex) ;;list-matches
(ice-9 textual-ports)
(ice-9 rdelim) ;;read-line
(ice-9 popen))

(define (get-svg-content gnuplot-script-file)
;;requires: set terminal svg size 600,400
;; save '-'
;;in the script
;;gnuplot-script-file is the script as a text variable
(let* ((port (open-input-pipe (string-append "gnuplot " gnuplot-script-file)))
(a "")
(dummy (let loop ((line (read-line port)))
(if (not (eof-object? line))
(begin
(set! a (string-append a line))
(loop (read-line port))))))
(dummy (close-pipe port))
(dummy (pretty-print a))
(coord-start (string-match "<svg width=" a ))
(coord-end (string-match "</g></svg>" a)))
(xsubstring a (match:start coord-start) (match:end coord-end))
))

Then in your controller:

mycontroller.scm
1
2
(let* ((myplot-svg (get-svg-content gnuplot-script-file))
etc....

And in the web page template:

page1.html.tpl
1
<%= myplot-svg %>

Now in the above snippet myplot-svg == ’<svg width=“600” height=“350” viewBox=“0 0 600 350” xmlns=“http://www.w3.org/2000/svg” xmlns:xlink=“http://www…etc….”

Application specific variables

Application specific variables are defined in ENTRY such as:

ENTRY
1
2
3
...
(conf-set! 'maxnumplates 100)
...

Since ENTRY is in the store, this will only work for variables that are not available to the end user for (re)setting. To provide editable application specific variables, put them in artanis.conf. Variables are grouped in artanis.conf. LIMS*Nucleus specific variable ‘maxnumplates’ is placed in the ‘cookie’ group for convenience, even though it is not a cookie.

artanis.conf
1
cookie.maxnumplates = 100

artanis/config.scm must be patched appropriately:

artanis/config.scm
1
2
3
4
5
6
7
8
(substitute* "artanis/config.scm"		
((" \\(else \\(error parse-namespace-cache \"Config: Invalid item\" item\\)\\)\\)\\)")
"(else (error parse-namespace-cache \"Config: Invalid item\" item))))\n\n(define (parse-namespace-cookie item)\n (match item\n (('expire expire) (conf-set! '(cookie expire) (->integer expire)))\n (('maxplates maxplates) (conf-set! '(cookie maxplates) (->integer maxplates)))\n (else (error parse-namespace-cookie \"Config: Invalid item\" item))))"))

(substitute* "artanis/config.scm"
(("debug.monitor = <PATHs>\")")
"debug.monitor = <PATHs>\")\n ((cookie expire)\n 3600\n \"Cookie expiration time in seconds.\n 1 hour is 3600\n 6 hours 21600\n 1 month 2592000\n cookie.expire = <integer>\")\n\n ((cookie maxplates)\n 10\n \"Maximum number of plates per plate-set.\n cookie.maxplates = <integer>\")"))

Modify controller syntax

Controllers as they are written will generate a warning:

guix package: warning: failed to load ‘(limsn app controllers plates)’: no code for module (lims app controllers plates) /home/mbc/.guix-profile/share/guile/site/3.0/myapp/app/controllers/pages.scm:4:0: warning: module name (app controllers plates) does not match file name ‘limsn/app/controllers/plates.scm’ hint: File `/home/mbc/.guix-profile/share/guile/site/3.0/limsn/app/controllers/plates.scm’ should probably start with: (define-module (limsn app controllers plates))

Guix expects the first statement in a module to begin with (define-module ()….)
Artanis wants modules to (use-modules (artanis mvc controller))
Satisfy both requirements with:

plates.scm
1
2
3
4
5
6
7
8
9
10
11
12
13
(define-module (limsn app controllers plates)
#:use-module (artanis artanis)
#:use-module (artanis mvc controller)) ;;to eliminate error

;;error: define-artanis-controller: unbound variable
;;hint: Did you forget `(use-modules (artanis mvc controller))'?

(define-artanis-controller pages) ; DO NOT REMOVE THIS LINE!!!
;;libraries must be imported after define-artanis-controller
(use-modules (myapp lib mylib) )

(pages-define plates
(lambda (rc)......etc.

Be sure to import libraries after (define-artanis-controller )

Make Libraries accessible

Artanis provides the …./lib directory to hold libraries. This directory is placed on the GUILE_LOAD_PATH for you. To avoid warnings, you may wish to write your library as a module e.g. (define-module (limsn lib mylib)…) in which case you need to place your project directory on GUILE_LOAD_PATH with a statment in ENTRY such as:

(add-to-load-path (string-append (find-ENTRY-path identity #t) “/..”))

Another option is to create a separate package for your library, package separately, and make it available as an input.

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.

AWS EC2 Installation

Prerequisites

  • AWS username/password
  • EC2 key pair
  • (Static IP address) A transient IP is adequate and will be used in the video tutorial. Consider a static IP for production. A static IP address is free upon request, but must be used on a running instance. You will be charged for a static IP that is requested but not used.
  • Credit card number - a valid credit card is required to register. Note that these are Amazon requirements.

Installation

Note: the video tutorial of AWS EC2 installation of LIMS*Nucleus describes installation of an older version of LIMS*Nucleus. Though still useful to watch as the overall process and many details are the same, details discussed below supercede what is in the video. The main changes are different names for scripts are being used, LIMS*Nucleus is now packaged as a guix module and so is installed in the store, and because a guix pull must be performed the free tier t2.micro may not provide enough memory. Use t2.medium.

Local: download the archive of install scripts and transfer to AWS with scp:

1
home@HP8300:~$scp -i labsolns.pem $HOME/temp/limsn-ec2.tar.xz  admin@ec2-18-191-151-165.us-east-2.compute.amazonaws.com:.

You must modify the above command with your own keys and the connection address provided to you by Amazon.

AWS: decompress and run the install script:

1
2
admin@ip-172-31-23-11:~$tar -xvf ./limsn-ec2.tar.xz
admin@ip-172-31-23-11:~$./install-limsn-ec2.sh

install-limsn-ec2.sh and guix-install-mod.sh must be in the same directory. Multiple files described below are loaded into the store at PATH_INTO_STORE/limsn/scripts

Supplied Scripts

Scripts available on this website or in /gnu/store are described on the scripts page.

Useful commands

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
## start the database server
admin@ip-172-31-25-179:~$ pg_ctl -D /home/admin/lndata -l logfile start

## start the application in detached mode
admin@ip-172-31-25-179:~$ nohup ~/start-limsn.sh

## find the application PID
admin@ip-172-31-25-179:~$ps aux | grep art
admin 1219 1.3 5.5 153504 56172 ? Sl 12:25 0:00 /gnu/store/18hp7flyb3yid3yp49i6qcdq0sbi5l1n-guile-3.0.2/bin/guile \ /gnu/store/imh84i7rcckxd55nndhrnr0j7jr64ffv-artanis-0.5.1/bin/.art-real work -h 0.0.0.0

## kill the application
admin@ip-172-31-25-179:~$kill -9 1219


## delete the database
admin@ip-172-31-25-179:~$ rm -r lndata


## reinstall the database
admin@ip-172-31-25-179:~$ ./install-pg-aws.sh



Administrator

LIMS*Nucleus characterizes two types of users, regular users and administrators. LIMS*Nucleus users are unique to LIMS*Nucleus and not shared with the operating system nor database. Administrative functionality is listed in the table below.

Item Description
Add User Add a user and password
View all users
Add Project Add a new project; users cannot create projects, only use them
View sessions
Input License Credentials

Algorithms

Processing steps

  1. Import data, setting all negative values to 0.

    On a plate by plate basis:

  2. Calculate the average of all wells labeled “blank” to obtain plate specific backgound signal

  3. Subract backgound from all signals to obtain background subtracted values (bkgrnd_sub below) which are used in all further calculations

  4. Set all background subtracted values that are less than zero to zero

(4.5 For layouts utilizing duplicates (2S4T, 4S2T), average the duplicates)

  1. Calculate norm, norm_pos, p_enhance as described below

Background subtraction, normalization

Upon data import, raw values are stored and processed as described above, then the calculations below are performed to yield additional columns of stored data.

column Description
raw imported raw data
bkgrnd_sub mean of all wells annotated “blank” subtracted from each raw value;
norm all values normalized to the maximum of the background subtracted values annotated as “unknown”;
norm_pos all values normalized to the mean of the background subtracted values annotated as “positive”;
p_enhance Percent enhancement over the positive control;
100*(

Hit identification

Algorithm

Label Hit threshold
mean(neg) + 3SD
mean(neg) + 2SD
>0% enhanced
Top N Highest N responses from unknowns



### References

Sittampalam GS, Coussens NP, Brimacombe K, et al., editors. Assay Guidance Manual Internet. Bethesda (MD): Eli Lilly & Company and the National Center for Advancing Translational Sciences; 2004-.

Brian P. Kelley, 1 Mitchell R. Lunn, 1 David E. Root, Stephen P. Flaherty, Allison M. Martino, and Brent R. Stockwell; A Flexible Data Analysis Tool for Chemical Genetic Screens, Chemistry & Biology 11:1495–1503, November, 2004

Architecture

LIMS*Nucleus is amenable to a variety of installation configurations:

Example Client Server 1 Server 2
Data Center Web Browser Application Server Database Server
AWS/EC2 Web Browser Application & Database Server
Personal laptop Browser, Application & Database Server

Most of the LIMS*Nucleus business logic is implemented using Postgres stored procedures. The client utililizes Bootstrap/Datatables to guide/validate user input, and display results in table format.

Import Accession IDs

Accession IDs are imported by plate number/well number. The files page provides details on the file format, with a 2 plate sample file available. Navigate into the project of interest and select the plate set of interest. From the tool icon select Accessions under import:

A standard file import form will open - find the file and click submit. The number of lines expected will be calculated by querying the sample id count for the plate set. For example a plate set of two 96 well plates with 4 control wells per plate (no sample ids for controls) will require 2x(96-4)=184 accession ids. The control wells should not be included in the import file. For example a portion of the accession import file looks like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

plate well accs.id
1 1 AMRVK5473H
1 2 KMNCX9294W
1 3 EHRXZ2102Z
1 4 COZHR7852Q
.
.
.
1 89 BKLUY4714F
1 90 VHDTN3829S
1 91 XUTEZ7832G
1 92 EGTKM4119P
2 1 GWGJT9769W
2 2 TKSUP0061X
2 3 HLVOR2656F
2 4 TIYAO0501Y
2 5 YBBDN6102H
.
.
.

Once imported, accesion ids will appear in the well table:

Example accession ID import files:

File name Description
accs96x2controls4.txt Two 96 well plates with 4 controls in column 12
accs384x2controls8.txt Two 384 well plates with 8 controls in column 24
accs1536x2controls16x2.txt Two 1536 well plates with 16 controls, in duplicate, in columns 47, 48