-
Notifications
You must be signed in to change notification settings - Fork 72
Module Conversion Steps
This step-by-step guide walks you through conversion of a module from SCIRun 4 to SCIRun 5. At this time, it only covers modules without a UI screen. Before you begin, make sure you are on your own git branch and NOT on master; master commits are for project admins only.
- Copy the module's C++ source file into the correct path. Look under
src/Modules/Legacy
to see if it is already there.
- Example:
src/Modules/Legacy/Fields/AlignMeshBoundingBoxes.cc
is already checked in, so nothing to do.
- Make a copy of the file
SCIRunGUIPrototype/src/Modules/Legacy/Fields/CalculateGradients.h
(TODO: general header template) and rename it using the same name as the module. It will act as a template for the newly-required module header file.
- Example: Copied
CalculateGradients.h
toAlignMeshBoundingBoxes.h
.
- Edit the corresponding
CMakeLists.txt
file to both (a) enable/add the module .cc file, and (b) add the newly-created module header file.
- Example:
src/Modules/Legacy/Fields/CMakeLists.txt
was edited to addAlignMeshBoundingBoxes.h
to theDataflow_Modules_Legacy_Fields_HEADERS
list; and, the line containingAlignMeshBoundingBoxes.cc
was uncommented to add both files to the project.
- Under
src/Modules/X/Tests
, where X is the general category of your module, add a unit test source file both to the filesystem and to the correspondingCMakeLists.txt
file.
- Example: Unit tests for the Legacy modules are separated from the Legacy directories to aid file diffing. Thus, a file
AlignMeshBoundingBoxesTests.cc
was added tosrc/Modules/Fields/Tests
, and then added to the project using CMake.GetFieldBoundaryTests.cc
was copied to create the new file; it will be edited in a later step.
- At this point, the CMake project structure should be valid (although the projects won't build), and your git changeset should look like this:
-
CHECKPOINT: If there is no corresponding Algorithm class for your module, there is a limit on the size of its
execute()
method of 5 lines. Otherwise, a separate Algorithm class is required to be extracted from the Module's implementation. - With the Algorithm implementation separate, proceed to the Algorithm class's directory.
- Example:
AlignMeshBoundingBoxes
usesAlignMeshBoundingBoxes.h/.cc
undersrc/Core/Algorithms/Legacy/Fields/TransformMesh
, the files are already there.
- Enable/add the algorithm source files to the correct CMake project.
- Example:
src/Core/Algorithms/Legacy/Fields/CMakeLists.txt
is edited to enableTransformMesh/AlignMeshBoundingBoxes.cc
and addTransformMesh/AlignMeshBoundingBoxes.h
(Most algorithm header files are not part of the CMakeLists file already and need to be added).
- Repeat step 4 for the Algorithm code. Everything needs test code.
- Example: The new algorithm tests will go under
src/Core/Algorithms/Field/Tests
. An existing test file is copied into the new fileAlignMeshBoundingBoxesAlgoTests.cc
, and it is added to the CMake file.
- Your CMake config should be valid, and it is time to make a commit. It's good to separate the file additions and CMake changes from actual code changes in the history.
- Example:
- Regenerate your project files and start a build. Most likely the algorithm class will fail to compile. The steps to get it compiling generally break down like this:
- Fix/delete unneeded include paths.
- Example:
- Update namespaces.
- Example:
- Update the base class for the Algorithm type.
- Example:
- Move all implementation to the .cc file.
- Example:
- The Algorithm parameter interfaces are centralized under one set of methods,
addParameter/get/set
. They don't take raw strings anymore, but need an object defined as a key for each parameter. Use a static member variable for each parameter name.
- Examples:
- The algo_start/end interface is removed, instead use
ScopedAlgorithmStatusReporter
.
- Example:
- Interface changes due switch from
LockingHandle
toboost::shared_ptr
- Example:
- Certain functions are not available yet, for now macro out their calls (TODO: this step needs to go away soon).
- Example:
-
asVector()
calls need to be removed.
- Example:
- The interface for deep-copying a field/mesh has changed.
- Example:
- There is a chance that you encounter a compiler error related to another interface change or utility library code that is not enabled yet. In this case, contact @dcwhite and he will work with you on your branch to enable the code you need.
- Open the algorithm unit test source file created in step A-9. Create a dummy test similar to the following example:
- Example:
- Make sure proper includes are made. It should fail to compile, with error "cannot instantiate abstract class". This is due to the new generic algorithm interface created to simplify module testing. Writing this new method is straightforward, and may even be automated in the future.
- First, declare the generic algorithm method in the header file.
- Example.
- Next, create the shell of the implementation in the source file.
- Example:
- Decide what you want to name the input/output values of the algorithm. They will need Name objects to enable provenance.
- Example:
- Define the name objects, using the same string as the identifier. Don't just use "Input" and "Output", this is a chance to self-document your algorithm.
- Example:
- Fix const-correctness of the run() method, and include
AlgorithmPreconditions.h
.
- Example:
- The algorithm test should compile now. Here is where you can test your algorithm code without having to instantiate a network, module, the UI, or anything else. If you have some easy base cases to test, or want to bring in some (small) data files to test with, the unit testing framework can handle all of that easily. We simply won't accept untested code into SCIRun 5, so the extra effort here is necessary. Talk to the dev team for assistance.
-
The module header file is a new concept. SCIRun 4's modules are not "includable" since the class declarations are in the source file lumped in with the implementation. The new version is taking advantage of some declarative techniques to do away with the module XML port definition file and keep port names synchronized. Thus there is a standard template for module headers:
class SCISHARE ModuleClassName : public Dataflow::Networks::Module,
public InputPortSpec,
public OutputPortSpec
{
public:
ModuleClassName();
virtual void execute();
INPUT_PORT_DESCs
OUTPUT_PORT_DESCs
};