Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -139,11 +139,12 @@ class JudgeScoreProfilerResults(ColumnProfilerResults):
def create_report_section(self) -> Panel:
layout = Table.grid(Column(), expand=True, padding=(2, 0))

histograms = {} if isinstance(self.score_distributions, MissingValue) else self.score_distributions.histograms
for score_name in self.summaries.keys():
layout.add_row(
create_judge_score_summary_table(
score_name=score_name,
histogram=self.score_distributions.histograms[score_name],
histogram=histograms.get(score_name, MissingValue.CALCULATION_FAILED),
summary=self.summaries[score_name].summary,
)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from rich.table import Column, Table
from rich.text import Text

from data_designer.config.analysis.column_statistics import MissingValue
from data_designer.config.analysis.utils.errors import AnalysisReportError
from data_designer.config.column_types import (
DataDesignerColumnType,
Expand Down Expand Up @@ -163,15 +164,20 @@ def generate_analysis_report(

def create_judge_score_summary_table(
score_name: str,
histogram: CategoricalHistogramData,
histogram: CategoricalHistogramData | MissingValue,
summary: str,
accent_style: str = ACCENT_STYLE,
summary_border_style: str = "dim",
) -> Table:
layout = Table.grid(Column(), Column(), expand=True, padding=(0, 2))

histogram_data = (
{}
if isinstance(histogram, MissingValue)
else {str(s): c for s, c in zip(histogram.categories, histogram.counts)}
)
histogram_table = create_rich_histogram_table(
{str(s): c for s, c in zip(histogram.categories, histogram.counts)},
histogram_data,
("score", "count"),
name_style=HIST_NAME_STYLE,
value_style=HIST_VALUE_STYLE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -262,11 +262,14 @@ def create_rich_histogram_table(
table.add_column(column_names[0], justify="right", style=name_style)
table.add_column(column_names[1], justify="left", style=value_style)

max_count = max(data.values())
max_count = max(data.values(), default=0)
for name, value in data.items():
bar = "" if max_count <= 0 else "█" * int((value / max_count) * 20)
table.add_row(str(name), f"{bar} {value:.1f}")

if not data:
table.add_row("[dim]no data[/dim]", "")

return table


Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,57 @@
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

from copy import deepcopy
from pathlib import Path
from unittest.mock import patch

import pytest

from data_designer.config.analysis.column_statistics import GeneralColumnStatistics, MissingValue
from data_designer.config.analysis.dataset_profiler import DatasetProfilerResults
from data_designer.config.utils.constants import EPSILON

_ISSUE_DOCUMENT = {
"num_records": 1,
"target_num_records": 1,
"column_statistics": [
{
"column_type": "general",
"column_name": "text",
"num_records": 1,
"num_null": 0,
"num_unique": 1,
"pyarrow_dtype": "string",
"simple_dtype": "str",
}
],
"column_profiles": [
{
"column_name": "quality",
"summaries": {"helpfulness": {"score_name": "helpfulness", "summary": "ok", "score_samples": []}},
"score_distributions": {
"scores": {"helpfulness": [5]},
"reasoning": {"helpfulness": ["ok"]},
"distribution_types": {"helpfulness": "categorical"},
"distributions": {"helpfulness": "--"},
"histograms": {"helpfulness": {"categories": [5], "counts": [1]}},
},
}
],
}

_DISTS = _ISSUE_DOCUMENT["column_profiles"][0]["score_distributions"]


def _dists(histograms: dict) -> dict:
return {**_DISTS, "histograms": histograms}


def _judge_profile_document(score_distributions: object) -> dict:
document = deepcopy(_ISSUE_DOCUMENT)
document["column_profiles"][0]["score_distributions"] = score_distributions
return document


def test_dataset_profiler_results_creation(sample_dataset_profiler_results):
"""Test that DatasetProfilerResults can be created with valid data."""
Expand Down Expand Up @@ -158,3 +202,24 @@ def test_dataset_profiler_results_from_dict():
assert result.target_num_records == 200
assert len(result.column_statistics) == 1
assert result.column_statistics[0].column_name == "test_col"


@pytest.mark.parametrize(
"score_distributions",
[
_dists({"helpfulness": {"categories": [], "counts": []}}),
_dists({"helpfulness": "--"}),
"--",
_dists({}),
_DISTS,
],
ids=["empty", "missing-value", "no-distributions", "no-histogram", "populated"],
)
def test_to_report_renders_degenerate_judge_histograms(score_distributions: object, tmp_path: Path) -> None:
"""Test that to_report renders judge profiles whose histogram data is empty or missing."""
results = DatasetProfilerResults.model_validate(_judge_profile_document(score_distributions))
report = tmp_path / "report.html"

results.to_report(report)

assert report.stat().st_size > 0
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
WithRecordSamplerMixin,
apply_html_post_processing,
convert_to_row_element,
create_rich_histogram_table,
display_sample_record,
get_truncated_list_as_string,
mask_api_key,
Expand Down Expand Up @@ -336,3 +337,17 @@ def __init__(self, dataset: pd.DataFrame, config_builder: DataDesignerConfigBuil

with pytest.raises(DatasetSampleDisplayError, match="out of bounds"):
results.display_sample_record(index=999)


@pytest.mark.parametrize(
("data", "expected_rows", "expected_bars"),
[({}, 1, [""]), ({"a": 0, "b": 0}, 2, ["", ""]), ({"a": 1, "b": 3}, 2, ["\u2588" * 6, "\u2588" * 20])],
ids=["empty", "all-zero", "populated"],
)
def test_create_rich_histogram_table_handles_empty_and_zero_counts(
data: dict[str, int], expected_rows: int, expected_bars: list[str]
) -> None:
"""Test that histogram rendering survives an empty mapping and all-zero counts."""
table = create_rich_histogram_table(data, ("score", "count"))
assert table.row_count == expected_rows
assert [str(cell).split(" ")[0] for cell in table.columns[1].cells] == expected_bars
Loading