### Install Launcher Source: https://github.com/slicer/slicerexecutionmodel/blob/master/GenerateCLP/CMakeLists.txt Installs the GenerateCLPLauncher executable to the 'bin' directory. This installation is conditional on the project's INSTALL_NO_DEVELOPMENT flag. ```cmake if(NOT ${PROJECT_NAME}_INSTALL_NO_DEVELOPMENT) install(TARGETS GenerateCLPLauncher RUNTIME DESTINATION bin COMPONENT Development ) endif() ``` -------------------------------- ### Basic Command Line Execution Source: https://github.com/slicer/slicerexecutionmodel/blob/master/tclap/docs/manual.html Demonstrates a simple command-line execution with arguments. This example shows how the program handles basic input and provides output. ```bash % test1 -r -n mike My name (spelled backwards) is: ekim ``` -------------------------------- ### Install development files Source: https://github.com/slicer/slicerexecutionmodel/blob/master/ModuleDescriptionParser/CMakeLists.txt Installs CMake configuration files to the development directory if the installation flag is enabled. ```cmake if(NOT ${PROJECT_NAME}_INSTALL_NO_DEVELOPMENT) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/UseModuleDescriptionParser.cmake ${CMAKE_CURRENT_BINARY_DIR}/install/ModuleDescriptionParserConfig.cmake DESTINATION lib/${lib_name} COMPONENT Development) endif() ``` -------------------------------- ### Install Support Files Source: https://github.com/slicer/slicerexecutionmodel/blob/master/GenerateCLP/CMakeLists.txt Installs CMake configuration files for GenerateCLP. These files are installed to a specific subdirectory and are only included if development components are not disabled. ```cmake if(NOT ${PROJECT_NAME}_INSTALL_NO_DEVELOPMENT) install(FILES ${GenerateCLP_BINARY_DIR}/GenerateCLPConfig.cmake_install DESTINATION lib/GenerateCLP COMPONENT Development RENAME GenerateCLPConfig.cmake ) install(FILES ${GenerateCLP_BINARY_DIR}/UseGenerateCLP.cmake_install DESTINATION lib/GenerateCLP COMPONENT Development RENAME UseGenerateCLP.cmake ) endif() ``` -------------------------------- ### Declare MultiSwitchArg with Custom Initial Value Source: https://github.com/slicer/slicerexecutionmodel/blob/master/tclap/docs/manual.html This example demonstrates initializing a MultiSwitchArg with a custom starting value, useful when the default count needs to be offset. ```cpp MultiSwitchArg quiet("q","quiet","Reduce the volume of output",5); cmd.add( quiet ); ``` -------------------------------- ### Demonstrate ModuleParameter Class Setup in C++ Source: https://context7.com/slicer/slicerexecutionmodel/llms.txt Illustrates how to instantiate and configure a ModuleParameter object, setting various properties like type, name, flags, values, constraints, and aliases. This is useful for defining parameters for command-line interfaces or module configurations. ```cpp #include "ModuleParameter.h" #include void demonstrateParameter() { ModuleParameter param; // Basic parameter setup param.SetTag("integer"); // Parameter type tag param.SetCPPType("int"); // C++ type for code generation param.SetName("Iterations"); // Variable name param.SetLabel("Number of Iterations"); param.SetDescription("Maximum iterations for optimization"); // Command-line flags param.SetFlag("i"); // Short flag: -i param.SetLongFlag("iterations"); // Long flag: --iterations // Value and channel param.SetValue("100"); // Default value param.SetChannel("input"); // "input" or "output" // Constraints param.SetConstraints("true"); param.SetMinimum("1"); param.SetMaximum("10000"); param.SetStep("10"); // Multiple values support param.SetMultiple("true"); // File extensions (for file parameters) param.SetFileExtensionsAsString(".nii,.nii.gz,.mha,.mhd"); // Coordinate system (for point/region parameters) param.SetCoordinateSystem("ras"); // or "lps", "ijk" // Hidden parameters (not shown in GUI) param.SetHidden("true"); // Flag aliases for backward compatibility param.SetFlagAliasesAsString("n,num"); param.SetLongFlagAliasesAsString("numiterations,iter"); // Enumeration elements std::vector elements; elements.push_back("option1"); elements.push_back("option2"); elements.push_back("option3"); param.SetElements(elements); // Query parameter properties std::cout << "Name: " << param.GetName() << std::endl; std::cout << "Is flag parameter: " << param.IsFlagParameter() << std::endl; std::cout << "Is index parameter: " << param.IsIndexParameter() << std::endl; std::cout << "Is return parameter: " << param.IsReturnParameter() << std::endl; // Get file extensions as vector const std::vector& extensions = param.GetFileExtensions(); for (const auto& ext : extensions) { std::cout << "Extension: " << ext << std::endl; } } ``` -------------------------------- ### Install Executable Source: https://github.com/slicer/slicerexecutionmodel/blob/master/GenerateCLP/CMakeLists.txt Installs the GenerateCLP executable to the specified runtime directory. This is conditional on the GenerateCLP_INSTALL_BIN_DIR variable and the project's INSTALL_NO_DEVELOPMENT flag. ```cmake if(NOT DEFINED GenerateCLP_INSTALL_BIN_DIR) set(GenerateCLP_INSTALL_BIN_DIR bin) endif() if(NOT DEFINED ${PROJECT_NAME}_INSTALL_NO_DEVELOPMENT) set(${PROJECT_NAME}_INSTALL_NO_DEVELOPMENT ON) endif() if(NOT ${PROJECT_NAME}_INSTALL_NO_DEVELOPMENT) install(TARGETS GenerateCLP RUNTIME DESTINATION ${GenerateCLP_INSTALL_BIN_DIR} COMPONENT Development ) endif() ``` -------------------------------- ### Configure Shared Library Forwarding Paths Source: https://github.com/slicer/slicerexecutionmodel/blob/master/GenerateCLP/CMakeLists.txt Configures paths for shared library forwarding, essential for running executables from build or installed trees. It dynamically includes paths based on found libraries like JsonCpp and project-specific settings. ```cmake set(additional_forward_paths_build "") foreach(lib_path ${SlicerExecutionModel_ADDITIONAL_FORWARD_PATHS_BUILD}) string(APPEND additional_forward_paths_build "${lib_path}", ) endforeach() set(additional_forward_paths_install "") foreach(lib_path ${SlicerExecutionModel_ADDITIONAL_FORWARD_PATHS_INSTALL}) string(APPEND additional_forward_paths_install "${lib_path}", ) endforeach() if(JsonCpp_FOUND) get_filename_component(json_library_dir ${JsonCpp_LIBRARY} DIRECTORY) set(json_forward_path_build "${json_library_dir}" CONFIG_DIR_POST, \ "${json_library_dir}", ) set(json_forward_path_install "${json_library_dir}",) endif() set(GenerateCLP_FORWARD_DIR_BUILD "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}") set(GenerateCLP_FORWARD_PATH_BUILD " \ "." CONFIG_DIR_POST, \ "${ITK_DIR}/bin" CONFIG_DIR_POST, \ ${json_forward_path_build} \ ${additional_forward_paths_build} \ "${ModuleDescriptionParser_DIR}/bin" CONFIG_DIR_POST \ ") set(GenerateCLP_FORWARD_PATH_INSTALL " \ ".", \ "${ITK_DIR}/bin", \ ${json_forward_path_install} \ ${additional_forward_paths_install} \ "${ModuleDescriptionParser_DIR}/bin" \ ") set(GenerateCLP_FORWARD_EXE GenerateCLP) set(GenerateCLP_FORWARD_DIR_INSTALL "..") ``` -------------------------------- ### Configure Windows-Style Argument Flags in TCLAP Source: https://github.com/slicer/slicerexecutionmodel/blob/master/tclap/docs/manual.html Customize TCLAP to use Windows-style argument flags (e.g., '/') and name starts (e.g., '~~') by defining TCLAP_FLAGSTARTSTRING and TCLAP_NAMESTARTSTRING before including the TCLAP header. This is useful for cross-platform compatibility. ```cpp // // This illustrates how to change the flag and name start strings for // Windows, otherwise the defaults are used. // // Note that these defines need to happen *before* tclap is included! // #ifdef WINDOWS #define TCLAP_NAMESTARTSTRING "~~") #define TCLAP_FLAGSTARTSTRING "/" #endif #include "tclap/CmdLine.h" using namespace TCLAP; using namespace std; int main(int argc, char** argv) { // Everything else is identical! ... ``` -------------------------------- ### Register SlicerExecutionModel Tests Source: https://github.com/slicer/slicerexecutionmodel/blob/master/GenerateCLP/Testing/CMakeLists.txt Registers various test suites for different examples using the generateclp_add_test macro. ```cmake set(_previous_test "NODEPENDS") generateclp_add_test(Slicer3Example Configure) generateclp_add_test(Slicer3Example Build) generateclp_add_test(Slicer3Example Test) set(_previous_test "NODEPENDS") generateclp_add_test(PointExample1 Configure) generateclp_add_test(PointExample1 Build) #generateclp_add_test(PointExample1 Test) set(_previous_test "NODEPENDS") generateclp_add_test(CLPExample1 Configure) generateclp_add_test(CLPExample1 Build) generateclp_add_test(CLPExample1 Test) set(_previous_test "NODEPENDS") generateclp_add_test(CLPTestMultiple Configure) generateclp_add_test(CLPTestMultiple Build) generateclp_add_test(CLPTestMultiple Test) if(SlicerExecutionModel_USE_UTF8) set(_previous_test "NODEPENDS") generateclp_add_test(Utf8Example Configure) generateclp_add_test(Utf8Example Build) generateclp_add_test(Utf8Example Test) endif() ``` -------------------------------- ### Declare MultiArg for Integers Source: https://github.com/slicer/slicerexecutionmodel/blob/master/tclap/docs/manual.html Use MultiArg when an argument can be specified multiple times and should collect all values into a vector. This example shows how to declare a MultiArg for integers. ```cpp MultiArg itest("i", "intTest", "multi int test", false, "int" ); cmd.add( itest ); ``` -------------------------------- ### Command Line Usage Help Source: https://github.com/slicer/slicerexecutionmodel/blob/master/tclap/docs/manual.html Displays the brief usage information for the command-line tool, outlining available arguments and their descriptions. ```bash % test1 --help USAGE: test1 [-r] -n [--] [-v] [-h] Where: -r, --reverse Print name backwards -n --name (required) (value required) Name to print --, --ignore_rest Ignores the rest of the labeled arguments following this flag. -v, --version Displays version information and exits. -h, --help Displays usage information and exits. Command description message ``` -------------------------------- ### Configure support files Source: https://github.com/slicer/slicerexecutionmodel/blob/master/ModuleDescriptionParser/CMakeLists.txt Includes the parser configuration script and copies the template file to the binary directory. ```cmake include(GenerateModuleDescriptionParserConfig.cmake) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/UseModuleDescriptionParser.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/UseModuleDescriptionParser.cmake COPYONLY) ``` -------------------------------- ### Build Launcher Source: https://github.com/slicer/slicerexecutionmodel/blob/master/GenerateCLP/CMakeLists.txt Configures and builds the GenerateCLPLauncher executable. This involves generating source files from templates and adding dependencies. ```cmake set(GenerateCLPLauncher_SOURCE ${CMAKE_CURRENT_BINARY_DIR}/GenerateCLPLauncher.c ) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/GenerateCLPLauncher.c.in ${GenerateCLPLauncher_SOURCE} @ONLY) set(KWSYS_NAMESPACE itksys) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/SharedForward.h.in ${CMAKE_CURRENT_BINARY_DIR}/SharedForward.h @ONLY) add_custom_command(TARGET GenerateCLP POST_BUILD COMMAND ${CMAKE_COMMAND} -E touch ${GenerateCLPLauncher_SOURCE} COMMENT "Force GenerateCLPLauncher to rebuild after GenerateCLP was modified" ) sem_add_executable(GenerateCLPLauncher ${GenerateCLPLauncher_SOURCE} ) list(APPEND targets_to_export GenerateCLPLauncher) add_dependencies(GenerateCLPLauncher GenerateCLP) ``` -------------------------------- ### Configure CMake Project Source: https://github.com/slicer/slicerexecutionmodel/blob/master/GenerateCLP/Testing/PointExample1/CMakeLists.txt Sets the minimum CMake version and policy for the project. Include necessary test macros. ```cmake cmake_minimum_required(VERSION 3.13.4...3.14.2) cmake_policy(VERSION 3.13.4...3.14.2) #----------------------------------------------------------------------------- # Configure & Build #----------------------------------------------------------------------------- include(${CMAKE_CURRENT_SOURCE_DIR}/../CMake/GenerateCLPTestMacros.cmake) GenerateCLP_TEST_PROJECT( NAME PointExample1 ) ``` -------------------------------- ### Declare MultiSwitchArg with Default Value Source: https://github.com/slicer/slicerexecutionmodel/blob/master/tclap/docs/manual.html MultiSwitchArg can be specified multiple times, and its value represents the count of occurrences. This example shows declaration with the default initial value of 0. ```cpp MultiSwitchArg quiet("q","quiet","Reduce the volume of output"); cmd.add( quiet ); ``` -------------------------------- ### Configure CLI Module Description Source: https://context7.com/slicer/slicerexecutionmodel/llms.txt Use ModuleDescription to set metadata, manage parameters, and add parameter groups for a CLI module. Ensure necessary headers are included. ```cpp #include "ModuleDescription.h" #include "ModuleParameterGroup.h" #include "ModuleParameter.h" void configureModule(ModuleDescription& module) { // Set module metadata module.SetTitle("Advanced Image Filter"); module.SetCategory("Filtering"); module.SetDescription("Apply advanced filtering to images"); module.SetVersion("2.0.0"); module.SetContributor("Development Team"); module.SetDocumentationURL("https://docs.example.com"); module.SetLicense("BSD-3-Clause"); // Check if module has specific parameter if (module.HasParameter("Sigma")) { // Get current parameter value std::string sigma = module.GetParameterValue("Sigma"); std::cout << "Current Sigma: " << sigma << std::endl; // Set new parameter value module.SetParameterValue("Sigma", "2.5"); } // Check for return parameters (output values) if (module.HasReturnParameters()) { std::cout << "Module has return parameters" << std::endl; } // Read/write parameter files module.ReadParameterFile("parameters.txt"); module.WriteParameterFile("output_parameters.txt", true); // Create and add a new parameter group ModuleParameterGroup advancedGroup; advancedGroup.SetLabel("Advanced Options"); advancedGroup.SetDescription("Advanced filtering parameters"); advancedGroup.SetAdvanced("true"); // Create a parameter ModuleParameter threshold; threshold.SetTag("double"); threshold.SetName("Threshold"); threshold.SetLabel("Threshold Value"); threshold.SetDescription("Intensity threshold for filtering"); threshold.SetLongFlag("threshold"); threshold.SetFlag("t"); threshold.SetValue("0.5"); threshold.SetConstraints("true"); threshold.SetMinimum("0.0"); threshold.SetMaximum("1.0"); threshold.SetStep("0.1"); threshold.SetChannel("input"); advancedGroup.AddParameter(threshold); module.AddParameterGroup(advancedGroup); } ``` -------------------------------- ### Configure SlicerExecutionModel Project Source: https://github.com/slicer/slicerexecutionmodel/blob/master/GenerateCLP/Testing/Slicer3Example/CMakeLists.txt Initializes the project environment and generates test macros for SlicerExecutionModel. ```cmake cmake_minimum_required(VERSION 3.13.4...3.14.2) cmake_policy(VERSION 3.13.4...3.14.2) include(${CMAKE_CURRENT_SOURCE_DIR}/../CMake/GenerateCLPTestMacros.cmake) #----------------------------------------------------------------------------- # Configure & Build #----------------------------------------------------------------------------- GenerateCLP_TEST_PROJECT( NAME Slicer3Example ) ``` -------------------------------- ### Implement CLI Module Logic in C++ Source: https://context7.com/slicer/slicerexecutionmodel/llms.txt Uses the PARSE_ARGS macro to access parameters defined in the XML and demonstrates progress reporting. ```cpp // SimpleFilter.cxx #include "SimpleFilterCLP.h" #include int main(int argc, char* argv[]) { PARSE_ARGS; // All variables are now available: // - Sigma (double) // - InputVolume (std::string) // - OutputVolume (std::string) std::cout << "Applying Gaussian filter" << std::endl; std::cout << " Sigma: " << Sigma << " mm" << std::endl; std::cout << " Input: " << InputVolume << std::endl; std::cout << " Output: " << OutputVolume << std::endl; // Report progress if available if (CLPProcessInformation) { CLPProcessInformation->Progress = 0.5f; strcpy(CLPProcessInformation->ProgressMessage, "Filtering..."); } // ... actual image processing code here ... if (CLPProcessInformation) { CLPProcessInformation->Progress = 1.0f; strcpy(CLPProcessInformation->ProgressMessage, "Complete"); } return EXIT_SUCCESS; } ``` -------------------------------- ### Configure CLP Test Project Source: https://github.com/slicer/slicerexecutionmodel/blob/master/GenerateCLP/Testing/CLPExample1/CMakeLists.txt Initializes the CLP test project using the GenerateCLP_TEST_PROJECT macro. ```cmake cmake_minimum_required(VERSION 3.13.4...3.14.2) cmake_policy(VERSION 3.13.4...3.14.2) include(${CMAKE_CURRENT_SOURCE_DIR}/../CMake/GenerateCLPTestMacros.cmake) #----------------------------------------------------------------------------- # Configure & Build #----------------------------------------------------------------------------- GenerateCLP_TEST_PROJECT( NAME CLPExample1 ) ``` -------------------------------- ### Compiling with TCLAP Include Path Source: https://github.com/slicer/slicerexecutionmodel/blob/master/tclap/docs/manual.html Demonstrates how to compile a C++ program that uses TCLAP, specifying the include path for the library's header files. ```bash c++ -o my_program -I /some/place/tclap-1.X/include my_program.cpp ``` -------------------------------- ### Configure GenerateCLP and Include Config Source: https://github.com/slicer/slicerexecutionmodel/blob/master/GenerateCLP/CMakeLists.txt Configures the GenerateCLP.cmake file and includes the corresponding configuration script. ```cmake configure_file( GenerateCLP.cmake ${CMAKE_CURRENT_BINARY_DIR}/GenerateCLP.cmake @ONLY ) include(GenerateGenerateCLPConfig.cmake) ``` -------------------------------- ### Generate CLP Header from XML using GenerateCLP Source: https://context7.com/slicer/slicerexecutionmodel/llms.txt Shows how to use the GenerateCLP executable to process an XML file and generate a C++ header for command-line argument parsing. Includes options for specifying input XML, output C++ header, and logo files. ```bash # Basic usage: generate CLP header from XML GenerateCLP --InputXML MyModule.xml --OutputCxx MyModuleCLP.h ``` ```bash # With logo file for module branding GenerateCLP --InputXML MyModule.xml --OutputCxx MyModuleCLP.h --logoFiles logo.h ``` ```bash # The generated header provides: # - PARSE_ARGS macro for automatic argument parsing # - GetXMLModuleDescription() function to retrieve XML at runtime # - GetModuleLogo() function (if logo provided) # - Support for --xml flag to output module description # - Support for --echo flag to print parsed arguments # Example module invocation after compilation: ./MyModule --xml # Output XML description ./MyModule --help # Show help (via TCLAP) ./MyModule -b 50 --interpolation sinc input.nii output.nii ./MyModule --histogrambins 50 -v input.nii output.nii ``` -------------------------------- ### Define Module Parameters in XML Source: https://context7.com/slicer/slicerexecutionmodel/llms.txt Use this schema to define inputs, outputs, and parameter constraints for a CLI module. ```xml registration Image Registration Tool Registers two images using rigid transform 1.0.0 https://example.com/docs BSD Your Name Parameters for registration algorithm HistogramBins -b --histogrambins Number of histogram bins 30 1 500 5 Verbose -v --verbose Enable verbose output false InterpolationType --interpolation Interpolation method linear sinc nearest linear LearningRates -l --learningrates Learning rates for each iteration 0.005,0.001,0.0005 Input/output files InputImage input 0 Input image file OutputImage output 1 Output image file ``` -------------------------------- ### Configure Build with CMake Source: https://context7.com/slicer/slicerexecutionmodel/llms.txt Uses SEMMacroBuildCLI to integrate the module with SlicerExecutionModel. ```cmake # CMakeLists.txt cmake_minimum_required(VERSION 3.13.4) project(SimpleFilter) find_package(SlicerExecutionModel REQUIRED) include(${SlicerExecutionModel_USE_FILE}) SEMMacroBuildCLI( NAME SimpleFilter TARGET_LIBRARIES ${ITK_LIBRARIES} ) ``` -------------------------------- ### Configure Slicer Execution Model Project Source: https://github.com/slicer/slicerexecutionmodel/blob/master/GenerateCLP/Testing/CLPTestMultiple/CMakeLists.txt Configures the main project for the Slicer execution model tests. This macro sets up the project name and potentially other configurations. ```cmake cmake_minimum_required(VERSION 3.13.4...3.14.2) cmake_policy(VERSION 3.13.4...3.14.2) include(${CMAKE_CURRENT_SOURCE_DIR}/../CMake/GenerateCLPTestMacros.cmake) #----------------------------------------------------------------------------- # Configure & Build #----------------------------------------------------------------------------- GenerateCLP_TEST_PROJECT( NAME CLPTestMultiple ) ``` -------------------------------- ### Add Args to CmdLine via Constructor Source: https://github.com/slicer/slicerexecutionmodel/blob/master/tclap/docs/manual.html Use new constructors for Arg types that accept a CmdLine object. The Arg then adds itself to the CmdLine automatically. This method is equivalent to calling add() directly, but does not support xorAdd(). ```cpp CmdLine cmd("this is a message", '=', "0.99" ); SwitchArg btest("B","existTestB", "exist Test B", cmd, false ); ValueArg stest("s", "stringTest", "string test", true, "homer", "string", cmd ); UnlabeledValueArg utest("unTest1","unlabeled test one", "default","string", cmd ); cmd.parse(argc,argv); ``` -------------------------------- ### Implement Progress Reporting and Abort Handling Source: https://context7.com/slicer/slicerexecutionmodel/llms.txt Utilize ModuleProcessInformation to report progress and handle abort requests during long-running CLI module operations. Requires including relevant headers and setting up callbacks. ```cpp #include "ModuleProcessInformation.h" #include #include // Callback function for progress updates void onProgressUpdate(void* clientData) { ModuleProcessInformation* info = static_cast(clientData); std::cout << "Progress: " << (info->Progress * 100) << "%" << std::endl; std::cout << "Message: " << info->ProgressMessage << std::endl; } int processWithProgress(ModuleProcessInformation* processInfo) { // Initialize process information processInfo->Initialize(); // Set up progress callback processInfo->SetProgressCallback(onProgressUpdate, processInfo); const int totalSteps = 100; for (int step = 0; step <= totalSteps; ++step) { // Check for abort request from calling application if (processInfo->Abort) { strcpy(processInfo->ProgressMessage, "Processing aborted by user"); return EXIT_FAILURE; } // Update overall progress (0.0 to 1.0) processInfo->Progress = static_cast(step) / totalSteps; // Update stage progress for multi-stage algorithms processInfo->StageProgress = static_cast(step % 10) / 10.0f; // Update progress message snprintf(processInfo->ProgressMessage, 1024, "Processing step %d of %d", step, totalSteps); // Call progress callback if set if (processInfo->ProgressCallbackFunction) { processInfo->ProgressCallbackFunction( processInfo->ProgressCallbackClientData); } // Simulate work std::this_thread::sleep_for(std::chrono::milliseconds(50)); } // Final update processInfo->Progress = 1.0f; strcpy(processInfo->ProgressMessage, "Processing complete"); processInfo->ElapsedTime = 5.0; // Total elapsed time in seconds return EXIT_SUCCESS; } int main(int argc, char* argv[]) { PARSE_ARGS; // CLPProcessInformation is automatically available after PARSE_ARGS // when --processinformationaddress is provided by the calling application if (CLPProcessInformation) { return processWithProgress(CLPProcessInformation); } else { // Run without progress reporting std::cout << "Running without progress reporting" << std::endl; return EXIT_SUCCESS; } } ``` -------------------------------- ### Build Parser1Test Executable Source: https://github.com/slicer/slicerexecutionmodel/blob/master/ModuleDescriptionParser/Testing/CMakeLists.txt Defines the source for Parser1Test and links it against the ModuleDescriptionParser library. ```cmake set(PARSER1TEST_SOURCE Parser1Test.cxx ) sem_add_executable(Parser1Test ${PARSER1TEST_SOURCE}) target_link_libraries(Parser1Test ModuleDescriptionParser ) ``` -------------------------------- ### Configure Slicer Execution Model Project Source: https://github.com/slicer/slicerexecutionmodel/blob/master/GenerateCLP/Testing/Utf8Example/CMakeLists.txt Sets the minimum CMake version and policy, and generates test macros for the project. ```cmake cmake_minimum_required(VERSION 3.13.4...3.14.2) cmake_policy(VERSION 3.13.4...3.14.2) #----------------------------------------------------------------------------- # Configure & Build #----------------------------------------------------------------------------- include(${CMAKE_CURRENT_SOURCE_DIR}/../CMake/GenerateCLPTestMacros.cmake) GenerateCLP_TEST_PROJECT( NAME Utf8Example1 ) ``` -------------------------------- ### Build C++ Test Executable Source: https://github.com/slicer/slicerexecutionmodel/blob/master/ModuleDescriptionParser/Testing/CMakeLists.txt Configures the test source list and creates an executable for C++ tests using sem_add_executable. ```cmake set(KIT ${PROJECT_NAME}) create_test_sourcelist(Tests ${KIT}CxxTests.cxx ModuleDescriptionTest.cxx ) sem_add_executable(${KIT}CxxTests ModuleDescriptionTestingMacros.h ModuleDescriptionTestingUtilities.cxx ModuleDescriptionTestingUtilities.h ${Tests} ) target_link_libraries(${KIT}CxxTests ${KIT}) ``` -------------------------------- ### Configure Test Prerequisites Source: https://github.com/slicer/slicerexecutionmodel/blob/master/GenerateCLP/Testing/CMakeLists.txt Configures the prerequisite CMake file for test generation. ```cmake configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/CMake/GenerateCLPTestPrerequisites.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/CMake/GenerateCLPTestPrerequisites.cmake @ONLY ) ``` -------------------------------- ### Register Test Cases Source: https://github.com/slicer/slicerexecutionmodel/blob/master/ModuleDescriptionParser/Testing/CMakeLists.txt Registers individual test cases using add_test and the Slicer launch command. ```cmake set(TEST_DATA ${CMAKE_CURRENT_SOURCE_DIR}/TestData) add_test( NAME Parser1Test1 COMMAND ${Slicer_LAUNCH_COMMAND} $ ${TEST_DATA}/ParserTest1.xml ) add_test( NAME Parser1Test2 COMMAND ${Slicer_LAUNCH_COMMAND} $ ${TEST_DATA}/ParserTest2.xml) add_test( NAME Parser1Test3 COMMAND ${Slicer_LAUNCH_COMMAND} $ ${TEST_DATA}/ParserTest3.xml) add_test( NAME ModuleDescriptionTest COMMAND ${Slicer_LAUNCH_COMMAND} $ ModuleDescriptionTest ${TEST_DATA} ) ``` -------------------------------- ### Define CLI Module Interface in XML Source: https://context7.com/slicer/slicerexecutionmodel/llms.txt Defines module metadata, input/output parameters, and constraints for the CLI module. ```xml Filtering Simple Gaussian Filter Apply Gaussian smoothing to an image 1.0.0 Example Developer Sigma --sigma -s Gaussian sigma in mm 1.0 0.1 10.0 0.1 InputVolume input 0 Input volume to filter OutputVolume output 1 Filtered output volume ``` -------------------------------- ### Define a Custom Visitor Class Source: https://github.com/slicer/slicerexecutionmodel/blob/master/tclap/docs/manual.html Subclass the Visitor class to implement custom behavior in the visit() method. Data required for the operation should be passed through the constructor. ```cpp #include "Visitor.h" #include #include class AuthorVisitor : public Visitor { protected: string _author; public: AuthorVisitor(const string& name ) : Visitor(), _author(name) {} ; void visit() { cout << "AUTHOR: " << _author << endl; exit(0); }; }; ``` -------------------------------- ### Set project include directories Source: https://github.com/slicer/slicerexecutionmodel/blob/master/ModuleDescriptionParser/CMakeLists.txt Defines and caches the project include directories for use by other modules. ```cmake set(${PROJECT_NAME}_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} CACHE INTERNAL "${PROJECT_NAME} include dirs" FORCE) ``` -------------------------------- ### Parse XML Module Descriptions with ModuleDescriptionParser Source: https://context7.com/slicer/slicerexecutionmodel/llms.txt Use the ModuleDescriptionParser class to parse XML module descriptions into C++ objects. This allows programmatic access to module metadata and parameters. Ensure the XML file exists and is readable. ```cpp #include "ModuleDescriptionParser.h" #include "ModuleDescription.h" #include "ModuleParameterGroup.h" #include "ModuleParameter.h" #include #include int main() { // Read XML content from file std::ifstream file("MyModule.xml"); std::stringstream buffer; buffer << file.rdbuf(); std::string xmlContent = buffer.str(); // Parse the XML into a ModuleDescription ModuleDescription module; ModuleDescriptionParser parser; int result = parser.Parse(xmlContent, module); if (result != 0) { std::cerr << "Failed to parse XML" << std::endl; return EXIT_FAILURE; } // Access module metadata std::cout << "Title: " << module.GetTitle() << std::endl; std::cout << "Description: " << module.GetDescription() << std::endl; std::cout << "Version: " << module.GetVersion() << std::endl; std::cout << "Category: " << module.GetCategory() << std::endl; std::cout << "Contributor: " << module.GetContributor() << std::endl; // Iterate through parameter groups const std::vector& groups = module.GetParameterGroups(); for (const auto& group : groups) { std::cout << "\nGroup: " << group.GetLabel() << std::endl; std::cout << "Description: " << group.GetDescription() << std::endl; // Iterate through parameters in the group const std::vector& params = group.GetParameters(); for (const auto& param : params) { std::cout << " Parameter: " << param.GetName() << std::endl; std::cout << " Type: " << param.GetTag() << std::endl; std::cout << " Label: " << param.GetLabel() << std::endl; std::cout << " Default: " << param.GetValue() << std::endl; std::cout << " Flag: " << param.GetFlag() << std::endl; std::cout << " LongFlag: " << param.GetLongFlag() << std::endl; } } return EXIT_SUCCESS; } ``` -------------------------------- ### Build CLI Modules with SEMMacroBuildCLI CMake Macro Source: https://context7.com/slicer/slicerexecutionmodel/llms.txt Use the SEMMacroBuildCLI CMake macro to build complete CLI modules, specifying source files, libraries, include directories, and output paths. Ensure SlicerExecutionModel is found. ```cmake # CMakeLists.txt cmake_minimum_required(VERSION 3.13.4) project(ImageProcessor) find_package(SlicerExecutionModel REQUIRED) include(${SlicerExecutionModel_USE_FILE}) # Build a CLI module using SEMMacroBuildCLI SEMMacroBuildCLI( NAME ImageProcessor # Optional: specify custom XML file location # CLI_XML_FILE ${CMAKE_CURRENT_SOURCE_DIR}/custom.xml # Additional source files ADDITIONAL_SRCS helper.cxx utils.cxx # Libraries to link TARGET_LIBRARIES ${ITK_LIBRARIES} ${VTK_LIBRARIES} # Include directories INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/include # Optional: logo header file # LOGO_HEADER ${CMAKE_CURRENT_SOURCE_DIR}/logo.h # Build options # EXECUTABLE_ONLY # Build static library instead of shared # NO_INSTALL # Don't install targets # VERBOSE # Enable verbose output # Custom output directories RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib # Custom install destinations INSTALL_RUNTIME_DESTINATION bin INSTALL_LIBRARY_DESTINATION lib ) ``` -------------------------------- ### Register a Visitor with a SwitchArg Source: https://github.com/slicer/slicerexecutionmodel/blob/master/tclap/docs/manual.html Attach an instance of the custom Visitor to a SwitchArg during its declaration to trigger the visit() method upon argument parsing. ```cpp SwitchArg author("a","author","Prints author name", false, new AuthorVisitor("Homer J. Simpson") ); cmd.add( author ); ``` -------------------------------- ### Basic Argument Parsing with TCLAP Source: https://github.com/slicer/slicerexecutionmodel/blob/master/tclap/docs/manual.html Parses a string name and a boolean reverse flag from the command line. Handles potential TCLAP exceptions. ```cpp #include #include #include #include int main(int argc, char** argv) { // Wrap everything in a try block. Do this every time, // because exceptions will be thrown for problems. try { // Define the command line object, and insert a message // that describes the program. The "Command description message" // is printed last in the help text. The second argument is the // delimiter (usually space) and the last one is the version number. // The CmdLine object parses the argv array based on the Arg objects // that it contains. TCLAP::CmdLine cmd("Command description message", ' ', "0.9"); // Define a value argument and add it to the command line. // A value arg defines a flag and a type of value that it expects, // such as "-n Bishop". TCLAP::ValueArg nameArg("n","name","Name to print",true,"homer","string"); // Add the argument nameArg to the CmdLine object. The CmdLine object // uses this Arg to parse the command line. cmd.add( nameArg ); // Define a switch and add it to the command line. // A switch arg is a boolean argument and only defines a flag that // indicates true or false. In this example the SwitchArg adds itself // to the CmdLine object as part of the constructor. This eliminates // the need to call the cmd.add() method. All args have support in // their constructors to add themselves directly to the CmdLine object. // It doesn't matter which idiom you choose, they accomplish the same thing. TCLAP::SwitchArg reverseSwitch("r","reverse","Print name backwards", cmd, false); // Parse the argv array. cmd.parse( argc, argv ); // Get the value parsed by each arg. std::string name = nameArg.getValue(); bool reverseName = reverseSwitch.getValue(); // Do what you intend. if ( reverseName ) { std::reverse(name.begin(),name.end()); std::cout << "My name (spelled backwards) is: " << name << std::endl; } else std::cout << "My name is: " << name << std::endl; } catch (TCLAP::ArgException &e) // catch any exceptions { std::cerr << "error: " << e.error() << " for arg " << e.argId() << std::endl; } } ``` -------------------------------- ### XOR Add Two Arguments Source: https://github.com/slicer/slicerexecutionmodel/blob/master/tclap/docs/manual.html Use `xorAdd(Arg& a, Arg& b)` to ensure exactly one of two arguments is provided. TCLAP handles the validation. ```cpp ValueArg fileArg("f","file","File name to read",true,"/dev/null", "filename"); ValueArg urlArg("u","url","URL to load",true, "http://example.com", "URL"); cmd.xorAdd( fileArg, urlArg ); cmd.parse(argc, argv); ``` -------------------------------- ### Parse Command-Line Arguments with PARSE_ARGS Macro Source: https://context7.com/slicer/slicerexecutionmodel/llms.txt Use the PARSE_ARGS macro to automatically parse command-line arguments into C++ variables. Ensure the generated header from your XML file is included. ```cpp // MyModule.cxx #include "MyModuleCLP.h" // Generated header from MyModule.xml int main(int argc, char* argv[]) { // PARSE_ARGS macro handles all command-line parsing // Variables are automatically declared based on XML parameter names PARSE_ARGS; // Now all parameters are available as C++ variables: // - HistogramBins (int) // - Verbose (bool) // - InterpolationType (std::string) // - LearningRates (std::vector) // - InputImage (std::string) // - OutputImage (std::string) if (Verbose) { std::cout << "Processing with " << HistogramBins << " bins" << std::endl; std::cout << "Interpolation: " << InterpolationType << std::endl; } // Access vector parameters for (size_t i = 0; i < LearningRates.size(); ++i) { std::cout << "Learning rate " << i << ": " << LearningRates[i] << std::endl; } // Process files std::cout << "Input: " << InputImage << std::endl; std::cout << "Output: " << OutputImage << std::endl; return EXIT_SUCCESS; } ``` -------------------------------- ### Check Which XOR Argument is Set Source: https://github.com/slicer/slicerexecutionmodel/blob/master/tclap/docs/manual.html After parsing, use `isSet()` on each argument to determine which one was provided. If one argument is set, others in the XOR group are marked as set but `isSet()` will return false for them. ```cpp if ( fileArg.isSet() ) readFile( fileArg.getValue() ); else if ( urlArg.isSet() ) readURL( urlArg.getValue() ); else // Should never get here because TCLAP will note that one of the // required args above has not been set. throw("Very bad things..."); ``` -------------------------------- ### Include TCLAP Header File Source: https://github.com/slicer/slicerexecutionmodel/blob/master/tclap/docs/manual.html Shows the necessary include directive to use the TCLAP library in a C++ project. Ensure the compiler can find the header files. ```cpp #include ``` -------------------------------- ### Declare and Add UnlabeledMultiArg Source: https://github.com/slicer/slicerexecutionmodel/blob/master/tclap/docs/manual.html Shows how to declare and add an UnlabeledMultiArg to handle multiple unlabeled values. This must be the last argument added to the CmdLine. ```cpp // // UnlabeledMultiArg must be the LAST argument added! // UnlabeledMultiArg multi("file names"); cmd.add( multi ); cmd.parse(argc, argv); vector fileNames = multi.getValue(); ``` -------------------------------- ### Command Line Parsing Error Source: https://github.com/slicer/slicerexecutionmodel/blob/master/tclap/docs/manual.html Illustrates a scenario where required arguments are missing, resulting in a parse error and a brief usage message. ```bash % test1 -r PARSE ERROR: One or more required arguments missing! ``` -------------------------------- ### Disable Automatic Help and Version Flags Source: https://github.com/slicer/slicerexecutionmodel/blob/master/tclap/docs/manual.html Prevent TCLAP from automatically generating --help and --version switches by setting the fourth parameter of the CmdLine constructor to false. ```cpp CmdLine cmd("this is a message", ' ', "0.99", false ); ``` -------------------------------- ### Read Integers in Different Bases with TCLAP Source: https://github.com/slicer/slicerexecutionmodel/blob/master/tclap/docs/manual.html Enable parsing of integers in decimal, hexadecimal, and octal formats by defining TCLAP_SETBASE_ZERO before including the TCLAP header. This allows for more flexible integer input. ```cpp #define TCLAP_SETBASE_ZERO 1 #include "tclap/CmdLine.h" #include using namespace TCLAP; using namespace std; int main(int argc, char** argv) { try { CmdLine cmd("this is a message", ' ', "0.99" ); ValueArg itest("i", "intTest", "integer test", true, 5, "int"); cmd.add( itest ); // // Parse the command line. // cmd.parse(argc,argv); // // Set variables // int _intTest = itest.getValue(); cout << "found int: " << _intTest << endl; } catch ( ArgException& e ) { cout << "ERROR: " << e.error() << " " << e.argId() << endl; } } ``` -------------------------------- ### XOR Add Multiple Arguments Source: https://github.com/slicer/slicerexecutionmodel/blob/master/tclap/docs/manual.html Use `xorAdd(vector xorList)` to enforce that exactly one argument from a list of three or more is provided. Ensure all arguments are added to the vector. ```cpp SwitchArg stdinArg("s", "stdin", "Read from STDIN", false); ValueArg fileArg("f","file","File name to read",true,"/dev/null", "filename"); ValueArg urlArg("u","url","URL to load",true, "http://example.com", "URL"); vector xorlist; xorlist.push_back(&stdinArg); xorlist.push_back(&fileArg); xorlist.push_back(&urlArg); cmd.xorAdd( xorlist ); ``` -------------------------------- ### Define Slicer Execution Model Tests Source: https://github.com/slicer/slicerexecutionmodel/blob/master/GenerateCLP/Testing/Utf8Example/CMakeLists.txt Registers test cases for the project using the generated executable. ```cmake add_test(NAME SlicerCLPExample1 COMMAND $ --help) add_test(NAME SlicerCLPExample2 COMMAND $) ``` -------------------------------- ### CmdLine Class Source: https://github.com/slicer/slicerexecutionmodel/blob/master/tclap/docs/manual.html The CmdLine class manages the parsing of command-line arguments. It keeps track of required arguments, relationships between arguments, and output generation, but does not perform the actual parsing itself. ```APIDOC ## CmdLine Class ### Description The `CmdLine` class contains the arguments that define the command line and manages the parsing of the command line. The `CmdLine` doesn't parse the command line itself; it only manages the parsing. The actual parsing of individual arguments occurs within the arguments themselves. The `CmdLine` keeps track of required arguments, relationships between arguments, and output generation. ### Method N/A (Class description) ### Endpoint N/A (Class description) ``` -------------------------------- ### SwitchArg Class Source: https://github.com/slicer/slicerexecutionmodel/blob/master/tclap/docs/manual.html SwitchArg represents simple, on/off, boolean switches. They are used to enable or disable system properties and do not parse a value, returning TRUE or FALSE based on presence and default value. ```APIDOC ## SwitchArg Class ### Description `SwitchArg`s are simple, on/off, boolean switches. Use `SwitchArg`s anytime you want to turn some sort of system property on or off. `SwitchArg`s don't parse a value. They return `TRUE` or `FALSE`, depending on whether the switch has been found on the command line and what the default value was defined as. ### Method N/A (Class description) ### Endpoint N/A (Class description) ```