Skip to content

Instantly share code, notes, and snippets.

@smrolfe
Last active November 10, 2021 19:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save smrolfe/f6ea90d9ff59bb306b8127b7342b4f6e to your computer and use it in GitHub Desktop.
Save smrolfe/f6ea90d9ff59bb306b8127b7342b4f6e to your computer and use it in GitHub Desktop.
ExportMorphoJLandmarkFile
import os, glob
import unittest
import vtk, qt, ctk, slicer
from slicer.ScriptedLoadableModule import *
import logging
import numpy as np
#
# ConvertMorphologikaLandmarks
#
class ExportMorphoJLandmarkFile(ScriptedLoadableModule):
"""Uses ScriptedLoadableModule base class, available at:
https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/ScriptedLoadableModule.py
"""
def __init__(self, parent):
ScriptedLoadableModule.__init__(self, parent)
self.parent.title = "ExportMorphoJLandmarkFile"
self.parent.categories = ["User_Specifications"]
self.parent.dependencies = []
self.parent.contributors = ["Steven Lewis (UB), Sara Rolfe (UW)"] # replace with "Firstname Lastname (Organization)"
self.parent.helpText = """
This module parses fcsv landmark files for landmark coordinates and compiles them into a new csv file where each sample name is followed by the x,y or x,y,& z coordinates
for all landmarks tied to the file.
"""
self.parent.helpText += self.getDefaultModuleDocumentationLink()
self.parent.acknowledgementText = """
This module was developed by Steven Lewis with the assistance of Sara Rolfe.
""" # replace with organization, grant and thanks.
class ExportMorphoJLandmarkFileWidget(ScriptedLoadableModuleWidget):
"""Uses ScriptedLoadableModuleWidget base class, available at:
https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/ScriptedLoadableModule.py
"""
def setup(self):
ScriptedLoadableModuleWidget.setup(self)
# Instantiate and connect widgets ...
#
# Parameters Area
#
parametersCollapsibleButton = ctk.ctkCollapsibleButton()
parametersCollapsibleButton.text = "Parameters"
self.layout.addWidget(parametersCollapsibleButton)
# Layout within the dummy collapsible button
parametersFormLayout = qt.QFormLayout(parametersCollapsibleButton)
#
# Select landmark folder to import
#
self.inputDirectory = ctk.ctkDirectoryButton()
self.inputDirectory.directory = qt.QDir.homePath()
self.inputDirectory.setToolTip('Select Directory with fcsv lanmark files')
parametersFormLayout.addRow("Input Directory:", self.inputDirectory)
#
# output directory selector
#
self.outputDirectory = ctk.ctkDirectoryButton()
self.outputDirectory.directory = qt.QDir.homePath()
parametersFormLayout.addRow("Output Directory:", self.outputDirectory)
#
# enter filename for output
#
self.outputFileName = qt.QLineEdit()
self.outputFileName.text = "morphoJOutput"
parametersFormLayout.addRow("Name of output file:", self.outputFileName)
#
# Apply Button
#
self.applyButton = qt.QPushButton("Apply")
self.applyButton.toolTip = "Run the compiling."
self.applyButton.enabled = False
parametersFormLayout.addRow(self.applyButton)
# connections
self.applyButton.connect('clicked(bool)', self.onApplyButton)
self.inputDirectory.connect('validInputChanged(bool)', self.onSelectInput)
# Add vertical spacer
self.layout.addStretch(1)
# Refresh Apply button state
self.onSelectInput()
#self.onSelectOutput()
def cleanup(self):
pass
def onSelectInput(self):
self.applyButton.enabled = bool(self.inputDirectory.directory)
def onApplyButton(self):
logic = ExportMorphoJLandmarkFileLogic()
outputFile = self.outputFileName.text + ".csv"
outputPath = os.path.join(self.outputDirectory.directory, outputFile)
logic.run(self.inputDirectory.directory, outputPath)
#
# ExportMorphoJLandmarkFileLogic
#
class ExportMorphoJLandmarkFileLogic(ScriptedLoadableModuleLogic):
"""This class should implement all the actual
computation done by your module. The interface
should be such that other python code can import
this class and make use of the functionality without
requiring an instance of the Widget.
Uses ScriptedLoadableModuleLogic base class, available at:
https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/ScriptedLoadableModule.py
"""
def run(self, inputDirectory, outputLandmarkFile):
extensionInput = ".fcsv"
fileList = glob.glob(inputDirectory + "/*.fcsv")
if(fileList == []):
logging.info("No landmark files found in: ", inputDirectory)
return False
success, currentLMNode = slicer.util.loadMarkupsFiducialList(fileList[0])
subjectNumber = len(fileList)
landmarkNumber = currentLMNode.GetNumberOfFiducials()
LMArray=np.zeros(shape=(subjectNumber,landmarkNumber,3))
fileIndex=0
fileStems=[];
headerLM = ["Subject"]
for pointIndex in range(currentLMNode.GetNumberOfMarkups()):
headerLM.append(currentLMNode.GetNthControlPointLabel(pointIndex)+'_X')
headerLM.append(currentLMNode.GetNthControlPointLabel(pointIndex)+'_Y')
headerLM.append(currentLMNode.GetNthControlPointLabel(pointIndex)+'_Z')
LPS = [-1,-1,1]
point = [0,0,0]
for file in fileList:
if fileIndex>0:
success, currentLMNode = slicer.util.loadMarkupsFiducialList(file)
fileStems.append(os.path.basename(file.split(extensionInput)[0]))
for pointIndex in range(currentLMNode.GetNumberOfMarkups()):
point=currentLMNode.GetNthControlPointPositionVector(pointIndex)
point.Set(point[0]*LPS[0],point[1]*LPS[1],point[2]*LPS[2])
LMArray[fileIndex, pointIndex,:]=point
slicer.mrmlScene.RemoveNode(currentLMNode)
fileIndex+=1
temp = np.column_stack((np.array(fileStems), LMArray.reshape(subjectNumber, int(3 * landmarkNumber))))
temp = np.vstack((np.array(headerLM), temp))
np.savetxt(outputLandmarkFile, temp, fmt="%s", delimiter=",")
logging.info("Processing complete")
return True
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment