def test_coin_sample_post(self): """Test sampling from posterior distribution""" outdir = 'test/tmp/test_hmm/test_coin_sample_post/' make_clean_dir(outdir) model = make_coin_model() # sample states and data ndata = 100 states = list(islice(hmm.sample_hmm_states(model), ndata)) data = list(hmm.sample_hmm_data(model, states)) model.prob_emission = (lambda pos, state: model.prob_emission_data(state, data[pos])) p = Gnuplot() p.enableOutput(False) p.plot(states, style="lines") probs = hmm.get_posterior_probs(model, len(data)) states2 = [exp(probs[i][1]) for i in xrange(len(data))] p.plot(util.vadds(states2, 1.5), style="lines", miny=-1, maxy=12) for i in range(2, 10): states2 = hmm.sample_posterior(model, ndata) self.assertTrue(stats.corr(states, states2) > .5) p.plot(util.vadds(states2, 1.5*i), style="lines", miny=-1, maxy=12) p.enableOutput(True) p.save(outdir + 'plot.png')
def test_trans(): """ Calculate transition probabilities """ create_data = False if create_data: make_clean_dir('test/data/test_trans') k = 8 n = 1e4 rho = 1.5e-8 * 20 length = 1000 times = argweaver.get_time_points(ntimes=10, maxtime=200000) popsizes = [n] * len(times) ntests = 40 # generate test data if create_data: for i in range(ntests): arg = arglib.sample_arg(k, 2*n, rho, start=0, end=length) argweaver.discretize_arg(arg, times) arg.write('test/data/test_trans/%d.arg' % i) for i in range(ntests): print 'arg', i arg = arglib.read_arg('test/data/test_trans/%d.arg' % i) argweaver.discretize_arg(arg, times) pos = 10 tree = arg.get_marginal_tree(pos) assert argweaverc.assert_transition_probs(tree, times, popsizes, rho)
def test_coin_sample_post(self): """Test sampling from posterior distribution""" outdir = 'test/tmp/test_hmm/test_coin_sample_post/' make_clean_dir(outdir) model = make_coin_model() # sample states and data ndata = 100 states = list(islice(hmm.sample_hmm_states(model), ndata)) data = list(hmm.sample_hmm_data(model, states)) model.prob_emission = ( lambda pos, state: model.prob_emission_data(state, data[pos])) p = Gnuplot() p.enableOutput(False) p.plot(states, style="lines") probs = hmm.get_posterior_probs(model, len(data)) states2 = [exp(probs[i][1]) for i in xrange(len(data))] p.plot(util.vadds(states2, 1.5), style="lines", miny=-1, maxy=12) for i in range(2, 10): states2 = hmm.sample_posterior(model, ndata) self.assertTrue(stats.corr(states, states2) > .5) p.plot(util.vadds(states2, 1.5 * i), style="lines", miny=-1, maxy=12) p.enableOutput(True) p.save(outdir + 'plot.png')
def test_cdf_coal_cond_counts(self): # test coalescent pdf when conditioned on future lineage counts outdir = 'test/tmp/test_coal/Coal_test_cdf_coal_cond_counts/' make_clean_dir(outdir) a = 5 for b in xrange(2, a): t = 500 n = 1000 p = Gnuplot() p.enableOutput(False) p.plotfunc(lambda x: coal.cdf_coal_cond_counts( x, a, b, t, n), 0, t, 10) # draw single coal samples using rejection sampling s = [] for i in xrange(1000): while True: times = coal.sample_coal_times(a, n) if times[a-b-1] < t and (b == 1 or times[a-b] > t): break s.append(times[0]) x2, y2 = stats.cdf(s) p.plot(x2, y2, style='lines') p.enableOutput(True) p.save(outdir + 'plot-%d.png' % b) eq_sample_pdf( x2, lambda x: coal.prob_coal_cond_counts(x, a, b, t, n), 40)
def test2(self): outdir = 'test/tmp/test_vistrans/Vis_test2/' make_clean_dir(outdir) stree = treelib.parse_newick(stree_newick) tree = treelib.read_tree(treefile2) brecon = phylo.read_brecon(breconfile2, tree, stree) transsvg.draw_tree(tree, brecon, stree, filename=outdir + "tree.svg")
def test_install(): """ Test installing compbio. """ make_clean_dir("test/tmp/install") run_cmd("python setup.py clean > /dev/null") run_cmd("python setup.py install --prefix=test/tmp/install > /dev/null") assert os.path.exists("test/tmp/install/bin/viewtree")
def test_install(): """ Test installing ARGweaver. """ make_clean_dir("test/tmp/install") run_cmd("python setup.py clean > /dev/null") run_cmd("make install prefix=test/tmp/install > /dev/null") run_cmd("PYTHONPATH=test/tmp/install python -c 'import argweaver'") assert os.path.exists("test/tmp/install/bin/arg-sample")
def test_install(): """ Test installing ARGweaver. """ make_clean_dir("test/data/install") run_cmd("python setup.py clean > /dev/null") run_cmd("make install prefix=test/data/install > /dev/null") run_cmd("PYTHONPATH=test/data/install python -c 'import argweaver'") assert os.path.exists("test/data/install/bin/arg-sample")
def test3(self): outdir = 'test/tmp/test_vistrans/Vis_test3/' make_clean_dir(outdir) stree = treelib.parse_newick(stree_newick) tree = treelib.read_tree(treefile3) brecon = phylo.read_brecon(breconfile3, tree, stree) phylo.add_implied_spec_nodes_brecon(tree, brecon) phylo.write_brecon(open(outdir + 'brecon', 'w'), brecon) transsvg.draw_tree(tree, brecon, stree, filename=outdir + "tree.svg")
def test_install_prog(): """ Test installing ARGweaver program. Use Makefile to install. """ make_clean_dir("test/tmp/install") run_cmd("python setup.py clean > /dev/null") run_cmd("make install prefix=test/tmp/install > /dev/null") run_cmd("PYTHONPATH=test/tmp/install python -c 'import argweaver; " "assert argweaver.argweaverc.argweaverclib'") assert os.path.exists("test/tmp/install/bin/arg-sample")
def test_trans_switch(): """ Calculate transition probabilities for switch matrix Only calculate a single matrix """ create_data = False if create_data: make_clean_dir('test/data/test_trans_switch') # model parameters k = 12 n = 1e4 rho = 1.5e-8 * 20 length = 1000 times = argweaver.get_time_points(ntimes=20, maxtime=200000) popsizes = [n] * len(times) ntests = 100 # generate test data if create_data: for i in range(ntests): # Sample ARG with at least one recombination. while True: arg = argweaver.sample_arg_dsmc(k, 2 * n, rho, start=0, end=length, times=times) if any(x.event == "recomb" for x in arg): break arg.write('test/data/test_trans_switch/%d.arg' % i) for i in range(ntests): print('arg', i) arg = arglib.read_arg('test/data/test_trans_switch/%d.arg' % i) argweaver.discretize_arg(arg, times) recombs = [x.pos for x in arg if x.event == "recomb"] pos = recombs[0] tree = arg.get_marginal_tree(pos - .5) rpos, r, c = next(arglib.iter_arg_sprs(arg, start=pos - .5)) spr = (r, c) if not argweaverc.assert_transition_switch_probs( tree, spr, times, popsizes, rho): tree2 = tree.get_tree() treelib.remove_single_children(tree2) treelib.draw_tree_names(tree2, maxlen=5, minlen=5) assert False
def test_read_sites(): """ Test reading site files. """ make_clean_dir("test/tmp/test_read_sites") os.system("""bin/arg-sim \ -k 10 -L 10000 \ -N 1e4 -r 1.5e-8 -m 2.5e-8 \ --ntimes 10 --maxtime 400e3 \ -o test/tmp/test_read_sites/0 > /dev/null""") sites = argweaverc.argweaver_read_sites('test/tmp/test_read_sites/0.sites', -1, -1) argweaverc.argweaver_delete_sites(sites)
def test_read_sites(): """ Test reading site files. """ make_clean_dir("test/tmp/test_read_sites") os.system("""bin/arg-sim \ -k 10 -L 10000 \ -N 1e4 -r 1.5e-8 -m 2.5e-8 \ --ntimes 10 --maxtime 400e3 \ -o test/tmp/test_read_sites/0 > /dev/null""") sites = argweaverc.argweaver_read_sites( 'test/tmp/test_read_sites/0.sites', -1, -1) argweaverc.argweaver_delete_sites(sites)
def test_trans_switch(): """ Calculate transition probabilities for switch matrix Only calculate a single matrix """ create_data = False if create_data: make_clean_dir('test/data/test_trans_switch') # model parameters k = 12 n = 1e4 rho = 1.5e-8 * 20 length = 1000 times = argweaver.get_time_points(ntimes=20, maxtime=200000) popsizes = [n] * len(times) ntests = 100 # generate test data if create_data: for i in range(ntests): # Sample ARG with at least one recombination. while True: arg = argweaver.sample_arg_dsmc( k, 2*n, rho, start=0, end=length, times=times) if any(x.event == "recomb" for x in arg): break arg.write('test/data/test_trans_switch/%d.arg' % i) for i in range(ntests): print 'arg', i arg = arglib.read_arg('test/data/test_trans_switch/%d.arg' % i) argweaver.discretize_arg(arg, times) recombs = [x.pos for x in arg if x.event == "recomb"] pos = recombs[0] tree = arg.get_marginal_tree(pos-.5) rpos, r, c = arglib.iter_arg_sprs(arg, start=pos-.5).next() spr = (r, c) if not argweaverc.assert_transition_switch_probs( tree, spr, times, popsizes, rho): tree2 = tree.get_tree() treelib.remove_single_children(tree2) treelib.draw_tree_names(tree2, maxlen=5, minlen=5) assert False
def test_install_lib(): """ Test installing ARGweaver python lib. Use setup.py to install and check that module can be imported. Also ensure that c library is installed. """ make_clean_dir("test/tmp/install_lib") run_cmd("python setup.py clean > /dev/null") run_cmd( "python setup.py install --prefix=test/tmp/install_lib " "--install-lib=test/tmp/install_lib/lib/python/site-packages " "> /dev/null") run_cmd("cd test; PYTHONPATH=tmp/install_lib/lib/python/site-packages " "python -c 'import argweaver; " "assert argweaver.argweaverc.argweaverclib'")
def test_top(self): outdir = 'test/tmp/test_coal/BMC_test_top/' make_clean_dir(outdir) stree = treelib.parse_newick( "(((A:200, E:200):800, B:1000):500, (C:700, D:700):800);") n = 500 T = 2000 nsamples = 4000 # compare top hist with simpler rejection sampling tops = {} tops2 = {} for i in xrange(nsamples): # use rejection sampling tree, recon = coal.sample_bounded_multicoal_tree_reject( stree, n, T, namefunc=lambda x: x) # sample tree tree2, recon2 = coal.sample_bounded_multicoal_tree( stree, n, T, namefunc=lambda x: x) top = phylo.hash_tree(tree) top2 = phylo.hash_tree(tree2) tops.setdefault(top, [0, tree, recon])[0] += 1 tops.setdefault(top2, [0, tree2, recon2]) tops2.setdefault(top2, [0, tree2, recon2])[0] += 1 tops2.setdefault(top, [0, tree, recon]) keys = tops.keys() x = [safelog(tops[i][0], default=0) for i in keys] y = [safelog(tops2[i][0], default=0) for i in keys] self.assertTrue(stats.corr(x, y) > .9) p = Gnuplot() p.enableOutput(False) p.plot(x, y) p.plot([min(x), max(x)], [min(x), max(x)], style="lines") p.enableOutput(True) p.save(outdir + 'plot.png')
def test_sample_lineages(self): """lineage over time""" outdir = 'test/tmp/test_arglib/Arg_test_sample_lineages/' make_clean_dir(outdir) rho = 1.5e-8 # recomb/site/gen l = 5000 # length of locus k = 60 # number of lineages n = 2*10000 # effective popsize r = rho * l # recomb/locus/gen rplot_start(outdir + '/plot.pdf') rp.plot([1, 40000], [1, k], t="n", log="xy") times, events = arglib.sample_coal_recomb_times(k, n, r) lineages = list(arglib.lineages_over_time(k, events)) rp.lines(times, lineages) rplot_end()
def test_install_sdist(): """ Test installing ARGweaver from a sdist. """ make_clean_dir("test/tmp/install_sdist") run_cmd("python setup.py clean > /dev/null") run_cmd("python setup.py sdist --dist-dir=test/tmp/install_sdist") run_cmd("cd test/tmp/install_sdist; " "tar zxvf *.tar.gz; " "cd argweaver-*; " "python setup.py install --prefix=. " "--install-lib=lib/python/site-packages " "> /dev/null") run_cmd("cd test/tmp/install_sdist/argweaver-*; " "PYTHONPATH=lib/python/site-packages " "python -c 'import argweaver; " "assert argweaver.argweaverc.argweaverclib'")
def _test_prog_infsites(): make_clean_dir("test/data/test_prog_infsites") run_cmd("""bin/arg-sim \ -k 40 -L 200000 \ -N 1e4 -r 1.5e-8 -m 2.5e-8 --infsites \ --ntimes 20 --maxtime 400e3 \ -o test/data/test_prog_infsites/0""") make_clean_dir("test/data/test_prog_infsites/0.sample") run_cmd("""bin/arg-sample \ -s test/data/test_prog_infsites/0.sites \ -N 1e4 -r 1.5e-8 -m 2.5e-8 \ --ntimes 5 --maxtime 100e3 -c 1 \ --climb 0 -n 20 --infsites \ -x 1 \ -o test/data/test_prog_infsites/0.sample/out""") arg = argweaver.read_arg( "test/data/test_prog_infsites/0.sample/out.0.smc.gz") sites = argweaver.read_sites("test/data/test_prog_infsites/0.sites") print "names", sites.names print noncompats = [] for block, tree in arglib.iter_local_trees(arg): tree = tree.get_tree() treelib.remove_single_children(tree) phylo.hash_order_tree(tree) for pos, col in sites.iter_region(block[0]+1, block[1]+1): assert block[0]+1 <= pos <= block[1]+1, (block, pos) split = sites_split(sites.names, col) node = arglib.split_to_tree_branch(tree, split) if node is None: noncompats.append(pos) print "noncompat", block, pos, col print phylo.hash_tree(tree) print tree.leaf_names() print "".join(col[sites.names.index(name)] for name in tree.leaf_names()) print split print print "num noncompats", len(noncompats)
def _test_prog_infsites(): make_clean_dir("test/tmp/test_prog_infsites") run_cmd("""bin/arg-sim \ -k 40 -L 200000 \ -N 1e4 -r 1.5e-8 -m 2.5e-8 --infsites \ --ntimes 20 --maxtime 400e3 \ -o test/tmp/test_prog_infsites/0""") make_clean_dir("test/tmp/test_prog_infsites/0.sample") run_cmd("""bin/arg-sample \ -s test/tmp/test_prog_infsites/0.sites \ -N 1e4 -r 1.5e-8 -m 2.5e-8 \ --ntimes 5 --maxtime 100e3 -c 1 \ --climb 0 -n 20 --infsites \ -x 1 \ -o test/tmp/test_prog_infsites/0.sample/out""") arg = argweaver.read_arg( "test/tmp/test_prog_infsites/0.sample/out.0.smc.gz") sites = argweaver.read_sites("test/tmp/test_prog_infsites/0.sites") print "names", sites.names print noncompats = [] for block, tree in arglib.iter_local_trees(arg): tree = tree.get_tree() treelib.remove_single_children(tree) phylo.hash_order_tree(tree) for pos, col in sites.iter_region(block[0] + 1, block[1] + 1): assert block[0] + 1 <= pos <= block[1] + 1, (block, pos) split = sites_split(sites.names, col) node = arglib.split_to_tree_branch(tree, split) if node is None: noncompats.append(pos) print "noncompat", block, pos, col print phylo.hash_tree(tree) print tree.leaf_names() print "".join(col[sites.names.index(name)] for name in tree.leaf_names()) print split print print "num noncompats", len(noncompats)
def test_prog_small(): """ Test arg-sample on a small simulated dataset """ make_clean_dir("test/data/test_prog_small") run_cmd("""bin/arg-sim \ -k 4 -L 100000 \ -N 1e4 -r 1.5e-8 -m 2.5e-8 \ --ntimes 10 --maxtime 400e3 \ -o test/data/test_prog_small/0 > /dev/null""") make_clean_dir("test/data/test_prog_small/0.sample") run_cmd("""bin/arg-sample -q \ -s test/data/test_prog_small/0.sites \ -x 1 -N 1e4 -r 1.5e-8 -m 2.5e-8 \ --ntimes 10 --maxtime 400e3 -c 20 \ -n 10 --sample-step 1 \ -o test/data/test_prog_small/0.sample/out""")
def test_prob_coal2(self): outdir = 'test/tmp/test_coal/Coal_test_prob_coal2/' make_clean_dir(outdir) k = 2 n = 1000 p = Gnuplot() p.enableOutput(False) p.plotfunc(lambda t: coal.prob_coal(t, k, n), 0, 4000, 10, ymin=0) # draw single coal samples x = [coal.sample_coal(k, n) for i in xrange(200)] plotdistrib(x, 40, plot=p) p.enableOutput(True) p.save(outdir + 'plot.png') eq_sample_pdf(x, lambda t: coal.prob_coal(t, k, n), 40)
def test_prog_small(): """ Test arg-sample on a small simulated dataset """ make_clean_dir("test/tmp/test_prog_small") run_cmd("""bin/arg-sim \ -k 4 -L 100000 \ -N 1e4 -r 1.5e-8 -m 2.5e-8 \ --ntimes 10 --maxtime 400e3 \ -o test/tmp/test_prog_small/0 > /dev/null""") make_clean_dir("test/tmp/test_prog_small/0.sample") run_cmd("""bin/arg-sample -q \ -s test/tmp/test_prog_small/0.sites \ -x 1 -N 1e4 -r 1.5e-8 -m 2.5e-8 \ --ntimes 10 --maxtime 400e3 -c 20 \ -n 10 --sample-step 1 \ -o test/tmp/test_prog_small/0.sample/out""")
def test_prog_popsizes(): """ Ensure arg-sample can use multiple population sizes from a file. """ make_clean_dir("test/tmp/test_prog_popsizes") # Setup popsize config file. popsizes = range(10000, 0, -1000) with open('test/tmp/test_prog_popsizes/popsizes', 'w') as out: out.write('\n'.join(map(str, popsizes))) run_cmd("""bin/arg-sim \ -k 4 -L 100000 \ -N 1e4 -r 1.5e-8 -m 2.5e-8 \ --ntimes 10 --maxtime 400e3 \ -o test/tmp/test_prog_popsizes/0 > /dev/null""") make_clean_dir("test/tmp/test_prog_popsizes/0.sample") run_cmd("""bin/arg-sample -q \ -s test/tmp/test_prog_popsizes/0.sites \ -x 1 -N 1e4 -r 1.5e-8 -m 2.5e-8 \ --ntimes 10 --maxtime 400e3 -c 20 \ --popsize-file test/tmp/test_prog_popsizes/popsizes \ -n 10 --sample-step 1 \ -o test/tmp/test_prog_popsizes/0.sample/out""") # Write too few population sizes to config file. popsizes_bad = range(10000, 5000, -1000) with open('test/tmp/test_prog_popsizes/popsizes-bad', 'w') as out: out.write('\n'.join(map(str, popsizes_bad))) # Expect an error. run_cmd( """bin/arg-sample -q \ -s test/tmp/test_prog_popsizes/0.sites \ -x 1 -N 1e4 -r 1.5e-8 -m 2.5e-8 \ --ntimes 10 --maxtime 400e3 -c 20 \ --popsize-file test/tmp/test_prog_popsizes/popsizes-bad \ -n 10 --sample-step 1 \ -o test/tmp/test_prog_popsizes/0.sample/out-bad""", EXIT_ERROR)
def test_prog_popsizes(): """ Ensure arg-sample can use multiple population sizes from a file. """ make_clean_dir("test/tmp/test_prog_popsizes") # Setup popsize config file. popsizes = range(10000, 0, -1000) with open('test/tmp/test_prog_popsizes/popsizes', 'w') as out: out.write('\n'.join(map(str, popsizes))) run_cmd("""bin/arg-sim \ -k 4 -L 100000 \ -N 1e4 -r 1.5e-8 -m 2.5e-8 \ --ntimes 10 --maxtime 400e3 \ -o test/tmp/test_prog_popsizes/0 > /dev/null""") make_clean_dir("test/tmp/test_prog_popsizes/0.sample") run_cmd("""bin/arg-sample -q \ -s test/tmp/test_prog_popsizes/0.sites \ -x 1 -N 1e4 -r 1.5e-8 -m 2.5e-8 \ --ntimes 10 --maxtime 400e3 -c 20 \ --popsize-file test/tmp/test_prog_popsizes/popsizes \ -n 10 --sample-step 1 \ -o test/tmp/test_prog_popsizes/0.sample/out""") # Write too few population sizes to config file. popsizes_bad = range(10000, 5000, -1000) with open('test/tmp/test_prog_popsizes/popsizes-bad', 'w') as out: out.write('\n'.join(map(str, popsizes_bad))) # Expect an error. run_cmd("""bin/arg-sample -q \ -s test/tmp/test_prog_popsizes/0.sites \ -x 1 -N 1e4 -r 1.5e-8 -m 2.5e-8 \ --ntimes 10 --maxtime 400e3 -c 20 \ --popsize-file test/tmp/test_prog_popsizes/popsizes-bad \ -n 10 --sample-step 1 \ -o test/tmp/test_prog_popsizes/0.sample/out-bad""", EXIT_ERROR)
def test_cdf_mrca(self): outdir = 'test/tmp/test_coal/Coal_test_cdf_mrca/' make_clean_dir(outdir) n = 1000 k = 6 step = 10 x = list(frange(0, 5000, step)) y = [coal.prob_mrca(i, k, n) * step for i in x] y2 = cumsum(y) y3 = [coal.cdf_mrca(t, k, n) for t in x] p = Gnuplot() p.enableOutput(False) p.plot(x, y2, style="lines") p.plot(x, y3, style="lines") p.enableOutput(True) p.save(outdir + 'plot.png') eq_sample_pdf(x, lambda t: coal.cdf_mrca(t, k, n), 40)
def test_prob_coal_cond_counts_simple(self): # when we condition on b=1, it is the same as the bounded coal # PDF. # prob_coal_cond_counts is actually a more general version of # prob_bounded_coal outdir = 'test/tmp/test_coal/Coal_test_prob_coal_counys_simple/' make_clean_dir(outdir) a = 5 b = 1 t = 2000 n = 1000 p = Gnuplot() p.enableOutput(False) for x in frange(0, 2000, 10): y = coal.prob_coal_cond_counts_simple(x, a, b, t, n) y2 = coal.prob_bounded_coal(x, a, n, t) self.assertAlmostEqual(y, y2)
def test_coin(self): """Test that viterbi and posterior coding work well.""" outdir = 'test/tmp/test_hmm/test_coin/' make_clean_dir(outdir) model = make_coin_model() # sample states ndata = 100 states = list(islice(hmm.sample_hmm_states(model), ndata)) p = Gnuplot() p.enableOutput(False) p.plot(states, style="lines") # sample data data = list(hmm.sample_hmm_data(model, states)) # viterbi model.prob_emission = ( lambda pos, state: model.prob_emission_data(state, data[pos])) states2 = hmm.viterbi(model, len(data)) # posterior probs = hmm.get_posterior_probs(model, len(data)) states3 = [exp(probs[i][1]) for i in xrange(len(data))] # assert that inferences correlates with true state self.assertTrue(stats.corr(states, states2) > .5) self.assertTrue(stats.corr(states, states3) > .5) # plot inference p.plot(util.vadds(states2, 1.5), style="lines", miny=-1, maxy=4) p.plot(util.vadds(states3, 2.5), style="lines", miny=-1, maxy=4) p.enableOutput(True) p.save(outdir + 'plot.png')
def test_coin(self): """Test that viterbi and posterior coding work well.""" outdir = 'test/tmp/test_hmm/test_coin/' make_clean_dir(outdir) model = make_coin_model() # sample states ndata = 100 states = list(islice(hmm.sample_hmm_states(model), ndata)) p = Gnuplot() p.enableOutput(False) p.plot(states, style="lines") # sample data data = list(hmm.sample_hmm_data(model, states)) # viterbi model.prob_emission = (lambda pos, state: model.prob_emission_data(state, data[pos])) states2 = hmm.viterbi(model, len(data)) # posterior probs = hmm.get_posterior_probs(model, len(data)) states3 = [exp(probs[i][1]) for i in xrange(len(data))] # assert that inferences correlates with true state self.assertTrue(stats.corr(states, states2) > .5) self.assertTrue(stats.corr(states, states3) > .5) # plot inference p.plot(util.vadds(states2, 1.5), style="lines", miny=-1, maxy=4) p.plot(util.vadds(states3, 2.5), style="lines", miny=-1, maxy=4) p.enableOutput(True) p.save(outdir + 'plot.png')