diff --git a/AutoscoperM/AutoscoperM.py b/AutoscoperM/AutoscoperM.py
index 694f9b4..4e39d16 100644
--- a/AutoscoperM/AutoscoperM.py
+++ b/AutoscoperM/AutoscoperM.py
@@ -441,6 +441,8 @@ def onGeneratePartialVolumes(self):
mainOutputDir = self.ui.mainOutputSelector.currentPath
tiffSubDir = self.ui.tiffSubDir.text
tfmSubDir = self.ui.tfmSubDir.text
+ trackingSubDir = self.ui.trackingSubDir.text
+ modelSubDir = self.ui.modelSubDir.text
segmentationNode = self.ui.pv_SegNodeComboBox.currentNode()
if not self.logic.validateInputs(
volumeNode=volumeNode,
@@ -448,12 +450,18 @@ def onGeneratePartialVolumes(self):
mainOutputDir=mainOutputDir,
volumeSubDir=tiffSubDir,
transformSubDir=tfmSubDir,
+ trackingSubDir=trackingSubDir,
+ modelSubDir=modelSubDir,
):
raise ValueError("Invalid inputs")
return
self.logic.createPathsIfNotExists(
- mainOutputDir, os.path.join(mainOutputDir, tiffSubDir), os.path.join(mainOutputDir, tfmSubDir)
+ mainOutputDir,
+ os.path.join(mainOutputDir, tiffSubDir),
+ os.path.join(mainOutputDir, tfmSubDir),
+ os.path.join(mainOutputDir, trackingSubDir),
+ os.path.join(mainOutputDir, modelSubDir),
)
self.ui.progressBar.setValue(0)
self.ui.progressBar.setMaximum(100)
@@ -463,6 +471,8 @@ def onGeneratePartialVolumes(self):
mainOutputDir,
volumeSubDir=tiffSubDir,
transformSubDir=tfmSubDir,
+ trackingSubDir=trackingSubDir,
+ modelSubDir=modelSubDir,
progressCallback=self.updateProgressBar,
)
slicer.util.messageBox("Success!")
@@ -1013,6 +1023,7 @@ def saveSubVolumesFromSegmentation(
volumeSubDir: str = "Volumes",
transformSubDir: str = "Transforms",
trackingSubDir: str = "Tracking",
+ modelSubDir: str = "Models",
progressCallback: Optional[callable] = None,
) -> bool:
"""
@@ -1065,7 +1076,6 @@ def progressCallback(x):
segmentVolume.DisableModifiedEventOff()
transformFilenameBase = os.path.join(outputDir, transformSubDir, segmentName)
-
origin = segmentVolume.GetOrigin()
IO.writeTFMFile(f"{transformFilenameBase}_t.tfm", [1.0, 1.0, 1.0], origin)
spacing = segmentVolume.GetSpacing()
@@ -1082,6 +1092,10 @@ def progressCallback(x):
dicom2autNode = self.createAndAddDicom2AutTransformNode(origin, pvol2autNode)
dicom2autFilename = os.path.join(outputDir, transformSubDir, f"{segmentVolume.GetName()}-DICOM2AUT.tfm")
slicer.util.exportNode(dicom2autNode, dicom2autFilename)
+
+ stlFilename = os.path.join(outputDir, modelSubDir, f"AUT_{segmentVolume.GetName()}.stl")
+ self.exportSTLFromSegment(segmentationNode, segmentID, stlFilename, dicom2autNode.GetTransformToParent())
+
slicer.mrmlScene.RemoveNode(dicom2autNode)
# Create TRA file
@@ -1122,6 +1136,36 @@ def progressCallback(x):
slicer.app.layoutManager().resetSliceViews()
return True
+ @staticmethod
+ def exportSTLFromSegment(
+ segmentationNode: slicer.vtkMRMLSegmentationNode,
+ segmentID: str,
+ filename: str,
+ transform: Optional[vtk.vtkAbstractTransform] = None,
+ ):
+ """Utility functions for exporting a segment as an STL. Optionally takes a vtk transform."""
+ if not segmentationNode.CreateClosedSurfaceRepresentation():
+ raise ValueError(
+ f"Failed to generate the closed surface representation from segmentation: {segmentationNode.GetName()}"
+ )
+
+ polyData = vtk.vtkPolyData()
+ if not segmentationNode.GetClosedSurfaceRepresentation(segmentID, polyData):
+ raise ValueError(f"Failed to get PolyData for segmentationNode {segmentationNode.GetName()}")
+
+ if transform is not None:
+ transformFilter = vtk.vtkTransformPolyDataFilter()
+ transformFilter.SetInputData(polyData)
+ transformFilter.SetTransform(transform)
+ transformFilter.Update()
+ polyData = transformFilter.GetOutput()
+
+ stlNode = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLModelNode")
+ stlNode.SetAndObservePolyData(polyData)
+
+ slicer.util.exportNode(stlNode, filename)
+ slicer.mrmlScene.RemoveNode(stlNode)
+
@staticmethod
def showVolumeIn3D(volumeNode: slicer.vtkMRMLVolumeNode):
logic = slicer.modules.volumerendering.logic()
diff --git a/AutoscoperM/Resources/UI/AutoscoperM.ui b/AutoscoperM/Resources/UI/AutoscoperM.ui
index 2cc142c..19e9e66 100644
--- a/AutoscoperM/Resources/UI/AutoscoperM.ui
+++ b/AutoscoperM/Resources/UI/AutoscoperM.ui
@@ -17,7 +17,7 @@
-
- 0
+ 1
@@ -205,10 +205,10 @@
true
- false
+ true
- true
+ false
-
@@ -218,83 +218,93 @@
- -
-
+
-
+
+
+ true
+
- Partial Volume Transforms Subdirectory:
+ Delete Temporary VRG Files
+
+
+ true
+
+
+ true
- -
-
+
-
+
- Virtual Radiograph Subdirectory:
+ Only use indices for radiograph filename
- -
-
+
-
+
- Volumes
+ VRG Temp Subdirectory:
- -
-
+
-
+
- VRG Resolution: (width,height)
+ Virtual Radiograph Subdirectory:
- -
-
+
-
+
+
+ true
+
- VRG-Temp
+ Calibration
- -
-
+
-
+
- RadiographImages
+ Tracking Subdirectory:
- -
-
-
- false
-
+
-
+
- Delete Temporary VRG Files
-
-
- true
-
-
- true
+ VRG Resolution: (width,height)
- -
-
+
-
+
- VRG Temp Subdirectory:
+ Transforms
- -
-
-
+
-
+
+
+ Camera Debug Mode
+
+
false
+
+
+ -
+
- Calibration
+ Volumes
- -
-
+
-
+
999999999
@@ -303,15 +313,22 @@
- -
-
+
-
+
- Partial Volume Subdirectory:
+ Partial Volume Transforms Subdirectory:
- -
-
+
-
+
+
+ RadiographImages
+
+
+
+ -
+
999999999
@@ -320,27 +337,38 @@
- -
-
+
-
+
- Transforms
+ VRG-Temp
- -
-
+
-
+
- Camera Debug Mode
+ Partial Volume Subdirectory:
-
- false
+
+
+ -
+
+
+ Model Subdirectory:
- -
-
+
-
+
- Only use indices for radiograph filename
+ Tracking
+
+
+
+ -
+
+
+ Models