Developer
Image Filter Templates ReadMe
This section outlines the system used to generate SimpleITK source code using an “Expand Template Generator” system. It uses Jinja as a template engine with YAML configuration files, template files for .h and .cxx files.
Overview
In order to create a uniform body of image filters, we use an automated code generation system to wrap existing ITK filters into SimpleITK filters. The development process consists of writing a YAML configuration file which specifies the information needed to fill in the fields of the template file. During the SimpleITK build process, each .yaml files are parsed using a Jinja template engine, with a header (.h) and a implementation (.cxx). Additionally, for each enabled language and C++, there is a test Jinja template that is used to generate testing source code.
Available Templates
The following template types are available in Code/BasicFilters/templates/ for generating SimpleITK filters:
ImageFilter: The standard template for most image filters with a single input image type or template. This is the most commonly used template and supports filters that take one input image and produce one output image.
BinaryFunctorFilter: Template for filters that perform pixel-wise operations between two input images using a functor (mathematical operation). Examples include arithmetic operations like addition, subtraction, multiplication, etc.
MultiInputImageFilter: Template for filters that accepts a variable number of input images. This template provides support for a variable number of inputs and a vector of images as input.
ImageSource: Template for filters that generate images without requiring input images. These are source filters that create images from parameters or mathematical functions.
DualImageFilter: Template that instantiates filters with combinations of different pixel types. This template should be used with caution as it can significantly increase compilation time and binary size due to the combinatorial explosion of type instantiations.
YAML Schema
YAML (YAML Ain’t Markup Language) is a human-readable data serialization format that is often used for configuration files and data exchange between languages with different data structures. For the purposes of SimpleITK, a yaml file consists of a single document which contains key-value pairs, lists, and nested structures.
The schema used for SimpleITK filter generation is defined in the ExpandTemplateGenerator/simpleitk_filter_description.schema.json file. This Schema document provides formal validation rules and documentation for all the fields that can be used in YAML filter description files.
The schema defines the structure for filter descriptions including required fields, optional parameters, data types, and validation constraints. It serves as both documentation and validation for YAML filter files used in the code generation process.
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "SimpleITK Filter Description",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Name of the filter as a SimpleITK class. This must be the name of the ITK filter."
},
"itk_name": {
"type": "string",
"description": "Name of the filter in ITK class, pamameter if not provided then the name properties will be used."
},
"template_code_filename": {
"type": "string",
"description": "The JINJA template template files used to generate the filter. The 'ImageFilter' is the baseline one."
},
"template_test_filename": {
"type": "string",
"description": "The JINJA template template files used to generate the test. The 'ImageFilter' is the baseline one."
},
"constant_type": {
"type": "string",
"description": "The Binary Functor template uses this as the optional non-image type for the operation."
},
"custom_register": {
"type": "string",
"description": "Custom registration code for the memberfunction factory. (optional)"
},
"filter_type": {
"type": "string",
"description": "The ITK filter type including template arguments. This allows for overriding template parameterization of the ITK class. (optional)"
},
"number_of_inputs": {
"type": "integer",
"description": "Number of input images",
"minimum": 0
},
"public_declarations": {
"type": "string",
"description": "Public declarations for the filter, can be used to declare and define a public member function."
},
"doc": {
"type": "string",
"description": "Documentation string for the filter."
},
"pixel_types": {
"type": "string",
"description": "Allowed pixel types (enum or type list) for the filter. The type lists are defined in sitkPixelIDTypeLists.h. Examples: 'BasicPixelIDTypeList', 'IntegerPixelIDTypeList'."
},
"output_pixel_type": {
"type": "string",
"description": "Output pixel type used for the output image template of the filter (optional)."
},
"vector_pixel_types_by_component": {
"type": "string",
"description": "Allowed vector pixel types (optional)"
},
"members": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "The name of the member variable. A variable named 'Var' will be accessible with the methods 'GetVar' and 'SetVar'."
},
"type": {
"type": "string",
"description": "The C++ type for this member. If using a type contained in a certain namespace (itk::simple for example), this must be included. If the member variable is of type bool, the additional ${name}On and ${name}Off member functions are added (optional)."
},
"default": {
"description": "The default value for this member. Can be a number for numerical types or a string specifying the constructor for non-basic types (std::vector< unsigned int >{} for example)."
},
"dim_vec": {
"type": "boolean",
"description": "If set to true, indicates the member is a std::vector with size equal to the dimension of the input image. As such, it will be printed out correctly and cast to its corresponding ITK type correctly (optional).",
"default": false
},
"point_vec": {
"type": "boolean",
"description": "Is this a vector of points parameter? (optional)",
"default": false
},
"enum": {
"type": "array",
"items": {
"type": "string"
},
"description": "Creates a member type of the class with the array of strings with a type defined by the name of this parameter. This field makes the 'type' parameter optional. It is recommended to add a test to ensure the SimpleITK values correspond to the ITK values (optional)."
},
"set_as_scalar": {
"type": "boolean",
"description": "If parameter is a dim_vec, then this method adds an additional set member method to set the variable as a scalar so that all components are the same (optional).",
"default": false
},
"doc": {
"type": "string",
"description": "Documentation (optional)"
},
"itk_type": {
"type": "string",
"description": "ITK type (optional)"
},
"briefdescriptionSet": {
"type": "string",
"description": "Brief description for setter (optional)"
},
"detaileddescriptionSet": {
"type": "string",
"description": "Detailed description for setter (optional)"
},
"briefdescriptionGet": {
"type": "string",
"description": "Brief description for getter (optional)"
},
"detaileddescriptionGet": {
"type": "string",
"description": "Detailed description for getter (optional)"
},
"custom_itk_cast": {
"type": "string",
"description": "Some non-basic types will require a custom cast before the corresponding ITK filter's member can be set. Allows specification how the ITK filter sets the member's value from the SimpleITK member's value, for example: 'filter->SetObjectValue(static_cast<typename FilterType::PixelType>(this->GetObjectValue()) );' (optional)."
},
"no_print": {
"type": "boolean",
"description": "Should not be printed (optional)",
"default": false
},
"pixeltype": {
"type": "string",
"description": "Pixel type (optional)"
}
},
"additionalProperties": false
}
},
"tests": {
"type": "array",
"items": {
"type": "object",
"properties": {
"tag": {
"type": "string",
"description": "The tag to identify this specific test for the filter."
},
"description": {
"type": "string",
"description": "Documentation to describe this specific test."
},
"no_procedure": {
"type": "boolean",
"description": "Do not test the procedural interface.",
"default": false
},
"md5hash": {
"type": "string",
"description": "An MD5 hash value to compare the resulting image against (optional)."
},
"settings": {
"type": "array",
"description": "Test parameter settings. For parameters defined with dim_vec=true in members, must also specify dim_vec=true here with base element type.",
"items": {
"type": "object",
"properties": {
"parameter": {
"type": "string",
"description": "Parameter name"
},
"type": {
"type": "string",
"description": "Data type"
},
"dim_vec": {
"type": "boolean",
"description": "If true then the value is exepected to be a YAML array, and the type is the vector component type e.g., 'uint32_t' part of 'std::vector<uint32_t>'.(optional)",
"default": false
},
"point_vec": {
"type": "boolean",
"description": "Is this a vector of points parameter? (optional)",
"default": false
},
"no_get_method": {
"type": "boolean",
"description": "Do not generate a getter method for this parameter (optional)",
"default": false
},
"value": {
"description": "Value (number, string, or array). For dim_vec parameters, use YAML array format."
},
"python_value": {
"description": "Language-specific value (optional)"
},
"lua_value": {
"description": "Language-specific value (optional)"
},
"ruby_value": {
"description": "Language-specific value (optional)"
},
"java_value": {
"description": "Language-specific value (optional)"
},
"tcl_value": {
"description": "Language-specific value (optional)"
},
"csharp_value": {
"description": "Language-specific value (optional)"
},
"cxx_value": {
"description": "Language-specific value (optional)"
},
"R_value": {
"description": "Language-specific value (optional)"
}
},
"additionalProperties": false
}
},
"inputs": {
"type": "array",
"items": {
"type": "string"
},
"description": "List of input files"
},
"tolerance": {
"type": "number",
"description": "Enables image comparison of output. The tolerance is root mean squared error between the baseline image and the output (optional)."
},
"inputA_cast": {
"type": "string",
"description": "An sitkPixelIDEnum. After input 1 is read, the CastImageFilter is run to convert the image type (optional)."
},
"inputB_cast": {
"type": "string",
"description": "An sitkPixelIDEnum for the second input, after input 2 is read the CastImageFilter is run to convert the image type (optional)."
},
"measurements_results": {
"type": "array",
"description": "Results for measurements (optional)",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Measurement name"
},
"parameters": {
"type": "array",
"description": "List of parameters for this measurement (optional)",
"items": {
"type": [
"string",
"number"
],
"description": "Parameter value to pass to measurement"
}
},
"dim_vec": {
"type": "boolean",
"description": "Is this a vector parameter? (optional)",
"default": false
},
"value": {
"description": "Measurement value (number, string, etc.)"
},
"python_value": {
"description": "Language-specific value (optional)"
},
"lua_value": {
"description": "Language-specific value (optional)"
},
"ruby_value": {
"description": "Language-specific value (optional)"
},
"java_value": {
"description": "Language-specific value (optional)"
},
"tcl_value": {
"description": "Language-specific value (optional)"
},
"csharp_value": {
"description": "Language-specific value (optional)"
},
"r_value": {
"description": "Language-specific value (optional)"
},
"tolerance": {
"description": "Tolerance for measurement (optional)"
}
},
"additionalProperties": false
}
}
},
"additionalProperties": false,
"required": [
"tag",
"description",
"inputs"
]
}
},
"briefdescription": {
"type": "string",
"description": "Brief description of the filter"
},
"detaileddescription": {
"type": "string",
"description": "Detailed description of the filter"
},
"itk_module": {
"type": "string",
"description": "A string naming the ITK module the filter originates from. If the ITK installation used for building SimpleITK does not have this named module then the filter will be omitted in SimpleITK. This field is maintained by JSONUpdateITKModules.py script."
},
"itk_group": {
"type": "string",
"description": "A string naming the ITK group the ITK filter originates from."
},
"in_place": {
"type": "boolean",
"description": "Can operate in-place?",
"default": false
},
"custom_methods": {
"type": "array",
"description": "This is a list of objects specifying custom methods that should be added to the filter (optional).",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Method name"
},
"doc": {
"type": "string",
"description": "Documentation for this custom method."
},
"briefdescription": {
"type": "string",
"description": "Brief description of the method (maybe removed)"
},
"detaileddescription": {
"type": "string",
"description": "Detailed description of the method (maybe removed)"
},
"static": {
"type": "boolean",
"description": "Is this method static?"
},
"return_type": {
"type": "string",
"description": "Return type"
},
"parameters": {
"type": "array",
"description": "Method parameters",
"items": {
"type": "object",
"properties": {
"type": {
"type": "string",
"description": "The parameter's type."
},
"var_name": {
"type": "string",
"description": "The name of the variable to be used in the body field for the custom method."
}
},
"required": [
"type",
"var_name"
],
"additionalProperties": false
}
},
"body": {
"type": "string",
"description": "This string is the body of the method and will be placed directly into the header file. The parameter names specified with var_name in each of the parameter objects can be used in this body."
}
},
"additionalProperties": false,
"required": [
"name",
"return_type",
"parameters",
"body"
]
}
},
"custom_set_input": {
"type": "string",
"description": "Code which is used to set input or multiple inputs to the filter. This overrides the standard setting of the inputs (optional)."
},
"no_procedure": {
"type": "boolean",
"description": "No procedure (optional)",
"default": false
},
"no_return_image": {
"type": "boolean",
"description": "If true then returns void instead of an image (optional)",
"default": false
},
"measurements": {
"type": "array",
"description": "List of measurement descriptors (optional)",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Measurement name"
},
"type": {
"type": "string",
"description": "Measurement type"
},
"function_name": {
"type": "string",
"description": "Function name for this measurement (optional) (may be removed)"
},
"active": {
"type": "boolean",
"description": "Is measurement active? (optional)",
"default": false
},
"default": {
"description": "Default value (optional)"
},
"no_print": {
"type": "boolean",
"description": "Suppress output for this measurement (optional)",
"default": false
},
"custom_itk_cast": {
"type": "string",
"description": "Custom ITK cast for this measurement (optional)"
},
"custom_cast": {
"type": "string",
"description": "Custom cast for this measurement (optional), used only with active measurements"
},
"itk_get": {
"type": "string",
"description": "ITK get function for this measurement (optional)"
},
"label_map": {
"type": "boolean",
"description": "Label map for this measurement (optional)"
},
"non_const": {
"type": "boolean",
"description": "Is this measurement non-const? (optional)",
"default": false
},
"briefdescriptionGet": {
"type": "string",
"description": "Brief description for getter (optional)"
},
"detaileddescriptionGet": {
"type": "string",
"description": "Detailed description for getter (optional)"
},
"parameters": {
"type": "array",
"description": "List of parameters for measurements or methods (optional)",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Parameter name"
},
"type": {
"type": "string",
"description": "Parameter type"
}
},
"required": [
"name",
"type"
],
"additionalProperties": false
}
}
},
"additionalProperties": false
}
},
"include_files": {
"type": "array",
"items": {
"type": "string"
},
"description": "This list of strings specifies additional header files to include in the cxx file for this filter (optional)."
},
"output_image_type": {
"type": "string",
"description": "Output image type (optional)"
},
"pixel_types2": {
"type": "string",
"description": "Second input pixel types (optional)"
},
"custom_type2": {
"type": "string",
"description": "Custom type for second input (optional)"
},
"vector_pixel_types_by_component2": {
"type": "string",
"description": "Vector pixel types for second input (optional)"
},
"inputs": {
"type": "array",
"description": "List of input image descriptors (optional, for filters with non-standard or multiple named inputs)",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Input name"
},
"type": {
"type": "string",
"description": "Input type"
},
"optional": {
"type": "boolean",
"description": "Is this input optional?"
},
"no_size_check": {
"type": "boolean",
"description": "Skip checking that the size of this input matches the first (optional)",
"default": false
},
"custom_itk_cast": {
"type": "string",
"description": "Custom ITK cast code (optional)"
}
},
"required": [
"name",
"type"
],
"additionalProperties": false
}
}
},
"required": [
"name",
"template_code_filename",
"template_test_filename",
"number_of_inputs",
"pixel_types",
"members",
"tests",
"briefdescription",
"detaileddescription",
"itk_module",
"itk_group"
],
"additionalProperties": false
}