partis-bcr 1.0.3__py3-none-any.whl → 1.0.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- bin/build.sh +1 -1
- bin/partis +18 -12
- bin/partis.py +18 -12
- partis_bcr-1.0.4.data/scripts/compare-plotdirs.py +298 -0
- partis_bcr-1.0.4.data/scripts/get-naive-probabilities.py +126 -0
- {partis_bcr-1.0.3.dist-info → partis_bcr-1.0.4.dist-info}/METADATA +1 -1
- {partis_bcr-1.0.3.dist-info → partis_bcr-1.0.4.dist-info}/RECORD +19 -17
- python/main.py +3 -1
- {partis_bcr-1.0.3.data → partis_bcr-1.0.4.data}/scripts/cf-alleles.py +0 -0
- {partis_bcr-1.0.3.data → partis_bcr-1.0.4.data}/scripts/cf-germlines.py +0 -0
- {partis_bcr-1.0.3.data → partis_bcr-1.0.4.data}/scripts/extract-pairing-info.py +0 -0
- {partis_bcr-1.0.3.data → partis_bcr-1.0.4.data}/scripts/gctree-run.py +0 -0
- {partis_bcr-1.0.3.data → partis_bcr-1.0.4.data}/scripts/parse-output.py +0 -0
- {partis_bcr-1.0.3.data → partis_bcr-1.0.4.data}/scripts/split-loci.py +0 -0
- {partis_bcr-1.0.3.data → partis_bcr-1.0.4.data}/scripts/test.py +0 -0
- {partis_bcr-1.0.3.dist-info → partis_bcr-1.0.4.dist-info}/WHEEL +0 -0
- {partis_bcr-1.0.3.dist-info → partis_bcr-1.0.4.dist-info}/entry_points.txt +0 -0
- {partis_bcr-1.0.3.dist-info → partis_bcr-1.0.4.dist-info}/licenses/COPYING +0 -0
- {partis_bcr-1.0.3.dist-info → partis_bcr-1.0.4.dist-info}/top_level.txt +0 -0
bin/build.sh
CHANGED
bin/partis
CHANGED
@@ -41,6 +41,15 @@ from python.parametercounter import ParameterCounter
|
|
41
41
|
from python.corrcounter import CorrCounter
|
42
42
|
from python.waterer import Waterer
|
43
43
|
|
44
|
+
# ----------------------------------------------------------------------------------------
|
45
|
+
def find_cmd(cmd):
|
46
|
+
if shutil.which(os.path.basename(cmd)): # use version in PATH if it's there (pipx seems to leave two incompatible versions lying around)
|
47
|
+
return os.path.basename(cmd)
|
48
|
+
elif os.path.exists(cmd):
|
49
|
+
return cmd
|
50
|
+
else:
|
51
|
+
return '%s/bin/%s' % (partis_dir, os.path.basename(cmd))
|
52
|
+
|
44
53
|
# ----------------------------------------------------------------------------------------
|
45
54
|
def run_simulation(args):
|
46
55
|
# ----------------------------------------------------------------------------------------
|
@@ -88,8 +97,7 @@ def run_simulation(args):
|
|
88
97
|
for iproc in range(args.n_procs):
|
89
98
|
n_sub_events = get_sub_events(iproc)
|
90
99
|
clist = copy.deepcopy(sys.argv)
|
91
|
-
|
92
|
-
clist[0] = 'partis'
|
100
|
+
clist[0] = find_cmd(clist[0])
|
93
101
|
utils.replace_in_arglist(clist, '--n-procs', '1')
|
94
102
|
clist.append('--im-a-subproc')
|
95
103
|
utils.replace_in_arglist(clist, '--random-seed', str(args.random_seed + iproc))
|
@@ -107,7 +115,7 @@ def run_simulation(args):
|
|
107
115
|
cmdstr = ' '.join(clist)
|
108
116
|
if args.debug:
|
109
117
|
print(' %s %s' % (utils.color('red', 'run'), cmdstr))
|
110
|
-
cmdfos.append({'cmd_str' : cmdstr, 'workdir' : get_workdir(iproc), 'logdir' : args.workdir+'/log-'+str(iproc), 'outfname' : get_outfname(iproc)}) # logdirs have to be different than <workdirs> since
|
118
|
+
cmdfos.append({'cmd_str' : cmdstr, 'workdir' : get_workdir(iproc), 'logdir' : args.workdir+'/log-'+str(iproc), 'outfname' : get_outfname(iproc)}) # logdirs have to be different than <workdirs> since partis (rightfully) barfs if its workdir already exists
|
111
119
|
|
112
120
|
utils.run_cmds(cmdfos, batch_system=args.batch_system, batch_options=args.batch_options, batch_config_fname=args.batch_config_fname, debug='print')
|
113
121
|
file_list = [cmdfos[i]['outfname'] for i in range(args.n_procs)]
|
@@ -330,8 +338,7 @@ def subset_partition(args):
|
|
330
338
|
# ----------------------------------------------------------------------------------------
|
331
339
|
def get_cmd(infname, outdir, merged_odir=None):
|
332
340
|
clist = copy.deepcopy(sys.argv)
|
333
|
-
|
334
|
-
clist[0] = 'partis'
|
341
|
+
clist[0] = find_cmd(clist[0])
|
335
342
|
assert is_subset_action(clist[1]) # ugh, but utils.replace_in_arglist() only handles -- style arg strs
|
336
343
|
clist[1] = args.action.split('-')[1]
|
337
344
|
utils.remove_from_arglist(clist, '--n-subsets', has_arg=True)
|
@@ -628,13 +635,13 @@ def run_all_loci(args, ig_or_tr='ig'):
|
|
628
635
|
mfname = getofn(None, joint=True, input_meta=True)
|
629
636
|
if is_subset_action(args.action): # UGH
|
630
637
|
mfname = '%s/input/%s' % (os.path.dirname(mfname), os.path.basename(mfname))
|
631
|
-
if not args.guess_pairing_info and not args.no_pairing_info and not has_input_meta_pair_info:
|
638
|
+
if True: #not args.guess_pairing_info and not args.no_pairing_info and not has_input_meta_pair_info:
|
632
639
|
if utils.getsuffix(args.infname) == '.yaml':
|
633
640
|
new_fn = '%s/input-seqs.fa' % utils.non_none([args.paired_outdir, args.workdir])
|
634
641
|
print(' note: converting input .yaml file to .fa so we can extract pairing info + split loci (new --infname: %s)' % new_fn)
|
635
|
-
utils.simplerun('%s
|
642
|
+
utils.simplerun('%s %s %s' % (find_cmd('parse-output.py'), args.infname, new_fn), extra_str=' ')
|
636
643
|
args.infname = new_fn
|
637
|
-
cmd = '%s%s
|
644
|
+
cmd = '%s%s %s %s' % (cov_cmd()+' ' if args.prepend_coverage_command else '', find_cmd('extract-pairing-info.py'), args.infname, mfname)
|
638
645
|
if args.n_max_queries > 0:
|
639
646
|
cmd += ' --n-max-queries %d' % args.n_max_queries
|
640
647
|
if args.n_random_queries is not None:
|
@@ -651,7 +658,7 @@ def run_all_loci(args, ig_or_tr='ig'):
|
|
651
658
|
print(' note: couldn\'t extract 10x-style droplet ids from sequence ids (see above), continuing without pairing info')
|
652
659
|
if is_subset_action(args.action): # don't want loci to be split, since we pass all loci to each subset process in one file
|
653
660
|
return
|
654
|
-
cmd = '%s%s
|
661
|
+
cmd = '%s%s %s --outdir %s' % (cov_cmd()+' ' if args.prepend_coverage_command else '', find_cmd('split-loci.py'), args.infname, getodir())
|
655
662
|
if args.reverse_negative_strands:
|
656
663
|
cmd += ' --reverse-negative-strands'
|
657
664
|
if os.path.exists(mfname): # NOTE this won't show up up in dry_run since it won't exist yet
|
@@ -718,8 +725,7 @@ def run_all_loci(args, ig_or_tr='ig'):
|
|
718
725
|
# ----------------------------------------------------------------------------------------
|
719
726
|
def prep_args(ltmp):
|
720
727
|
clist = copy.deepcopy(sys.argv)
|
721
|
-
|
722
|
-
clist[0] = 'partis'
|
728
|
+
clist[0] = find_cmd(clist[0])
|
723
729
|
if any('=' in a for a in clist): # arg (have to handle --arg=val style syntax)
|
724
730
|
new_clist = []
|
725
731
|
for cstr in clist:
|
@@ -1325,7 +1331,7 @@ def run_all_loci(args, ig_or_tr='ig'):
|
|
1325
1331
|
titlestr = ltmp
|
1326
1332
|
# if ccfs is not None and ltmp in ccfs:
|
1327
1333
|
# titlestr += ':@specif.%.2f'%ccfs[ltmp][0]
|
1328
|
-
cmdstr = '%s
|
1334
|
+
cmdstr = '%s --outdir %s/%s --names single:joint --plotdirs %s/%s:%s/%s' % (find_cmd('compare-plotdirs.py'), cfpdir, ltmp, getplotdir(ltmp, single_chain=True), subd, getplotdir(ltmp), subd)
|
1329
1335
|
cmdstr += ' --make-parent-html --add-to-title %s --log xy --translegend=0.07:0.07' % titlestr
|
1330
1336
|
utils.simplerun(cmdstr, dryrun=args.dry_run)
|
1331
1337
|
|
bin/partis.py
CHANGED
@@ -41,6 +41,15 @@ from python.parametercounter import ParameterCounter
|
|
41
41
|
from python.corrcounter import CorrCounter
|
42
42
|
from python.waterer import Waterer
|
43
43
|
|
44
|
+
# ----------------------------------------------------------------------------------------
|
45
|
+
def find_cmd(cmd):
|
46
|
+
if shutil.which(os.path.basename(cmd)): # use version in PATH if it's there (pipx seems to leave two incompatible versions lying around)
|
47
|
+
return os.path.basename(cmd)
|
48
|
+
elif os.path.exists(cmd):
|
49
|
+
return cmd
|
50
|
+
else:
|
51
|
+
return '%s/bin/%s' % (partis_dir, os.path.basename(cmd))
|
52
|
+
|
44
53
|
# ----------------------------------------------------------------------------------------
|
45
54
|
def run_simulation(args):
|
46
55
|
# ----------------------------------------------------------------------------------------
|
@@ -88,8 +97,7 @@ def run_simulation(args):
|
|
88
97
|
for iproc in range(args.n_procs):
|
89
98
|
n_sub_events = get_sub_events(iproc)
|
90
99
|
clist = copy.deepcopy(sys.argv)
|
91
|
-
|
92
|
-
clist[0] = 'partis'
|
100
|
+
clist[0] = find_cmd(clist[0])
|
93
101
|
utils.replace_in_arglist(clist, '--n-procs', '1')
|
94
102
|
clist.append('--im-a-subproc')
|
95
103
|
utils.replace_in_arglist(clist, '--random-seed', str(args.random_seed + iproc))
|
@@ -107,7 +115,7 @@ def run_simulation(args):
|
|
107
115
|
cmdstr = ' '.join(clist)
|
108
116
|
if args.debug:
|
109
117
|
print(' %s %s' % (utils.color('red', 'run'), cmdstr))
|
110
|
-
cmdfos.append({'cmd_str' : cmdstr, 'workdir' : get_workdir(iproc), 'logdir' : args.workdir+'/log-'+str(iproc), 'outfname' : get_outfname(iproc)}) # logdirs have to be different than <workdirs> since
|
118
|
+
cmdfos.append({'cmd_str' : cmdstr, 'workdir' : get_workdir(iproc), 'logdir' : args.workdir+'/log-'+str(iproc), 'outfname' : get_outfname(iproc)}) # logdirs have to be different than <workdirs> since partis (rightfully) barfs if its workdir already exists
|
111
119
|
|
112
120
|
utils.run_cmds(cmdfos, batch_system=args.batch_system, batch_options=args.batch_options, batch_config_fname=args.batch_config_fname, debug='print')
|
113
121
|
file_list = [cmdfos[i]['outfname'] for i in range(args.n_procs)]
|
@@ -330,8 +338,7 @@ def subset_partition(args):
|
|
330
338
|
# ----------------------------------------------------------------------------------------
|
331
339
|
def get_cmd(infname, outdir, merged_odir=None):
|
332
340
|
clist = copy.deepcopy(sys.argv)
|
333
|
-
|
334
|
-
clist[0] = 'partis'
|
341
|
+
clist[0] = find_cmd(clist[0])
|
335
342
|
assert is_subset_action(clist[1]) # ugh, but utils.replace_in_arglist() only handles -- style arg strs
|
336
343
|
clist[1] = args.action.split('-')[1]
|
337
344
|
utils.remove_from_arglist(clist, '--n-subsets', has_arg=True)
|
@@ -628,13 +635,13 @@ def run_all_loci(args, ig_or_tr='ig'):
|
|
628
635
|
mfname = getofn(None, joint=True, input_meta=True)
|
629
636
|
if is_subset_action(args.action): # UGH
|
630
637
|
mfname = '%s/input/%s' % (os.path.dirname(mfname), os.path.basename(mfname))
|
631
|
-
if not args.guess_pairing_info and not args.no_pairing_info and not has_input_meta_pair_info:
|
638
|
+
if True: #not args.guess_pairing_info and not args.no_pairing_info and not has_input_meta_pair_info:
|
632
639
|
if utils.getsuffix(args.infname) == '.yaml':
|
633
640
|
new_fn = '%s/input-seqs.fa' % utils.non_none([args.paired_outdir, args.workdir])
|
634
641
|
print(' note: converting input .yaml file to .fa so we can extract pairing info + split loci (new --infname: %s)' % new_fn)
|
635
|
-
utils.simplerun('%s
|
642
|
+
utils.simplerun('%s %s %s' % (find_cmd('parse-output.py'), args.infname, new_fn), extra_str=' ')
|
636
643
|
args.infname = new_fn
|
637
|
-
cmd = '%s%s
|
644
|
+
cmd = '%s%s %s %s' % (cov_cmd()+' ' if args.prepend_coverage_command else '', find_cmd('extract-pairing-info.py'), args.infname, mfname)
|
638
645
|
if args.n_max_queries > 0:
|
639
646
|
cmd += ' --n-max-queries %d' % args.n_max_queries
|
640
647
|
if args.n_random_queries is not None:
|
@@ -651,7 +658,7 @@ def run_all_loci(args, ig_or_tr='ig'):
|
|
651
658
|
print(' note: couldn\'t extract 10x-style droplet ids from sequence ids (see above), continuing without pairing info')
|
652
659
|
if is_subset_action(args.action): # don't want loci to be split, since we pass all loci to each subset process in one file
|
653
660
|
return
|
654
|
-
cmd = '%s%s
|
661
|
+
cmd = '%s%s %s --outdir %s' % (cov_cmd()+' ' if args.prepend_coverage_command else '', find_cmd('split-loci.py'), args.infname, getodir())
|
655
662
|
if args.reverse_negative_strands:
|
656
663
|
cmd += ' --reverse-negative-strands'
|
657
664
|
if os.path.exists(mfname): # NOTE this won't show up up in dry_run since it won't exist yet
|
@@ -718,8 +725,7 @@ def run_all_loci(args, ig_or_tr='ig'):
|
|
718
725
|
# ----------------------------------------------------------------------------------------
|
719
726
|
def prep_args(ltmp):
|
720
727
|
clist = copy.deepcopy(sys.argv)
|
721
|
-
|
722
|
-
clist[0] = 'partis'
|
728
|
+
clist[0] = find_cmd(clist[0])
|
723
729
|
if any('=' in a for a in clist): # arg (have to handle --arg=val style syntax)
|
724
730
|
new_clist = []
|
725
731
|
for cstr in clist:
|
@@ -1325,7 +1331,7 @@ def run_all_loci(args, ig_or_tr='ig'):
|
|
1325
1331
|
titlestr = ltmp
|
1326
1332
|
# if ccfs is not None and ltmp in ccfs:
|
1327
1333
|
# titlestr += ':@specif.%.2f'%ccfs[ltmp][0]
|
1328
|
-
cmdstr = '%s
|
1334
|
+
cmdstr = '%s --outdir %s/%s --names single:joint --plotdirs %s/%s:%s/%s' % (find_cmd('compare-plotdirs.py'), cfpdir, ltmp, getplotdir(ltmp, single_chain=True), subd, getplotdir(ltmp), subd)
|
1329
1335
|
cmdstr += ' --make-parent-html --add-to-title %s --log xy --translegend=0.07:0.07' % titlestr
|
1330
1336
|
utils.simplerun(cmdstr, dryrun=args.dry_run)
|
1331
1337
|
|
@@ -0,0 +1,298 @@
|
|
1
|
+
#!python
|
2
|
+
from __future__ import absolute_import, division, unicode_literals
|
3
|
+
from __future__ import print_function
|
4
|
+
import argparse
|
5
|
+
from collections import OrderedDict
|
6
|
+
import os
|
7
|
+
import glob
|
8
|
+
import sys
|
9
|
+
import colored_traceback.always
|
10
|
+
import copy
|
11
|
+
from pathlib import Path
|
12
|
+
partis_dir = str(Path(__file__).parent.parent)
|
13
|
+
sys.path.insert(1, partis_dir) # + '/python')
|
14
|
+
|
15
|
+
import python.plotconfig as plotconfig
|
16
|
+
import python.plotting as plotting
|
17
|
+
import python.utils as utils
|
18
|
+
import python.glutils as glutils
|
19
|
+
from python.hist import Hist
|
20
|
+
import python.treeutils as treeutils
|
21
|
+
|
22
|
+
xtitledict = copy.deepcopy(plotting.legends)
|
23
|
+
xtitledict.update(plotconfig.xtitles)
|
24
|
+
xtitledict.update(treeutils.legtexts)
|
25
|
+
|
26
|
+
ptitledict = copy.deepcopy(plotting.legends)
|
27
|
+
ptitledict.update(plotconfig.plot_titles)
|
28
|
+
ptitledict.update(treeutils.legtexts)
|
29
|
+
|
30
|
+
# ----------------------------------------------------------------------------------------
|
31
|
+
def get_hists_from_dir(dirname, histname, string_to_ignore=None):
|
32
|
+
hists = {}
|
33
|
+
for fname in glob.glob('%s/%s' % (dirname, args.file_glob_str)):
|
34
|
+
varname = os.path.basename(fname)
|
35
|
+
for rstr in args.file_replace_strs:
|
36
|
+
varname = varname.replace(rstr, '')
|
37
|
+
if string_to_ignore is not None:
|
38
|
+
varname = varname.replace(string_to_ignore, '')
|
39
|
+
hists[varname] = Hist(fname=fname, title=histname)
|
40
|
+
if len(hists) == 0:
|
41
|
+
print(' no csvs found%s in %s' % ('' if args.file_glob_str is None else ' with --file-glob-str \'%s\''%args.file_glob_str, dirname))
|
42
|
+
return hists
|
43
|
+
|
44
|
+
|
45
|
+
# ----------------------------------------------------------------------------------------
|
46
|
+
def compare_directories(args, plotdirlist, outdir):
|
47
|
+
utils.prep_dir(outdir, wildlings=['*.png', '*.svg', '*.csv'])
|
48
|
+
|
49
|
+
# read hists from <plotdirlist>
|
50
|
+
allhists = OrderedDict()
|
51
|
+
allvars = set() # all variables that appeared in any dir
|
52
|
+
for idir in range(len(plotdirlist)):
|
53
|
+
dirhists = get_hists_from_dir(plotdirlist[idir], args.names[idir])
|
54
|
+
allvars |= set(dirhists.keys())
|
55
|
+
allhists[args.names[idir]] = dirhists
|
56
|
+
# then loop over all the <varname>s we found
|
57
|
+
for varname in allvars:
|
58
|
+
hlist = [allhists[dname].get(varname, Hist(1, 0, 1, title='null')) for dname in allhists]
|
59
|
+
plot_single_variable(args, varname, hlist, outdir, pathnameclues=plotdirlist[0])
|
60
|
+
|
61
|
+
plotting.make_html(outdir, n_columns=4)
|
62
|
+
|
63
|
+
# ----------------------------------------------------------------------------------------
|
64
|
+
def plot_single_variable(args, varname, hlist, outdir, pathnameclues):
|
65
|
+
if varname in plotconfig.gene_usage_columns:
|
66
|
+
hlist = plotting.add_bin_labels_not_in_all_hists(hlist)
|
67
|
+
|
68
|
+
no_labels = False
|
69
|
+
xline, bounds, figsize = None, None, None
|
70
|
+
stats = args.extra_stats
|
71
|
+
translegend = [0.0, -0.2]
|
72
|
+
xtitle, ytitle = hlist[0].xtitle, hlist[0].ytitle
|
73
|
+
bounds, xticks, xticklabels = args.xbounds, args.xticks, None
|
74
|
+
if xtitle == '': # arg, plotting.py thinks default should be None, hist.py thinks it's ''
|
75
|
+
xtitle = None
|
76
|
+
if '-mean-bins' in varname:
|
77
|
+
raise Exception('darn, I was hoping I wasn\'t making these plots any more')
|
78
|
+
plottitle = args.plottitle
|
79
|
+
if plottitle is None:
|
80
|
+
plottitle = ptitledict.get(varname, varname)
|
81
|
+
|
82
|
+
ytitle = 'fraction of total' if args.normalize else 'counts'
|
83
|
+
|
84
|
+
if 'mute-freqs/v' in pathnameclues or 'mute-freqs/d' in pathnameclues or 'mute-freqs/j' in pathnameclues:
|
85
|
+
assert not args.normalize
|
86
|
+
ytitle = 'mutation freq'
|
87
|
+
|
88
|
+
if varname in plotconfig.gene_usage_columns:
|
89
|
+
xtitle = 'allele'
|
90
|
+
if hlist[0].n_bins == 2:
|
91
|
+
stats = '0-bin' # print the fraction of entries in the zero bin into the legend (i.e. the fraction correct)
|
92
|
+
xtitle = None
|
93
|
+
# elif hlist[0].bin_labels.count('') == hlist[0].n_bins + 2:
|
94
|
+
# xtitle = '???'
|
95
|
+
|
96
|
+
line_width_override = None
|
97
|
+
if args.performance_plots:
|
98
|
+
if 'hamming_to_true_naive' in varname:
|
99
|
+
xtitle = 'hamming distance'
|
100
|
+
if '_normed' in varname:
|
101
|
+
xtitle = 'fractional ' + xtitle
|
102
|
+
elif '_vs_mute_freq' in varname:
|
103
|
+
xtitle = 'mutation freq'
|
104
|
+
ytitle = 'fraction correct'
|
105
|
+
if varname[0] == 'v' or varname[0] == 'j':
|
106
|
+
translegend = [-0.4, -0.4]
|
107
|
+
elif varname.find('_gene') == 1:
|
108
|
+
xtitle = ''
|
109
|
+
ytitle = 'fraction correct'
|
110
|
+
else:
|
111
|
+
xtitle = 'inferred - true'
|
112
|
+
bounds = plotconfig.true_vs_inferred_hard_bounds.setdefault(varname, None)
|
113
|
+
else:
|
114
|
+
if bounds is None:
|
115
|
+
bounds = plotconfig.default_hard_bounds.setdefault(varname, None)
|
116
|
+
if bounds is None and 'insertion' in varname:
|
117
|
+
bounds = plotconfig.default_hard_bounds.setdefault('all_insertions', None)
|
118
|
+
if varname in plotconfig.gene_usage_columns:
|
119
|
+
# no_labels = True # not sure why i wanted these labels turned off?
|
120
|
+
if 'j_' not in varname:
|
121
|
+
figsize = (10, 5)
|
122
|
+
line_width_override = 1
|
123
|
+
elif 'per-gene-per-position/v' in pathnameclues:
|
124
|
+
figsize = (20, 5)
|
125
|
+
if bounds is None:
|
126
|
+
bounds = plotconfig.default_hard_bounds.setdefault(utils.unsanitize_name(varname), None)
|
127
|
+
|
128
|
+
if 'IG' in varname or 'TR' in varname:
|
129
|
+
if 'mute-freqs' in pathnameclues:
|
130
|
+
gene = utils.unsanitize_name(varname)
|
131
|
+
plottitle = gene # + ' -- mutation frequency'
|
132
|
+
xtitle = 'position'
|
133
|
+
if utils.get_region(gene) == 'j':
|
134
|
+
translegend = [0.1, 0.] #(-0.35, -0.02)
|
135
|
+
else:
|
136
|
+
translegend = [0.15, -0.02]
|
137
|
+
xline = None
|
138
|
+
if args.glfo is not None:
|
139
|
+
if utils.get_region(gene) in utils.conserved_codons[args.locus]:
|
140
|
+
xline = args.glfo[utils.conserved_codons[args.locus][utils.get_region(gene)] + '-positions'][gene]
|
141
|
+
else:
|
142
|
+
ilastdash = varname.rfind('-')
|
143
|
+
gene = utils.unsanitize_name(varname[:ilastdash])
|
144
|
+
base_varname = varname[ilastdash + 1 :]
|
145
|
+
base_plottitle = plotconfig.plot_titles[base_varname] if base_varname in plotconfig.plot_titles else ''
|
146
|
+
plottitle = gene + ' -- ' + base_plottitle
|
147
|
+
|
148
|
+
if varname == 'cluster-sizes':
|
149
|
+
xtitle = 'cluster size'
|
150
|
+
ytitle = 'fraction of clusters' if args.normalize else 'N clusters'
|
151
|
+
plottitle = ''
|
152
|
+
xticks, xticklabels = plotting.get_cluster_size_xticks(hlist=hlist) # it would be better to use all the hists, but i think it'll just screw up the ticks
|
153
|
+
import matplotlib.pyplot as plt
|
154
|
+
if varname in ['func-per-drop', 'nonfunc-per-drop']:
|
155
|
+
bounds = (-0.5, 15.5)
|
156
|
+
if 'subtree-purity' in varname:
|
157
|
+
if 'size' in varname:
|
158
|
+
if args.log == '':
|
159
|
+
args.log = 'xy'
|
160
|
+
xticks = [1, 2, 3, 5, 10, 15, 20]
|
161
|
+
xticklabels = ['1', '2', '3', '5', '10', '15', '20']
|
162
|
+
|
163
|
+
if xtitle is None:
|
164
|
+
xtitle = xtitledict.get(varname)
|
165
|
+
|
166
|
+
if args.add_to_title is not None:
|
167
|
+
plottitle += args.add_to_title
|
168
|
+
|
169
|
+
if len(hlist) > 9: # skootch it down so they (maybe) all fit
|
170
|
+
translegend[1] -= 0.5
|
171
|
+
if args.translegend is not None: # override with the command line
|
172
|
+
translegend = args.translegend
|
173
|
+
if varname == 'paired-uids-per-uid':
|
174
|
+
translegend = [translegend[0] + 0.15, translegend[1] - 0.3]
|
175
|
+
if args.extra_stats == 'auto': # kind of hackey
|
176
|
+
if xtitle == 'inferred - true':
|
177
|
+
stats = 'absmean'
|
178
|
+
else:
|
179
|
+
stats = 'mean'
|
180
|
+
# draw that little #$*(!
|
181
|
+
linewidths = [line_width_override, ] if line_width_override is not None else args.linewidths
|
182
|
+
if args.alphas is None or len(args.alphas) != len(hlist):
|
183
|
+
if args.alphas is not None and len(args.alphas) != len(hlist):
|
184
|
+
print(' %s --alphas wrong length, using first entry for all' % utils.wrnstr())
|
185
|
+
args.alphas = [0.6 if args.alphas is None else args.alphas[0] for _ in range(len(hlist))]
|
186
|
+
shift_overflows = os.path.basename(outdir) != 'gene-call' and 'func-per-drop' not in varname
|
187
|
+
plotting.draw_no_root(hlist[0], plotname=varname, plotdir=outdir, more_hists=hlist[1:], write_csv=False, stats=stats, bounds=bounds, ybounds=args.ybounds,
|
188
|
+
shift_overflows=shift_overflows, plottitle=plottitle, colors=args.colors,
|
189
|
+
xtitle=xtitle if args.xtitle is None else args.xtitle, ytitle=ytitle if args.ytitle is None else args.ytitle, xline=xline, normalize=(args.normalize and '_vs_mute_freq' not in varname),
|
190
|
+
linewidths=linewidths, markersizes=args.markersizes, alphas=args.alphas, errors=not args.no_errors, remove_empty_bins=True, #='y' in args.log,
|
191
|
+
figsize=figsize, no_labels=no_labels, log=args.log, translegend=translegend, xticks=xticks, xticklabels=xticklabels, square_bins=args.square_bins)
|
192
|
+
|
193
|
+
if args.swarm_meta_key is not None:
|
194
|
+
plotvals = {h.title : [h.get_bin_centers()[i] for i in h.ibiniter(True) for _ in range(int(h.bin_contents[i]))] for h in hlist}
|
195
|
+
plotting.stack_meta_hists(varname, outdir, args.swarm_meta_key, plotvals, colors={h.title : c for h, c in zip(hlist, args.colors)}, xtitle=xtitle, swarm_plots=True, no_hist=True, xticks=xticks)
|
196
|
+
|
197
|
+
# ----------------------------------------------------------------------------------------
|
198
|
+
helpstr = """
|
199
|
+
Compare csv histogram plot files across multiple directories
|
200
|
+
./bin/compare-plotdirs.py --outdir _output/tmp-plots --plotdirs docs/example-plots/sw/mute-freqs/overall:docs/example-plots/hmm/mute-freqs/overall:docs/example-plots/multi-hmm/mute-freqs/overall --names sw:hmm:multi-hmm --normalize
|
201
|
+
"""
|
202
|
+
class MultiplyInheritedFormatter(argparse.RawTextHelpFormatter, argparse.ArgumentDefaultsHelpFormatter):
|
203
|
+
pass
|
204
|
+
formatter_class = MultiplyInheritedFormatter
|
205
|
+
parser = argparse.ArgumentParser(formatter_class=MultiplyInheritedFormatter, description=helpstr)
|
206
|
+
parser.add_argument('--outdir', required=True, help='Output directory to which to write the resulting comparison plots. A summary .html file is also written to <outdir>.html')
|
207
|
+
parser.add_argument('--plotdirs', required=True, help='Colon-separated list of input plot directories, each of which must have identical structure. Looks for svgs first in each dir, but then also in the subdirs of each dir (so e.g. if each of them have a/, b/, and c/ subdirs, this script will make a separate comparison of a/, b/, and c/)')
|
208
|
+
parser.add_argument('--names', required=True, help='colon-separated list of names/labels corresponding to --plotdirs (use @ as space)')
|
209
|
+
parser.add_argument('--performance-plots', action='store_true', help='set to true if these are annotation performance plots, i.e. made with --plot-annotation-performance (this makes the axis labels more sensible)')
|
210
|
+
parser.add_argument('--colors', default=':'.join(plotting.default_colors), help='color-separated list of colors to cycle through for the plotdirs')
|
211
|
+
parser.add_argument('--alphas')
|
212
|
+
parser.add_argument('--linewidths', default=':'.join(plotting.default_linewidths), help='colon-separated list of linewidths to cycle through')
|
213
|
+
parser.add_argument('--markersizes', default=':'.join(plotting.default_markersizes), help='colon-separated list of linewidths to cycle through')
|
214
|
+
parser.add_argument('--gldirs', help='On plots showing mutation vs individual gene positions, if you\'d like a dashed veritcal line showing conserved codon positions, set this as a colon-separated list of germline info dirs corresponding to each plotdir') #, default=['data/germlines/human'])
|
215
|
+
parser.add_argument('--locus', default='igh')
|
216
|
+
parser.add_argument('--normalize', action='store_true', help='If set, the histograms from each plotdir are normalized (each bin contents divided by the integral) before making the comparison (e.g. for comparing different size samples).')
|
217
|
+
parser.add_argument('--extra-stats', help='if set, adds extra stat to legend, e.g. \'mean\', \'absmean\', \'auto\'')
|
218
|
+
parser.add_argument('--translegend', help='colon-separated list of x, y values with which to translate all the legends')
|
219
|
+
parser.add_argument('--log', default='', help='Display these axes on a log scale, set to either \'x\', \'y\', or \'xy\'')
|
220
|
+
parser.add_argument('--make-parent-html', action='store_true', help='after doing everything within subdirs, make a single html in the main/parent dir with all plots from subdirs')
|
221
|
+
parser.add_argument('--add-to-title', help='string to append to existing title (use @ as space)')
|
222
|
+
parser.add_argument('--file-glob-str', default='*.csv', help='shell glob style regex for matching plot files')
|
223
|
+
parser.add_argument('--file-replace-strs', default='.csv', help='colon-separated list of strings to remove frome file base name to get variable name')
|
224
|
+
parser.add_argument('--xbounds')
|
225
|
+
parser.add_argument('--ybounds')
|
226
|
+
parser.add_argument('--xticks')
|
227
|
+
parser.add_argument('--plottitle')
|
228
|
+
parser.add_argument('--xtitle')
|
229
|
+
parser.add_argument('--ytitle')
|
230
|
+
parser.add_argument('--no-errors', action='store_true')
|
231
|
+
parser.add_argument('--single-plotdir', action='store_true')
|
232
|
+
parser.add_argument('--square-bins', action='store_true')
|
233
|
+
parser.add_argument('--swarm-meta-key', help='if set, also make swarm plots, pretending that each hist\'s title is the value for this "fake" meta info key, and treat each bin\'s entries as observations at the bin center\'s value')
|
234
|
+
|
235
|
+
args = parser.parse_args()
|
236
|
+
args.plotdirs = utils.get_arg_list(args.plotdirs)
|
237
|
+
args.names = utils.get_arg_list(args.names)
|
238
|
+
args.alphas = utils.get_arg_list(args.alphas, floatify=True)
|
239
|
+
args.colors = utils.get_arg_list(args.colors)
|
240
|
+
args.linewidths = utils.get_arg_list(args.linewidths, intify=True)
|
241
|
+
args.markersizes = utils.get_arg_list(args.markersizes, intify=True)
|
242
|
+
args.gldirs = utils.get_arg_list(args.gldirs)
|
243
|
+
args.translegend = utils.get_arg_list(args.translegend, floatify=True)
|
244
|
+
args.xbounds = utils.get_arg_list(args.xbounds, floatify=True)
|
245
|
+
args.ybounds = utils.get_arg_list(args.ybounds, floatify=True)
|
246
|
+
args.xticks = utils.get_arg_list(args.xticks, floatify=True)
|
247
|
+
args.file_replace_strs = utils.get_arg_list(args.file_replace_strs)
|
248
|
+
for iname in range(len(args.names)):
|
249
|
+
args.names[iname] = args.names[iname].replace('@', ' ')
|
250
|
+
if args.add_to_title is not None:
|
251
|
+
args.add_to_title = args.add_to_title.replace('@', ' ')
|
252
|
+
|
253
|
+
if len(args.plotdirs) == 1 and not args.single_plotdir:
|
254
|
+
print(' --plotdirs is length 1 (and --single-plotdir wasn\'t set), so assuming --names has the desired subdirs')
|
255
|
+
parentdir = args.plotdirs[0]
|
256
|
+
args.plotdirs = [parentdir + '/' + n for n in args.names]
|
257
|
+
|
258
|
+
if len(args.plotdirs) != len(args.names):
|
259
|
+
raise Exception('poorly formatted args:\n %s\n %s' % (' '.join(args.plotdirs), ' '.join(args.names)))
|
260
|
+
|
261
|
+
# make a merged glfo from all the gldirs
|
262
|
+
args.glfo = None
|
263
|
+
if args.gldirs is not None:
|
264
|
+
for gldir in [gd for gd in args.gldirs if os.path.exists(gd)]:
|
265
|
+
tmpglfo = glutils.read_glfo(gldir, args.locus)
|
266
|
+
if args.glfo is None:
|
267
|
+
args.glfo = tmpglfo
|
268
|
+
else:
|
269
|
+
args.glfo = glutils.get_merged_glfo(args.glfo, tmpglfo)
|
270
|
+
|
271
|
+
if any(not os.path.isdir(d) for d in args.plotdirs):
|
272
|
+
print(' at least one of --plotdirs doesn\'t exist: %s' % ' '.join(d for d in args.plotdirs if not os.path.isdir(d)))
|
273
|
+
sys.exit(0)
|
274
|
+
|
275
|
+
listof_plotdirlists, listof_outdirs = [], []
|
276
|
+
# first add the main/parent dir, if it has csvs
|
277
|
+
firstdir = args.plotdirs[0]
|
278
|
+
if len(glob.glob(firstdir + '/*.csv')) > 0:
|
279
|
+
listof_plotdirlists.append(args.plotdirs)
|
280
|
+
listof_outdirs.append(args.outdir)
|
281
|
+
else:
|
282
|
+
print(' no csvs in main/parent dir %s' % firstdir)
|
283
|
+
# then figure out if there's subdirs we need to deal with
|
284
|
+
added_subds = []
|
285
|
+
|
286
|
+
for subdir in [d for d in os.listdir(firstdir) if os.path.isdir(firstdir + '/' + d)]:
|
287
|
+
listof_plotdirlists.append([d + '/' + subdir for d in args.plotdirs])
|
288
|
+
listof_outdirs.append(args.outdir + '/' + subdir)
|
289
|
+
added_subds.append(subdir)
|
290
|
+
if len(added_subds) > 0:
|
291
|
+
print(' added %d subdirs: %s' % (len(added_subds), ' '.join(added_subds)))
|
292
|
+
|
293
|
+
for dlist, outdir in zip(listof_plotdirlists, listof_outdirs):
|
294
|
+
compare_directories(args, dlist, outdir)
|
295
|
+
|
296
|
+
if args.make_parent_html: # didn't really test this very well
|
297
|
+
fnoutstr, _ = utils.simplerun('find %s -type f -name *.svg' % args.outdir, return_out_err=True)
|
298
|
+
plotting.make_html(args.outdir, fnames=[fnoutstr.strip().split('\n')])
|
@@ -0,0 +1,126 @@
|
|
1
|
+
#!python
|
2
|
+
from __future__ import absolute_import, division, unicode_literals
|
3
|
+
from __future__ import print_function
|
4
|
+
import os
|
5
|
+
import sys
|
6
|
+
import csv
|
7
|
+
import argparse
|
8
|
+
import operator
|
9
|
+
import argparse
|
10
|
+
import yaml
|
11
|
+
import colored_traceback.always
|
12
|
+
from io import open
|
13
|
+
|
14
|
+
# if you move this script, you'll need to change this method of getting the imports
|
15
|
+
from pathlib import Path
|
16
|
+
partis_dir = str(Path(__file__).parent.parent)
|
17
|
+
sys.path.insert(1, partis_dir) # + '/python')
|
18
|
+
|
19
|
+
import python.utils as utils
|
20
|
+
|
21
|
+
# ----------------------------------------------------------------------------------------
|
22
|
+
def is_acceptable(scol, acceptable_values, lval):
|
23
|
+
if lval in acceptable_values:
|
24
|
+
return True
|
25
|
+
if args.any_allele and '_gene' in scol and any(utils.are_alleles(g, lval) for g in acceptable_values):
|
26
|
+
return True
|
27
|
+
return False
|
28
|
+
|
29
|
+
class MultiplyInheritedFormatter(argparse.RawTextHelpFormatter, argparse.ArgumentDefaultsHelpFormatter):
|
30
|
+
pass
|
31
|
+
formatter_class = MultiplyInheritedFormatter
|
32
|
+
parser = argparse.ArgumentParser(formatter_class=MultiplyInheritedFormatter)
|
33
|
+
parser.add_argument('--infname', default='test/ref-results/test/parameters/data/hmm/all-probs.csv', help='input all-probs.csv file from a previously-inferred partis parameter directory, for instance: test/reference-results/test/parameters/data/hmm/all-probs.csv')
|
34
|
+
parser.add_argument('--config-fname', help='yaml file with info on columns for which we want to specify particular values (and skip others). See default/example set below. To create a yaml config file to start from, uncomment the yaml.dump() line below and rerun with no arguments.')
|
35
|
+
parser.add_argument('--outfname')
|
36
|
+
parser.add_argument('--any-allele', action='store_true', help='if set, also include any other alleles of any of the genes specified in \'skip_column_vals\' (note: can also set it in the cfg file).')
|
37
|
+
parser.add_argument('--debug', action='store_true', default=True) # it's kind of confusing without the debug printout
|
38
|
+
args = parser.parse_args()
|
39
|
+
|
40
|
+
non_summed_column = None
|
41
|
+
if args.config_fname is None:
|
42
|
+
non_summed_column = 'v_gene'
|
43
|
+
skip_column_vals = { # to input your own dict on the command line, just convert with str() and quote it
|
44
|
+
# 'cdr3_length' : ['33', '36', '39', '42', '45', '48'], # <value> is list of acceptable values NOTE need to all be strings, otherwise you have to worry about converting the values in the csv file
|
45
|
+
'v_gene' : ['IGHV1-2*02+G35A', 'IGHV1-2*02+T147C', 'IGHV1-2*02'],
|
46
|
+
# 'd_gene' : ['IGHD3-22*01'],
|
47
|
+
'j_gene' : ['IGHJ4*02'],
|
48
|
+
'cdr3_length' : ['66',],
|
49
|
+
}
|
50
|
+
print('%s using default skip column/non-summed column values (which probably don\'t correspond to what you\'re actually interested in)' % utils.color('red', 'note'))
|
51
|
+
# # uncomment to create a yaml file to start from:
|
52
|
+
# with open('tmp.yaml', 'w') as tfile:
|
53
|
+
# yaml.dump({'non_summed_column' : non_summed_column, 'skip_column_vals' : skip_column_vals}, tfile)
|
54
|
+
else:
|
55
|
+
with open(args.config_fname) as yamlfile:
|
56
|
+
yamlfo = yaml.load(yamlfile, Loader=yaml.Loader)
|
57
|
+
if 'non_summed_column' in yamlfo:
|
58
|
+
non_summed_column = yamlfo['non_summed_column']
|
59
|
+
skip_column_vals = yamlfo['skip_column_vals']
|
60
|
+
for scol in skip_column_vals:
|
61
|
+
skip_column_vals[scol] = [str(v) for v in skip_column_vals[scol]] # yaml.load() converts to integers, which is usually nice, but here we don't want it to since we're not converting when reading all-probs.csv (I think there's options to yaml.load to change this, I just don't want to figure it out now)
|
62
|
+
if 'any_allele' in yamlfo:
|
63
|
+
if args.any_allele and not yamlfo['any_allele']: # if it's set to true on the command line, but false in the file
|
64
|
+
print(' %s overwriting --any-allele with value from cfg file %s' % (utils.color('red', 'warning'), args.config_fname))
|
65
|
+
args.any_allele = yamlfo['any_allele']
|
66
|
+
|
67
|
+
info = {}
|
68
|
+
lines_skipped, lines_used = 0, 0
|
69
|
+
counts_skipped, counts_used = 0, 0
|
70
|
+
print(' reading probs from %s' % args.infname)
|
71
|
+
with open(args.infname) as csvfile:
|
72
|
+
reader = csv.DictReader(csvfile)
|
73
|
+
# if args.debug:
|
74
|
+
# print ' all columns in file: %s' % ' '.join(reader.fieldnames)
|
75
|
+
if len(set(skip_column_vals) - set(reader.fieldnames)) > 0:
|
76
|
+
raise Exception('keys in --skip-column-fname not in file: %s' % ' '.join(set(skip_column_vals) - set(reader.fieldnames)))
|
77
|
+
for line in reader:
|
78
|
+
skip_this_line = False
|
79
|
+
for scol, acceptable_values in skip_column_vals.items():
|
80
|
+
if not is_acceptable(scol, acceptable_values, line[scol]):
|
81
|
+
skip_this_line = True
|
82
|
+
lines_skipped += 1
|
83
|
+
counts_skipped += int(line['count'])
|
84
|
+
break
|
85
|
+
if skip_this_line:
|
86
|
+
continue
|
87
|
+
|
88
|
+
if non_summed_column is not None:
|
89
|
+
if line[non_summed_column] not in info:
|
90
|
+
info[line[non_summed_column]] = 0
|
91
|
+
info[line[non_summed_column]] += int(line['count'])
|
92
|
+
|
93
|
+
lines_used += 1
|
94
|
+
counts_used += int(line['count'])
|
95
|
+
|
96
|
+
# ----------------------------------------------------------------------------------------
|
97
|
+
import python.fraction_uncertainty as fraction_uncertainty
|
98
|
+
def frac_err(obs, total):
|
99
|
+
lo, hi = fraction_uncertainty.err(obs, total)
|
100
|
+
return 0.5 * (hi - lo)
|
101
|
+
count_fraction = counts_used / float(counts_used + counts_skipped)
|
102
|
+
|
103
|
+
if args.debug:
|
104
|
+
print(' applied restrictions:%s' % (' (including all alleles of these genes)' if args.any_allele else ''))
|
105
|
+
for scol, acceptable_values in skip_column_vals.items():
|
106
|
+
print(' %15s in %s' % (scol, acceptable_values))
|
107
|
+
print(' used:')
|
108
|
+
print(' %6d / %-6d = %.3f lines' % (lines_used, lines_used + lines_skipped, lines_used / float(lines_used + lines_skipped)))
|
109
|
+
print(' %6d / %-6d = %.3f +/- %.3f counts' % (counts_used, counts_used + counts_skipped, count_fraction, frac_err(counts_used, counts_used + counts_skipped)))
|
110
|
+
|
111
|
+
if non_summed_column is not None:
|
112
|
+
print(' %18s count / %d = fraction' % (non_summed_column, counts_used))
|
113
|
+
for val, count in sorted(list(info.items()), key=operator.itemgetter(1), reverse=True): # sort by counts
|
114
|
+
# for val, count in sorted(info.items()): # sort by column value (e.g. cdr3 length)
|
115
|
+
print(' %18s %6d %.3f +/- %.3f' % (val, count, count / float(counts_used), frac_err(count, counts_used)))
|
116
|
+
|
117
|
+
if args.outfname is not None:
|
118
|
+
if args.debug:
|
119
|
+
print(' writing total counts (plus %d info entries) to %s' % (len(info), args.outfname))
|
120
|
+
with open(args.outfname, 'w') as outfile:
|
121
|
+
yamlfo = {'counts' : counts_used,
|
122
|
+
'total' : counts_used + counts_skipped,
|
123
|
+
'fraction' : count_fraction,
|
124
|
+
'frac_err' : frac_err(counts_used, counts_used + counts_skipped),
|
125
|
+
'info' : info}
|
126
|
+
yaml.dump(yamlfo, outfile, width=150)
|
@@ -2,7 +2,7 @@ bin/FastTree,sha256=ztIqHXzUJRUFLo-BEcE97UyityueIJmFPWXFOoJ0l4k,368264
|
|
2
2
|
bin/add-chimeras.py,sha256=7Zug9D7qtVa2k81kcIGtMKH0BjCmeiq2_rRDjPoiZug,2351
|
3
3
|
bin/add-seqs-to-outputs.py,sha256=O7Mkz7GbkJPNtJ4v1fI1d3XfuYLOxG0ZofG37U_Rjsg,5156
|
4
4
|
bin/bcr-phylo-run.py,sha256=rzafOBrnLlOQWp3XnBHwYqnsVQVThrVLab1K_zgNi-k,54060
|
5
|
-
bin/build.sh,sha256=
|
5
|
+
bin/build.sh,sha256=W2U4VNyf3lHTSiwb4K8lI8kFRmiXiTn0EfKpB520_DY,691
|
6
6
|
bin/cf-alleles.py,sha256=HEQzDvXGSIFoWysUQTF5MZwDWIYwfAeXTepOZj8UN6A,4737
|
7
7
|
bin/cf-germlines.py,sha256=AA82Hvy53Qh9czl3gQK6IzZAb8BnqcoUWFbIFuBGyQw,3149
|
8
8
|
bin/cf-linearham.py,sha256=mUp7aEUGLCifUv-jk3GL5IbeUiktJ9f8tFi5h7CRkYc,11603
|
@@ -21,9 +21,9 @@ bin/lonr.r,sha256=YzAsjyQ-NZ2shOPhzkFFppsgXJEhMTztFA-C6NVyEJ4,44212
|
|
21
21
|
bin/makeHtml,sha256=SMMulEmYoU4ve4jlCRNaDuw9f4FS4t8g_FGE7z5Ndb4,1190
|
22
22
|
bin/mds-run.py,sha256=rShy5b3oqvFZqhNdVxrtyZ4nw7whK-SKPAYl2thXooU,2003
|
23
23
|
bin/parse-output.py,sha256=_vlx4ptHEoKiztm2RrCMqQZYlFriFmv4Sv17E6M6J9o,19533
|
24
|
-
bin/partis,sha256=
|
24
|
+
bin/partis,sha256=sz5w4-MTttkbaerC8FYA7YMiJu_8VBcnXhVsNXitLJE,225069
|
25
25
|
bin/partis-pip,sha256=STJkb_lm94kKxthpmIsMgFIhBWsoOJAtRJZbiFewaAU,5562
|
26
|
-
bin/partis.py,sha256=
|
26
|
+
bin/partis.py,sha256=sz5w4-MTttkbaerC8FYA7YMiJu_8VBcnXhVsNXitLJE,225069
|
27
27
|
bin/plot-gl-set-trees.py,sha256=bgWPBmzzlD_YgWl9nQetGdzmgosXDKyVyfvaHs0VvVc,25695
|
28
28
|
bin/plot-hmms.py,sha256=rKhPyWxexMKBt8kmwuM5ebFfFONtREoDlRqs4J52rT8,6560
|
29
29
|
bin/plot-lb-tree.py,sha256=EKvA2DhRL8oAJoUy5FYdQaLyZYL4Ez6_4OpwD3kVbVM,23674
|
@@ -298,14 +298,16 @@ data/substitution-profiles/GSSPs_for_VL_genes_with_at_least_300_lineages.txt,sha
|
|
298
298
|
data/substitution-profiles/notes.txt,sha256=-DK9E31YovqOWaXR1Q-LL5KFhjVJcSLwXbriajUq1TA,389
|
299
299
|
packages/ham/bcrham,sha256=4NstZkQgqdF1l_tNemIwuzVyN2zOFsw248qPoPldYWg,1194368
|
300
300
|
packages/ig-sw/src/ig_align/ig-sw,sha256=SNFYfMlvX9s9T64t9fYIB5ugD6cZ016SZVbRhrz5Pro,293464
|
301
|
-
partis_bcr-1.0.
|
302
|
-
partis_bcr-1.0.
|
303
|
-
partis_bcr-1.0.
|
304
|
-
partis_bcr-1.0.
|
305
|
-
partis_bcr-1.0.
|
306
|
-
partis_bcr-1.0.
|
307
|
-
partis_bcr-1.0.
|
308
|
-
partis_bcr-1.0.
|
301
|
+
partis_bcr-1.0.4.data/scripts/cf-alleles.py,sha256=AgFLoRfcwuX1InVpE3zG6-unqoCBGOeCTpEl_RZftvU,4723
|
302
|
+
partis_bcr-1.0.4.data/scripts/cf-germlines.py,sha256=8_bq0ue3ALFQ-a7-ntnhkbCaBdQ5mlWtQgNeQP_TvcQ,3135
|
303
|
+
partis_bcr-1.0.4.data/scripts/compare-plotdirs.py,sha256=AABVGUOwlLCijjo-wwDLfLHiq80TrFVm8mE-4Zqn5Sg,16370
|
304
|
+
partis_bcr-1.0.4.data/scripts/extract-pairing-info.py,sha256=IGPd4jYpsW3IPgsrxTJrk9jAwUKlb45eX3lOpb8Maos,2941
|
305
|
+
partis_bcr-1.0.4.data/scripts/gctree-run.py,sha256=BfSZCFgqdhUEqVsv2h20o6OkS6KbQgx5tfvBhySRx2U,13950
|
306
|
+
partis_bcr-1.0.4.data/scripts/get-naive-probabilities.py,sha256=WfuglaedP3PF0wpksGiUSvfAg4wJoNlucTPa1Wl9MDo,6916
|
307
|
+
partis_bcr-1.0.4.data/scripts/parse-output.py,sha256=8nrg0ip3XDhme02NCiI45BrSqCNvbRIbKYErD8STk8U,19519
|
308
|
+
partis_bcr-1.0.4.data/scripts/split-loci.py,sha256=K0WXQYtloL5rs46mwvEXUecqT3iG8bbqwNOTNwfpvzY,20704
|
309
|
+
partis_bcr-1.0.4.data/scripts/test.py,sha256=aI-2mLH5WXYVWoS4zateeSgDynDUC_DK9QF-UAEpWms,63609
|
310
|
+
partis_bcr-1.0.4.dist-info/licenses/COPYING,sha256=jOtLnuWt7d5Hsx6XXB2QxzrSe2sWWh3NgMfFRetluQM,35147
|
309
311
|
python/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
310
312
|
python/alleleclusterer.py,sha256=x50E_lJMlKPc-CPkdkM1qe4AvVi-mkDJ1cBDxs5L-ms,30551
|
311
313
|
python/allelefinder.py,sha256=SgJjopk5ivLOcmTumsWq5PZ05aPZ6zQyjTd1fxeRjaM,80402
|
@@ -326,7 +328,7 @@ python/hmmwriter.py,sha256=lWC4oW7dvAFj0mmCYCmzV67kuM-zZPSzPXqu0d6o_Ro,55480
|
|
326
328
|
python/hutils.py,sha256=o3z4LbFbemxiQdBoTJv8YPbnwul0SkdfBl9UXJXOHIE,15684
|
327
329
|
python/indelutils.py,sha256=SlPFQnzPN27VHxvcUXHIgHZtBm6MGfookz6jHDavtm4,45001
|
328
330
|
python/lbplotting.py,sha256=AKQsFJKi_gw7us7ARNwUhVNfHvWbxp1oo4JbJtWORaQ,126486
|
329
|
-
python/main.py,sha256=
|
331
|
+
python/main.py,sha256=f_xBE3yxVo7k7CMWkYRD6kHyAeGt4QV75bD_rO-wOyc,994
|
330
332
|
python/mds.py,sha256=58JdN3X11t8yMLeuhpYEqpC6doZQc9m4yLFj4Bm1hHc,15859
|
331
333
|
python/mutefreqer.py,sha256=1xkbi0rnkKbPN-09VB0OXC4MLAMAzwVYsOlQ77NVB9Q,14097
|
332
334
|
python/paircluster.py,sha256=jnIXPtGe2-Z_PP-bYztMh0BuKnoh7P55ixsEkls0xUg,154337
|
@@ -350,8 +352,8 @@ python/vrc01.py,sha256=f3PpRV9ZOU9kxJCKdoJlP9wvKB7FEgMM8WoNpevsEOE,10813
|
|
350
352
|
python/waterer.py,sha256=sPBsJchmK2EO3M5UCwZq_S5mRV3eYFuIZoite4Js62g,109955
|
351
353
|
python/cache/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
352
354
|
python/cache/cached_uncertainties.py,sha256=GNs18AG8ROdDg0OOrcArsU73Ev1U8k5Gsnf79WndHG8,4257821
|
353
|
-
partis_bcr-1.0.
|
354
|
-
partis_bcr-1.0.
|
355
|
-
partis_bcr-1.0.
|
356
|
-
partis_bcr-1.0.
|
357
|
-
partis_bcr-1.0.
|
355
|
+
partis_bcr-1.0.4.dist-info/METADATA,sha256=NdUeCqs9F-GpKyvHaA2DCYr3IAKyQ01GI1qdmjGzqOk,4976
|
356
|
+
partis_bcr-1.0.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
357
|
+
partis_bcr-1.0.4.dist-info/entry_points.txt,sha256=Q-AkAQ91YwiKNHruS32ACdY4_IQdpZhpij2EuVDmdnM,44
|
358
|
+
partis_bcr-1.0.4.dist-info/top_level.txt,sha256=J-z0poNcsv31IHB413--iOY8LoHBKiTHeybHX3abokI,7
|
359
|
+
partis_bcr-1.0.4.dist-info/RECORD,,
|
python/main.py
CHANGED
@@ -20,7 +20,9 @@ def main():
|
|
20
20
|
|
21
21
|
if os.path.exists(bin_partis):
|
22
22
|
import subprocess
|
23
|
-
|
23
|
+
# If no arguments provided, show help
|
24
|
+
args = sys.argv[1:] if len(sys.argv) > 1 else ['--help']
|
25
|
+
result = subprocess.run([sys.executable, bin_partis] + args)
|
24
26
|
sys.exit(result.returncode)
|
25
27
|
else:
|
26
28
|
print(f'Error: partis script not found at {bin_partis}')
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|