Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Antisource/heronaisec/llms.txt

Use this file to discover all available pages before exploring further.

The visualization module produces publication-quality figures that summarise the results of backdoor persistence experiments. It contains no training, evaluation, or attack logic — it consumes a pandas DataFrame of pre-computed metrics and writes a .png file to disk. All plots apply a consistent global style at module import time so that figures are uniformly formatted across an entire experiment without any per-call configuration. Both functions enforce column presence at runtime, raising ValueError with a descriptive message if the expected data is absent.

Global Style Settings

The following matplotlib.rcParams are applied once when src.visualization is first imported. They affect all subsequent Matplotlib figures created in the same Python process.
ParameterValueEffect
figure.figsize(8, 5)Default figure dimensions in inches
figure.dpi300Publication-quality raster resolution
axes.gridTrueHorizontal and vertical grid lines on all axes
axes.spines.topFalseTop spine hidden for a cleaner look
axes.spines.rightFalseRight spine hidden
font.size11Base font size for labels, ticks, and legends
legend.frameonFalseLegend drawn without a bounding box
Because rcParams are global, importing src.visualization will alter the appearance of any other Matplotlib figures created in the same session. If you need to isolate styles, use matplotlib.style.context() around your plotting calls.

Functions

plot_backdoor_persistence()

Plot backdoor persistence across a range of clean fine-tuning ratios. Creates a dual-axis figure: the left y-axis (ax1) tracks Attack Success Rate and Trigger Confidence (both on a [0.0, 1.05] scale), while the right y-axis (ax2 = ax1.twinx()) tracks Clean Accuracy. The x-axis is the clean fine-tuning ratio. The results DataFrame is sorted by "clean_ratio" before plotting, so rows do not need to be pre-sorted. The figure is always saved as .png via output_path.with_suffix(".png") regardless of the suffix provided in output_path. Required columns in results:
  • clean_ratio — the intervention strength (x-axis)
  • attack_success_rate — primary left-axis metric
  • mean_trigger_confidence — secondary left-axis metric
  • clean_accuracy — right-axis metric
results
pd.DataFrame
required
A DataFrame where each row corresponds to one evaluated intervention level. Must contain the four required columns listed above.
output_path
str | Path
required
Destination path for the saved figure. The suffix is always replaced with .png. Parent directories are created automatically if they do not exist.
return
None
Returns None. Raises ValueError if any required column is absent.
The output file extension is always overridden to .png via output_path.with_suffix(".png"). Passing output_path="figure.pdf" will produce figure.png, not a PDF. If you need vector output, convert the saved PNG using an external tool or call plt.savefig() directly after inspecting the source.
Example:
import pandas as pd
from src.visualization import plot_backdoor_persistence

results = pd.DataFrame([
    {"clean_ratio": 0.00, "attack_success_rate": 0.94, "clean_accuracy": 0.91, "mean_trigger_confidence": 0.97},
    {"clean_ratio": 0.10, "attack_success_rate": 0.81, "clean_accuracy": 0.92, "mean_trigger_confidence": 0.88},
    {"clean_ratio": 0.25, "attack_success_rate": 0.63, "clean_accuracy": 0.92, "mean_trigger_confidence": 0.74},
    {"clean_ratio": 0.50, "attack_success_rate": 0.41, "clean_accuracy": 0.93, "mean_trigger_confidence": 0.55},
    {"clean_ratio": 1.00, "attack_success_rate": 0.18, "clean_accuracy": 0.93, "mean_trigger_confidence": 0.29},
])

plot_backdoor_persistence(
    results=results,
    output_path="results/run_01/figures/backdoor_persistence.png",
)
# Saved to: results/run_01/figures/backdoor_persistence.png
Example — handling a missing column:
import pandas as pd
from src.visualization import plot_backdoor_persistence

bad_df = pd.DataFrame([{"clean_ratio": 0.0, "attack_success_rate": 0.9}])

try:
    plot_backdoor_persistence(bad_df, "figures/out.png")
except ValueError as exc:
    print(exc)
# ValueError: Missing columns: {'clean_accuracy', 'mean_trigger_confidence'}

plot_reviewer_intervention()

Highlight the reviewer intervention point on a backdoor persistence curve. Plots Attack Success Rate vs. Clean Fine-Tuning Ratio as a line with circle markers (the same curve as plot_backdoor_persistence()), then overlays a scatter point using ax.scatter with s=100, marker="*", and label="Reviewer Intervention" at the (reviewer_ratio, attack_success_rate) coordinate corresponding to reviewer_ratio. The results DataFrame is sorted by "clean_ratio" before plotting. The figure is saved as .png via output_path.with_suffix(".png") regardless of the suffix provided in output_path. Required columns in results: same as plot_backdoor_persistence()clean_ratio, attack_success_rate, clean_accuracy, mean_trigger_confidence.
results
pd.DataFrame
required
A DataFrame of per-ratio evaluation results. Must contain the four required columns.
reviewer_ratio
float
required
The exact clean_ratio value at which the reviewer intervened. The function filters results for rows where clean_ratio == reviewer_ratio to determine the star marker position. The value must exist in the DataFrame.
output_path
str | Path
required
Destination path for the saved figure. Always saved as .png.
return
None
Returns None. Raises ValueError if any required column is absent.
If reviewer_ratio does not match any value in results["clean_ratio"] exactly (e.g. due to floating-point representation), the star marker will simply not appear. Ensure that the reviewer_ratio passed here is the same float used when constructing the results DataFrame.
Example:
import pandas as pd
from src.visualization import plot_reviewer_intervention

results = pd.DataFrame([
    {"clean_ratio": 0.00, "attack_success_rate": 0.94, "clean_accuracy": 0.91, "mean_trigger_confidence": 0.97},
    {"clean_ratio": 0.25, "attack_success_rate": 0.63, "clean_accuracy": 0.92, "mean_trigger_confidence": 0.74},
    {"clean_ratio": 0.50, "attack_success_rate": 0.41, "clean_accuracy": 0.93, "mean_trigger_confidence": 0.55},
    {"clean_ratio": 1.00, "attack_success_rate": 0.18, "clean_accuracy": 0.93, "mean_trigger_confidence": 0.29},
])

plot_reviewer_intervention(
    results=results,
    reviewer_ratio=0.25,   # star marker placed at (0.25, 0.63)
    output_path="results/run_01/figures/reviewer_intervention.png",
)

Build docs developers (and LLMs) love