def test_simple_band_pattern(tmpdir): png_path = os.path.join(str(tmpdir), "test.png") patterns = [ BandsPattern([100, 500, 3500], ladder, label="C1"), BandsPattern([300, 400, 1500], ladder, label="C2"), BandsPattern([100, 1200, 1400, 3000], ladder, label="C3"), BandsPattern([100, 700], ladder, label="C4"), BandsPattern([200], ladder, label="C4", band_is_uncut=True), ] patterns_set = BandsPatternsSet(patterns=[ladder] + patterns, ladder=ladder, label="Digests", ladder_ticks=3) ax = patterns_set.plot() ax.figure.savefig(png_path, bbox_inches="tight", dpi=200) assert os.path.exists(png_path)
def test_mixed_digestions(tmpdir): png_path = os.path.join(str(tmpdir), "test.png") enzymes = "EcoRI", "EcoRV", "BamHI", "XhoI" mixes = [[e] for e in enzymes] + list(itertools.combinations(enzymes, 2)) patterns = [ BandsPattern( compute_digestion_bands(example_sequence, mix, linear=True), ladder=LADDER_100_to_4k, label=" + ".join(mix), label_fontdict={ "rotation": 40, "size": 9 }, ) for mix in mixes ] patterns_set = BandsPatternsSet( patterns=[LADDER_100_to_4k] + patterns, ladder=LADDER_100_to_4k, label="Digestion results", ladder_ticks=3, ) ax = patterns_set.plot() ax.figure.savefig(png_path, bbox_inches="tight", dpi=200) assert os.path.exists(png_path)
def draw_gel(self, digest_metadata, xlabel, output_dir): strain_name = digest_metadata['ID'] cpn60UT_ladder = custom_ladder( "cpn60UT", { 25: 250, 50: 225, 100: 205, 200: 186, 300: 171, 400: 158, 500: 149, 600: 139 }) LADDER_100_to_1k = custom_ladder( "cpn60UT", { 25: 249, 50: 226, 100: 205, 200: 186, 300: 171, 400: 158, 500: 149, 650: 139, 850: 128, 1000: 121 }) # ladder = cpn60UT_ladder.modified(background_color="#E2EDFF", label_fontdict={"rotation": -90}, label="MW") ladder = LADDER_100_to_1k.modified(background_color="#E2EDFF", label_fontdict={"rotation": -90}, label="MW") patterns = [] for renzyme in sorted(self.renzymes): patterns.append( BandsPattern(digest_metadata[str((renzyme, 'Band Sizes'))], ladder, label_fontdict={"rotation": -90}, label=renzyme)) # patterns_set = BandsPatternsSet(patterns=[ladder] + patterns, ladder=ladder, label_fontdict={"size": 7}, label="Migration Distance", ladder_ticks=3) patterns_set = BandsPatternsSet(patterns=[ladder] + patterns, ladder=ladder, ladder_ticks=3) ax = patterns_set.plot() ax.set_xlabel(xlabel) strain_filename = strain_name.replace("/", "-").replace("(", "_").replace( ")", "_") outfile = os.path.join(output_dir, strain_filename + ".png") if not os.path.exists(outfile): ax.figure.savefig(outfile, bbox_inches="tight", dpi=600) return outfile
def to_bandwagon_bandpattern(self, background_color=None, label="auto"): """Return a pattern version for the plotting library Bandwagon. If label is left to 'auto', it will be the pattern's name. """ if label == "auto": label = self.name return BandsPattern( self.bands, corner_note="Total: %d bp." % sum(self.bands), ladder=self.ladder, label=label, gel_image=self.migration_image, background_color=background_color, )
def test_simple_digestions_matplotlib_plot(tmpdir): png_path = os.path.join(str(tmpdir), "test.png") patterns = [ BandsPattern( compute_digestion_bands(example_sequence, [enzyme]), ladder=LADDER_100_to_4k, label=enzyme, global_bands_props={"label": "=size"}, ) for enzyme in ["BamHI", "EcoRI", "EcoRV", "PstI", "SpeI", "XbaI"] ] patterns_set = BandsPatternsSet( patterns=[LADDER_100_to_4k] + patterns, ladder=LADDER_100_to_4k, label="Digestion results", ladder_ticks=3, ) ax = patterns_set.plot() ax.figure.savefig(png_path, bbox_inches="tight", dpi=200) assert os.path.exists(png_path)
def test_customized_band_pattern(tmpdir): band_image_path = os.path.join("tests", "data", "band_image.png") png_path = os.path.join(str(tmpdir), "test.png") gel_image = mpimg.imread(band_image_path) patterns = [ BandsPattern( [100, 1500, 2000, 1000, 3500], ladder, label="C1", corner_note="corner note", corner_note_fontdict=None, background_color="#eeeeff", gel_image=gel_image, ) ] patterns_set = BandsPatternsSet(patterns=[ladder] + patterns, ladder=ladder, label="Digests", ladder_ticks=3) ax = patterns_set.plot() ax.figure.savefig(png_path, bbox_inches="tight", dpi=200) assert os.path.exists(png_path)
def test_simple_digestions_bokeh_plot(tmpdir): patterns = [ BandsPattern( compute_digestion_bands(example_sequence, [enzyme]), ladder=LADDER_100_to_4k, label=enzyme, global_bands_props={"label": "=size"}, ) for enzyme in ["BamHI", "EcoRI", "EcoRV", "PstI", "SpeI", "XbaI"] ] patterns_set = BandsPatternsSet( patterns=[LADDER_100_to_4k] + patterns, ladder=LADDER_100_to_4k, label="Digestion results", ladder_ticks=3, ) plot = patterns_set.plot_with_bokeh() target_file = os.path.join(str(tmpdir), "plot_with_bokeh.html") with open(target_file, "w+") as f: f.write(file_html(plot, CDN, "Example Sequence")) with open(target_file, "r") as f: assert len(f.read()) > 9400
#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Created on Mon May 27 09:46:13 2019 @author: bjorn """ from bandwagon import BandsPattern, BandsPatternsSet, LADDER_100_to_4k ladder = LADDER_100_to_4k.modified(label="Ladder", background_color="#ffffaf") patterns = [ BandsPattern([100, 500, 3500], ladder, label="C1"), BandsPattern([300, 400, 1500], ladder, label="C2"), BandsPattern([100, 1200, 1400, 3000], ladder, label="C3"), BandsPattern([100, 700], ladder, label="C4"), ] patterns_set = BandsPatternsSet(patterns=[ladder] + patterns, ladder=ladder, label="Test pattern", ladder_ticks=3) ax = patterns_set.plot() #ax.figure.savefig("simple_band_patterns.png", bbox_inches="tight", dpi=200)
"""Simple gel simulation with gelsimulation.py. This example shows how to plot the the digestion patterns produced by different restriction enzymes on a same DNA sequence. """ import itertools from bandwagon import (BandsPattern, BandsPatternsSet, LADDER_100_to_4k, compute_digestion_bands) with open("example_sequence.txt", "r") as f: sequence = f.read() enzymes = "EcoRI", "EcoRV", "BamHI", "XhoI" mixes = [[e] for e in enzymes] + list(itertools.combinations(enzymes, 2)) patterns = [ BandsPattern(compute_digestion_bands(sequence, mix, linear=True), ladder=LADDER_100_to_4k, label=" + ".join(mix), label_fontdict={"rotation": 40, "size": 9}) for mix in mixes ] patterns_set = BandsPatternsSet(patterns=[LADDER_100_to_4k] + patterns, ladder=LADDER_100_to_4k, label="Digestion results", ladder_ticks=3) ax = patterns_set.plot() ax.figure.savefig("mixed_digestions.png", bbox_inches="tight", dpi=120)
"""Simple gel simulation with gelsimulation.py. This example shows how to plot the digestion patterns produced by different restriction enzymes on a same DNA sequence. """ from bandwagon import (BandsPattern, BandsPatternsSet, LADDER_100_to_4k, compute_digestion_bands) with open("example_sequence.txt", "r") as f: sequence = f.read() patterns = [ BandsPattern(compute_digestion_bands(sequence, [enzyme], linear=True), ladder=LADDER_100_to_4k, label=enzyme) for enzyme in ["BamHI", "EcoRI", "EcoRV", "PstI", "SpeI", "XbaI"] ] patterns_set = BandsPatternsSet(patterns=[LADDER_100_to_4k] + patterns, ladder=LADDER_100_to_4k, label="Digestion results", ladder_ticks=3) ax = patterns_set.plot() ax.figure.savefig("simple_digestions.png", bbox_inches="tight", dpi=120)
def write_identification_report( self, target_file=None, relative_tolerance=0.05, min_band_cutoff=None, max_band_cutoff=None, ): """Plot a Graphic report of the gel validation. The report displays the patterns, with green and red backgrounds depending on whether they passed the validation test. Parameters ---------- target_file File object or file path where to save the figure. If provided, the function returns none, else the function returns the axes array of the final figure relative_tolerance Relative error tolerated on each band for the ovserved patterns to be considered similar to the expected patterns. min_band_cutoff Bands with a size below this value will not be considered max_band_cutoff Bands with a size above this value will not be considered """ bands_validities = self.compute_all_bands_validities( relative_tolerance=relative_tolerance, min_band_cutoff=min_band_cutoff, max_band_cutoff=max_band_cutoff, ) L = len(self.constructs_records) max_x = ( max(len(measures) for measures in self.observed_bands.values()) + 1) fig, axes = plt.subplots(L, 1, figsize=(2.2 * max_x, 3 * L)) axes_validities = zip(axes, bands_validities.items()) for ax, (construct_id, validities) in axes_validities: reference = BandsPattern( self.expected_bands[construct_id], ladder=self.ladder, label="exp.", background_color="#c6dcff", corner_note="Total: %d bp" % sum(self.expected_bands[construct_id]), global_bands_props={"label_fontdict": { "size": 5 }}, ) sorted_bands = sorted(reference.bands, key=lambda b: -b.dna_size) for band_name, band in zip("abcdefghijklm", sorted_bands): band.label = band_name patterns = [ BandsPattern( self.observed_bands[construct_id][measure_name], corner_note="Total: %d bp" % sum(self.observed_bands[construct_id][measure_name]), ladder=self.ladder, label=measure_name, gel_image=self.migration_images[measure_name], background_color="#aaffaa" if validities[measure_name] else "#ffaaaa", ) for measure_name in self.observed_bands[construct_id] ] patterns_set = BandsPatternsSet( [reference] + patterns, ladder=self.ladder, label=construct_id, ladder_ticks=5, global_patterns_props={"label_fontdict": { "rotation": 60 }}, ) ax.set_xlim(0.5, max_x + 2) patterns_set.plot(ax) fig.subplots_adjust(hspace=0.3) if target_file is not None: fig.savefig(target_file, bbox_inches="tight") plt.close(fig) else: return axes
def plot_all_validations_patterns(self, validations, target=None, per_digestion_discrepancy=False): """Plot a Graphic report of the gel validation. The report displays the patterns, with green and red backgrounds depending on whether they passed the validation test. Parameters ---------- target_file File object or file path where to save the figure. If provided, the function returns none, else the function returns the axes array of the final figure relative_tolerance Relative error tolerated on each band for the ovserved patterns to be considered similar to the expected patterns. min_band_cutoff Bands with a size below this value will not be considered max_band_cutoff Bands with a size above this value will not be considered """ summary = self.validations_summary(validations) max_x = ( Counter([clone.construct_id for clone in self.clones.values()]).most_common(1)[0][1] + 2) digestions_by_construct = {construct: [] for construct in summary} for construct, validations in summary.items(): for validation in validations: for digestion in validation.discrepancies: if digestion not in digestions_by_construct[construct]: digestions_by_construct[construct].append(digestion) # ladder = list(validations[0].clone.digestions.values())[0].ladder pdf_io = BytesIO() with PdfPages(pdf_io) as pdf: for construct_id, validations in summary.items(): ladder = list( validations[0].clone.digestions.values())[0].ladder digestions = digestions_by_construct[construct_id] band_patterns = OrderedDict() seen_clones = set() for i, digestion in enumerate(digestions): reference_bands = self.get_digestion_bands_for_construct( construct_id, digestion) reference = BandsPattern( bands=reference_bands, ladder=ladder, label="exp." if (i == 0) else None, background_color="#c6dcff", corner_note="Total: %d bp" % sum(reference_bands), global_bands_props={"label_fontdict": { "size": 5 }}, ) sorted_bands = sorted(reference.bands, key=lambda b: -b.dna_size) for band_name, band in zip("abcdefghijklm", sorted_bands): band.label = band_name patterns = [] for validation in validations: clone_name = validation.clone.name label = None if clone_name in seen_clones else "auto" pattern = validation.to_bandwagon_bandpattern( digestion=digestion, label=label, per_digestion_discrepancy=per_digestion_discrepancy, ) if pattern is not None: seen_clones.add(clone_name) patterns.append(pattern) band_patterns[digestion] = BandsPatternsSet( [reference] + patterns, ladder=ladder, label=" + ".join(digestion), ladder_ticks=5, global_patterns_props={ "label_fontdict": { "rotation": 60 } }, ) digestions = digestions_by_construct[construct_id] fig, axes = plt.subplots( len(digestions), 1, sharex=True, figsize=(1.1 * max_x, 3 * len(digestions)), ) if len(digestions) == 1: axes = [axes] axes[-1].set_xlim(right=max_x) for ax, (dig, pattern_set) in zip(axes, band_patterns.items()): pattern_set.plot(ax) axes[-1].set_xlabel( construct_id, fontdict=dict(size=14, weight="bold"), ha="left", position=(0.0, 0.1), ) pdf.attach_note(construct_id) # Temporary fix because of Matplotlib bug #12634 pdf.savefig(fig, bbox_inches="tight") plt.close(fig) pdf_data = pdf_io.getvalue() if target is None: return pdf_data elif target == "base64": return "data:application/pdf;base64," + pdf_data.decode("utf-8") else: with open(target, "wb") as f: f.write(pdf_data)