fixed plots

This commit is contained in:
Jan Kowalczyk
2025-10-21 19:04:19 +02:00
parent 8f983b890f
commit 7b5accb6c5
25 changed files with 1917 additions and 165 deletions

View File

@@ -1,6 +1,6 @@
{ pkgs, ... }:
let
native_dependencies = with pkgs.python312Packages; [
native_dependencies = with pkgs.python311Packages; [
torch-bin
torchvision-bin
aggdraw # for visualtorch
@@ -16,7 +16,7 @@ in
packages = native_dependencies ++ tools;
languages.python = {
enable = true;
package = pkgs.python312;
package = pkgs.python311;
uv = {
enable = true;
sync.enable = true;

View File

@@ -12,7 +12,7 @@ import numpy as np
import polars as pl
# CHANGE THIS IMPORT IF YOUR LOADER MODULE IS NAMED DIFFERENTLY
from plot_scripts.load_results import load_pretraining_results_dataframe
from load_results import load_pretraining_results_dataframe
# ----------------------------
# Config
@@ -78,8 +78,8 @@ def build_arch_curves_from_df(
"overall": (dims, means, stds),
} }
"""
if "split" not in df.columns:
raise ValueError("Expected 'split' column in AE dataframe.")
# if "split" not in df.columns:
# raise ValueError("Expected 'split' column in AE dataframe.")
if "scores" not in df.columns:
raise ValueError("Expected 'scores' column in AE dataframe.")
if "network" not in df.columns or "latent_dim" not in df.columns:
@@ -88,7 +88,7 @@ def build_arch_curves_from_df(
raise ValueError(f"Expected '{label_field}' column in AE dataframe.")
# Keep only test split
df = df.filter(pl.col("split") == "test")
# df = df.filter(pl.col("split") == "test")
groups: dict[tuple[str, int], dict[str, list[float]]] = {}
@@ -201,7 +201,7 @@ def plot_multi_loss_curve(arch_results, title, output_path, colors=None):
plt.xlabel("Latent Dimensionality")
plt.ylabel("Test Loss")
plt.title(title)
# plt.title(title)
plt.legend()
plt.grid(True, alpha=0.3)
plt.xticks(all_dims)

View File

@@ -171,28 +171,28 @@ def plot_combined_timeline(
range(num_bins), near_sensor_binned, color=color, linestyle="--", alpha=0.6
)
# Add vertical lines for manually labeled frames if available
if all_paths[i].with_suffix(".npy").name in manually_labeled_anomaly_frames:
begin_frame, end_frame = manually_labeled_anomaly_frames[
all_paths[i].with_suffix(".npy").name
]
# Convert frame numbers to normalized timeline positions
begin_pos = (begin_frame / exp_len) * (num_bins - 1)
end_pos = (end_frame / exp_len) * (num_bins - 1)
# # Add vertical lines for manually labeled frames if available
# if all_paths[i].with_suffix(".npy").name in manually_labeled_anomaly_frames:
# begin_frame, end_frame = manually_labeled_anomaly_frames[
# all_paths[i].with_suffix(".npy").name
# ]
# # Convert frame numbers to normalized timeline positions
# begin_pos = (begin_frame / exp_len) * (num_bins - 1)
# end_pos = (end_frame / exp_len) * (num_bins - 1)
# Add vertical lines with matching color and loose dotting
ax1.axvline(
x=begin_pos,
color=color,
linestyle=":",
alpha=0.6,
)
ax1.axvline(
x=end_pos,
color=color,
linestyle=":",
alpha=0.6,
)
# # Add vertical lines with matching color and loose dotting
# ax1.axvline(
# x=begin_pos,
# color=color,
# linestyle=":",
# alpha=0.6,
# )
# ax1.axvline(
# x=end_pos,
# color=color,
# linestyle=":",
# alpha=0.6,
# )
# Customize axes
ax1.set_xlabel("Normalized Timeline")
@@ -202,7 +202,7 @@ def plot_combined_timeline(
ax1.set_ylabel("Missing Points (%)")
ax2.set_ylabel("Points with <0.5m Range (%)")
plt.title(title)
# plt.title(title)
# Create legends without fixed positions
# First get all lines and labels for experiments
@@ -221,7 +221,8 @@ def plot_combined_timeline(
)
# Create single legend in top right corner with consistent margins
fig.legend(all_handles, all_labels, loc="upper right", borderaxespad=4.8)
# fig.legend(all_handles, all_labels, loc="upper right", borderaxespad=2.8)
fig.legend(all_handles, all_labels, bbox_to_anchor=(0.95, 0.99))
plt.grid(True, alpha=0.3)

View File

@@ -122,8 +122,8 @@ def plot_data_points_pie(normal_experiment_frames, anomaly_experiment_frames):
# prepare data for pie chart
labels = [
"Normal Lidar Frames\nNon-Degraded Pointclouds",
"Anomalous Lidar Frames\nDegraded Pointclouds",
"Normal Lidar Frames\nNon-Degraded Point Clouds",
"Anomalous Lidar Frames\nDegraded Point Clouds",
]
sizes = [total_normal_frames, total_anomaly_frames]
explode = (0.1, 0) # explode the normal slice
@@ -150,9 +150,9 @@ def plot_data_points_pie(normal_experiment_frames, anomaly_experiment_frames):
va="center",
color="black",
)
plt.title(
"Distribution of Normal and Anomalous\nPointclouds in all Experiments (Lidar Frames)"
)
# plt.title(
# "Distribution of Normal and Anomalous\nPointclouds in all Experiments (Lidar Frames)"
# )
plt.tight_layout()
# save the plot

View File

@@ -5,7 +5,6 @@ from pathlib import Path
import matplotlib.pyplot as plt
import numpy as np
from pointcloudset import Dataset
# define data path containing the bag files
all_data_path = Path("/home/fedex/mt/data/subter")
@@ -82,7 +81,7 @@ def plot_data_points(normal_experiment_paths, anomaly_experiment_paths, title):
plt.figure(figsize=(10, 5))
plt.hist(missing_points_normal, bins=100, alpha=0.5, label="Normal Experiments")
plt.hist(missing_points_anomaly, bins=100, alpha=0.5, label="Anomaly Experiments")
plt.title(title)
# plt.title(title)
plt.xlabel("Number of Missing Points")
plt.ylabel("Number of Pointclouds")
plt.legend()
@@ -109,7 +108,7 @@ def plot_data_points(normal_experiment_paths, anomaly_experiment_paths, title):
label="Anomaly Experiments",
orientation="horizontal",
)
plt.title(title)
# plt.title(title)
plt.xlabel("Number of Pointclouds")
plt.ylabel("Number of Missing Points")
plt.legend()
@@ -142,7 +141,7 @@ def plot_data_points(normal_experiment_paths, anomaly_experiment_paths, title):
label="Anomaly Experiments",
density=True,
)
plt.title(title)
# plt.title(title)
plt.xlabel("Number of Missing Points")
plt.ylabel("Density")
plt.legend()
@@ -169,7 +168,7 @@ def plot_data_points(normal_experiment_paths, anomaly_experiment_paths, title):
label="Anomaly Experiments (With Artifical Smoke)",
density=True,
)
plt.title(title)
# plt.title(title)
plt.xlabel("Percentage of Missing Lidar Measurements")
plt.ylabel("Density")
# display the x axis as percentages
@@ -210,7 +209,7 @@ def plot_data_points(normal_experiment_paths, anomaly_experiment_paths, title):
alpha=0.5,
label="Anomaly Experiments",
)
plt.title(title)
# plt.title(title)
plt.xlabel("Number of Missing Points")
plt.ylabel("Normalized Density")
plt.legend()

View File

@@ -5,7 +5,6 @@ from pathlib import Path
import matplotlib.pyplot as plt
import numpy as np
from pointcloudset import Dataset
# define data path containing the bag files
all_data_path = Path("/home/fedex/mt/data/subter")
@@ -164,7 +163,7 @@ def plot_data_points(normal_experiment_paths, anomaly_experiment_paths, title):
plt.gca().set_yticklabels(
["{:.0f}%".format(y * 100) for y in plt.gca().get_yticks()]
)
plt.title("Particles Closer than 0.5m to the Sensor")
# plt.title("Particles Closer than 0.5m to the Sensor")
plt.ylabel("Percentage of measurements closer than 0.5m")
plt.tight_layout()
plt.savefig(output_datetime_path / f"particles_near_sensor_boxplot_{rt}.png")
@@ -186,7 +185,7 @@ def plot_data_points(normal_experiment_paths, anomaly_experiment_paths, title):
plt.gca().set_yticklabels(
["{:.0f}%".format(y * 100) for y in plt.gca().get_yticks()]
)
plt.title("Particles Closer than 0.5m to the Sensor")
# plt.title("Particles Closer than 0.5m to the Sensor")
plt.ylabel("Percentage of measurements closer than 0.5m")
plt.ylim(0, 0.05)
plt.tight_layout()

View File

@@ -112,18 +112,27 @@ cmap = get_colormap_with_special_missing_color(
args.colormap, args.missing_data_color, args.reverse_colormap
)
# --- Create a figure with 2 vertical subplots ---
# --- Create a figure with 2 vertical subplots and move titles to the left ---
fig, (ax1, ax2) = plt.subplots(nrows=2, ncols=1, figsize=(10, 5))
for ax, frame, title in zip(
# leave extra left margin for the left-side labels
fig.subplots_adjust(left=0.14, hspace=0.05)
for ax, frame, label in zip(
(ax1, ax2),
(frame1, frame2),
(
"Projection of Lidar Frame without Degradation",
"Projection of Lidar Frame with Degradation (Artifical Smoke)",
),
("(a)", "(b)"),
):
im = ax.imshow(frame, cmap=cmap, aspect="auto", vmin=global_vmin, vmax=global_vmax)
ax.set_title(title)
# place the "title" to the left, vertically centered relative to the axes
ax.text(
-0.02, # negative x places text left of the axes (in axes coordinates)
0.5,
label,
transform=ax.transAxes,
va="center",
ha="right",
fontsize=12,
)
ax.axis("off")
# Adjust layout to fit margins for a paper

View File

@@ -260,11 +260,11 @@ def baseline_transform(clean: np.ndarray, other: np.ndarray, mode: str):
def pick_method_series(gdf: pl.DataFrame, label: str) -> Optional[np.ndarray]:
if label == "DeepSAD (LeNet)":
if label == "DeepSAD LeNet":
sel = gdf.filter(
(pl.col("network") == "subter_LeNet") & (pl.col("model") == "deepsad")
)
elif label == "DeepSAD (efficient)":
elif label == "DeepSAD Efficient":
sel = gdf.filter(
(pl.col("network") == "subter_efficient") & (pl.col("model") == "deepsad")
)
@@ -311,8 +311,8 @@ def compare_two_experiments_progress(
include_stats: bool = True,
):
methods = [
"DeepSAD (LeNet)",
"DeepSAD (efficient)",
"DeepSAD LeNet",
"DeepSAD Efficient",
"OCSVM",
"Isolation Forest",
]
@@ -392,8 +392,8 @@ def compare_two_experiments_progress(
axes = axes.ravel()
method_to_axidx = {
"DeepSAD (LeNet)": 0,
"DeepSAD (efficient)": 1,
"DeepSAD LeNet": 0,
"DeepSAD Efficient": 1,
"OCSVM": 2,
"Isolation Forest": 3,
}
@@ -404,6 +404,8 @@ def compare_two_experiments_progress(
if not stats_available:
print("[WARN] One or both stats missing. Subplots will include methods only.")
letters = ["a", "b", "c", "d"]
for label, axidx in method_to_axidx.items():
ax = axes[axidx]
yc = curves_clean.get(label)
@@ -412,7 +414,7 @@ def compare_two_experiments_progress(
ax.text(
0.5, 0.5, "No data", ha="center", va="center", transform=ax.transAxes
)
ax.set_title(label)
ax.set_title(f"({letters[axidx]}) {label}")
ax.grid(True, alpha=0.3)
continue
@@ -435,6 +437,7 @@ def compare_two_experiments_progress(
)
ax.set_ylabel(y_label)
ax.set_title(label)
ax.set_title(f"({letters[axidx]}) {label}")
ax.grid(True, alpha=0.3)
# Right axis #1 (closest to plot): Missing points (%)
@@ -550,11 +553,11 @@ def compare_two_experiments_progress(
for ax in axes:
ax.set_xlabel("Progress through experiment (%)")
fig.suptitle(
f"AD Method vs Stats Inference — progress-normalized\n"
f"Transform: z-score normalized to non-degraded experiment | EMA(α={EMA_ALPHA_METHODS})",
fontsize=14,
)
# fig.suptitle(
# f"AD Method vs Stats Inference — progress-normalized\n"
# f"Transform: z-score normalized to non-degraded experiment | EMA(α={EMA_ALPHA_METHODS})",
# fontsize=14,
# )
fig.tight_layout(rect=[0, 0, 1, 0.99])
out_name = (

View File

@@ -161,7 +161,7 @@ def _ensure_dim_axes(fig_title: str):
fig, axes = plt.subplots(
nrows=4, ncols=2, figsize=(12, 16), constrained_layout=True
)
fig.suptitle(fig_title, fontsize=14)
# fig.suptitle(fig_title, fontsize=14)
axes = axes.ravel()
return fig, axes
@@ -213,11 +213,13 @@ def plot_grid_from_df(
legend_labels = []
have_legend = False
letters = ["a", "b", "c", "d", "e", "f", "g", "h"]
for i, dim in enumerate(LATENT_DIMS):
if i >= 7:
break # last slot reserved for legend
ax = axes[i]
ax.set_title(f"Latent Dim. = {dim}")
ax.set_title(f"({letters[i]}) Latent Dim. = {dim}")
ax.grid(True, alpha=0.3)
if kind == "roc":

View File

@@ -260,9 +260,9 @@ def make_figures_for_dim(
fig_roc, axes = plt.subplots(
nrows=2, ncols=1, figsize=(7, 10), constrained_layout=True
)
fig_roc.suptitle(
f"ROC — {EVALS_LABELS[eval_type]} — Latent Dim.={latent_dim}", fontsize=14
)
# fig_roc.suptitle(
# f"ROC — {EVALS_LABELS[eval_type]} — Latent Dim.={latent_dim}", fontsize=14
# )
_plot_panel(
axes[0],
@@ -272,7 +272,7 @@ def make_figures_for_dim(
latent_dim=latent_dim,
kind="roc",
)
axes[0].set_title("DeepSAD (LeNet) + Baselines")
axes[0].set_title("(a) DeepSAD (LeNet) + Baselines")
_plot_panel(
axes[1],
@@ -282,7 +282,7 @@ def make_figures_for_dim(
latent_dim=latent_dim,
kind="roc",
)
axes[1].set_title("DeepSAD (Efficient) + Baselines")
axes[1].set_title("(b) DeepSAD (Efficient) + Baselines")
out_roc = out_dir / f"roc_{latent_dim}_{eval_type}.png"
fig_roc.savefig(out_roc, dpi=150, bbox_inches="tight")
@@ -292,9 +292,9 @@ def make_figures_for_dim(
fig_prc, axes = plt.subplots(
nrows=2, ncols=1, figsize=(7, 10), constrained_layout=True
)
fig_prc.suptitle(
f"PRC — {EVALS_LABELS[eval_type]} — Latent Dim.={latent_dim}", fontsize=14
)
# fig_prc.suptitle(
# f"PRC — {EVALS_LABELS[eval_type]} — Latent Dim.={latent_dim}", fontsize=14
# )
_plot_panel(
axes[0],
@@ -304,7 +304,7 @@ def make_figures_for_dim(
latent_dim=latent_dim,
kind="prc",
)
axes[0].set_title("DeepSAD (LeNet) + Baselines")
axes[0].set_title("(a)")
_plot_panel(
axes[1],
@@ -314,7 +314,7 @@ def make_figures_for_dim(
latent_dim=latent_dim,
kind="prc",
)
axes[1].set_title("DeepSAD (Efficient) + Baselines")
axes[1].set_title("(b)")
out_prc = out_dir / f"prc_{latent_dim}_{eval_type}.png"
fig_prc.savefig(out_prc, dpi=150, bbox_inches="tight")

View File

@@ -6,6 +6,7 @@ readme = "README.md"
requires-python = ">=3.11.9"
dependencies = [
"pandas>=2.3.2",
"pointcloudset>=0.11.0",
"polars>=1.33.0",
"pyarrow>=21.0.0",
"tabulate>=0.9.0",

1890
tools/uv.lock generated

File diff suppressed because it is too large Load Diff