kdiagram.plot.anomaly.plot_cas_layers

kdiagram.plot.anomaly.plot_cas_layers(df, actual_col, q_low_col, q_up_col, *, sort_by=None, window_size=21, title=None, figsize=(11.0, 6.5), show_severity=True, show_density=True, band_alpha=0.18, anom_alpha=0.85, base_alpha=0.35, cmap='inferno', mark_size=36, show_grid=True, grid_props=None, lw=1.4, ax=None, savefig=None, **kwargs)[source]

Visualizes anomaly severity in layered Cartesian coordinates.

This function creates a highly informative, non-polar diagnostic plot that visualizes a forecast’s prediction interval, the true values, and the calculated anomaly characteristics in layered panels. It is particularly effective for sequential data like time series.

Parameters:
dfpd.DataFrame

The input DataFrame containing the data.

actual_colstr

Name of the column containing the true observed values.

q_low_colstr

Name of the column for the lower bound of the prediction interval.

q_up_colstr

Name of the column for the upper bound of the prediction interval.

sort_bystr or array_like, optional

The feature used to order points along the x-axis. Can be a column name (e.g., a datetime column) or an external array. If None, the DataFrame’s index is used.

window_sizeint, default=21

The size of the moving window used to calculate the local anomaly density and severity.

titlestr, optional

A custom title for the plot.

figsizetuple of (float, float), default=(11.0, 6.5)

The figure size in inches.

show_severitybool, default=True

If True, a second panel is added below the main plot to visualize the per-sample severity scores.

show_densitybool, default=True

If True and show_severity is also True, the local density line is overlaid in the bottom panel.

band_alphafloat, default=0.18

Transparency of the shaded prediction interval band.

anom_alphafloat, default=0.85

Transparency of the anomaly markers.

cmapstr, default=’inferno’

The colormap for coloring anomaly markers and severity bars based on their severity score.

mark_sizeint, default=36

The size of the anomaly markers (^ and v).

show_gridbool, default=True

If True, displays grid lines on the axes.

grid_propsdict, optional

Custom keyword arguments to style the grid.

lwfloat, default=1.4

The base line width for plotted lines.

axmatplotlib.axes.Axes, optional

An existing Cartesian axes for the main plot. Note that the second panel (ax2) will be created new.

savefigstr, optional

The file path to save the plot.

Returns:
axmatplotlib.axes.Axes

The Axes object for the main plot.

(ax, ax2)tuple of (Axes, Axes)

A tuple of both axes is returned if show_severity is True.

None

If the data is empty after handling NaNs.

Parameters:
Return type:

Axes | tuple[Axes, Axes] | None

See also

clustered_anomaly_severity

The underlying metric function.

plot_glyphs

A polar alternative for visualizing anomalies.

Notes

This plot decomposes the CAS diagnostic into layers, providing a clear, sequential view of model performance.

Top Panel (Forecast and Anomalies):

  • A shaded gray area shows the prediction interval (q_low_col to q_up_col).

  • A dark line shows the true values (actual_col).

  • Anomalies are marked with colored triangles ( for over-predictions, for under-predictions). The color intensity of the marker corresponds to its severity score.

Bottom Panel (Severity Breakdown):

  • Vertical bars show the per-sample severity score, colored consistently with the markers above.

  • An optional black line shows the local anomaly density, highlighting the “hotspot” regions that contribute to high severity scores.

References

Examples

>>> import numpy as np
>>> import pandas as pd
>>> from kdiagram.plot.anomaly import plot_cas_layers
>>>
>>> # Simulate data with a failure hotspot in the middle
>>> np.random.seed(0)
>>> n_samples = 400
>>> x_axis = np.arange(n_samples)
>>> y_true = 20 * np.sin(x_axis * np.pi / 100)
>>> y_qlow = y_true - 10
>>> y_qup = y_true + 10
>>> # Introduce a cluster of severe failures
>>> y_true[180:220] += np.random.uniform(12, 20, 40)
>>>
>>> df = pd.DataFrame({
...     "x": x_axis, "actual": y_true,
...     "q10": y_qlow, "q90": y_qup
... })
>>>
>>> axes = plot_cas_layers(
...     df,
...     actual_col="actual",
...     q_low_col="q10",
...     q_up_col="q90",
...     sort_by="x",
...     title="Layered CAS Diagnostic Profile"
... )