Commit aff60475 authored by Thonier Florian's avatar Thonier Florian

tools/distribution.py; add a script to compute distributions on vidjil files

Probably use by fuse.py
In pseudo-code, just an orientation
Link to #3902
parent fddb5aa7
Pipeline #82322 failed with stages
in 5 seconds
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
### fuse.py - Vidjil utility to parse and regroup list of clones of different timepoints or origins
# This file is part of Vidjil <http://www.vidjil.org>,
# High-throughput Analysis of V(D)J Immune Repertoire.
# Copyright (C) 2011-2017 by Bonsai bioinformatics
# at CRIStAL (UMR CNRS 9189, Université Lille) and Inria Lille
# Contributors:
# Marc Duez <marc.duez@vidjil.org>
# Mathieu Giraud <mathieu.giraud@vidjil.org>
# The Vidjil Team <contact@vidjil.org>
#
# "Vidjil" is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# "Vidjil" is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with "Vidjil". If not, see <http://www.gnu.org/licenses/>
from __future__ import print_function
import check_python_version
import sys
import json
import argparse
import os.path
import os
import datetime
import subprocess
import tempfile
from operator import itemgetter, le
from utils import *
from defs import *
from collections import defaultdict
from pipes import quote
# ==================
from fuse import *
# ==================
class Tree(defaultdict):
""" une classe qui permet de descendre sur de nombreux niveaux (defaultdict recursif)"""
def __init__(self, value=None):
super(Tree, self).__init__(Tree)
self.value = value
# On peut reprendre le Window de fuse, mais il faudra l'augmenter d'une fct get_value
# Cette fonction permettra pour un champs donne de retrouver la valeur specifique a ce clone
class Clone(Window):
# def __init__(self, data):
# """ un objet pour manipuler les champs d'un clone """
# return
def get_values(self, value):
""" une liste pour recuperer la valeur d'un champs du clone """
try:
if value == 'reagmt':
return clone. ...
if clone == "seg5":
return clone.d["seg"]["5"]["name"]
...
except:
return ""
return
def get_reads(self, t=-1):
""" une fonction direct """
if t== -1:
return self.d["reads"]
else
return self.d["reads"][t]
### Je pense que distribution devrait pouvoir être autonome, dans passer par fuse
#
class Distribution(VidjilJson):
""" on garde la fct originale """
def __init__(self, fileIn):
'''init ListWindows with the minimum data required'''
super(VidjilJson, self).__init__(VidjilJson)
self.distributions = {}
self.load(fileIn)
def cut_at_top(self, top):
if top != 0:
self.clones = self.clones[:top]
return
def load(self, file_path, verbose=True):
'''init listWindows with data file
Detects and selects the parser according to the file extension.'''
extension = file_path.split('.')[-1]
if verbose:
print("<==", file_path, "\t", end=' ')
with open(file_path, "r") as f:
self.d(json.load(f))
### On pourrait aussi imaginer prendre directement un jlist depuis fuse
return
def init_distrib(self, list_distrib):
""" on creer la liste des distributions avec des valeurs nulles pour le moment """
distributions = []
nb_sample = self.d["samples"].d["number"]...
for distrib in list_distrib:
### ICI le defaultdict devra être de la profondeur du nombre d'axes (soit la len de distrib)
distributions.append([{"axes":distrib,"values":[Tree([0, 0])] * nb_sample}])
return
def compute_distribution(self, list_distrib):
"""
list_distrib sera une listes des combinaisons d'axes a calculer
"""
# creer une liste de distribs
# ATTENTION, on peut avoir plusieurs fichier deja fuse
for filename in self.sample...:
self.distributions[filename] = self.init_distrib(list_distrib)
# passer la liste des clones en revue
for clone in self.clones:
for distrib_pos in range(self.distribs):
distrib = list_distrib[distrib_pos]
clone_values = clone.get_values( distrib.axes )
# list de valeur, pour les axes
self.add_clone_values( filename, distrib_pos, clone_values, clone["reads"])
return
def add_clone_values(self, filename, distrib_pos, values, nb_reads):
# ici on ajoute la valeur souhaité; peut-être de manière recursive au cas ou
self.distributions[filename][distrib_pos]...
i = 0
# Je ne pense pas que cette approche marche en python
obj = self.distributions[filename][distrib_pos]["values"]
while i != len(values):
obj = obj[values[i]]
i += 1
# incremente
# Pas certain que ça marche. A voir.
obj[0] += 1
obj[1] += nb_reads
return
if __name__ =='__main__':
DESCRIPTION = 'Vidjil utility to create distributions'
#### Argument parser (argparse)
parser = argparse.ArgumentParser(description= DESCRIPTION,
epilog='''Example:
python %(prog)s out/data1.vidjil out/data2.vidjil''',
formatter_class=argparse.RawTextHelpFormatter)
group_options = parser.add_argument_group() # title='Options and parameters')
group_options.add_argument('--top', '-t', type=int, default=50, help='keep only clones in the top TOP of some point (%(default)s)')
parser.add_argument('file', nargs='+', help='''input files (.vidjil/.cnltab)''')
args = parser.parse_args()
print("### fuse.py -- %s\n" % DESCRIPTION)
LISTE_D = []
## pouvoir lire un fichier de paramètres ?
#envoyer ça par cli ?
LISTE_D.append(["reagmt", "lenCDR3"])
LISTE_D.append(["reagmt", "productive"])
LISTE_D.append(["reagmt", "seg5"])
LISTE_D.append(["reagmt", "seg4"])
LISTE_D.append(["reagmt", "seg3"])
LISTE_D.append(["seg5", "seg3"])
files = args.file
jlist = Distribution()
for path_name in files:
jlist.load(path_name, args.pipeline)
jlist.cut_at_top(args.top)
jlist.get_distrib(LISTE_D)
# Perrmettre ensuite de faire un export json ?
# Un seul esport pour tous les fichiers ? Ou bien un par fichier ?
# Les deux me semble logique.
# On peux imaginer que chaque fichier .vidjil soit accompagné d'un fichier de metadata et de distributions qui lui soit propre.
#
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment