Source code for neurokit2.misc.report

# -*- coding: utf-8 -*-
import inspect

import matplotlib
import numpy as np
import pandas as pd


[docs] def create_report(file="myreport.html", signals=None, info={"sampling_rate": 1000}, fig=None): """**Reports** Create report containing description and figures of processing. This function is meant to be used via the :func:`.rsp_process` or :func:`.ppg_process` functions. Parameters ---------- file : str Name of the file to save the report to. Can also be ``"text"`` to simply print the text in the console. signals : pd.DataFrame A DataFrame of signals. Usually obtained from :func:`.rsp_process`, :func:`.ppg_process`, or :func:`.emg_process`. info : dict A dictionary containing the information of peaks and the signals' sampling rate. Usually obtained from :func:`.rsp_process` or :func:`.ppg_process`. fig : matplotlib.figure.Figure or plotly.graph_objects.Figure A figure containing the processed signals. Usually obtained from :func:`.rsp_plot`, :func:`.ppg_plot`, or :func:`.emg_plot`. Returns ------- str The report as a string. See Also -------- rsp_process, ppg_process, emg_process Examples -------- .. ipython:: python import neurokit2 as nk rsp = nk.rsp_simulate(duration=30, sampling_rate=200, random_state=0) signals, info = nk.rsp_process(rsp, sampling_rate=200, report="text") """ description, ref = text_combine(info) table_html, table_md = summarize_table(signals) # Print text in the console for key in [k for k in info.keys() if "text_" in k]: print(info[key] + "\n") print(table_md) print("\nReferences") for s in info["references"]: print("- " + s) # Save report if ".html" in file: # Make figures fig_html = '<h2 style="background-color: #FB661C">Visualization</h1>' fig_html += fig_to_html(fig) print(f"The report has been saved to {file}") contents = [description, table_html, fig_html, ref] html_save(contents=contents, file=file)
def summarize_table(signals): """Create table to summarize statistics of a signal.""" # TODO: add more features summary = {} rate_cols = [col for col in signals.columns if "Rate" in col] if len(rate_cols) > 0: rate_col = rate_cols[0] summary[rate_col + "_Mean"] = np.mean(signals[rate_col]) summary[rate_col + "_SD"] = np.std(signals[rate_col]) summary_table = pd.DataFrame(summary, index=[0]) # Make HTML and Markdown versions html = '<h2 style="background-color: #D60574">Summary table</h1>' + summary_table.to_html( index=None ) try: md = summary_table.to_markdown(index=None) except ImportError: md = summary_table # in case printing markdown export fails return html, md else: return "", "" def text_combine(info): """Reformat dictionary describing processing methods as strings to be inserted into HTML file.""" preprocessing = '<h2 style="background-color: #FB1CF0">Preprocessing</h1>' for key in ["text_cleaning", "text_peaks"]: if key in info.keys(): preprocessing += info[key] + "<br>" ref = '<h2 style="background-color: #FBB41C">References</h1>' if "references" in info.keys(): ref += "\n <ul> \n" for reference in info["references"]: ref += "<li>" + reference + "</li>" + "\n" ref += "\n </ul> \n" return preprocessing, ref def fig_to_html(fig): """Convert a figure to HTML.""" if isinstance(fig, str): return fig elif isinstance(fig, matplotlib.pyplot.Figure): # https://stackoverflow.com/questions/48717794/matplotlib-embed-figures-in-auto-generated-html import base64 from io import BytesIO temp_file = BytesIO() fig.savefig(temp_file, format="png") encoded = base64.b64encode(temp_file.getvalue()).decode("utf-8") return "<img src='data:image/png;base64,{}'>".format(encoded) else: try: import plotly if isinstance(fig, plotly.graph_objs._figure.Figure): # https://stackoverflow.com/questions/59868987/plotly-saving-multiple-plots-into-a-single-html return fig.to_html().split("<body>")[1].split("</body>")[0] else: return "" except ImportError: return "" def html_save(contents=[], file="myreport.html"): """Combine figures and text in a single HTML document.""" # https://stackoverflow.com/questions/59868987/plotly-saving-multiple-plots-into-a-single-html with open(file, "w") as page: page.write( r"""<html> <head> <style> h1 { text-align: center; font-family: Arial, Helvetica, sans-serif; } h2 { text-align: center; font-family: Arial, Helvetica, sans-serif; } p { text-align: left; font-family: Arial, Helvetica, sans-serif; } div { text-align: center; font-family: Arial, Helvetica, sans-serif; } ul { text-align: left; list-style-position: inside; font-family: Arial, Helvetica, sans-serif; } </style> </head> <body> <h1>NeuroKit Processing Report</h1>""" ) for content in contents: if isinstance(content, str): inner_html = content else: # assume the content is an interactive plotly figure and export to HTML inner_html = content.to_html().split("<body>")[1].split("</body>")[0] page.write(inner_html) page.write("<br>") page.write("</body></html>" + "\n") def get_default_args(func): """Get the default values of a function's arguments.""" # https://stackoverflow.com/questions/12627118/get-a-function-arguments-default-value signature = inspect.signature(func) return { k: v.default for k, v in signature.parameters.items() if v.default is not inspect.Parameter.empty } def get_kwargs(report_info, func): """Get keyword arguments from report_info and update report_info if defaults.""" defaults = get_default_args(func) kwargs = {} for key in defaults: if key not in ["sampling_rate", "method"]: # if arguments have not been specified by user, # set them to the defaults if key not in report_info: report_info[key] = defaults[key] elif report_info[key] != defaults[key]: kwargs[key] = report_info[key] return kwargs, report_info