diff --git a/CHANGES.md b/CHANGES.md index 3c17cde0..fd6a48a5 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,10 @@ # CHANGES.md +## v0.2.0.13 + +- fix pandas API call: sort_index() now requires the axis keyword +- change deprecated matplotlib register_colormap() to matplotlib.colormaps.register() + ## v0.2.12 - fix Issue #177: input filenames that contain an open or a closed parenthesis produce the message: 'WARNING: At least one BLAST run failed. ANIb may fail.' diff --git a/Makefile b/Makefile index 047d23f0..19854804 100644 --- a/Makefile +++ b/Makefile @@ -41,7 +41,7 @@ sge : clean test_sge ANIm : @echo "Testing ANIm analysis..." - ./average_nucleotide_identity.py -i $(DATA) -o $(OUT_M) \ + average_nucleotide_identity.py -i $(DATA) -o $(OUT_M) \ -m ANIm --classes $(CLASSES) --labels $(LABELS) -g -v \ $(LAZYMUMMER) --gformat $(GFORMAT) --gmethod $(GMETHOD) @echo "ANIm analysis test done" @@ -49,7 +49,7 @@ ANIm : ANIm_sge : @echo "Testing ANIm analysis with SGE..." - ./average_nucleotide_identity.py -i $(DATA) -o $(OUT_M) \ + average_nucleotide_identity.py -i $(DATA) -o $(OUT_M) \ -m ANIm --classes $(CLASSES) --labels $(LABELS) -g -v \ --scheduler SGE $(LAZYMUMMER) --gformat $(GFORMAT)\ --gmethod $(GMETHOD) @@ -58,7 +58,7 @@ ANIm_sge : ANIb : @echo "Testing ANIb analysis..." - ./average_nucleotide_identity.py -i $(DATA) -o $(OUT_B) \ + average_nucleotide_identity.py -i $(DATA) -o $(OUT_B) \ -m ANIb --classes $(CLASSES) --labels $(LABELS) -g -v \ $(LAZYBLAST) --gformat $(GFORMAT) --gmethod $(GMETHOD) @echo "ANIb analysis test done" @@ -66,7 +66,7 @@ ANIb : ANIb_sge : @echo "Testing ANIb analysis with SGE..." - ./average_nucleotide_identity.py -i $(DATA) -o $(OUT_B) \ + average_nucleotide_identity.py -i $(DATA) -o $(OUT_B) \ -m ANIb --classes $(CLASSES) --labels $(LABELS) -g -v \ --scheduler SGE $(LAZYBLAST) --gformat $(GFORMAT) \ --gmethod $(GMETHOD) @@ -83,7 +83,7 @@ ANIblastall : ANIblastall_sge : @echo "Testing ANIblastall analysis with SGE..." - ./average_nucleotide_identity.py -i $(DATA) -o $(OUT_BLASTALL) \ + average_nucleotide_identity.py -i $(DATA) -o $(OUT_BLASTALL) \ -m ANIblastall --classes $(CLASSES) --labels $(LABELS) -g -v \ --scheduler SGE $(LAZYBLAST) --gformat $(GFORMAT) --gmethod $(GMETHOD) @@ -94,7 +94,7 @@ BLAST : ANIb ANIblastall TETRA : @echo "Testing TETRA analysis..." - ./average_nucleotide_identity.py -i $(DATA) -o $(OUT_TETRA) \ + average_nucleotide_identity.py -i $(DATA) -o $(OUT_TETRA) \ -m TETRA --classes $(CLASSES) --labels $(LABELS) -g -v \ $(LAZYTETRA) --gformat $(GFORMAT) --gmethod $(GMETHOD) @echo "TETRA analysis test done" diff --git a/pyani/pyani_graphics.py b/pyani/pyani_graphics.py index feeb4f9d..1290a334 100644 --- a/pyani/pyani_graphics.py +++ b/pyani/pyani_graphics.py @@ -67,14 +67,13 @@ # Register Matplotlib colourmaps -plt.register_cmap(cmap=pyani_config.CMAP_SPBND_BURD) -plt.register_cmap(cmap=pyani_config.CMAP_HADAMARD_BURD) -plt.register_cmap(cmap=pyani_config.CMAP_BURD) +plt.colormaps.register(cmap=pyani_config.CMAP_SPBND_BURD) +plt.colormaps.register(cmap=pyani_config.CMAP_HADAMARD_BURD) +plt.colormaps.register(cmap=pyani_config.CMAP_BURD) # Convenience class to hold heatmap graphics parameters class Params(object): # pylint: disable=too-few-public-methods - """Convenience class to hold heatmap rendering parameters.""" def __init__(self, params, labels=None, classes=None): @@ -116,9 +115,7 @@ def get_seaborn_colorbar(dfr, classes): lvl: pal for (lvl, pal) in zip( levels, - sns.cubehelix_palette( - len(levels), light=0.9, dark=0.1, reverse=True, start=1, rot=-2 - ), + sns.cubehelix_palette(len(levels), light=0.9, dark=0.1, reverse=True, start=1, rot=-2), ) } lvl_pal = {cls: paldict[lvl] for (cls, lvl) in list(classes.items())} @@ -326,9 +323,7 @@ def add_mpl_colorscale(fig, heatmap_gs, ax_map, params, title=None): exponent = int(floor(log10(params.vmax))) - 1 cbticks = [int(round(e, -exponent)) for e in cbticks] - scale_subplot = gridspec.GridSpecFromSubplotSpec( - 1, 3, subplot_spec=heatmap_gs[0, 0], wspace=0.0, hspace=0.0 - ) + scale_subplot = gridspec.GridSpecFromSubplotSpec(1, 3, subplot_spec=heatmap_gs[0, 0], wspace=0.0, hspace=0.0) scale_ax = fig.add_subplot(scale_subplot[0, 1]) cbar = fig.colorbar(ax_map, scale_ax, ticks=cbticks) if title: @@ -358,9 +353,7 @@ def heatmap_mpl(dfr, outfilename=None, title=None, params=None): fig = plt.figure(figsize=(figsize, figsize)) # if title: # fig.suptitle(title) - heatmap_gs = gridspec.GridSpec( - 2, 2, wspace=0.0, hspace=0.0, width_ratios=[0.3, 1], height_ratios=[0.3, 1] - ) + heatmap_gs = gridspec.GridSpec(2, 2, wspace=0.0, hspace=0.0, width_ratios=[0.3, 1], height_ratios=[0.3, 1]) # Add column and row dendrograms/axes to figure coldend = add_mpl_dendrogram(dfr, fig, heatmap_gs, orientation="col") diff --git a/tests/test_anib.py b/tests/test_anib.py index 2c41dc69..90b1246d 100644 --- a/tests/test_anib.py +++ b/tests/test_anib.py @@ -62,7 +62,6 @@ class TestBLASTCmdline(unittest.TestCase): - """Class defining tests of BLAST command-line generation.""" def setUp(self): @@ -70,9 +69,7 @@ def setUp(self): self.indir = os.path.join("tests", "test_input", "anib") self.outdir = os.path.join("tests", "test_output", "anib") self.seqdir = os.path.join("tests", "test_input", "sequences") - self.infiles = [ - os.path.join(self.seqdir, fname) for fname in os.listdir(self.seqdir) - ] + self.infiles = [os.path.join(self.seqdir, fname) for fname in os.listdir(self.seqdir)] self.fraglen = 1000 self.fmtdboutdir = os.path.join(self.outdir, "formatdb") self.fmtdbcmd = " ".join( @@ -88,15 +85,10 @@ def setUp(self): "makeblastdb -dbtype nucl -in", "tests/test_input/sequences/NC_002696.fna", "-title NC_002696 -out", - os.path.join( - "tests", "test_output", "anib", "makeblastdb", "NC_002696.fna" - ), + os.path.join("tests", "test_output", "anib", "makeblastdb", "NC_002696.fna"), ] ) - self.blastdbfnames = [ - os.path.join(self.seqdir, fname) - for fname in ("NC_002696.fna", "NC_010338.fna") - ] + self.blastdbfnames = [os.path.join(self.seqdir, fname) for fname in ("NC_002696.fna", "NC_010338.fna")] self.blastdbtgt = [ ( " ".join( @@ -146,9 +138,7 @@ def setUp(self): self.blastncmd = " ".join( [ "blastn -out", - os.path.join( - "tests", "test_output", "anib", "NC_002696_vs_NC_010338.blast_tab" - ), + os.path.join("tests", "test_output", "anib", "NC_002696_vs_NC_010338.blast_tab"), "-query tests/test_input/sequences/NC_002696.fna", "-db tests/test_input/sequences/NC_010338.fna", "-xdrop_gap_final 150 -dust no -evalue 1e-15", @@ -160,9 +150,7 @@ def setUp(self): self.blastallcmd = " ".join( [ "blastall -p blastn -o", - os.path.join( - "tests", "test_output", "anib", "NC_002696_vs_NC_010338.blast_tab" - ), + os.path.join("tests", "test_output", "anib", "NC_002696_vs_NC_010338.blast_tab"), "-i tests/test_input/sequences/NC_002696.fna", "-d tests/test_input/sequences/NC_010338.fna", "-X 150 -q -1 -F F -e 1e-15 -b 1 -v 1 -m 8", @@ -266,23 +254,19 @@ def setUp(self): [ ( "tests/test_output/anib/NC_002696.fna", - "formatdb -p F -i tests/test_output/anib/NC_002696.fna " - + "-t NC_002696", + "formatdb -p F -i tests/test_output/anib/NC_002696.fna " + "-t NC_002696", ), ( "tests/test_output/anib/NC_010338.fna", - "formatdb -p F -i tests/test_output/anib/NC_010338.fna " - + "-t NC_010338", + "formatdb -p F -i tests/test_output/anib/NC_010338.fna " + "-t NC_010338", ), ( "tests/test_output/anib/NC_011916.fna", - "formatdb -p F -i tests/test_output/anib/NC_011916.fna " - + "-t NC_011916", + "formatdb -p F -i tests/test_output/anib/NC_011916.fna " + "-t NC_011916", ), ( "tests/test_output/anib/NC_014100.fna", - "formatdb -p F -i tests/test_output/anib/NC_014100.fna " - + "-t NC_014100", + "formatdb -p F -i tests/test_output/anib/NC_014100.fna " + "-t NC_014100", ), ] ) @@ -293,65 +277,49 @@ def setUp(self): @nottest #  legacy BLAST deprecated def test_formatdb_generation(self): """generate formatdb command-line.""" - cmd = anib.construct_formatdb_cmd( - os.path.join(self.seqdir, "NC_002696.fna"), self.fmtdboutdir - ) + cmd = anib.construct_formatdb_cmd(os.path.join(self.seqdir, "NC_002696.fna"), self.fmtdboutdir) assert_equal(cmd[0], self.fmtdbcmd) # correct command assert os.path.isfile(cmd[1]) # creates new file def test_makeblastdb_generation(self): """generate makeblastdb command-line.""" - cmd = anib.construct_makeblastdb_cmd( - os.path.join(self.seqdir, "NC_002696.fna"), self.makeblastdbdir - ) + cmd = anib.construct_makeblastdb_cmd(os.path.join(self.seqdir, "NC_002696.fna"), self.makeblastdbdir) assert_equal(cmd[0], self.makeblastdbcmd) # correct command def test_blastdb_commands(self): """generate BLAST+ db commands.""" # BLAST+ - cmds = anib.generate_blastdb_commands( - self.blastdbfnames, self.outdir, mode="ANIb" - ) + cmds = anib.generate_blastdb_commands(self.blastdbfnames, self.outdir, mode="ANIb") assert_equal(cmds, self.blastdbtgt) @nottest #  legacy BLAST deprecated def test_legacy_blastdb_commands(self): """generate legacy BLAST db commands.""" # legacy - cmds = anib.generate_blastdb_commands( - self.blastdbfnames, self.outdir, mode="ANIblastall" - ) + cmds = anib.generate_blastdb_commands(self.blastdbfnames, self.outdir, mode="ANIblastall") assert_equal(cmds, self.blastdbtgtlegacy) def test_blastn_generation(self): """generate BLASTN+ command-line.""" - cmd = anib.construct_blastn_cmdline( - self.blastdbfnames[0], self.blastdbfnames[1], self.outdir - ) + cmd = anib.construct_blastn_cmdline(self.blastdbfnames[0], self.blastdbfnames[1], self.outdir) assert_equal(cmd, self.blastncmd) @nottest #  legacy BLAST deprecated def test_blastall_generation(self): """generate legacy BLASTN command-line.""" - cmd = anib.construct_blastall_cmdline( - self.blastdbfnames[0], self.blastdbfnames[1], self.outdir - ) + cmd = anib.construct_blastall_cmdline(self.blastdbfnames[0], self.blastdbfnames[1], self.outdir) assert_equal(cmd, self.blastallcmd) def test_blastn_commands(self): """generate BLASTN+ commands.""" # BLAST+ - cmds = anib.generate_blastn_commands( - self.blastdbfnames, self.outdir, mode="ANIb" - ) + cmds = anib.generate_blastn_commands(self.blastdbfnames, self.outdir, mode="ANIb") assert_equal(cmds, self.blastntgt) @nottest #  legacy BLAST deprecated def test_legacy_blastn_commands(self): """generate legacy BLASTN commands.""" - cmds = anib.generate_blastn_commands( - self.blastdbfnames, self.outdir, mode="ANIblastall" - ) + cmds = anib.generate_blastn_commands(self.blastdbfnames, self.outdir, mode="ANIblastall") assert_equal(cmds, self.blastalltgt) @nottest #  legacy BLAST deprecated @@ -359,17 +327,13 @@ def test_blastall_dbjobdict(self): """generate dictionary of legacy BLASTN database jobs.""" blastcmds = anib.make_blastcmd_builder("ANIblastall", self.outdir) jobdict = anib.build_db_jobs(self.infiles, blastcmds) - assert_equal( - sorted([(k, v.script) for (k, v) in jobdict.items()]), self.blastalljobdict - ) + assert_equal(sorted([(k, v.script) for (k, v) in jobdict.items()]), self.blastalljobdict) def test_blastn_dbjobdict(self): """generate dictionary of BLASTN+ database jobs.""" blastcmds = anib.make_blastcmd_builder("ANIb", self.outdir) jobdict = anib.build_db_jobs(self.infiles, blastcmds) - assert_equal( - sorted([(k, v.script) for (k, v) in jobdict.items()]), self.blastnjobdict - ) + assert_equal(sorted([(k, v.script) for (k, v) in jobdict.items()]), self.blastnjobdict) def test_blastn_graph(self): """create jobgraph for BLASTN+ jobs.""" @@ -400,7 +364,6 @@ def test_blastall_graph(self): class TestFragments(unittest.TestCase): - """Class defining tests of ANIb FASTA fragmentation""" def setUp(self): @@ -442,7 +405,6 @@ def test_fragment_files(self): class TestParsing(unittest.TestCase): - """Class defining tests of BLAST output parsing.""" def setUp(self): @@ -502,9 +464,7 @@ def test_parse_blasttab(self): result = anib.parse_blast_tab(self.fname, fragdata, 0.3, 0.7, mode="ANIb") assert_equal(result, (4016551, 93, 99.997693577050029)) # ANIblastall output - result = anib.parse_blast_tab( - self.fname_legacy, fragdata, 0.3, 0.7, mode="ANIblastall" - ) + result = anib.parse_blast_tab(self.fname_legacy, fragdata, 0.3, 0.7, mode="ANIblastall") assert_equal(result, (1966922, 406104, 78.578978313253018)) def test_blastdir_processing(self): @@ -514,8 +474,8 @@ def test_blastdir_processing(self): # ANIb result = anib.process_blast(self.anibdir, orglengths, fraglengths, mode="ANIb") assert_frame_equal( - result.percentage_identity.sort_index(1).sort_index(), - self.anibtgt.sort_index(1).sort_index(), + result.percentage_identity.sort_index(axis=1).sort_index(), + self.anibtgt.sort_index(axis=1).sort_index(), ) @nottest #  legacy BLAST deprecated @@ -524,9 +484,7 @@ def test_legacy_blastdir_processing(self): orglengths = pyani_files.get_sequence_lengths(self.infnames) fraglengths = anib.get_fraglength_dict(self.fragfiles) # ANIblastall - result = anib.process_blast( - self.aniblastalldir, orglengths, fraglengths, mode="ANIblastall" - ) + result = anib.process_blast(self.aniblastalldir, orglengths, fraglengths, mode="ANIblastall") assert_frame_equal( result.percentage_identity.sort_index(1).sort_index(), self.aniblastalltgt.sort_index(1).sort_index(), diff --git a/tests/test_anim.py b/tests/test_anim.py index 0c843b6e..51c658d0 100644 --- a/tests/test_anim.py +++ b/tests/test_anim.py @@ -63,7 +63,6 @@ class TestNUCmerCmdline(unittest.TestCase): - """Class defining tests of NUCmer command-line generation.""" def setUp(self): @@ -152,16 +151,12 @@ def test_single_cmd_generation(self): Tests that a single NUCmer/delta-filter command-line pair is produced correctly """ - cmds = anim.construct_nucmer_cmdline( - "file1.fna", "file2.fna", outdir=self.outdir - ) + cmds = anim.construct_nucmer_cmdline("file1.fna", "file2.fna", outdir=self.outdir) assert_equal(cmds, (self.ntgt, self.ftgt)) def test_maxmatch_cmd_generation(self): """generate NUCmer command line with maxmatch.""" - ncmd, fcmd = anim.construct_nucmer_cmdline( - "file1.fna", "file2.fna", outdir=self.outdir, maxmatch=True - ) + ncmd, fcmd = anim.construct_nucmer_cmdline("file1.fna", "file2.fna", outdir=self.outdir, maxmatch=True) assert_equal(ncmd, self.ntgtmax) def test_multi_cmd_generation(self): @@ -182,13 +177,10 @@ def test_nucmer_job_generation(self): for idx, job in enumerate(joblist): assert_equal(job.name, "test_%06d-f" % idx) # filter job name assert_equal(len(job.dependencies), 1) # has NUCmer job - assert_equal( - job.dependencies[0].name, "test_%06d-n" % idx - ) # NUCmer job name + assert_equal(job.dependencies[0].name, "test_%06d-n" % idx) # NUCmer job name class TestDeltafileProcessing(unittest.TestCase): - """Class defining tests for .delta/.filter file parsing""" def setUp(self): @@ -219,6 +211,6 @@ def test_process_deltadir(self): orglengths = pyani_files.get_sequence_lengths(seqfiles) result = anim.process_deltadir(self.deltadir, orglengths) assert_frame_equal( - result.percentage_identity.sort_index(1).sort_index(), - self.df_pid.sort_index(1).sort_index(), + result.percentage_identity.sort_index(axis=1).sort_index(), + self.df_pid.sort_index(axis=1).sort_index(), ) diff --git a/tests/test_graphics.py b/tests/test_graphics.py index 4c0087cc..62fbb70d 100644 --- a/tests/test_graphics.py +++ b/tests/test_graphics.py @@ -12,9 +12,7 @@ import os import pandas as pd -import shutil -from nose.tools import assert_equal, assert_less, nottest from pyani import pyani_graphics, pyani_config, pyani_tools @@ -26,33 +24,24 @@ def define_inputs(): - return {'infilename': os.path.join("tests", "target_ANIm_output", - "ANIm_percentage_identity.tab"), - 'labels': pyani_tools.get_labels(os.path.join("tests", - "test_ani_data", - "labels.tab"), - logger=None), - 'classes': pyani_tools.get_labels(os.path.join("tests", - "test_ani_data", - "classes.tab"), - logger=None)} - + return { + "infilename": os.path.join("tests", "target_ANIm_output", "ANIm_percentage_identity.tab"), + "labels": pyani_tools.get_labels(os.path.join("tests", "test_ani_data", "labels.tab"), logger=None), + "classes": pyani_tools.get_labels(os.path.join("tests", "test_ani_data", "classes.tab"), logger=None), + } + def draw_format_method(fmt, mth): """Render graphics format and method output.""" inputs = define_inputs() outfilename = os.path.join(OUTDIR, "%s.%s" % (mth, fmt)) stem = "ANIm_percentage_identity" - df = pd.read_csv(inputs['infilename'], index_col=0, sep="\t") + df = pd.read_csv(inputs["infilename"], index_col=0, sep="\t") os.makedirs(OUTDIR, exist_ok=True) - fn = {"mpl": pyani_graphics.heatmap_mpl, - "seaborn": pyani_graphics.heatmap_seaborn} - params = {"mpl": pyani_config.params_mpl, - "seaborn": pyani_config.params_mpl} - method_params = pyani_graphics.Params(params[mth](df)[stem], - inputs['labels'], inputs['classes']) - fn[mth](df, outfilename, title="%s:%s test" % (mth, fmt), - params=method_params) + fn = {"mpl": pyani_graphics.heatmap_mpl, "seaborn": pyani_graphics.heatmap_seaborn} + params = {"mpl": pyani_config.params_mpl, "seaborn": pyani_config.params_mpl} + method_params = pyani_graphics.Params(params[mth](df)[stem], inputs["labels"], inputs["classes"]) + fn[mth](df, outfilename, title="%s:%s test" % (mth, fmt), params=method_params) def test_png_mpl():