Skip to content

Report

generate_report

generate_report(real: ECGDataset, synthetics: List[ECGDataset], metric_results: Dict[str, Dict[str, MetricResult]], output_path: Union[str, Path], n_ecg_samples: int = 3, leads: Optional[List[str]] = None, compare_mode: str = 'overlay', plotly_cdn: bool = True, fs: float = 500.0, feature_df_real=None, feature_dfs_synth=None, feature_plots_2d: bool = False, feature_plots_3d: bool = False) -> Path

Build and write a self-contained HTML report.

Parameters:

Name Type Description Default
real ECGDataset
required
synthetics list of ECGDataset
required
metric_results metric_name: {synth_label: MetricResult}
metric_name: {synth_label: MetricResult}
output_path str or Path
required
n_ecg_samples int — number of ECG recordings to show in gallery
3
leads list of str, optional — subset of leads to show in ECG gallery
None
compare_mode 'overlay' | 'sidebyside' | 'grid'
'overlay'
plotly_cdn bool — if True, load Plotly.js from CDN (smaller HTML);
            if False, embed full JS (offline-capable).
True

Returns:

Type Description
Path to the written HTML file.
Source code in ecgen_eval/report/html_report.py
def generate_report(
    real: ECGDataset,
    synthetics: List[ECGDataset],
    metric_results: Dict[str, Dict[str, MetricResult]],
    output_path: Union[str, Path],
    n_ecg_samples: int = 3,
    leads: Optional[List[str]] = None,
    compare_mode: str = "overlay",
    plotly_cdn: bool = True,
    fs: float = 500.0,
    feature_df_real=None,
    feature_dfs_synth=None,
    feature_plots_2d: bool = False,
    feature_plots_3d: bool = False,
) -> Path:
    """
    Build and write a self-contained HTML report.

    Parameters
    ----------
    real : ECGDataset
    synthetics : list of ECGDataset
    metric_results : {metric_name: {synth_label: MetricResult}}
    output_path : str or Path
    n_ecg_samples : int — number of ECG recordings to show in gallery
    leads : list of str, optional — subset of leads to show in ECG gallery
    compare_mode : 'overlay' | 'sidebyside' | 'grid'
    plotly_cdn : bool — if True, load Plotly.js from CDN (smaller HTML);
                        if False, embed full JS (offline-capable).

    Returns
    -------
    Path to the written HTML file.
    """
    output_path = Path(output_path)
    output_path.parent.mkdir(parents=True, exist_ok=True)

    include_js = "cdn" if plotly_cdn else True

    sections: List[str] = []

    # 1. Header / summary
    sections.append(_render_header(real, synthetics))

    # 2. Dataset summary table
    sections.append(_render_dataset_table(real, synthetics))

    # 3. ECG Sample Gallery
    sections.append(_render_ecg_gallery(
        real, synthetics, n_ecg_samples, leads, compare_mode, include_js
    ))

    # 4. Metric sections
    for metric_name, by_synth in metric_results.items():
        sections.append(_render_metric_section(
            metric_name, by_synth, real.lead_names, include_js,
            fs=fs,
        ))

    # 5. Metrics summary table with CSV download
    if metric_results:
        sections.append(_render_summary_table(metric_results, synthetics))

    # 6. Radar summary (if multiple metrics)
    if len(metric_results) > 1:
        sections.append(_render_radar(metric_results, include_js))

    # 7. Clinical Feature Summary table
    if feature_df_real is not None and feature_dfs_synth:
        sections.append(_render_feature_summary_table(
            feature_df_real, feature_dfs_synth, synthetics
        ))

    # 8. 2D feature distribution plots
    if feature_plots_2d and feature_df_real is not None and feature_dfs_synth:
        for i, (sdf, sds) in enumerate(zip(feature_dfs_synth, synthetics)):
            sections.append(_render_feature_2d_section(
                feature_df_real, sdf, sds.label, include_js=(i == 0 and not metric_results)
            ))

    # 9. 3D feature distribution plots
    if feature_plots_3d and feature_df_real is not None and feature_dfs_synth:
        for i, (sdf, sds) in enumerate(zip(feature_dfs_synth, synthetics)):
            sections.append(_render_feature_3d_section(feature_df_real, sdf, sds.label))

    # 10. Citations
    sections.append(_render_citations(metric_results))

    html = _wrap_html(
        title=f"ECGEN-Eval Report — {real.label}",
        body="\n".join(sections),
        plotly_cdn=plotly_cdn,
    )

    output_path.write_text(html, encoding="utf-8")
    return output_path