-
Notifications
You must be signed in to change notification settings - Fork 124
Guidelines for Developing a New TTK Module
Thanks for creating a new module for TTK!
Please take a few minutes to review our guidelines below, which will hopefully ease your work.
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. - ParaView layer
paraview/
: This directory provides XML specifications for ParaView plug-ins. We provide a set of scripts which will help you create automatically all the necessary files. 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>
Assuming your module name is HelloWorld
, the above command will create the following directories:
core/base/helloWorld
core/vtk/ttkHelloWorld
paraview/HelloWorld
standalone/HelloWorld
The last directory (standalone/HelloWorld
) contains 2 standalone programs using your new module (one in command line, the other one with a basic VTK-based GUI). If you do not wish to provide/maintain these standalone programs, simply remove the directory standalone/HelloWorld
.
At this point, 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
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. 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 recommendations.
-
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()
). - Use performance profilers (perf+hotspot, 1 thread, with CMAKE_CXX_FLAGS="--ggdb -fno-omit-frame-pointer") and memory leak trackers (heaptrack)
-
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