diff.py 4.62 KB
Newer Older
1 2 3
#!/usr/bin/env python
# -*- coding: utf-8 -*-

Mathieu Giraud's avatar
Mathieu Giraud committed
4
from __future__ import print_function
5
import fuse
6
import ansi
Mathieu Giraud's avatar
Mathieu Giraud committed
7 8
import argparse

9
parser = argparse.ArgumentParser(description = 'Show differences or similarities between clones in two .vidjil files')
10
parser.add_argument('--nb', '-n', type=int, default=5, help='number of clones to display from the first file (%(default)d), 0 for all')
Mathieu Giraud's avatar
Mathieu Giraud committed
11
parser.add_argument('--nb_others', '-o', type=int, default=3, help='number of clones to display from the other files (%(default)d)')
12
parser.add_argument('--common', '-c', action='store_true', help='display common clones instead of different clones')
Mathieu Giraud's avatar
Mathieu Giraud committed
13 14 15
parser.add_argument('--verbose', '-v', action='store_true', help='verbose output')
parser.add_argument('file', nargs=2, help='''.vidjil files to be compared''')

16

17 18 19 20 21 22 23 24 25
DIFF_COLORS = {
    '+': ansi.Fore.GREEN,
    '-': ansi.Fore.RED,
    '=': ansi.Fore.BLUE,
    '?': ansi.Fore.CYAN,
}



26 27 28 29 30 31 32 33
def format_rank(rank, colorize):
    s = ''
    if rank < 1000:
        s += '#%03d' % rank
    else:
        s += '#%02dk' % (rank / 1000)

    if rank <= 5 and colorize:
34
        s = ansi.Fore.BLUE + s + ansi.Style.RESET_ALL
35 36 37 38

    return s

def format_rank_nb_reads(rank, list_nb_reads, list_total_nb_reads):
39
    s = format_rank(rank, True) + ' '
40 41 42 43
    for (nb_reads, total_nb_reads) in zip(list_nb_reads, list_total_nb_reads):
        s += ' %6d %6.2f%%' % (nb_reads, 100*float(nb_reads)/float(total_nb_reads))
    return s

44

45 46 47 48 49
def common_two_clones(self, other, seg=None):

    if seg is None:
        seg = [1000000]
    
50 51
    if not other or not self:
        return
Mathieu Giraud's avatar
Mathieu Giraud committed
52 53 54 55
    
    print("%s\t%s%s" % (self.d['id'],
                        format_rank_nb_reads(self.d['top'], self.d['reads'], seg),
                        format_rank_nb_reads(other.d['top'], other.d['reads'], seg)))
56 57


58
def diff_two_clones(self, other):
59

60
    if not other or not self:
61
        who = "+-"[not other]
Mathieu Giraud's avatar
Mathieu Giraud committed
62 63 64
        print(DIFF_COLORS[who]+who, end=' ')
        print("!!! Clone not present:", self, "/", other, end=' ')
        print(ansi.Style.RESET_ALL)
65 66 67
        return

    if not self.d['reads'] == other.d['reads']:
68 69 70 71 72 73 74 75 76 77

        ### Computes 'who' character identification
        who_minus = False
        who_plus = False
        for reads_s, reads_o in zip(self.d['reads'], other.d['reads']):
            if reads_o > reads_s:
                who_plus = True
            if reads_o < reads_s:
                who_minus = True
        who = ["=+", "-?"][who_minus][who_plus]
Mathieu Giraud's avatar
Mathieu Giraud committed
78 79 80
        print(DIFF_COLORS[who]+who, end=' ')
        print("!!! Not the same number or reads:", self.d['id'], "-", self.d['reads'], "/", other.d['reads'], end=' ')
        print(ansi.Style.RESET_ALL)
81 82


Mathieu Giraud's avatar
Mathieu Giraud committed
83
def compare(data1, data2, args):
84 85 86 87 88 89 90

    displayed_clones = []

    def print_clone_in_self_and_others(clone):
        if clone in displayed_clones:
            return

Mathieu Giraud's avatar
Mathieu Giraud committed
91
        if args.verbose:
Mathieu Giraud's avatar
Mathieu Giraud committed
92
            print(clone, end=' ')
93 94
        other_clones = []
        for o in [data1] + [data2]:
Mathieu Giraud's avatar
Mathieu Giraud committed
95
            if args.verbose:
Mathieu Giraud's avatar
Mathieu Giraud committed
96
                print("\t", end='')
97 98 99
            try:
                w = o[clone]
                other_clones += [w]
100
            except KeyError:
101 102 103 104
                continue
            if not w:
                continue

Mathieu Giraud's avatar
Mathieu Giraud committed
105
            if args.verbose:
Mathieu Giraud's avatar
Mathieu Giraud committed
106
                print(format_rank_nb_reads(w.d['top'], w.d['reads'], o.d['reads'].d['segmented']), end=' ')
107 108

        displayed_clones.append(clone)        
Mathieu Giraud's avatar
Mathieu Giraud committed
109
        if args.verbose:
Mathieu Giraud's avatar
Mathieu Giraud committed
110
            print()
111 112 113 114 115 116 117

        if args.common:
            common_two_clones(other_clones[0], other_clones[1] if len(other_clones) > 1 else None)
        else:
            diff_two_clones(other_clones[0], other_clones[1] if len(other_clones) > 1 else None)


118 119 120 121 122 123 124

    ### 

    ids_1 = [clone.d['id'] for clone in data1]
    ids_2 = [clone.d['id'] for clone in data2]
 
    ### Display clones of this ListWindows
Mathieu Giraud's avatar
Mathieu Giraud committed
125
    if args.verbose:
Mathieu Giraud's avatar
Mathieu Giraud committed
126
        print("==== Diff from %s, %d first clones" % (data1, args.nb))
127

128 129
    ids_1_cut = ids_1[:args.nb] if args.nb else ids_1

130 131
    for cid in ids_1_cut:
        print_clone_in_self_and_others(cid)
132 133

    ### Display clones of other ListWindows not present in this ListWindows
Mathieu Giraud's avatar
Mathieu Giraud committed
134
    if args.verbose:
Mathieu Giraud's avatar
Mathieu Giraud committed
135 136
        print()
        print("==== Other clones in the top %d of other files" % args.nb_others)
137 138

    for o in [ids_2]:
139 140
        for cid in o[:args.nb_others]:
            if cid in ids_1[:args.nb]:
141
                continue
142
            print_clone_in_self_and_others(cid)
143 144 145



Mathieu Giraud's avatar
Mathieu Giraud committed
146 147 148 149 150 151 152 153 154
def main():

    args = parser.parse_args()
    datas = []

    for i in args.file:
        data = fuse.ListWindows()
        data.load(i, False, verbose = args.verbose)
        datas.append(data)
155
    
Mathieu Giraud's avatar
Mathieu Giraud committed
156 157 158 159 160
    data1 = datas[0]
    data2 = datas[1]

    compare(data1, data2, args)

161 162


Mathieu Giraud's avatar
Mathieu Giraud committed
163 164
if  __name__ =='__main__':
    main()
165 166 167 168