Skip to content

FlexReg: build a registration patch on an intraoral arch and register on it - #23

Open
Jules-GP wants to merge 13 commits into
mainfrom
feat/flexreg
Open

FlexReg: build a registration patch on an intraoral arch and register on it#23
Jules-GP wants to merge 13 commits into
mainfrom
feat/flexreg

Conversation

@Jules-GP

Copy link
Copy Markdown
Collaborator

Ports FlexReg from SlicerAutomatedDentalTools. Two arches are aligned on a
REGION the clinician chooses rather than on the whole mesh: teeth move between
timepoints and the palate does not, so registering on everything drags the
result toward whatever moved most.

One tool, not several

The dependency test says so. Every engine here imports the same set - torch,
vtk, numpy, SimpleITK - and none needs pytorch3d or monai, so nothing
forces one pin onto another.

What moved, and what did not

upstream type here
butterfly mode="Patch"
icp mode="Register", patch="Palate (butterfly)"
icp_mgl mode="Register", patch="Mucogingival line"
curve not ported: its input is a polyline drawn in the 3D view
delete not ported: array bookkeeping, no computation

The two left behind are deliberate. curve takes the stroke itself, so there is
no form of it without a Slicer scene, and a mesh crossing the network per stroke
is slower than the local pass it replaces. delete renames Butterfly<n+1>
down over Butterfly<n>; a round trip costs more than doing it.

The GPU is not optional for the patch: upstream's propagation calls .cuda()
with no availability test and no device argument, which is why the module ships
191 lines of install_pytorch.py to get torch into Slicer on a clinician's
laptop. Running it server-side is the point.

Defects fixed in the port

  • Two undefined names on a live path. ApplyTransform dispatched on type
    and called TransformDict and TransformList, neither of which exists in
    this module - the file was copied from AREG_IOS without them. Both branches
    raised NameError, and it never showed because the one caller passes a
    surface. Found by pyflakes, not by importing.
  • A .stl was silently empty. Upstream read everything through
    vtkPolyDataReader, so a .stl came back with no points and failed much
    later without naming the file. The reader is chosen by extension, and an empty
    result is refused with the file's name.
  • The coordinate convention leaked. A .vtk on disk is LPS and Slicer works
    in RAS; upstream flipped on read and never flipped back, so the file it wrote
    was RAS. Invisible while both ends are Slicer, wrong the moment anything else
    reads the result. The flip is applied both ways now.
  • A missing tooth killed the run. ToothNoExist reached the CLI's top
    level; it names a tooth the caller chose, so it is refused by name.
  • A cohort is one call. Upstream took one file. A folder is walked, sorted,
    and one unusable surface is reported per patient instead of losing the batch.

Verified

Real labelled arch, 294,260 points: patch built in 3.4s, 54,030 points in it.
Registering that surface onto itself returns the identity exactly - maximum
deviation 0.00e+00 on both rotation and translation.

Run directly in its venv and again through POST /run/FlexReg, then diffed:
coordinates and all three point arrays bit-identical, 0.000e+00 mm.

16 unit tests, no GPU, no network.

Copilot AI lite review requested due to automatic review settings August 19, 2026 21:26

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants