diff --git a/nanoplot/NanoPlot.py b/nanoplot/NanoPlot.py index 36db0a1..a64d83e 100755 --- a/nanoplot/NanoPlot.py +++ b/nanoplot/NanoPlot.py @@ -18,6 +18,7 @@ import nanoplot.utils as utils from nanoplot.version import __version__ from nanoplotter.plot import Plot +from plotly.offline import get_plotlyjs def main(): @@ -401,9 +402,12 @@ def make_report(plots, settings): report.run_info(settings) if settings["info_in_report"] else "", "", ] + if settings["include_js"] is False: + # embed plotly.js once, at the start of the body, rather than in every plot + html_content.insert(1, f'') with open(settings["path"] + "NanoPlot-report.html", "w") as html_file: html_file.write(report.html_head + "\n".join(html_content)) if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/nanoplot/utils.py b/nanoplot/utils.py index 2eb5a1c..b70a6f6 100644 --- a/nanoplot/utils.py +++ b/nanoplot/utils.py @@ -110,6 +110,12 @@ def get_args(): general.add_argument( "--info_in_report", help="Add NanoPlot run info in the report.", action="store_true" ) + general.add_argument( + "--include-js", + choices=["cdn", "embedded"], + help="Either cdn or embedded. If cdn (the default) is specified, the javascript for plotly images will be sourced from the web. If embedded is specified, then the javascript will be directly put into the html file, resulting in a larger but self-contained HTML file.", + default="cdn", + ) filtering = parser.add_argument_group( title="Options for filtering or transforming input prior to plotting" ) @@ -298,6 +304,8 @@ def get_args(): sys.exit("ARGUMENT ERROR: --barcoded only works with data provided as --summary!") settings = vars(args) settings["path"] = os.path.join(args.outdir, args.prefix) + if settings["include_js"] == "embedded": + settings["include_js"] = False return settings, args diff --git a/nanoplotter/nanoplotter_main.py b/nanoplotter/nanoplotter_main.py index a336a34..1fe517f 100644 --- a/nanoplotter/nanoplotter_main.py +++ b/nanoplotter/nanoplotter_main.py @@ -146,7 +146,7 @@ def scatter( ) dot_plot.fig = fig - dot_plot.html = dot_plot.fig.to_html(full_html=False, include_plotlyjs="cdn") + dot_plot.html = dot_plot.fig.to_html(full_html=False, include_plotlyjs=settings["include_js"]) dot_plot.save(settings) plots_made.append(dot_plot) @@ -177,7 +177,7 @@ def scatter( ) kde_plot.fig = fig - kde_plot.html = kde_plot.fig.to_html(full_html=False, include_plotlyjs="cdn") + kde_plot.html = kde_plot.fig.to_html(full_html=False, include_plotlyjs=settings["include_js"]) kde_plot.save(settings) plots_made.append(kde_plot) @@ -433,7 +433,7 @@ def length_plots(array, name, path, settings, title=None, n50=None, color="#4CB3 ) histogram.fig = fig - histogram.html = histogram.fig.to_html(full_html=False, include_plotlyjs="cdn") + histogram.html = histogram.fig.to_html(full_html=False, include_plotlyjs=settings["include_js"]) histogram.save(settings) log_histogram = Plot( @@ -484,7 +484,7 @@ def length_plots(array, name, path, settings, title=None, n50=None, color="#4CB3 fig.update_annotations(font_size=8) log_histogram.fig = fig - log_histogram.html = log_histogram.fig.to_html(full_html=False, include_plotlyjs="cdn") + log_histogram.html = log_histogram.fig.to_html(full_html=False, include_plotlyjs=settings["include_js"]) log_histogram.save(settings) plots.extend([histogram, log_histogram]) @@ -560,7 +560,7 @@ def yield_by_minimal_length_plot(array, name, path, settings, title=None, color= ) yield_by_length.fig = fig - yield_by_length.html = yield_by_length.fig.to_html(full_html=False, include_plotlyjs="cdn") + yield_by_length.html = yield_by_length.fig.to_html(full_html=False, include_plotlyjs=settings["include_js"]) yield_by_length.save(settings) return yield_by_length diff --git a/nanoplotter/plot.py b/nanoplotter/plot.py index db593f2..6b6a5cf 100644 --- a/nanoplotter/plot.py +++ b/nanoplotter/plot.py @@ -51,9 +51,15 @@ def save(self, settings): return if self.html: - # Save the interactive HTML + # Save the interactive HTML. With embedded javascript self.html contains no + # javascript at all (it is added once to the combined report), so write a + # self-contained copy here to keep individual plot files usable on their own. + if settings.get("include_js", "cdn") is False and self.fig is not None: + standalone = self.fig.to_html(full_html=False, include_plotlyjs=True) + else: + standalone = self.html with open(self.path, "w") as html_out: - html_out.write(self.html) + html_out.write(standalone) # Also save static images unless suppressed if not settings.get("no_static", False): diff --git a/nanoplotter/spatial_heatmap.py b/nanoplotter/spatial_heatmap.py index d7cd991..de1b0eb 100644 --- a/nanoplotter/spatial_heatmap.py +++ b/nanoplotter/spatial_heatmap.py @@ -91,6 +91,6 @@ def spatial_heatmap(array, path, colormap, settings, title=None): activity_map.fig = fig activity_map.html = activity_map.fig.to_html( - full_html=False, include_plotlyjs='cdn') + full_html=False, include_plotlyjs=settings["include_js"]) activity_map.save(settings) return [activity_map] diff --git a/nanoplotter/timeplots.py b/nanoplotter/timeplots.py index 50f754b..d16743e 100644 --- a/nanoplotter/timeplots.py +++ b/nanoplotter/timeplots.py @@ -136,7 +136,7 @@ def length_over_time(dfs, path, title, settings, log_length=False, color="#4CB39 time_length.fig = fig time_length.html = time_length.fig.to_html( - full_html=False, include_plotlyjs='cdn') + full_html=False, include_plotlyjs=settings["include_js"]) time_length.save(settings) return time_length @@ -163,7 +163,7 @@ def quality_over_time(dfs, path, settings, title=None, color="#4CB391", downsamp time_qual.fig = fig time_qual.html = time_qual.fig.to_html( - full_html=False, include_plotlyjs='cdn') + full_html=False, include_plotlyjs=settings["include_js"]) time_qual.save(settings) return time_qual @@ -193,7 +193,7 @@ def sequencing_speed_over_time(dfs, path, title, settings, color="#4CB391", down time_duration.fig = fig time_duration.html = time_duration.fig.to_html( - full_html=False, include_plotlyjs='cdn') + full_html=False, include_plotlyjs=settings["include_js"]) time_duration.save(settings) return time_duration @@ -226,7 +226,7 @@ def plot_over_time(dfs, path, title, settings, color="#4CB391"): num_reads.fig = fig num_reads.html = num_reads.fig.to_html( - full_html=False, include_plotlyjs='cdn') + full_html=False, include_plotlyjs=settings["include_js"]) num_reads.save(settings) plots = [num_reads] @@ -249,7 +249,7 @@ def plot_over_time(dfs, path, title, settings, color="#4CB391"): pores_over_time.fig = fig pores_over_time.html = pores_over_time.fig.to_html( - full_html=False, include_plotlyjs='cdn') + full_html=False, include_plotlyjs=settings["include_js"]) pores_over_time.save(settings) plots.append(pores_over_time) @@ -274,7 +274,7 @@ def cumulative_yield(dfs, path, title, color, settings): cum_yield_gb.fig = fig cum_yield_gb.html = cum_yield_gb.fig.to_html( - full_html=False, include_plotlyjs='cdn') + full_html=False, include_plotlyjs=settings["include_js"]) cum_yield_gb.save(settings) cum_yield_reads = Plot(path=path + "CumulativeYieldPlot_NumberOfReads.html", @@ -294,7 +294,7 @@ def cumulative_yield(dfs, path, title, color, settings): cum_yield_reads.fig = fig cum_yield_reads.html = cum_yield_reads.fig.to_html( - full_html=False, include_plotlyjs='cdn') + full_html=False, include_plotlyjs=settings["include_js"]) cum_yield_reads.save(settings) return [cum_yield_gb, cum_yield_reads]