Version 0.2.12
A Python library to build and compile interactive HTML reports using the Datalys2 Reporting framework.
Note: Compatible with dl2 version 0.2.12 https://github.com/kameronbrooks/datalys2-reporting
pip install dl2-reportsimport pandas as pd
from dl2_reports import DL2Report
# Create a report
report = DL2Report(title="My Report")
# Add data
df = pd.DataFrame({"A": [1, 2], "B": [3, 4]})
report.add_df("my_data", df, compress=True)
# Add a page and visual
page = report.add_page("Overview")
page.add_row().add_kpi("my_data", value_column="A", title="Metric A")
# Save to HTML or show in Jupyter
report.save("report.html")
report.show()Always use compression for production reports. The Python API provides automatic gzip compression for your datasets, which significantly reduces file size and improves browser performance.
- Large datasets will cause severe performance issues or fail to load entirely without compression
- Compressed reports load faster and consume less memory in the browser
- File sizes can be reduced by 80-90% or more
- The browser automatically decompresses data on-the-fly using the built-in
DecompressionStreamAPI
When creating a DL2Report, you can set the default compression behavior:
from dl2_reports import DL2Report
# Enable compression by default (recommended)
report = DL2Report(
title="My Report",
compress_visuals=True # This is the default
)Control compression for individual datasets using the compress parameter in add_df():
import pandas as pd
from dl2_reports import DL2Report
report = DL2Report(title="Sales Report")
# Compress large datasets (recommended for most data)
large_df = pd.read_csv("sales_data.csv")
report.add_df("salesData", large_df, compress=True)
# Small datasets can be uncompressed for easier debugging
small_df = pd.DataFrame({"kpi": [100]})
report.add_df("kpiData", small_df, compress=False)When you set compress=True, the Python API automatically:
- Serializes your data to JSON
- Compresses it using gzip
- Encodes it as a Base64 string
- Stores it in a separate
<script>tag in the HTML - Adds the
gc-compressed-datameta tag for automatic memory cleanup
The browser then decompresses the data when the report loads.
- ✅ Always compress in production - essential for performance and reliability
- ✅ Compress any dataset with more than a few rows - the overhead is minimal
- ❌ Only disable compression when:
- Debugging and you need to inspect the raw JSON in the HTML file
- Working with extremely small datasets (single-row KPI values) during development
You can render reports directly inside Jupyter Notebooks (including VS Code and JupyterLab).
report.show(height=800): Displays the report in an iframe.- Automatic Rendering: Simply placing the
reportobject at the end of a cell will render it automatically.
Requirements:
IPythonmust be installed in your environment.
All visuals are added to a layout row using row.add_<type>(...).
All Layout.add_* visual helpers accept **kwargs which are passed through to the viewer as visual properties.
Common properties supported by the viewer include:
padding: number (px)margin: number (px)border: bool or CSS border stringshadow: bool or CSS box-shadow stringflex: number (flex grow)modal_id: string (global modal id opened via the expand icon)
The Python API accepts these in snake_case; the compiled report JSON uses camelCase.
Below are the current convenience helpers available on Layout (rows are layouts).
These are the visual types you can add via the Layout helpers:
kpi(viaadd_kpi)table(viaadd_table)card(viaadd_card)pie(viaadd_pie)clusteredBar/stackedBar(viaadd_bar(stacked=...))scatter(viaadd_scatter)line(viaadd_line)area(viaadd_area)checklist(viaadd_checklist)histogram(viaadd_histogram)heatmap(viaadd_heatmap)boxplot(viaadd_boxplot)modal(viaadd_modal_button)
You can also add any viewer-supported visual type directly using add_visual(type=..., ...).
Use this when you want to pass through viewer props that don't have a dedicated helper yet.
| Parameter | Type | Default | Description |
|---|---|---|---|
type |
str |
(required) | Visual type (e.g., 'kpi', 'table', 'line', 'scatter'). |
dataset_id |
str | None |
None |
Dataset id to bind to this visual (required for most chart/data visuals). |
**kwargs |
Any |
— | Additional visual properties (serialized to JSON). Common ones include padding, margin, border, shadow, flex, modal_id. |
| Parameter | Type | Default | Description |
|---|---|---|---|
dataset_id |
str |
(required) | The dataset id. |
value_column |
str | int |
(required) | Column for the main KPI value. |
title |
str | None |
None |
Optional KPI card title. |
comparison_column |
str | int | None |
None |
Column for the comparison value. |
comparison_row_index |
int | None |
None |
Row index to use for comparison (supports negative indices). If not provided, the viewer uses the same row as row_index. |
comparison_text |
str |
The comparison text to show alongside the comparison value. Ex. ("Last Month", "Yesterday", etc.) | |
row_index |
int | None |
None |
Row index to display (supports negative indices). |
format |
str | None |
None |
'number', 'currency', 'percent', 'date', 'hms'. |
| ` | |||
currency_symbol |
str | None |
None |
Currency symbol (viewer default is usually '$'). |
good_direction |
str | None |
None |
Which direction is “good” ('higher' or 'lower'). |
breach_value |
float | int | None |
None |
Value that triggers a breach indicator. |
warning_value |
float | int | None |
None |
Value that triggers a warning indicator. |
description |
str | None |
None |
Optional description text. |
width |
int | None |
None |
Optional width. |
height |
int | None |
None |
Optional height. |
**kwargs |
Any |
— | Additional common visual properties (e.g., modal_id, padding/margins, etc.). |
| Parameter | Type | Default | Description |
|---|---|---|---|
dataset_id |
str |
(required) | The dataset id. |
title |
str | None |
None |
Optional table title. |
columns |
list[str] | None |
None |
Optional list of columns to display. |
page_size |
int | None |
None |
Rows per page. |
table_style |
str | None |
None |
'plain', 'bordered', or 'alternating'. |
show_search |
bool | None |
None |
Whether to show the search box. |
**kwargs |
Any |
— | Additional common visual properties. |
| Parameter | Type | Default | Description |
|---|---|---|---|
title |
str | None |
(required) | Optional title (supports template syntax in the viewer). |
text |
str |
(required) | Main card text (supports template syntax in the viewer). |
**kwargs |
Any |
— | Additional common visual properties. |
| Parameter | Type | Default | Description |
|---|---|---|---|
dataset_id |
str |
(required) | The dataset id. |
category_column |
str | int |
(required) | Column for slice labels. |
value_column |
str | int |
(required) | Column for slice values. |
inner_radius |
int | None |
None |
Inner radius for donut styling. |
show_legend |
bool | None |
None |
Whether to show the legend. |
**kwargs |
Any |
— | Additional common visual properties. |
| Parameter | Type | Default | Description |
|---|---|---|---|
dataset_id |
str |
(required) | The dataset id. |
x_column |
str | int |
(required) | Column for X-axis categories. |
y_columns |
list[str] |
(required) | Series columns for Y values. |
stacked |
bool |
False |
If True, uses stacked bars; otherwise clustered. |
threshold |
dict | None |
None |
Optional pass/fail coloring (see Threshold Configuration). |
x_axis_label |
str | None |
None |
Optional X-axis label. |
y_axis_label |
str | None |
None |
Optional Y-axis label. |
show_legend |
bool | None |
None |
Whether to show the legend. |
show_labels |
bool | None |
None |
Whether to show value labels. |
horizontal |
bool | None |
None |
Whether to render bars horizontally (viewer-dependent). |
**kwargs |
Any |
— | Additional common visual properties. |
| Parameter | Type | Default | Description |
|---|---|---|---|
dataset_id |
str |
(required) | The dataset id. |
x_column |
str | int |
(required) | Column for numeric X values. |
y_column |
str | int |
(required) | Column for numeric Y values. |
category_column |
str | int | None |
None |
Optional column for coloring points by category. |
show_trendline |
bool | None |
None |
Whether to show a trendline. |
show_correlation |
bool | None |
None |
Whether to show correlation stats. |
point_size |
int | None |
None |
Point size. |
x_axis_label |
str | None |
None |
Optional X-axis label. |
y_axis_label |
str | None |
None |
Optional Y-axis label. |
**kwargs |
Any |
— | Additional common visual properties. |
| Parameter | Type | Default | Description |
|---|---|---|---|
dataset_id |
str |
(required) | The dataset id. |
x_column |
str | int |
(required) | Column for X values (time or category). |
y_columns |
list[str] | str |
(required) | Column(s) for Y series. |
smooth |
bool | None |
None |
Whether to render smooth curves. |
show_legend |
bool | None |
None |
Whether to show the legend. |
show_labels |
bool | None |
None |
Whether to show value labels. |
min_y |
float | int | None |
None |
Optional minimum Y. |
max_y |
float | int | None |
None |
Optional maximum Y. |
colors |
list[str] | None |
None |
Optional list of series colors. |
threshold |
dict | None |
None |
Optional pass/fail coloring (see Threshold Configuration). |
x_axis_label |
str | None |
None |
Optional X-axis label. |
y_axis_label |
str | None |
None |
Optional Y-axis label. |
**kwargs |
Any |
— | Additional common visual properties. |
| Parameter | Type | Default | Description |
|---|---|---|---|
dataset_id |
str |
(required) | The dataset id. |
x_column |
str | int |
(required) | Column for X values. |
y_columns |
list[str] | str |
(required) | Column(s) for Y series. |
smooth |
bool | None |
None |
Whether to render smooth curves. |
show_line |
bool | None |
True |
Show line stroke on top of fill. |
show_markers |
bool | None |
True |
Show interactive marker points. |
fill_opacity |
float | None |
0.3 |
Area fill opacity (0-1). |
show_legend |
bool | None |
None |
Whether to show the legend. |
show_labels |
bool | None |
None |
Whether to show value labels. |
min_y |
float | int | None |
None |
Optional minimum Y. |
max_y |
float | int | None |
None |
Optional maximum Y. |
colors |
list[str] | None |
None |
Optional list of series colors. |
threshold |
dict | None |
None |
Optional pass/fail coloring (see Threshold Configuration). |
x_axis_label |
str | None |
None |
Optional X-axis label. |
y_axis_label |
str | None |
None |
Optional Y-axis label. |
**kwargs |
Any |
— | Additional common visual properties. |
| Parameter | Type | Default | Description |
|---|---|---|---|
dataset_id |
str |
(required) | The dataset id. |
status_column |
str |
(required) | Column containing a truthy completion value. |
warning_column |
str | None |
None |
Optional date column to evaluate for warnings. |
warning_threshold |
int | None |
None |
Days before due date to trigger warning. |
columns |
list[str] | None |
None |
Optional subset of columns to display. |
page_size |
int | None |
None |
Rows per page. |
show_search |
bool | None |
None |
Whether to show the search box. |
**kwargs |
Any |
— | Additional common visual properties. |
| Parameter | Type | Default | Description |
|---|---|---|---|
dataset_id |
str |
(required) | The dataset id. |
column |
str | int |
(required) | Numeric column to bin. |
bins |
int | None |
None |
Number of bins. |
color |
str | None |
None |
Bar color. |
show_labels |
bool | None |
None |
Whether to show count labels. |
x_axis_label |
str | None |
None |
Optional X-axis label. |
y_axis_label |
str | None |
None |
Optional Y-axis label. |
**kwargs |
Any |
— | Additional common visual properties. |
| Parameter | Type | Default | Description |
|---|---|---|---|
dataset_id |
str |
(required) | The dataset id. |
x_column |
str | int |
(required) | Column for X categories. |
y_column |
str | int |
(required) | Column for Y categories. |
value_column |
str | int |
(required) | Column for cell values. |
show_cell_labels |
bool | None |
None |
Whether to show values inside cells. |
min_value |
float | int | None |
None |
Optional minimum for the color scale. |
max_value |
float | int | None |
None |
Optional maximum for the color scale. |
color |
str | list[str] | None |
None |
D3 interpolator name (e.g., 'Viridis') or custom colors. |
x_axis_label |
str | None |
None |
Optional X-axis label. |
y_axis_label |
str | None |
None |
Optional Y-axis label. |
**kwargs |
Any |
— | Additional common visual properties. |
Supports two modes:
- Data mode: provide
data_column(and optionalcategory_column) - Pre-calculated mode: provide
min_column,q1_column,median_column,q3_column,max_column(and optionalmean_column)
| Parameter | Type | Default | Description |
|---|---|---|---|
dataset_id |
str |
(required) | The dataset id. |
data_column |
str | int | None |
None |
Raw values column (data mode). |
category_column |
str | int | None |
None |
Grouping/label column. |
min_column |
str | int | None |
None |
Pre-calculated minimum column. |
q1_column |
str | int | None |
None |
Pre-calculated Q1 column. |
median_column |
str | int | None |
None |
Pre-calculated median column. |
q3_column |
str | int | None |
None |
Pre-calculated Q3 column. |
max_column |
str | int | None |
None |
Pre-calculated maximum column. |
mean_column |
str | int | None |
None |
Pre-calculated mean column (optional). |
direction |
str | None |
None |
'vertical' or 'horizontal'. |
show_outliers |
bool | None |
None |
Whether to show outliers. |
color |
str | list[str] | None |
None |
Fill color or scheme. |
x_axis_label |
str | None |
None |
Optional X-axis label. |
y_axis_label |
str | None |
None |
Optional Y-axis label. |
**kwargs |
Any |
— | Additional common visual properties. |
| Parameter | Type | Default | Description |
|---|---|---|---|
modal_id |
str |
(required) | The global modal id to open. |
button_label |
str |
(required) | Button label text. |
**kwargs |
Any |
— | Additional common visual properties. |
Note: Most visuals also support
modal_idas a keyword argument to enable an "expand" icon that opens a modal on click.
Color chart elements based on whether values pass or fail a threshold. Applies to Line, Area, and Clustered Bar.
| Property | Type | Default | Description |
|---|---|---|---|
value |
number |
(required) | The threshold value to compare against. |
pass_color |
str |
#22c55e |
Color for passing values. |
fail_color |
str |
#ef4444 |
Color for failing values. |
mode |
'above'|'below'|'equals' |
'above' |
How to determine pass/fail. |
show_line |
bool |
True |
Show reference line at threshold. |
line_style |
'solid'|'dashed'|'dotted' |
'dashed' |
Threshold line style. |
blend_width |
number |
5 |
Gradient blend zone width (line/area only). |
apply_to |
'both'|'markers'|'lines' |
'both' |
Which elements get threshold colors. |
Mode Options:
'above'- Values >= threshold pass'below'- Values <= threshold pass'equals'- Only exact matches pass
Create detailed overlays that can be triggered from any element.
# Define a modal
modal = report.add_modal("details", "Detailed View")
modal.add_row().add_table("my_data")
# Trigger from a visual
page.add_row().add_kpi("my_data", "A", "Metric", modal_id="details")
# Or add a dedicated button
page.add_row().add_modal_button("details", "Open Details")Add trend lines, markers, and custom axes to your charts.
You can add a trend line using the .add_trend() method. It can automatically calculate linear or polynomial regression if you don't provide coefficients.
chart = page.add_row().add_scatter("my_data", "A", "B")
# Auto-calculate linear trend (degree 1)
chart.add_trend(color="red")
# Auto-calculate polynomial trend (e.g., degree 2)
chart.add_trend(coefficients=2, color="blue", line_style="dashed")
# Manually provide coefficients [intercept, slope, ...]
chart.add_trend(coefficients=[0, 1.5], color="green")Use .add_element(type, **kwargs) for other annotations.
| Element Type | Description | Key Arguments |
|---|---|---|
xAxis |
Vertical line at a specific X value. | value, color, label, line_style |
yAxis |
Horizontal line at a specific Y value. | value, color, label, line_style |
marker |
A point marker at a specific value. | value, size, shape (circle, square, triangle), color |
label |
A text label at a specific value. | value, label, font_size, font_weight |
chart.add_element("yAxis", value=100, label="Target", color="green")All components (Pages, Rows, Layouts, Visuals) are part of a tree. You can access the root report from any component using .get_report().
visual = layout.add_visual("line", "my_data")
report = visual.get_report()
print(report.title)The API provides two ways to read scalar values back from your data after the report is built. These are useful for conditional layout logic, threshold checks, or computing derived metrics without re-querying the original DataFrame.
Query a value from any registered dataset by name — no visual reference required.
report.get_value(data_source_name, column_name, row_index=-1)| Parameter | Type | Default | Description |
|---|---|---|---|
data_source_name |
str |
(required) | The dataset name passed to add_df(). |
column_name |
str |
(required) | The column to read from. |
row_index |
int |
-1 |
Row index. Negative indices count from the end (e.g. -1 = last row). |
This is the right tool when you need to inspect a value before or without creating a visual — for example, deciding whether to add a row at all:
report = DL2Report(title="Sales Report")
report.add_df("sales", sales_df, format="records", compress=False)
page = report.add_page("Overview")
# Add a bar chart
bar_row = page.add_row()
bar_row.add_bar(dataset_id="sales", x_column="region", y_columns=["revenue"])
# Only add a warning card if the worst region is below target
TARGET = 120_000
revenues = [report.get_value("sales", "revenue", i) for i in range(len(sales_df))]
worst = min(revenues)
if worst < TARGET:
warning_row = page.add_row()
warning_row.add_card(
title="Warning: underperforming region detected",
text=f"Lowest revenue is ${worst:,} — below the ${TARGET:,} target.",
content_type="md",
)Read the scalar value that a specific visual represents, directly from its backing DataFrame. The visual must be part of the report tree (i.e. already added to a row) and its props must include row_index and value_column.
value = visual.get_value()This is the right tool when you already have a visual reference and want to inspect or act on its value:
kpi = page.add_row().add_kpi(
dataset_id="sales",
value_column="revenue",
row_index=0,
title="Revenue – North",
format="currency",
)
north_revenue = kpi.get_value()
print(f"North revenue: {north_revenue:,}")Create a duplicate of a visual with the same type, dataset_id, props, and annotations, but a new unique ID. Use this to stamp the same visual configuration into multiple rows without re-specifying every argument.
copied_visual = visual.copy()After copying, add the copy back into any layout row using row.add_visual(copy.type, visual=copy). You can then mutate copy.props to override only what differs:
# Build a prototype KPI once
proto = row.add_kpi(
dataset_id="sales",
value_column="revenue",
row_index=0,
title="Revenue – North",
format="currency",
)
# Stamp copies for remaining regions
for i, region in enumerate(["South", "East", "West"], start=1):
copy = proto.copy()
copy.props["row_index"] = i
copy.props["title"] = f"Revenue – {region}"
row.add_visual(copy.type, visual=copy)
# Each copy exposes get_value() once it is in the tree
total = proto.get_value() + sum(
row.children[i].get_value() for i in range(1, 4)
)Use layout.on_condition() to conditionally add visuals to a row at report-build time. This is a compile-time guard — it evaluates a plain Python bool and either delegates the add_* call to the real layout or silently discards it.
layout.on_condition(condition).add_<visual>(...)| Parameter | Type | Description |
|---|---|---|
condition |
bool |
If True, the visual is added normally and returned. If False, nothing is added and None is returned. |
- When
conditionisTrue, the call is forwarded to the parent layout exactly as if you had calledlayout.add_<visual>(...)directly. - When
conditionisFalse, no visual is created, no element ID is consumed, andNoneis returned. - The wrapper is not a tree node — it never occupies a slot in the report tree regardless of the condition.
report = DL2Report(title="Sales Report")
report.add_df("sales", sales_df, format="records", compress=False)
page = report.add_page("Overview")
row = page.add_row()
row.add_bar(dataset_id="sales", x_column="region", y_columns=["revenue"])
TARGET = 120_000
worst = min(report.get_value("sales", "revenue", i) for i in range(len(sales_df)))
warning_row = page.add_row()
warning_row.on_condition(worst < TARGET).add_card(
title="Warning: underperforming region detected",
text=f"Lowest revenue is ${worst:,} — below the ${TARGET:,} target.",
)show_details = True # could come from any Python logic
detail_row = page.add_row()
detail_row.on_condition(show_details).add_table("sales", title="Detail View")Tip: Because
on_conditionreturnsNonewhen the condition isFalse, avoid using the return value without aNonecheck when the condition may beFalse.
For detailed information on available visuals and configuration, see DOCUMENTATION.md.
Or see the github repo at https://github.com/kameronbrooks/datalys2-reporting