Skip to content

complexity

Full name: tenets.viz.complexity

complexity

Complexity visualization module.

This module provides visualization capabilities for complexity metrics, including cyclomatic complexity, cognitive complexity, and other complexity-related visualizations.

Classes

ComplexityVisualizer

Python
ComplexityVisualizer(chart_config: Optional[ChartConfig] = None, display_config: Optional[DisplayConfig] = None)

Bases: BaseVisualizer

Visualizer for complexity metrics.

Creates visualizations for complexity analysis results including distribution charts, heatmaps, and trend analysis.

Initialize complexity visualizer.

PARAMETERDESCRIPTION
chart_config

Chart configuration

TYPE:Optional[ChartConfig]DEFAULT:None

display_config

Display configuration

TYPE:Optional[DisplayConfig]DEFAULT:None

Source code in tenets/viz/complexity.py
Python
def __init__(
    self,
    chart_config: Optional[ChartConfig] = None,
    display_config: Optional[DisplayConfig] = None,
):
    """Initialize complexity visualizer.

    Args:
        chart_config: Chart configuration
        display_config: Display configuration
    """
    super().__init__(chart_config, display_config)
    self.terminal_display = TerminalDisplay(display_config)
Functions
create_distribution_chart
Python
create_distribution_chart(complexity_data: Dict[str, Any], chart_type: ChartType = ChartType.BAR) -> Dict[str, Any]

Create complexity distribution chart.

PARAMETERDESCRIPTION
complexity_data

Complexity analysis data

TYPE:Dict[str, Any]

chart_type

Type of chart to create

TYPE:ChartTypeDEFAULT:BAR

RETURNSDESCRIPTION
Dict[str, Any]

Dict[str, Any]: Chart configuration

Source code in tenets/viz/complexity.py
Python
def create_distribution_chart(
    self, complexity_data: Dict[str, Any], chart_type: ChartType = ChartType.BAR
) -> Dict[str, Any]:
    """Create complexity distribution chart.

    Args:
        complexity_data: Complexity analysis data
        chart_type: Type of chart to create

    Returns:
        Dict[str, Any]: Chart configuration
    """
    distribution = complexity_data.get("distribution", {})

    # Try alternate key
    if not distribution:
        distribution = complexity_data.get("complexity_distribution", {})

    # Default distribution if not provided
    if not distribution:
        distribution = {
            "low": complexity_data.get("low_complexity_count", 0),
            "medium": complexity_data.get("medium_complexity_count", 0),
            "high": complexity_data.get("high_complexity_count", 0),
            "very_high": complexity_data.get("very_high_complexity_count", 0),
        }

    # Handle different key formats
    labels = ["Low (1-5)", "Medium (6-10)", "High (11-20)", "Very High (>20)"]
    values = []

    # Check for formatted keys first
    if "simple (1-5)" in distribution or "Low (1-5)" in distribution:
        # Already formatted keys
        for label in labels:
            found = False
            for key in distribution:
                if (
                    (
                        "Low" in label
                        and ("simple" in key.lower() or "low" in key.lower() or "1-5" in key)
                    )
                    or (
                        "Medium" in label
                        and (
                            "moderate" in key.lower()
                            or "medium" in key.lower()
                            or "6-10" in key
                        )
                    )
                    or (
                        "High" in label
                        and "Very" not in label
                        and (
                            ("complex" in key.lower() and "very" not in key.lower())
                            or "high" in key.lower()
                            or "11-20" in key
                        )
                    )
                    or (
                        "Very High" in label
                        and ("very" in key.lower() or "21" in key or ">20" in key)
                    )
                ):
                    values.append(distribution[key])
                    found = True
                    break
            if not found:
                values.append(0)
    else:
        # Simple keys
        values = [
            distribution.get("low", 0) + distribution.get("simple", 0),
            distribution.get("medium", 0) + distribution.get("moderate", 0),
            distribution.get("high", 0) + distribution.get("complex", 0),
            distribution.get("very_high", 0) + distribution.get("very_complex", 0),
        ]

    # Use severity colors for complexity levels
    colors = [
        ColorPalette.HEALTH["excellent"],
        ColorPalette.HEALTH["good"],
        ColorPalette.HEALTH["fair"],
        ColorPalette.HEALTH["critical"],
    ]

    config = ChartConfig(type=chart_type, title="Complexity Distribution", colors=colors)

    return self.create_chart(chart_type, {"labels": labels, "values": values}, config)
create_top_complex_chart
Python
create_top_complex_chart(complex_items: List[Dict[str, Any]], limit: int = 10) -> Dict[str, Any]

Create chart of top complex items.

PARAMETERDESCRIPTION
complex_items

List of complex items with name and complexity

TYPE:List[Dict[str, Any]]

limit

Maximum items to show

TYPE:intDEFAULT:10

RETURNSDESCRIPTION
Dict[str, Any]

Dict[str, Any]: Chart configuration

Source code in tenets/viz/complexity.py
Python
def create_top_complex_chart(
    self, complex_items: List[Dict[str, Any]], limit: int = 10
) -> Dict[str, Any]:
    """Create chart of top complex items.

    Args:
        complex_items: List of complex items with name and complexity
        limit: Maximum items to show

    Returns:
        Dict[str, Any]: Chart configuration
    """
    # Sort and limit items
    sorted_items = sorted(complex_items, key=lambda x: x.get("complexity", 0), reverse=True)[
        :limit
    ]

    labels = []
    values = []
    colors = []

    for item in sorted_items:
        name = item.get("name", "Unknown")
        # Truncate long names
        if len(name) > 30:
            name = name[:27] + "..."
        labels.append(name)

        complexity = item.get("complexity", 0)
        values.append(complexity)

        # Color based on complexity level
        if complexity > 20:
            colors.append(ColorPalette.SEVERITY["critical"])
        elif complexity > 10:
            colors.append(ColorPalette.SEVERITY["high"])
        elif complexity > 5:
            colors.append(ColorPalette.SEVERITY["medium"])
        else:
            colors.append(ColorPalette.SEVERITY["low"])

    config = ChartConfig(
        type=ChartType.HORIZONTAL_BAR,
        title=f"Top {len(sorted_items)} Most Complex Functions",
        colors=colors,
    )

    return self.create_chart(
        ChartType.HORIZONTAL_BAR, {"labels": labels, "values": values}, config
    )
create_complexity_heatmap
Python
create_complexity_heatmap(file_complexities: Dict[str, List[int]], max_functions: int = 50) -> Dict[str, Any]

Create complexity heatmap for files.

PARAMETERDESCRIPTION
file_complexities

Dictionary of file paths to complexity values

TYPE:Dict[str, List[int]]

max_functions

Maximum functions per file to show

TYPE:intDEFAULT:50

RETURNSDESCRIPTION
Dict[str, Any]

Dict[str, Any]: Heatmap configuration

Source code in tenets/viz/complexity.py
Python
def create_complexity_heatmap(
    self, file_complexities: Dict[str, List[int]], max_functions: int = 50
) -> Dict[str, Any]:
    """Create complexity heatmap for files.

    Args:
        file_complexities: Dictionary of file paths to complexity values
        max_functions: Maximum functions per file to show

    Returns:
        Dict[str, Any]: Heatmap configuration
    """
    # Prepare matrix data
    file_names = []
    matrix = []

    for file_path, complexities in file_complexities.items():
        # Extract filename from path
        file_name = file_path.split("/")[-1]
        if len(file_name) > 20:
            file_name = file_name[:17] + "..."
        file_names.append(file_name)

        # Pad or truncate complexity list
        row = complexities[:max_functions]
        if len(row) < max_functions:
            row.extend([0] * (max_functions - len(row)))
        matrix.append(row)

    # Create function labels
    function_labels = [f"F{i + 1}" for i in range(max_functions)]

    config = ChartConfig(type=ChartType.HEATMAP, title="Complexity Heatmap (Files × Functions)")

    return self.create_chart(
        ChartType.HEATMAP,
        {"matrix": matrix, "x_labels": function_labels, "y_labels": file_names},
        config,
    )
create_trend_chart
Python
create_trend_chart(trend_data: List[Dict[str, Any]]) -> Dict[str, Any]

Create complexity trend chart over time.

PARAMETERDESCRIPTION
trend_data

List of data points with date and metrics

TYPE:List[Dict[str, Any]]

RETURNSDESCRIPTION
Dict[str, Any]

Dict[str, Any]: Line chart configuration

Source code in tenets/viz/complexity.py
Python
def create_trend_chart(self, trend_data: List[Dict[str, Any]]) -> Dict[str, Any]:
    """Create complexity trend chart over time.

    Args:
        trend_data: List of data points with date and metrics

    Returns:
        Dict[str, Any]: Line chart configuration
    """
    if not trend_data:
        return {}

    labels = []
    avg_complexity = []
    max_complexity = []
    total_complex = []

    for point in trend_data:
        labels.append(point.get("date", ""))
        avg_complexity.append(point.get("avg_complexity", 0))
        max_complexity.append(point.get("max_complexity", 0))
        total_complex.append(point.get("complex_functions", 0))

    datasets = [
        {
            "label": "Average Complexity",
            "data": avg_complexity,
            "borderColor": ColorPalette.DEFAULT[0],
            "fill": False,
        },
        {
            "label": "Max Complexity",
            "data": max_complexity,
            "borderColor": ColorPalette.SEVERITY["high"],
            "fill": False,
        },
    ]

    config = ChartConfig(type=ChartType.LINE, title="Complexity Trend Over Time")

    return self.create_chart(ChartType.LINE, {"labels": labels, "datasets": datasets}, config)
create_comparison_chart
Python
create_comparison_chart(current_data: Dict[str, Any], baseline_data: Dict[str, Any]) -> Dict[str, Any]

Create comparison chart between current and baseline.

PARAMETERDESCRIPTION
current_data

Current complexity metrics

TYPE:Dict[str, Any]

baseline_data

Baseline complexity metrics

TYPE:Dict[str, Any]

RETURNSDESCRIPTION
Dict[str, Any]

Dict[str, Any]: Grouped bar chart configuration

Source code in tenets/viz/complexity.py
Python
def create_comparison_chart(
    self, current_data: Dict[str, Any], baseline_data: Dict[str, Any]
) -> Dict[str, Any]:
    """Create comparison chart between current and baseline.

    Args:
        current_data: Current complexity metrics
        baseline_data: Baseline complexity metrics

    Returns:
        Dict[str, Any]: Grouped bar chart configuration
    """
    metrics = ["avg_complexity", "max_complexity", "complex_functions"]
    labels = ["Average", "Maximum", "Complex Count"]

    current_values = [current_data.get(m, 0) for m in metrics]
    baseline_values = [baseline_data.get(m, 0) for m in metrics]

    datasets = [
        {
            "label": "Current",
            "data": current_values,
            "backgroundColor": ColorPalette.DEFAULT[0],
        },
        {
            "label": "Baseline",
            "data": baseline_values,
            "backgroundColor": ColorPalette.DEFAULT[1],
        },
    ]

    config = ChartConfig(type=ChartType.BAR, title="Complexity Comparison")

    return {
        "type": "bar",
        "data": {"labels": labels, "datasets": datasets},
        "options": self._get_chart_options(config),
    }
display_terminal
Python
display_terminal(complexity_data: Dict[str, Any], show_details: bool = True) -> None

Display complexity analysis in terminal.

PARAMETERDESCRIPTION
complexity_data

Complexity analysis data

TYPE:Dict[str, Any]

show_details

Whether to show detailed breakdown

TYPE:boolDEFAULT:True

Source code in tenets/viz/complexity.py
Python
def display_terminal(self, complexity_data: Dict[str, Any], show_details: bool = True) -> None:
    """Display complexity analysis in terminal.

    Args:
        complexity_data: Complexity analysis data
        show_details: Whether to show detailed breakdown
    """
    # Display header
    self.terminal_display.display_header("Complexity Analysis", style="double")

    # Display summary metrics
    summary_data = {
        "Average Complexity": self.format_number(
            complexity_data.get("avg_complexity", 0), precision=2
        ),
        "Maximum Complexity": complexity_data.get("max_complexity", 0),
        "Complex Functions": complexity_data.get("complex_functions", 0),
        "Total Functions": complexity_data.get("total_functions", 0),
    }

    self.terminal_display.display_metrics(summary_data, title="Summary")

    # Display distribution
    if "distribution" in complexity_data:
        self.terminal_display.display_distribution(
            complexity_data["distribution"],
            title="Complexity Distribution",
            labels=["Low", "Medium", "High", "Very High"],
        )

    # Display top complex functions
    if show_details and "complex_items" in complexity_data:
        headers = ["Function", "File", "Complexity", "Risk"]
        rows = []

        for item in complexity_data["complex_items"][:10]:
            risk = self._get_risk_level(item.get("complexity", 0))
            rows.append(
                [
                    item.get("name", "Unknown"),
                    self._truncate_path(item.get("file", "")),
                    str(item.get("complexity", 0)),
                    self.terminal_display.colorize(risk, self._get_risk_color(risk)),
                ]
            )

        self.terminal_display.display_table(headers, rows, title="Top Complex Functions")

    # Display recommendations
    if "recommendations" in complexity_data:
        self.terminal_display.display_list(
            complexity_data["recommendations"], title="Recommendations", style="numbered"
        )
create_radar_chart
Python
create_radar_chart(metrics: Dict[str, float]) -> Dict[str, Any]

Create radar chart for complexity metrics.

PARAMETERDESCRIPTION
metrics

Dictionary of metric names to values

TYPE:Dict[str, float]

RETURNSDESCRIPTION
Dict[str, Any]

Dict[str, Any]: Radar chart configuration

Source code in tenets/viz/complexity.py
Python
def create_radar_chart(self, metrics: Dict[str, float]) -> Dict[str, Any]:
    """Create radar chart for complexity metrics.

    Args:
        metrics: Dictionary of metric names to values

    Returns:
        Dict[str, Any]: Radar chart configuration
    """
    # Normalize metrics to 0-100 scale
    normalized = {}
    max_values = {
        "cyclomatic": 50,
        "cognitive": 100,
        "halstead": 1000,
        "maintainability": 100,
        "lines": 500,
    }

    labels = []
    values = []

    for metric, value in metrics.items():
        labels.append(metric.replace("_", " ").title())
        max_val = max_values.get(metric, 100)
        normalized_value = min(100, (value / max_val) * 100)
        values.append(normalized_value)

    config = ChartConfig(type=ChartType.RADAR, title="Complexity Metrics Radar")

    return self.create_chart(
        ChartType.RADAR,
        {"labels": labels, "datasets": [{"label": "Current", "data": values}]},
        config,
    )