Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[pull] master from Slicer:master #376

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 0 additions & 78 deletions .flake8
Original file line number Diff line number Diff line change
@@ -40,94 +40,16 @@ ignore = \
B009, \
# B010] Do not call setattr with a constant attribute value, it is not any safer than normal property access.
B010, \
# Indentation is not a multiple of four
E111, \
# Indentation is not a multiple of four (comment)
E114, \
# expected an indented block (comment)
E115, \
# unexpected indentation (comment)
E116, \
# over-indented
E117, \
# continuation line under-indented for hanging indent
E121, \
# continuation line missing indentation or outdented
E122, \
# closing bracket does not match visual indentation
E124, \
# closing bracket does not match indentation of opening bracket's line
E123, \
# continuation line with same indent as next logical line
E125, \
# continuation line over-indented for hanging indent
E126, \
# continuation line over-indented for visual indent
E127, \
# continuation line under-indented for visual indent
E128, \
# visually indented line with same indent as next logical line
E129, \
# continuation line unaligned for hanging indent
E131, \
# whitespace after '('
E201, \
# whitespace before ')'
E202, \
# whitespace before ','
E203, \
# whitespace before '('
E211, \
# multiple spaces before operator
E221, \
# multiple spaces after operator
E222, \
# missing whitespace around operator
E225, \
# missing whitespace around arithmetic operator
E226, \
# missing whitespace around bitwise or shift operator
E227, \
# missing whitespace around modulo operator
E228, \
# missing whitespace after ','
E231, \
# multiple spaces after ','
E241, \
# unexpected spaces around keyword / parameter equals
E251, \
# at least two spaces before inline comment
E261, \
# inline comment should start with '# '
E262, \
# block comment should start with '# '
E265, \
# too many leading '#' for block comment
E266, \
# multiple spaces after keyword
E271, \
# multiple imports on one line
E401, \
# module level import not at top of file
E402, \
# the backslash is redundant between bracket
E502, \
# multiple statements on one line (colon)
E701, \
# statement ends with a semicolon
E703, \
# comparison to True should be 'if cond is True:' or 'if cond:'
E712, \
# test for membership should be 'not in'
E713, \
# test for object identity should be 'is not'
E714, \
# do not use bare 'except'
E722, \
# do not assign a lambda expression, use a def
E731, \
# ambiguous variable name 'l'
E741, \
# 'from module import *' used; unable to detect undefined names
F403, \
# Name may be undefined, or defined from star import
418 changes: 209 additions & 209 deletions Applications/SlicerApp/Testing/Python/AtlasTests.py

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -9,129 +9,129 @@
#

class BRAINSFitRigidRegistrationCrashIssue4139(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 = "BRAINSFit Rigid Registration vtkITKTransformConverter crash (Issue 4139)"
self.parent.categories = ["Testing.TestCases"]
self.parent.dependencies = []
self.parent.contributors = ["Jean-Christophe Fillion-Robin (Kitware)"] # replace with "Firstname Lastname (Organization)"
self.parent.helpText = """This test has been added to check that
"""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 = "BRAINSFit Rigid Registration vtkITKTransformConverter crash (Issue 4139)"
self.parent.categories = ["Testing.TestCases"]
self.parent.dependencies = []
self.parent.contributors = ["Jean-Christophe Fillion-Robin (Kitware)"] # replace with "Firstname Lastname (Organization)"
self.parent.helpText = """This test has been added to check that
Slicer does not crash in vtkITKTransformConverter after completing BRAINSFit rigid registration.
Problem has been documented in issue #4139. Commit r24901 fixes the problem
by updating vtkITKTransformConverter class.
"""
self.parent.acknowledgementText = """
self.parent.acknowledgementText = """
This file was originally developed by Jean-Christophe Fillion-Robin, Kitware Inc.
and was partially funded by NIH grant 1U24CA194354-01.
""" # replace with organization, grant and thanks.
""" # replace with organization, grant and thanks.


#
# BRAINSFitRigidRegistrationCrashIssue4139Widget
#

class BRAINSFitRigidRegistrationCrashIssue4139Widget(ScriptedLoadableModuleWidget):
"""Uses ScriptedLoadableModuleWidget base class, available at:
https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/ScriptedLoadableModule.py
"""
"""Uses ScriptedLoadableModuleWidget base class, available at:
https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/ScriptedLoadableModule.py
"""

def setup(self):
ScriptedLoadableModuleWidget.setup(self)
def setup(self):
ScriptedLoadableModuleWidget.setup(self)


#
# BRAINSFitRigidRegistrationCrashIssue4139Logic
#

class BRAINSFitRigidRegistrationCrashIssue4139Logic(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 hasImageData(self,volumeNode):
"""This is an example logic method that
returns true if the passed in volume
node has valid image data
"""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
"""
if not volumeNode:
logging.debug('hasImageData failed: no volume node')
return False
if volumeNode.GetImageData() is None:
logging.debug('hasImageData failed: no image data in volume node')
return False
return True

def hasImageData(self, volumeNode):
"""This is an example logic method that
returns true if the passed in volume
node has valid image data
"""
if not volumeNode:
logging.debug('hasImageData failed: no volume node')
return False
if volumeNode.GetImageData() is None:
logging.debug('hasImageData failed: no image data in volume node')
return False
return True

class BRAINSFitRigidRegistrationCrashIssue4139Test(ScriptedLoadableModuleTest):
"""
This is the test case for your scripted module.
Uses ScriptedLoadableModuleTest base class, available at:
https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/ScriptedLoadableModule.py
"""

def setUp(self):
""" Do whatever is needed to reset the state - typically a scene clear will be enough.
"""
slicer.mrmlScene.Clear(0)

def runTest(self):
"""Run as few or as many tests as needed here.
class BRAINSFitRigidRegistrationCrashIssue4139Test(ScriptedLoadableModuleTest):
"""
self.setUp()
self.test_BRAINSFitRigidRegistrationCrashIssue4139()

def test_BRAINSFitRigidRegistrationCrashIssue4139(self):
""" Ideally you should have several levels of tests. At the lowest level
tests should exercise the functionality of the logic with different inputs
(both valid and invalid). At higher levels your tests should emulate the
way the user would interact with your code and confirm that it still works
the way you intended.
One of the most important features of the tests is that it should alert other
developers when their changes will have an impact on the behavior of your
module. For example, if a developer removes a feature that you depend on,
your test should break so they know that the feature is needed.
This is the test case for your scripted module.
Uses ScriptedLoadableModuleTest base class, available at:
https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/ScriptedLoadableModule.py
"""

self.delayDisplay("Starting the test")
def setUp(self):
""" Do whatever is needed to reset the state - typically a scene clear will be enough.
"""
slicer.mrmlScene.Clear(0)

def runTest(self):
"""Run as few or as many tests as needed here.
"""
self.setUp()
self.test_BRAINSFitRigidRegistrationCrashIssue4139()

def test_BRAINSFitRigidRegistrationCrashIssue4139(self):
""" Ideally you should have several levels of tests. At the lowest level
tests should exercise the functionality of the logic with different inputs
(both valid and invalid). At higher levels your tests should emulate the
way the user would interact with your code and confirm that it still works
the way you intended.
One of the most important features of the tests is that it should alert other
developers when their changes will have an impact on the behavior of your
module. For example, if a developer removes a feature that you depend on,
your test should break so they know that the feature is needed.
"""

self.delayDisplay("Starting the test")

logic = BRAINSFitRigidRegistrationCrashIssue4139Logic()
logic = BRAINSFitRigidRegistrationCrashIssue4139Logic()

import SampleData
import SampleData

fixed = SampleData.downloadSample('MRBrainTumor1')
self.assertIsNotNone(logic.hasImageData(fixed))
fixed = SampleData.downloadSample('MRBrainTumor1')
self.assertIsNotNone(logic.hasImageData(fixed))

moving = SampleData.downloadSample('MRBrainTumor2')
self.assertIsNotNone(logic.hasImageData(moving))
moving = SampleData.downloadSample('MRBrainTumor2')
self.assertIsNotNone(logic.hasImageData(moving))

self.delayDisplay('Finished with download and loading')
self.delayDisplay('Finished with download and loading')

outputTransform = slicer.vtkMRMLLinearTransformNode()
slicer.mrmlScene.AddNode(outputTransform)
outputTransform = slicer.vtkMRMLLinearTransformNode()
slicer.mrmlScene.AddNode(outputTransform)

outputVolume = slicer.vtkMRMLScalarVolumeNode()
slicer.mrmlScene.AddNode(outputVolume)
outputVolume = slicer.vtkMRMLScalarVolumeNode()
slicer.mrmlScene.AddNode(outputVolume)

parameters = {
'fixedVolume' : fixed,
'movingVolume' : moving,
'linearTransform' : outputTransform,
'outputVolume' : outputVolume,
'useRigid' : True
}
cmdLineNode = slicer.cli.runSync(slicer.modules.brainsfit, parameters=parameters)
self.assertIsNotNone(cmdLineNode)
parameters = {
'fixedVolume': fixed,
'movingVolume': moving,
'linearTransform': outputTransform,
'outputVolume': outputVolume,
'useRigid': True
}
cmdLineNode = slicer.cli.runSync(slicer.modules.brainsfit, parameters=parameters)
self.assertIsNotNone(cmdLineNode)

# If test reach this point without crashing it is a success
# If test reach this point without crashing it is a success

self.delayDisplay('Test passed!')
self.delayDisplay('Test passed!')
364 changes: 182 additions & 182 deletions Applications/SlicerApp/Testing/Python/CLIEventTest.py

Large diffs are not rendered by default.

396 changes: 198 additions & 198 deletions Applications/SlicerApp/Testing/Python/CLISerializationTest.py

Large diffs are not rendered by default.

18 changes: 9 additions & 9 deletions Applications/SlicerApp/Testing/Python/DCMTKPrivateDictTest.py
Original file line number Diff line number Diff line change
@@ -4,17 +4,17 @@

dcmfile = sys.argv[1]

dcmdump=DICOMLib.DICOMCommand('dcmdump',[dcmfile])
dump=str(dcmdump.start()).replace("\\r","\r").replace("\\n","\n").splitlines()
dcmdump = DICOMLib.DICOMCommand('dcmdump', [dcmfile])
dump = str(dcmdump.start()).replace("\\r", "\r").replace("\\n", "\n").splitlines()

found_private_tag = False
for line in dump:
line = line.split(' ')
if line[0] == '(2001,1003)':
if line[-1] == "DiffusionBFactor":
found_private_tag = True
break
line = line.split(' ')
if line[0] == '(2001,1003)':
if line[-1] == "DiffusionBFactor":
found_private_tag = True
break

if not found_private_tag:
raise Exception("Could not find 'DiffusionBFactor' "
"private tag reading file '%s' using 'dcmdump' !" % dcmfile)
raise Exception("Could not find 'DiffusionBFactor' "
"private tag reading file '%s' using 'dcmdump' !" % dcmfile)
552 changes: 276 additions & 276 deletions Applications/SlicerApp/Testing/Python/DICOMReaders.py

Large diffs are not rendered by default.

22 changes: 11 additions & 11 deletions Applications/SlicerApp/Testing/Python/DWMRIMultishellIOTests.py
Original file line number Diff line number Diff line change
@@ -9,21 +9,21 @@

import slicer

#===============================================================================
# ===============================================================================

mrmlcore_testdata_path = "Libs/MRML/Core/Testing/TestData/"


multishell_dwi_451 = os.path.join(mrmlcore_testdata_path, "multishell-DWI-451dir.nhdr")

#================================================================================
# ================================================================================
NRRD = namedtuple('NRRD', ['header', 'bvalue', 'gradients'])


def parse_nhdr(path):
dwmri_bval_key = "DWMRI_b-value"
dwmri_grad_keybase = "DWMRI_gradient_"
dwmri_grad_key_n = "DWMRI_gradient_{:04d}"
dwmri_bval_key = "DWMRI_b-value"
dwmri_grad_keybase = "DWMRI_gradient_"
dwmri_grad_key_n = "DWMRI_gradient_{:04d}"

kvdict = {}
grad_count = 0
@@ -44,9 +44,9 @@ def parse_nhdr(path):
kvdict[key] = val

if key.startswith(dwmri_grad_keybase):
_gn = int(key[ len(dwmri_grad_keybase):None ])
_gn = int(key[len(dwmri_grad_keybase):None])
# monotonic keys
assert( _gn == grad_count ) # offset
assert(_gn == grad_count) # offset
grad_count += 1

bvalue = float(kvdict[dwmri_bval_key])
@@ -60,13 +60,13 @@ def parse_nhdr(path):
return NRRD(header=kvdict, bvalue=bvalue, gradients=grads)


#================================================================================
# ================================================================================
def normalize(vec):
norm = np.linalg.norm(vec)
if norm == 0.0:
return vec
else:
return vec * 1/norm
return vec * 1 / norm


def test_nrrd_dwi_load(first_file, second_file=None):
@@ -94,7 +94,7 @@ def test_nrrd_dwi_load(first_file, second_file=None):
##################################
# 1) check the number of gradients

assert( len(parsed_nrrd.gradients) == slicer_numgrads )
assert(len(parsed_nrrd.gradients) == slicer_numgrads)

##################################
# 2) check the node b values and gradients are correct
@@ -126,7 +126,7 @@ def test_nrrd_dwi_load(first_file, second_file=None):
for i in range(0, slicer_numgrads):
grad_key = f"DWMRI_gradient_{i:04d}"
parsed_gradient = np.fromstring(parsed_nrrd.header[grad_key], count=3, sep=' ', dtype=np.float64)
attr_gradient = np.fromstring(dw_node.GetAttribute(grad_key), count=3, sep=' ', dtype=np.float64)
attr_gradient = np.fromstring(dw_node.GetAttribute(grad_key), count=3, sep=' ', dtype=np.float64)

np.testing.assert_array_almost_equal(parsed_gradient, attr_gradient, decimal=12,
err_msg="NHDR gradient does not match gradient in node attribute dictionary")
326 changes: 163 additions & 163 deletions Applications/SlicerApp/Testing/Python/FiducialLayoutSwitchBug1914.py

Large diffs are not rendered by default.

954 changes: 477 additions & 477 deletions Applications/SlicerApp/Testing/Python/JRC2013Vis.py

Large diffs are not rendered by default.

22 changes: 11 additions & 11 deletions Applications/SlicerApp/Testing/Python/KneeAtlasTest.py
Original file line number Diff line number Diff line change
@@ -4,20 +4,20 @@


class testClass:
""" Run the knee atlas test by itself
"""
""" Run the knee atlas test by itself
"""

def setUp(self):
print("Import the atlas tests...")
atlasTests = AtlasTests.AtlasTestsTest()
atlasTests.test_KneeAtlasTest()
def setUp(self):
print("Import the atlas tests...")
atlasTests = AtlasTests.AtlasTestsTest()
atlasTests.test_KneeAtlasTest()


class KneeAtlasTest(unittest.TestCase):

def setUp(self):
pass
def setUp(self):
pass

def test_testClass(self):
test = testClass()
test.setUp()
def test_testClass(self):
test = testClass()
test.setUp()
Original file line number Diff line number Diff line change
@@ -2,10 +2,10 @@


def testMRMLCreateNodeByClassWithSetReferenceCountMinusOne():
n = slicer.mrmlScene.CreateNodeByClass('vtkMRMLViewNode')
n.UnRegister(None) # the node object is now owned by n Python variable therefore we can release the reference that CreateNodeByClass added
slicer.mrmlScene.AddNode(n)
n = slicer.mrmlScene.CreateNodeByClass('vtkMRMLViewNode')
n.UnRegister(None) # the node object is now owned by n Python variable therefore we can release the reference that CreateNodeByClass added
slicer.mrmlScene.AddNode(n)


if __name__ == '__main__':
testMRMLCreateNodeByClassWithSetReferenceCountMinusOne()
testMRMLCreateNodeByClassWithSetReferenceCountMinusOne()
Original file line number Diff line number Diff line change
@@ -3,18 +3,18 @@

def testMRMLCreateNodeByClassWithoutSetReferenceCount():

# Always run this test as if CTest ran it.
# It is necessary because without this the test on Windows
# would report leaks in a popup window that has to be closed manually
# (or wait a long time for timeout) when run from VisualStudio by
# building the RUN_TESTS project.
slicer.app.setEnvironmentVariable("DASHBOARD_TEST_FROM_CTEST", "1")
# Always run this test as if CTest ran it.
# It is necessary because without this the test on Windows
# would report leaks in a popup window that has to be closed manually
# (or wait a long time for timeout) when run from VisualStudio by
# building the RUN_TESTS project.
slicer.app.setEnvironmentVariable("DASHBOARD_TEST_FROM_CTEST", "1")

n = slicer.mrmlScene.CreateNodeByClass('vtkMRMLViewNode')
slicer.mrmlScene.AddNode(n)
# This is expected to leak memory because CreateNodeByClass increments the reference count by one
# and nothing decrements it.
n = slicer.mrmlScene.CreateNodeByClass('vtkMRMLViewNode')
slicer.mrmlScene.AddNode(n)
# This is expected to leak memory because CreateNodeByClass increments the reference count by one
# and nothing decrements it.


if __name__ == '__main__':
testMRMLCreateNodeByClassWithoutSetReferenceCount()
testMRMLCreateNodeByClassWithoutSetReferenceCount()
20 changes: 10 additions & 10 deletions Applications/SlicerApp/Testing/Python/MRMLSceneImportAndExport.py
Original file line number Diff line number Diff line change
@@ -3,17 +3,17 @@


def testMRMLSceneImportAndExport():
tempDir = slicer.app.temporaryPath
scenePath = tempDir + '/temp_scene.mrml'
slicer.mrmlScene.SetURL(scenePath)
if not slicer.mrmlScene.Commit(scenePath):
raise Exception('Saving a MRML scene failed !')
tempDir = slicer.app.temporaryPath
scenePath = tempDir + '/temp_scene.mrml'
slicer.mrmlScene.SetURL(scenePath)
if not slicer.mrmlScene.Commit(scenePath):
raise Exception('Saving a MRML scene failed !')

success = slicer.mrmlScene.Import()
os.remove(scenePath)
if not success:
raise Exception('Importing back a MRML scene failed !')
success = slicer.mrmlScene.Import()
os.remove(scenePath)
if not success:
raise Exception('Importing back a MRML scene failed !')


if __name__ == '__main__':
testMRMLSceneImportAndExport()
testMRMLSceneImportAndExport()
352 changes: 181 additions & 171 deletions Applications/SlicerApp/Testing/Python/MeasureStartupTimes.py

Large diffs are not rendered by default.

108 changes: 54 additions & 54 deletions Applications/SlicerApp/Testing/Python/RSNA2012ProstateDemo.py
Original file line number Diff line number Diff line change
@@ -8,81 +8,81 @@
#

class RSNA2012ProstateDemo(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)
parent.title = "RSNA2012ProstateDemo" # TODO make this more human readable by adding spaces
parent.categories = ["Testing.TestCases"]
parent.dependencies = []
parent.contributors = ["Steve Pieper (Isomics)"] # replace with "Firstname Lastname (Org)"
parent.helpText = """
"""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)
parent.title = "RSNA2012ProstateDemo" # TODO make this more human readable by adding spaces
parent.categories = ["Testing.TestCases"]
parent.dependencies = []
parent.contributors = ["Steve Pieper (Isomics)"] # replace with "Firstname Lastname (Org)"
parent.helpText = """
This module was developed as a self test to perform the operations needed for the RSNA 2012 Prostate Demo
"""
parent.acknowledgementText = """
parent.acknowledgementText = """
This file was originally developed by Steve Pieper, Isomics, Inc. and was partially funded by NIH grant 3P41RR013218-12S1.
""" # replace with organization, grant and thanks.
""" # replace with organization, grant and thanks.


#
# qRSNA2012ProstateDemoWidget
#

class RSNA2012ProstateDemoWidget(ScriptedLoadableModuleWidget):
"""Uses ScriptedLoadableModuleWidget base class, available at:
https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/ScriptedLoadableModule.py
"""
"""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 ...
def setup(self):
ScriptedLoadableModuleWidget.setup(self)
# Instantiate and connect widgets ...

# Add vertical spacer
self.layout.addStretch(1)
# Add vertical spacer
self.layout.addStretch(1)

def cleanup(self):
pass
def cleanup(self):
pass


class RSNA2012ProstateDemoTest(ScriptedLoadableModuleTest):
"""
This is the test case for your scripted module.
Uses ScriptedLoadableModuleTest base class, available at:
https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/ScriptedLoadableModule.py
"""
"""
This is the test case for your scripted module.
Uses ScriptedLoadableModuleTest base class, available at:
https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/ScriptedLoadableModule.py
"""

def setUp(self):
slicer.mrmlScene.Clear(0)
def setUp(self):
slicer.mrmlScene.Clear(0)

def runTest(self):
self.setUp()
self.test_RSNA2012ProstateDemo()
def runTest(self):
self.setUp()
self.test_RSNA2012ProstateDemo()

def test_RSNA2012ProstateDemo(self):
"""
Replicate one of the crashes in issue 2512
"""
def test_RSNA2012ProstateDemo(self):
"""
Replicate one of the crashes in issue 2512
"""

print("Running RSNA2012ProstateDemo Test case:")
print("Running RSNA2012ProstateDemo Test case:")

import SampleData
SampleData.downloadFromURL(
fileNames='RSNA2012ProstateDemo.mrb',
loadFiles=True,
uris=TESTING_DATA_URL + 'SHA256/2627388ee213564f8783d0242993212ba01189f4c6640d57c4cde4e28fc5f97b',
checksums='SHA256:2627388ee213564f8783d0242993212ba01189f4c6640d57c4cde4e28fc5f97b')
import SampleData
SampleData.downloadFromURL(
fileNames='RSNA2012ProstateDemo.mrb',
loadFiles=True,
uris=TESTING_DATA_URL + 'SHA256/2627388ee213564f8783d0242993212ba01189f4c6640d57c4cde4e28fc5f97b',
checksums='SHA256:2627388ee213564f8783d0242993212ba01189f4c6640d57c4cde4e28fc5f97b')

# get all scene view nodes and test switching
svns = slicer.util.getNodes('vtkMRMLSceneViewNode*')
# get all scene view nodes and test switching
svns = slicer.util.getNodes('vtkMRMLSceneViewNode*')

for reps in range(5):
for svname,svnode in svns.items():
self.delayDisplay('Restoring scene view %s ...' % svname )
svnode.RestoreScene()
self.delayDisplay('OK')
for reps in range(5):
for svname, svnode in svns.items():
self.delayDisplay('Restoring scene view %s ...' % svname)
svnode.RestoreScene()
self.delayDisplay('OK')

self.delayDisplay('Done testing scene views, will clear the scene')
slicer.mrmlScene.Clear(0)
self.delayDisplay('Test passed')
self.delayDisplay('Done testing scene views, will clear the scene')
slicer.mrmlScene.Clear(0)
self.delayDisplay('Test passed')
786 changes: 393 additions & 393 deletions Applications/SlicerApp/Testing/Python/RSNAQuantTutorial.py

Large diffs are not rendered by default.

1,002 changes: 501 additions & 501 deletions Applications/SlicerApp/Testing/Python/RSNAVisTutorial.py

Large diffs are not rendered by default.

492 changes: 246 additions & 246 deletions Applications/SlicerApp/Testing/Python/ScenePerformance.py

Large diffs are not rendered by default.

108 changes: 54 additions & 54 deletions Applications/SlicerApp/Testing/Python/ScriptedModuleCleanupTest.py
Original file line number Diff line number Diff line change
@@ -23,9 +23,9 @@
import tempfile

from SlicerAppTesting import (
EXIT_FAILURE,
EXIT_SUCCESS,
run,
EXIT_FAILURE,
EXIT_SUCCESS,
run,
)

"""
@@ -41,59 +41,59 @@


def check_exit_code(slicer_executable, testing_enabled=True, debug=False):
"""
If debug is set to True:
* display the path of the expected test output file
* avoid deleting the created temporary directory
"""

temporaryModuleDirPath = tempfile.mkdtemp().replace('\\','/')
try:
# Copy helper module that creates a file when startup completed event is received
currentDirPath = os.path.dirname(__file__).replace('\\','/')
from shutil import copyfile
copyfile(currentDirPath+'/ScriptedModuleCleanupTestHelperModule.py',
temporaryModuleDirPath+'/ModuleCleanup.py')

common_arguments = [
'--no-splash',
'--disable-builtin-modules',
'--additional-module-path', temporaryModuleDirPath,
'--python-code', 'slicer.util.selectModule("ModuleCleanup")'
]

test_output_file = temporaryModuleDirPath + "/ModuleCleanupTest.out"
os.environ['SLICER_MODULE_CLEANUP_TEST_OUTPUT'] = test_output_file
if debug:
print("SLICER_MODULE_CLEANUP_TEST_OUTPUT=%s" % test_output_file)

# Test
args = list(common_arguments)
if testing_enabled:
args.append('--testing')
else:
args.append('--exit-after-startup')
(returnCode, stdout, stderr) = run(slicer_executable, args)

assert(os.path.isfile(test_output_file))

if testing_enabled:
assert(returnCode == EXIT_FAILURE)
else:
assert(returnCode == EXIT_SUCCESS)

finally:
if not debug:
import shutil
shutil.rmtree(temporaryModuleDirPath)
"""
If debug is set to True:
* display the path of the expected test output file
* avoid deleting the created temporary directory
"""

temporaryModuleDirPath = tempfile.mkdtemp().replace('\\', '/')
try:
# Copy helper module that creates a file when startup completed event is received
currentDirPath = os.path.dirname(__file__).replace('\\', '/')
from shutil import copyfile
copyfile(currentDirPath + '/ScriptedModuleCleanupTestHelperModule.py',
temporaryModuleDirPath + '/ModuleCleanup.py')

common_arguments = [
'--no-splash',
'--disable-builtin-modules',
'--additional-module-path', temporaryModuleDirPath,
'--python-code', 'slicer.util.selectModule("ModuleCleanup")'
]

test_output_file = temporaryModuleDirPath + "/ModuleCleanupTest.out"
os.environ['SLICER_MODULE_CLEANUP_TEST_OUTPUT'] = test_output_file
if debug:
print("SLICER_MODULE_CLEANUP_TEST_OUTPUT=%s" % test_output_file)

# Test
args = list(common_arguments)
if testing_enabled:
args.append('--testing')
else:
args.append('--exit-after-startup')
(returnCode, stdout, stderr) = run(slicer_executable, args)

assert(os.path.isfile(test_output_file))

if testing_enabled:
assert(returnCode == EXIT_FAILURE)
else:
assert(returnCode == EXIT_SUCCESS)

finally:
if not debug:
import shutil
shutil.rmtree(temporaryModuleDirPath)


if __name__ == "__main__":

parser = argparse.ArgumentParser()
parser.add_argument("/path/to/Slicer")
parser.add_argument('--with-testing', dest='testing_enabled', action='store_true')
args = parser.parse_args()
parser = argparse.ArgumentParser()
parser.add_argument("/path/to/Slicer")
parser.add_argument('--with-testing', dest='testing_enabled', action='store_true')
args = parser.parse_args()

slicer_executable = os.path.expanduser(getattr(args, "/path/to/Slicer"))
check_exit_code(slicer_executable, testing_enabled=args.testing_enabled)
slicer_executable = os.path.expanduser(getattr(args, "/path/to/Slicer"))
check_exit_code(slicer_executable, testing_enabled=args.testing_enabled)
Original file line number Diff line number Diff line change
@@ -4,34 +4,34 @@


class ModuleCleanup(ScriptedLoadableModule):
def __init__(self, parent):
ScriptedLoadableModule.__init__(self, parent)
self.parent.title = "Module for cleanup test"
self.parent.categories = ["ModuleCleanup"] # Explicitly add a category to work around issue #4698
self.parent.contributors = ["Jean-Christophe Fillion-Robin (Kitware)",]
self.parent.helpText = """
def __init__(self, parent):
ScriptedLoadableModule.__init__(self, parent)
self.parent.title = "Module for cleanup test"
self.parent.categories = ["ModuleCleanup"] # Explicitly add a category to work around issue #4698
self.parent.contributors = ["Jean-Christophe Fillion-Robin (Kitware)", ]
self.parent.helpText = """
This module allows to test that exception raised during module cleanup
sets exit code.
"""
self.parent.acknowledgementText = """
self.parent.acknowledgementText = """
Developed by Jean-Christophe Fillion-Robin, Kitware Inc.,
partially funded by NIH grant 1R01EB021391.
"""


class ModuleCleanupWidget(ScriptedLoadableModuleWidget):
def __init__(self, parent=None):
ScriptedLoadableModuleWidget.__init__(self, parent)
def __init__(self, parent=None):
ScriptedLoadableModuleWidget.__init__(self, parent)

self.testOutputFileName = os.environ['SLICER_MODULE_CLEANUP_TEST_OUTPUT']
if os.path.isfile(self.testOutputFileName):
os.remove(self.testOutputFileName)
self.testOutputFileName = os.environ['SLICER_MODULE_CLEANUP_TEST_OUTPUT']
if os.path.isfile(self.testOutputFileName):
os.remove(self.testOutputFileName)

def setup(self):
ScriptedLoadableModuleWidget.setup(self)
print("ModuleCleanupWidget setup")
def setup(self):
ScriptedLoadableModuleWidget.setup(self)
print("ModuleCleanupWidget setup")

def cleanup(self):
with open(self.testOutputFileName, "w") as fd:
fd.write('ModuleCleanup generated this file when application exited')
raise RuntimeError("ModuleCleanupWidget error")
def cleanup(self):
with open(self.testOutputFileName, "w") as fd:
fd.write('ModuleCleanup generated this file when application exited')
raise RuntimeError("ModuleCleanupWidget error")
Original file line number Diff line number Diff line change
@@ -4,28 +4,28 @@


class ModuleA(ScriptedLoadableModule):
def __init__(self, parent):
ScriptedLoadableModule.__init__(self, parent)
self.parent.title = "Module A"
self.parent.contributors = ["Jean-Christophe Fillion-Robin (Kitware)",]
self.parent.helpText = """
def __init__(self, parent):
ScriptedLoadableModule.__init__(self, parent)
self.parent.title = "Module A"
self.parent.contributors = ["Jean-Christophe Fillion-Robin (Kitware)", ]
self.parent.helpText = """
This module allows to test the scripted module import.
"""
self.parent.acknowledgementText = """
self.parent.acknowledgementText = """
Developed by Jean-Christophe Fillion-Robin, Kitware Inc.,
partially funded by NIH grant 3P41RR013218-12S1.
"""

def somevar(self):
return SOMEVAR
def somevar(self):
return SOMEVAR


class ModuleAWidget(ScriptedLoadableModuleWidget):
def __init__(self, parent=None):
ScriptedLoadableModuleWidget.__init__(self, parent)
def __init__(self, parent=None):
ScriptedLoadableModuleWidget.__init__(self, parent)

def setup(self):
ScriptedLoadableModuleWidget.setup(self)
def setup(self):
ScriptedLoadableModuleWidget.setup(self)

def cleanup(self):
print("ModuleAWidget finalized")
def cleanup(self):
print("ModuleAWidget finalized")
Original file line number Diff line number Diff line change
@@ -4,25 +4,25 @@


class ModuleB(ScriptedLoadableModule):
def __init__(self, parent):
ScriptedLoadableModule.__init__(self, parent)
self.parent.title = "Module B"
self.parent.contributors = ["Jean-Christophe Fillion-Robin (Kitware)",]
self.parent.helpText = """
def __init__(self, parent):
ScriptedLoadableModule.__init__(self, parent)
self.parent.title = "Module B"
self.parent.contributors = ["Jean-Christophe Fillion-Robin (Kitware)", ]
self.parent.helpText = """
This module allows to test the scripted module import.
"""
self.parent.acknowledgementText = """
self.parent.acknowledgementText = """
Developed by Jean-Christophe Fillion-Robin, Kitware Inc.,
partially funded by NIH grant 3P41RR013218-12S1.
"""

def somevar(self):
return SOMEVAR
def somevar(self):
return SOMEVAR


class ModuleBWidget(ScriptedLoadableModuleWidget):
def __init__(self, parent=None):
ScriptedLoadableModuleWidget.__init__(self, parent)
def __init__(self, parent=None):
ScriptedLoadableModuleWidget.__init__(self, parent)

def setup(self):
ScriptedLoadableModuleWidget.setup(self)
def setup(self):
ScriptedLoadableModuleWidget.setup(self)
Original file line number Diff line number Diff line change
@@ -4,17 +4,17 @@


class ModuleC_WithoutWidget(ScriptedLoadableModule):
def __init__(self, parent):
ScriptedLoadableModule.__init__(self, parent)
self.parent.title = "Module A"
self.parent.contributors = ["Jean-Christophe Fillion-Robin (Kitware)",]
self.parent.helpText = """
def __init__(self, parent):
ScriptedLoadableModule.__init__(self, parent)
self.parent.title = "Module A"
self.parent.contributors = ["Jean-Christophe Fillion-Robin (Kitware)", ]
self.parent.helpText = """
This module allows to test the scripted module import.
"""
self.parent.acknowledgementText = """
self.parent.acknowledgementText = """
Developed by Jean-Christophe Fillion-Robin, Kitware Inc.,
partially funded by NIH grant 3P41RR013218-12S1.
"""

def somevar(self):
return SOMEVAR
def somevar(self):
return SOMEVAR
Original file line number Diff line number Diff line change
@@ -4,35 +4,35 @@


class ModuleD_WithFileDialog_WithoutWidget(ScriptedLoadableModule):
def __init__(self, parent):
ScriptedLoadableModule.__init__(self, parent)
self.parent.title = "Module A"
self.parent.contributors = ["Jean-Christophe Fillion-Robin (Kitware)",]
self.parent.helpText = """
def __init__(self, parent):
ScriptedLoadableModule.__init__(self, parent)
self.parent.title = "Module A"
self.parent.contributors = ["Jean-Christophe Fillion-Robin (Kitware)", ]
self.parent.helpText = """
This module allows to test the scripted module import.
"""
self.parent.acknowledgementText = """
self.parent.acknowledgementText = """
Developed by Jean-Christophe Fillion-Robin, Kitware Inc.,
partially funded by NIH grant 3P41RR013218-12S1.
"""

def somevar(self):
return SOMEVAR
def somevar(self):
return SOMEVAR


class DICOMFileDialog:

def __init__(self,qSlicerFileDialog):
self.qSlicerFileDialog = qSlicerFileDialog
qSlicerFileDialog.fileType = 'Foo Directory'
qSlicerFileDialog.description = 'Do something awesome with Foo'
qSlicerFileDialog.action = slicer.qSlicerFileDialog.Read
def __init__(self, qSlicerFileDialog):
self.qSlicerFileDialog = qSlicerFileDialog
qSlicerFileDialog.fileType = 'Foo Directory'
qSlicerFileDialog.description = 'Do something awesome with Foo'
qSlicerFileDialog.action = slicer.qSlicerFileDialog.Read

def execDialog(self):
pass
def execDialog(self):
pass

def isMimeDataAccepted(self):
self.qSlicerFileDialog.acceptMimeData(True)
def isMimeDataAccepted(self):
self.qSlicerFileDialog.acceptMimeData(True)

def dropEvent(self):
pass
def dropEvent(self):
pass
Original file line number Diff line number Diff line change
@@ -4,17 +4,17 @@


class ModuleE_WithFileWriter_WithoutWidget(ScriptedLoadableModule):
def __init__(self, parent):
ScriptedLoadableModule.__init__(self, parent)
self.parent.title = "Module A"
self.parent.contributors = ["Jean-Christophe Fillion-Robin (Kitware)",]
self.parent.helpText = """
def __init__(self, parent):
ScriptedLoadableModule.__init__(self, parent)
self.parent.title = "Module A"
self.parent.contributors = ["Jean-Christophe Fillion-Robin (Kitware)", ]
self.parent.helpText = """
This module allows to test the scripted module import.
"""
self.parent.acknowledgementText = """
self.parent.acknowledgementText = """
Developed by Jean-Christophe Fillion-Robin, Kitware Inc.,
partially funded by NIH grant 3P41RR013218-12S1.
"""

def somevar(self):
return SOMEVAR
def somevar(self):
return SOMEVAR
442 changes: 221 additions & 221 deletions Applications/SlicerApp/Testing/Python/ShaderProperties.py

Large diffs are not rendered by default.

478 changes: 239 additions & 239 deletions Applications/SlicerApp/Testing/Python/SliceLinkLogic.py

Large diffs are not rendered by default.

280 changes: 140 additions & 140 deletions Applications/SlicerApp/Testing/Python/Slicer4Minute.py
Original file line number Diff line number Diff line change
@@ -11,174 +11,174 @@
#

class Slicer4Minute(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)
parent.title = "Slicer4Minute" # TODO make this more human readable by adding spaces
parent.categories = ["Testing.TestCases"]
parent.dependencies = []
parent.contributors = ["Jim Miller (GE)"] # replace with "Firstname Lastname (Org)"
parent.helpText = """
"""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)
parent.title = "Slicer4Minute" # TODO make this more human readable by adding spaces
parent.categories = ["Testing.TestCases"]
parent.dependencies = []
parent.contributors = ["Jim Miller (GE)"] # replace with "Firstname Lastname (Org)"
parent.helpText = """
Test suite for the Slicer 4 Minute tutorial
"""
parent.acknowledgementText = """
parent.acknowledgementText = """
This file was originally developed by Jim Miller, GE and was partially funded by NIH grant U54EB005149.
""" # replace with organization, grant and thanks.
""" # replace with organization, grant and thanks.


#
# qSlicer4MinuteWidget
#

class Slicer4MinuteWidget(ScriptedLoadableModuleWidget):
"""Uses ScriptedLoadableModuleWidget base class, available at:
https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/ScriptedLoadableModule.py
"""
"""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 ...
def setup(self):
ScriptedLoadableModuleWidget.setup(self)
# Instantiate and connect widgets ...

# Collapsible button
dummyCollapsibleButton = ctk.ctkCollapsibleButton()
dummyCollapsibleButton.text = "A collapsible button"
self.layout.addWidget(dummyCollapsibleButton)
# Collapsible button
dummyCollapsibleButton = ctk.ctkCollapsibleButton()
dummyCollapsibleButton.text = "A collapsible button"
self.layout.addWidget(dummyCollapsibleButton)

# Layout within the dummy collapsible button
dummyFormLayout = qt.QFormLayout(dummyCollapsibleButton)
# Layout within the dummy collapsible button
dummyFormLayout = qt.QFormLayout(dummyCollapsibleButton)

# HelloWorld button
helloWorldButton = qt.QPushButton("Hello world")
helloWorldButton.toolTip = "Print 'Hello world' in standard output."
dummyFormLayout.addWidget(helloWorldButton)
helloWorldButton.connect('clicked(bool)', self.onHelloWorldButtonClicked)
# HelloWorld button
helloWorldButton = qt.QPushButton("Hello world")
helloWorldButton.toolTip = "Print 'Hello world' in standard output."
dummyFormLayout.addWidget(helloWorldButton)
helloWorldButton.connect('clicked(bool)', self.onHelloWorldButtonClicked)

# Add vertical spacer
self.layout.addStretch(1)
# Add vertical spacer
self.layout.addStretch(1)

# Set local var as instance attribute
self.helloWorldButton = helloWorldButton
# Set local var as instance attribute
self.helloWorldButton = helloWorldButton

def onHelloWorldButtonClicked(self):
print("Hello World !")
def onHelloWorldButtonClicked(self):
print("Hello World !")


#
# Slicer4MinuteLogic
#

class Slicer4MinuteLogic(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 hasImageData(self,volumeNode):
"""This is a dummy logic method that
returns true if the passed in volume
node has valid image data
"""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
"""
if not volumeNode:
print('no volume node')
return False
if volumeNode.GetImageData() is None:
print('no image data')
return False
return True

def hasImageData(self, volumeNode):
"""This is a dummy logic method that
returns true if the passed in volume
node has valid image data
"""
if not volumeNode:
print('no volume node')
return False
if volumeNode.GetImageData() is None:
print('no image data')
return False
return True


class Slicer4MinuteTest(ScriptedLoadableModuleTest):
"""
This is the test case for your scripted module.
Uses ScriptedLoadableModuleTest base class, available at:
https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/ScriptedLoadableModule.py
"""

def setUp(self):
""" Do whatever is needed to reset the state - typically a scene clear will be enough.
"""
slicer.mrmlScene.Clear(0)

def runTest(self):
"""Run as few or as many tests as needed here.
This is the test case for your scripted module.
Uses ScriptedLoadableModuleTest base class, available at:
https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/ScriptedLoadableModule.py
"""
self.setUp()
self.test_Slicer4Minute1()

def test_Slicer4Minute1(self):
""" Tests parts of the Slicer4Minute tutorial.

Currently testing 'Part 2' which covers volumes, models, visibility and clipping.
"""
self.delayDisplay("Starting the test")

logic = Slicer4MinuteLogic()

#
# first, get some data
#
import SampleData
SampleData.downloadFromURL(
fileNames='slicer4minute.mrb',
loadFiles=True,
uris=TESTING_DATA_URL + 'SHA256/5a1c78c3347f77970b1a29e718bfa10e5376214692d55a7320af94b9d8d592b8',
checksums='SHA256:5a1c78c3347f77970b1a29e718bfa10e5376214692d55a7320af94b9d8d592b8')
self.delayDisplay('Finished with download and loading')

# Testing "Part 2" of Tutorial
#
#
self.delayDisplay('Testing Part 2 of the Tutorial')

# check volume is loaded out of scene
volumeNode = slicer.util.getNode(pattern="grayscale")
self.assertIsNotNone( logic.hasImageData(volumeNode) )

# check the slice planes
red = slicer.util.getNode(pattern="vtkMRMLSliceNode1")
red.SetSliceVisible(1)

green = slicer.util.getNode(pattern="vtkMRMLSliceNode3")
green.SetSliceVisible(1)

# rotate a bit
cam = slicer.util.getNode(pattern='vtkMRMLCameraNode1')
cam.GetCamera().Azimuth(90)
cam.GetCamera().Elevation(20)

# turn off skin and skull
skin = slicer.util.getNode(pattern='Skin')
skin.GetDisplayNode().SetVisibility(0)

skull = slicer.util.getNode(pattern='skull_bone')
skull.GetDisplayNode().SetVisibility(0)

# clip the model hemispheric_white_matter.vtk
m = slicer.util.mainWindow()
m.moduleSelector().selectModule('Models')

models = slicer.util.getModule('Models')
logic = models.logic()

hemispheric_white_matter = slicer.util.getNode(pattern='hemispheric_white_matter')
hemispheric_white_matter.GetDisplayNode().SetClipping(1)

clip = slicer.util.getNode('ClipModelsParameters1')
clip.SetRedSliceClipState(0)
clip.SetYellowSliceClipState(0)
clip.SetGreenSliceClipState(2)

# Can we make this more than just a Smoke Test?
self.delayDisplay('Optic chiasm should be visible. Front part of white matter should be clipped.')

# Done
#
#
self.delayDisplay('Test passed!')
def setUp(self):
""" Do whatever is needed to reset the state - typically a scene clear will be enough.
"""
slicer.mrmlScene.Clear(0)

def runTest(self):
"""Run as few or as many tests as needed here.
"""
self.setUp()
self.test_Slicer4Minute1()

def test_Slicer4Minute1(self):
""" Tests parts of the Slicer4Minute tutorial.
Currently testing 'Part 2' which covers volumes, models, visibility and clipping.
"""
self.delayDisplay("Starting the test")

logic = Slicer4MinuteLogic()

#
# first, get some data
#
import SampleData
SampleData.downloadFromURL(
fileNames='slicer4minute.mrb',
loadFiles=True,
uris=TESTING_DATA_URL + 'SHA256/5a1c78c3347f77970b1a29e718bfa10e5376214692d55a7320af94b9d8d592b8',
checksums='SHA256:5a1c78c3347f77970b1a29e718bfa10e5376214692d55a7320af94b9d8d592b8')
self.delayDisplay('Finished with download and loading')

# Testing "Part 2" of Tutorial
#
#
self.delayDisplay('Testing Part 2 of the Tutorial')

# check volume is loaded out of scene
volumeNode = slicer.util.getNode(pattern="grayscale")
self.assertIsNotNone(logic.hasImageData(volumeNode))

# check the slice planes
red = slicer.util.getNode(pattern="vtkMRMLSliceNode1")
red.SetSliceVisible(1)

green = slicer.util.getNode(pattern="vtkMRMLSliceNode3")
green.SetSliceVisible(1)

# rotate a bit
cam = slicer.util.getNode(pattern='vtkMRMLCameraNode1')
cam.GetCamera().Azimuth(90)
cam.GetCamera().Elevation(20)

# turn off skin and skull
skin = slicer.util.getNode(pattern='Skin')
skin.GetDisplayNode().SetVisibility(0)

skull = slicer.util.getNode(pattern='skull_bone')
skull.GetDisplayNode().SetVisibility(0)

# clip the model hemispheric_white_matter.vtk
m = slicer.util.mainWindow()
m.moduleSelector().selectModule('Models')

models = slicer.util.getModule('Models')
logic = models.logic()

hemispheric_white_matter = slicer.util.getNode(pattern='hemispheric_white_matter')
hemispheric_white_matter.GetDisplayNode().SetClipping(1)

clip = slicer.util.getNode('ClipModelsParameters1')
clip.SetRedSliceClipState(0)
clip.SetYellowSliceClipState(0)
clip.SetGreenSliceClipState(2)

# Can we make this more than just a Smoke Test?
self.delayDisplay('Optic chiasm should be visible. Front part of white matter should be clipped.')

# Done
#
#
self.delayDisplay('Test passed!')
102 changes: 51 additions & 51 deletions Applications/SlicerApp/Testing/Python/SlicerAppTesting.py
Original file line number Diff line number Diff line change
@@ -36,71 +36,71 @@

__all__ = ['EXIT_FAILURE', 'EXIT_SUCCESS', 'run', 'runSlicer', 'runSlicerAndExit', 'timecall']

EXIT_FAILURE=1
EXIT_SUCCESS=0
EXIT_FAILURE = 1
EXIT_SUCCESS = 0


def dropcache():
if sys.platform in ["linux", "linux2"]:
run('/usr/bin/sudo', ['sysctl', 'vm.drop_caches=1'], drop_cache=False)
else:
# XXX Implement other platform (Windows: EmptyStandbyList ?, macOS: Purge ?)
raise Exception("--drop-cache is not supported on %s" % sys.platform)
if sys.platform in ["linux", "linux2"]:
run('/usr/bin/sudo', ['sysctl', 'vm.drop_caches=1'], drop_cache=False)
else:
# XXX Implement other platform (Windows: EmptyStandbyList ?, macOS: Purge ?)
raise Exception("--drop-cache is not supported on %s" % sys.platform)


def run(executable, arguments=[], verbose=True, shell=False, drop_cache=False):
"""Run ``executable`` with provided ``arguments``.
"""
if drop_cache:
dropcache()
if verbose:
print("{} {}".format(os.path.basename(executable), " ".join([pipes.quote(arg) for arg in arguments])))
arguments.insert(0, executable)
if shell:
arguments = " ".join([pipes.quote(arg) for arg in arguments])
p = subprocess.Popen(args=arguments, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, shell=shell)
stdout, stderr = p.communicate()
"""Run ``executable`` with provided ``arguments``.
"""
if drop_cache:
dropcache()
if verbose:
print("{} {}".format(os.path.basename(executable), " ".join([pipes.quote(arg) for arg in arguments])))
arguments.insert(0, executable)
if shell:
arguments = " ".join([pipes.quote(arg) for arg in arguments])
p = subprocess.Popen(args=arguments, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, shell=shell)
stdout, stderr = p.communicate()

if p.returncode != EXIT_SUCCESS:
print('STDERR: ' + stderr.decode(), file=sys.stderr)
if p.returncode != EXIT_SUCCESS:
print('STDERR: ' + stderr.decode(), file=sys.stderr)

return (p.returncode, stdout.decode(), stderr.decode())
return (p.returncode, stdout.decode(), stderr.decode())


def runSlicer(slicer_executable, arguments=[], verbose=True, **kwargs):
"""Run ``slicer_executable`` with provided ``arguments``.
"""
args = ['--no-splash']
args.extend(arguments)
return run(slicer_executable, args, verbose, **kwargs)
"""Run ``slicer_executable`` with provided ``arguments``.
"""
args = ['--no-splash']
args.extend(arguments)
return run(slicer_executable, args, verbose, **kwargs)


def runSlicerAndExit(slicer_executable, arguments=[], verbose=True, **kwargs):
"""Run ``slicer_executable`` with provided ``arguments`` and exit.
"""
args = ['--exit-after-startup']
args.extend(arguments)
return runSlicer(slicer_executable, args, verbose, **kwargs)
"""Run ``slicer_executable`` with provided ``arguments`` and exit.
"""
args = ['--exit-after-startup']
args.extend(arguments)
return runSlicer(slicer_executable, args, verbose, **kwargs)


def timecall(method, **kwargs):
"""Wrap ``method`` and return its execution time.
"""
repeat = 1
if 'repeat' in kwargs:
repeat = kwargs['repeat']

def wrapper(*args, **kwargs):
durations = []
for iteration in range(1, repeat + 1):
start = time.time()
result = method(*args, **kwargs)
durations.append(time.time() - start)
print(f"{iteration:d}/{repeat:d}: {durations[-1]:.2f}s")
average = sum(durations) / len(durations)
print(f"Average: {average:.2f}s\n")
duration = average
return (duration, result)

return wrapper
"""Wrap ``method`` and return its execution time.
"""
repeat = 1
if 'repeat' in kwargs:
repeat = kwargs['repeat']

def wrapper(*args, **kwargs):
durations = []
for iteration in range(1, repeat + 1):
start = time.time()
result = method(*args, **kwargs)
durations.append(time.time() - start)
print(f"{iteration:d}/{repeat:d}: {durations[-1]:.2f}s")
average = sum(durations) / len(durations)
print(f"Average: {average:.2f}s\n")
duration = average
return (duration, result)

return wrapper
472 changes: 236 additions & 236 deletions Applications/SlicerApp/Testing/Python/SlicerBoundsTest.py

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -9,114 +9,114 @@
#

class SlicerCreateRulerCrashIssue4199(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 = "Create ruler crash (Issue 4199)"
self.parent.categories = ["Testing.TestCases"]
self.parent.dependencies = []
self.parent.contributors = ["Jean-Christophe Fillion-Robin (Kitware)"] # replace with "Firstname Lastname (Organization)"
self.parent.helpText = """This test has been added to check that
"""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 = "Create ruler crash (Issue 4199)"
self.parent.categories = ["Testing.TestCases"]
self.parent.dependencies = []
self.parent.contributors = ["Jean-Christophe Fillion-Robin (Kitware)"] # replace with "Firstname Lastname (Organization)"
self.parent.helpText = """This test has been added to check that
Slicer does not crash after creating a ruler and entering
the Annotations module.
Problem has been documented in issue #4199.
"""
self.parent.acknowledgementText = """
self.parent.acknowledgementText = """
This file was originally developed by Jean-Christophe Fillion-Robin, Kitware Inc.
and was partially funded by NIH grant 1U24CA194354-01.
""" # replace with organization, grant and thanks.
""" # replace with organization, grant and thanks.


#
# SlicerCreateRulerCrashIssue4199Widget
#

class SlicerCreateRulerCrashIssue4199Widget(ScriptedLoadableModuleWidget):
"""Uses ScriptedLoadableModuleWidget base class, available at:
https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/ScriptedLoadableModule.py
"""
"""Uses ScriptedLoadableModuleWidget base class, available at:
https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/ScriptedLoadableModule.py
"""

def setup(self):
ScriptedLoadableModuleWidget.setup(self)
def setup(self):
ScriptedLoadableModuleWidget.setup(self)


#
# SlicerCreateRulerCrashIssue4199Logic
#

class SlicerCreateRulerCrashIssue4199Logic(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 hasImageData(self,volumeNode):
"""This is an example logic method that
returns true if the passed in volume
node has valid image data
"""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
"""
if not volumeNode:
logging.debug('hasImageData failed: no volume node')
return False
if volumeNode.GetImageData() is None:
logging.debug('hasImageData failed: no image data in volume node')
return False
return True

def hasImageData(self, volumeNode):
"""This is an example logic method that
returns true if the passed in volume
node has valid image data
"""
if not volumeNode:
logging.debug('hasImageData failed: no volume node')
return False
if volumeNode.GetImageData() is None:
logging.debug('hasImageData failed: no image data in volume node')
return False
return True

class SlicerCreateRulerCrashIssue4199Test(ScriptedLoadableModuleTest):
"""
This is the test case for your scripted module.
Uses ScriptedLoadableModuleTest base class, available at:
https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/ScriptedLoadableModule.py
"""

def setUp(self):
""" Do whatever is needed to reset the state - typically a scene clear will be enough.
"""
slicer.mrmlScene.Clear(0)

def runTest(self):
"""Run as few or as many tests as needed here.
class SlicerCreateRulerCrashIssue4199Test(ScriptedLoadableModuleTest):
"""
self.setUp()
self.test_SlicerCreateRulerCrashIssue4199()

def test_SlicerCreateRulerCrashIssue4199(self):
""" Ideally you should have several levels of tests. At the lowest level
tests should exercise the functionality of the logic with different inputs
(both valid and invalid). At higher levels your tests should emulate the
way the user would interact with your code and confirm that it still works
the way you intended.
One of the most important features of the tests is that it should alert other
developers when their changes will have an impact on the behavior of your
module. For example, if a developer removes a feature that you depend on,
your test should break so they know that the feature is needed.
This is the test case for your scripted module.
Uses ScriptedLoadableModuleTest base class, available at:
https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/ScriptedLoadableModule.py
"""

logic = SlicerCreateRulerCrashIssue4199Logic()
def setUp(self):
""" Do whatever is needed to reset the state - typically a scene clear will be enough.
"""
slicer.mrmlScene.Clear(0)

def runTest(self):
"""Run as few or as many tests as needed here.
"""
self.setUp()
self.test_SlicerCreateRulerCrashIssue4199()

def test_SlicerCreateRulerCrashIssue4199(self):
""" Ideally you should have several levels of tests. At the lowest level
tests should exercise the functionality of the logic with different inputs
(both valid and invalid). At higher levels your tests should emulate the
way the user would interact with your code and confirm that it still works
the way you intended.
One of the most important features of the tests is that it should alert other
developers when their changes will have an impact on the behavior of your
module. For example, if a developer removes a feature that you depend on,
your test should break so they know that the feature is needed.
"""

logic = SlicerCreateRulerCrashIssue4199Logic()

self.delayDisplay("Starting the test")
self.delayDisplay("Starting the test")

slicer.util.selectModule('Welcome')
slicer.util.selectModule('Welcome')

# Add a ruler
rulerNode = slicer.vtkMRMLAnnotationRulerNode()
rulerNode.SetPosition1(0, 0, 0)
rulerNode.SetPosition2(1, 1, 1)
rulerNode.Initialize(slicer.mrmlScene)
# Add a ruler
rulerNode = slicer.vtkMRMLAnnotationRulerNode()
rulerNode.SetPosition1(0, 0, 0)
rulerNode.SetPosition2(1, 1, 1)
rulerNode.Initialize(slicer.mrmlScene)

# Enter the Annotations module
slicer.util.selectModule('Annotations')
# Enter the Annotations module
slicer.util.selectModule('Annotations')

# If test reach this point without crashing it is a success
# If test reach this point without crashing it is a success

self.delayDisplay('Test passed!')
self.delayDisplay('Test passed!')
Original file line number Diff line number Diff line change
@@ -9,20 +9,20 @@
#

class SlicerMRBMultipleSaveRestoreLoopTest(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)
parent.title = "SlicerMRBMultipleSaveRestoreLoopTest"
parent.categories = ["Testing.TestCases"]
parent.contributors = ["Nicole Aucoin (BWH)"]
parent.helpText = """
"""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)
parent.title = "SlicerMRBMultipleSaveRestoreLoopTest"
parent.categories = ["Testing.TestCases"]
parent.contributors = ["Nicole Aucoin (BWH)"]
parent.helpText = """
Self test for MRB and Scene Views multiple save.
No module interface here, only used in SelfTests module
"""
parent.acknowledgementText = """
parent.acknowledgementText = """
This test was developed by
Nicole Aucoin, BWH
and was partially funded by NIH grant 3P41RR013218.
@@ -34,124 +34,124 @@ def __init__(self, parent):
#

class SlicerMRBMultipleSaveRestoreLoopTestWidget(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)


class SlicerMRBMultipleSaveRestoreLoop(ScriptedLoadableModuleTest):
"""
This is the test case for your scripted module.
Uses ScriptedLoadableModuleTest base class, available at:
https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/ScriptedLoadableModule.py
"""

def __init__(self, methodName='runTest', numberOfIterations=5, uniqueDirectory=True, strict=False):
"""Uses ScriptedLoadableModuleWidget base class, available at:
https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/ScriptedLoadableModule.py
"""
Tests the use of mrml and mrb save formats with volumes and point lists.
Checks that scene views are saved and restored as expected after multiple
MRB saves and loads.
numberOfIterations: integer number of times to save and restore an MRB.
uniqueDirectory: boolean about save directory
False to reuse standard dir name
True timestamps dir name
strict: boolean about how carefully to check result
True then check every detail
False then confirm basic operation, but allow non-critical issues to pass
"""
ScriptedLoadableModuleTest.__init__(self, methodName)
self.numberOfIterations = numberOfIterations
self.uniqueDirectory = uniqueDirectory
self.strict = strict

def setUp(self):
slicer.mrmlScene.Clear(0)
def setup(self):
ScriptedLoadableModuleWidget.setup(self)

def runTest(self):
self.setUp()
self.test_SlicerMRBMultipleSaveRestoreLoop()

def test_SlicerMRBMultipleSaveRestoreLoop(self):
class SlicerMRBMultipleSaveRestoreLoop(ScriptedLoadableModuleTest):
"""
Stress test the issue reported in bug 3956 where saving
and restoring an MRB file does not work.
This is the test case for your scripted module.
Uses ScriptedLoadableModuleTest base class, available at:
https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/ScriptedLoadableModule.py
"""

print("Running SlicerMRBMultipleSaveRestoreLoop Test case with:")
print("numberOfIterations: %s" % self.numberOfIterations)
print("uniqueDirectory : %s" % self.uniqueDirectory)
print("strict : %s" % self.strict)

#
# first, get the data
#
print("Getting MR Head Volume")
import SampleData
mrHeadVolume = SampleData.downloadSample("MRHead")

# Place a control point
pointListNode = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLMarkupsFiducialNode", "F")
pointListNode.CreateDefaultDisplayNodes()
fid1 = [0.0, 0.0, 0.0]
fidIndex1 = pointListNode.AddControlPoint(fid1)

self.delayDisplay('Finished with download and placing points')

ioManager = slicer.app.ioManager()
widget = slicer.app.layoutManager().viewport()
self.pointPosition = fid1
for i in range(self.numberOfIterations):

print('\n\nIteration %s' % i)
#
# save the mrml scene to an mrb
#
sceneSaveDirectory = slicer.util.tempDirectory('__scene__')
mrbFilePath = slicer.util.tempDirectory('__mrb__') + '/SlicerMRBMultipleSaveRestoreLoop-' + str(i) + '.mrb'
self.delayDisplay("Saving mrb to: %s" % mrbFilePath)
screenShot = ctk.ctkWidgetsUtils.grabWidget(widget)
self.assertTrue(
ioManager.saveScene(mrbFilePath, screenShot)
)
self.delayDisplay("Finished saving MRB %s" % i)

#
# reload the mrb
#
slicer.mrmlScene.Clear(0)
self.delayDisplay('Now, reload the saved MRB')
mrbLoaded = ioManager.loadScene(mrbFilePath)

# load can return false even though it succeeded - only fail if in strict mode
self.assertTrue( not self.strict or mrbLoaded )
slicer.app.processEvents()

# confirm that MRHead is in the background of the Red slice
redComposite = slicer.util.getNode('vtkMRMLSliceCompositeNodeRed')
mrHead = slicer.util.getNode('MRHead')
self.assertEqual(redComposite.GetBackgroundVolumeID(), mrHead.GetID())
self.delayDisplay('The MRHead volume is AGAIN in the background of the Red viewer')

# confirm that the point list exists with 1 points
pointListNode = slicer.util.getNode('F')
self.assertEqual(pointListNode.GetNumberOfControlPoints(), 1)
self.delayDisplay('The point list has 1 point in it')

# adjust the fid list location
self.pointPosition = [i, i, i]
print((i, ': reset point position array to ', self.pointPosition))
pointListNode.SetNthControlPointPosition(0, self.pointPosition)
self.delayDisplay("Loop Finished")

print(('Point position from loop = ',self.pointPosition))
pointListNode = slicer.util.getNode('F')
finalPointPosition = [ 0,0,0 ]
pointListNode.GetNthControlPointPosition(0, finalPointPosition)
print(('Final point scene pos = ',finalPointPosition))
self.assertEqual(self.pointPosition, finalPointPosition)

self.delayDisplay("Test Finished")
def __init__(self, methodName='runTest', numberOfIterations=5, uniqueDirectory=True, strict=False):
"""
Tests the use of mrml and mrb save formats with volumes and point lists.
Checks that scene views are saved and restored as expected after multiple
MRB saves and loads.
numberOfIterations: integer number of times to save and restore an MRB.
uniqueDirectory: boolean about save directory
False to reuse standard dir name
True timestamps dir name
strict: boolean about how carefully to check result
True then check every detail
False then confirm basic operation, but allow non-critical issues to pass
"""
ScriptedLoadableModuleTest.__init__(self, methodName)
self.numberOfIterations = numberOfIterations
self.uniqueDirectory = uniqueDirectory
self.strict = strict

def setUp(self):
slicer.mrmlScene.Clear(0)

def runTest(self):
self.setUp()
self.test_SlicerMRBMultipleSaveRestoreLoop()

def test_SlicerMRBMultipleSaveRestoreLoop(self):
"""
Stress test the issue reported in bug 3956 where saving
and restoring an MRB file does not work.
"""

print("Running SlicerMRBMultipleSaveRestoreLoop Test case with:")
print("numberOfIterations: %s" % self.numberOfIterations)
print("uniqueDirectory : %s" % self.uniqueDirectory)
print("strict : %s" % self.strict)

#
# first, get the data
#
print("Getting MR Head Volume")
import SampleData
mrHeadVolume = SampleData.downloadSample("MRHead")

# Place a control point
pointListNode = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLMarkupsFiducialNode", "F")
pointListNode.CreateDefaultDisplayNodes()
fid1 = [0.0, 0.0, 0.0]
fidIndex1 = pointListNode.AddControlPoint(fid1)

self.delayDisplay('Finished with download and placing points')

ioManager = slicer.app.ioManager()
widget = slicer.app.layoutManager().viewport()
self.pointPosition = fid1
for i in range(self.numberOfIterations):

print('\n\nIteration %s' % i)
#
# save the mrml scene to an mrb
#
sceneSaveDirectory = slicer.util.tempDirectory('__scene__')
mrbFilePath = slicer.util.tempDirectory('__mrb__') + '/SlicerMRBMultipleSaveRestoreLoop-' + str(i) + '.mrb'
self.delayDisplay("Saving mrb to: %s" % mrbFilePath)
screenShot = ctk.ctkWidgetsUtils.grabWidget(widget)
self.assertTrue(
ioManager.saveScene(mrbFilePath, screenShot)
)
self.delayDisplay("Finished saving MRB %s" % i)

#
# reload the mrb
#
slicer.mrmlScene.Clear(0)
self.delayDisplay('Now, reload the saved MRB')
mrbLoaded = ioManager.loadScene(mrbFilePath)

# load can return false even though it succeeded - only fail if in strict mode
self.assertTrue(not self.strict or mrbLoaded)
slicer.app.processEvents()

# confirm that MRHead is in the background of the Red slice
redComposite = slicer.util.getNode('vtkMRMLSliceCompositeNodeRed')
mrHead = slicer.util.getNode('MRHead')
self.assertEqual(redComposite.GetBackgroundVolumeID(), mrHead.GetID())
self.delayDisplay('The MRHead volume is AGAIN in the background of the Red viewer')

# confirm that the point list exists with 1 points
pointListNode = slicer.util.getNode('F')
self.assertEqual(pointListNode.GetNumberOfControlPoints(), 1)
self.delayDisplay('The point list has 1 point in it')

# adjust the fid list location
self.pointPosition = [i, i, i]
print((i, ': reset point position array to ', self.pointPosition))
pointListNode.SetNthControlPointPosition(0, self.pointPosition)
self.delayDisplay("Loop Finished")

print(('Point position from loop = ', self.pointPosition))
pointListNode = slicer.util.getNode('F')
finalPointPosition = [0, 0, 0]
pointListNode.GetNthControlPointPosition(0, finalPointPosition)
print(('Final point scene pos = ', finalPointPosition))
self.assertEqual(self.pointPosition, finalPointPosition)

self.delayDisplay("Test Finished")
406 changes: 203 additions & 203 deletions Applications/SlicerApp/Testing/Python/SlicerMRBMultipleSaveRestoreTest.py

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -30,79 +30,79 @@


def checkUserSettings(slicer_executable, common_args, keep_temporary_settings=False):
# Add a user setting
args = list(common_args)
args.extend(['--python-code',
'slicer.app.userSettings().setValue("foo", "bar"); print("foo: %s" % slicer.app.userSettings().value("foo"))'])
assert runSlicerAndExit(slicer_executable, args)[0] == EXIT_SUCCESS
print("=> ok\n")

# User settings previously added should:
# * NOT be set by detault
# * be set if '--keep-temporary-settings' is provided
args = list(common_args)
condition = 'is not None'
error = "Setting foo should NOT be set"
if keep_temporary_settings:
args.append('--keep-temporary-settings')
condition = '!= "bar"'
error = "Setting foo should be set to bar"
args.extend(['--python-code',
'if slicer.app.userSettings().value("foo") ' + condition + ': raise Exception("' + error + '.")'])
assert runSlicerAndExit(slicer_executable, args)[0] == EXIT_SUCCESS
print("=> ok\n")
# Add a user setting
args = list(common_args)
args.extend(['--python-code',
'slicer.app.userSettings().setValue("foo", "bar"); print("foo: %s" % slicer.app.userSettings().value("foo"))'])
assert runSlicerAndExit(slicer_executable, args)[0] == EXIT_SUCCESS
print("=> ok\n")

# User settings previously added should:
# * NOT be set by detault
# * be set if '--keep-temporary-settings' is provided
args = list(common_args)
condition = 'is not None'
error = "Setting foo should NOT be set"
if keep_temporary_settings:
args.append('--keep-temporary-settings')
condition = '!= "bar"'
error = "Setting foo should be set to bar"
args.extend(['--python-code',
'if slicer.app.userSettings().value("foo") ' + condition + ': raise Exception("' + error + '.")'])
assert runSlicerAndExit(slicer_executable, args)[0] == EXIT_SUCCESS
print("=> ok\n")


def checkRevisionUserSettings(slicer_executable, common_args, keep_temporary_settings=False):
# Add a user revision setting
args = list(common_args)
args.extend(['--python-code',
'slicer.app.revisionUserSettings().setValue("foo", "bar"); print("foo: %s" % slicer.app.revisionUserSettings().value("foo"))'])
assert runSlicerAndExit(slicer_executable, args)[0] == EXIT_SUCCESS
print("=> ok\n")

# User revision settings previously added should:
# * NOT be set by detault
# * be set if '--keep-temporary-settings' is provided
args = list(common_args)
condition = 'is not None'
error = "Setting foo should NOT be set"
if keep_temporary_settings:
args.append('--keep-temporary-settings')
condition = '!= "bar"'
error = "Setting foo should be set to bar"
args.extend(['--python-code',
'if slicer.app.revisionUserSettings().value("foo") ' + condition + ': raise Exception("' + error + '.")'])
assert runSlicerAndExit(slicer_executable, args)[0] == EXIT_SUCCESS
print("=> ok\n")
# Add a user revision setting
args = list(common_args)
args.extend(['--python-code',
'slicer.app.revisionUserSettings().setValue("foo", "bar"); print("foo: %s" % slicer.app.revisionUserSettings().value("foo"))'])
assert runSlicerAndExit(slicer_executable, args)[0] == EXIT_SUCCESS
print("=> ok\n")

# User revision settings previously added should:
# * NOT be set by detault
# * be set if '--keep-temporary-settings' is provided
args = list(common_args)
condition = 'is not None'
error = "Setting foo should NOT be set"
if keep_temporary_settings:
args.append('--keep-temporary-settings')
condition = '!= "bar"'
error = "Setting foo should be set to bar"
args.extend(['--python-code',
'if slicer.app.revisionUserSettings().value("foo") ' + condition + ': raise Exception("' + error + '.")'])
assert runSlicerAndExit(slicer_executable, args)[0] == EXIT_SUCCESS
print("=> ok\n")


def checkKeepTemporarySettingsWithoutDisableSettingsDisplayWarning(slicer_executable, common_args):
args = list(common_args)
args.remove('--disable-settings')
args.extend(['--keep-temporary-settings'])
(returnCode, stdout, stderr) = runSlicerAndExit(slicer_executable, args)
expectedMessage = "Argument '--keep-temporary-settings' requires '--settings-disabled' to be specified."
if expectedMessage not in stderr:
print(f"=> return code{returnCode}\n")
raise Exception(f"Warning [{expectedMessage}] not found in stderr [{stderr}]")
assert returnCode == EXIT_SUCCESS
print("=> ok\n")
args = list(common_args)
args.remove('--disable-settings')
args.extend(['--keep-temporary-settings'])
(returnCode, stdout, stderr) = runSlicerAndExit(slicer_executable, args)
expectedMessage = "Argument '--keep-temporary-settings' requires '--settings-disabled' to be specified."
if expectedMessage not in stderr:
print(f"=> return code{returnCode}\n")
raise Exception(f"Warning [{expectedMessage}] not found in stderr [{stderr}]")
assert returnCode == EXIT_SUCCESS
print("=> ok\n")


if __name__ == '__main__':

if len(sys.argv) != 2:
print(os.path.basename(sys.argv[0]) +" /path/to/Slicer")
exit(EXIT_FAILURE)
if len(sys.argv) != 2:
print(os.path.basename(sys.argv[0]) + " /path/to/Slicer")
exit(EXIT_FAILURE)

slicer_executable = os.path.expanduser(sys.argv[1])
common_args = ['--disable-settings', '--disable-modules', '--no-main-window']
slicer_executable = os.path.expanduser(sys.argv[1])
common_args = ['--disable-settings', '--disable-modules', '--no-main-window']

checkUserSettings(slicer_executable, common_args)
checkRevisionUserSettings(slicer_executable, common_args)
checkUserSettings(slicer_executable, common_args)
checkRevisionUserSettings(slicer_executable, common_args)

checkUserSettings(slicer_executable, common_args, keep_temporary_settings=True)
checkRevisionUserSettings(slicer_executable, common_args, keep_temporary_settings=True)
checkUserSettings(slicer_executable, common_args, keep_temporary_settings=True)
checkRevisionUserSettings(slicer_executable, common_args, keep_temporary_settings=True)

checkKeepTemporarySettingsWithoutDisableSettingsDisplayWarning(slicer_executable, common_args)
checkKeepTemporarySettingsWithoutDisableSettingsDisplayWarning(slicer_executable, common_args)
Original file line number Diff line number Diff line change
@@ -31,61 +31,62 @@

if __name__ == '__main__':

debug = False # Set to True to:
# * display the path of the created slicerrc file
# * avoid deleting the slicerrc file
debug = False
# Set to True to:
# * display the path of the created slicerrc file
# * avoid deleting the slicerrc file

if len(sys.argv) != 2:
print(os.path.basename(sys.argv[0]) +" /path/to/Slicer")
exit(EXIT_FAILURE)
if len(sys.argv) != 2:
print(os.path.basename(sys.argv[0]) + " /path/to/Slicer")
exit(EXIT_FAILURE)

slicer_executable = os.path.expanduser(sys.argv[1])
common_args = ['--disable-modules', '--no-main-window']
slicer_executable = os.path.expanduser(sys.argv[1])
common_args = ['--disable-modules', '--no-main-window']

fd, slicerrc = tempfile.mkstemp()
assert os.path.isfile(slicerrc)
try:
fd, slicerrc = tempfile.mkstemp()
assert os.path.isfile(slicerrc)
try:

# Create a slicerrc file that creates SLICERRCTESTOUTPUT file when executed
with os.fdopen(fd, 'w') as file:
file.write("# Generated by SlicerOptionIgnoreSlicerRCTest.py\n"+\
"import os\n"+\
"fd = os.open(os.environ['SLICERRCTESTOUTPUT'], os.O_RDWR|os.O_CREAT)\n"+\
"os.write(fd, 'Generated by SlicerOptionIgnoreSlicerRCTest.py test when slicerrc executed'.encode())\n"+\
"os.close(fd)\n")
# Create a slicerrc file that creates SLICERRCTESTOUTPUT file when executed
with os.fdopen(fd, 'w') as file:
file.write("# Generated by SlicerOptionIgnoreSlicerRCTest.py\n" +\
"import os\n" +\
"fd = os.open(os.environ['SLICERRCTESTOUTPUT'], os.O_RDWR|os.O_CREAT)\n" +\
"os.write(fd, 'Generated by SlicerOptionIgnoreSlicerRCTest.py test when slicerrc executed'.encode())\n" +\
"os.close(fd)\n")

slicerrctestoutput = slicerrc + ".out"
os.environ['SLICERRC'] = slicerrc
os.environ['SLICERRCTESTOUTPUT'] = slicerrctestoutput
if debug:
print("SLICERRC=%s" % slicerrc)
print("SLICERRCTESTOUTPUT=%s" % slicerrctestoutput)
slicerrctestoutput = slicerrc + ".out"
os.environ['SLICERRC'] = slicerrc
os.environ['SLICERRCTESTOUTPUT'] = slicerrctestoutput
if debug:
print("SLICERRC=%s" % slicerrc)
print("SLICERRCTESTOUTPUT=%s" % slicerrctestoutput)

# Check that slicerrc file is loaded
args = list(common_args)
(returnCode, stdout, stderr) = runSlicerAndExit(slicer_executable, args)
assert os.path.isfile(slicerrctestoutput)
os.remove(slicerrctestoutput)
assert returnCode == EXIT_SUCCESS
print("=> ok\n")
# Check that slicerrc file is loaded
args = list(common_args)
(returnCode, stdout, stderr) = runSlicerAndExit(slicer_executable, args)
assert os.path.isfile(slicerrctestoutput)
os.remove(slicerrctestoutput)
assert returnCode == EXIT_SUCCESS
print("=> ok\n")

# Check that --ignore-slicerrc works
args = list(common_args)
args.extend(['--ignore-slicerrc'])
(returnCode, stdout, stderr) = runSlicerAndExit(slicer_executable, args)
assert not os.path.isfile(slicerrctestoutput)
assert returnCode == EXIT_SUCCESS
print("=> ok\n")
# Check that --ignore-slicerrc works
args = list(common_args)
args.extend(['--ignore-slicerrc'])
(returnCode, stdout, stderr) = runSlicerAndExit(slicer_executable, args)
assert not os.path.isfile(slicerrctestoutput)
assert returnCode == EXIT_SUCCESS
print("=> ok\n")

# Check that --testing implies --ignore-slicerrc
args = list(common_args)
args.extend(['--testing'])
(returnCode, stdout, stderr) = runSlicerAndExit(slicer_executable, args)
assert not os.path.isfile(slicerrctestoutput)
assert returnCode == EXIT_SUCCESS
print("=> ok\n")
finally:
if not debug:
os.remove(slicerrc)
if os.path.isfile(slicerrctestoutput):
os.remove(slicerrctestoutput)
# Check that --testing implies --ignore-slicerrc
args = list(common_args)
args.extend(['--testing'])
(returnCode, stdout, stderr) = runSlicerAndExit(slicer_executable, args)
assert not os.path.isfile(slicerrctestoutput)
assert returnCode == EXIT_SUCCESS
print("=> ok\n")
finally:
if not debug:
os.remove(slicerrc)
if os.path.isfile(slicerrctestoutput):
os.remove(slicerrctestoutput)
Original file line number Diff line number Diff line change
@@ -32,88 +32,89 @@

if __name__ == '__main__':

debug = False # Set to True to:
# * display the path of the created extension_dir
# * avoid deleting the extension_dir
debug = False
# Set to True to:
# * display the path of the created extension_dir
# * avoid deleting the extension_dir

if len(sys.argv) != 3:
print(os.path.basename(sys.argv[0]) +" /path/to/Slicer /path/to/slicerExtensionWizard")
exit(EXIT_FAILURE)
if len(sys.argv) != 3:
print(os.path.basename(sys.argv[0]) + " /path/to/Slicer /path/to/slicerExtensionWizard")
exit(EXIT_FAILURE)

slicer_executable = os.path.expanduser(sys.argv[1])
slicer_extension_wizard = os.path.expanduser(sys.argv[2])
slicer_executable = os.path.expanduser(sys.argv[1])
slicer_extension_wizard = os.path.expanduser(sys.argv[2])

common_args = ['--testing', '--disable-builtin-modules', '--no-main-window']
common_args = ['--testing', '--disable-builtin-modules', '--no-main-window']

# Prerequisites:
# * create temporary extension directory
# * create an extension with four scripted modules: A, B, C and D
# Prerequisites:
# * create temporary extension directory
# * create an extension with four scripted modules: A, B, C and D

extension_dir = tempfile.mkdtemp()
assert os.path.isdir(extension_dir)
if debug:
print("extension_dir: %s" % extension_dir)
extension_dir = tempfile.mkdtemp()
assert os.path.isdir(extension_dir)
if debug:
print("extension_dir: %s" % extension_dir)

moduleNames = ['A', 'B', 'C', 'D']
moduleNames = ['A', 'B', 'C', 'D']

additional_module_paths = ['--additional-module-paths']
additional_module_paths.extend([f'{extension_dir}/Test/{moduleName}' for moduleName in moduleNames])
additional_module_paths = ['--additional-module-paths']
additional_module_paths.extend([f'{extension_dir}/Test/{moduleName}' for moduleName in moduleNames])

args = ['--create', 'Test']
for moduleName in moduleNames:
args.extend(['--addModule', 'scripted:%s' % moduleName])
args.extend([extension_dir])
(returnCode, stdout, stderr) = run(slicer_extension_wizard, args, shell=True)
assert returnCode == EXIT_SUCCESS
print("=> ok\n")

try:

# Check that the modules are loaded
args = list(common_args)
args.extend(['--python-code', 'assert len([module for module in dir(slicer.moduleNames) if module in ["A", "B", "C", "D"]]) == 4, "Failed to load modules"'])
args.extend(additional_module_paths)
(returnCode, stdout, stderr) = runSlicerAndExit(slicer_executable, args)
assert returnCode == EXIT_SUCCESS
print("=> ok\n")

# Update settings disabling module B
args = list(common_args)
args.extend(['--keep-temporary-settings'])
args.extend(['--python-code', 'slicer.app.moduleManager().factoryManager().modulesToIgnore = ["B"]'])
args.extend(additional_module_paths)
(returnCode, stdout, stderr) = runSlicerAndExit(slicer_executable, args)
assert returnCode == EXIT_SUCCESS
print("=> ok\n")

# Run application to check that module B is disabled
args = list(common_args)
args.extend(['--keep-temporary-settings'])
args.extend(['--python-code', 'assert len([module for module in dir(slicer.moduleNames) if module in ["A", "C", "D"]]) == 3, "Failed to disable modules"'])
args.extend(additional_module_paths)
(returnCode, stdout, stderr) = runSlicerAndExit(slicer_executable, args)
assert returnCode == EXIT_SUCCESS
print("=> ok\n")

# Run application given "--modules-to-ignore A,D" and check that A, D and B are disabled
args = list(common_args)
args.extend(['--keep-temporary-settings'])
args.extend(['--modules-to-ignore', 'A,D'])
args.extend(['--python-code', 'assert len([module for module in dir(slicer.moduleNames) if module in ["C"]]) == 1, "Failed to disable modules"'])
args.extend(additional_module_paths)
(returnCode, stdout, stderr) = runSlicerAndExit(slicer_executable, args)
assert returnCode == EXIT_SUCCESS
print("=> ok\n")

# Run application to check that only B remains disabled
args = list(common_args)
args.extend(['--keep-temporary-settings'])
args.extend(['--python-code', 'assert len([module for module in dir(slicer.moduleNames) if module in ["A", "C", "D"]]) == 3, "Failed to disable modules"'])
args.extend(additional_module_paths)
(returnCode, stdout, stderr) = runSlicerAndExit(slicer_executable, args)
args = ['--create', 'Test']
for moduleName in moduleNames:
args.extend(['--addModule', 'scripted:%s' % moduleName])
args.extend([extension_dir])
(returnCode, stdout, stderr) = run(slicer_extension_wizard, args, shell=True)
assert returnCode == EXIT_SUCCESS
print("=> ok\n")

finally:
if not debug:
shutil.rmtree(extension_dir)
try:

# Check that the modules are loaded
args = list(common_args)
args.extend(['--python-code', 'assert len([module for module in dir(slicer.moduleNames) if module in ["A", "B", "C", "D"]]) == 4, "Failed to load modules"'])
args.extend(additional_module_paths)
(returnCode, stdout, stderr) = runSlicerAndExit(slicer_executable, args)
assert returnCode == EXIT_SUCCESS
print("=> ok\n")

# Update settings disabling module B
args = list(common_args)
args.extend(['--keep-temporary-settings'])
args.extend(['--python-code', 'slicer.app.moduleManager().factoryManager().modulesToIgnore = ["B"]'])
args.extend(additional_module_paths)
(returnCode, stdout, stderr) = runSlicerAndExit(slicer_executable, args)
assert returnCode == EXIT_SUCCESS
print("=> ok\n")

# Run application to check that module B is disabled
args = list(common_args)
args.extend(['--keep-temporary-settings'])
args.extend(['--python-code', 'assert len([module for module in dir(slicer.moduleNames) if module in ["A", "C", "D"]]) == 3, "Failed to disable modules"'])
args.extend(additional_module_paths)
(returnCode, stdout, stderr) = runSlicerAndExit(slicer_executable, args)
assert returnCode == EXIT_SUCCESS
print("=> ok\n")

# Run application given "--modules-to-ignore A,D" and check that A, D and B are disabled
args = list(common_args)
args.extend(['--keep-temporary-settings'])
args.extend(['--modules-to-ignore', 'A,D'])
args.extend(['--python-code', 'assert len([module for module in dir(slicer.moduleNames) if module in ["C"]]) == 1, "Failed to disable modules"'])
args.extend(additional_module_paths)
(returnCode, stdout, stderr) = runSlicerAndExit(slicer_executable, args)
assert returnCode == EXIT_SUCCESS
print("=> ok\n")

# Run application to check that only B remains disabled
args = list(common_args)
args.extend(['--keep-temporary-settings'])
args.extend(['--python-code', 'assert len([module for module in dir(slicer.moduleNames) if module in ["A", "C", "D"]]) == 3, "Failed to disable modules"'])
args.extend(additional_module_paths)
(returnCode, stdout, stderr) = runSlicerAndExit(slicer_executable, args)
assert returnCode == EXIT_SUCCESS
print("=> ok\n")

finally:
if not debug:
shutil.rmtree(extension_dir)
188 changes: 94 additions & 94 deletions Applications/SlicerApp/Testing/Python/SlicerOrientationSelectorTest.py
Original file line number Diff line number Diff line change
@@ -9,123 +9,123 @@
#

class SlicerOrientationSelectorTest(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 = "Create ruler crash (Issue 4199)"
self.parent.categories = ["Testing.TestCases"]
self.parent.dependencies = []
self.parent.contributors = ["Jean-Christophe Fillion-Robin (Kitware)",
"Davide Punzo (Kapteyn astronomical institute)"] # replace with "Firstname Lastname (Organization)"
self.parent.helpText = """This test has been added to check that
"""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 = "Create ruler crash (Issue 4199)"
self.parent.categories = ["Testing.TestCases"]
self.parent.dependencies = []
self.parent.contributors = ["Jean-Christophe Fillion-Robin (Kitware)",
"Davide Punzo (Kapteyn astronomical institute)"] # replace with "Firstname Lastname (Organization)"
self.parent.helpText = """This test has been added to check that
orientation selector is correctly updated when updating the SliceToRAS matrix.
"""
self.parent.acknowledgementText = """
self.parent.acknowledgementText = """
This file was originally developed by Jean-Christophe Fillion-Robin, Kitware Inc.
and was partially funded by NIH grant 1U24CA194354-01.
""" # replace with organization, grant and thanks.
""" # replace with organization, grant and thanks.


#
# SlicerOrientationSelectorTestWidget
#

class SlicerOrientationSelectorTestWidget(ScriptedLoadableModuleWidget):
"""Uses ScriptedLoadableModuleWidget base class, available at:
https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/ScriptedLoadableModule.py
"""
"""Uses ScriptedLoadableModuleWidget base class, available at:
https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/ScriptedLoadableModule.py
"""

def setup(self):
ScriptedLoadableModuleWidget.setup(self)
def setup(self):
ScriptedLoadableModuleWidget.setup(self)


#
# SlicerOrientationSelectorTestLogic
#

class SlicerOrientationSelectorTestLogic(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 hasImageData(self,volumeNode):
"""This is an example logic method that
returns true if the passed in volume
node has valid image data
"""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
"""
if not volumeNode:
logging.debug('hasImageData failed: no volume node')
return False
if volumeNode.GetImageData() is None:
logging.debug('hasImageData failed: no image data in volume node')
return False
return True

def hasImageData(self, volumeNode):
"""This is an example logic method that
returns true if the passed in volume
node has valid image data
"""
if not volumeNode:
logging.debug('hasImageData failed: no volume node')
return False
if volumeNode.GetImageData() is None:
logging.debug('hasImageData failed: no image data in volume node')
return False
return True

class SlicerOrientationSelectorTestTest(ScriptedLoadableModuleTest):
"""
This is the test case for your scripted module.
Uses ScriptedLoadableModuleTest base class, available at:
https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/ScriptedLoadableModule.py
"""

def setUp(self):
""" Do whatever is needed to reset the state - typically a scene clear will be enough.
"""
slicer.mrmlScene.Clear(0)

def runTest(self):
"""Run as few or as many tests as needed here.
class SlicerOrientationSelectorTestTest(ScriptedLoadableModuleTest):
"""
self.setUp()
self.test_SlicerOrientationSelectorTest()

def test_SlicerOrientationSelectorTest(self):
""" Ideally you should have several levels of tests. At the lowest level
tests should exercise the functionality of the logic with different inputs
(both valid and invalid). At higher levels your tests should emulate the
way the user would interact with your code and confirm that it still works
the way you intended.
One of the most important features of the tests is that it should alert other
developers when their changes will have an impact on the behavior of your
module. For example, if a developer removes a feature that you depend on,
your test should break so they know that the feature is needed.
This is the test case for your scripted module.
Uses ScriptedLoadableModuleTest base class, available at:
https://github.com/Slicer/Slicer/blob/master/Base/Python/slicer/ScriptedLoadableModule.py
"""

logic = SlicerOrientationSelectorTestLogic()

self.delayDisplay("Starting the test")
import SampleData
mrHeadVolume = SampleData.downloadSample("MRHead")

slicer.util.selectModule('Reformat')

# Select Red slice
widget = slicer.modules.reformat.widgetRepresentation()
sliceNodeSelector = slicer.util.findChildren(widget, "SliceNodeSelector")[0]
sliceNodeSelector.setCurrentNodeID("vtkMRMLSliceNodeRed")

# Set LR value using Reformat module
lrslider = slicer.util.findChildren(widget, "LRSlider")[0]
lrslider.value = 1

# Get reference to the Red slice controller
lm = slicer.app.layoutManager()
sliceWidget = lm.sliceWidget("Red")
sliceOrientationSelector = slicer.util.findChildren(sliceWidget, "SliceOrientationSelector")[0]

# Check orientations associated with orientations selector
orientations = [sliceOrientationSelector.itemText(idx) for idx in range(sliceOrientationSelector.count)]
expectedOrientations = ['Axial', 'Sagittal', 'Coronal', 'Reformat']
if orientations != expectedOrientations:
raise Exception(f'Problem with orientation selector\norientations: {orientations}\nexpectedOrientations: {expectedOrientations}')

self.delayDisplay('Test passed!')
def setUp(self):
""" Do whatever is needed to reset the state - typically a scene clear will be enough.
"""
slicer.mrmlScene.Clear(0)

def runTest(self):
"""Run as few or as many tests as needed here.
"""
self.setUp()
self.test_SlicerOrientationSelectorTest()

def test_SlicerOrientationSelectorTest(self):
""" Ideally you should have several levels of tests. At the lowest level
tests should exercise the functionality of the logic with different inputs
(both valid and invalid). At higher levels your tests should emulate the
way the user would interact with your code and confirm that it still works
the way you intended.
One of the most important features of the tests is that it should alert other
developers when their changes will have an impact on the behavior of your
module. For example, if a developer removes a feature that you depend on,
your test should break so they know that the feature is needed.
"""

logic = SlicerOrientationSelectorTestLogic()

self.delayDisplay("Starting the test")
import SampleData
mrHeadVolume = SampleData.downloadSample("MRHead")

slicer.util.selectModule('Reformat')

# Select Red slice
widget = slicer.modules.reformat.widgetRepresentation()
sliceNodeSelector = slicer.util.findChildren(widget, "SliceNodeSelector")[0]
sliceNodeSelector.setCurrentNodeID("vtkMRMLSliceNodeRed")

# Set LR value using Reformat module
lrslider = slicer.util.findChildren(widget, "LRSlider")[0]
lrslider.value = 1

# Get reference to the Red slice controller
lm = slicer.app.layoutManager()
sliceWidget = lm.sliceWidget("Red")
sliceOrientationSelector = slicer.util.findChildren(sliceWidget, "SliceOrientationSelector")[0]

# Check orientations associated with orientations selector
orientations = [sliceOrientationSelector.itemText(idx) for idx in range(sliceOrientationSelector.count)]
expectedOrientations = ['Axial', 'Sagittal', 'Coronal', 'Reformat']
if orientations != expectedOrientations:
raise Exception(f'Problem with orientation selector\norientations: {orientations}\nexpectedOrientations: {expectedOrientations}')

self.delayDisplay('Test passed!')
Loading