This repository serve as a backup for my Maxwell-TD code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

85 lines
3.2 KiB

#!/usr/bin/env python3
import argparse
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from pathlib import Path
def load_unique_faces(wide_csv: str) -> pd.DataFrame:
df = pd.read_csv(wide_csv)
# Keep the first occurrence per face_id (faces may be listed from multiple tets)
df = df.sort_values(["face_id", "tet_id"]).drop_duplicates(subset=["face_id"], keep="first")
return df
def plot_faces(df: pd.DataFrame, out_png: str, view="xy", linewidth=1.5, annotate=True):
# Choose which plane to show
axes = {"xy": ("_x","_y"), "xz": ("_x","_z"), "yz": ("_y","_z")}
if view not in axes:
raise ValueError("view must be one of: xy, xz, yz")
axa, axb = axes[view]
fig, ax = plt.subplots(figsize=(10, 10)) # larger square figure
all_x, all_y = [], []
# Plot each face as a closed triangle
for _, r in df.iterrows():
x = [r["face0"+axa], r["face1"+axa], r["face2"+axa], r["face0"+axa]]
y = [r["face0"+axb], r["face1"+axb], r["face2"+axb], r["face0"+axb]]
ax.plot(x, y, "-k", lw=linewidth)
all_x.extend(x)
all_y.extend(y)
if annotate:
cx = (r["face0"+axa] + r["face1"+axa] + r["face2"+axa]) / 3.0
cy = (r["face0"+axb] + r["face1"+axb] + r["face2"+axb]) / 3.0
ax.annotate(f'{int(r["face_id"])}', (cx, cy),
textcoords="offset points", xytext=(0, 0),
ha="center", va="center", fontsize=8,
bbox=dict(boxstyle="round,pad=0.2", fc="yellow", ec="black", lw=0.5))
# Square bounding box
if all_x and all_y:
min_x, max_x = min(all_x), max(all_x)
min_y, max_y = min(all_y), max(all_y)
span = max(max_x - min_x, max_y - min_y)
cx = 0.5 * (max_x + min_x)
cy = 0.5 * (max_y + min_y)
ax.set_xlim(cx - span/2, cx + span/2)
ax.set_ylim(cy - span/2, cy + span/2)
ax.set_aspect("equal", adjustable="box")
ax.set_xlabel(view[0])
ax.set_ylabel(view[1])
ax.grid(True, ls="--", alpha=0.4)
ax.set_title(f"Faces with face_id annotations ({view}-view)")
# Expand to fill entire figure
plt.subplots_adjust(left=0, right=1, top=1, bottom=0)
out_png = Path(out_png)
out_png.parent.mkdir(parents=True, exist_ok=True)
fig.savefig(out_png, dpi=220, bbox_inches="tight")
plt.close(fig)
print(f"Saved {out_png}")
def main():
ap = argparse.ArgumentParser(description="Plot faces from parsed CUDA debug CSV and annotate face_id.")
ap.add_argument("--wide-csv", required=True, help="Path to *_wide.csv produced by the parser.")
ap.add_argument("--out", default="faces_annotated.png", help="Output PNG path.")
ap.add_argument("--view", choices=["xy","xz","yz"], default="xy", help="Projection plane to plot.")
ap.add_argument("--linewidth", type=float, default=1.5, help="Triangle edge width.")
ap.add_argument("--no-annotate", action="store_true", help="Disable face_id annotations.")
args = ap.parse_args()
df = load_unique_faces(args.wide_csv)
if df.empty:
print("No faces found in CSV.")
return
plot_faces(df, args.out, view=args.view, linewidth=args.linewidth, annotate=not args.no_annotate)
if __name__ == "__main__":
main()