-
Notifications
You must be signed in to change notification settings - Fork 125
Guidelines for Developing a New TTK Module [experimental branch paraview5.7]
Thanks for creating a new module for TTK!
Please take a few minutes to review our guidelines below, which will hopefully ease your work.
This version is for the experimental branch of TTK. If you are on a release or the master branch, please refer to these guidelines.
As documented in TTK's companion paper, each TTK module is organized in 3 layers:
- Base layer
core/base/
: This directory contains the implementations of the core algorithms. - VTK layer
core/vtk
: This directory provides wrappers for the VTK API as well as XML specifications for the ParaView plug-ins. - ParaView layer
paraview/
: This directory contains the CMake files to declare the ParaView plug-ins.
Assuming a module named HelloWorld, it is composed of the following directories:
-
core/base/helloWorld
: heart of the algorithm, VTK free -
core/vtk/ttkHelloWorld
: wrapper VTK, XML files -
paraview/HelloWorld
: register the ParaView filter -
standalone/HelloWorld
: GUI and CLI programs
The content of these directories is detailed in the following. A set of scripts made to create, clone and delete modules is presented in section 1.5
The first directory (core/base/helloWorld
) is where you can implement
the heart of your algorithm. It contains:
-
core/base/helloWorld/
-
HelloWorld.h
: header file -
HelloWorld.cpp
: source file -
CMakeLists.txt
: declare sources, headers and base code dependencies
-
If you create new header or source files for your algorithm, you need to
update the CMakeLists.txt
. Usually, you start by setting up the I/O for your
algorithm (see 1.2) before implementing the base code.
The VTK wrappers directory (core/vtk
) contains files to set up the I/O of
your filger and build the VTK wrapper and the ParaView plugin:
-
core/vtk/ttkHelloWorld/
-
ttkHelloWorld.h
: header file -
ttkHelloWorld.cpp
: source file -
HelloWorld.xml
: GUI of the ParaView filter -
vtk.module
: declare the VTK dependencies (VTK modules to build) -
ttk.module
: declare the TTK dependencies (sources, header and XML files, base code targets) -
TTKWrapper.cmake
: register the module in the ParaView plugin -
CMakeLists.txt
: register the VTK module (may be called during the ParaView plugin build)
-
If you create new header or source files for the wrapper, you need to update the ttk.module. The vtk.module file only needs to be updated if your wrapper requires specific VTK features.
Most of the time, you only need to update the header, source and XML files here.
The ParaView directory (paraview
) contains files to register the
TTK modules in the ParaView plugin:
-
paraview/HelloWorld/
-
TTKFilter.cmake
: register the ParaView filter
-
You can ignore this folder.
The last directory (standalone/HelloWorld
) contains the hierarchy to build 2
standalone programs using your new module (one in command line, the other one
with a basic VTK-based GUI):
-
standalone/HelloWorld/
-
cmd/
-
main.cpp
: source file -
CMakeLists.txt
: declare source file and base code dependencies
-
-
gui/
-
main.cpp
: source file -
CMakeLists.txt
: declare source file and base code dependencies
-
-
If you do not wish to provide/maintain these standalone
programs, simply remove the directory standalone/HelloWorld
.
We provide a set of scripts which will help you create automatically all the necessary files for a module.
To create a blank new module, enter the following command from the top of TTK's source tree:
$ scripts/createTTKmodule.sh <Name, first letter in uppercase, no space. for example: HelloWorld>
If you build and install TTK, your new module should be readily available and executable in ParaView.
If you wish to delete a module (for instance the above HelloWorld example), enter the following command:
$ scripts/deleteTTKmodule.sh HelloWorld
You can also create a new module by cloning an already-existing module (which is particularly useful to copy a specific configuration of the VTK layer, in terms of inputs and outputs):
$ scripts/cloneTTKmodule.sh <SourceTTKmodule> <DestinationTTKmodule>
If you created your module with the createTTKmodule.sh script, you can
start to adjust the module to your needs by typically updating the input and
output specification at the VTK/ParaView layers (in the core/vtk
folder).
For this, follow the TODO comments, in increasing order, from the file
core/vtk/ttkHelloWorld/ttkHelloWorld.h
. Note that modifications made to the
VTK layer will probably have to be reported to the ParaView and standalone
components.
Once you have adjusted the inputs and outputs of your TTK module, you can
proceed with the implementation of the core algorithm in the base layer. For
this, follow the TODO comments, in increasing order, from the file
core/base/helloWorld/HelloWorld.h
. Note that this file contains many other
comments providing useful recommendations (in particular regarding
interactions with TTK's internal triangulation data structure).
Note that by default, new modules will use TTK's internal triangulation data structure for efficient mesh traversals. Please review this class documentation before using it, as it uses an original pre-conditioning mechanism.
Now, before diving in the implementation of your module, we invite you to read
carefully the following documentation, explaining the content of each file
initially created by the createTTKmodule.sh
script.
-
Base layer:
- The base TTK classes (implementing the core of your module) should be implemented as templatized functors (as initially declared with the above scripts). This means that your base class should not store data. It should only be passed a pointer to an input buffer to read, and a pointer to an output buffer to fill. It is recommend to templatize the core functions of your class to be generic to the type of data considered on the input and the output (float, double, char, etc., as initially declared with the above scripts).
- By default (as initially declared with the above scripts), each TTK base
class inherits from the
ttk::Debug
class, which holds some information about:- the current debug level (
debugLevel_
, setup by the calling program with the functionsetDebugLevel()
) - the current thread number (
threadNumber_
, setup by the calling program with the functionsetThreadNumber()
, default value: number of cores on the system). - a pointer to the calling wrapper (used by the VTK layer)
- the current debug level (
- To print some messages on the standard outputs, please do not use
std::cout or std::cerr. Please use the
dMsg()
function of your TTK class instead (see the doxygen documentation of thettk::Debug
class) - TTK provides a number of general-purpose classes that may make your life
easier in the development of the base classes of your module:
- To measure time in your code, please use the
ttk::Timer
class. - To perform some geometrical computation (dot products, cross products,
barycentric coordinates, etc), please checkout the doxygen
documentation of the
ttk::Geometry
class. It is likely that what you need is already implemented there. If it is not, this class is the right place to implement new, low-level, geometry related functions. - The
ttk::CommandLineParser
class provides a full featured command line parser (used by the standalone components of your module). - Several other classes from the base layer can be useful for the
development of your own module (see for instance:
ttk::Dijkstra
class,ttk::DimensionReduction
class,ttk::Laplacian
class,ttk::UnionFind
class). Please have a quick look at the list of available classes before implementing a new algorithm your module may need. Note that if your module needs a specific functionality, it may be useful to implement it as a separate base layer class (for instance thettk::HarmonicField
class uses thettk::Laplacian
class, which uses itself thettk::Geometry
class). - If you use an already-existing base layer class B in the base class A
of your own module, please update A's
CMakeLists.txt
file accordingly to make sure that it links against B (see for instancecore/base/scalarFieldCriticalPoints/CMakeLists.txt
, where the classttk::ScalarFieldCriticalPoints
links against thettk::UnionFind
class in addition to the defaultttk::Triangulation
one).
- To measure time in your code, please use the
- We recommend to use OpenMP as soon as possible. Please wrap any OpenMP
call around
#ifdef TTK_ENABLE_OPENMP
and#endif
statements. - At the beginning of each function, wrap the check of the validity of its
parameters around
#ifdef TTK_ENABLE_KAMIKAZE
and#endif
statements (seecore/base/blank/Blank.h
for an example). When built in KAMIKAZE mode, TTK will skip these sanity checks for faster performances. - Function prototypes in the base layer are based on the following
conventions:
- Functions return an error code (0 if success).
- Inputs are passed as function arguments with const references (const pointers if not possible otherwise).
- Outputs are passed as function arguments with references (pointers if not possible otherwise).
-
Third-party dependencies:
- Third-party dependencies should be handled at the base layer.
- If a third-party dependency is not found, your module should still build and run. At run time, an error message can be reported about the missing dependency.
- To add a third-party dependency in your code, follow the example of the
inclusion of ZLIB:
- Add the necessary
find_package
instructions incore/CMakeLists.txt
and position a CMake optionTTK_ENABLE_\<NAME OF YOUR DEPENDENCY\>
with a description - Add a status message regarding the presence of your third-party
library in
functions.cmake
- Add the necessary compile instructions in
core/functions.cmake
- Add the necessary compile instructions in
core/base/functions.cmake
- Add the necessary dependency handling instructions in
core/base/TTKBaseConfig.cmake.in
- In your base class, protect the usage of the calls to the third-party
library (with
TTK_ENABLE_\<NAME OF YOUR DEPENDENCY\>
) and return an error message if it has not been installed. See the filescore/base/topologicalCompression/TopologicalCompression.h
andcore/base/topologicalCompression/TopologicalCompression.cpp
for an example (applied to ZLIB, seeTTK_ENABLE_ZLIB
).
- Add the necessary
-
TODO VTK layer:
- pointer to VTK documentation
- by default shallowcopy, deepcopy only for data which needs to be modified (smoother version of an input field)
GetVoidPointer
SetVoidPointer
-
TODO ParaView layer: make sure to assign your module to the right category.
-
TODO General recommendations:
- Never use
new
(or related functions, such as VTK's::New()
).
- Never use
- TTK uses Doxygen to generate online documentations.
- Please provide a general documentation for each class you write.
- Within each class, please provide a documentation for each function. See the
ttk::Triangulation
class for an example.
- To track down original authorship directly from the source, please add your name and email address (with the
\author
Doxygen command) at the beginning of your header files (see for instancecore/base/blank/Blank.h
) - If your work implements a specific research paper, please mention that:
- in your header files, with a Doxygen paragraph called "Related publication". See
core/base/topologicalSimplification/TopologicalSimplification.h
for an example. - in the online help of the ParaView layer of your module. See
paraview/TopologicalSimplification/TopologicalSimplification.xml
for an example.
- in your header files, with a Doxygen paragraph called "Related publication". See