Visualization & HTML Reports¶
This document describes the system for visualizing profile results and generating HTML reports.
Overview¶
The visualization system implemented in src/truthound/profiler/visualization.py provides pure SVG-based chart rendering and HTML report generation.
ChartType¶
class ChartType(Enum):
"""Chart types"""
BAR = "bar" # Bar chart
HORIZONTAL_BAR = "horizontal_bar" # Horizontal bar chart
PIE = "pie" # Pie chart
DONUT = "donut" # Donut chart
LINE = "line" # Line chart
AREA = "area" # Area chart
SCATTER = "scatter" # Scatter plot
HISTOGRAM = "histogram" # Histogram
HEATMAP = "heatmap" # Heatmap
TABLE = "table" # Table
GAUGE = "gauge" # Gauge chart
SPARKLINE = "sparkline" # Sparkline
TREEMAP = "treemap" # Treemap
SANKEY = "sankey" # Sankey diagram
ReportTheme¶
class ReportTheme(Enum):
"""Report themes"""
LIGHT = "light" # Light theme
DARK = "dark" # Dark theme
PROFESSIONAL = "professional" # Professional theme
MINIMAL = "minimal" # Minimal theme
COLORFUL = "colorful" # Colorful theme
SectionType¶
class SectionType(Enum):
"""Report section types"""
OVERVIEW = "overview" # Overview section
COLUMN_DETAILS = "column_details" # Column details
DATA_QUALITY = "data_quality" # Data quality
STATISTICS = "statistics" # Statistics information
PATTERNS = "patterns" # Pattern information
ALERTS = "alerts" # Alerts
RECOMMENDATIONS = "recommendations" # Recommendations
CUSTOM = "custom" # Custom section
SVGChartRenderer¶
Renders charts as pure SVG without external dependencies. Uses ChartData and ChartConfig for a unified interface.
from truthound.profiler.visualization import (
SVGChartRenderer, ChartData, ChartConfig, ChartType
)
renderer = SVGChartRenderer()
# Bar chart
bar_data = ChartData(
labels=["A", "B", "C", "D", "E"],
values=[10, 25, 15, 30, 20],
title="Distribution",
)
bar_config = ChartConfig(chart_type=ChartType.BAR, width=400, height=300)
bar_svg = renderer.render(bar_data, bar_config)
# Pie chart
pie_data = ChartData(
labels=["Cat A", "Cat B", "Cat C", "Cat D", "Cat E"],
values=[30, 25, 20, 15, 10],
)
pie_config = ChartConfig(chart_type=ChartType.PIE, width=300, height=300)
pie_svg = renderer.render(pie_data, pie_config)
# Histogram
hist_data = ChartData(
labels=["0-10", "10-20", "20-30", "30-40"],
values=[5, 12, 8, 3],
title="Value Distribution",
)
hist_config = ChartConfig(chart_type=ChartType.HISTOGRAM, width=400, height=300)
hist_svg = renderer.render(hist_data, hist_config)
# Gauge chart
gauge_data = ChartData(
values=[85], # Current value
title="Completeness",
metadata={"min": 0, "max": 100},
)
gauge_config = ChartConfig(chart_type=ChartType.GAUGE, width=250, height=180)
gauge_svg = renderer.render(gauge_data, gauge_config)
HTMLReportGenerator¶
Generates complete HTML reports. Accepts ProfileData objects or dicts as input.
from truthound.profiler.visualization import (
HTMLReportGenerator, ReportConfig, ReportTheme, ProfileData
)
# Configuration
config = ReportConfig(
title="Data Profile Report",
subtitle="Generated by Truthound",
theme=ReportTheme.PROFESSIONAL,
include_toc=True,
include_timestamp=True,
include_summary=True,
sections=[
SectionType.OVERVIEW,
SectionType.DATA_QUALITY,
SectionType.COLUMN_DETAILS,
SectionType.PATTERNS,
SectionType.RECOMMENDATIONS,
],
)
# Generate report
generator = HTMLReportGenerator()
html = generator.generate(profile_data, config)
# Save to file
generator.save(profile_data, "report.html", config)
# Generate from dict
html = generator.generate_from_dict(profile_dict, config)
ReportConfig¶
@dataclass
class ReportConfig:
"""Report configuration"""
title: str = "Data Profile Report"
subtitle: str = ""
theme: ReportTheme = ReportTheme.LIGHT
logo_path: str | None = None # Logo file path
logo_base64: str | None = None # Base64 encoded logo
include_toc: bool = True # Include table of contents
include_timestamp: bool = True # Include timestamp
include_summary: bool = True # Include summary
sections: list[SectionType] = field(default_factory=lambda: [
SectionType.OVERVIEW,
SectionType.DATA_QUALITY,
SectionType.COLUMN_DETAILS,
SectionType.PATTERNS,
SectionType.RECOMMENDATIONS,
])
custom_css: str | None = None # Custom CSS
custom_js: str | None = None # Custom JavaScript
embed_resources: bool = True # Embed resources
language: str = "en" # Language code
Section Renderers¶
Each section is generated by a separate renderer (implementing the SectionRenderer protocol). Renderers receive SectionContent, ChartRenderer, and ThemeConfig as input.
OverviewSectionRenderer¶
from truthound.profiler.visualization import (
OverviewSectionRenderer, SectionContent, SectionType
)
renderer = OverviewSectionRenderer()
content = SectionContent(
section_type=SectionType.OVERVIEW,
title="Overview",
text_blocks=["Table: users", "Rows: 10,000 | Columns: 5"],
charts=[...],
tables=[...],
)
html = renderer.render(content, chart_renderer, theme)
DataQualitySectionRenderer¶
from truthound.profiler.visualization import DataQualitySectionRenderer
renderer = DataQualitySectionRenderer()
# Included content:
# - Quality gauge chart
# - Alert/warning display
# - Per-column quality table
ColumnDetailsSectionRenderer¶
from truthound.profiler.visualization import ColumnDetailsSectionRenderer
renderer = ColumnDetailsSectionRenderer()
# For each column:
# - Value distribution chart (BAR or HISTOGRAM)
# - Column statistics table
# - Collapsible support (collapsible=True)
PatternsSectionRenderer¶
from truthound.profiler.visualization import PatternsSectionRenderer
renderer = PatternsSectionRenderer()
# Included content:
# - Pattern type pie chart
# - Pattern detail table
RecommendationsSectionRenderer¶
from truthound.profiler.visualization import RecommendationsSectionRenderer
renderer = RecommendationsSectionRenderer()
# Included content:
# - Recommendations list (text_blocks)
# - Additional information table
ReportExporter¶
Supports export to various formats. HTML and JSON formats are supported by default.
from truthound.profiler.visualization import ReportExporter, ProfileData
exporter = ReportExporter()
# HTML export
html_str = exporter.to_html(profile_data, config)
# JSON export
json_str = exporter.to_json(profile_data)
# Export to file
exporter.to_file(profile_data, "report.html", format="html")
exporter.to_file(profile_data, "profile.json", format="json")
Theme Customization¶
Custom themes can be created with ThemeConfig or registered in ThemeRegistry.
from truthound.profiler.visualization import ThemeConfig, theme_registry, HTMLReportGenerator
custom_theme = ThemeConfig(
name="my_theme",
primary_color="#3498db",
secondary_color="#2ecc71",
accent_color="#e74c3c",
background_color="#ffffff",
text_color="#333333",
border_color="#e0e0e0",
font_family="'Noto Sans KR', sans-serif",
header_bg="#f8f9fa",
card_bg="#ffffff",
shadow="0 2px 4px rgba(0,0,0,0.1)",
border_radius="8px",
)
# Register in registry
theme_registry.register("my_theme", custom_theme)
# Pass theme directly
generator = HTMLReportGenerator(theme=custom_theme)
Chart Rendering Methods¶
| Output Format | Chart Engine | Characteristics |
|---|---|---|
| HTML | ApexCharts | Interactive, requires JS |
| SVG (pure) | No JS dependency, static | |
| Markdown | Text | ASCII art charts |
# Interactive charts for HTML
html_generator = HTMLReportGenerator(config)
html = html_generator.generate(profile) # Uses ApexCharts
# Static SVG charts for PDF
pdf_exporter = ReportExporter()
pdf_exporter.export(profile, "report.pdf") # Uses pure SVG
Quick Report Generation¶
from truthound.profiler.visualization import generate_report
# Convenience function
html = generate_report(profile)
with open("report.html", "w") as f:
f.write(html)
# Specify theme
html = generate_report(profile, theme=ReportTheme.DARK)
Comparison Reports¶
Generate reports comparing multiple profiles.
from truthound.profiler.visualization import compare_profiles
# Compare multiple profiles
html = compare_profiles(
profiles=[profile1, profile2, profile3],
labels=["Before", "After", "Latest"],
config=ReportConfig(title="Profile Comparison Report"),
)
# Included content:
# - Profile overview comparison table (table name, row count, column count)
# - Quality score comparison bar chart
CLI Usage¶
# Generate HTML report
th profile data.csv --output report.html --format html
# Specify theme
th profile data.csv --output report.html --theme dark
# Generate PDF report
th profile data.csv --output report.pdf --format pdf
# Comparison report
th compare-profiles profile1.json profile2.json --output comparison.html
Next Steps¶
- Internationalization - Generate multilingual reports
- Distributed Processing - Parallel report generation at scale