diff --git a/CMake/SlicerExtensionTemplatesGenerator.cmake b/CMake/SlicerExtensionTemplatesGenerator.cmake index 89ae8a8fa4e..5d6334db1d4 100644 --- a/CMake/SlicerExtensionTemplatesGenerator.cmake +++ b/CMake/SlicerExtensionTemplatesGenerator.cmake @@ -81,7 +81,7 @@ macro(_append_extension_template_generator_commands module_type) endmacro() # Loop over module type and add template generators -foreach(type IN ITEMS CLI Loadable ScriptedLoadable) +foreach(type IN ITEMS CLI PythonCLI Loadable ScriptedLoadable) _append_extension_template_generator_commands(${type}) endforeach() diff --git a/Extensions/PythonCLIExtensionTemplate.s4ext b/Extensions/PythonCLIExtensionTemplate.s4ext new file mode 100644 index 00000000000..2ce8e785a1a --- /dev/null +++ b/Extensions/PythonCLIExtensionTemplate.s4ext @@ -0,0 +1,44 @@ +# +# First token of each non-comment line is the keyword and the rest of the line +# (including spaces) is the value. +# - the value can be blank +# + +# This is source code manager (i.e. svn) +scm local +scmurl Testing/PythonCLIExtensionTemplate +scmrevision NA + +# list dependencies +# - These should be names of other modules that have .s4ext files +# - The dependencies will be built first +depends NA + +# Inner build directory (default is ".") +build_subdirectory . + +# homepage +homepage http://slicer.org/slicerWiki/index.php/Documentation/Nightly/Extensions/PythonCLIExtensionTemplate + +# Firstname1 Lastname1 ([SubOrg1, ]Org1), Firstname2 Lastname2 ([SubOrg2, ]Org2) +# For example: Jane Roe (Superware), John Doe (Lab1, Nowhere), Joe Bloggs (Noware) +contributors John Doe (AnyWare Corp.) + +# Match category in the xml description of the module (where it shows up in Modules menu) +category Examples + +# url to icon (png, size 128x128 pixels) +iconurl http://www.example.com/Slicer/Extensions/PythonCLIExtensionTemplate.png + +# Give people an idea what to expect from this code +# - Is it just a test or something you stand behind? +status + +# One line stating what the module does +description This is an example of a simple extension + +# Space separated list of urls +screenshoturls http://www.example.com/Slicer/Extensions/PythonCLIExtensionTemplate/Screenshots/1.png + +# 0 or 1: Define if the extension should be enabled after its installation. +enabled 1 diff --git a/Extensions/Testing/CLIExtensionTemplate/CLIModuleTemplate/CLIModuleTemplate.cxx b/Extensions/Testing/CLIExtensionTemplate/CLIModuleTemplate/CLIModuleTemplate.cxx index 28f2121d40c..f0cc177539d 100644 --- a/Extensions/Testing/CLIExtensionTemplate/CLIModuleTemplate/CLIModuleTemplate.cxx +++ b/Extensions/Testing/CLIExtensionTemplate/CLIModuleTemplate/CLIModuleTemplate.cxx @@ -15,7 +15,7 @@ namespace { template -int DoIt( int argc, char * argv[], T ) +int DoIt( int argc, char * argv[], TPixel ) { PARSE_ARGS; diff --git a/Extensions/Testing/PythonCLIExtensionTemplate/CMakeLists.txt b/Extensions/Testing/PythonCLIExtensionTemplate/CMakeLists.txt new file mode 100644 index 00000000000..a45b67b2db9 --- /dev/null +++ b/Extensions/Testing/PythonCLIExtensionTemplate/CMakeLists.txt @@ -0,0 +1,25 @@ +cmake_minimum_required(VERSION 2.8.9) + +project(PythonCLIExtensionTemplate) + +#----------------------------------------------------------------------------- +# Extension meta-information +set(EXTENSION_HOMEPAGE "http://slicer.org/slicerWiki/index.php/Documentation/Nightly/Extensions/PythonCLIExtensionTemplate") +set(EXTENSION_CATEGORY "Examples") +set(EXTENSION_CONTRIBUTORS "John Doe (AnyWare Corp.)") +set(EXTENSION_DESCRIPTION "This is an example of a simple extension") +set(EXTENSION_ICONURL "http://www.example.com/Slicer/Extensions/PythonCLIExtensionTemplate.png") +set(EXTENSION_SCREENSHOTURLS "http://www.example.com/Slicer/Extensions/PythonCLIExtensionTemplate/Screenshots/1.png") + +#----------------------------------------------------------------------------- +# Extension dependencies +find_package(Slicer REQUIRED) +include(${Slicer_USE_FILE}) + +#----------------------------------------------------------------------------- +# Extension modules +add_subdirectory(PythonCLIModuleTemplate) +## NEXT_MODULE + +#----------------------------------------------------------------------------- +include(${Slicer_EXTENSION_CPACK}) diff --git a/Extensions/Testing/PythonCLIExtensionTemplate/PythonCLIExtensionTemplate.png b/Extensions/Testing/PythonCLIExtensionTemplate/PythonCLIExtensionTemplate.png new file mode 100644 index 00000000000..6aae6ab703e Binary files /dev/null and b/Extensions/Testing/PythonCLIExtensionTemplate/PythonCLIExtensionTemplate.png differ diff --git a/Extensions/Testing/PythonCLIExtensionTemplate/PythonCLIModuleTemplate/CMakeLists.txt b/Extensions/Testing/PythonCLIExtensionTemplate/PythonCLIModuleTemplate/CMakeLists.txt new file mode 100644 index 00000000000..b6cc49745bd --- /dev/null +++ b/Extensions/Testing/PythonCLIExtensionTemplate/PythonCLIModuleTemplate/CMakeLists.txt @@ -0,0 +1,24 @@ +#----------------------------------------------------------------------------- +set(MODULE_NAME PythonCLIModuleTemplate) + +#----------------------------------------------------------------------------- +set(MODULE_PYTHON_SCRIPTS + ${MODULE_NAME}.py + ) + +set(MODULE_PYTHON_RESOURCES + ${MODULE_NAME}.xml + ) + +#----------------------------------------------------------------------------- +slicerMacroBuildScriptedModule( + NAME ${MODULE_NAME} + SCRIPTS ${MODULE_PYTHON_SCRIPTS} + RESOURCES ${MODULE_PYTHON_RESOURCES} + ) + +#----------------------------------------------------------------------------- +if(BUILD_TESTING) + # Additional build-time testing + add_subdirectory(Testing) +endif() diff --git a/Extensions/Testing/PythonCLIExtensionTemplate/PythonCLIModuleTemplate/Data/Baseline/PythonCLIModuleTemplateTest.nhdr.md5 b/Extensions/Testing/PythonCLIExtensionTemplate/PythonCLIModuleTemplate/Data/Baseline/PythonCLIModuleTemplateTest.nhdr.md5 new file mode 100644 index 00000000000..e3f7f4074cd --- /dev/null +++ b/Extensions/Testing/PythonCLIExtensionTemplate/PythonCLIModuleTemplate/Data/Baseline/PythonCLIModuleTemplateTest.nhdr.md5 @@ -0,0 +1 @@ +fc6170ceeff3d8217a9dd6a1add2ec8c diff --git a/Extensions/Testing/PythonCLIExtensionTemplate/PythonCLIModuleTemplate/Data/Baseline/PythonCLIModuleTemplateTest.raw.md5 b/Extensions/Testing/PythonCLIExtensionTemplate/PythonCLIModuleTemplate/Data/Baseline/PythonCLIModuleTemplateTest.raw.md5 new file mode 100644 index 00000000000..6e640c3071f --- /dev/null +++ b/Extensions/Testing/PythonCLIExtensionTemplate/PythonCLIModuleTemplate/Data/Baseline/PythonCLIModuleTemplateTest.raw.md5 @@ -0,0 +1 @@ +0749d4d3f07a217030f9ae33d94c4559 \ No newline at end of file diff --git a/Extensions/Testing/PythonCLIExtensionTemplate/PythonCLIModuleTemplate/Data/Input/CTHeadAxial.nhdr.md5 b/Extensions/Testing/PythonCLIExtensionTemplate/PythonCLIModuleTemplate/Data/Input/CTHeadAxial.nhdr.md5 new file mode 100644 index 00000000000..734a0467eee --- /dev/null +++ b/Extensions/Testing/PythonCLIExtensionTemplate/PythonCLIModuleTemplate/Data/Input/CTHeadAxial.nhdr.md5 @@ -0,0 +1 @@ +6e5c289c73e14ba7a1b0f8aaf6ed249a \ No newline at end of file diff --git a/Extensions/Testing/PythonCLIExtensionTemplate/PythonCLIModuleTemplate/Data/Input/CTHeadAxial.raw.gz.md5 b/Extensions/Testing/PythonCLIExtensionTemplate/PythonCLIModuleTemplate/Data/Input/CTHeadAxial.raw.gz.md5 new file mode 100644 index 00000000000..f555cb43501 --- /dev/null +++ b/Extensions/Testing/PythonCLIExtensionTemplate/PythonCLIModuleTemplate/Data/Input/CTHeadAxial.raw.gz.md5 @@ -0,0 +1 @@ +3ebd710c9cf9d75750f4569b8caf6d07 \ No newline at end of file diff --git a/Extensions/Testing/PythonCLIExtensionTemplate/PythonCLIModuleTemplate/PythonCLIModuleTemplate.py b/Extensions/Testing/PythonCLIExtensionTemplate/PythonCLIModuleTemplate/PythonCLIModuleTemplate.py new file mode 100644 index 00000000000..841dd166246 --- /dev/null +++ b/Extensions/Testing/PythonCLIExtensionTemplate/PythonCLIModuleTemplate/PythonCLIModuleTemplate.py @@ -0,0 +1,36 @@ +import itk +from ctk_cli import * +import sys +import logging + +def SmoothingRecursiveGaussianImageFilter(inputVolume, outputVolume, sigma): + reader = itk.ImageFileReader.New(FileName=inputVolume) + filter = itk.SmoothingRecursiveGaussianImageFilter.New(reader) + filter.SetSigma(sigma) + writer = itk.ImageFileWriter.New(filter,FileName=outputVolume) + writer.SetUseCompression(True) + writer.Update() + return 1 + + +def main(): + """Parsing command line arguments and reading input files.""" + logging.basicConfig(level=logging.INFO) + args=CLIArgumentParser().parse_args() + # Run processing + SmoothingRecursiveGaussianImageFilter(args.inputVolume,args.outputVolume,args.sigma) + # Compare output with baseline + reader1 = itk.ImageFileReader.New(FileName=args.outputVolume) + reader2 = itk.ImageFileReader.New(FileName=args.baselineVolume) + compareFilter=itk.ComparisonImageFilter.New(reader1) + compareFilter.SetTestInput(reader1) + compareFilter.SetValidInput(reader2) + diff=compareFilter.GetTotalDifference() + if diff < args.tolerance: + return 0 + return 1 + +if __name__ == "__main__": + ret=main() + if ret: + sys.exit(ret) diff --git a/Extensions/Testing/PythonCLIExtensionTemplate/PythonCLIModuleTemplate/PythonCLIModuleTemplate.xml b/Extensions/Testing/PythonCLIExtensionTemplate/PythonCLIModuleTemplate/PythonCLIModuleTemplate.xml new file mode 100644 index 00000000000..604f1421566 --- /dev/null +++ b/Extensions/Testing/PythonCLIExtensionTemplate/PythonCLIModuleTemplate/PythonCLIModuleTemplate.xml @@ -0,0 +1,52 @@ + + + Examples + PythonCLIModuleTemplate + + 0.0.1 + http://www.example.com/Slicer/Modules/PythonCLIModuleTemplate + Slicer + FirstName LastName (Institution), FirstName LastName (Institution) + This work was partially funded by NIH grant NXNNXXNNNNNN-NNXN + + + + + sigma + sigma + s + + + 1.0 + + + inputVolume + + input + 0 + + + + outputVolume + + output + 1 + + + + baselineVolume + + input + 2 + + + + tolerance + tolerance + t + + + 0.0001 + + + diff --git a/Extensions/Testing/PythonCLIExtensionTemplate/PythonCLIModuleTemplate/Testing/CMakeLists.txt b/Extensions/Testing/PythonCLIExtensionTemplate/PythonCLIModuleTemplate/Testing/CMakeLists.txt new file mode 100644 index 00000000000..655007a0aab --- /dev/null +++ b/Extensions/Testing/PythonCLIExtensionTemplate/PythonCLIModuleTemplate/Testing/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(Python) diff --git a/Extensions/Testing/PythonCLIExtensionTemplate/PythonCLIModuleTemplate/Testing/Python/CMakeLists.txt b/Extensions/Testing/PythonCLIExtensionTemplate/PythonCLIModuleTemplate/Testing/Python/CMakeLists.txt new file mode 100644 index 00000000000..82ea85b1231 --- /dev/null +++ b/Extensions/Testing/PythonCLIExtensionTemplate/PythonCLIModuleTemplate/Testing/Python/CMakeLists.txt @@ -0,0 +1,17 @@ +#----------------------------------------------------------------------------- +set(BASELINE ${CMAKE_CURRENT_SOURCE_DIR}/../../Data/Baseline) +set(INPUT ${CMAKE_CURRENT_SOURCE_DIR}/../../Data/Input) +set(TEMP "${CMAKE_BINARY_DIR}/Testing/Temporary") + +set(CLP ${MODULE_NAME}) + +#----------------------------------------------------------------------------- +set(testname ${CLP}Test) +ExternalData_add_test(${CLP}Data NAME ${testname} COMMAND ${Slicer_LAUNCHER_EXECUTABLE} ${MODULE_NAME}.py + --sigma 2.5 DATA{${INPUT}/CTHeadAxial.nhdr,CTHeadAxial.raw.gz} ${TEMP}/${CLP}Test.nhdr + DATA{${BASELINE}/${CLP}Test.nhdr,${CLP}Test.raw} + ) +set_property(TEST ${testname} PROPERTY LABELS ${CLP}) + +#----------------------------------------------------------------------------- +ExternalData_add_target(${CLP}Data) diff --git a/SuperBuild.cmake b/SuperBuild.cmake index c1c40204dc3..c5da79be547 100644 --- a/SuperBuild.cmake +++ b/SuperBuild.cmake @@ -100,7 +100,7 @@ if(Slicer_USE_SimpleITK) endif() if(Slicer_BUILD_CLI_SUPPORT) - list(APPEND Slicer_DEPENDENCIES SlicerExecutionModel) + list(APPEND Slicer_DEPENDENCIES SlicerExecutionModel python-ctk_cli) endif() if(Slicer_BUILD_EXTENSIONMANAGER_SUPPORT) diff --git a/SuperBuild/External_python-ctk_cli.cmake b/SuperBuild/External_python-ctk_cli.cmake new file mode 100644 index 00000000000..64c37751c2f --- /dev/null +++ b/SuperBuild/External_python-ctk_cli.cmake @@ -0,0 +1,36 @@ +set(proj python-ctk_cli) + +# Set dependency list +set(${proj}_DEPENDENCIES python python-setuptools) + +# Include dependent projects if any +ExternalProject_Include_Dependencies(${proj} PROJECT_VAR proj DEPENDS_VAR ${proj}_DEPENDENCIES) + +if(${CMAKE_PROJECT_NAME}_USE_SYSTEM_${proj}) + # XXX - Add a test checking if is available +endif() + +if(NOT DEFINED ${CMAKE_PROJECT_NAME}_USE_SYSTEM_${proj}) + set(${CMAKE_PROJECT_NAME}_USE_SYSTEM_${proj} ${${CMAKE_PROJECT_NAME}_USE_SYSTEM_python}) +endif() + +set(ctk_cli_REPOSITORY ${git_protocol}://github.com/commontk/ctk-cli.git) +set(ctk_cli_GIT_TAG 4346a22618b299c8eff84c6a179067ca68db43b9) + +if(NOT ${CMAKE_PROJECT_NAME}_USE_SYSTEM_${proj}) + + ExternalProject_Add(${proj} + ${${proj}_EP_ARGS} + GIT_REPOSITORY ${ctk_cli_REPOSITORY} + GIT_TAG ${ctk_cli_GIT_TAG} + SOURCE_DIR ${proj} + BUILD_IN_SOURCE 1 + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND ${PYTHON_EXECUTABLE} setup.py install + DEPENDS + ${${proj}_DEPENDENCIES} + ) +else() + ExternalProject_Add_Empty(${proj} DEPENDS ${${proj}_DEPENDENCIES}) +endif() diff --git a/Utilities/Templates/Modules/CLI/TemplateKey.cxx b/Utilities/Templates/Modules/CLI/TemplateKey.cxx index 95b183e9613..1729d2734e4 100644 --- a/Utilities/Templates/Modules/CLI/TemplateKey.cxx +++ b/Utilities/Templates/Modules/CLI/TemplateKey.cxx @@ -15,7 +15,7 @@ namespace { template -int DoIt( int argc, char * argv[], T ) +int DoIt( int argc, char * argv[], TPixel ) { PARSE_ARGS; diff --git a/Utilities/Templates/Modules/PythonCLI/CMakeLists.txt b/Utilities/Templates/Modules/PythonCLI/CMakeLists.txt new file mode 100644 index 00000000000..b6cc49745bd --- /dev/null +++ b/Utilities/Templates/Modules/PythonCLI/CMakeLists.txt @@ -0,0 +1,24 @@ +#----------------------------------------------------------------------------- +set(MODULE_NAME PythonCLIModuleTemplate) + +#----------------------------------------------------------------------------- +set(MODULE_PYTHON_SCRIPTS + ${MODULE_NAME}.py + ) + +set(MODULE_PYTHON_RESOURCES + ${MODULE_NAME}.xml + ) + +#----------------------------------------------------------------------------- +slicerMacroBuildScriptedModule( + NAME ${MODULE_NAME} + SCRIPTS ${MODULE_PYTHON_SCRIPTS} + RESOURCES ${MODULE_PYTHON_RESOURCES} + ) + +#----------------------------------------------------------------------------- +if(BUILD_TESTING) + # Additional build-time testing + add_subdirectory(Testing) +endif() diff --git a/Utilities/Templates/Modules/PythonCLI/Data/Baseline/PythonCLIModuleTemplateTest.nhdr.md5 b/Utilities/Templates/Modules/PythonCLI/Data/Baseline/PythonCLIModuleTemplateTest.nhdr.md5 new file mode 100644 index 00000000000..e3f7f4074cd --- /dev/null +++ b/Utilities/Templates/Modules/PythonCLI/Data/Baseline/PythonCLIModuleTemplateTest.nhdr.md5 @@ -0,0 +1 @@ +fc6170ceeff3d8217a9dd6a1add2ec8c diff --git a/Utilities/Templates/Modules/PythonCLI/Data/Baseline/PythonCLIModuleTemplateTest.raw.md5 b/Utilities/Templates/Modules/PythonCLI/Data/Baseline/PythonCLIModuleTemplateTest.raw.md5 new file mode 100644 index 00000000000..6e640c3071f --- /dev/null +++ b/Utilities/Templates/Modules/PythonCLI/Data/Baseline/PythonCLIModuleTemplateTest.raw.md5 @@ -0,0 +1 @@ +0749d4d3f07a217030f9ae33d94c4559 \ No newline at end of file diff --git a/Utilities/Templates/Modules/PythonCLI/Data/Input/CTHeadAxial.nhdr.md5 b/Utilities/Templates/Modules/PythonCLI/Data/Input/CTHeadAxial.nhdr.md5 new file mode 100644 index 00000000000..734a0467eee --- /dev/null +++ b/Utilities/Templates/Modules/PythonCLI/Data/Input/CTHeadAxial.nhdr.md5 @@ -0,0 +1 @@ +6e5c289c73e14ba7a1b0f8aaf6ed249a \ No newline at end of file diff --git a/Utilities/Templates/Modules/PythonCLI/Data/Input/CTHeadAxial.raw.gz.md5 b/Utilities/Templates/Modules/PythonCLI/Data/Input/CTHeadAxial.raw.gz.md5 new file mode 100644 index 00000000000..f555cb43501 --- /dev/null +++ b/Utilities/Templates/Modules/PythonCLI/Data/Input/CTHeadAxial.raw.gz.md5 @@ -0,0 +1 @@ +3ebd710c9cf9d75750f4569b8caf6d07 \ No newline at end of file diff --git a/Utilities/Templates/Modules/PythonCLI/PythonCLIModuleTemplate.py b/Utilities/Templates/Modules/PythonCLI/PythonCLIModuleTemplate.py new file mode 100644 index 00000000000..841dd166246 --- /dev/null +++ b/Utilities/Templates/Modules/PythonCLI/PythonCLIModuleTemplate.py @@ -0,0 +1,36 @@ +import itk +from ctk_cli import * +import sys +import logging + +def SmoothingRecursiveGaussianImageFilter(inputVolume, outputVolume, sigma): + reader = itk.ImageFileReader.New(FileName=inputVolume) + filter = itk.SmoothingRecursiveGaussianImageFilter.New(reader) + filter.SetSigma(sigma) + writer = itk.ImageFileWriter.New(filter,FileName=outputVolume) + writer.SetUseCompression(True) + writer.Update() + return 1 + + +def main(): + """Parsing command line arguments and reading input files.""" + logging.basicConfig(level=logging.INFO) + args=CLIArgumentParser().parse_args() + # Run processing + SmoothingRecursiveGaussianImageFilter(args.inputVolume,args.outputVolume,args.sigma) + # Compare output with baseline + reader1 = itk.ImageFileReader.New(FileName=args.outputVolume) + reader2 = itk.ImageFileReader.New(FileName=args.baselineVolume) + compareFilter=itk.ComparisonImageFilter.New(reader1) + compareFilter.SetTestInput(reader1) + compareFilter.SetValidInput(reader2) + diff=compareFilter.GetTotalDifference() + if diff < args.tolerance: + return 0 + return 1 + +if __name__ == "__main__": + ret=main() + if ret: + sys.exit(ret) diff --git a/Utilities/Templates/Modules/PythonCLI/PythonCLIModuleTemplate.xml b/Utilities/Templates/Modules/PythonCLI/PythonCLIModuleTemplate.xml new file mode 100644 index 00000000000..604f1421566 --- /dev/null +++ b/Utilities/Templates/Modules/PythonCLI/PythonCLIModuleTemplate.xml @@ -0,0 +1,52 @@ + + + Examples + PythonCLIModuleTemplate + + 0.0.1 + http://www.example.com/Slicer/Modules/PythonCLIModuleTemplate + Slicer + FirstName LastName (Institution), FirstName LastName (Institution) + This work was partially funded by NIH grant NXNNXXNNNNNN-NNXN + + + + + sigma + sigma + s + + + 1.0 + + + inputVolume + + input + 0 + + + + outputVolume + + output + 1 + + + + baselineVolume + + input + 2 + + + + tolerance + tolerance + t + + + 0.0001 + + + diff --git a/Utilities/Templates/Modules/PythonCLI/Testing/CMakeLists.txt b/Utilities/Templates/Modules/PythonCLI/Testing/CMakeLists.txt new file mode 100644 index 00000000000..655007a0aab --- /dev/null +++ b/Utilities/Templates/Modules/PythonCLI/Testing/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(Python) diff --git a/Utilities/Templates/Modules/PythonCLI/Testing/Python/CMakeLists.txt b/Utilities/Templates/Modules/PythonCLI/Testing/Python/CMakeLists.txt new file mode 100644 index 00000000000..82ea85b1231 --- /dev/null +++ b/Utilities/Templates/Modules/PythonCLI/Testing/Python/CMakeLists.txt @@ -0,0 +1,17 @@ +#----------------------------------------------------------------------------- +set(BASELINE ${CMAKE_CURRENT_SOURCE_DIR}/../../Data/Baseline) +set(INPUT ${CMAKE_CURRENT_SOURCE_DIR}/../../Data/Input) +set(TEMP "${CMAKE_BINARY_DIR}/Testing/Temporary") + +set(CLP ${MODULE_NAME}) + +#----------------------------------------------------------------------------- +set(testname ${CLP}Test) +ExternalData_add_test(${CLP}Data NAME ${testname} COMMAND ${Slicer_LAUNCHER_EXECUTABLE} ${MODULE_NAME}.py + --sigma 2.5 DATA{${INPUT}/CTHeadAxial.nhdr,CTHeadAxial.raw.gz} ${TEMP}/${CLP}Test.nhdr + DATA{${BASELINE}/${CLP}Test.nhdr,${CLP}Test.raw} + ) +set_property(TEST ${testname} PROPERTY LABELS ${CLP}) + +#----------------------------------------------------------------------------- +ExternalData_add_target(${CLP}Data)