diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..af96791fc63ed27af167ba8856d2a0088506d0cc
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+.vscode
+build
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a1ea9f56542c851155ec9eb1199fd9a1ce1d89c2..31220fe87030cc1f0658c3b2fa2e13ab736c0fcd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -40,7 +40,7 @@ set( MODULE_NAME ${SHORT_NAME}module )
 # 2) Add all your sources here
 set( MODULE_SOURCES
     streamingmodule.h streamingmodule.cpp
-    recording_backend_nesci_contra.h recording_backend_nesci_contra.cpp
+    streaming_recording_backend.h streaming_recording_backend.cpp
     )
 
 # 3) We require a header name like this:
@@ -179,6 +179,17 @@ execute_process(
     OUTPUT_STRIP_TRAILING_WHITESPACE
 )
 
+#--------------------------------------------------------------------
+set(CMAKE_CXX_STANDARD 14)
+
+if (NOT CONTRA_TRANSPORT)
+  set(CONTRA_TRANSPORT shared_memory)
+endif()
+
+find_package(contra COMPONENTS contra ${CONTRA_TRANSPORT} REQUIRED)
+find_package(nesci COMPONENTS producer REQUIRED)
+#--------------------------------------------------------------------
+
 # on OS X
 set( CMAKE_MACOSX_RPATH ON )
 
@@ -231,14 +242,13 @@ add_custom_target( dist
     COMMENT "Creating a source distribution from ${MODULE_NAME}..."
     )
 
-include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
-conan_basic_setup( TARGETS )
+add_subdirectory(demos)
 
 if ( BUILD_SHARED_LIBS )
   # When building shared libraries, also create a module for loading at runtime
   # with the `Install` command.
   add_library( ${MODULE_NAME}_module MODULE ${MODULE_SOURCES} )
-  target_link_libraries( ${MODULE_NAME}_module CONAN_PKG::nesci CONAN_PKG::contra )
+  target_link_libraries( ${MODULE_NAME}_module nesci::producer contra::${CONTRA_TRANSPORT} )
   set_target_properties( ${MODULE_NAME}_module
       PROPERTIES
       COMPILE_FLAGS "${NEST_CXXFLAGS} -DLTX_MODULE"
@@ -252,7 +262,7 @@ endif ()
 
 # Build dynamic/static library for standard linking from NEST.
 add_library( ${MODULE_NAME}_lib ${MODULE_SOURCES} )
-target_link_libraries( ${MODULE_NAME}_lib CONAN_PKG::nesci CONAN_PKG::contra )
+target_link_libraries( ${MODULE_NAME}_lib nesci::producer contra::${CONTRA_TRANSPORT} )
 if ( BUILD_SHARED_LIBS )
   # Dynamic libraries are initiated by a `global` variable of the `SLIModule`,
   # which is included, when the flag `LINKED_MODULE` is set.
@@ -296,7 +306,6 @@ if ( NOT CMAKE_CROSSCOMPILING )
     )
 endif ()
 
-
 message( "" )
 message( "-------------------------------------------------------" )
 message( "${MODULE_NAME} Configuration Summary" )
diff --git a/CPPLINT.cfg b/CPPLINT.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..ce7c7e4c264e5a39da61062cc86686e28865fee8
--- /dev/null
+++ b/CPPLINT.cfg
@@ -0,0 +1,4 @@
+set noparent
+filter=-readability/check,-build/c++tr1,-build/c++11,-build/c++14
+linelength=80
+headers=h,hpp
diff --git a/README.md b/README.md
index 84571b76334196e2989fe88346b6f463b5ff2476..959031604698864c49194136ac7276d464606bde 100644
--- a/README.md
+++ b/README.md
@@ -3,15 +3,15 @@
 ## Prerequisites
 * CMake >= 3.6.0 (https://cmake.org/)
 * Python 2.7 (https://www.python.org/)
-* Conan (`pip install conan`)
-* NEST: the latest release of NEST does currently not support modules. Thus, a custom version is required that can be found [here](https://github.com/jougs/nest-simulator/tree/feature/custom-recording-backend). 
+* NEST: the latest release of NEST does currently not support modules. Thus, a custom version is required that can be found [here](https://github.com/jougs/nest-simulator/tree/feature/custom-recording-backend). You need to checkout and build the branch `feature/custom-recording-backend`
 
 ## Building
 1. Create a build directory
 2. Open terminal in build directory
 3. Run CMake: `cmake -Dwith-nest=${PATH_TO_NEST_INSTALLATION} ${PATH_TO_NEST_STREAMING_MODULE_SOURCE}`
-4. Build: `cmake --build .`
-5. Install: `cmake --build . --target install`
+4. Run Conan: `conan install ${PATH_TO_NEST_STREAMING_MODULE_SOURCE} --build=missing`
+5. Build: `cmake --build .`
+6. Install: `cmake --build . --target install`
 
 ## How to use the nest-streaming-module?
 The *nest-streaming-module* registers a new RecordingBackend to the simulator. When registering a `RecordingDevice` using PyNEST the used recording backend can be specified in the `record_to` parameter. If you want to stream the data, set this parameter to `['streaming']`. Clients that receive the data can be either written in Python or C++. See https://devhub.vr.rwth-aachen.de/VR-Group/nesci-contra-demos for examples.
\ No newline at end of file
diff --git a/conanfile.py b/conanfile.py
deleted file mode 100644
index 89c81b32798f259395ba22372cca213e4b43691e..0000000000000000000000000000000000000000
--- a/conanfile.py
+++ /dev/null
@@ -1,37 +0,0 @@
-# conanfile.py
-#
-# This file is part of NEST.
-#
-# Copyright (C) 2004 The NEST Initiative
-#
-# NEST is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 2 of the License, or
-# (at your option) any later version.
-#
-# NEST is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with NEST.  If not, see <http://www.gnu.org/licenses/>
-
-from conans import ConanFile, CMake
-
-class nest(ConanFile):
-    name = "NEST"
-    version = "18.05"
-    license = "GNU General Public License, Version 2"
-    description = """NEST is a simulator for spiking neural network models that focuses on the dynamics, size and structure of neural systems rather than on the exact morphology of individual neurons."""
-    settings = "os", "compiler", "build_type", "arch"
-
-    requires = (("contra/18.05@RWTH-VR/develop"),
-                ("nesci/18.05@RWTH-VR/develop"))
-    generators = "cmake"
-
-    def configure(self):
-        pass
-
-    def imports(self):
-        pass
diff --git a/demos/CMakeLists.txt b/demos/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..406fe9e6e986f14f50b815e53eacb80d1dafea05
--- /dev/null
+++ b/demos/CMakeLists.txt
@@ -0,0 +1,33 @@
+#-------------------------------------------------------------------------------
+# nest-streaming-module
+#
+# Copyright (c) 2018 RWTH Aachen University, Germany,
+# Virtual Reality & Immersive Visualization Group.
+#-------------------------------------------------------------------------------
+#                                  License
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#-------------------------------------------------------------------------------
+
+option(BUILD_BRUNEL_SIMULATION "Build the brunel simulation" ON)
+option(BUILD_QVTK_DEMO "Build the QVTK visualization demo" OFF)
+
+if (${BUILD_BRUNEL_SIMULATION})
+    add_subdirectory(brunel_simulation)
+endif (${BUILD_BRUNEL_SIMULATION})
+
+if (${BUILD_QVTK_DEMO})
+    add_subdirectory(QVTK-Demo)
+endif (${BUILD_QVTK_DEMO})
+
+
diff --git a/demos/QVTK-Demo/CMakeLists.txt b/demos/QVTK-Demo/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..492be448f7d430f12d10ca085c0e18ce7c72454e
--- /dev/null
+++ b/demos/QVTK-Demo/CMakeLists.txt
@@ -0,0 +1,24 @@
+#-------------------------------------------------------------------------------
+# QVTK-Demo
+#
+# Copyright (c) 2017-2018 RWTH Aachen University, Germany,
+# Virtual Reality & Immersive Visualization Group.
+#-------------------------------------------------------------------------------
+#                                  License
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#-------------------------------------------------------------------------------
+
+add_subdirectory(qvtk-app)
+add_subdirectory(qvtk-lib)
+
diff --git a/demos/QVTK-Demo/Readme.txt b/demos/QVTK-Demo/Readme.txt
new file mode 100644
index 0000000000000000000000000000000000000000..8602ac1f9b151f31187404906c1cbde5b65e521d
--- /dev/null
+++ b/demos/QVTK-Demo/Readme.txt
@@ -0,0 +1,36 @@
+#-------------------------------------------------------------------------------
+# QVTK-Demo
+#
+# Copyright (c) 2017-2018 RWTH Aachen University, Germany,
+# Virtual Reality & Immersive Visualization Group.
+#-------------------------------------------------------------------------------
+#                                  License
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#-------------------------------------------------------------------------------
+
+This is a brief summary on how to get the QVTK-Demo running.
+
+Prerequisites:
+	-QT (Version 5.9 or higher is advised! -older versions might work aswell but havent been tested).
+		-Get this first and build it.
+	-The Visualization Toolkit(VTK) (The demo was originally build with version 8.0.1. Newer versions should work too but havent been tested).
+		-Ŵhen building VTK with CMake make sure you enable VTK_BUILD_QT_DESIGNER_PLUGIN, VTK_Group_Qt and set VTK_QT_VERSION to 5.
+
+Installing:
+When running CMake enable BUILD_QVTK_DEMO and BUILD_BRUNEL_SIMULATION.
+
+Running the Demo:
+To run the Demo start both, the QVTK-Demo(qvtk-app) and the Brunel Simulation(run_sim.sh) from your build folder.
+
+ 
diff --git a/demos/QVTK-Demo/qvtk-app/CMakeLists.txt b/demos/QVTK-Demo/qvtk-app/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..aa8b8c96f551b878ec5dfbbb749c9b7d9e5c0009
--- /dev/null
+++ b/demos/QVTK-Demo/qvtk-app/CMakeLists.txt
@@ -0,0 +1,71 @@
+#-------------------------------------------------------------------------------
+# QVTK-Demo
+#
+# Copyright (c) 2017-2018 RWTH Aachen University, Germany,
+# Virtual Reality & Immersive Visualisation Group.
+#-------------------------------------------------------------------------------
+#                                 License
+#
+# This framework is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# In the future, we may decide to add a commercial license
+# at our own discretion without further notice.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesse  r General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#-------------------------------------------------------------------------------
+
+set(CMAKE_AUTOMOC ON)
+set(QVTK_APP_API_HEADER_DIR include/qvtk_app)
+
+file(GLOB QVTK_APP_SOURCES src/*.cpp)
+file(GLOB QVTK_APP_HEADERS include/qvtk_app/*.hpp)
+file(GLOB QVTK_APP_API_HEADERS ${QVTK_APP_API_HEADER_DIR}/*.hpp)
+file(GLOB QVTK_APP_SUPPRESS_WARNING_HEADERS include/qvtk_app/suppress_warnings/Qt *.hpp)
+
+add_executable(qvtk_app
+  ${QVTK_APP_SOURCES}
+  ${QVTK_APP_HEADERS}
+  ${QVTK_APP_API_HEADERS}
+  ${QVTK_APP_SUPPRESS_WARNING_HEADERS}
+)
+
+target_include_directories(
+  qvtk_app PUBLIC
+  ${CMAKE_CURRENT_SOURCE_DIR}/include
+  ${CMAKE_BINARY_DIR}
+)
+
+#add_test_cpplint(NAME "qvtk_app--cpplint"
+#  ${QVTK_APP_SOURCES}
+#  ${QVTK_APP_HEADERS}
+#  ${QVTK_APP_API_HEADERS}
+#  ${QVTK_APP_SUPPRESS_WARNING_HEADERS}
+#)
+
+set_warning_levels_RWTH(qvtk_app
+  SUPPRESS_WARNINGS_HEADER ${CMAKE_CURRENT_BINARY_DIR}/include/qt_app/suppress_warnings.hpp
+)
+
+include_directories(include)
+
+# --- dependencies ---
+
+#  VTK
+find_package(VTK REQUIRED)
+include(${VTK_USE_FILE})
+target_include_directories(qvtk_app PUBLIC ${VTK_INCLUDE_DIR})
+
+#vtkexperiment
+target_include_directories(qvtk_app PUBLIC ${QVTK_LIB_INCLUDE_DIRS})
+
+target_link_libraries(qvtk_app PUBLIC qvtk-lib debug ${VTK_LIBRARIES} optimized ${VTK_LIBRARIES})
+
diff --git a/demos/QVTK-Demo/qvtk-app/include/qvtk_app/application.hpp b/demos/QVTK-Demo/qvtk-app/include/qvtk_app/application.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..b2beda8abf3487f26919ba90f914135075bb5e5c
--- /dev/null
+++ b/demos/QVTK-Demo/qvtk-app/include/qvtk_app/application.hpp
@@ -0,0 +1,49 @@
+//------------------------------------------------------------------------------
+// QVTK-Demo
+//
+// Copyright (c) 2017-2018 RWTH Aachen University, Germany,
+// Virtual Reality & Immersive Visualisation Group.
+//------------------------------------------------------------------------------
+//                                 License
+//
+// This framework is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// In the future, we may decide to add a commercial license
+// at our own discretion without further notice.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//------------------------------------------------------------------------------
+
+#ifndef QVTK_APP_INCLUDE_QVTK_APP_APPLICATION_HPP_
+#define QVTK_APP_INCLUDE_QVTK_APP_APPLICATION_HPP_
+
+#include "QApplication"
+
+#include "qvtk-lib/main_window.hpp"
+#include "qvtk-lib/point_data.hpp"
+
+class Application
+{
+public:
+  Application(int *argc, char **argv);
+  ~Application() {}
+
+  int Run();
+
+private:
+  QApplication qt_app_;
+
+  vtkexp::PointData points_;
+  vtkexp::MainWindow window_;
+};
+
+#endif // QVTK_APP_INCLUDE_QVTK_APP_APPLICATION_HPP_
diff --git a/demos/QVTK-Demo/qvtk-app/src/application.cpp b/demos/QVTK-Demo/qvtk-app/src/application.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3b5fd95dab12a074e3b1eb5875cb22666947bb9c
--- /dev/null
+++ b/demos/QVTK-Demo/qvtk-app/src/application.cpp
@@ -0,0 +1,35 @@
+//------------------------------------------------------------------------------
+// QVTK-Demo
+//
+// Copyright (c) 2017-2018 RWTH Aachen University, Germany,
+// Virtual Reality & Immersive Visualisation Group.
+//------------------------------------------------------------------------------
+//                                 License
+//
+// This framework is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// In the future, we may decide to add a commercial license
+// at our own discretion without further notice.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//------------------------------------------------------------------------------
+
+#include "qvtk_app/application.hpp"
+
+Application::Application(int *argc, char **argv)
+    : qt_app_{*argc, argv}, points_(6, 6, 1), window_{&points_} {}
+
+int Application::Run()
+{
+  window_.show();
+  return qt_app_.exec();
+}
diff --git a/demos/QVTK-Demo/qvtk-app/src/main.cpp b/demos/QVTK-Demo/qvtk-app/src/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..1fc8d5018dc15715da06ac22aace0dd6ab7a78b6
--- /dev/null
+++ b/demos/QVTK-Demo/qvtk-app/src/main.cpp
@@ -0,0 +1,32 @@
+//------------------------------------------------------------------------------
+// QVTK-Demo
+//
+// Copyright (c) 2017-2018 RWTH Aachen University, Germany,
+// Virtual Reality & Immersive Visualisation Group.
+//------------------------------------------------------------------------------
+//                                 License
+//
+// This framework is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// In the future, we may decide to add a commercial license
+// at our own discretion without further notice.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//------------------------------------------------------------------------------
+
+#include "qvtk_app/application.hpp"
+
+int main(int argc, char **argv)
+{
+  Application app(&argc, argv);
+  return app.Run();
+}
diff --git a/demos/QVTK-Demo/qvtk-lib/CMakeLists.txt b/demos/QVTK-Demo/qvtk-lib/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..32ce237d4fbb58314fee48eb5541bf8bc4f9ba4a
--- /dev/null
+++ b/demos/QVTK-Demo/qvtk-lib/CMakeLists.txt
@@ -0,0 +1,83 @@
+#-------------------------------------------------------------------------------
+# QVTK-Demo
+#
+# Copyright (c) 2017-2018 RWTH Aachen University, Germany,
+# Virtual Reality & Immersive Visualisation Group.
+#-------------------------------------------------------------------------------
+#                                 License
+#
+# This framework is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# In the future, we may decide to add a commercial license
+# at our own discretion without further notice.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesse  r General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#-------------------------------------------------------------------------------
+
+set(CMAKE_AUTOMOC ON)
+set(QVTK_LIB_API_HEADER_DIR include/qvtk-lib)
+
+file(GLOB QVTK_LIB_SOURCES src/*.cpp)
+file(GLOB QVTK_LIB_HEADERS include/qvtk-lib/*.hpp)
+file(GLOB QVTK_LIB_API_HEADERS ${QVTK_LIB_API_HEADER_DIR}/*.hpp)
+
+set(QVTK_LIB_INCLUDE_DIRS 
+  ${CMAKE_CURRENT_SOURCE_DIR}/include
+  ${PROJECT_SOURCE_DIR}qvtk-lib/include
+  ${PROJECT_BINARY_DIR}
+  CACHE PATH "Path to public headers in vtk's source tree."
+)
+
+add_library(qvtk-lib
+  ${QVTK_LIB_SOURCES}
+  ${QVTK_LIB_HEADERS}
+)
+
+target_include_directories(qvtk-lib
+  PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}
+  PUBLIC ${CMAKE_CURRENT_BINARY_DIR}
+)
+
+generate_export_header(qvtk-lib
+  EXPORT_FILE_NAME ${CMAKE_CURRENT_BINARY_DIR}/include/qvtk-lib/export.hpp
+)
+
+set_warning_levels_RWTH(qvtk-lib
+  SUPPRESS_WARNINGS_HEADER ${CMAKE_CURRENT_BINARY_DIR}/include/qvtk-lib/suppress_warnings.hpp
+)
+
+#add_test_cpplint(NAME "vtkexperiment--cpplint"
+#  ${VTKEXPERIMENT_SOURCES}
+#  ${VTKEXPERIMENT_HEADERS}
+#)
+
+include_directories(include)
+
+# --- dependencies ---
+#  VTK
+find_package(VTK REQUIRED)
+include(${VTK_USE_FILE})
+target_include_directories(qvtk-lib PUBLIC ${VTK_INCLUDE_DIR})
+
+target_include_directories(qvtk-lib PUBLIC
+  ${CONAN_INCLUDE_DIRS}
+)
+
+target_link_libraries(qvtk-lib
+  PUBLIC ${CONAN_OR_CMAKE_contra}
+  PUBLIC ${CONAN_OR_CMAKE_nesci}
+  PUBLIC ${CONAN_OR_CMAKE_conduit}
+  PUBLIC ${CONAN_OR_CMAKE_Qt}
+  PUBLIC ${CONAN_OR_CMAKE_VTK}
+  debug ${VTK_LIBRARIES} 
+  optimized ${VTK_LIBRARIES}
+)
diff --git a/demos/QVTK-Demo/qvtk-lib/include/qvtk-lib/animate.hpp b/demos/QVTK-Demo/qvtk-lib/include/qvtk-lib/animate.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..bdedbbb2a48fbb1af8ebc09ba19d67a7ce51dad8
--- /dev/null
+++ b/demos/QVTK-Demo/qvtk-lib/include/qvtk-lib/animate.hpp
@@ -0,0 +1,76 @@
+//------------------------------------------------------------------------------
+// QVTK-Demo
+//
+// Copyright (c) 2017-2018 RWTH Aachen University, Germany,
+// Virtual Reality & Immersive Visualisation Group.
+//------------------------------------------------------------------------------
+//                                 License
+//
+// This framework is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// In the future, we may decide to add a commercial license
+// at our own discretion without further notice.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//------------------------------------------------------------------------------
+
+#ifndef QVTK_LIB_INCLUDE_QVTK_LIB_ANIMATE_HPP_
+#define QVTK_LIB_INCLUDE_QVTK_LIB_ANIMATE_HPP_
+
+#include "QObject"
+#include "QTimer"
+
+#include "include/qvtk-lib/suppress_warnings.hpp"
+SUPPRESS_WARNINGS_BEGIN
+#include "qvtk-lib/point_data.hpp"
+SUPPRESS_WARNINGS_END
+
+namespace vtkexp
+{
+
+class Animate : public QObject
+{
+  Q_OBJECT
+
+public:
+  explicit Animate(PointData *points);
+  ~Animate() {}
+
+  void StartTimer();
+
+signals:
+  void DataChanged();
+  void DataChanged(int time_step);
+  void NextStep();
+  void LastStep();
+  void SwitchRealtime();
+  void SwitchPlayPause();
+
+public slots: // NOLINT
+  void ChangeData(int timestep = -1);
+  void IncreaseSpeed();
+  void DecreaseSpeed();
+  void Iterate();
+  void RealtimeButton();
+  void PlayButton();
+  void SpeedMenu(int index);
+
+private:
+  PointData *points_;
+  QTimer *rt_timer_;
+  QTimer *play_timer_;
+  int play_speed_ = 1000;
+};
+
+} // namespace vtkexp
+
+#endif // QVTK_LIB_INCLUDE_QVTK_LIB_ANIMATE_HPP_
diff --git a/demos/QVTK-Demo/qvtk-lib/include/qvtk-lib/data_stream.hpp b/demos/QVTK-Demo/qvtk-lib/include/qvtk-lib/data_stream.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..7254ccf5045a38be1e1a0289dda4fd2773c25ec0
--- /dev/null
+++ b/demos/QVTK-Demo/qvtk-lib/include/qvtk-lib/data_stream.hpp
@@ -0,0 +1,64 @@
+//------------------------------------------------------------------------------
+// QVTK-Demo
+//
+// Copyright (c) 2017-2018 RWTH Aachen University, Germany,
+// Virtual Reality & Immersive Visualisation Group.
+//------------------------------------------------------------------------------
+//                                 License
+//
+// This framework is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// In the future, we may decide to add a commercial license
+// at our own discretion without further notice.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//------------------------------------------------------------------------------
+
+#ifndef QVTK_LIB_INCLUDE_QVTK_LIB_DATA_STREAM_HPP_
+#define QVTK_LIB_INCLUDE_QVTK_LIB_DATA_STREAM_HPP_
+
+#include <vector>
+
+#include "conduit/conduit_node.hpp"
+//#include "contra/boost-shmem/shared_memory_transport.hpp"
+#include "contra/relay.hpp"
+#include "contra/zmq/zeromq_transport.hpp"
+
+#include "nesci/consumer/nest_multimeter.hpp"
+
+namespace vtkexp
+{
+
+class DataStream
+{
+public:
+  DataStream();
+  ~DataStream() {}
+
+  std::vector<double> GetMultValuesAt(int time_step);
+  std::vector<double> GetTimeSteps();
+
+private:
+  void SetUpStream();
+  void Update(int time_step);
+
+  std::vector<double> mult_values_;
+
+  contra::Relay<contra::ZMQTransport> *relay_;
+  nesci::consumer::NestMultimeter *multimeter_;
+
+  conduit::Node node_;
+};
+
+} // namespace vtkexp
+
+#endif // QVTK_LIB_INCLUDE_QVTK_LIB_DATA_STREAM_HPP_
diff --git a/demos/QVTK-Demo/qvtk-lib/include/qvtk-lib/interaction.hpp b/demos/QVTK-Demo/qvtk-lib/include/qvtk-lib/interaction.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..cfc6b51abc9a946416fdae1aac9885ac5eef47fa
--- /dev/null
+++ b/demos/QVTK-Demo/qvtk-lib/include/qvtk-lib/interaction.hpp
@@ -0,0 +1,87 @@
+//------------------------------------------------------------------------------
+// QVTK-Demo
+//
+// Copyright (c) 2017-2018 RWTH Aachen University, Germany,
+// Virtual Reality & Immersive Visualisation Group.
+//------------------------------------------------------------------------------
+//                                 License
+//
+// This framework is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// In the future, we may decide to add a commercial license
+// at our own discretion without further notice.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//------------------------------------------------------------------------------
+
+#ifndef QVTK_LIB_INCLUDE_QVTK_LIB_INTERACTION_HPP_
+#define QVTK_LIB_INCLUDE_QVTK_LIB_INTERACTION_HPP_
+
+#include <string>
+
+#include "include/qvtk-lib/suppress_warnings.hpp"
+SUPPRESS_WARNINGS_BEGIN
+#include <vtkActor.h>
+#include <vtkDataSetMapper.h>
+#include <vtkMapper.h>
+#include <vtkPointGaussianMapper.h>
+#include <vtkPointPicker.h>
+#include <vtkUnstructuredGrid.h>
+#include "vtkInteractorStyleTrackballCamera.h"
+#include "vtkPolyData.h"
+SUPPRESS_WARNINGS_END
+
+namespace vtkexp
+{
+
+class Interaction : public vtkInteractorStyleTrackballCamera
+{
+  public:
+    static Interaction *New();
+    vtkTypeMacro(Interaction, vtkInteractorStyleTrackballCamera)
+
+        Interaction();
+
+    virtual void OnLeftButtonUp();
+
+    void SetUpShaders();
+    void SetUpActor();
+    void SetUpMapper();
+
+    double GetNeuronValue();
+    vtkIdType GetNeuronId();
+
+    void SetData(vtkSmartPointer<vtkPolyData> data);
+    void SwitchMapper(int rendertype);
+    void ExtractSelection();
+    void HighlightSelection();
+    void Deselect();
+    void Pick();
+
+  private:
+    double neuron_value_;
+    vtkIdType id_;
+    vtkSmartPointer<vtkUnstructuredGrid> selected_;
+
+    vtkSmartPointer<vtkPolyData> data_;
+
+    vtkSmartPointer<vtkActor> actor_;
+    vtkSmartPointer<vtkPointGaussianMapper> mapper_;
+    vtkSmartPointer<vtkPointPicker> picker_;
+
+    std::string point_shader_;
+    std::string sphere_shader_;
+};
+
+} // namespace vtkexp
+
+#endif // QVTK_LIB_INCLUDE_QVTK_LIB_INTERACTION_HPP_
diff --git a/demos/QVTK-Demo/qvtk-lib/include/qvtk-lib/main_widget.hpp b/demos/QVTK-Demo/qvtk-lib/include/qvtk-lib/main_widget.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..fd0ec97094735bb488f0a6ff010f87d9e7a80968
--- /dev/null
+++ b/demos/QVTK-Demo/qvtk-lib/include/qvtk-lib/main_widget.hpp
@@ -0,0 +1,71 @@
+//------------------------------------------------------------------------------
+// QVTK-Demo
+//
+// Copyright (c) 2017-2018 RWTH Aachen University, Germany,
+// Virtual Reality & Immersive Visualisation Group.
+//------------------------------------------------------------------------------
+//                                 License
+//
+// This framework is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// In the future, we may decide to add a commercial license
+// at our own discretion without further notice.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//------------------------------------------------------------------------------
+
+#ifndef QVTK_LIB_INCLUDE_QVTK_LIB_MAIN_WIDGET_HPP_
+#define QVTK_LIB_INCLUDE_QVTK_LIB_MAIN_WIDGET_HPP_
+
+#include "qvtk-lib/visualize.hpp"
+
+#include "qvtk-lib/interaction.hpp"
+
+#include "QObject"
+
+#include "include/qvtk-lib/suppress_warnings.hpp"
+SUPPRESS_WARNINGS_BEGIN
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpedantic"
+#include "QVTKOpenGLWidget.h"
+#include "vtkGenericOpenGLRenderWindow.h"
+#pragma GCC diagnostic pop
+SUPPRESS_WARNINGS_END
+
+namespace vtkexp
+{
+
+class MainWidget : public QVTKOpenGLWidget
+{
+  Q_OBJECT
+
+public:
+  explicit MainWidget(PointData *points, QVTKOpenGLWidget *parent = 0);
+  ~MainWidget() {}
+
+  void Rerender();
+
+public slots: // NOLINT
+  void ChangeRendertype(int rendertype);
+
+protected:
+  void mouseReleaseEvent(QMouseEvent *event) override;
+
+private:
+  Visualize *vispoints_;
+  vtkSmartPointer<Interaction> style_;
+  vtkSmartPointer<vtkGenericOpenGLRenderWindow> renderwindow_;
+};
+
+} // namespace vtkexp
+
+#endif // QVTK_LIB_INCLUDE_QVTK_LIB_MAIN_WIDGET_HPP_
diff --git a/demos/QVTK-Demo/qvtk-lib/include/qvtk-lib/main_window.hpp b/demos/QVTK-Demo/qvtk-lib/include/qvtk-lib/main_window.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..a9bf28246dd4a41fcfff408052b1315bd10761f2
--- /dev/null
+++ b/demos/QVTK-Demo/qvtk-lib/include/qvtk-lib/main_window.hpp
@@ -0,0 +1,99 @@
+//------------------------------------------------------------------------------
+// QVTK-Demo
+//
+// Copyright (c) 2017-2018 RWTH Aachen University, Germany,
+// Virtual Reality & Immersive Visualisation Group.
+//------------------------------------------------------------------------------
+//                                 License
+//
+// This framework is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// In the future, we may decide to add a commercial license
+// at our own discretion without further notice.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//------------------------------------------------------------------------------
+
+#ifndef QVTK_LIB_INCLUDE_QVTK_LIB_MAIN_WINDOW_HPP_
+#define QVTK_LIB_INCLUDE_QVTK_LIB_MAIN_WINDOW_HPP_
+
+#include "include/qvtk-lib/suppress_warnings.hpp"
+
+#include "qvtk-lib/animate.hpp"
+#include "qvtk-lib/main_widget.hpp"
+SUPPRESS_WARNINGS_BEGIN
+#include "qvtk-lib/point_data.hpp"
+SUPPRESS_WARNINGS_END
+
+#include "QComboBox"
+#include "QGridLayout"
+#include "QLabel"
+#include "QLineEdit"
+#include "QMainWindow"
+#include "QPushButton"
+#include "QSlider"
+#include "QTimer"
+
+namespace vtkexp
+{
+
+class MainWindow : public QMainWindow
+{
+  Q_OBJECT
+
+public:
+  explicit MainWindow(PointData *points);
+  ~MainWindow() {}
+
+  QLineEdit *slider_line_edit_;
+
+public slots: // NOLINT
+  void Rerender();
+  void Realtime();
+  void PlayPause();
+  void IncrementSlider();
+  void UpdateSlider();
+  void AdjustSlider();
+  void SliderValue();
+  void SliderValue(int time_step);
+
+private:
+  void ConnectSignals();
+  void InitSlider(QSlider *slider);
+  void SetUpButtons();
+  void SetUpContent();
+  void SetUpLayout();
+  void SetUpLineEdit();
+  void SetUpSliders();
+  void SetUpVisualization();
+  void StartAnimation();
+
+  Animate *animation_;
+  PointData *points_;
+
+  QWidget *dummywidget_;
+  MainWidget *mainwidget_;
+  QComboBox *render_type_;
+  QComboBox *speed_menu_;
+  QPushButton *rt_button_;
+  QPushButton *play_button_;
+  QGridLayout *grid_;
+  QLabel *time_label_;
+  QSlider *time_slider_;
+
+  bool realtime_{true};
+  bool play_{true};
+};
+
+} // namespace vtkexp
+
+#endif // QVTK_LIB_INCLUDE_QVTK_LIB_MAIN_WINDOW_HPP_
diff --git a/demos/QVTK-Demo/qvtk-lib/include/qvtk-lib/point_data.hpp b/demos/QVTK-Demo/qvtk-lib/include/qvtk-lib/point_data.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..934ccb63c71b959d625599c0d47165c43f71e4c8
--- /dev/null
+++ b/demos/QVTK-Demo/qvtk-lib/include/qvtk-lib/point_data.hpp
@@ -0,0 +1,73 @@
+//------------------------------------------------------------------------------
+// QVTK-Demo
+//
+// Copyright (c) 2017-2018 RWTH Aachen University, Germany,
+// Virtual Reality & Immersive Visualisation Group.
+//------------------------------------------------------------------------------
+//                                 License
+//
+// This framework is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// In the future, we may decide to add a commercial license
+// at our own discretion without further notice.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//------------------------------------------------------------------------------
+
+#ifndef QVTK_LIB_INCLUDE_QVTK_LIB_POINT_DATA_HPP_
+#define QVTK_LIB_INCLUDE_QVTK_LIB_POINT_DATA_HPP_
+
+#include <vector>
+
+#include "include/qvtk-lib/suppress_warnings.hpp"
+SUPPRESS_WARNINGS_BEGIN
+#include "qvtk-lib/data_stream.hpp"
+
+#include "vtkDataObject.h"
+#include "vtkFloatArray.h"
+#include "vtkPolyData.h"
+#include "vtkSmartPointer.h"
+SUPPRESS_WARNINGS_END
+
+namespace vtkexp
+{
+
+class PointData
+{
+public:
+  PointData(int num_x, int num_y, int num_z);
+  ~PointData() {}
+
+  void Update(int time_step = -1);
+  vtkSmartPointer<vtkPolyData> GetPolyPoints();
+  vtkSmartPointer<vtkFloatArray> GetColors() const;
+
+  int GetEndTime() const;
+  int GetStartTime() const;
+
+private:
+  void AttachColorsToPoints(const std::vector<double> &colors);
+  static vtkSmartPointer<vtkPoints> CreatePoints(int num_x, int num_y,
+                                                 int num_z);
+  void Initialize(int x, int y, int z);
+  void ColorsModified();
+
+  DataStream *stream_;
+
+  int num_points_;
+  vtkSmartPointer<vtkPolyData> points_polydata_;
+  vtkSmartPointer<vtkFloatArray> pointcolors_;
+};
+
+} // namespace vtkexp
+
+#endif // QVTK_LIB_INCLUDE_QVTK_LIB_POINT_DATA_HPP_
diff --git a/demos/QVTK-Demo/qvtk-lib/include/qvtk-lib/visualize.hpp b/demos/QVTK-Demo/qvtk-lib/include/qvtk-lib/visualize.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..9b0fc750c88a364b742638dfca86b0cfaef2a5bc
--- /dev/null
+++ b/demos/QVTK-Demo/qvtk-lib/include/qvtk-lib/visualize.hpp
@@ -0,0 +1,98 @@
+//------------------------------------------------------------------------------
+// QVTK-Demo
+//
+// Copyright (c) 2017-2018 RWTH Aachen University, Germany,
+// Virtual Reality & Immersive Visualisation Group.
+//------------------------------------------------------------------------------
+//                                 License
+//
+// This framework is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// In the future, we may decide to add a commercial license
+// at our own discretion without further notice.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//------------------------------------------------------------------------------
+
+#ifndef QVTK_LIB_INCLUDE_QVTK_LIB_VISUALIZE_HPP_
+#define QVTK_LIB_INCLUDE_QVTK_LIB_VISUALIZE_HPP_
+
+#include <string>
+
+#include "include/qvtk-lib/suppress_warnings.hpp"
+SUPPRESS_WARNINGS_BEGIN
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpedantic"
+#include "qvtk-lib/interaction.hpp"
+#include "qvtk-lib/point_data.hpp"
+
+#include "vtkActor.h"
+#include "vtkAxesActor.h"
+#include "vtkColorTransferFunction.h"
+#include "vtkGenericOpenGLRenderWindow.h"
+#include "vtkOrientationMarkerWidget.h"
+#include "vtkPointGaussianMapper.h"
+#include "vtkRenderWindowInteractor.h"
+#include "vtkRenderer.h"
+#include "vtkScalarBarActor.h"
+#include "vtkScalarBarWidget.h"
+#include "vtkSmartPointer.h"
+#pragma GCC diagnostic pop
+SUPPRESS_WARNINGS_END
+
+namespace vtkexp
+{
+
+class Visualize
+{
+public:
+  explicit Visualize(PointData *points);
+  ~Visualize() {}
+
+  void Initialize(vtkSmartPointer<vtkGenericOpenGLRenderWindow> renderwindow,
+                  vtkSmartPointer<vtkRenderWindowInteractor> interactor);
+  vtkSmartPointer<vtkRenderer> GetRenderer();
+
+  void SwitchMapper(int rendertype);
+
+private:
+  void SetUpAxes();
+  void SetUpInteractor();
+  void SetUpLegend();
+  void SetUpMapper();
+  void SetUpRenderer();
+  void SetUpScene();
+  void SetUpShaders();
+  void SetUpTransferFunction();
+
+  PointData *points_;
+
+  std::string point_shader_;
+  std::string sphere_shader_;
+
+  vtkSmartPointer<vtkActor> actor_;
+  vtkSmartPointer<vtkRenderer> renderer_;
+  vtkSmartPointer<vtkRenderWindowInteractor> interactor_;
+  vtkSmartPointer<vtkGenericOpenGLRenderWindow> renderwindow_;
+
+  vtkSmartPointer<vtkPointGaussianMapper> mapper_;
+  vtkSmartPointer<vtkColorTransferFunction> transfer_function_;
+
+  vtkSmartPointer<vtkAxesActor> axes_;
+  vtkSmartPointer<vtkOrientationMarkerWidget> axes_widget_;
+  vtkSmartPointer<vtkScalarBarWidget> scalar_bar_widget_;
+  vtkSmartPointer<vtkScalarBarActor> scalar_bar_;
+};
+
+} // namespace vtkexp
+
+#endif // QVTK_LIB_INCLUDE_QVTK_LIB_VISUALIZE_HPP_
diff --git a/demos/QVTK-Demo/qvtk-lib/src/animate.cpp b/demos/QVTK-Demo/qvtk-lib/src/animate.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..fb736464121e7be169c2964721cefc1bc50b45fa
--- /dev/null
+++ b/demos/QVTK-Demo/qvtk-lib/src/animate.cpp
@@ -0,0 +1,107 @@
+//------------------------------------------------------------------------------
+// QVTK-Demo
+//
+// Copyright (c) 2017-2018 RWTH Aachen University, Germany,
+// Virtual Reality & Immersive Visualisation Group.
+//------------------------------------------------------------------------------
+//                                 License
+//
+// This framework is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// In the future, we may decide to add a commercial license
+// at our own discretion without further notice.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//------------------------------------------------------------------------------
+
+#include "qvtk-lib/animate.hpp"
+
+namespace vtkexp
+{
+
+Animate::Animate(PointData *points) : points_(points)
+{
+  rt_timer_ = new QTimer(this);
+  play_timer_ = new QTimer(this);
+  connect(rt_timer_, SIGNAL(timeout()), this, SLOT(ChangeData()));
+  connect(play_timer_, SIGNAL(timeout()), this, SLOT(Iterate()));
+}
+
+void Animate::ChangeData(int time_step)
+{
+  points_->Update(time_step);
+  emit DataChanged();
+}
+
+void Animate::IncreaseSpeed() { play_speed_ += 1; }
+
+void Animate::DecreaseSpeed() { play_speed_ -= 1; }
+
+void Animate::Iterate()
+{
+  rt_timer_->isActive() ? emit LastStep() : emit NextStep();
+}
+
+void Animate::StartTimer()
+{
+  rt_timer_->start(1);
+  play_timer_->start(play_speed_);
+}
+
+void Animate::RealtimeButton()
+{
+  if (rt_timer_->isActive())
+  {
+    rt_timer_->stop();
+    emit SwitchRealtime();
+  }
+  else
+  {
+    rt_timer_->start(1);
+    emit SwitchRealtime();
+  }
+}
+
+void Animate::SpeedMenu(int index)
+{
+  switch (index)
+  {
+  case 0:
+    play_speed_ = 1000;
+    break;
+  case 1:
+    play_speed_ = 1000 / 5;
+    break;
+  case 2:
+    play_speed_ = 1000 / 10;
+    break;
+  case 3:
+    play_speed_ = 1000 / 50;
+    break;
+  case 4:
+    play_speed_ = 1000 / 100;
+    break;
+  default:
+    play_speed_ = 1000;
+    break;
+  }
+  play_timer_->setInterval(play_speed_);
+}
+
+void Animate::PlayButton()
+{
+  play_timer_->isActive() ? play_timer_->stop()
+                          : play_timer_->start(play_speed_);
+  emit SwitchPlayPause();
+}
+
+} // namespace vtkexp
diff --git a/demos/QVTK-Demo/qvtk-lib/src/data_stream.cpp b/demos/QVTK-Demo/qvtk-lib/src/data_stream.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..16d39ab583025c37bb8a81023f361835eb6ec853
--- /dev/null
+++ b/demos/QVTK-Demo/qvtk-lib/src/data_stream.cpp
@@ -0,0 +1,78 @@
+//------------------------------------------------------------------------------
+// QVTK-Demo
+//
+// Copyright (c) 2017-2018 RWTH Aachen University, Germany,
+// Virtual Reality & Immersive Visualisation Group.
+//------------------------------------------------------------------------------
+//                                 License
+//
+// This framework is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// In the future, we may decide to add a commercial license
+// at our own discretion without further notice.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//------------------------------------------------------------------------------
+
+#include "qvtk-lib/data_stream.hpp"
+
+#include <vector>
+
+namespace vtkexp
+{
+
+DataStream::DataStream() { SetUpStream(); }
+
+void DataStream::SetUpStream()
+{
+  relay_ = new contra::Relay<contra::ZMQTransport>(
+      contra::ZMQTransport::Type::CLIENT, "tcp://localhost:5555");
+
+  multimeter_ = new nesci::consumer::NestMultimeter("recordingNode51");
+  multimeter_->SetNode(&node_);
+}
+
+void DataStream::Update(int time_step)
+{
+  auto time_step_string = std::to_string(static_cast<double>(time_step));
+
+  const auto received_nodes = relay_->Receive();
+  for (auto node : received_nodes)
+  {
+    node_.update(node);
+  }
+
+  if (time_step == -1 && !multimeter_->GetTimesteps().empty())
+  {
+    time_step_string = multimeter_->GetTimesteps().back();
+  }
+
+  mult_values_ = multimeter_->GetTimestepData(time_step_string, "V_m");
+}
+
+std::vector<double> DataStream::GetMultValuesAt(int time_step)
+{
+  Update(time_step);
+  return mult_values_;
+}
+
+std::vector<double> DataStream::GetTimeSteps()
+{
+  std::vector<double> ret;
+  for (auto value : multimeter_->GetTimesteps())
+  {
+    ret.push_back(std::stod(value));
+  }
+  return ret;
+}
+
+} // namespace vtkexp
diff --git a/demos/QVTK-Demo/qvtk-lib/src/interaction.cpp b/demos/QVTK-Demo/qvtk-lib/src/interaction.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d6554811cb363e5cf50c4f4e98e7f648ac146c31
--- /dev/null
+++ b/demos/QVTK-Demo/qvtk-lib/src/interaction.cpp
@@ -0,0 +1,242 @@
+//------------------------------------------------------------------------------
+// QVTK-Demo
+//
+// Copyright (c) 2017-2018 RWTH Aachen University, Germany,
+// Virtual Reality & Immersive Visualisation Group.
+//------------------------------------------------------------------------------
+//                                 License
+//
+// This framework is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// In the future, we may decide to add a commercial license
+// at our own discretion without further notice.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//------------------------------------------------------------------------------
+
+#include "qvtk-lib/interaction.hpp"
+
+#include <string>
+
+SUPPRESS_WARNINGS_BEGIN
+#include "vtkExtractSelection.h"
+#include "vtkGeometryFilter.h"
+#include "vtkHardwareSelector.h"
+#include "vtkIdTypeArray.h"
+#include "vtkPointData.h"
+#include "vtkProperty.h"
+#include "vtkRenderWindow.h"
+#include "vtkRenderWindowInteractor.h"
+#include "vtkRendererCollection.h"
+#include "vtkSelection.h"
+#include "vtkSelectionNode.h"
+#include "vtkSmartPointer.h"
+#include "vtkVertexGlyphFilter.h"
+SUPPRESS_WARNINGS_END
+
+namespace vtkexp
+{
+
+vtkStandardNewMacro(Interaction)
+
+    Interaction::Interaction()
+{
+  SetUpShaders();
+  SetUpMapper();
+  SetUpActor();
+}
+
+void Interaction::SetUpMapper()
+{
+  mapper_ = vtkSmartPointer<vtkPointGaussianMapper>::New();
+  mapper_->SetSplatShaderCode(point_shader_.c_str());
+  mapper_->ScalarVisibilityOff();
+  mapper_->SetScaleFactor(0.35);
+  mapper_->UseLookupTableScalarRangeOn();
+  mapper_->EmissiveOff();
+  mapper_->Update();
+}
+
+void Interaction::SetUpActor()
+{
+  actor_ = vtkSmartPointer<vtkActor>::New();
+  actor_->SetMapper(mapper_);
+  actor_->GetProperty()->SetColor(0.0, 1.0, 0.0);
+  actor_->GetProperty()->SetEdgeVisibility(1);
+}
+
+void Interaction::OnLeftButtonUp()
+{
+  Pick();
+
+  vtkSmartPointer<vtkHardwareSelector> selector =
+      vtkSmartPointer<vtkHardwareSelector>::New();
+  selector->SetRenderer(
+      this->Interactor->GetRenderWindow()->GetRenderers()->GetFirstRenderer());
+  int *temp = this->Interactor->GetRenderWindow()->GetSize();
+  unsigned int windowSize[4];
+  windowSize[0] = temp[2];
+  windowSize[1] = temp[3];
+  windowSize[2] = temp[0];
+  windowSize[3] = temp[1];
+  /*
+  for(unsigned int i = 0; i < 4; i++)
+    {
+    windowSize[i] = temp[i];
+    }
+  */
+  selector->SetArea(windowSize);
+  selector->SetFieldAssociation(vtkDataObject::FIELD_ASSOCIATION_POINTS);
+  vtkSelection *selection = selector->Select();
+  std::cout << "Selection has " << selection->GetNumberOfNodes() << " nodes."
+            << std::endl;
+
+  vtkSmartPointer<vtkExtractSelection> extractSelection =
+      vtkSmartPointer<vtkExtractSelection>::New();
+  extractSelection->SetInputData(0, data_);
+  extractSelection->Update();
+
+  vtkSmartPointer<vtkDataSetMapper> mapper =
+      vtkSmartPointer<vtkDataSetMapper>::New();
+  mapper->SetInputConnection(extractSelection->GetOutputPort());
+
+  vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
+  actor->SetMapper(mapper);
+  actor->GetProperty()->SetColor(1, 0, 0);
+  GetDefaultRenderer()->AddActor(actor);
+
+  if (id_ != -1)
+  {
+    ExtractSelection();
+    HighlightSelection();
+  }
+  else
+  {
+    Deselect();
+  }
+  vtkInteractorStyleTrackballCamera::OnLeftButtonUp();
+}
+
+void Interaction::Pick()
+{
+  int *pos = GetInteractor()->GetEventPosition();
+
+  picker_ = vtkSmartPointer<vtkPointPicker>::New();
+  picker_->SetTolerance(0.015);
+
+  picker_->Pick(pos[0], pos[1], 0, GetDefaultRenderer());
+  id_ = picker_->GetPointId();
+  std::cout << id_ << std::endl;
+}
+
+void Interaction::ExtractSelection()
+{
+  vtkSmartPointer<vtkIdTypeArray> ids = vtkSmartPointer<vtkIdTypeArray>::New();
+  ids->SetNumberOfComponents(1);
+  ids->InsertNextValue(picker_->GetPointId());
+
+  vtkSmartPointer<vtkSelectionNode> selectionNode =
+      vtkSmartPointer<vtkSelectionNode>::New();
+  selectionNode->SetFieldType(vtkSelectionNode::POINT);
+  selectionNode->SetContentType(vtkSelectionNode::INDICES);
+  selectionNode->SetSelectionList(ids);
+
+  vtkSmartPointer<vtkSelection> selection =
+      vtkSmartPointer<vtkSelection>::New();
+  selection->AddNode(selectionNode);
+
+  vtkSmartPointer<vtkExtractSelection> extract_selection =
+      vtkSmartPointer<vtkExtractSelection>::New();
+  extract_selection->SetInputData(0, data_);
+  extract_selection->SetInputData(1, selection);
+  extract_selection->Update();
+
+  selected_ = vtkSmartPointer<vtkUnstructuredGrid>::New();
+  selected_->ShallowCopy(extract_selection->GetOutput());
+
+  neuron_value_ = selected_->GetPointData()->GetScalars()->GetComponent(0, 0);
+}
+
+void Interaction::HighlightSelection()
+{
+  vtkSmartPointer<vtkGeometryFilter> geometryFilter =
+      vtkSmartPointer<vtkGeometryFilter>::New();
+  geometryFilter->SetInputData(selected_);
+  geometryFilter->Update();
+
+  vtkSmartPointer<vtkVertexGlyphFilter> glyphFilter =
+      vtkSmartPointer<vtkVertexGlyphFilter>::New();
+  glyphFilter->SetInputData(geometryFilter->GetOutput());
+  glyphFilter->Update();
+
+  mapper_->SetInputData(glyphFilter->GetOutput());
+
+  CurrentRenderer->AddActor(actor_);
+  GetInteractor()->GetRenderWindow()->Render();
+}
+
+void Interaction::Deselect()
+{
+  vtkSmartPointer<vtkPolyData> empty = vtkSmartPointer<vtkPolyData>::New();
+
+  mapper_->SetInputData(empty);
+  mapper_->Update();
+
+  CurrentRenderer->AddActor(actor_);
+  GetInteractor()->GetRenderWindow()->Render();
+}
+
+void Interaction::SetData(vtkSmartPointer<vtkPolyData> data) { data_ = data; }
+
+void Interaction::SwitchMapper(int rendertype)
+{
+  if (rendertype == 0)
+  {
+    mapper_->SetSplatShaderCode(point_shader_.c_str());
+  }
+  else if (rendertype == 1)
+  {
+    mapper_->SetSplatShaderCode(sphere_shader_.c_str());
+  }
+}
+
+double Interaction::GetNeuronValue() { return neuron_value_; }
+
+vtkIdType Interaction::GetNeuronId() { return id_; }
+
+void Interaction::SetUpShaders()
+{
+  sphere_shader_ =
+      "//VTK::Color::Impl\n"
+      "float dist = dot(offsetVCVSOutput.xy,offsetVCVSOutput.xy);\n"
+      "if (dist > 0.9) {\n"
+      "  discard;\n"
+      "} else {\n"
+      "  float scale = (1.0 - dist);\n"
+      "  ambientColor *= 0.5;\n"
+      "  diffuseColor *= 0.7;\n"
+      "}\n";
+
+  point_shader_ =
+      "//VTK::Color::Impl\n"
+      "ambientColor *= 0.5;\n"
+      "diffuseColor *= 0.7;\n"
+      "if (abs(offsetVCVSOutput.x) > 0.3 || abs(offsetVCVSOutput.y) > 0.3) "
+      "{\n"
+      "  discard;\n"
+      "}\n"
+      "if (abs(offsetVCVSOutput.x) < 0.0 && abs(offsetVCVSOutput.y) < 0.0) "
+      "{\n"
+      "  discard;\n"
+      "}\n";
+}
+} // namespace vtkexp
diff --git a/demos/QVTK-Demo/qvtk-lib/src/main_widget.cpp b/demos/QVTK-Demo/qvtk-lib/src/main_widget.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..dcc6f6cf638bb7153e63d7cac1d99fc9f63e2c67
--- /dev/null
+++ b/demos/QVTK-Demo/qvtk-lib/src/main_widget.cpp
@@ -0,0 +1,68 @@
+//------------------------------------------------------------------------------
+// QVTK-Demo
+//
+// Copyright (c) 2017-2018 RWTH Aachen University, Germany,
+// Virtual Reality & Immersive Visualisation Group.
+//------------------------------------------------------------------------------
+//                                 License
+//
+// This framework is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// In the future, we may decide to add a commercial license
+// at our own discretion without further notice.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//------------------------------------------------------------------
+
+#include "qvtk-lib/main_widget.hpp"
+
+#include "vtkGenericOpenGLRenderWindow.h"
+
+#include "QString"
+#include "QtWidgets"
+
+namespace vtkexp
+{
+
+MainWidget::MainWidget(PointData *points, QVTKOpenGLWidget *parent)
+    : QVTKOpenGLWidget(parent)
+{
+  renderwindow_ = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();
+  this->SetRenderWindow(renderwindow_.Get());
+
+  style_ = vtkSmartPointer<Interaction>::New();
+  style_->SetData(points->GetPolyPoints());
+  this->GetInteractor()->SetInteractorStyle(style_);
+
+  vispoints_ = new Visualize(points);
+  vispoints_->Initialize(renderwindow_, this->GetInteractor());
+}
+
+void MainWidget::mouseReleaseEvent(QMouseEvent *event)
+{
+  QVTKOpenGLWidget::mouseReleaseEvent(event);
+  if (event->button() == Qt::LeftButton && style_->GetNeuronId() != -1)
+  {
+    QToolTip::showText(this->mapToGlobal(event->pos()),
+                       QString::number(style_->GetNeuronValue()));
+  }
+}
+
+void MainWidget::ChangeRendertype(int rendertype)
+{
+  vispoints_->SwitchMapper(rendertype);
+  style_->SwitchMapper(rendertype);
+}
+
+void MainWidget::Rerender() { renderwindow_->Render(); }
+
+} // namespace vtkexp
diff --git a/demos/QVTK-Demo/qvtk-lib/src/main_window.cpp b/demos/QVTK-Demo/qvtk-lib/src/main_window.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..980eb8afc59c25bff71de6222b5a2fa810fb21e2
--- /dev/null
+++ b/demos/QVTK-Demo/qvtk-lib/src/main_window.cpp
@@ -0,0 +1,208 @@
+//------------------------------------------------------------------------------
+// QVTK-Demo
+//
+// Copyright (c) 2017-2018 RWTH Aachen University, Germany,
+// Virtual Reality & Immersive Visualisation Group.
+//------------------------------------------------------------------------------
+//                                 License
+//
+// This framework is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// In the future, we may decide to add a commercial license
+// at our own discretion without further notice.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//------------------------------------------------------------------------------
+
+#include "qvtk-lib/main_window.hpp"
+
+namespace vtkexp
+{
+
+MainWindow::MainWindow(PointData *points) : points_(points)
+{
+  setWindowTitle("QVTK-Neuron-Viewer");
+  SetUpVisualization();
+  SetUpContent();
+  setCentralWidget(dummywidget_);
+  ConnectSignals();
+  StartAnimation();
+}
+
+void MainWindow::SetUpVisualization()
+{
+  animation_ = new Animate(points_);
+  mainwidget_ = new MainWidget(points_);
+}
+
+void MainWindow::SetUpContent()
+{
+  SetUpSliders();
+  SetUpLineEdit();
+  SetUpButtons();
+  SetUpLayout();
+}
+
+void MainWindow::SetUpLayout()
+{
+  dummywidget_ = new QWidget;
+  grid_ = new QGridLayout;
+  grid_->addWidget(mainwidget_, 0, 0, 1, -1);
+  grid_->addWidget(time_label_, 1, 0, 1, 1);
+  grid_->addWidget(time_slider_, 1, 1, 1, 1);
+  grid_->addWidget(slider_line_edit_, 1, 2, 1, 10);
+  grid_->addWidget(render_type_, 1, 14, 1, 1);
+  grid_->addWidget(rt_button_, 1, 15, 1, 1);
+  grid_->addWidget(play_button_, 1, 13, 1, 1);
+  grid_->addWidget(speed_menu_, 1, 12, 1, 1);
+  dummywidget_->setLayout(grid_);
+
+  resize(800, 600);
+}
+
+void MainWindow::SetUpLineEdit()
+{
+  slider_line_edit_ = new QLineEdit();
+  slider_line_edit_->setText(std::to_string(0).c_str());
+}
+
+void MainWindow::SetUpSliders()
+{
+  time_slider_ = new QSlider(Qt::Horizontal);
+  time_label_ = new QLabel("Time:");
+  InitSlider(time_slider_);
+  time_slider_->setEnabled(0);
+}
+
+void MainWindow::InitSlider(QSlider *slider)
+{
+  slider->setFocusPolicy(Qt::StrongFocus);
+  slider->setTickPosition(QSlider::TicksAbove);
+  slider->setTickInterval(50);
+  slider->setSingleStep(20);
+  slider->setMinimum(0);
+  slider->setMaximum(100);
+  slider->setValue(100);
+}
+
+void MainWindow::SetUpButtons()
+{
+  rt_button_ = new QPushButton("Replay", this);
+  rt_button_->setFixedSize(QSize(80, 32));
+  play_button_ = new QPushButton("⏸", this);
+  play_button_->setFixedSize(QSize(32, 32));
+  render_type_ = new QComboBox(this);
+  render_type_->setFixedSize(QSize(80, 32));
+  render_type_->addItems({"Points", "Spheres"});
+  speed_menu_ = new QComboBox(this);
+  speed_menu_->addItems({"1/sec", "5/sec", "10/sec", "50/sec", "100/sec"});
+}
+
+void MainWindow::StartAnimation() { animation_->StartTimer(); }
+
+void MainWindow::ConnectSignals()
+{
+  connect(speed_menu_, SIGNAL(activated(int)), animation_,
+          SLOT(SpeedMenu(int)));
+  connect(rt_button_, SIGNAL(clicked()), animation_, SLOT(RealtimeButton()));
+  connect(play_button_, SIGNAL(clicked()), animation_, SLOT(PlayButton()));
+  connect(time_slider_, SIGNAL(valueChanged(int)), animation_,
+          SLOT(ChangeData(int)));
+  connect(time_slider_, SIGNAL(valueChanged(int)), SLOT(SliderValue(int)));
+  connect(slider_line_edit_, SIGNAL(editingFinished()), SLOT(SliderValue()));
+  connect(render_type_, SIGNAL(currentIndexChanged(int)), mainwidget_,
+          SLOT(ChangeRendertype(int)));
+  connect(animation_, SIGNAL(SwitchRealtime()), this, SLOT(Realtime()));
+  connect(animation_, SIGNAL(SwitchPlayPause()), this, SLOT(PlayPause()));
+  connect(animation_, SIGNAL(DataChanged()), this, SLOT(Rerender()));
+  connect(animation_, SIGNAL(DataChanged()), this, SLOT(AdjustSlider()));
+  connect(animation_, SIGNAL(NextStep()), SLOT(IncrementSlider()));
+  connect(animation_, SIGNAL(LastStep()), SLOT(UpdateSlider()));
+}
+
+void MainWindow::Rerender() { mainwidget_->Rerender(); }
+
+void MainWindow::IncrementSlider()
+{
+  int newval;
+  if (time_slider_->value() + 1 < time_slider_->maximum())
+  {
+    newval = time_slider_->value() + 1;
+  }
+  else
+  {
+    newval = time_slider_->maximum();
+  }
+
+  time_slider_->setValue(newval);
+  slider_line_edit_->setText(std::to_string(newval).c_str());
+}
+
+void MainWindow::UpdateSlider()
+{
+  time_slider_->setValue(points_->GetEndTime());
+  slider_line_edit_->setText(std::to_string(time_slider_->value()).c_str());
+}
+
+void MainWindow::AdjustSlider()
+{
+  time_slider_->setMinimum(points_->GetStartTime());
+  time_slider_->setMaximum(points_->GetEndTime());
+}
+
+void MainWindow::SliderValue(int time_step)
+{
+  slider_line_edit_->setText(std::to_string(time_step).c_str());
+  time_slider_->setMinimum(points_->GetStartTime());
+  time_slider_->setMaximum(points_->GetEndTime());
+}
+
+void MainWindow::SliderValue()
+{
+  time_slider_->setValue(slider_line_edit_->text().toInt());
+}
+
+void MainWindow::Realtime()
+{
+  if (realtime_)
+  {
+    realtime_ = false;
+    rt_button_->setText("Realtime");
+    time_slider_->setMinimum(points_->GetStartTime());
+    time_slider_->setMaximum(points_->GetEndTime());
+    time_slider_->setEnabled(1);
+  }
+  else
+  {
+    realtime_ = true;
+    time_slider_->setValue(points_->GetEndTime());
+    rt_button_->setText("Replay");
+    time_slider_->setEnabled(0);
+  }
+}
+
+void MainWindow::PlayPause()
+{
+  if (play_)
+  {
+    play_ = false;
+    play_button_->setText("▶");
+    SliderValue(slider_line_edit_->text().toInt());
+  }
+  else
+  {
+    play_ = true;
+    play_button_->setText("⏸");
+  }
+}
+
+} // namespace vtkexp
diff --git a/demos/QVTK-Demo/qvtk-lib/src/point_data.cpp b/demos/QVTK-Demo/qvtk-lib/src/point_data.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..263c7bc1d82a35fcb489f6fc975d98ad7c22edfc
--- /dev/null
+++ b/demos/QVTK-Demo/qvtk-lib/src/point_data.cpp
@@ -0,0 +1,133 @@
+//------------------------------------------------------------------------------
+// QVTK-Demo
+//
+// Copyright (c) 2017-2018 RWTH Aachen University, Germany,
+// Virtual Reality & Immersive Visualisation Group.
+//------------------------------------------------------------------------------
+//                                 License
+//
+// This framework is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// In the future, we may decide to add a commercial license
+// at our own discretion without further notice.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//------------------------------------------------------------------------------
+
+#include <vector>
+
+#include "include/qvtk-lib/suppress_warnings.hpp"
+SUPPRESS_WARNINGS_BEGIN
+#include "qvtk-lib/point_data.hpp"
+
+#include "vtkCellArray.h"
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpedantic"
+#include "vtkPointData.h"
+#pragma GCC diagnostic pop
+SUPPRESS_WARNINGS_END
+
+namespace vtkexp
+{
+
+PointData::PointData(int num_x, int num_y, int num_z)
+    : num_points_(num_x * num_y * num_z)
+{
+  Initialize(num_x, num_y, num_z);
+}
+
+void PointData::Initialize(int x, int y, int z)
+{
+  points_polydata_ = vtkSmartPointer<vtkPolyData>::New();
+  points_polydata_->SetPoints(CreatePoints(x, y, z));
+
+  pointcolors_ = vtkSmartPointer<vtkFloatArray>::New();
+  pointcolors_->SetName("colors");
+  pointcolors_->SetNumberOfTuples(num_points_);
+
+  std::vector<double> init(num_points_);
+  std::fill(init.begin(), init.end(), 0);
+  AttachColorsToPoints(init);
+
+  stream_ = new DataStream();
+}
+
+vtkSmartPointer<vtkPoints> PointData::CreatePoints(int num_x, int num_y,
+                                                   int num_z)
+{
+  vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
+  for (int i = 0; i < num_x; ++i)
+  {
+    for (int j = 0; j < num_y; ++j)
+    {
+      for (int k = 0; k < num_z; ++k)
+      {
+        points->InsertNextPoint(i, j, k);
+      }
+    }
+  }
+  return points;
+}
+
+void PointData::ColorsModified()
+{
+  points_polydata_->GetPointData()->GetScalars()->Modified();
+}
+
+void PointData::AttachColorsToPoints(const std::vector<double> &scalars)
+{
+  if (!scalars.empty())
+  {
+    for (int i = 0; i < num_points_; ++i)
+    {
+      pointcolors_->SetValue(
+          i, static_cast<float>(scalars.at(static_cast<int>(i))));
+    }
+    points_polydata_->GetPointData()->SetScalars(pointcolors_);
+  }
+}
+
+void PointData::Update(int time_step)
+{
+  AttachColorsToPoints(stream_->GetMultValuesAt(time_step));
+  ColorsModified();
+}
+
+vtkSmartPointer<vtkPolyData> PointData::GetPolyPoints()
+{
+  return points_polydata_;
+}
+
+vtkSmartPointer<vtkFloatArray> PointData::GetColors() const
+{
+  return pointcolors_;
+}
+
+int PointData::GetStartTime() const
+{
+  if (!stream_->GetTimeSteps().empty())
+  {
+    return static_cast<int>(stream_->GetTimeSteps().front());
+  }
+  return 0;
+}
+
+int PointData::GetEndTime() const
+{
+  if (!stream_->GetTimeSteps().empty())
+  {
+    return static_cast<int>(stream_->GetTimeSteps().back());
+  }
+  return 100;
+}
+
+} // namespace vtkexp
diff --git a/demos/QVTK-Demo/qvtk-lib/src/visualize.cpp b/demos/QVTK-Demo/qvtk-lib/src/visualize.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..614c74b13507c2eb05468c8c82d0c27f60686e96
--- /dev/null
+++ b/demos/QVTK-Demo/qvtk-lib/src/visualize.cpp
@@ -0,0 +1,157 @@
+//------------------------------------------------------------------------------
+// QVTK-Demo
+//
+// Copyright (c) 2017-2018 RWTH Aachen University, Germany,
+// Virtual Reality & Immersive Visualisation Group.
+//------------------------------------------------------------------------------
+//                                 License
+//
+// This framework is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// In the future, we may decide to add a commercial license
+// at our own discretion without further notice.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//------------------------------------------------------------------------------
+
+#include "qvtk-lib/visualize.hpp"
+
+#include <string>
+
+namespace vtkexp
+{
+
+Visualize::Visualize(PointData *points) { points_ = points; }
+
+vtkSmartPointer<vtkRenderer> Visualize::GetRenderer() { return renderer_; }
+
+void Visualize::Initialize(
+    vtkSmartPointer<vtkGenericOpenGLRenderWindow> renderwindow,
+    vtkSmartPointer<vtkRenderWindowInteractor> interactor)
+{
+  renderwindow_ = renderwindow;
+  interactor_ = interactor;
+  SetUpTransferFunction();
+  SetUpMapper();
+  SetUpScene();
+  SetUpRenderer();
+  SetUpAxes();
+  SetUpLegend();
+}
+
+void Visualize::SetUpLegend()
+{
+  scalar_bar_widget_ = vtkSmartPointer<vtkScalarBarWidget>::New();
+  scalar_bar_widget_->SetInteractor(interactor_);
+  scalar_bar_widget_->SetEnabled(true);
+
+  scalar_bar_ = scalar_bar_widget_->GetScalarBarActor();
+  // scalar_bar_->SetTitle("Legend");
+  scalar_bar_->SetLookupTable(transfer_function_);
+  scalar_bar_->SetOrientationToVertical();
+  scalar_bar_->SetNumberOfLabels(0);
+
+  scalar_bar_->SetPosition2(0, 0);
+  scalar_bar_->SetBarRatio(0.6);
+}
+
+void Visualize::SetUpAxes()
+{
+  axes_ = vtkSmartPointer<vtkAxesActor>::New();
+
+  axes_widget_ = vtkSmartPointer<vtkOrientationMarkerWidget>::New();
+  axes_widget_->SetOutlineColor(0.9300, 0.5700, 0.1300);
+  axes_widget_->SetOrientationMarker(axes_);
+  axes_widget_->SetInteractor(interactor_);
+  axes_widget_->SetViewport(0.0, 0.0, 0.2, 0.2);
+  axes_widget_->SetEnabled(1);
+  axes_widget_->InteractiveOn();
+
+  renderer_->ResetCamera();
+}
+
+void Visualize::SetUpScene()
+{
+  actor_ = vtkSmartPointer<vtkActor>::New();
+  actor_->SetMapper(mapper_);
+}
+
+void Visualize::SetUpRenderer()
+{
+  renderer_ = vtkSmartPointer<vtkRenderer>::New();
+  renderwindow_->AddRenderer(renderer_);
+  renderer_->AddActor(actor_);
+  interactor_->GetInteractorStyle()->SetDefaultRenderer(renderer_);
+
+  renderer_->GradientBackgroundOn();
+  renderer_->SetBackground(0.3, 0.4, 0.5);
+  renderer_->SetBackground2(0.1, 0.2, 0.3);
+}
+
+void Visualize::SetUpTransferFunction()
+{
+  transfer_function_ = vtkSmartPointer<vtkColorTransferFunction>::New();
+  transfer_function_->SetColorSpaceToDiverging();
+  transfer_function_->AddRGBPoint(-15, 0, 0, 1);
+  transfer_function_->AddRGBPoint(5, 1, 0, 0);
+}
+
+void Visualize::SetUpMapper()
+{
+  SetUpShaders();
+
+  mapper_ = vtkSmartPointer<vtkPointGaussianMapper>::New();
+  mapper_->SetInputData(points_->GetPolyPoints());
+  mapper_->SetSplatShaderCode(point_shader_.c_str());
+  mapper_->SetLookupTable(transfer_function_);
+  mapper_->SetScaleFactor(0.35);
+  mapper_->UseLookupTableScalarRangeOn();
+  mapper_->EmissiveOff();
+  mapper_->Update();
+}
+
+void Visualize::SetUpShaders()
+{
+  point_shader_ =
+      "//VTK::Color::Impl\n"
+      "ambientColor *= 1.0;\n"
+      "diffuseColor *= 1.0;\n"
+      "if (abs(offsetVCVSOutput.x) > 0.2 || abs(offsetVCVSOutput.y) > 0.2) "
+      "{\n"
+      "  discard;\n"
+      "}\n";
+
+  sphere_shader_ =
+      "//VTK::Color::Impl\n"
+      "float dist = dot(offsetVCVSOutput.xy,offsetVCVSOutput.xy);\n"
+      "if (dist > 0.8) {\n"
+      "  discard;\n"
+      "} else {\n"
+      "  float scale = (1.0 - dist);\n"
+      "  ambientColor *= scale;\n"
+      "  diffuseColor *= scale;\n"
+      "}\n";
+}
+
+void Visualize::SwitchMapper(int rendertype)
+{
+  if (rendertype == 0)
+  {
+    mapper_->SetSplatShaderCode(point_shader_.c_str());
+  }
+  else if (rendertype == 1)
+  {
+    mapper_->SetSplatShaderCode(sphere_shader_.c_str());
+  }
+}
+
+} // namespace vtkexp
diff --git a/demos/brunel_simulation/CMakeLists.txt b/demos/brunel_simulation/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..6fd813ebf9dbf4b4c0e2db0852fcc1879ec51b1a
--- /dev/null
+++ b/demos/brunel_simulation/CMakeLists.txt
@@ -0,0 +1,37 @@
+#-------------------------------------------------------------------------------
+# nest-streaming-module
+#
+# Copyright (c) 2018 RWTH Aachen University, Germany,
+# Virtual Reality & Immersive Visualization Group.
+#-------------------------------------------------------------------------------
+#                                  License
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#-------------------------------------------------------------------------------
+
+get_filename_component(NEST_DIR ${with-nest} DIRECTORY)
+
+set(SCRIPT_FILENAME "${CMAKE_CURRENT_BINARY_DIR}/run_sim.sh")
+execute_process(
+    COMMAND ${NEST_CONFIG} --python-executable
+    RESULT_VARIABLE RES_VAR
+    OUTPUT_VARIABLE PYTHON_EXECUTABLE
+    OUTPUT_STRIP_TRAILING_WHITESPACE
+)
+message(STATUS "PYTHON_EXECUTABLE ${PYTHON_EXECUTABLE}")
+
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/run_sim.sh.in ${SCRIPT_FILENAME})
+file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/brunel_example.py ${CMAKE_CURRENT_SOURCE_DIR}/nest_sim.py DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
+add_custom_target(brunel_simulation ALL chmod "+x" "run_sim.sh"
+  WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+  DEPENDS ${SCRIPT_FILENAME} ${CMAKE_CURRENT_BINARY_DIR}/brunel_example.py ${CMAKE_CURRENT_SOURCE_DIR}/nest_sim.py)
diff --git a/demos/brunel_simulation/brunel_example.py b/demos/brunel_simulation/brunel_example.py
new file mode 100644
index 0000000000000000000000000000000000000000..4c59b60dbaa9fd1c84c694131ef9825f736d9a3c
--- /dev/null
+++ b/demos/brunel_simulation/brunel_example.py
@@ -0,0 +1,265 @@
+
+"""
+Definition of spatially extended Brunel network.
+This module provides layer and projections declarations suitable for
+use with the NEST Topology Module.
+It defines a Brunel-style network with neurons placed on a regular grid.
+Connectivity is probabilitstic from the entire network, i.e., connectivity
+is not structured spatially.
+"""
+
+from copy import deepcopy
+from math import sqrt
+import numpy as np
+from mpl_toolkits.mplot3d import Axes3D
+import matplotlib.pyplot as plt
+
+import nest
+import nest.raster_plot
+import nest.topology as tp
+
+
+class Brunel3D:
+
+    def __init__(self):
+        self.layer_dict = {}
+        nest.Install("streamingmodule")
+        # nest.SetKernelStatus({'print_time': True})
+
+    class Parameters:
+        """
+        Define model parameters.
+        """
+        order = 9   # must be square
+        NE = 4 * order  # number of excitatory neurons.
+        NI = 1 * order  # number of inhibitory neurons
+
+        lengthE = int(sqrt(NE))
+        lengthI = int(sqrt(NI))
+
+        if not (lengthE**2 == NE and lengthI**2 == NI):
+            raise ValueError('Order must be a square number (order = n**2)')
+
+        # neuron_model = 'iaf_psc_alpha'
+        neuron_model = 'mat2_psc_exp'
+
+        g = 5.0  # ratio inhibitory weight/excitatory weight
+        eta = 2.0  # external rate relative to threshold rate
+        epsilon = 0.1  # connection probability
+
+        delay = 1.5  # synaptic delay in ms
+
+        tauMem = 20.0  # time constant of membrane potential in ms
+        theta = 20.0  # membrane threshold potential in mV
+
+        J = 0.1  # postsynaptic amplitude in mV
+        J_ex = J  # amplitude of excitatory postsynaptic potential
+        J_in = -g * J_ex  # amplitude of inhibitory postsynaptic potential
+
+        CE = int(epsilon * NE)  # number of excitatory synapses per neuron
+
+        nu_th = theta / (J * CE * tauMem)
+        nu_ex = eta * nu_th
+        p_rate = 1.0 * nu_ex * CE
+
+        neuron_params = {"C_m": 1.0,
+                         "tau_m": tauMem,
+                         "t_ref": 2.0,
+                         "E_L": 0.0,
+                         # "V_reset": 0.0,  # doesn't work with mat2_psc_exp
+                         # "V_th": theta,  # doesn't work with mat2_psc_exp
+                         "V_m": 0.0
+                         }
+        mm_params = {'record_from': ['V_m', 'V_th'],
+                     'record_to': ['streaming']}
+        poisson_params = {"rate": p_rate}
+
+    def modified_copy(self, orig, diff):
+        """
+        Returns a deep copy of dictionary with changes applied.
+        @param orig  original dictionary, will be deep-copied
+        @param diff  copy will be updated with this dict
+        """
+
+        tmp = deepcopy(orig)
+        tmp.update(diff)
+        return tmp
+
+    def make_layer_specs(self):
+        """
+        Returns lists of dictionaries with model, layer, and synapse model
+        specifications.
+        """
+
+        P = self.Parameters
+
+        self.models = [(P.neuron_model, 'excitatory', P.neuron_params),
+                       (P.neuron_model, 'inhibitory', P.neuron_params),
+                       ('poisson_generator', 'noise', P.poisson_params),
+                       ('multimeter', 'recordingNode', P.mm_params)]
+
+        self.syn_models = [('static_synapse', 'static_excitatory', {})]
+
+        dE = 1.0 / float(P.lengthE)
+        limE = (1.0 - dE) / 2.0
+        posE = np.linspace(-limE, limE, num=P.lengthE)
+
+        dI = 1.0 / float(P.lengthI)
+        limI = (1.0 - dI) / 2.0
+        posI = np.linspace(-limI, limI, num=P.lengthI)
+
+        self.layers = [('Excitatory', {'positions': [[x, y, 0.4]
+                                                     for x in posE
+                                                     for y in posE],
+                                       'edge_wrap': True,
+                                       'elements': 'excitatory'}),
+                       ('Inhibitory', {'positions': [[x, y, -0.4]
+                                                     for x in posI
+                                                     for y in posI],
+                                       'edge_wrap': True,
+                                       'elements': 'inhibitory'})]
+        self.layers.append(('PoissonGenerator',
+                            {'positions': [[0.0, 0.0, 0.0]],
+                             'elements': 'noise'}))
+        self.layers.append(('Multimeter',
+                            {'positions': [[0.0, 0.0, 0.0]],
+                             'elements': 'recordingNode'}))
+        self.layers.append(('SpikeDetector',
+                            {'positions': [[0.0, 0.0, 0.0]],
+                             'elements': 'spike_detector'}))
+
+    def make_connection_specs(self):
+        """
+        Returns list of dictionaries specifying projections for Brunel network.
+        """
+
+        P = self.Parameters
+
+        self.projections = [('Excitatory', 'Excitatory',
+                             {'connection_type': 'convergent',
+                              'synapse_model': 'static_synapse',
+                              'kernel': P.epsilon,
+                              'weights': P.J_ex,
+                              'delays': P.delay}),
+                            ('Excitatory', 'Inhibitory',
+                             {'connection_type': 'convergent',
+                              'synapse_model': 'static_synapse',
+                              'kernel': P.epsilon,
+                              'weights': P.J_ex,
+                              'delays': P.delay}),
+                            ('Inhibitory', 'Excitatory',
+                             {'connection_type': 'convergent',
+                              'synapse_model': 'static_synapse',
+                              'kernel': P.epsilon,
+                              'weights': P.J_in,
+                              'delays': P.delay}),
+                            ('Inhibitory', 'Excitatory',
+                             {'connection_type': 'convergent',
+                              'synapse_model': 'static_synapse',
+                              'kernel': P.epsilon,
+                              'weights': P.J_in,
+                              'delays': P.delay}),
+                            ('Multimeter', 'Excitatory',
+                             {'connection_type': 'convergent'}),
+                            ('Excitatory', 'SpikeDetector',
+                             {'connection_type': 'convergent'}),
+                            ('Inhibitory', 'SpikeDetector',
+                             {'connection_type': 'convergent'}),
+                            ('PoissonGenerator', 'Excitatory',
+                             {'connection_type': 'convergent'})]
+
+    def make_layers(self):
+        # First, we copy the models with custom specifications
+        # Neuron models
+        for model in self.models:
+            old_name, new_name, spec = model
+            nest.CopyModel(old_name, new_name, spec)
+        # Synapse models
+        for model in self.syn_models:
+            old_name, new_name, spec = model
+            nest.CopyModel(old_name, new_name, spec)
+
+        # Next we make the layers
+        for l in self.layers:
+            name = l[0]
+            specs = l[1]
+            self.layer_dict.update({name: tp.CreateLayer(specs)})
+
+    def make_connections(self):
+        # Connect layers
+        for proj in self.projections:
+            pre_layer = self.layer_dict[proj[0]]
+            post_layer = self.layer_dict[proj[1]]
+            conn_specs = proj[2]
+            tp.ConnectLayers(pre_layer, post_layer, conn_specs)
+
+    def simulate(self):
+        nest.Simulate(1000)
+
+    def plot_positions(self):
+        ex_pos = self.layers[0][1]['positions']
+        in_pos = self.layers[1][1]['positions']
+        fig = plt.figure()
+        ax = Axes3D(fig)
+        for c, m, positions in [('b', 'o', ex_pos), ('r', '^', in_pos)]:
+            ax.scatter([x for x, y, z in positions],
+                       [y for x, y, z in positions],
+                       [z for x, y, z in positions],
+                       c=c, marker=m)
+
+    def get_results(self):
+        mm = (self.layer_dict['Multimeter'][0] + 1,)
+        sd = (self.layer_dict['SpikeDetector'][0] + 1,)
+        mm_status = nest.GetStatus(mm)[0]
+        sd_status = nest.GetStatus(sd)[0]
+
+        nest.raster_plot.from_device(sd, hist=True)
+
+        senders = mm_status['events']['senders']
+        times = mm_status['events']['times']
+        v_m = mm_status['events']['V_m']
+        v_th = mm_status['events']['V_th']
+        step = int(max(senders)/100 + 1)  # Only plot results from some GIDs
+
+        mm_events = []
+        for i in range(1, max(senders) + 1, step):
+            if i in senders:
+                indices = np.argwhere(senders == i)
+                mm_events.append({'GID': i,
+                      'times': [times[n] for n in indices],
+                      'V_m': [v_m[n] for n in indices],
+                      'V_th': [v_th[n] for n in indices]})
+
+        return {'multimeter': mm_events,
+                'spike_detector': nest.GetStatus(sd)[0]}
+
+
+if __name__ == '__main__':
+    nest.ResetKernel()
+
+    print('Making specifications')
+    brunel = Brunel3D()
+    brunel.make_layer_specs()
+    brunel.make_connection_specs()
+
+    print('Making layers')
+    brunel.make_layers()
+    nest.topology.DumpLayerNodes([l[0] for l in brunel.layer_dict.values()][:2],
+                                     'brunel_nodes.txt')
+
+    print('Making connections')
+    brunel.make_connections()
+
+    brunel.simulate()
+
+    print('Getting results')
+    brunel.plot_positions()
+    results = brunel.get_results()
+
+    for value in ['V_m', 'V_th']:
+        plt.figure()
+        for n in results['multimeter'][::20]:
+            plt.plot(n['times'], n[value], label='{}'.format(n['GID']))
+            plt.legend()
+        plt.title(value)
+    plt.show()
diff --git a/demos/brunel_simulation/nest_sim.py b/demos/brunel_simulation/nest_sim.py
new file mode 100644
index 0000000000000000000000000000000000000000..65788db7fdfa3b6b407bc8f91ba08e04e1dc8dfc
--- /dev/null
+++ b/demos/brunel_simulation/nest_sim.py
@@ -0,0 +1,94 @@
+#-------------------------------------------------------------------------------
+# nest in situ vis
+#
+# Copyright (c) 2017-2018 RWTH Aachen University, Germany,
+# Virtual Reality & Immersive Visualisation Group.
+#-------------------------------------------------------------------------------
+#                                  License
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#-------------------------------------------------------------------------------
+
+import sys
+import nest
+import numpy
+
+from PyQt5.QtWidgets import QApplication, QPushButton
+from PyQt5.QtCore import QTimer
+
+import brunel_example
+
+class Simulation:
+    def __init__(self):
+        self.SetupSim()
+        
+    def SetupSim(self):
+        nest.ResetKernel()
+        
+        print('Making specifications')
+        self.brunel = brunel_example.Brunel3D()
+        self.brunel.make_layer_specs()
+        self.brunel.make_connection_specs()
+
+        print('Making layers')
+        self.brunel.make_layers()
+        nest.topology.DumpLayerNodes([l[0] for l in self.brunel.layer_dict.values()][:2],
+                                     'brunel_nodes.txt')
+
+        print('Making connections')
+        self.brunel.make_connections()
+
+    def Simulate(self, steps):
+        nest.Simulate(steps)
+
+
+class MainWindow:
+    def __init__(self, screen_resolution):
+        self.screen_resolution = screen_resolution
+        self.SetupWindow()
+        self.simulation = Simulation()
+
+    def SetupWindow(self):
+        self.simulate_button = QPushButton("nest.Simulate(1000)")
+        self.simulate_button.clicked.connect(self.SimulateButtonClicked)
+
+    def SimulateButtonClicked(self):
+        self.simulate_button.setEnabled(False)
+        QApplication.processEvents()
+
+        self.simulation.Simulate(1000)
+
+        QApplication.processEvents()
+        self.simulate_button.setEnabled(True)
+
+    def Show(self):
+        self.simulate_button.show()
+        button_geometry = self.simulate_button.geometry()
+        self.simulate_button.setGeometry(
+            self.screen_resolution.width() - button_geometry.width(),
+            self.screen_resolution.height() - button_geometry.height(),
+            button_geometry.width(),
+            button_geometry.height())
+
+
+def main(argv):
+    app = QApplication(argv)
+    screen_resolution = app.desktop().screenGeometry()
+
+    w = MainWindow(screen_resolution)
+    w.Show()
+
+    return app.exec_()
+
+if __name__ == "__main__":
+    main(sys.argv)
diff --git a/demos/brunel_simulation/run_sim.sh.in b/demos/brunel_simulation/run_sim.sh.in
new file mode 100644
index 0000000000000000000000000000000000000000..dd5c5c1b65105d5bd99b67e3b61314d2e362be64
--- /dev/null
+++ b/demos/brunel_simulation/run_sim.sh.in
@@ -0,0 +1,3 @@
+#!/bin/bash
+source ${NEST_DIR}/nest_vars.sh
+LD_LIBRARY_PATH=$NEST_MODULE_PATH:$LD_LIBRARY_PATH ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/nest_sim.py
\ No newline at end of file
diff --git a/recording_backend_nesci_contra.cpp b/recording_backend_nesci_contra.cpp
deleted file mode 100644
index 57b97e96d44390f5afacace84631e3d9a7069efa..0000000000000000000000000000000000000000
--- a/recording_backend_nesci_contra.cpp
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- *  recording_backend_stream_niv.cpp
- *
- *  This file is part of NEST.
- *
- *  Copyright (C) 2004 The NEST Initiative
- *
- *  NEST is free software: you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation, either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  NEST is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with NEST.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include "recording_backend_nesci_contra.h"
-
-#include "recording_device.h"
-
-#include <iostream>
-#include <memory>
-#include <sstream>
-
-streamingnest::RecordingBackendNesciContra::RecordingBackendNesciContra()
-  : num_buffered_steps_( 0 ), datum_(0, std::string{}, std::vector<double>{})
-{
-  datum_.values.reserve(10);
-}
-
-void
-streamingnest::RecordingBackendNesciContra::enroll( const nest::RecordingDevice& device )
-{
-  enroll( device, std::vector< Name >() );
-}
-
-
-void
-streamingnest::RecordingBackendNesciContra::enroll( const nest::RecordingDevice& device,
-  const std::vector< Name >& value_names )
-{
-  if ( !is_enrolled_( device ) )
-  {
-    do_enroll_( device, value_names );
-  }
-}
-
-bool
-streamingnest::RecordingBackendNesciContra::is_enrolled_( const nest::RecordingDevice& device )
-{
-  return recorders_.find( device.get_gid() ) != recorders_.end();
-}
-
-void
-streamingnest::RecordingBackendNesciContra::do_enroll_( const nest::RecordingDevice& device,
-  const std::vector< Name >& value_names )
-{
-  std::unique_ptr< nesci::producer::Device > recorder{ create_recorder_(
-    device, value_names ) };
-
-
-  recorders_[ device.get_gid() ] = std::move( recorder );
-}
-
-std::unique_ptr< nesci::producer::Device >
-streamingnest::RecordingBackendNesciContra::create_recorder_(
-  const nest::RecordingDevice& device,
-  const std::vector< Name >& value_names )
-{
-  if ( device.get_type() == nest::RecordingDevice::MULTIMETER )
-  {
-    const std::vector< std::string > converted_value_names{ convert_value_names(
-      value_names ) };
-    return std::unique_ptr< nesci::producer::Device >(
-      new nesci::producer::NestMultimeter(
-        generate_device_identifier_( device ), converted_value_names ) );
-  }
-  // Spike detector is currently not supported
-  // else if ( device.get_type() == nest::RecordingDevice::SPIKE_DETECTOR )
-  // {
-  //   return std::unique_ptr< nesci::producer::Device >(
-  //     new nesci::producer::SpikeDetector(
-  //       generate_device_identifier_( device ) ) );
-  // }
-  return std::unique_ptr< nesci::producer::Device >( nullptr );
-}
-
-std::vector< std::string >
-streamingnest::RecordingBackendNesciContra::convert_value_names(
-  const std::vector< Name >& value_names ) const
-{
-  std::vector< std::string > converted_value_names;
-  std::for_each( value_names.begin(),
-    value_names.end(),
-    [&converted_value_names]( const Name& name ) {
-      converted_value_names.push_back( name.toString() );
-    } );
-  return converted_value_names;
-}
-
-std::string
-streamingnest::RecordingBackendNesciContra::generate_device_identifier_(
-  const nest::RecordingDevice& device ) const
-{
-  if ( device.get_label().size() == 0 )
-  {
-    std::stringstream device_identifier;
-    device_identifier << device.get_name();
-    device_identifier << device.get_gid();
-    return device_identifier.str();
-  }
-
-  return device.get_label();
-}
-
-void
-streamingnest::RecordingBackendNesciContra::initialize()
-{
-  num_buffered_steps_ = 0;
-}
-
-void
-streamingnest::RecordingBackendNesciContra::finalize()
-{
-}
-
-void
-streamingnest::RecordingBackendNesciContra::synchronize()
-{
-#pragma omp barrier
-#pragma omp master
-  {
-    ++num_buffered_steps_;
-    if ( num_buffered_steps_ == 10 )
-    {
-      send_and_reset_node_();
-      num_buffered_steps_ = 0;
-    }
-  }
-}
-
-void
-streamingnest::RecordingBackendNesciContra::send_and_reset_node_()
-{
-  for ( const auto& indexRecorder : recorders_ )
-  {
-    relay_.Send( indexRecorder.second->node() );
-    indexRecorder.second->node().reset();
-  }
-}
-
-void
-streamingnest::RecordingBackendNesciContra::write( const nest::RecordingDevice& device,
-  const nest::Event& event )
-{
-  if ( !is_enrolled_( device ) )
-  {
-    return;
-  }
-
-  // nesci does currently not support spike detectors
-  // const auto time = event.get_stamp().get_ms() - event.get_offset();
-  // auto& recorder = recorders_[ device.get_gid() ];
-  // recorder->Record(
-  //   niv::producer::SpikeDetector::Datum( time, event.get_sender_gid() ) );
-}
-
-void
-streamingnest::RecordingBackendNesciContra::write( const nest::RecordingDevice& device,
-  const nest::Event& event,
-  const std::vector< double >& values )
-{
-  if ( !is_enrolled_( device ) )
-  {
-    return;
-  }
-
-  const auto time = event.get_stamp().get_ms() - event.get_offset();
-  auto& recorder = recorders_[ device.get_gid() ];
-  datum_.time = time;
-  datum_.neuron_id = std::to_string(event.get_sender_gid());
-  datum_.values = values;
-  recorder->Record( datum_ );
-}
-
-void
-streamingnest::RecordingBackendNesciContra::set_status( const DictionaryDatum& d )
-{
-  Parameters_ ptmp = P_; // temporary copy in case of errors
-  ptmp.set( *this, d );  // throws if BadProperty
-
-  // if we get here, temporaries contain consistent set of properties
-  P_ = ptmp;
-}
-
-void
-streamingnest::RecordingBackendNesciContra::get_status( DictionaryDatum& d ) const
-{
-  P_.get( *this, d );
-}
-
-streamingnest::RecordingBackendNesciContra::Parameters_::Parameters_()
-  : stream_interval_( 10 )
-{
-}
-
-void
-streamingnest::RecordingBackendNesciContra::Parameters_::get(
-  const RecordingBackendNesciContra&,
-  DictionaryDatum& d ) const
-{
-  ( *d )[ "stream_interval" ] = stream_interval_;
-}
-
-void
-streamingnest::RecordingBackendNesciContra::Parameters_::set(
-  const RecordingBackendNesciContra&,
-  const DictionaryDatum& d )
-{
-  if ( updateValue< long >( d, "stream_interval", stream_interval_ ) )
-  {
-    // do nothing for now
-  }
-}
diff --git a/recording_backend_nesci_contra.h b/recording_backend_nesci_contra.h
deleted file mode 100644
index 70389b7a85439a8cbe5e17441141d1d4e9634f69..0000000000000000000000000000000000000000
--- a/recording_backend_nesci_contra.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- *  recording_backend_stream_niv.h
- *
- *  This file is part of NEST.
- *
- *  Copyright (C) 2004 The NEST Initiative
- *
- *  NEST is free software: you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation, either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  NEST is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with NEST.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifndef RECORDING_BACKEND_STREAM_NIV_H
-#define RECORDING_BACKEND_STREAM_NIV_H
-
-#include <map>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "conduit/conduit_node.hpp"
-
-#include "nest_types.h"
-#include "recording_backend.h"
-
-#include "contra/relay.hpp"
-#include "contra/boost-shmem/shared_memory_transport.hpp"
-#include "nesci/producer/device.hpp"
-#include "nesci/producer/nest_multimeter.hpp"
-
-namespace streamingnest
-{
-
-class RecordingBackendNesciContra : public nest::RecordingBackend
-{
-public:
-  RecordingBackendNesciContra();
-  ~RecordingBackendNesciContra() throw()
-  {
-  }
-
-  void enroll( const nest::RecordingDevice& device );
-  void enroll( const nest::RecordingDevice& device,
-    const std::vector< Name >& value_names );
-  void initialize();
-  void finalize();
-  void synchronize();
-  void write( const nest::RecordingDevice& device, const nest::Event& event );
-  void write( const nest::RecordingDevice& device,
-    const nest::Event& event,
-    const std::vector< double >& );
-
-  void set_status( const DictionaryDatum& );
-  void get_status( DictionaryDatum& ) const;
-
-private:
-  bool is_enrolled_( const nest::RecordingDevice& device );
-  void do_enroll_( const nest::RecordingDevice& device,
-    const std::vector< Name >& value_names );
-  std::string generate_device_identifier_(
-    const nest::RecordingDevice& device ) const;
-  std::unique_ptr< nesci::producer::Device > create_recorder_(
-    const nest::RecordingDevice& device,
-    const std::vector< Name >& value_names );
-  void send_and_reset_node_();
-
-  struct Parameters_
-
-  {
-    long stream_interval_;
-
-    Parameters_();
-
-    void get( const RecordingBackendNesciContra&, DictionaryDatum& ) const;
-    void set( const RecordingBackendNesciContra&, const DictionaryDatum& );
-  };
-
-  Parameters_ P_;
-
-  std::size_t num_buffered_steps_;
-
-  std::vector< std::string > convert_value_names(
-    const std::vector< Name >& value_names ) const;
-
-
-  contra::Relay< contra::SharedMemoryTransport > relay_;
-  std::map< nest::index, std::unique_ptr< nesci::producer::Device > > recorders_;
-  nesci::producer::NestMultimeter::Datum datum_;
-};
-}
-
-#endif // RECORDING_BACKEND_STREAM_NIV_H
diff --git a/sli/mymodule-init.sli b/sli/streamingmodule-init.sli
similarity index 100%
rename from sli/mymodule-init.sli
rename to sli/streamingmodule-init.sli
diff --git a/streaming_recording_backend.cpp b/streaming_recording_backend.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f6cf26da6dcd3eb83c68d0473b96bc68a737c5b3
--- /dev/null
+++ b/streaming_recording_backend.cpp
@@ -0,0 +1,139 @@
+/*
+ *  recording_backend_stream_niv.cpp
+ *
+ *  This file is part of NEST.
+ *
+ *  Copyright (C) 2004 The NEST Initiative
+ *
+ *  NEST is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  NEST is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with NEST.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "streaming_recording_backend.h"
+
+#include "recording_device.h"
+
+#include <iostream>
+#include <memory>
+#include <sstream>
+#include <thread>
+
+namespace streamingnest {
+
+StreamingRecordingBackend::StreamingRecordingBackend() {}
+
+void StreamingRecordingBackend::initialize() {
+  // Called once
+  std::cout << "initialize()" << std::endl;
+}
+
+void StreamingRecordingBackend::enroll(
+    const nest::RecordingDevice &device,
+    const std::vector<Name> &double_value_names,
+    const std::vector<Name> &long_value_names) {
+  // Called per thread
+  std::lock_guard<std::mutex> lock_guard(enroll_mutex_);
+
+  std::vector<std::string> double_parameter_names;
+  double_parameter_names.reserve(double_value_names.size());
+  for (const auto &value_name : double_value_names) {
+    double_parameter_names.push_back(value_name.toString());
+  }
+
+  std::vector<std::string> long_parameter_names;
+  long_parameter_names.reserve(long_value_names.size());
+  for (const auto &value_name : long_value_names) {
+    long_parameter_names.push_back(value_name.toString());
+  }
+
+  if (device.get_type() == nest::RecordingDevice::Type::MULTIMETER) {
+    devices_[std::this_thread::get_id()][device.get_name()] =
+        std::make_unique<nesci::producer::NestMultimeter>(
+            device.get_name(), double_parameter_names, long_parameter_names);
+  }
+
+  std::cout << std::this_thread::get_id() << ' ';
+  std::cout << device.get_name() << ' ';
+  std::cout << "double_value_names: ";
+  for (const auto &name : double_value_names) {
+    std::cout << name << ' ';
+  }
+  std::cout << ", long_value_names: ";
+  for (const auto &name : long_value_names) {
+    std::cout << name << ' ';
+  }
+  std::cout << std::endl;
+}
+
+void StreamingRecordingBackend::write(const nest::RecordingDevice &device,
+                                      const nest::Event &event,
+                                      const std::vector<double> &double_values,
+                                      const std::vector<long> &long_values) {
+  // Called per thread
+  // std::lock_guard<std::mutex> lock_guard(write_mutex_);
+  // std::cout << std::this_thread::get_id() << ' ';
+  // std::cout << device.get_name() << ' ';
+  // std::cout << event.get_sender_gid() << ' ';
+  // std::cout << event.get_stamp() << ' ';
+  // for (const auto value : double_values) {
+  //   std::cout << value << ' ';
+  // }
+  // std::cout << ' ';
+  // for (const auto value : long_values) {
+  //   std::cout << value << ' ';
+  // }
+  // std::cout << std::endl;
+
+  const auto thread_devices = devices_.find(std::this_thread::get_id());
+  if (thread_devices == devices_.end()) {
+    // std::cout << "Error: no devices assigned to this thread!" << std::endl;
+    return;
+  }
+
+  const auto thread_device = thread_devices->second.find(device.get_name());
+  if (thread_device == thread_devices->second.end()) {
+    // std::cout << "Error: device not found in this thread (device = "
+    //           << device.get_name() << ")" << std::endl;
+
+    return;
+  }
+
+  auto &nesci_device = thread_device->second;
+
+  if (device.get_type() == nest::RecordingDevice::Type::MULTIMETER) {
+    auto multimeter =
+        static_cast<nesci::producer::NestMultimeter *>(nesci_device.get());
+    multimeter->Record(event.get_stamp().get_ms(), event.get_sender_gid(),
+                       double_values.data(), long_values.data());
+  }
+}
+
+void StreamingRecordingBackend::synchronize() {
+  // Called per thread
+  for (const auto &device : devices_.at(std::this_thread::get_id())) {
+    {
+      std::lock_guard<std::mutex> lock_guard(relay_mutex_);
+      relay_.Send(device.second->node(), false);
+    }
+    static_cast<nesci::producer::NestMultimeter *>(device.second.get())
+        ->Clear();
+  }
+}
+
+void StreamingRecordingBackend::finalize() {
+  // Called once
+  std::cout << "finalize()" << std::endl;
+}
+
+}  // namespace streamingnest
diff --git a/streaming_recording_backend.h b/streaming_recording_backend.h
new file mode 100644
index 0000000000000000000000000000000000000000..ede20e6b3761b28fb4be86f4d6a153c2fae85778
--- /dev/null
+++ b/streaming_recording_backend.h
@@ -0,0 +1,71 @@
+/*
+ *  recording_backend_stream_niv.h
+ *
+ *  This file is part of NEST.
+ *
+ *  Copyright (C) 2004 The NEST Initiative
+ *
+ *  NEST is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  NEST is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with NEST.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef RECORDING_BACKEND_STREAM_NIV_H
+#define RECORDING_BACKEND_STREAM_NIV_H
+
+#include <map>
+#include <memory>
+#include <mutex>
+#include <string>
+#include <vector>
+
+#include "nest_types.h"
+#include "recording_backend.h"
+
+#include "contra/relay.hpp"
+#include "contra/shared_memory/shared_memory_transport.hpp"
+#include "nesci/producer/device.hpp"
+#include "nesci/producer/nest_multimeter.hpp"
+
+namespace streamingnest {
+
+class StreamingRecordingBackend : public nest::RecordingBackend {
+ public:
+  StreamingRecordingBackend();
+  ~StreamingRecordingBackend() throw() {}
+
+  void enroll(const nest::RecordingDevice &, const std::vector<Name> &,
+              const std::vector<Name> &) override;
+
+  void initialize() override;
+
+  void finalize() override;
+  void synchronize() override;
+
+  void write(const nest::RecordingDevice &, const nest::Event &,
+             const std::vector<double> &, const std::vector<long> &) override;
+
+ private:
+  std::mutex relay_mutex_;
+  contra::Relay<contra::SharedMemoryTransport> relay_;
+
+  std::mutex write_mutex_;
+
+  std::map<std::thread::id,
+           std::map<std::string, std::unique_ptr<nesci::producer::Device>>>
+      devices_;
+  std::mutex enroll_mutex_;
+};
+}  // namespace streamingnest
+
+#endif  // RECORDING_BACKEND_STREAM_NIV_H
diff --git a/streamingmodule.cpp b/streamingmodule.cpp
index 0b0a1948e0839237f4e35c6887dc8de9984b06fe..f5c95340db7ce0b102dbd5dbfc5ea168dbe4a2ad 100644
--- a/streamingmodule.cpp
+++ b/streamingmodule.cpp
@@ -26,7 +26,7 @@
 #include "config.h"
 
 // include headers with your own stuff
-#include "recording_backend_nesci_contra.h"
+#include "streaming_recording_backend.h"
 
 // Includes from nestkernel:
 #include "connection_manager_impl.h"
@@ -35,10 +35,10 @@
 #include "exceptions.h"
 #include "genericmodel.h"
 #include "genericmodel_impl.h"
+#include "io_manager_impl.h"
 #include "kernel_manager.h"
 #include "model.h"
 #include "model_manager_impl.h"
-#include "io_manager_impl.h"
 #include "nestmodule.h"
 #include "target_identifier.h"
 
@@ -70,45 +70,38 @@
  * registration will take place in the file `static_modules.h`, which is
  * generated by cmake.
  */
-#if defined( LTX_MODULE ) | defined( LINKED_MODULE )
+#if defined(LTX_MODULE) | defined(LINKED_MODULE)
 streamingnest::StreamingModule streamingmodule_LTX_mod;
 #endif
 // -- DynModule functions ------------------------------------------------------
 
-streamingnest::StreamingModule::StreamingModule()
-{
-#ifdef LINKED_MODULE
+streamingnest::StreamingModule::StreamingModule() {
+#if defined(LINKED_MODULE) && defined(HAVE_LIBLTDL)
   // register this module at the dynamic loader
   // this is needed to allow for linking in this module at compile time
   // all registered modules will be initialized by the main app's dynamic loader
-  nest::DynamicLoaderModule::registerLinkedModule( this );
+  nest::DynamicLoaderModule::registerLinkedModule(this);
 #endif
 }
 
-streamingnest::StreamingModule::~StreamingModule()
-{
-}
+streamingnest::StreamingModule::~StreamingModule() {}
 
-const std::string
-streamingnest::StreamingModule::name( void ) const
-{
-  return std::string( "Streaming NEST Module" ); // Return name of the module
+const std::string streamingnest::StreamingModule::name(void) const {
+  return std::string("Streaming NEST Module");  // Return name of the module
 }
 
-const std::string
-streamingnest::StreamingModule::commandstring( void ) const
-{
+const std::string streamingnest::StreamingModule::commandstring(void) const {
   // Instruct the interpreter to load streamingmodule-init.sli
-  return std::string( "(streamingmodule-init) run" );
+  return std::string("(streamingmodule-init) run");
 }
 
 //-------------------------------------------------------------------------------------
 
-void
-streamingnest::StreamingModule::init( SLIInterpreter* i )
-{
+void streamingnest::StreamingModule::init(SLIInterpreter *i) {
   // Register recording backend.
-  nest::kernel().io_manager.register_recording_backend< streamingnest::RecordingBackendNesciContra >(
-    "streaming" );
+  nest::kernel()
+      .io_manager
+      .register_recording_backend<streamingnest::StreamingRecordingBackend>(
+          "streaming");
 
-} // StreamingModule::init()
+}  // StreamingModule::init()
diff --git a/streamingmodule.h b/streamingmodule.h
index bb1309340d476351783618fe548f4ff22a9d27e8..e06646c49b23d97b89cae5e84075ad665a00df70 100644
--- a/streamingmodule.h
+++ b/streamingmodule.h
@@ -28,16 +28,14 @@
 #include "slimodule.h"
 
 // Put your stuff into your own namespace.
-namespace streamingnest
-{
+namespace streamingnest {
 
 /**
  * Class defining your model.
  * @note For each model, you must define one such class, with a unique name.
  */
-class StreamingModule : public SLIModule
-{
-public:
+class StreamingModule : public SLIModule {
+ public:
   // Interface functions ------------------------------------------
 
   /**
@@ -55,20 +53,20 @@ public:
    * Initialize module.
    * @param SLIInterpreter* SLI interpreter
    */
-  void init( SLIInterpreter* );
+  void init(SLIInterpreter *);
 
   /**
    * Return the name of your model.
    */
-  const std::string name( void ) const;
+  const std::string name(void) const;
 
   /**
    * Return the name of a sli file to execute when streamingmodule is loaded.
    * This mechanism can be used to define SLI commands associated with your
    * module, in particular, set up type tries for functions you have defined.
    */
-  const std::string commandstring( void ) const;
+  const std::string commandstring(void) const;
 };
-} // namespace streamingnest
+}  // namespace streamingnest
 
 #endif