Slicer3:Execution Model
Contents
Abstract
The purpose of this proposal is to facilitate a "run-everywhere" philosophy for algorithm writers. If NAMIC adopts a standard for algorithm "self-description" that is followed when command line executables are written, Slicer, the grid, clusters, etc... should be able to use the executables directly in their environment.
Execution model for stand-alone executables
For Slicer3 to interact with stand-alone executables, a communications protocol must be created and implemented on both sides. This implies that the executable must be able to describe itself in sufficient detail for Slicer3 to run it and retrieve the results of the algorithm.
Initial Standard
This sample describes the initial standard. The current best implementation is to write your XML algorithm description by hand, then have your executable respond to the --xml flag by producing the XML description to standard output.
Some notes about the sample below.
- The <category> tag corresponds to where the executable should show up in a menu on the calling Application
- <parameters> tags are grouped together by name in the GUI, in the example "Registration Parameters" and "IO"
- The currently described parameters are
- <integer> for simple integers
- <double> for floating point numbers
- <string> for string arguments
- <boolean> for boolean switches
- <image> for images. The current standard is 3d images, but may be agumented in the future
- <file> for files.
- <integer-vector> for a comma separated list of integers
- <float-vector> for a comma separated list of floats
- <double-vector> for a comma separated list of doubles
- Most parameters share some common attributes
- <flag> the short flag for this parameter, i.e. <flag>f</flag>
- <longflag> the long flag for this parameter, i.e. <longflag>foo</longflag>
- <label> the text to display next to the parameter
- <default> default value
- <description> a useful description of the parameter, suitable for tool tips, etc...
- <constraints> currently <minimum>, <maximum>, and <step> for <integer> and <double>
- For positional arguments, an index is required, in this case Fixed and Moving images are indices 0 and 1
- For images, there is a <channel> tag. <channel>input</channel> indicates that this file is read by the executable, <channel>output</channel> indicates the executale writes the image
To Do
- Add radiobutton like choices
- Add image format discription, i.e. does this algorithm handle 2D images, need DICOM files, etc...
- Establish convention for progress indications
- XSD
This is the example from the NAMIC Sandbox.
{practical:CommandLineAPI-Linux}1356:./CLRegistration --xml <?xml version="1.0" encoding="utf-8"?> <executable> <category>registration</category> <title>NAMIC sample registration</title> <description>Registers two images together using a rigid transform and MI</description> <version>1.0</version> <documentationurl></documentationurl> <license></license> <contributor>Daniel Blezek</contributor> <parameters> <label>Registration Parameters</label> <description>Parameters used for registration</description> <integer> <flag>b</flag> <longflag>histogrambins</longflag> <description>Number of histogram bins to use for Mattes Mutual Information</description> <label>Histogram Bins</label> <default>30</default> <constraints> <minimum>1</minimum> <maximum>500</maximum> <step>5</step> </constraints> </integer> <integer> <flag>s</flag> <longflag>spatialsamples</longflag> <description>Number of spatial samples to use in estimating Mattes Mutual Information</description> <label>Spatial Samples</label> <default>10000</default> <constraints> <minimum>1000</minimum> <maximum>50000</maximum> <step>1000</step> </constraints> </integer> <string> <flag>i</flag> <longflag>iterations</longflag> <description>Comma separated list of iterations must have the same number of elements as learning rate</description> <label>Iterations</label> <default>200,100</default> </string> <string> <flag>l</flag> <longflag>learningrate</longflag> <description>Comma separated list of learning rates must have the same number of elements as iterations</description> <label>Learning Rates</label> <default>0.05,0.005</default> </string> <double> <longflag>translationscale</longflag> <flag>t</flag> <description>Relative scale of translations to rotations, i.e. a value of 100 means 10mm = 1 degree</description> <label>Translation scaling</label> <default>100.0</default> <constraints> <minimum>10.0</minimum> <maximum>500.0</maximum> <step>50.0</step> </constraints> </double> </parameters> <parameters> <label>IO</label> <description>Input/output parameters</description> <image> <name>Fixed</name> <label>Fixed Image</label> <channel>input</channel> <index>0</index> <description>Fixed image to register to</description> </image> <image> <name>Moving</name> <label>Moving Image</label> <channel>input</channel> <index>1</index> <description>Moving image</description> </image> <image> <name>Output</name> <label>Output Volume</label> <channel>output</channel> <index>2</index> <description>Resampled Moving Image</description> </image> </parameters> </executable>
Sample screenshots
Open questions
- What classes of algorithms should Slicer3 be aware of?
- Registration, classification, segmentation, filtering?
- How should Slicer3 communicate with the executables?
- Special FileIO objects (for ITK) has been suggested.
- MMapped files for efficient IO.
- Shared memory.
- Standard files.
- Does Slicer3 need to communicate with the executing process?
- For status, "Cancel" operations, etc...
Proposal
If we adopt a standard XML description of the parameters to the algorithm, any application should be able to parse the XML and construct a GUI suitable for interaction with the software.
Below are potential ideas for an XML file format:
Initial JSON output from sample registration package
/* JSON version 1.0 */ { "class" : "registration", "name" : "CLRegistration", "info" : "Register two volumes", "executable" : "CLRegistration", "requiredparameters": { "fixed" : { "type" : "file", "index" : "0", "channel" : "input", /* what about image dimension: 2, 3, ... */ }, "moving" : { }, "output" : { } "parameters" : { "histogrambins" : { "flag" : "b", "name" : "histogrambins", "displayname" : "Number of histogram bins", "description" : "Number of histogram bins", "type" : "integer", "guihints" : "slider", "range" : "[5-200]", "default" : "100" }, "randomseed" : { "flag" : "d", "name" : "randomseed", }, "gradtolerance" : { "flag" : "g", "name" : "gradtolerance", }, "iterations" : { "flag" : "i", "name" : "iterations", }, "learningrate" : { "flag" : "l", "name" : "learningrate", }, "spatialsamples" : { "flag" : "s", "name" : "spatialsamples", }, "translationscale" : { "flag" : "t", "name" : "translationscale", }, "noinitializetransform" : { "flag" : "u", "name" : "noinitializetransform", }, "help" : { "flag" : "h", "name" : "help", }, "json" : { "flag" : "j", "name" : "json", }, } }
XML Version of the same description
<sl class = "registration" name = "CLRegistration" info = "Register two volumes" executable = "CLRegistration"> <requiredparameters> <requirement name="fixed"> type = "file" index = "0" channel = "input" </requirement> <requirement name="moving" /> <requirement name="output" /> </requiredparameters> <parameters> <parameter name="histogrambins" flag = "b" name = "histogrambins" displayname = "Number of histogram bins" description = "Number of histogram bins" type = "integer" guihints = "slider" range = "[5-200]" default = "100" /> <parameter name="randomseed" flag = "d" name = "randomseed" /> <parameter name="gradtolerance" flag = "g" name = "gradtolerance" /> <parameter name="iterations" flag = "i" name = "iterations" /> <parameter name="learningrate" flag = "l" name = "learningrate" /> <parameter name="spatialsamples" flag = "s" name = "spatialsamples" /> <parameter name="translationscale" flag = "t" name = "translationscale" /> <parameter name="noinitializetransform" flag = "u" name = "noinitializetransform" /> <parameter name="help" flag = "h" name = "help" /> <parameter name="json" flag = "j" name = "json" /> </parameters> </sl>
Data-centric proposal
<?xml version="1.0" encoding="utf-8"?> <executable class="registration"> <Name>CLRegistration</name> <Description>Registers two images, writes the resampled moving image</description> <Parameters> <Parameter required="false" flag="t" name="threshold"> <Description>Threshold</Description> <Type>integer</Type> <Constraints> <Range minimum="0" maximum="100"/> </Constraints> </Parameter> <Parameter required="true"> </Parameter> </Parameters> </executable>
GUI-centric proposal
<?xml version="1.0" encoding="utf-8"?> <executable class="register"> <name>Register3d</name> <version>1.0</version> <description>This registers and resamples two images</description> <parameters> <switch name="interpolate" flag="i" default="true" required="false"> <description></description> </switch> <value name="metric" flag="m" default="mattes" required="false" type="string"> <description></description> <constraints> <list> <constraint>mattes</constraint> <constraint>mi</constraint> <constraint>normalizedcorrelation</constraint> </list> </constraints> </value> <value name="threshold" flag="t" type="integer"> <constraints> <range minimum="0" maximum="100"/> <increment>.1</increment> </constraints> </value> <value name="iterations" flag="e" type="iteration" allowrepeats="true"> <constraints> <range minimum="1"/> </constraints> </value> <xor> <value name="file" flag="f" type="filename"/> <value name="url" flag="u"/> </xor> <unlabeledvalue name="fixedimage" position="0" type="filename"/> <unlabeledvalue name="movingimage" position="1" type="filename"/> <unlabeledvalue name="outputimage" position="2" type="filename"/> </parameters> </executable>
JSON description
/* JSON version 1.0 January 11, 2005 */ { "class" : "registration", "name" : "CLRegistration", "info" : "Registers two images, writes the resampled moving image", "executable" : "CLRegistration", "parameters" : "threshold" : { "info" : "threshold" "flag" : "t", "required" : "true", "type" : "integer", "default" : "50", "contraints" : { "range" : { "minimum" : "0", "maximum" : "100" } }, "guihints" : { "control" : "slider", "group" : "preprocessing" } }, "xsigma" : { "info" : "X Direction in sigma", "flag" : "x", "required" : "false", "type" : "float", "default" : "1.0", "contraints" : { "range" : { "minimum" : "0", "maximum" : "5.0" } }, "guihints" : { "control" : "slider", "group" : "preprocessing" } }, "fixedfile" : { "info" : "Fixed Image", "order" : "0", "required" : "true", "type" : "file", "contraints" : { "filetypes" : [ "ITK", "Slicerd", "MRML" ] }, "guihints" : { "control" : "fileselection", "group" : "io" } }, }
Related Work
MetaCommand
Julien Jomier and Stephen Aylward have added support for command line parsing to itk with the MetaCommand class (Utilities/MetaIO/metaCommand.{h,cxx}). It supports a -xml flag to output args in an xml syntax.
Qt Designer XML Format
Qt has an xml syntax for representing their GUI layouts. It's unclear if this tool could be used to design layouts used by other GUI packages.
ParaView Server
ParaView has a syntax to extend the GUI described on their wiki here.
LONI Pipeline
Parameters to executables are described in an XML file as part of the process of wrapping them for the pipeline. These XML descriptions are quite similar to the example given above. Some example pipelines are available at the Pipeline Wiki. A working draft of the language description is found also on the Wiki.
JSON
Mike Halle suggested looking a JSON to describe the command line arguments to the parser, then to fill in the values from the command line. With this description, a GUI could build an interface for your code and/or communicate with your executable using JSON. Requires a standard set of elements.
JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easy for humans to read and write. It is easy for machines to parse and generate. It is based on a subset of the JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1999. JSON is a text format that is completely language independent but uses conventions that are familiar to programmers of the C-family of languages, including C, C++, C#, Java, JavaScript, Perl, Python, and many others. These properties make JSON an ideal data-interchange language.
DICOM Working Group 23
Dave Channin suggests this group be aware of the efforts of DICOM Working Group 23 along these lines. Although termed application hosting the work group is defining a DICOM standard mechanism by which a workstation can invoke an algorithm, send it (DICOM) data and receive from it (DICOM) results (as well as statuses, etc.) Although still in draft form they are thinking about using web services and in particular, OGSA (Open Grid Services Architecture). This has the interesting repercussion of allowing invoked algorihtms to be run locally or over the grid. This effort may be of interest to this group along two lines: 1) IMNSHO, Slicer should support the DICOM WG23 plug so as to be able to invoke compliant algorithms, and 2) Algorithm developers need to decide whether to add their specific functionality to base Slicer or as a DICOM WG23. In th elatter case it would then be possible to run these (presumably VTK and iTK based) algorithms not only on Slicer but on other (potentially commercial workstations) that support DICOM WG23. (I hope this is the right group to consider this).