SimpleITK  1.2.4
Image Filter Templates ReadMe

This ReadMe outlines the system used to generate SimpleITK files using json data files in conjunction with the template .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 JSON data file which specifies the information needed to fill in the fields of the template file. During compilation, all of the .json files are parsed using a lua template engine which fills in the appropriate template file from the provided fields. This ReadMe provides a detailed description of the fields that can be used in the json data files and what effect each field has on the resulting image filter. When writing your own json file, it should be saved in:

$SimpleITK_SOURCE_DIR/Code/$FILTER_DIR/json

Here $FILTER_DIR is the directory in which the code for the generated filter should live. For simple filters this is the "BasicFilters" directory.

JSON File Structure

JSON (JavaScript Object Notation) is a simple text formatting system used to specify data values. A full description of the specification can be found at http://www.json.org/. For the purposes of SimpleITK, a json file consists of a single data object (denoted by {}) which contains several string : value pairs (here value may be a list denoted by []) and sub-objects. Here is an example from LaplacianRecursiveGaussian:

{
  "name" : "LaplacianRecursiveGaussianImageFilter",
  "template_code_filename" : "ImageFilter",
  "template_test_filename" : "ImageFilter",
  "doc" : "",
  "number_of_inputs" : 1,
  "pixel_types" : "BasicPixelIDTypeList",
  "output_pixel_type" : "float",
  "members" : [
    {
      "name" : "Sigma",
      "type" : "double",
      "default" : "1.0",
      "doc" : "",
      "briefdescriptionSet" : "",
      "detaileddescriptionSet" : "Set Sigma value. Sigma is measured in the units of image spacing.",
      "briefdescriptionGet" : "",
      "detaileddescriptionGet" : "Set Sigma value. Sigma is measured in the units of image spacing."
    },
    {
      "name" : "NormalizeAcrossScale",
      "type" : "bool",
      "default" : "false",
      "doc" : "",
      "briefdescriptionSet" : "",
      "detaileddescriptionSet" : "Define which normalization factor will be used for the Gaussian \\see RecursiveGaussianImageFilter::SetNormalizeAcrossScale",
      "briefdescriptionGet" : "",
      "detaileddescriptionGet" : "Define which normalization factor will be used for the Gaussian \\see RecursiveGaussianImageFilter::SetNormalizeAcrossScale"
    }
  ],
  "tests" : [
    {
      "tag" : "default",
      "description" : "Simply run with default settings",
      "settings" : [],
      "tolerance" : 0.0001,
      "inputs" : [
        "Input/RA-Float.nrrd"
      ]
    }
  ],
  "briefdescription" : "Computes the Laplacian of Gaussian (LoG) of an image.",
  "detaileddescription" : "Computes the Laplacian of Gaussian (LoG) of an image by convolution with the second derivative of a Gaussian. This filter is implemented using the recursive gaussian filters.",
  "itk_module" : "ITKImageFeature",
  "itk_group" : "ImageFeature"
}

In this example, we see that all pairs must use a string as the key, but may have any valid type as the value (string - "Abs", number - 1, list - [], object - {}).

Fields For All Templates

This section describes the minimal set of fields required to wrap an ITK filter into SimpleITK.

Top Level Fields

<InputImageType, (if 2 inputs)InputImageType, OutputImageType)>

Some filters require additional template types between the list of input image types and the output image type such as the input type of a constant. This list allows these additional parameters to be added so that the template signature looks like:

<InputImageType, (if 2 inputs)InputImageType, (ADDITIONAL TYPES), OutputImageType)>

Each type in the list is specified by an object with a only a type field which is a string specifying the type to be used.

A sample custom method might look like:

{ "name" : "Foo",
  "doc" : "This method checks if a string is equal to Foo"
  "return_type" : "bool",
  "parameters" : [
    { "type" : "std::string",
      "var_name" : "inString"
    }
  ],
  "body" : "if (!strcmp(inString.c_str(), "Foo")) { return true; } else { return false; }"
}

This will translate to a custom method that looks like:

  /**
   * This method checks if a string is equal to Foo
   */
  bool Foo( std::string inString )
    {
    if (!strcmp(inString.c_str(), "Foo")) { return true; } else { return false; }
    }

Member Fields

A basic member object looks like:

{
  "name" : "Sigma",
  "type" : "double",
  "default" : 1.0,
  "briefdescriptionSet" : "",
  "detaileddescriptionSet" : "Define which normalization factor will be used for the Gaussian\\see RecursiveGaussianImageFilter::SetNormalizeAcrossScale\n\n",
  "briefdescriptionGet" : "",
  "detaileddescriptionGet" : ""
 }
"custom_itk_cast" :
  "filter->SetObjectValue(static_cast<typename FilterType::PixelType>(this->GetObjectValue()) );"

Test Fields

A basic test object looks like:

{
  "tag" : "float",
  "description" : "Dilate a float image",
  "inputA" : "Input/RA-Slice-Float.nrrd",
  "tolerance" : 0.01,
  "settings" : []
}

There are three ways of checking the resulting image: against a baseline image, a sha1 hash, or an md5 hash. At least one of these options must be used for each test.

{ "parameter" : "Sigma",
  "value" : 1.0
}
{ "parameter" : "Size",
  "dim_vec" : 1,
  "type" : "unsigned int"
  "value" : "{1,2}",
  "java_value" : "{1,2}",
  "tcl_value" : "[list 1 2]",
  "python_value" : "[1,2]",
  "lua_value" : "{1,2}",
  "ruby_value" : "[1,2]"
}

Directory Structure

The code generation system is designed to be agnostic of what subdirectory is being parsed. An example of this is BasicFilters. Here will just refer to $FILTER_DIR

There are four important subdirectores in $SimpleITK_SOURCE_DIR/Code/$FILTER_DIR:

When a filter is generated, it produces a .h and a .cxx file that are placed in $SimpleITK_BUILD_DIR/Code/$FILTER_DIR/include and $SimpleITK_BUILD_DIR/Code/$FILTER_DIR/src respectively.

It is also worth noting that the template files in the templates directory are comprised of a combination of c++ code, lua template expansion directives, and $(include xxx) statements. These include statements each pull in a section of template code from a file in $SimpleITK_SOURCE_DIR/ExpandTemplateGenerator/Components. These component files represent pieces of templates that are shared by multiple unique filter template types.

Specialized Templates

The standard template is ImageFilter. This section describes the differences for each of the other template types.