Ejemplo n.º 1
0
def lazy_content_dependency_dict() -> ContentDependencyDict:
    bootstrap_inline = Path(options.bootstrap_css).read_text()
    bootstrap_inline = f"<style>\n{bootstrap_inline}\n</style>"

    content_dependency_dict = ContentDependencyDict()
    content_dependency_dict += ContentDependency(
        "bootstrap", options.bootstrap_cdn, bootstrap_inline, "head"
    )

    if "bokeh" in _INSTALLED_MODULES:
        import bokeh.resources as bk_resources  # type: ignore

        bokeh_cdn = bk_resources.CDN.render_js()
        bokeh_inline = bk_resources.INLINE.render_js()

        content_dependency_dict += ContentDependency(
            "bokeh", bokeh_cdn, bokeh_inline, "tail"
        )

    if "plotly" in _INSTALLED_MODULES:
        from plotly import offline as plotly_offline  # type: ignore

        plotly_version = "latest"
        plotly_cdn = f"<script src='https://cdn.plot.ly/plotly-{plotly_version}.min.js'></script>"
        plotly_inline = plotly_offline.get_plotlyjs()
        plotly_inline = f"<script>\n{plotly_inline}\n</script>"

        content_dependency_dict += ContentDependency(
            "plotly", plotly_cdn, plotly_inline, "head"
        )

    return content_dependency_dict
Ejemplo n.º 2
0
def to_html(divs, filename):
    """Convert DIVs, obtained from 'to_div', into one HTML file

    Parameters
    ----------
    divs : list of divs
        list of the output of 'to_div'
    filename : path
        path of the file to write (extension should be .html). It overwrites if
        it exists
    """
    filename.parent.mkdir(exist_ok=True, parents=True)
    lg.debug(f'Saving {len(divs)} plots to {filename}')

    html = '''
        <html>
         <head>
             <script type="text/javascript">{plotlyjs}</script>
         </head>
         <body>
            {div}
         </body>
     </html>
    '''.format(plotlyjs=get_plotlyjs(), div='\n'.join(divs))

    with filename.open('w') as f:
        f.write(html)
Ejemplo n.º 3
0
def lazy_content_dependency_dict() -> ContentDependencyDict:
    bootstrap_cdn = (
        '<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" '
        +
        'integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">'
    )
    bootstrap_inline = Path(_MODULE_PATH,
                            "resources/css/bootstrap.min.css").read_text()
    bootstrap_inline = f"<style>\n{bootstrap_inline}\n</style>"

    content_dependency_dict = ContentDependencyDict()
    content_dependency_dict += ContentDependency("bootstrap", bootstrap_cdn,
                                                 bootstrap_inline, "head")

    if "bokeh" in _INSTALLED_MODULES:
        import bokeh.resources as bk_resources  # type: ignore

        bokeh_cdn = bk_resources.CDN.render_js()
        bokeh_inline = bk_resources.INLINE.render_js()

        content_dependency_dict += ContentDependency("bokeh", bokeh_cdn,
                                                     bokeh_inline, "tail")

    if "plotly" in _INSTALLED_MODULES:
        from plotly import offline as plotly_offline  # type: ignore

        plotly_version = "latest"
        plotly_cdn = f"<script src='https://cdn.plot.ly/plotly-{plotly_version}.min.js'></script>"
        plotly_inline = plotly_offline.get_plotlyjs()
        plotly_inline = f"<script>\n{plotly_inline}\n</script>"

        content_dependency_dict += ContentDependency("plotly", plotly_cdn,
                                                     plotly_inline, "head")

    return content_dependency_dict
Ejemplo n.º 4
0
def write_summary_html(out_file, src_file, md5, summary_df, top_df,
                       catplot_fig, heatmap_fig, ridgeplot_fig):
    """Write summary HTML report"""
    # Get CpG_Interval template
    template = get_jinja_template("CpG_summary.html.j2")

    # Render pandas dataframes and plotly figures to HTML
    summary_html = render_df(summary_df)
    top_html = render_df(top_df, empty_msg="No significant candidates found")
    catplot_html = render_fig(
        catplot_fig,
        empty_msg="Not enough significant candidates to render catplot")
    heatmap_html = render_fig(
        heatmap_fig,
        empty_msg="Not enough significant candidates to render heatmap")
    ridgeplot_html = render_fig(
        ridgeplot_fig,
        empty_msg="Not enough significant candidates to render ridgeplot")

    # Render HTML report using Jinja
    rendering = template.render(
        plotlyjs=py.get_plotlyjs(),
        version=version,
        date=datetime.datetime.now().strftime("%d/%m/%y"),
        src_file=src_file,
        md5=md5,
        summary_html=summary_html,
        top_html=top_html,
        catplot_html=catplot_html,
        heatmap_html=heatmap_html,
        ridgeplot_html=ridgeplot_html)

    with open(out_file, "w") as fp:
        fp.write(rendering)
Ejemplo n.º 5
0
def write_cpg_interval_html(out_file, src_file, md5, summary_link,
                            previous_link, next_link, max_tss_distance,
                            interval_df, transcript_df, heatmap_fig,
                            ridgeplot_fig):
    """Write CpG interval HTML report"""
    # Get CpG_Interval template
    template = get_jinja_template("CpG_Interval.html.j2")

    # Render pandas dataframes and plotly figures to HTML
    interval_html = render_df(interval_df)
    transcript_html = render_df(
        transcript_df,
        empty_msg=
        f"No transcripts TTS found within {max_tss_distance} bp upstream or downstream"
    )
    heatmap_html = render_fig(heatmap_fig)
    ridgeplot_html = render_fig(ridgeplot_fig)

    # Render HTML report using Jinja
    rendering = template.render(
        plotlyjs=py.get_plotlyjs(),
        version=version,
        date=datetime.datetime.now().strftime("%d/%m/%y"),
        src_file=src_file,
        md5=md5,
        summary_link=summary_link,
        previous_link=previous_link,
        next_link=next_link,
        interval_html=interval_html,
        transcript_html=transcript_html,
        heatmap_html=heatmap_html,
        ridgeplot_html=ridgeplot_html)

    with open(out_file, "w") as fp:
        fp.write(rendering)
Ejemplo n.º 6
0
 def load_nb(cls, inline=True):
     """
     Loads the plotly notebook resources.
     """
     from IPython.display import publish_display_data
     cls._loaded = True
     init_notebook_mode(connected=not inline)
     publish_display_data(data={MIME_TYPES['jlab-hv-load']: get_plotlyjs()})
Ejemplo n.º 7
0
 def load_nb(cls, inline=True):
     """
     Loads the plotly notebook resources.
     """
     from IPython.display import publish_display_data
     cls._loaded = True
     init_notebook_mode(connected=not inline)
     publish_display_data(data={MIME_TYPES['jlab-hv-load']:
                                get_plotlyjs()})
Ejemplo n.º 8
0
    def html_report(self,
                    outfile: str,
                    config_file: str = "",
                    template_file: str = "",
                    report_title: str = "PycoQC report",
                    skip_coverage_plot: bool = False):
        """"""
        self.logger.info("Generating HTML report")

        # Parse configuration file
        self.logger.info("\tParsing html config file")
        config_dict = self._get_config(config_file)
        self.logger.debug(config_dict)

        # Loop over configuration file and run the pycoQC functions defined
        plots = list()
        titles = list()
        for method_name, method_args in config_dict.items():
            if skip_coverage_plot and method_name == "alignment_coverage":
                self.logger.info("\tSkipping method {}".format(method_name))
                continue
            try:
                self.logger.info("\tRunning method {}".format(method_name))
                self.logger.debug("\t{} ({})".format(method_name, method_args))

                # Store plot title for HTML title and remove from data passed to plotly
                plot_title = method_args["plot_title"]
                method_args["plot_title"] = ""

                # Get method and generate plot
                method = getattr(self.plotter, method_name)
                fig = method(**method_args)
                plot = py.plot(fig,
                               output_type='div',
                               include_plotlyjs=False,
                               image_width='',
                               image_height='',
                               show_link=False,
                               auto_open=False)

                plots.append(plot)
                titles.append(plot_title)

            except AttributeError as E:
                self.logger.info(
                    "\t\t{} is not a valid plotting method".format(
                        method_name))
                self.logger.info("\t\t{}".format(E))

            except pycoQCError as E:
                self.logger.info("\t\t{}".format(E))

        # Load HTML template for Jinja
        self.logger.info("\tLoading HTML template")
        template = self._get_jinja_template(template_file)

        # Set a subtitle for the HTML report
        report_subtitle = "Generated on {} with {} {}".format(
            datetime.datetime.now().strftime("%d/%m/%y"), package_name,
            package_version)

        # Define source files list
        src_files = ""
        for files_list, name in ((self.parser.summary_files_list, "summary"),
                                 (self.parser.barcode_files_list, "barcode"),
                                 (self.parser.bam_file_list, "bam")):

            if files_list:
                src_files += "<h4>Source {} files</h4><ul>".format(name)
                for f in files_list:
                    f = os.path.abspath(f)
                    src_files += "<li>{}</li>".format(f)
                src_files += "</ul>"

        # Render plots
        self.logger.info("\tRendering plots in d3js")
        rendering = template.render(plots=plots,
                                    titles=titles,
                                    plotlyjs=py.get_plotlyjs(),
                                    report_title=report_title,
                                    report_subtitle=report_subtitle,
                                    src_files=src_files)

        # Write to HTML file
        self.logger.info("\tWriting to HTML file")
        mkbasedir(outfile, exist_ok=True)
        with open(outfile, "w") as fp:
            fp.write(rendering)
Ejemplo n.º 9
0
def assert_offline(html):
    assert get_plotlyjs() in html
Ejemplo n.º 10
0
class PlotlyRenderer(Renderer):

    backend = param.String(default='plotly', doc="The backend name.")

    fig = param.ObjectSelector(default='auto',
                               objects=['html', 'json', 'png', 'svg', 'auto'],
                               doc="""
        Output render format for static figures. If None, no figure
        rendering will occur. """)

    mode_formats = {
        'fig': {
            'default': ['html', 'png', 'svg', 'json']
        },
        'holomap': {
            'default': ['widgets', 'scrubber', 'auto']
        }
    }

    widgets = {
        'scrubber': PlotlyScrubberWidget,
        'widgets': PlotlySelectionWidget
    }

    backend_dependencies = {'js': (get_plotlyjs(), )}

    comm_msg_handler = plotly_msg_handler

    _loaded = False

    def __call__(self, obj, fmt='html', divuuid=None):
        plot, fmt = self._validate(obj, fmt)
        mime_types = {'file-ext': fmt, 'mime_type': MIME_TYPES[fmt]}

        if isinstance(plot, tuple(self.widgets.values())):
            return plot(), mime_types
        elif fmt in ('html', 'png', 'svg'):
            return self._figure_data(plot, fmt, divuuid=divuuid), mime_types
        elif fmt == 'json':
            return self.diff(plot), mime_types

    def diff(self, plot, serialize=True):
        """
        Returns a json diff required to update an existing plot with
        the latest plot data.
        """
        diff = plot.state
        if serialize:
            return json.dumps(diff, cls=utils.PlotlyJSONEncoder)
        else:
            return diff

    def _figure_data(self,
                     plot,
                     fmt=None,
                     divuuid=None,
                     comm=True,
                     as_script=False,
                     width=800,
                     height=600):
        # Wrapping plot.state in go.Figure here performs validation
        # and applies any default theme.
        figure = go.Figure(plot.state)

        if fmt in ('png', 'svg'):
            import plotly.io as pio
            data = pio.to_image(figure, fmt)
            if as_script:
                b64 = base64.b64encode(data).decode("utf-8")
                (mime_type, tag) = MIME_TYPES[fmt], HTML_TAGS[fmt]
                src = HTML_TAGS['base64'].format(mime_type=mime_type, b64=b64)
                div = tag.format(src=src, mime_type=mime_type, css='')
                js = ''
                return div, js
            return data

        if divuuid is None:
            divuuid = plot.id

        jdata = json.dumps(figure.data, cls=utils.PlotlyJSONEncoder)
        jlayout = json.dumps(figure.layout, cls=utils.PlotlyJSONEncoder)

        config = {}
        config['showLink'] = False
        jconfig = json.dumps(config)

        if as_script:
            header = 'window.PLOTLYENV=window.PLOTLYENV || {};'
        else:
            header = ('<script type="text/javascript">'
                      'window.PLOTLYENV=window.PLOTLYENV || {};'
                      '</script>')

        script = '\n'.join([
            'var plotly = window._Plotly || window.Plotly;'
            'plotly.plot("{id}", {data}, {layout}, {config}).then(function() {{',
            '    var elem = document.getElementById("{id}.loading"); elem.parentNode.removeChild(elem);',
            '}})'
        ]).format(id=divuuid, data=jdata, layout=jlayout, config=jconfig)

        html = ('<div id="{id}.loading" style="color: rgb(50,50,50);">'
                'Drawing...</div>'
                '<div id="{id}" style="height: {height}; width: {width};" '
                'class="plotly-graph-div">'
                '</div>'.format(id=divuuid, height=height, width=width))
        if as_script:
            return html, header + script

        content = ('{html}'
                   '<script type="text/javascript">'
                   '  {script}'
                   '</script>').format(html=html, script=script)
        return '\n'.join([header, content])

    @classmethod
    def plot_options(cls, obj, percent_size):
        factor = percent_size / 100.0
        obj = obj.last if isinstance(obj, HoloMap) else obj
        plot = Store.registry[cls.backend].get(type(obj), None)
        options = plot.lookup_options(obj, 'plot').options
        width = options.get('width', plot.width) * factor
        height = options.get('height', plot.height) * factor
        return dict(options, **{'width': int(width), 'height': int(height)})

    @classmethod
    def load_nb(cls, inline=True):
        """
        Loads the plotly notebook resources.
        """
        from IPython.display import publish_display_data
        cls._loaded = True
        init_notebook_mode(connected=not inline)
        publish_display_data(data={MIME_TYPES['jlab-hv-load']: get_plotlyjs()})
Ejemplo n.º 11
0
def orderedOnce():
    print("List of customers who ordered once and did not order again:")
    for i in range(0, len(new_list)):
        fname_list.append(new_list[i][2])
    for i in range(0, len(new_list)):
        lname_list.append(new_list[i][3])
    for i in range(0, len(fname_list)):
        #logic to combine first and last name.
        name.append(fname_list[i] + ' ' + lname_list[i])
        name[i] = name[i].replace(',', '')
    oneTimeOrder = 0
    twoTimeOrder = 0
    threeTimeOrder = 0
    fourTimeOrder = 0
    fiveTimeOrder = 0
    for i in range(0, len(name)):
        if name.count(name[i]) == 1:
            oneTimeOrder += 1
            print(name[i])

    for i in range(0, len(name)):
        if name.count(name[i]) == 2:
            twoTimeOrder += 1

    for i in range(0, len(name)):
        if name.count(name[i]) == 3:
            threeTimeOrder += 1

    for i in range(0, len(name)):
        if name.count(name[i]) == 4:
            fourTimeOrder += 1

    for i in range(0, len(name)):
        if name.count(name[i]) >= 5:
            fiveTimeOrder += 1


##Plotting the graph using Plotly
    data = [
        go.Bar(x=[1, 2, 3, 4, 5],
               y=[
                   oneTimeOrder, twoTimeOrder, threeTimeOrder, fourTimeOrder,
                   fiveTimeOrder
               ])
    ]
    layout = go.Layout(
        autosize=False,
        width=500,
        height=500,
        margin=dict(l=50, r=50, b=100, t=100, pad=4),
        xaxis=dict(title='Orders',
                   titlefont=dict(family='Courier New, monospace',
                                  size=18,
                                  color='#7f7f7f')),
        yaxis=dict(title='Count of customers',
                   titlefont=dict(family='Courier New, monospace',
                                  size=18,
                                  color='#7f7f7f')),
        title="<b>Distribution of Customers</b>",
        # paper_bgcolor='#7f7f7f',
        #plot_bgcolor='#c7c7c7'
    )
    fig = go.Figure(data=data, layout=layout)
    plot_url = plot(fig,
                    output_type='div',
                    include_plotlyjs=False,
                    show_link=False)
    html_start = """
    <html>
      <head>
         <style type="text/css">
             .plotly-graph-div { width: 50%; float: left; }
             .floatRight {width: 50%;position: absolute;top: 100px;left: 600px;}
             .container { overflow: hidden; }
         </style>
         <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
      </head>
    <body>"""
    html_end = """
       <div class="container">
             {plot_url}
           <div class="floatRight">
               <h3>Distribution of Customers</h3>
               <table border=1 cellspacing="1px">
                        <tr>
                            <th>Orders</th>
                            <th>Count of customers</th>
                        </tr>
                        <tr>
                            <td>1</td>
                            <td>{One}</td>
                        </tr>
                        <tr>
                            <td>2</td>
                            <td>{Two}</td>
                        </tr>
                        <tr>
                            <td>3</td>
                            <td>{Three}</td>
                        </tr>
                        <tr>
                            <td>4</td>
                            <td>{Four}</td>
                        </tr>
                        <tr>
                            <td>5+</td>
                            <td>{FivePlus}</td>
                        </tr>
        
                </table>
            </div>
       </div>
    </body>
    </html>""".format(plotlyjs=get_plotlyjs(),
                      plot_url=plot_url,
                      One=oneTimeOrder,
                      Two=twoTimeOrder,
                      Three=threeTimeOrder,
                      Four=fourTimeOrder,
                      FivePlus=fiveTimeOrder)
    fileData = html_start + html_end
    writeFile = open("report.html", "w")
    writeFile.write(fileData)
    writeFile.close()
Ejemplo n.º 12
0
def generate_report(summary_file,
                    barcode_file,
                    outfile,
                    qual=7,
                    filter_calibration=False,
                    config=None,
                    template_file=None,
                    verbose_level=1,
                    title=None):
    """ Runs pycoQC and generates the HTML report"""

    # Parse configuration file
    logger.warning("PARSE CONFIGURATION FILE")
    config_dict = parse_config_file(config)
    logger.debug(config_dict)

    # Initiate pycoQC
    logger.warning("PARSE DATA FILES")
    p = pycoQC(seq_summary_file=summary_file,
               barcode_summary_file=barcode_file,
               verbose_level=verbose_level,
               min_pass_qual=qual,
               filter_calibration=filter_calibration)

    # Loop over configuration file and run the pycoQC functions defined
    logger.warning("GENERATES PLOTS")
    plots = list()
    titles = list()
    for method_name, method_args in config_dict.items():

        # Check if method exists and is callable
        if not method_name in plot_methods:
            logger.info(
                "\tWarning: Method {} is defined in configuration but not supported"
                .format(method_name))

        try:
            logger.info("\tRunning method {}".format(method_name))
            logger.debug("\t{} ({})".format(method_name, method_args))

            # Store plot title for HTML tittle and remove from data passed to plotly
            plot_title = method_args["plot_title"]
            method_args["plot_title"] = ""

            # Get method and generate plot
            method = getattr(p, method_name)
            fig = method(**method_args)
            plot = py.plot(fig,
                           output_type='div',
                           include_plotlyjs=False,
                           image_width='',
                           image_height='',
                           show_link=False,
                           auto_open=False)

            plots.append(plot)
            titles.append(plot_title)

        except pycoQCError as E:
            logger.info("\t\t{}".format(E))

    logger.warning("WRITE HTML REPORT")

    # Load HTML template for Jinja
    logger.info("\tLoad HTML template")
    template = get_jinja_template(template_file)

    # Set a title for the HTML report
    report_title = ""
    if title:
        report_title += title + "<br>"
    report_title += "generated on " + datetime.datetime.now().strftime(
        "%d/%m/%y")

    # # Calculate SHA checksum and pass it to template
    # with open(summary_file, 'rb') as f:
    #     contents = f.read()
    # summary_file_hash = hashlib.sha256(contents).hexdigest()

    # Render plots
    logger.info("\tRender plots with Jinja2")
    rendering = template.render(plots=plots,
                                titles=titles,
                                plotlyjs=py.get_plotlyjs(),
                                report_title=report_title)

    # Write to HTML file
    logger.info("\tWrite to HTML file")
    with open(outfile, "w") as f:
        f.write(rendering)
Ejemplo n.º 13
0
    def html_report(self,
                    outfile: str,
                    config_file: str = "",
                    template_file: str = "",
                    report_title: str = ""):
        """"""
        # Parse configuration file
        self.logger.info("\tParsing html config file")
        config_dict = self._get_config(config_file)
        self.logger.debug(config_dict)

        # Loop over configuration file and run the pycoQC functions defined
        plots = list()
        titles = list()
        for method_name, method_args in config_dict.items():

            # Check if method exists and is callable
            if not method_name in self.PLOT_METHODS:
                self.logger.info(
                    "\tMethod `{}` is not defined in pycoQC".format(
                        method_name))

            try:
                self.logger.info("\tRunning method {}".format(method_name))
                self.logger.debug("\t{} ({})".format(method_name, method_args))

                # Store plot title for HTML title and remove from data passed to plotly
                plot_title = method_args["plot_title"]
                method_args["plot_title"] = ""

                # Get method and generate plot
                method = getattr(self.pp, method_name)
                fig = method(**method_args)
                plot = py.plot(fig,
                               output_type='div',
                               include_plotlyjs=False,
                               image_width='',
                               image_height='',
                               show_link=False,
                               auto_open=False)

                plots.append(plot)
                titles.append(plot_title)

            except pycoQCError as E:
                self.logger.info("\t\t{}".format(E))

        # Load HTML template for Jinja
        self.logger.info("\tLoading HTML template")
        template = self._get_jinja_template(template_file)

        # Set a title for the HTML report
        if report_title:
            report_title += "<br>"

        report_title += "Generated on {} with {} {}".format(
            datetime.datetime.now().strftime("%d/%m/%y"), package_name,
            package_version)

        # Render plots
        self.logger.info("\tRendering plots in d3js")
        rendering = template.render(plots=plots,
                                    titles=titles,
                                    plotlyjs=py.get_plotlyjs(),
                                    report_title=report_title)

        # Write to HTML file
        self.logger.info("\tWriting to HTML file")
        with open(outfile, "w") as fp:
            fp.write(rendering)
Ejemplo n.º 14
0
def assert_offline(html):
    assert get_plotlyjs() in html
Ejemplo n.º 15
0
 def write_summary_html(
     self,
     summary_df,
     top_interval_summary_df,
     catplot_fig,
     heatmap_fig,
     ridgeplot_fig,
     ideogram_fig,
     tss_dist_fig,
     sample=None,
 ):
     """Write summary HTML report"""
     out_file = os.path.join(self.get_outputdir(sample=sample, relative_to="wd"), self.summary_report_fn)
     
     # Get CpG_Interval template
     template = get_jinja_template("CpG_summary.html.j2")
     
     # Render pandas dataframes and plotly figures to HTML
     summary_html = render_df(summary_df)
     top_html = render_df(top_interval_summary_df, empty_msg="No significant candidates found")
     catplot_html = render_fig(catplot_fig, empty_msg="Not enough significant candidates to render catplot")
     heatmap_html = render_fig(heatmap_fig, empty_msg="Not enough significant candidates to render heatmap")
     ridgeplot_html = render_fig(ridgeplot_fig, empty_msg="Not enough significant candidates to render ridgeplot")
     ideogram_html = render_fig(ideogram_fig, empty_msg="Not enough significant candidates to render ideogram")
     tss_dist_html = render_fig(
         tss_dist_fig, empty_msg="Not enough significant candidates to render tss distance plot"
     )
     
     if self.report_posthoc:
         relative_to = "summary" if sample is None else "posthoc"
         link_dir = self.get_outputdir(sample=None, relative_to=relative_to)
         navigation = f"<div><a href='{link_dir}/{self.summary_report_fn}' class=\"navbar-brand mr-2\">Main Summary</a></div><div>&nbsp;</div><div>Post-Hoc test:</div>"
         for other_sample in self.sample_id_list:
             link_dir = self.get_outputdir(sample=other_sample, relative_to=relative_to)
             navigation += f"<div><a href='{link_dir}/{self.summary_report_fn}'>{other_sample}</a></div>"
     else:
         navigation = ""
     
     if sample is None:
         title = "MethComp summary report"
     else:
         title = f"MethComp post-hoc signficant intervals {sample}"
     
     # Render HTML report using Jinja
     rendering = template.render(
         plotlyjs=py.get_plotlyjs(),
         version=version,
         title_text=title,
         date=datetime.datetime.now().strftime("%d/%m/%y"),
         src_file=self.src_file,
         md5=self.md5,
         summary_html=summary_html,
         top_html=top_html,
         catplot_html=catplot_html,
         heatmap_html=heatmap_html,
         ridgeplot_html=ridgeplot_html,
         ideogram_html=ideogram_html,
         tss_dist_html=tss_dist_html,
         navigation=navigation,
     )
     
     with open(out_file, "w") as fp:
         fp.write(rendering)