Welcome to Pirus’s documentation!¶
Contents:
Presentation¶
- Pirus ( PIpeline RUnner Service) is a tool to manage installation and execution of informatic pipelines.
- Stand alone project
- Sub project of Regovar
Goals of Pirus¶
Pirus aimed at performing computing tasks taking as input files to produce results in the form of one or more files. First devised in order to perform bioinformatic pipelines as part of research and or medical diagnostics, Pirus is for both computer scientists developing these pipelines, as system administrators to ensure the computer server maintenance, that to end users.
Each of them have different needs :

Sys administrator | Bio informaticien | Clinician |
---|---|---|
|
|
|
Yes ! The solution exists ! Pirus !

Features¶
- Deployement with pip install [TODO]
- All in one product (server application, client web interface)
- One simple config file
- No exotics depencies, no weird customizations
- Virtual environment for pipeline execution (LXD container)
- API REST
- Easy to create a custom pipeline (few technical constraints)
- Resumable upload for big files
- Possibility to expose a simple interface to setup a pipeline (according to a unique json file)
- Push notification for Run progress
- Mail notification for Run status changed (when finished or when an error occured by example) [TODO]
- Run can be paused, resumed and canceled
Quick guide¶
- Deploye and use Pirus in 5 minutes. In the below tutorial :
- <HOST> : is the server host, by example “www.pirus.com”
- <PORT> ! is the port that will be use by the pirus python application, by example 8080
- <PIRUS_PATH> : is the path on the server where is deployed the pirus python application, by example “/var/pirus”
Installation¶
You need to have MongoDB and RabbitMQ installed on your system
sudo apt install rabbitmq-server
sudo apt install mongodb
sudo apt install lxd
sudo apt install nginx
You may need also to install
sudo apt install build-essential libssl-dev libffi-dev python3-dev virtualenv
You can then clone the repository and install requirements
git clone https://github.com/REGOVAR/Pirus.git
cd <PIRUS_PATH>
virtualenv -p /usr/bin/python3.5 venv
source venv/bin/activate
pip install -r requirements.txt
Using NginX¶
Create the file into /etc/nginx/sites-available/pirus with the following content
Replace <PORT> and <HOST> with the good value:
#
# Virtual Host configuration for <HOST>
#
upstream aiohttp_pirus
{
server 127.0.0.1:<PORT> fail_timeout=0;
}
server
{
listen 80;
listen [::]:80;
server_name <HOST>;
location / {
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_redirect off;
proxy_buffering off;
proxy_pass http://aiohttp_pirus;
}
location /static {
root <PIRUS_PATH>/pirus/templates;
#TODO : add path to run/files directories
}
}
Enable this virtual host by creating a symbolic link
sudo ln -s /etc/nginx/sites-enable/pirus /etc/nginx/sites-available/pirus
sudo /etc/init.d/nginx restart
Installing genomic databases¶
According to the config file of the Pirus application, you will install databases in the folder /var/pirus/databases by examples. You have to put in this directory all heavy databases used by pipes. The organisation shall stay simple, one folder by reference
/var/pirus/databases
/hg19
hg19.fa
1000g.vcf.gz
1000g.vcf.gz.tbi
... <- all other files that could be used by pipelines
/hg38
hg38.fa
...
Below the command to get all files for hg19 from the gatk public repository
mkdir -p /var/pirus/databases/hg19
cd /var/pirus/databases/hg19
nohup wget ftp://gsapubftp-anonymous@ftp.broadinstitute.org/bundle/hg19/ -r &
# nohup allow the long task to run without bocking your shell session
# you can follow the execution by looking the log
tail -f nohup.out # Ctrl+C to quit
# meanwhile, downloading hg19.fa ref
wget http://hgdownload.soe.ucsc.edu/goldenPath/hg19/bigZips/hg19.2bit
md5sum hg19.2bit # compare fingerprint with online md5
# TODO : choice 1 : installing bioinfo tools on the server or choice 2 : download all file from a directory ?
twoBitToFa hg19.2bit hg19.fa
samtools faidx hg19.fa
bwa index hg19.fa
# when all other downloads are completed (look into nohup.out file)
mv ftp.broadinstitute.org/bundle/hg19/* .
# If you don't trust your connection, you can check if file are not corrupted...
# unfortunately, md5 provided by the broad institute are not for the good files :P
cat *.md5 >> all.md5
sed -i 's/humgen\/gsa-scr1\/pub\/bundle\/2.8\/hg19/var\/pirus\/databases\/hg19/' all.md5
md5sum -c all.md5
# Unfortunately -again-, all gz file in the gatk ftp are not in bzip format... so, to be used
# by bioinformatic's pipelines, we need to redo compression with the good algorithm
# To get the bzip tool, you need to get and compile Htslib (https://github.com/samtools/htslib)
gzip -d *.vcf.gz
rm *.vcf.idx.gz
rm *.md5
for i in `ls -L *.vcf`; bgzip $i;
for i in `ls -L *.vcf.gz`; tabix -p vcf $i;
Run pirus¶
Your need first to run celery
cd pirus/
celery worker -A pirus_worker --loglevel=info -Q PirusQueue
So you can run pirus web api
python application.py
Check if pirus is working there : http://localhost:8080/v1/www
You can also test pirus direclty from command line by using the pirus executable file
$: pirus file list
Developer Guide¶
Solution organisation¶
- The core team of Pirus project:
- As sub project of Revogar, the core team of Pirus, is the same as for Regovar : Ikit, dridk, Oodnadatta and Arkanosis. All of them are both consultant and developer.
- Coding Rules :
- Git branching strategy :
- Dev on master,
- One branch by release; with the version number as name (by example branch “v1.0.0” for the v1.0.0)
- Discussion :
Architecture¶
See dedicated page
Model¶
Pipeline¶
Run¶
- Static property :
- public_fields <str[]> : liste des champs exportable pour le enduser (client pirus)
- Public properties :
- pipe_id <str> : (required) the id of the pipe used for this run name <str> : (required) the name set by the user for this run config <str> : the json config data (result of the config form send by the user) provided to the run as input start <str> : end = StringField() status = StringField() # WAITING, PAUSE, INITIALIZING, RUNNING, FINISHING, ERROR, DONE, CANCELED inputs = ListField(StringField()) outputs = StringField() progress = DynamicField(required=True)
- Internal properties :
- lxc_alias <str> : the alias of the lxc container used for the run
API¶
See dedicated page for the current api implemented.
- How to update current api
- Implement a new version of the api
TUS.IO protocol¶
API REST : Vue d’ensemble¶
Le serveur Regovar expose une API Rest via aioHTTP. Tout le code concernant l’API se trouve dans le répertoire /regovar/web
. L’API permet d’accéder et de gérer les resources de Regovar ainsi que de réaliser toutes les fonctionnalités proposées par le serveur via une interface web.
Pour connaître les détails concernant les resources et fonctionnalités de Regovar, lire la section concernant le core
Principaux points d’entrée¶
Les points d’entrée principaux de l’API sont les suivants :
Règles générales¶
CRUD¶
GET Read
POST Create
PUT Update
DELETE Delete
Réponses et prise en charge des erreurs¶
Les seuls codes d’erreur HTTP retournés par le server sont :
| Code | Description |
|——| ———– |
|200
| “OK”, le server fonctionne bien et vous a répondu (ce qui ne veut pas dire qu’il n’y a pas eu d’erreur)|
|404
| “request not found”, l’url saisie n’existe pas |
|403
|“authentication required”, l’utilisateur doit être identifié pour accéder au service, ou bien l’authentification a échoué (mauvais login/mot de passe saisis)|
|5XX
| “server errors”, une erreur non gérée côté server est survenue et a “cassé” le server... ça craint.|
Donc en théorie, quand tout fonctionne normalement, le server doit toujours renvoyer du JSON (utf8), avec code HTTP valant 200
.
La structure de la réponse JSON est toujours la même :
En cas de succès du traitement de la requête
HTTP code = 200
{
"success" : True, // boolean à vrai pour indiquer le traitement avec succès
// Optionnel si resultat attendu
"data" : json, // toujours formaté en JSON
// Optionnel si pagination du resultat
"range_offset" : int, // l'offset de départ des résultats
"range_limit" : int, // la limit autorisée du nombre de résultats renvoyés utilisé par la requête (1000 par défaut)
"range_total" : int, // le nombre total d'éléments en base de donnée (à e pas confondre avec le nombre d'élement retournée par la requête)
}
En cas d’erreur (gérée) lors du traitement de la requête
HTTP code = 200
{
"success" : False, // boolean à faux
"msg": string, // un message d'erreur humainement compréhensible en anglais
"error_code": string, // le code d'erreur
"error_url": string, // l'url de la doc en ligne concernant l'erreur
"error_id": string // l'identifiant unique de l'erreur qui permet de localiser facilement l'erreur dans les logs.
}
Lazy Loading¶
Par défaut une requête va retourner les ressources avec un certain nombre de champs renseignés. Pour économiser de la bande passante il est parfois nécessaire de ne récupérer que les infos dont on a besoin. Par défaut les requêtes qui renvoient des listes de résultat ne fournissent qu’un nombre limité d’information, alors que les requêtes qui retournent un seul résultat vont retourner l’ensemble des infos disponibles. Mais tout ceci est détaillé dans les pages dédiées aux points d’accès des différentes ressources.
Pour les requêtes qui supportent le lazy loading (par exemple /users
qui retourne la liste des utilisateurs), il est possible de spécifier quels champs à retourner dans la réponse.
Query Parameter : ?fields={fieldname}[,{fieldname2},...]
Exemple :
GET regovar.org/users
{
"success" : True,
"data": [{
"id" : int;
"firstname": string,
"lastname" : string,
"function" : string,
"location" : string,
"email" : string,
"roles" : json,
// ...
}]
}
GET regovar.org/users?fields=id,email
{
"success" : True,
"data": [
{"id" : 1, "email" : "user1@mail.com"},
{"id" : 2, "email" : "user2@mail.com"},
{"id" : 3, "email" : "user3@mail.com"},
...]
}
Pagination¶
Pour les requêtes qui la supportent (par exemple /users
), il est possible de spécifier la plage de résultat à retourner.
Query Parameter : ?range={first}-{end}
- Retourne la liste des résultat allant du
{first}
au{end}
inclus (à noter que le premier élément à pour index 0).
Exemple :
GET regovar.org/alphabet
{
"success" : True,
"data": ["a", "b", ... "z"] // total = 26 éléments
}
GET regovar.org/alphabet?range=2-6
{
"success" : True,
"data": ["c", "d", "e", "f"],
"range_offset" : 2,
"range_limit" : 4, // = min ({end}-{first}, Default_limite=1000)
"range_total" : 26
}
Filtrage¶
Pour les requêtes qui le supportent (par exemple /users
), il est possible de spécifier des paramètres de filtrage pour ne retourner qu’une certaine partie des résultats.
Query Parameter : ?{fieldname}={value}[,{or_value},...][&{fieldname2...}]
- On peut filtrer en précisant en paramètre un champs de la ressource et la valeur attendue. La liste des champs filtrables est fournie par la requête principale sans aucun argument (dans notre exemple la requête
/users
). Seuls les attributs directs de la ressource peuvent être filtrés.; - On peut filtrer sur plusieurs champs à la fois en les séparant avec le
&
. Dans ce cas le moteur de filtrage appliquera implicement la conditionAND
entre chaque champs filtré; - On peut filtrer sur plusieurs valeurs pour un même champs, en les séparant avec le symble
,
. Pour le moteur de filtrage il s’agira d’appliquer unOR
pour chacune de ces valeurs; - il n’est pas possible de faire du filtrage complexe via ce systeme. Ainsi pour les recherches ou filtrages nécessitant l’usage d’expression régulière, d’opérateur type
>=
, etc, si la ressource le permet, une requete dédiée sera proposée (par exemplePOST
/users/search
).
Exemple :
GET regovar.org/users?firstname=Toto
// Return list of user with firstname == "Toto"
{
"success" : True,
"data": [
{
"id" : 15,
"firstname" : "Toto",
"lastname" : "TOTO",
},
{
"id" : 16,
"firstname" : "Toto",
"lastname" : "TATA",
}]
}
GET regovar.org/users?firstname=Toto,Titi&lastname=TATA
// Return list of user with (firstname == "Toto" or "Titi") and with lastname == "TATA"
{
"success" : True,
"data": [
{
"id" : 16,
"firstname" : "Toto",
"lastname" : "TATA",
}]
}
Ordonner¶
Pour les requêtes qui le supportent (par exemple /users
), il est possible de spécifier des paramètres pour ordonner les résultats selon certains champs par ordre croissant ou décroissant.
Query Parameter : ?sort={field1}[,{field2},...][&desc={fieldX}[,{fieldY}]]
- L’attribut
sort
permet de lister les champs dans l’ordre suivant lequel les résultats vont être ordonnés (par ordre croissant pour chaque champs); - L’attribut
desc
liste les champs (parmis ceux avec l’attributs sort qui doivent suivrent l’ordre décroissant et non croissant)
Exemple :
GET regovar.org/users?sort=lastname,firstname
// Retourne la liste des utilisateur par ordre alphabétique des Nom, puis des Prénoms
GET regovar.org/users?sort=lastname,firstname&desc=lastname
// Retourne la liste des utilisateur par ordre alphabétique inversé des Nom, puis par ordre alphabétique des Prénoms
Search¶
à définir ...
Identification et authentification¶
Qui dit internet, dit authentification des utilisateurs à distance, session et mot de passe. Tout cela est géré via le point d’entrée /users
, grâce aux actions :
POST
/users/login
: qui permet l’authentification grâce aux paramètreslogin
etpassword
à fournir dans le corps de la requête. Si l’authentification échoue, une erreur 403 est retournée (Forbidden); si elle réussit,GET
/users/logout
:
API REST : Vue d’ensemble¶
Le serveur Regovar expose une API Rest via aioHTTP. Tout le code concernant l’API se trouve dans le répertoire /regovar/web
. L’API permet d’accéder et de gérer les resources de Regovar ainsi que de réaliser toutes les fonctionnalités proposées par le serveur via une interface web.
Pour connaître les détails concernant les resources et fonctionnalités de Regovar, lire la section concernant le core
Principaux points d’entrée¶
Les points d’entrée principaux de l’API sont les suivants :
Règles générales¶
CRUD¶
GET Read
POST Create
PUT Update
DELETE Delete
Réponses et prise en charge des erreurs¶
Les seuls codes d’erreur HTTP retournés par le server sont :
Code | Description
—- | ———–
200
| “OK”, le server fonctionne bien et vous a répondu (ce qui ne veut pas dire qu’il n’y a pas eu d’erreur)
404
| “request not found”, l’url saisie n’existe pas
403
|“authentication required”, l’utilisateur doit être identifié pour accéder au service, ou bien l’authentification a échoué (mauvais login/mot de passe saisis)
5XX
| “server errors”, une erreur non gérée côté server est survenue et a “cassé” le server... ça craint.
Donc en théorie, quand tout fonctionne normalement, le server doit toujours renvoyer du JSON (utf8), avec code HTTP valant 200
.
La structure de la réponse JSON est toujours la même :
En cas de succès du traitement de la requête
HTTP code = 200
{
"success" : True, // boolean à vrai pour indiquer le traitement avec succès
// Optionnel si resultat attendu
"data" : json, // toujours formaté en JSON
// Optionnel si pagination du resultat
"range_offset" : int, // l'offset de départ des résultats
"range_limit" : int, // la limit autorisée du nombre de résultats renvoyés utilisé par la requête (1000 par défaut)
"range_total" : int, // le nombre total d'éléments en base de donnée (à e pas confondre avec le nombre d'élement retournée par la requête)
}
En cas d’erreur (gérée) lors du traitement de la requête
HTTP code = 200
{
"success" : False, // boolean à faux
"msg": string, // un message d'erreur humainement compréhensible en anglais
"error_code": string, // le code d'erreur
"error_url": string, // l'url de la doc en ligne concernant l'erreur
"error_id": string // l'identifiant unique de l'erreur qui permet de localiser facilement l'erreur dans les logs.
}
Lazy Loading¶
Par défaut une requête va retourner les ressources avec un certain nombre de champs renseignés. Pour économiser de la bande passante il est parfois nécessaire de ne récupérer que les infos dont on a besoin. Par défaut les requêtes qui renvoient des listes de résultat ne fournissent qu’un nombre limité d’information, alors que les requêtes qui retournent un seul résultat vont retourner l’ensemble des infos disponibles. Mais tout ceci est détaillé dans les pages dédiées aux points d’accès des différentes ressources.
Pour les requêtes qui supportent le lazy loading (par exemple /users
qui retourne la liste des utilisateurs), il est possible de spécifier quels champs à retourner dans la réponse.
Query Parameter : ?fields={fieldname}[,{fieldname2},...]
Exemple :
GET regovar.org/users
{
"success" : True,
"data": [{
"id" : int;
"firstname": string,
"lastname" : string,
"function" : string,
"location" : string,
"email" : string,
"roles" : json,
// ...
}]
}
GET regovar.org/users?fields=id,email
{
"success" : True,
"data": [
{"id" : 1, "email" : "user1@mail.com"},
{"id" : 2, "email" : "user2@mail.com"},
{"id" : 3, "email" : "user3@mail.com"},
...]
}
Pagination¶
Pour les requêtes qui la supportent (par exemple /users
), il est possible de spécifier la plage de résultat à retourner.
Query Parameter : ?range={first}-{end}
- Retourne la liste des résultat allant du
{first}
au{end}
inclus (à noter que le premier élément à pour index 0).
Exemple :
GET regovar.org/alphabet
{
"success" : True,
"data": ["a", "b", ... "z"] // total = 26 éléments
}
GET regovar.org/alphabet?range=2-6
{
"success" : True,
"data": ["c", "d", "e", "f"],
"range_offset" : 2,
"range_limit" : 4, // = min ({end}-{first}, Default_limite=1000)
"range_total" : 26
}
Filtrage¶
Pour les requêtes qui le supportent (par exemple /users
), il est possible de spécifier des paramètres de filtrage pour ne retourner qu’une certaine partie des résultats.
Query Parameter : ?{fieldname}={value}[,{or_value},...][&{fieldname2...}]
- On peut filtrer en précisant en paramètre un champs de la ressource et la valeur attendue. La liste des champs filtrables est fournie par la requête principale sans aucun argument (dans notre exemple la requête
/users
). Seuls les attributs directs de la ressource peuvent être filtrés.; - On peut filtrer sur plusieurs champs à la fois en les séparant avec le
&
. Dans ce cas le moteur de filtrage appliquera implicement la conditionAND
entre chaque champs filtré; - On peut filtrer sur plusieurs valeurs pour un même champs, en les séparant avec le symble
,
. Pour le moteur de filtrage il s’agira d’appliquer unOR
pour chacune de ces valeurs; - il n’est pas possible de faire du filtrage complexe via ce systeme. Ainsi pour les recherches ou filtrages nécessitant l’usage d’expression régulière, d’opérateur type
>=
, etc, si la ressource le permet, une requete dédiée sera proposée (par exemplePOST
/users/search
).
Exemple :
GET regovar.org/users?firstname=Toto
// Return list of user with firstname == "Toto"
{
"success" : True,
"data": [
{
"id" : 15,
"firstname" : "Toto",
"lastname" : "TOTO",
},
{
"id" : 16,
"firstname" : "Toto",
"lastname" : "TATA",
}]
}
GET regovar.org/users?firstname=Toto,Titi&lastname=TATA
// Return list of user with (firstname == "Toto" or "Titi") and with lastname == "TATA"
{
"success" : True,
"data": [
{
"id" : 16,
"firstname" : "Toto",
"lastname" : "TATA",
}]
}
Ordonner¶
Pour les requêtes qui le supportent (par exemple /users
), il est possible de spécifier des paramètres pour ordonner les résultats selon certains champs par ordre croissant ou décroissant.
Query Parameter : ?sort={field1}[,{field2},...][&desc={fieldX}[,{fieldY}]]
- L’attribut
sort
permet de lister les champs dans l’ordre suivant lequel les résultats vont être ordonnés (par ordre croissant pour chaque champs); - L’attribut
desc
liste les champs (parmis ceux avec l’attributs sort qui doivent suivrent l’ordre décroissant et non croissant)
Exemple :
GET regovar.org/users?sort=lastname,firstname
// Retourne la liste des utilisateur par ordre alphabétique des Nom, puis des Prénoms
GET regovar.org/users?sort=lastname,firstname&desc=lastname
// Retourne la liste des utilisateur par ordre alphabétique inversé des Nom, puis par ordre alphabétique des Prénoms
Search¶
à définir ...
Identification et authentification¶
Qui dit internet, dit authentification des utilisateurs à distance, session et mot de passe. Tout cela est géré via le point d’entrée /users
, grâce aux actions :
POST
/users/login
: qui permet l’authentification grâce aux paramètreslogin
etpassword
à fournir dans le corps de la requête. Si l’authentification échoue, une erreur 403 est retournée (Forbidden); si elle réussit,GET
/users/logout
: