diff --git a/coolbox/cli.py b/coolbox/cli.py index c15eade..4ae9ddb 100644 --- a/coolbox/cli.py +++ b/coolbox/cli.py @@ -250,7 +250,6 @@ def source(self) -> str: def print_source(self): """Print the browser composing code.""" print(self.source()) - return self def gen_notebook(self, notebook_path, notes=True, figsave=True): """Generate The notebook contain codes for run coolbox browser. @@ -288,7 +287,6 @@ def gen_notebook(self, notebook_path, notes=True, figsave=True): ) nb['cells'] = cells nbf.write(nb, notebook_path) - return self def run_jupyter(self, jupyter_args="--ip=0.0.0.0"): """Create a notebook according to command line, then start a jupyter process. diff --git a/coolbox/core/coverage/highlights.py b/coolbox/core/coverage/highlights.py index f4641fc..b437eb5 100644 --- a/coolbox/core/coverage/highlights.py +++ b/coolbox/core/coverage/highlights.py @@ -87,9 +87,9 @@ def __init__(self, file_, **kwargs): "file": file_, "color": "bed_rgb", "alpha": 0.1, - "border_line": True, + "border_line": False, "border_line_style": "dashed", - "border_line_width": 0, + "border_line_width": 2, "border_line_color": "#000000", "border_line_alpha": 0.8, } @@ -168,9 +168,9 @@ def __init__(self, highlight_regions, **kwargs): "highlight_regions": highlight_regions, "color": HighLights.DEFAULT_COLOR, "alpha": 0.25, - "border_line": True, + "border_line": False, "border_line_style": "dashed", - "border_line_width": 0, + "border_line_width": 2, "border_line_color": "#000000", "border_line_alpha": 0.8, } diff --git a/coolbox/core/frame/frame.py b/coolbox/core/frame/frame.py index 53597e7..f06b6f2 100644 --- a/coolbox/core/frame/frame.py +++ b/coolbox/core/frame/frame.py @@ -146,7 +146,7 @@ def get_tracks_height(self, default_height=3): heights.append(default_height) return heights - def plot(self, *args): + def plot(self, *args, close_fig=True): """ Plot all tracks. @@ -231,7 +231,8 @@ def plot(self, *args): bottom=margins['bottom'], top=margins['top']) - plt.close() + if close_fig: + plt.close() return fig diff --git a/coolbox/core/track/ideogram.py b/coolbox/core/track/ideogram.py index 3c1a26a..c4bf6a3 100644 --- a/coolbox/core/track/ideogram.py +++ b/coolbox/core/track/ideogram.py @@ -1,5 +1,5 @@ import pandas as pd -from matplotlib.collections import BrokenBarHCollection +import matplotlib.pyplot as plt from coolbox.utilities import ( get_logger, GenomeRange, file_to_intervaltree, hex2rgb, @@ -102,9 +102,10 @@ def plot(self, ax, gr: GenomeRange, **kwargs): and gr.length < 80_000_000 ): self.plot_text(band_name, start, end, gr, band_color) - coll = BrokenBarHCollection(xranges, (0, band_height), facecolors=colors, - linewidths=self.properties['border_width'], - edgecolors=self.properties['border_color']) + coll = plt.broken_barh( + xranges, (0, band_height), facecolors=colors, + linewidth=self.properties['border_width'], + edgecolor=self.properties['border_color']) ax.add_collection(coll) ax.set_ylim(-0.1, band_height + 0.1) ax.set_xlim(gr.start, gr.end) diff --git a/tests/conftest.py b/tests/conftest.py index fe2936b..fffd5a6 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,5 +1,7 @@ import os import os.path as osp +import pytest +from coolbox.utilities import GenomeRange HERE = osp.dirname(osp.abspath(__file__)) @@ -24,3 +26,47 @@ def pytest_sessionstart(session): def pytest_sessionfinish(session): clear_bgz_and_indexes() + +@pytest.fixture +def data_dir(): + return DATA_DIR + + +@pytest.fixture +def test_interval(): + test_interval = GenomeRange("chr9:4000000-6000000") + return test_interval + + +@pytest.fixture +def test_itv(test_interval): + return str(test_interval).replace(':', '_').replace('-', '_') + + +@pytest.fixture +def empty_interval(): + empty_interval = GenomeRange("chr10:4000000-6000000") + return empty_interval + + +@pytest.fixture +def sub_interval1(): + sub_interval1 = GenomeRange("chr9:4500000-5000000") + return sub_interval1 + + +@pytest.fixture +def sub_interval2(): + sub_interval2 = GenomeRange("chr9:5200000-5850000") + return sub_interval2 + + +@pytest.fixture +def tmp_dir(): + # yield a temporary directory + # delete it after the test + from tempfile import mkdtemp + import shutil + tmpdir = mkdtemp() + yield tmpdir + shutil.rmtree(tmpdir) diff --git a/tests/test_cli.py b/tests/test_cli.py index 61402c0..7818b51 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -1,21 +1,19 @@ import os.path as osp import subprocess as subp - HERE = osp.dirname(osp.abspath(__file__)) -DATA_DIR = f"{HERE}/test_data" test_interval = "chr9:4000000-6000000" empty_interval = "chr10:4000000-6000000" test_itv = test_interval.replace(':', '_').replace('-', '_') -def test_cli_plot(): +def test_cli_plot(data_dir, tmp_dir): cmd = [ "python", "-m", "coolbox.cli", "add", "XAxis", "-", - "add", "BigWig", f"{DATA_DIR}/bigwig_{test_itv}.bw", "-", - "add", "BedGraph", f"{DATA_DIR}/bedgraph_{test_itv}.bg", "-", - "add", "GTF", f"{DATA_DIR}/gtf_{test_itv}.gtf", "-", + "add", "BigWig", f"{data_dir}/bigwig_{test_itv}.bw", "-", + "add", "BedGraph", f"{data_dir}/bedgraph_{test_itv}.bg", "-", + "add", "GTF", f"{data_dir}/gtf_{test_itv}.gtf", "-", "goto", test_interval, "-", "plot", "/tmp/test_coolbox.pdf", ] @@ -25,36 +23,39 @@ def test_cli_plot(): python -m coolbox.cli joint_view top - add XAxis - - add GTF {DATA_DIR}/gtf_{test_itv}.gtf - + add GTF {data_dir}/gtf_{test_itv}.gtf - add Title GTF - joint_view right - add XAxis - - add BigWig {DATA_DIR}/bigwig_{test_itv}.bw - + add BigWig {data_dir}/bigwig_{test_itv}.bw - add TrackHeight 2 - add MinValue 0 - joint_view center - - add Cool {DATA_DIR}/cool_{test_itv}.mcool - + add Cool {data_dir}/cool_{test_itv}.mcool - goto 'chr9:4500000-5000000' 'chr9:5200000-5850000' - - plot /tmp/test_coolbox_joint_view.svg + plot {tmp_dir}/test_coolbox_joint_view.svg """ - - subp.check_call(cmd.replace("\n", ""), shell=True) + cmd = cmd.replace("\n", "") + print(cmd) + subp.check_call(cmd, shell=True) -def test_cli_gen_notebook(): +def test_cli_gen_notebook(data_dir, tmp_dir): cmd = [ "python", "-m", "coolbox.cli", "add", "XAxis", "-", - "add", "BigWig", f"{DATA_DIR}/bigwig_{test_itv}.bw", "-", - "add", "BedGraph", f"{DATA_DIR}/bedgraph_{test_itv}.bg", "-", - "add", "GTF", f"{DATA_DIR}/gtf_{test_itv}.gtf", "-", + "add", "BigWig", f"{data_dir}/bigwig_{test_itv}.bw", "-", + "add", "BedGraph", f"{data_dir}/bedgraph_{test_itv}.bg", "-", + "add", "GTF", f"{data_dir}/gtf_{test_itv}.gtf", "-", "goto", test_interval, "-", - "gen_notebook", "/tmp/test_coolbox.ipynb", + "gen_notebook", f"{tmp_dir}/test_coolbox.ipynb", ] - subp.check_call(cmd) + cmd = " ".join(cmd) + print(cmd) + subp.check_call(cmd, shell=True) -def test_cli_import_custom(): +def test_cli_import_custom(tmp_dir): custom_path = osp.join(HERE, "custom_track.py") cmd = [ "python", "-m", "coolbox.cli", @@ -62,6 +63,8 @@ def test_cli_import_custom(): "add", "XAxis", "-", "add", "CustomTrack", "-", "goto", test_interval, "-", - "plot", "/tmp/test_coolbox_custom.pdf" + "plot", f"{tmp_dir}/test_coolbox_custom.pdf" ] - subp.check_call(cmd) + cmd = " ".join(cmd) + print(cmd) + subp.check_call(cmd, shell=True) diff --git a/tests/test_coverage.py b/tests/test_coverage.py index 74b7221..c44be78 100644 --- a/tests/test_coverage.py +++ b/tests/test_coverage.py @@ -1,54 +1,52 @@ -import os.path as osp from coolbox.api import * -HERE = osp.dirname(osp.abspath(__file__)) -DATA_DIR = f"{HERE}/test_data" -test_interval = "chr9:4000000-6000000" -empty_interval = "chr10:4000000-6000000" -test_itv = test_interval.replace(':', '_').replace('-', '_') - -def test_vlines(): +def test_vlines(test_interval, tmp_dir): vlines = Vlines([("chr9", 4000000), "chr9:5000000-6000000", ("chr1", 4000000)]) with vlines: frame = XAxis() + XAxis() fig = frame.plot(test_interval) - fig.savefig("/tmp/test_coolbox_vline.pdf") + fig.savefig(f"{tmp_dir}/test_coolbox_vline.pdf") -def test_highlights(): +def test_highlights(test_interval, tmp_dir): highlights = HighLights([ ("chr9", 4000000, 5000000), "chr9:5000000-6000000", ]) with highlights: frame = XAxis() + XAxis() - fig = frame.plot(test_interval) - fig.savefig("/tmp/test_coolbox_highlights.pdf") + fig = frame.plot(test_interval, close_fig=False) + fig.savefig(f"{tmp_dir}/test_coolbox_highlights.pdf") -def test_bigwig_coverage(): +def test_bigwig_coverage(data_dir, test_itv, test_interval, tmp_dir): frame = XAxis() +\ - BigWig(f"{DATA_DIR}/bigwig_{test_itv}.bw", style="line:1") + \ - BigWigCoverage(f"{DATA_DIR}/bigwig_{test_itv}.bw", style="fill", color="red", alpha=0.3) +\ - BigWigCoverage(f"{DATA_DIR}/bigwig_{test_itv}.bw", style="fill", color="blue", alpha=0.3) + BigWig(f"{data_dir}/bigwig_{test_itv}.bw", style="line:1") + \ + BigWigCoverage(f"{data_dir}/bigwig_{test_itv}.bw", style="fill", color="red", alpha=0.3) +\ + BigWigCoverage(f"{data_dir}/bigwig_{test_itv}.bw", style="fill", color="blue", alpha=0.3) fig = frame.plot(test_interval) - fig.savefig("/tmp/test_coolbox_bwcov.pdf") + fig.savefig(f"{tmp_dir}/test_coolbox_bwcov.pdf") -def test_arcs_coverage(): +def test_arcs_coverage(data_dir, test_itv, test_interval, tmp_dir): frame = XAxis() + \ - BigWig(f"{DATA_DIR}/bigwig_{test_itv}.bw", style="fill", alpha=0.5) + \ - ArcsCoverage(f"{DATA_DIR}/bedpe_{test_itv}.bedpe") + BigWig(f"{data_dir}/bigwig_{test_itv}.bw", style="fill", alpha=0.5) + \ + ArcsCoverage(f"{data_dir}/bedpe_{test_itv}.bedpe") fig = frame.plot(test_interval) - fig.savefig("/tmp/test_coolbox_arcscov.pdf") + fig.savefig(f"{tmp_dir}/test_coolbox_arcscov.pdf") -def test_tad_coverage(): +def test_tad_coverage(data_dir, test_itv, test_interval, tmp_dir): frame = XAxis() + \ - Cool(f"{DATA_DIR}/cool_{test_itv}.mcool") + \ - TADCoverage(f"{DATA_DIR}/tad_{test_itv}.bed") + Cool(f"{data_dir}/cool_{test_itv}.mcool") + \ + TADCoverage(f"{data_dir}/tad_{test_itv}.bed") fig = frame.plot(test_interval) - fig.savefig("/tmp/test_coobox_tadcov.pdf") + fig.savefig(f"{tmp_dir}/test_coobox_tadcov.pdf") + + +if __name__ == '__main__': + test_highlights(GenomeRange("chr9:3000000-7000000"), "/tmp") + #test_vlines(GenomeRange("chr9:4000000-6000000"), "/tmp") diff --git a/tests/test_track.py b/tests/test_track.py index 4a255d2..46ab96c 100644 --- a/tests/test_track.py +++ b/tests/test_track.py @@ -6,22 +6,14 @@ from coolbox.utilities import GenomeRange import matplotlib.pyplot as plt -HERE = osp.dirname(osp.abspath(__file__)) -DATA_DIR = f"{HERE}/test_data" -test_interval = GenomeRange("chr9:4000000-6000000") -empty_interval = GenomeRange("chr10:4000000-6000000") -sub_interval1 = GenomeRange("chr9:4500000-5000000") -sub_interval2 = GenomeRange("chr9:5200000-5850000") -test_itv = str(test_interval).replace(':', '_').replace('-', '_') - def test_xaxis(): x_axis = XAxis() assert x_axis -def test_bigwig(): - bw = BigWig(f"{DATA_DIR}/bigwig_{test_itv}.bw") +def test_bigwig(data_dir, test_interval, test_itv, empty_interval): + bw = BigWig(f"{data_dir}/bigwig_{test_itv}.bw") intervals = bw.fetch_data(test_interval) assert isinstance(intervals, pd.DataFrame) fig, ax = plt.subplots() @@ -29,8 +21,8 @@ def test_bigwig(): bw.fetch_data(empty_interval) -def test_bed(): - path = f"{DATA_DIR}/bed_{test_itv}.bed" +def test_bed(data_dir, test_interval, test_itv, empty_interval): + path = f"{data_dir}/bed_{test_itv}.bed" bed = BED(path) df = bed.fetch_data(test_interval) count = 0 @@ -42,52 +34,52 @@ def test_bed(): fig, ax = plt.subplots() bed.plot(ax, test_interval) bed.fetch_data(empty_interval) - bed6 = BED(f"{DATA_DIR}/bed6_{test_itv}.bed") + bed6 = BED(f"{data_dir}/bed6_{test_itv}.bed") bed6.plot(ax, test_interval) assert bed6.properties['bed_type'] == 'bed6' - bed9 = BED(f"{DATA_DIR}/bed9_{test_itv}.bed") + bed9 = BED(f"{data_dir}/bed9_{test_itv}.bed") bed9.plot(ax, test_interval) assert bed9.properties['bed_type'] == 'bed9' -def test_bedpe(): - arcs = BEDPE(f"{DATA_DIR}/bedpe_{test_itv}.bedpe") +def test_bedpe(data_dir, test_interval, test_itv, empty_interval): + arcs = BEDPE(f"{data_dir}/bedpe_{test_itv}.bedpe") assert arcs.fetch_data(test_interval) is not None fig, ax = plt.subplots() arcs.plot(ax, test_interval) arcs.fetch_data(empty_interval) -def test_pairs(): - arcs = Pairs(f"{DATA_DIR}/pairs_{test_itv}.pairs") +def test_pairs(data_dir, test_interval, test_itv, empty_interval): + arcs = Pairs(f"{data_dir}/pairs_{test_itv}.pairs") assert arcs.fetch_data(test_interval) is not None fig, ax = plt.subplots() arcs.plot(ax, test_interval) arcs.fetch_data(empty_interval) -def test_arcs(): - arcs = Arcs(f"{DATA_DIR}/bedpe_{test_itv}.bedpe") +def test_arcs(data_dir, test_itv): + arcs = Arcs(f"{data_dir}/bedpe_{test_itv}.bedpe") assert isinstance(arcs, BEDPE) - arcs = Arcs(f"{DATA_DIR}/pairs_{test_itv}.pairs") + arcs = Arcs(f"{data_dir}/pairs_{test_itv}.pairs") assert isinstance(arcs, Pairs) -def test_gtf(): - gtf = GTF(f"{DATA_DIR}/gtf_{test_itv}.gtf") +def test_gtf(data_dir, test_interval, test_itv, empty_interval): + gtf = GTF(f"{data_dir}/gtf_{test_itv}.gtf") assert gtf.fetch_data(test_interval) is not None fig, ax = plt.subplots() gtf.plot(ax, test_interval) gtf.fetch_data(empty_interval) - gtf = GTF(f"{DATA_DIR}/gtf_{test_itv}_fake.gtf") + gtf = GTF(f"{data_dir}/gtf_{test_itv}_fake.gtf") assert gtf.fetch_data(test_interval) is not None fig, ax = plt.subplots() gtf.plot(ax, test_interval) gtf.fetch_data(empty_interval) -def test_bam(): - bam_path = f"{DATA_DIR}/bam_{test_itv}.bam" +def test_bam(data_dir, test_interval, test_itv, empty_interval): + bam_path = f"{data_dir}/bam_{test_itv}.bam" bai_path = bam_path + ".bai" if osp.exists(bai_path): os.remove(bai_path) @@ -104,8 +96,8 @@ def test_bam(): bam.fetch_data(empty_interval) -def test_bedgraph(): - bg_path = f"{DATA_DIR}/bedgraph_{test_itv}.bg" +def test_bedgraph(data_dir, test_interval, test_itv, empty_interval): + bg_path = f"{data_dir}/bedgraph_{test_itv}.bg" bg = BedGraph(bg_path) assert bg.fetch_data(test_interval) is not None bg.fetch_data(empty_interval) @@ -114,20 +106,20 @@ def test_bedgraph(): fig.savefig("/tmp/test_coolbox_bg.pdf") -def test_tads(): - cool = Cool(f"{DATA_DIR}/cool_{test_itv}.mcool") - tad = cool + TADCoverage(f"{DATA_DIR}/tad_{test_itv}.bed") +def test_tads(data_dir, test_interval, test_itv, empty_interval): + cool = Cool(f"{data_dir}/cool_{test_itv}.mcool") + tad = cool + TADCoverage(f"{data_dir}/tad_{test_itv}.bed") assert tad.fetch_data(test_interval) is not None fig, ax = plt.subplots() tad.plot(ax, test_interval) tad.fetch_data(empty_interval) - tad = TAD(f"{DATA_DIR}/tad_{test_itv}.bed") + tad = TAD(f"{data_dir}/tad_{test_itv}.bed") tad.plot(ax, test_interval) -def test_hicdiff(): - cl1 = Cool(f"{DATA_DIR}/cool_{test_itv}.mcool") - cl2 = Cool(f"{DATA_DIR}/cool_{test_itv}.mcool") +def test_hicdiff(data_dir, test_interval, test_itv, empty_interval): + cl1 = Cool(f"{data_dir}/cool_{test_itv}.mcool") + cl2 = Cool(f"{data_dir}/cool_{test_itv}.mcool") diff = HiCDiff(cl1, cl2) assert diff.fetch_data(test_interval) is not None fig, ax = plt.subplots() @@ -135,9 +127,9 @@ def test_hicdiff(): diff.fetch_data(empty_interval) -def test_selfish(): - cl1 = Cool(f"{DATA_DIR}/cool_{test_itv}.mcool") - cl2 = Cool(f"{DATA_DIR}/cool_{test_itv}.mcool") +def test_selfish(data_dir, test_interval, test_itv, empty_interval): + cl1 = Cool(f"{data_dir}/cool_{test_itv}.mcool") + cl2 = Cool(f"{data_dir}/cool_{test_itv}.mcool") sel = Selfish(cl1, cl2) assert sel.fetch_data(test_interval) is not None fig, ax = plt.subplots() @@ -145,8 +137,8 @@ def test_selfish(): sel.fetch_data(empty_interval) -def test_cool(): - cl = Cool(f"{DATA_DIR}/cool_{test_itv}.mcool") +def test_cool(data_dir, test_interval, test_itv, empty_interval, sub_interval1, sub_interval2): + cl = Cool(f"{data_dir}/cool_{test_itv}.mcool") exp_binsize = cl.infer_binsize(test_interval) assert cl.fetch_data(test_interval) is not None assert cl.fetch_data(test_interval, gr2=test_interval) is not None @@ -155,7 +147,7 @@ def test_cool(): cl.plot(ax, test_interval) cl.fetch_data(empty_interval) exp_binsize = 10000 - cl2 = Cool(f"{DATA_DIR}/cool_{test_itv}.mcool", resolution=exp_binsize) + cl2 = Cool(f"{data_dir}/cool_{test_itv}.mcool", resolution=exp_binsize) cl2.fetch_data(test_interval) assert cl2.fetched_binsize == exp_binsize mat1 = cl.fetch_data(sub_interval1, gr2=sub_interval2) @@ -168,8 +160,8 @@ def test_cool(): cl.plot(ax, sub_interval1, gr2=sub_interval2) -def test_dothic(): - dothic_path = f"{DATA_DIR}/dothic_{test_itv}.hic" +def test_dothic(data_dir, test_interval, test_itv, empty_interval, sub_interval1, sub_interval2): + dothic_path = f"{data_dir}/dothic_{test_itv}.hic" dot = DotHiC(dothic_path) exp_binsize = dot.infer_binsize(test_interval) assert dot.fetch_data(test_interval) is not None @@ -192,8 +184,8 @@ def test_dothic(): dot.plot(ax, sub_interval1, gr2=sub_interval2) -def test_hicfeatures(): - cool_path = f"{DATA_DIR}/cool_{test_itv}.mcool" +def test_hicfeatures(data_dir, test_interval, test_itv, empty_interval): + cool_path = f"{data_dir}/cool_{test_itv}.mcool" cl = Cool(cool_path) # test fot di_score and insu_score @@ -229,9 +221,18 @@ def test_hicfeatures(): assert v4c.fetch_data(test_interval) is not None +def test_ideogram(data_dir, test_interval): + idiogram = Ideogram(f"{data_dir}/hg19_ideogram.txt") + assert idiogram.fetch_data(test_interval) is not None + _, ax = plt.subplots() + idiogram.plot(ax, test_interval) + idiogram.fetch_data(test_interval) + + if __name__ == "__main__": + test_ideogram("./tests/test_data", GenomeRange("chr9:4000000-6000000")) # test_cool() - test_dothic() + #test_dothic() # test_xaxis() # test_gtf() # test_bam()