stentfit.stent

Classes

Stent

A stent design, from its STL surface mesh to a fitted spline wireframe.

Module Contents

class stentfit.stent.Stent(stl_file: str, stent_name: str, output_dir: str, n_points: int | None = None, max_display: int = 500000, remove_supports: bool = False, random_seed: int = 0, n_rings: int | None = None, auto_tune: bool = True, pixels_per_strut: int = 10, dilate_px: int = 3, pad_fraction: float = 0.2, tune_time_limit: int = 120, quality_gamma: float = 2.0, ring_halo_frac: float = 0.4)[source]

A stent design, from its STL surface mesh to a fitted spline wireframe.

Holds one stent’s data as it moves through the skeletonisation pipeline. Every stage sets more attributes and writes its own inspectable intermediate (CSV + Plotly HTML) into output_dir, so the run can be checked before committing to an expensive contact simulation.

Run the whole thing with skeletonize(), or drive the three phases separately for the interactive per-ring workflow:

stent = Stent(stl_file, "stent01", "outputs/stent01").skeletonize()

# or, phase by phase, inspecting the plots in between:
stent = Stent(stl_file, "stent01", "outputs/stent01")
stent.skeletonize_2d()        # sample -> rings -> 2D skeleton + checkpoint
stent.edit_and_assemble()     # manual 2D fixes -> assembled flat skeleton
stent.finalize()              # wrap to 3D -> clean graph -> fit splines

After a kernel restart, load() rebuilds the object from the checkpoint in an existing output folder, so the run can pick up at edit_and_assemble() without recomputing anything.

The tuning parameters below are set once on the instance; per-operation parameters stay as arguments on the method that uses them.

Parameters:
  • stl_file – Path to the stent surface mesh (STL).

  • stent_name – Name used to label outputs and plots.

  • output_dir – Folder for all outputs. If it already exists and is non-empty, skeletonize_2d() asks whether to reuse, overwrite, or branch into a versioned folder, and may replace this with the folder actually used.

  • n_points – Number of points to sample from the mesh. None picks the count automatically from the stent size.

  • max_display – Maximum number of points drawn in the HTML views.

  • remove_supports – Drop print-support points during sampling.

  • random_seed – Seed for the point sampling, for repeatable runs.

  • n_rings – Expected ring count. None lets ring detection decide.

  • auto_tune – Search for the best 2D skeletonisation parameters per ring.

  • pixels_per_strut – Raster resolution, in pixels across one strut width.

  • dilate_px – Dilation radius, in pixels, before thinning.

  • pad_fraction – Seam padding added when unrolling a ring to 2D.

  • tune_time_limit – Time budget, in seconds, for the auto-tune search.

  • quality_gamma – Weight of the skeleton quality score during tuning.

  • ring_halo_frac – Z-halo, as a fraction of ring height, so struts reconnect across neighbouring rings.

stl_file
stent_name
output_dir
n_points = None
max_display = 500000
remove_supports = False
random_seed = 0
n_rings = None
auto_tune = True
pixels_per_strut = 10
dilate_px = 3
pad_fraction = 0.2
tune_time_limit = 120
quality_gamma = 2.0
ring_halo_frac = 0.4
mesh = None
stent_df = None
stent_features = None
stent_centerline_direction = None
ring_edges = None
ring_order = None
ring_2d = None
skel_arc = None
skel_z = None
skel_px = None
surf_df = None
skeleton_df = None
skeleton_curves = None
skeleton_splines = None
_versioned_candidates() list[str][source]

List the existing output folders belonging to this stent.

Matches output_dir itself plus any versioned siblings (<name>_v02, _v03, …) in the same parent folder.

Returns:

Sorted folder paths, empty if none exist yet.

_pick_existing_output_dir(action: str = 'use') str[source]

Resolve which of this stent’s versioned output folders to act on.

With no candidate found, returns output_dir unchanged; with exactly one, returns it; with several, prints them and prompts the user to pick one. Used for both reusing and overwriting, so a stent with several versions never has one silently picked for it.

Parameters:

action – Verb used in the prompt, so it reads as the operation actually about to happen — "use" or "overwrite".

Returns:

The resolved folder path to actually act on.

_resolve_output_dir() bool[source]

Settle on the output folder, asking the user if one already exists.

If output_dir exists and is non-empty, offers to reuse it as-is, overwrite (wipe) it, or branch into a new versioned folder (<name>_v02, _v03, …). Reusing loads that folder’s checkpoint straight onto this object instead of recomputing anything. Updates output_dir in place, and creates the folder.

Reusing and overwriting both go through _pick_existing_output_dir(), so when several versions of this stent exist the user is asked which one — an overwrite never silently wipes the unversioned base folder while other versions sit alongside it.

Returns:

True if an existing checkpoint was loaded and the caller should skip recomputation, False to carry on with a fresh run.

save_checkpoint(verbose: bool = True) str[source]

Write the per-ring 2D skeletons and stent geometry to ring_2d.pkl.

Together with the already-saved ring_points.csv, this lets load() rebuild the object after a kernel restart, without rerunning sampling, ring detection, or 2D skeletonisation.

Parameters:

verbose – Print the saved path and ring count.

Returns:

Path to the written ring_2d.pkl.

_load_checkpoint_into(output_dir: str) None[source]

Restore this object’s state from an output folder’s checkpoint.

Parameters:

output_dir – Folder holding ring_2d.pkl and ring_points.csv.

classmethod load(output_dir: str, stl_file: str = '', stent_name: str = '', **kwargs) Stent[source]

Rebuild a Stent from an existing output folder.

Reads back the ring_2d.pkl checkpoint and ring_points.csv, so the pipeline can resume at edit_and_assemble() after a kernel restart. This replaces the procedural pipeline’s state=None resume branch — a reloaded object is the resumed state.

The stent’s own geometry (features, centreline direction, ring edges, surface cloud) all comes from the checkpoint. stl_file only matters if you intend to re-run skeletonize_2d() on the reloaded object.

Parameters:
  • output_dir – Folder holding ring_2d.pkl and ring_points.csv.

  • stl_file – Path to the original STL, if it is needed again.

  • stent_name – Name used to label outputs and plots. Empty uses the output folder’s basename.

  • kwargs – Any Stent tuning parameter, to override the constructor defaults on the reloaded object.

Raises:

FileNotFoundError – If the folder has no checkpoint to load.

Returns:

The reconstructed stent.

skeletonize_2d() Stent[source]

Sample the stent mesh, detect its rings, and 2D-skeletonise each ring.

Loads the STL, samples a point cloud, splits the stent into rings, then runs the 2D skeletonisation per ring. The assembled ring data is checkpointed to disk (save_checkpoint()) so the run can resume after a kernel restart.

If output_dir already exists and is non-empty, the user is asked whether to reuse it as-is, overwrite it, or branch into a new versioned folder. Reusing loads that folder’s checkpoint instead of recomputing anything.

Sets stent_df, stent_features, stent_centerline_direction, ring_edges, ring_2d, and ring_order.

Raises:

FileNotFoundError – If stl_file does not exist.

Returns:

self, so phases can be chained.

edit_and_assemble() Stent[source]

Apply the interactive manual 2D edits, then assemble the flat skeleton.

Runs after skeletonize_2d(). Always prompts once to manually edit any ring, so defects the automatic detector missed can be fixed by hand on the flat ring skeleton, then concatenates every ring into one 2D skeleton.

Sets skel_arc, skel_z, skel_px, and surf_df.

Returns:

self, so phases can be chained.

finalize(prune_tip_frac: float = 0, max_display: int = 500000, random_seed: int = 0) Stent[source]

Wrap the 2D skeleton to 3D, fit splines, and write the final exports.

Runs after edit_and_assemble(). Lifts the assembled 2D skeleton onto the 3D stent surface (which also cleans up the graph: junction blobs contracted to a centroid, short dead-ends pruned), fits a B-spline per curve, then writes the final feature/view exports plus the unrolled-2D and trimesh-3D spline views.

Sets skeleton_df, skeleton_curves, and skeleton_splines.

Parameters:
  • prune_tip_frac – Fraction of each curve tip to prune after wrapping.

  • max_display – Maximum number of points drawn in the HTML views.

  • random_seed – Seed for any subsampling during the 3D wrap.

Returns:

self, so phases can be chained.

skeletonize(prune_tip_frac: float = 0) Stent[source]

Run the full skeletonisation, from the STL mesh to fitted splines.

Chains all three phases: skeletonize_2d(), edit_and_assemble(), then finalize(). Each writes its own intermediates into output_dir.

(skeletonize_2d() is only the first phase, despite the similar name — the verb alone means the whole run, the _2d suffix marks the sub-step.)

Parameters:

prune_tip_frac – Fraction of each curve tip to prune after wrapping.

Returns:

self, holding the 2D skeleton, the 3D skeleton graph, the grouped curves, and the fitted splines.

plot_splines_2d() None[source]

Draw the fitted splines on the unrolled (arc, z) plane.

Writes skeleton_splines_2d.html / .png into output_dir.

plot_splines_trimesh() None[source]

Draw the fitted splines as 3D tubes with trimesh.

Writes skeleton_splines_trimesh.html and skeleton_splines.glb into output_dir.

__repr__() str[source]
Returns:

A short summary of how far this stent has been processed.